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