Home | History | Annotate | Line # | Download | only in tspi
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2007
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #include <openssl/asn1.h>
     17 #include <openssl/asn1t.h>
     18 
     19 #ifndef TSS_BUILD_ASN1_OPENSSL
     20 #include <arpa/inet.h>
     21 #endif
     22 
     23 #include "trousers/tss.h"
     24 #include "trousers/trousers.h"
     25 #include "trousers_types.h"
     26 #include "tsplog.h"
     27 
     28 #define TSS_OPENSSL_ASN1_ERROR	(0xffffffff)
     29 
     30 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
     31 #define OPENSSL_COMPAT_CONST const
     32 #else
     33 #define OPENSSL_COMPAT_CONST
     34 #endif
     35 
     36 #define OPENSSL_COMPAT_ASN1_SEQUENCE(tname) \
     37 	static const ASN1_TEMPLATE tname##_seq_tt[]
     38 
     39 typedef struct tdTSS_BLOB {
     40 	ASN1_INTEGER *		structVersion;
     41 	ASN1_INTEGER *		blobType;
     42 	ASN1_INTEGER *		blobLength;
     43 	ASN1_OCTET_STRING *	blob;
     44 } TSS_BLOB;
     45 
     46 OPENSSL_COMPAT_ASN1_SEQUENCE(TSS_BLOB) = {
     47 	ASN1_SIMPLE(TSS_BLOB, structVersion, ASN1_INTEGER),
     48 	ASN1_SIMPLE(TSS_BLOB, blobType, ASN1_INTEGER),
     49 	ASN1_SIMPLE(TSS_BLOB, blobLength, ASN1_INTEGER),
     50 	ASN1_SIMPLE(TSS_BLOB, blob, ASN1_OCTET_STRING)
     51 } ASN1_SEQUENCE_END(TSS_BLOB)
     52 IMPLEMENT_ASN1_FUNCTIONS(TSS_BLOB)
     53 
     54 
     55 TSS_RESULT
     56 Tspi_EncodeDER_TssBlob(UINT32 rawBlobSize,		/* in */
     57 			BYTE *rawBlob,			/* in */
     58 			UINT32 blobType,		/* in */
     59 			UINT32 *derBlobSize,		/* in/out */
     60 			BYTE *derBlob)			/* out */
     61 {
     62 #ifdef TSS_BUILD_ASN1_OPENSSL
     63 	TSS_BLOB *tssBlob = NULL;
     64 #endif
     65 	BYTE *encBlob = NULL;
     66 	UINT32 encBlobLen;
     67 
     68 	if ((rawBlobSize == 0) || (rawBlob == NULL))
     69 		return TSPERR(TSS_E_BAD_PARAMETER);
     70 
     71 	if ((blobType < TSS_BLOB_TYPE_KEY) || (blobType > TSS_BLOB_TYPE_CMK_BYTE_STREAM))
     72 		return TSPERR(TSS_E_BAD_PARAMETER);
     73 
     74 	if ((*derBlobSize != 0) && (derBlob == NULL))
     75 		return TSPERR(TSS_E_BAD_PARAMETER);
     76 
     77 	/* The TSS working group has stated that the ASN1 encoding will be done in a
     78 	 * specific way that generates an ASN1 encoding that is exactly 20 bytes
     79 	 * larger than the blob being encoded.
     80 	 *
     81 	 * OpenSSL uses the smallest number of bytes possible to encode and object
     82 	 * and as a result cannot be used to perform the encoding.  The encoding
     83 	 * must be done manually.
     84 	 *
     85 	 * The 20 byte fixed header will result in issues for objects greater than
     86 	 * 2^16 in size since some fields are now limited to 16-bit lengths.
     87 	 */
     88 
     89 #ifdef TSS_BUILD_ASN1_OPENSSL
     90 	tssBlob = TSS_BLOB_new();
     91 	if (!tssBlob)
     92 		return TSPERR(TSS_E_OUTOFMEMORY);
     93 
     94 	if (ASN1_INTEGER_set(tssBlob->structVersion, TSS_BLOB_STRUCT_VERSION) == 0) {
     95 		TSS_BLOB_free(tssBlob);
     96 		return TSPERR(TSS_E_OUTOFMEMORY);
     97 	}
     98 
     99 	if (ASN1_INTEGER_set(tssBlob->blobType, blobType) == 0) {
    100 		TSS_BLOB_free(tssBlob);
    101 		return TSPERR(TSS_E_OUTOFMEMORY);
    102 	}
    103 
    104 	if (ASN1_INTEGER_set(tssBlob->blobLength, rawBlobSize) == 0) {
    105 		TSS_BLOB_free(tssBlob);
    106 		return TSPERR(TSS_E_OUTOFMEMORY);
    107 	}
    108 
    109 	if (ASN1_OCTET_STRING_set(tssBlob->blob, rawBlob, rawBlobSize) == 0) {
    110 		TSS_BLOB_free(tssBlob);
    111 		return TSPERR(TSS_E_OUTOFMEMORY);
    112 	}
    113 
    114 	encBlobLen = i2d_TSS_BLOB(tssBlob, &encBlob);
    115 	if (encBlobLen <= 0) {
    116 		TSS_BLOB_free(tssBlob);
    117 		return TSPERR(TSS_E_INTERNAL_ERROR);
    118 	}
    119 
    120 	if (*derBlobSize != 0) {
    121 		if (encBlobLen <= *derBlobSize) {
    122 			memcpy(derBlob, encBlob, encBlobLen);
    123 		}
    124 		else {
    125 			OPENSSL_free(encBlob);
    126 			TSS_BLOB_free(tssBlob);
    127 			return TSPERR(TSS_E_BAD_PARAMETER);
    128 		}
    129 	}
    130 
    131 	*derBlobSize = encBlobLen;
    132 
    133 	OPENSSL_free(encBlob);
    134 	TSS_BLOB_free(tssBlob);
    135 #else
    136 	if ((rawBlobSize + 16) > UINT16_MAX)
    137 		return TSPERR(TSS_E_INTERNAL_ERROR);
    138 
    139 	encBlobLen = rawBlobSize + 20;
    140 
    141 	if (*derBlobSize != 0) {
    142 		if (encBlobLen <= *derBlobSize) {
    143 			UINT16 *pShort;
    144 			UINT32 *pLong;
    145 
    146 			encBlob = derBlob;
    147 			encBlob[0] = 0x30;	/* Sequence tag */
    148 			encBlob[1] = 0x82;	/* Length in the two octets that follow */
    149 			encBlob += 2;
    150 			pShort = (UINT16 *)encBlob;
    151 			*pShort = htons(rawBlobSize + 16);
    152 			encBlob += sizeof(UINT16);
    153 
    154 			encBlob[0] = 0x02;	/* Integer tag */
    155 			encBlob[1] = 0x01;	/* Length is one */
    156 			encBlob[2] = (BYTE)TSS_BLOB_STRUCT_VERSION;
    157 			encBlob += 3;
    158 
    159 			encBlob[0] = 0x02;	/* Integer tag */
    160 			encBlob[1] = 0x01;	/* Length is one */
    161 			encBlob[2] = (BYTE)blobType;
    162 			encBlob += 3;
    163 
    164 			encBlob[0] = 0x02;	/* Integer tag */
    165 			encBlob[1] = 0x04;	/* Length is four */
    166 			encBlob += 2;
    167 			pLong = (UINT32 *)encBlob;
    168 			*pLong = htonl(rawBlobSize);
    169 			encBlob += sizeof(UINT32);
    170 
    171 			encBlob[0] = 0x04;	/* Octet string tag */
    172 			encBlob[1] = 0x82;	/* Length in the two octets that follow */
    173 			encBlob += 2;
    174 			pShort = (UINT16 *)encBlob;
    175 			*pShort = htons(rawBlobSize);
    176 			encBlob += sizeof(UINT16);
    177 			memcpy(encBlob, rawBlob, rawBlobSize);
    178 		}
    179 		else
    180 			return TSPERR(TSS_E_BAD_PARAMETER);
    181 	}
    182 
    183 	*derBlobSize = encBlobLen;
    184 #endif
    185 
    186 	return TSS_SUCCESS;
    187 }
    188 
    189 TSS_RESULT
    190 Tspi_DecodeBER_TssBlob(UINT32 berBlobSize,		/* in */
    191 			BYTE *berBlob,			/* in */
    192 			UINT32 *blobType,		/* out */
    193 			UINT32 *rawBlobSize,		/* in/out */
    194 			BYTE *rawBlob)			/* out */
    195 {
    196 	TSS_BLOB *tssBlob = NULL;
    197 	OPENSSL_COMPAT_CONST BYTE *encBlob = berBlob;
    198 
    199 	UINT32 encBlobLen = berBlobSize;
    200 	UINT32 decStructVersion, decBlobType, decBlobSize;
    201 
    202 	if ((berBlobSize == 0) || (berBlob == NULL))
    203 		return TSPERR(TSS_E_BAD_PARAMETER);
    204 
    205 	if ((*rawBlobSize != 0) && (rawBlob == NULL))
    206 		return TSPERR(TSS_E_BAD_PARAMETER);
    207 
    208 	tssBlob = d2i_TSS_BLOB(NULL, &encBlob, encBlobLen);
    209 	if (!tssBlob)
    210 		return TSPERR(TSS_E_INTERNAL_ERROR);
    211 
    212 	decStructVersion = ASN1_INTEGER_get(tssBlob->structVersion);
    213 	if (decStructVersion == TSS_OPENSSL_ASN1_ERROR) {
    214 		TSS_BLOB_free(tssBlob);
    215 		return TSPERR(TSS_E_INTERNAL_ERROR);
    216 	}
    217 	if (decStructVersion > TSS_BLOB_STRUCT_VERSION) {
    218 		TSS_BLOB_free(tssBlob);
    219 		return TSPERR(TSS_E_BAD_PARAMETER);
    220 	}
    221 
    222 	decBlobType = ASN1_INTEGER_get(tssBlob->blobType);
    223 	if (decBlobType == TSS_OPENSSL_ASN1_ERROR) {
    224 		TSS_BLOB_free(tssBlob);
    225 		return TSPERR(TSS_E_INTERNAL_ERROR);
    226 	}
    227 	if ((decBlobType < TSS_BLOB_TYPE_KEY) || (decBlobType > TSS_BLOB_TYPE_CMK_BYTE_STREAM)) {
    228 		TSS_BLOB_free(tssBlob);
    229 		return TSPERR(TSS_E_BAD_PARAMETER);
    230 	}
    231 
    232 	decBlobSize = ASN1_INTEGER_get(tssBlob->blobLength);
    233 	if (decBlobSize == TSS_OPENSSL_ASN1_ERROR) {
    234 		TSS_BLOB_free(tssBlob);
    235 		return TSPERR(TSS_E_INTERNAL_ERROR);
    236 	}
    237 
    238 	if (*rawBlobSize != 0) {
    239 		if (decBlobSize <= *rawBlobSize) {
    240 			memcpy(rawBlob, tssBlob->blob->data, decBlobSize);
    241 		}
    242 		else {
    243 			TSS_BLOB_free(tssBlob);
    244 			return TSPERR(TSS_E_BAD_PARAMETER);
    245 		}
    246 	}
    247 
    248 	*rawBlobSize = decBlobSize;
    249 	*blobType = decBlobType;
    250 
    251 	TSS_BLOB_free(tssBlob);
    252 
    253 	return TSS_SUCCESS;
    254 }
    255 
    256