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
39typedef struct tdTSS_BLOB {
40	ASN1_INTEGER *		structVersion;
41	ASN1_INTEGER *		blobType;
42	ASN1_INTEGER *		blobLength;
43	ASN1_OCTET_STRING *	blob;
44} TSS_BLOB;
45
46OPENSSL_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)
52IMPLEMENT_ASN1_FUNCTIONS(TSS_BLOB)
53
54
55TSS_RESULT
56Tspi_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
189TSS_RESULT
190Tspi_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