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