xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tspi_asn1.c (revision 2d5f7628c5531eb583b9313ac2fd1cf8582b4479)
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
Tspi_DecodeBER_TssBlob(UINT32 berBlobSize,BYTE * berBlob,UINT32 * blobType,UINT32 * rawBlobSize,BYTE * rawBlob)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