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. 2004-2006
8  *
9  */
10 
11 /*
12  * rsa.c - openssl TSS crypto routines
13  *
14  * Kent Yoder <shpedoikal@gmail.com>
15  *
16  */
17 
18 #include <string.h>
19 
20 #include <openssl/evp.h>
21 #include <openssl/err.h>
22 #include <openssl/sha.h>
23 #include <openssl/rsa.h>
24 
25 #include "trousers/tss.h"
26 #include "trousers/trousers.h"
27 #include "trousers_types.h"
28 #include "spi_utils.h"
29 #include "tsplog.h"
30 
31 #ifdef TSS_DEBUG
32 #define DEBUG_print_openssl_errors() \
33 	do { \
34 		ERR_load_crypto_strings(); \
35 		ERR_print_errors_fp(stderr); \
36 	} while (0)
37 #else
38 #define DEBUG_print_openssl_errors()
39 #endif
40 
41 #if OPENSSL_VERSION_NUMBER < 0x10100001L
42 static int
RSA_set0_key(RSA * r,BIGNUM * n,BIGNUM * e,BIGNUM * d)43 RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
44 {
45 	if (n != NULL) {
46 		BN_free(r->n);
47 		r->n = n;
48 	}
49 	if (e != NULL) {
50 		BN_free(r->e);
51 		r->e = e;
52 	}
53 	if (d != NULL) {
54 		BN_free(r->d);
55 		r->d = d;
56 	}
57 	return 1;
58 }
59 #endif
60 
61 /*
62  * Hopefully this will make the code clearer since
63  * OpenSSL returns 1 on success
64  */
65 #define EVP_SUCCESS 1
66 
67 /* XXX int set to unsigned int values */
68 int
Trspi_RSA_Encrypt(unsigned char * dataToEncrypt,unsigned int dataToEncryptLen,unsigned char * encryptedData,unsigned int * encryptedDataLen,unsigned char * publicKey,unsigned int keysize)69 Trspi_RSA_Encrypt(unsigned char *dataToEncrypt, /* in */
70 		unsigned int dataToEncryptLen,  /* in */
71 		unsigned char *encryptedData,   /* out */
72 		unsigned int *encryptedDataLen, /* out */
73 		unsigned char *publicKey,
74 		unsigned int keysize)
75 {
76 	int rv;
77 	unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* 65537 hex */
78 	unsigned char oaepPad[] = "TCPA";
79 	int oaepPadLen = 4;
80 	RSA *rsa = RSA_new();
81 	BYTE encodedData[256];
82 	int encodedDataLen;
83 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
84 
85 	if (rsa == NULL) {
86 		rv = TSPERR(TSS_E_OUTOFMEMORY);
87 		goto err;
88 	}
89 
90 	/* set the public key value in the OpenSSL object */
91 	rsa_n = BN_bin2bn(publicKey, keysize, NULL);
92 	/* set the public exponent */
93 	rsa_e = BN_bin2bn(exp, sizeof(exp), NULL);
94 
95 	if (rsa_n == NULL || rsa_e == NULL) {
96 		rv = TSPERR(TSS_E_OUTOFMEMORY);
97 		BN_free(rsa_n);
98 		BN_free(rsa_e);
99 		goto err;
100 	}
101 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
102 		rv = TSPERR(TSS_E_FAIL);
103 		BN_free(rsa_n);
104 		BN_free(rsa_e);
105 		goto err;
106 	}
107 
108 	/* padding constraint for PKCS#1 OAEP padding */
109 	if ((int)dataToEncryptLen >= (RSA_size(rsa) - ((2 * SHA_DIGEST_LENGTH) + 1))) {
110 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
111 		goto err;
112 	}
113 
114 	encodedDataLen = MIN(RSA_size(rsa), 256);
115 
116 	/* perform our OAEP padding here with custom padding parameter */
117 	rv = RSA_padding_add_PKCS1_OAEP(encodedData, encodedDataLen, dataToEncrypt,
118 			dataToEncryptLen, oaepPad, oaepPadLen);
119 	if (rv != EVP_SUCCESS) {
120 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
121 		goto err;
122 	}
123 
124 	/* call OpenSSL with no additional padding */
125 	rv = RSA_public_encrypt(encodedDataLen, encodedData,
126 				encryptedData, rsa, RSA_NO_PADDING);
127 	if (rv == -1) {
128 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
129 		goto err;
130 	}
131 
132 	/* RSA_public_encrypt returns the size of the encrypted data */
133 	*encryptedDataLen = rv;
134 	rv = TSS_SUCCESS;
135 	goto out;
136 
137 err:
138 	DEBUG_print_openssl_errors();
139 out:
140 	if (rsa)
141 		RSA_free(rsa);
142         return rv;
143 }
144 
145 TSS_RESULT
Trspi_Verify(UINT32 HashType,BYTE * pHash,UINT32 iHashLength,unsigned char * pModulus,int iKeyLength,BYTE * pSignature,UINT32 sig_len)146 Trspi_Verify(UINT32 HashType, BYTE *pHash, UINT32 iHashLength,
147 	     unsigned char *pModulus, int iKeyLength,
148 	     BYTE *pSignature, UINT32 sig_len)
149 {
150 	int rv, nid;
151 	unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* The default public exponent for the TPM */
152 	unsigned char buf[256];
153 	RSA *rsa = RSA_new();
154 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
155 
156 	if (rsa == NULL) {
157 		rv = TSPERR(TSS_E_OUTOFMEMORY);
158 		goto err;
159 	}
160 
161 	/* We assume we're verifying data from a TPM, so there are only
162 	 * two options, SHA1 data and PKCSv1.5 encoded signature data.
163 	 */
164 	switch (HashType) {
165 		case TSS_HASH_SHA1:
166 			nid = NID_sha1;
167 			break;
168 		case TSS_HASH_OTHER:
169 			nid = NID_undef;
170 			break;
171 		default:
172 			rv = TSPERR(TSS_E_BAD_PARAMETER);
173 			goto out;
174 			break;
175 	}
176 
177 	/* set the public key value in the OpenSSL object */
178 	rsa_n = BN_bin2bn(pModulus, iKeyLength, NULL);
179 	/* set the public exponent */
180 	rsa_e = BN_bin2bn(exp, sizeof(exp), NULL);
181 
182 	if (rsa_n == NULL || rsa_e == NULL) {
183 		rv = TSPERR(TSS_E_OUTOFMEMORY);
184 		BN_free(rsa_n);
185 		BN_free(rsa_e);
186 		goto err;
187 	}
188 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
189 		rv = TSPERR(TSS_E_FAIL);
190 		BN_free(rsa_n);
191 		BN_free(rsa_e);
192 		goto err;
193 	}
194 
195 	/* if we don't know the structure of the data we're verifying, do a public decrypt
196 	 * and compare manually. If we know we're looking for a SHA1 hash, allow OpenSSL
197 	 * to do the work for us.
198 	 */
199 	if (nid == NID_undef) {
200 		rv = RSA_public_decrypt(sig_len, pSignature, buf, rsa, RSA_PKCS1_PADDING);
201 		if ((UINT32)rv != iHashLength) {
202 			rv = TSPERR(TSS_E_FAIL);
203 			goto out;
204 		} else if (memcmp(pHash, buf, iHashLength)) {
205 			rv = TSPERR(TSS_E_FAIL);
206 			goto out;
207 		}
208 	} else {
209 		if ((rv = RSA_verify(nid, pHash, iHashLength, pSignature, sig_len, rsa)) == 0) {
210 			rv = TSPERR(TSS_E_FAIL);
211 			goto out;
212 		}
213 	}
214 
215 	rv = TSS_SUCCESS;
216 	goto out;
217 
218 err:
219 	DEBUG_print_openssl_errors();
220 out:
221 	if (rsa)
222 		RSA_free(rsa);
223         return rv;
224 }
225 
226 int
Trspi_RSA_Public_Encrypt(unsigned char * in,unsigned int inlen,unsigned char * out,unsigned int * outlen,unsigned char * pubkey,unsigned int pubsize,unsigned int e,int padding)227 Trspi_RSA_Public_Encrypt(unsigned char *in, unsigned int inlen,
228 			 unsigned char *out, unsigned int *outlen,
229 			 unsigned char *pubkey, unsigned int pubsize,
230 			 unsigned int e, int padding)
231 {
232 	int rv, e_size = 3;
233 	unsigned char exp[] = { 0x01, 0x00, 0x01 };
234 	RSA *rsa = RSA_new();
235 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
236 
237 	if (rsa == NULL) {
238 		rv = TSPERR(TSS_E_OUTOFMEMORY);
239 		goto err;
240 	}
241 
242 	switch (e) {
243 		case 0:
244 			/* fall through */
245 		case 65537:
246 			break;
247 		case 17:
248 			exp[0] = 17;
249 			e_size = 1;
250 			break;
251 		case 3:
252 			exp[0] = 3;
253 			e_size = 1;
254 			break;
255 		default:
256 			rv = TSPERR(TSS_E_INTERNAL_ERROR);
257 			goto out;
258 			break;
259 	}
260 
261 	switch (padding) {
262 		case TR_RSA_PKCS1_OAEP_PADDING:
263 			padding = RSA_PKCS1_OAEP_PADDING;
264 			break;
265 		case TR_RSA_PKCS1_PADDING:
266 			padding = RSA_PKCS1_PADDING;
267 			break;
268 		case TR_RSA_NO_PADDING:
269 			padding = RSA_NO_PADDING;
270 			break;
271 		default:
272 			rv = TSPERR(TSS_E_INTERNAL_ERROR);
273 			goto out;
274 			break;
275 	}
276 
277 	/* set the public key value in the OpenSSL object */
278 	rsa_n = BN_bin2bn(pubkey, pubsize, NULL);
279 	/* set the public exponent */
280 	rsa_e = BN_bin2bn(exp, e_size, NULL);
281 
282 	if (rsa_n == NULL || rsa_e == NULL) {
283 		rv = TSPERR(TSS_E_OUTOFMEMORY);
284                 BN_free(rsa_n);
285                 BN_free(rsa_e);
286                 goto err;
287         }
288         if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
289                 rv = TSPERR(TSS_E_FAIL);
290                 BN_free(rsa_n);
291                 BN_free(rsa_e);
292 		goto err;
293 	}
294 
295 	rv = RSA_public_encrypt(inlen, in, out, rsa, padding);
296 	if (rv == -1) {
297 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
298 		goto err;
299 	}
300 
301 	/* RSA_public_encrypt returns the size of the encrypted data */
302 	*outlen = rv;
303 	rv = TSS_SUCCESS;
304 	goto out;
305 
306 err:
307 	DEBUG_print_openssl_errors();
308 out:
309 	if (rsa)
310 		RSA_free(rsa);
311         return rv;
312 }
313