/src/libtpms/src/tpm12/tpm_crypto.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Platform Dependent Crypto */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: tpm_crypto.c 4767 2017-07-27 23:06:32Z kgoldman $ */ |
7 | | /* */ |
8 | | /* (c) Copyright IBM Corporation 2006, 2010. */ |
9 | | /* */ |
10 | | /* All rights reserved. */ |
11 | | /* */ |
12 | | /* Redistribution and use in source and binary forms, with or without */ |
13 | | /* modification, are permitted provided that the following conditions are */ |
14 | | /* met: */ |
15 | | /* */ |
16 | | /* Redistributions of source code must retain the above copyright notice, */ |
17 | | /* this list of conditions and the following disclaimer. */ |
18 | | /* */ |
19 | | /* Redistributions in binary form must reproduce the above copyright */ |
20 | | /* notice, this list of conditions and the following disclaimer in the */ |
21 | | /* documentation and/or other materials provided with the distribution. */ |
22 | | /* */ |
23 | | /* Neither the names of the IBM Corporation nor the names of its */ |
24 | | /* contributors may be used to endorse or promote products derived from */ |
25 | | /* this software without specific prior written permission. */ |
26 | | /* */ |
27 | | /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ |
28 | | /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ |
29 | | /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ |
30 | | /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ |
31 | | /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ |
32 | | /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ |
33 | | /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ |
34 | | /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ |
35 | | /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ |
36 | | /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ |
37 | | /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
38 | | /********************************************************************************/ |
39 | | |
40 | | /* This is the openSSL implementation */ |
41 | | |
42 | | #include <stdio.h> |
43 | | #include <stdarg.h> |
44 | | #include <stdlib.h> |
45 | | #include <string.h> |
46 | | |
47 | | #include <openssl/crypto.h> |
48 | | #include <openssl/rand.h> |
49 | | #include <openssl/sha.h> |
50 | | #include <openssl/err.h> |
51 | | #include <openssl/evp.h> |
52 | | #include <openssl/rsa.h> |
53 | | |
54 | | #include "tpm_cryptoh.h" |
55 | | #include "tpm_debug.h" |
56 | | #include "tpm_error.h" |
57 | | #include "tpm_key.h" |
58 | | #include "tpm_io.h" |
59 | | #include "tpm_load.h" |
60 | | #include "tpm_memory.h" |
61 | | #include "tpm_process.h" |
62 | | #include "tpm_types.h" |
63 | | |
64 | | #include "tpm_crypto.h" |
65 | | |
66 | | #include "tpm_openssl_helpers.h" // libtpms added |
67 | | |
68 | | /* The TPM OAEP encoding parameter */ |
69 | | static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; |
70 | | |
71 | | |
72 | | /* local prototypes */ |
73 | | |
74 | | static void TPM_OpenSSL_PrintError(void); |
75 | | |
76 | | static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, |
77 | | unsigned char *narr, |
78 | | uint32_t nbytes, |
79 | | unsigned char *earr, |
80 | | uint32_t ebytes); |
81 | | static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, |
82 | | unsigned char *narr, |
83 | | uint32_t nbytes, |
84 | | unsigned char *earr, |
85 | | uint32_t ebytes, |
86 | | unsigned char *darr, |
87 | | uint32_t dbytes); |
88 | | static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, |
89 | | unsigned int *signature_length, |
90 | | const unsigned char *message, |
91 | | size_t message_size, |
92 | | RSA *rsa_pri_key); |
93 | | static TPM_RESULT TPM_RSASignDER(unsigned char *signature, |
94 | | unsigned int *signature_length, |
95 | | const unsigned char *message, |
96 | | size_t message_size, |
97 | | RSA *rsa_pri_key); |
98 | | |
99 | | static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx); |
100 | | |
101 | | |
102 | | |
103 | | /* TPM_SYMMETRIC_KEY_DATA is a crypto library platform dependent symmetric key structure |
104 | | */ |
105 | | #ifdef TPM_DES |
106 | | |
107 | | /* local prototype and structure for DES */ |
108 | | |
109 | | #include <openssl/des.h> |
110 | | |
111 | | /* DES requires data lengths that are a multiple of the block size */ |
112 | | #define TPM_DES_BLOCK_SIZE 8 |
113 | | |
114 | | typedef struct tdTPM_SYMMETRIC_KEY_DATA { |
115 | | TPM_TAG tag; |
116 | | TPM_BOOL valid; |
117 | | BYTE fill; |
118 | | DES_cblock des_cblock1; |
119 | | DES_cblock des_cblock2; |
120 | | DES_cblock des_cblock3; |
121 | | } TPM_SYMMETRIC_KEY_DATA; |
122 | | |
123 | | static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, |
124 | | const unsigned char *data_in, |
125 | | uint32_t length, |
126 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, |
127 | | int enc, |
128 | | TPM_RESULT error); |
129 | | |
130 | | #endif |
131 | | |
132 | | #ifdef TPM_AES |
133 | | |
134 | | /* local prototype and structure for AES */ |
135 | | |
136 | | #include <openssl/aes.h> |
137 | | |
138 | | #if OPENSSL_VERSION_NUMBER < 0x10100000 |
139 | | #define OPENSSL_OLD_API |
140 | | #endif |
141 | | |
142 | | /* AES requires data lengths that are a multiple of the block size */ |
143 | 0 | #define TPM_AES_BITS 128 |
144 | | /* The AES block size is always 16 bytes */ |
145 | 0 | #define TPM_AES_BLOCK_SIZE 16 |
146 | | |
147 | | /* Since the AES key is often derived by truncating the session shared secret, test that it's not |
148 | | too large |
149 | | */ |
150 | | |
151 | | #if (TPM_AES_BLOCK_SIZE > TPM_SECRET_SIZE) |
152 | | #error TPM_AES_BLOCK_SIZE larger than TPM_SECRET_SIZE |
153 | | #endif |
154 | | |
155 | | /* The AES initial CTR value is derived from a nonce. */ |
156 | | |
157 | | #if (TPM_AES_BLOCK_SIZE > TPM_NONCE_SIZE) |
158 | | #error TPM_AES_BLOCK_SIZE larger than TPM_NONCE_SIZE |
159 | | #endif |
160 | | |
161 | | typedef struct tdTPM_SYMMETRIC_KEY_DATA { |
162 | | TPM_TAG tag; |
163 | | TPM_BOOL valid; |
164 | | TPM_BOOL fill; |
165 | | unsigned char userKey[TPM_AES_BLOCK_SIZE]; |
166 | | /* For performance, generate these once from userKey */ |
167 | | AES_KEY aes_enc_key; |
168 | | AES_KEY aes_dec_key; |
169 | | } TPM_SYMMETRIC_KEY_DATA; |
170 | | |
171 | | static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data); |
172 | | static TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, |
173 | | const unsigned char *key_data, |
174 | | uint32_t key_data_size); |
175 | | static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, |
176 | | const unsigned char *data_in, |
177 | | uint32_t data_size, |
178 | | const AES_KEY *aes_enc_key, |
179 | | unsigned char ctr[TPM_AES_BLOCK_SIZE]); |
180 | | |
181 | | #endif |
182 | | |
183 | | /* |
184 | | Initialization function |
185 | | */ |
186 | | |
187 | | TPM_RESULT TPM_Crypto_Init() |
188 | | { |
189 | | TPM_RESULT rc = 0; |
190 | | |
191 | | printf("TPM_Crypto_Init: OpenSSL library %08lx\n", (unsigned long)OPENSSL_VERSION_NUMBER); |
192 | | /* sanity check that the SHA1 context handling remains portable */ |
193 | | if (rc == 0) { |
194 | | if ((sizeof(SHA_LONG) != sizeof(uint32_t)) || |
195 | | (sizeof(unsigned int) != sizeof(uint32_t)) || |
196 | | (sizeof(SHA_CTX) != (sizeof(uint32_t) * (8 + SHA_LBLOCK)))) { |
197 | | printf("TPM_Crypto_Init: Error(fatal), SHA_CTX has unexpected structure\n"); |
198 | | rc = TPM_FAIL; |
199 | | } |
200 | | } |
201 | | return rc; |
202 | | } |
203 | | |
204 | | /* TPM_Crypto_TestSpecific() performs any library specific tests |
205 | | |
206 | | For OpenSSL |
207 | | */ |
208 | | |
209 | | TPM_RESULT TPM_Crypto_TestSpecific() |
210 | 0 | { |
211 | 0 | TPM_RESULT rc = 0; |
212 | | |
213 | | /* Saving the SHA-1 context is fragile code, so test at startup */ |
214 | 0 | void *context1; |
215 | 0 | void *context2; |
216 | 0 | unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; |
217 | 0 | unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, |
218 | 0 | 0x3B,0xD2,0x6E,0xBA,0xAE, |
219 | 0 | 0x4A,0xA1,0xF9,0x51,0x29, |
220 | 0 | 0xE5,0xE5,0x46,0x70,0xF1}; |
221 | 0 | TPM_DIGEST actual; |
222 | 0 | int not_equal; |
223 | 0 | TPM_STORE_BUFFER sbuffer; |
224 | 0 | const unsigned char *stream; |
225 | 0 | uint32_t stream_size; |
226 | | |
227 | 0 | printf(" TPM_Crypto_TestSpecific: Test 1 - SHA1 two parts\n"); |
228 | 0 | context1 = NULL; /* freed @1 */ |
229 | 0 | context2 = NULL; /* freed @2 */ |
230 | 0 | TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ |
231 | | |
232 | 0 | if (rc== 0) { |
233 | 0 | rc = TPM_Malloc((unsigned char **)&context1, sizeof(SHA_CTX)); /* freed @1 */ |
234 | 0 | } |
235 | | /* digest the first part of the array */ |
236 | 0 | if (rc== 0) { |
237 | 0 | SHA1_Init(context1); |
238 | 0 | SHA1_Update(context1, buffer1, 16); |
239 | 0 | } |
240 | | /* store the SHA1 context */ |
241 | 0 | if (rc== 0) { |
242 | 0 | rc = TPM_Sha1Context_Store(&sbuffer, context1); |
243 | 0 | } |
244 | | /* load the SHA1 context */ |
245 | 0 | if (rc== 0) { |
246 | 0 | TPM_Sbuffer_Get(&sbuffer, &stream, &stream_size); |
247 | 0 | rc = TPM_Sha1Context_Load |
248 | 0 | (&context2, (unsigned char **)&stream, &stream_size); /* freed @2 */ |
249 | 0 | } |
250 | | /* digest the rest of the array */ |
251 | 0 | if (rc== 0) { |
252 | 0 | SHA1_Update(context2, buffer1 + 16, sizeof(buffer1) - 17); |
253 | 0 | SHA1_Final(actual, context2); |
254 | 0 | } |
255 | 0 | if (rc == 0) { |
256 | 0 | not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); |
257 | 0 | if (not_equal) { |
258 | 0 | printf("TPM_Crypto_TestSpecific: Error in test 1\n"); |
259 | 0 | TPM_PrintFour("\texpect", expect1); |
260 | 0 | TPM_PrintFour("\tactual", actual); |
261 | 0 | rc = TPM_FAILEDSELFTEST; |
262 | 0 | } |
263 | 0 | } |
264 | 0 | free(context1); /* @1 */ |
265 | 0 | free(context2); /* @2 */ |
266 | 0 | TPM_Sbuffer_Delete(&sbuffer); /* @3 */ |
267 | 0 | return rc; |
268 | 0 | } |
269 | | |
270 | | |
271 | | |
272 | | /* |
273 | | Random Number Functions |
274 | | */ |
275 | | |
276 | | /* TPM_Random() fills 'buffer' with 'bytes' bytes. |
277 | | */ |
278 | | |
279 | | TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes) |
280 | 0 | { |
281 | 0 | TPM_RESULT rc = 0; |
282 | |
|
283 | 0 | printf(" TPM_Random: Requesting %lu bytes\n", (unsigned long)bytes); |
284 | |
|
285 | 0 | if (rc == 0) { |
286 | | /* openSSL call */ |
287 | 0 | rc = RAND_bytes(buffer, bytes); |
288 | 0 | if (rc == 1) { /* OSSL success */ |
289 | 0 | rc = 0; |
290 | 0 | } |
291 | 0 | else { /* OSSL failure */ |
292 | 0 | printf("TPM_Random: Error (fatal) calling RAND_bytes()\n"); |
293 | 0 | rc = TPM_FAIL; |
294 | 0 | } |
295 | 0 | } |
296 | 0 | return rc; |
297 | 0 | } |
298 | | |
299 | | TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData) |
300 | 0 | { |
301 | 0 | TPM_RESULT rc = 0; |
302 | |
|
303 | 0 | printf(" TPM_StirRandomCmd:\n"); |
304 | 0 | if (rc == 0) { |
305 | | /* NOTE: The TPM command does not give an entropy estimate. This assumes the best case */ |
306 | | /* openSSL call */ |
307 | 0 | RAND_add(inData->buffer, /* buf mixed into PRNG state*/ |
308 | 0 | inData->size, /* number of bytes */ |
309 | 0 | inData->size); /* entropy, the lower bound of an estimate of how much randomness is |
310 | | contained in buf */ |
311 | 0 | } |
312 | 0 | return rc; |
313 | 0 | } |
314 | | |
315 | | /* |
316 | | RSA Functions |
317 | | */ |
318 | | |
319 | | /* Generate an RSA key pair. |
320 | | |
321 | | 'n', 'p', 'q', 'd' must be freed by the caller |
322 | | */ |
323 | | |
324 | | TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, /* public key - modulus */ |
325 | | unsigned char **p, /* private key prime */ |
326 | | unsigned char **q, /* private key prime */ |
327 | | unsigned char **d, /* private key (private exponent) */ |
328 | | int num_bits, /* key size in bits */ |
329 | | const unsigned char *earr, /* public exponent as an array */ |
330 | | uint32_t e_size) |
331 | 0 | { |
332 | 0 | TPM_RESULT rc = 0; |
333 | 0 | RSA *rsa = NULL; |
334 | 0 | const BIGNUM *bnn = NULL; |
335 | 0 | BIGNUM *bne = NULL; |
336 | 0 | const BIGNUM *bnp = NULL; |
337 | 0 | const BIGNUM *bnq = NULL; |
338 | 0 | const BIGNUM *bnd = NULL; |
339 | 0 | uint32_t nbytes; |
340 | 0 | uint32_t pbytes; |
341 | 0 | uint32_t qbytes; |
342 | 0 | uint32_t dbytes; |
343 | |
|
344 | 0 | unsigned long e; |
345 | | |
346 | | /* initialize in case of error */ |
347 | 0 | printf(" TPM_RSAGenerateKeyPair:\n"); |
348 | 0 | *n = NULL; |
349 | 0 | *p = NULL; |
350 | 0 | *q = NULL; |
351 | 0 | *d = NULL; |
352 | | |
353 | | /* check that num_bits is a multiple of 16. If not, the primes p and q will not be a multiple of |
354 | | 8 and will not fit well in a byte */ |
355 | 0 | if (rc == 0) { |
356 | 0 | if ((num_bits % 16) != 0) { |
357 | 0 | printf("TPM_RSAGenerateKeyPair: Error, num_bits %d is not a multiple of 16\n", |
358 | 0 | num_bits); |
359 | 0 | rc = TPM_BAD_KEY_PROPERTY; |
360 | 0 | } |
361 | 0 | } |
362 | | /* convert the e array to an unsigned long */ |
363 | 0 | if (rc == 0) { |
364 | 0 | rc = TPM_LoadLong(&e, earr, e_size); |
365 | 0 | } |
366 | | /* validate the public exponent against a list of legal values. Some values (e.g. even numbers) |
367 | | will hang the key generator. */ |
368 | 0 | if (rc == 0) { |
369 | 0 | rc = TPM_RSA_exponent_verify(e); |
370 | 0 | } |
371 | 0 | if (rc == 0) { |
372 | 0 | rsa = RSA_new(); /* freed @1 */ |
373 | 0 | if (rsa == NULL) { |
374 | 0 | printf("TPM_RSAGenerateKeyPair: Error in RSA_new()\n"); |
375 | 0 | rc = TPM_SIZE; |
376 | 0 | } |
377 | 0 | } |
378 | 0 | if (rc == 0) { |
379 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&bne, earr, e_size); /* freed @2 */ |
380 | 0 | } |
381 | 0 | if (rc == 0) { |
382 | 0 | printf(" TPM_RSAGenerateKeyPair: num_bits %d exponent %08lx\n", num_bits, e); |
383 | 0 | int irc = RSA_generate_key_ex(rsa, num_bits, bne, NULL); |
384 | 0 | if (irc != 1) { |
385 | 0 | printf("TPM_RSAGenerateKeyPair: Error calling RSA_generate_key_ex()\n"); |
386 | 0 | rc = TPM_BAD_KEY_PROPERTY; |
387 | 0 | } |
388 | 0 | } |
389 | 0 | if (rc == 0) { |
390 | | #if defined OPENSSL_OLD_API |
391 | | bnn = rsa->n; |
392 | | bnp = rsa->p; |
393 | | bnq = rsa->q; |
394 | | bnd = rsa->d; |
395 | | #else |
396 | | /* currently, this function accepts NULL inputs, but it's not guaranteed by the |
397 | | documentation */ |
398 | 0 | const BIGNUM *bnetmp = NULL; /* not needed */ |
399 | 0 | RSA_get0_key(rsa, &bnn, &bnetmp, &bnd); |
400 | 0 | RSA_get0_factors(rsa, &bnp, &bnq); |
401 | 0 | #endif |
402 | 0 | } |
403 | | /* load n */ |
404 | 0 | if (rc == 0) { |
405 | 0 | rc = TPM_bn2binMalloc(n, &nbytes, (TPM_BIGNUM)bnn, num_bits/8); /* freed by caller */ |
406 | 0 | } |
407 | | /* load p */ |
408 | 0 | if (rc == 0) { |
409 | 0 | rc = TPM_bn2binMalloc(p, &pbytes, (TPM_BIGNUM)bnp, num_bits/16); /* freed by caller */ |
410 | 0 | } |
411 | | /* load q */ |
412 | 0 | if (rc == 0) { |
413 | 0 | rc = TPM_bn2binMalloc(q, &qbytes, (TPM_BIGNUM)bnq, num_bits/16); /* freed by caller */ |
414 | 0 | } |
415 | | /* load d */ |
416 | 0 | if (rc == 0) { |
417 | 0 | rc = TPM_bn2binMalloc(d, &dbytes, (TPM_BIGNUM)bnd, num_bits/8); /* freed by caller */ |
418 | 0 | } |
419 | 0 | if (rc == 0) { |
420 | 0 | printf(" TPM_RSAGenerateKeyPair: length of n,p,q,d = %d / %d / %d / %d\n", |
421 | 0 | nbytes, pbytes, qbytes, dbytes); |
422 | 0 | } |
423 | 0 | if (rc != 0) { |
424 | 0 | free(*n); |
425 | 0 | free(*p); |
426 | 0 | free(*q); |
427 | 0 | free(*d); |
428 | 0 | *n = NULL; |
429 | 0 | *p = NULL; |
430 | 0 | *q = NULL; |
431 | 0 | *d = NULL; |
432 | 0 | } |
433 | 0 | if (rsa != NULL) { |
434 | 0 | RSA_free(rsa); /* @1 */ |
435 | 0 | } |
436 | 0 | if (bne != NULL) { |
437 | 0 | BN_free(bne); /* @2 */ |
438 | 0 | } |
439 | 0 | return rc; |
440 | 0 | } |
441 | | |
442 | | /* TPM_RSAGeneratePublicToken() generates an RSA key token from n and e |
443 | | */ |
444 | | |
445 | | static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, /* freed by caller */ |
446 | | unsigned char *narr, /* public modulus */ |
447 | | uint32_t nbytes, |
448 | | unsigned char *earr, /* public exponent */ |
449 | | uint32_t ebytes) |
450 | 0 | { |
451 | 0 | TPM_RESULT rc = 0; |
452 | 0 | BIGNUM * n = NULL; |
453 | 0 | BIGNUM * e = NULL; |
454 | | |
455 | | /* sanity check for the free */ |
456 | 0 | if (rc == 0) { |
457 | 0 | if (*rsa_pub_key != NULL) { |
458 | 0 | printf("TPM_RSAGeneratePublicToken: Error (fatal), token %p should be NULL\n", |
459 | 0 | *rsa_pub_key ); |
460 | 0 | rc = TPM_FAIL; |
461 | | |
462 | 0 | } |
463 | 0 | } |
464 | | /* construct the OpenSSL private key object */ |
465 | 0 | if (rc == 0) { |
466 | 0 | *rsa_pub_key = RSA_new(); /* freed by caller */ |
467 | 0 | if (*rsa_pub_key == NULL) { |
468 | 0 | printf("TPM_RSAGeneratePublicToken: Error in RSA_new()\n"); |
469 | 0 | rc = TPM_SIZE; |
470 | 0 | } |
471 | 0 | } |
472 | 0 | if (rc == 0) { |
473 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ |
474 | 0 | } |
475 | 0 | if (rc == 0) { |
476 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ |
477 | 0 | } |
478 | 0 | if (rc == 0) { |
479 | | #if defined OPENSSL_OLD_API |
480 | | (*rsa_pub_key)->n = n; |
481 | | (*rsa_pub_key)->e = e; |
482 | | (*rsa_pub_key)->d = NULL; |
483 | | #else |
484 | 0 | int irc = RSA_set0_key(*rsa_pub_key, n, e, NULL); |
485 | 0 | if (irc != 1) { |
486 | 0 | printf("TPM_RSAGeneratePublicToken: Error in RSA_set0_key()\n"); |
487 | 0 | rc = TPM_SIZE; |
488 | 0 | } |
489 | 0 | #endif |
490 | 0 | } |
491 | 0 | return rc; |
492 | 0 | } |
493 | | |
494 | | /* TPM_RSAGeneratePrivateToken() generates an RSA key token from n,e,d |
495 | | */ |
496 | | |
497 | | static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, /* freed by caller */ |
498 | | unsigned char *narr, /* public modulus */ |
499 | | uint32_t nbytes, |
500 | | unsigned char *earr, /* public exponent */ |
501 | | uint32_t ebytes, |
502 | | unsigned char *darr, /* private exponent */ |
503 | | uint32_t dbytes) |
504 | 0 | { |
505 | 0 | TPM_RESULT rc = 0; |
506 | 0 | BIGNUM * n = NULL; |
507 | 0 | BIGNUM * e = NULL; |
508 | 0 | BIGNUM * d = NULL; |
509 | | |
510 | | /* sanity check for the free */ |
511 | 0 | if (rc == 0) { |
512 | 0 | if (*rsa_pri_key != NULL) { |
513 | 0 | printf("TPM_RSAGeneratePrivateToken: Error (fatal), token %p should be NULL\n", |
514 | 0 | *rsa_pri_key ); |
515 | 0 | rc = TPM_FAIL; |
516 | | |
517 | 0 | } |
518 | 0 | } |
519 | | /* construct the OpenSSL private key object */ |
520 | 0 | if (rc == 0) { |
521 | 0 | *rsa_pri_key = RSA_new(); /* freed by caller */ |
522 | 0 | if (*rsa_pri_key == NULL) { |
523 | 0 | printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); |
524 | 0 | rc = TPM_SIZE; |
525 | 0 | } |
526 | 0 | } |
527 | 0 | if (rc == 0) { |
528 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ |
529 | 0 | } |
530 | 0 | if (rc == 0) { |
531 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ |
532 | 0 | } |
533 | 0 | if (rc == 0) { |
534 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ |
535 | 0 | } |
536 | 0 | if (rc == 0) { |
537 | | #if defined OPENSSL_OLD_API |
538 | | (*rsa_pri_key)->n = n; |
539 | | (*rsa_pri_key)->e = e; |
540 | | (*rsa_pri_key)->d = d; |
541 | | BN_set_flags(d, BN_FLG_CONSTTIME); // d is private |
542 | | #else |
543 | 0 | int irc = RSA_set0_key(*rsa_pri_key, n, e, d); |
544 | 0 | if (irc != 1) { |
545 | 0 | printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); |
546 | 0 | rc = TPM_SIZE; |
547 | 0 | } |
548 | 0 | #endif |
549 | 0 | } |
550 | 0 | return rc; |
551 | 0 | } |
552 | | |
553 | | #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added |
554 | | /* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP |
555 | | padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. |
556 | | |
557 | | 'decrypt_data_length' is at most 'decrypt_data_size'. |
558 | | */ |
559 | | |
560 | | TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ |
561 | | uint32_t *decrypt_data_length, /* length of data put into |
562 | | decrypt_data */ |
563 | | size_t decrypt_data_size, /* size of decrypt_data buffer */ |
564 | | TPM_ENC_SCHEME encScheme, /* encryption scheme */ |
565 | | unsigned char *encrypt_data, /* encrypted data */ |
566 | | uint32_t encrypt_data_size, |
567 | | unsigned char *narr, /* public modulus */ |
568 | | uint32_t nbytes, |
569 | | unsigned char *earr, /* public exponent */ |
570 | | uint32_t ebytes, |
571 | | unsigned char *darr, /* private exponent */ |
572 | | uint32_t dbytes) |
573 | | { |
574 | | TPM_RESULT rc = 0; |
575 | | int irc; |
576 | | RSA * rsa_pri_key = NULL; /* freed @1 */ |
577 | | |
578 | | unsigned char *padded_data = NULL; |
579 | | int padded_data_size = 0; |
580 | | |
581 | | printf(" TPM_RSAPrivateDecrypt:\n"); |
582 | | /* construct the OpenSSL private key object */ |
583 | | if (rc == 0) { |
584 | | rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ |
585 | | narr, /* public modulus */ |
586 | | nbytes, |
587 | | earr, /* public exponent */ |
588 | | ebytes, |
589 | | darr, /* private exponent */ |
590 | | dbytes); |
591 | | } |
592 | | /* intermediate buffer for the decrypted but still padded data */ |
593 | | if (rc == 0) { |
594 | | /* the size of the decrypted data is guaranteed to be less than this */ |
595 | | padded_data_size = RSA_size(rsa_pri_key); |
596 | | rc = TPM_Malloc(&padded_data, padded_data_size); |
597 | | } |
598 | | if (rc == 0) { |
599 | | /* decrypt with private key. Must decrypt first and then remove padding because the decrypt |
600 | | call cannot specify an encoding parameter */ |
601 | | /* returns the size of the encrypted data. On error, -1 is returned */ |
602 | | irc = RSA_private_decrypt(encrypt_data_size, /* length */ |
603 | | encrypt_data, /* from - the encrypted data */ |
604 | | padded_data, /* to - the decrypted but padded data */ |
605 | | rsa_pri_key, /* key */ |
606 | | RSA_NO_PADDING); /* padding */ |
607 | | if (irc < 0) { |
608 | | printf("TPM_RSAPrivateDecrypt: Error in RSA_private_decrypt()\n"); |
609 | | rc = TPM_DECRYPT_ERROR; |
610 | | } |
611 | | } |
612 | | if (rc == 0) { |
613 | | printf(" TPM_RSAPrivateDecrypt: RSA_private_decrypt() success\n"); |
614 | | printf(" TPM_RSAPrivateDecrypt: Padded data size %u\n", padded_data_size); |
615 | | TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt padded data", padded_data); |
616 | | if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { |
617 | | /* openSSL expects the padded data to skip the first 0x00 byte, since it expects the |
618 | | padded data to come from a bignum via bn2bin. */ |
619 | | irc = RSA_padding_check_PKCS1_OAEP(decrypt_data, /* to */ |
620 | | decrypt_data_size, /* to length */ |
621 | | padded_data + 1, /* from */ |
622 | | padded_data_size - 1, /* from length */ |
623 | | encrypt_data_size, /* rsa_len */ |
624 | | tpm_oaep_pad_str, /* encoding parameter */ |
625 | | sizeof(tpm_oaep_pad_str) /* encoding parameter length |
626 | | */ |
627 | | ); |
628 | | if (irc < 0) { |
629 | | printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_OAEP()\n"); |
630 | | rc = TPM_DECRYPT_ERROR; |
631 | | } |
632 | | } |
633 | | else if (encScheme == TPM_ES_RSAESPKCSv15) { |
634 | | irc = RSA_padding_check_PKCS1_type_2(decrypt_data, /* to */ |
635 | | decrypt_data_size, /* to length */ |
636 | | padded_data + 1, /* from */ |
637 | | padded_data_size - 1, /* from length */ |
638 | | encrypt_data_size /* rsa_len */ |
639 | | ); |
640 | | if (irc < 0) { |
641 | | printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_type_2()\n"); |
642 | | rc = TPM_DECRYPT_ERROR; |
643 | | } |
644 | | } |
645 | | else { |
646 | | printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); |
647 | | rc = TPM_INAPPROPRIATE_ENC; |
648 | | } |
649 | | } |
650 | | if (rc == 0) { |
651 | | *decrypt_data_length = irc; |
652 | | printf(" TPM_RSAPrivateDecrypt: RSA_padding_check_PKCS1_OAEP() recovered %d bytes\n", irc); |
653 | | TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); |
654 | | } |
655 | | if (rsa_pri_key != NULL) { |
656 | | RSA_free(rsa_pri_key); /* @1 */ |
657 | | } |
658 | | free(padded_data); /* @2 */ |
659 | | return rc; |
660 | | } |
661 | | |
662 | | #else // libtpms added begin |
663 | | |
664 | | TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ |
665 | | uint32_t *decrypt_data_length, /* length of data put into |
666 | | decrypt_data */ |
667 | | size_t decrypt_data_size, /* size of decrypt_data buffer */ |
668 | | TPM_ENC_SCHEME encScheme, /* encryption scheme */ |
669 | | unsigned char *encrypt_data, /* encrypted data */ |
670 | | uint32_t encrypt_data_size, |
671 | | unsigned char *narr, /* public modulus */ |
672 | | uint32_t nbytes, |
673 | | unsigned char *earr, /* public exponent */ |
674 | | uint32_t ebytes, |
675 | | unsigned char *darr, /* private exponent */ |
676 | | uint32_t dbytes) |
677 | 0 | { |
678 | 0 | TPM_RESULT rc = 0; |
679 | 0 | EVP_PKEY *pkey = NULL; |
680 | 0 | EVP_PKEY_CTX *ctx = NULL; |
681 | 0 | const EVP_MD *md = NULL; |
682 | 0 | unsigned char *label = NULL; |
683 | 0 | size_t outlen; |
684 | 0 | unsigned char buffer[(TPM_RSA_KEY_LENGTH_MAX + 7) / 8]; |
685 | |
|
686 | 0 | printf(" TPM_RSAPrivateDecrypt:\n"); |
687 | | /* construct the OpenSSL private key object */ |
688 | 0 | if (rc == 0) { |
689 | 0 | rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ |
690 | 0 | narr, /* public modulus */ |
691 | 0 | nbytes, |
692 | 0 | earr, /* public exponent */ |
693 | 0 | ebytes, |
694 | 0 | darr, /* private exponent */ |
695 | 0 | dbytes); |
696 | 0 | } |
697 | |
|
698 | 0 | if (rc == 0) { |
699 | 0 | ctx = EVP_PKEY_CTX_new(pkey, NULL); |
700 | 0 | if (ctx == 0) { |
701 | 0 | printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); |
702 | 0 | rc = TPM_FAIL; |
703 | 0 | } |
704 | 0 | } |
705 | 0 | if (rc == 0) { |
706 | 0 | if (EVP_PKEY_decrypt_init(ctx) <= 0) { |
707 | 0 | printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); |
708 | 0 | rc = TPM_FAIL; |
709 | 0 | } |
710 | 0 | } |
711 | |
|
712 | 0 | if (rc == 0) { |
713 | 0 | switch (encScheme) { |
714 | 0 | case TPM_ES_RSAESOAEP_SHA1_MGF1: |
715 | 0 | if (rc == 0) { |
716 | 0 | md = EVP_get_digestbyname("sha1"); |
717 | 0 | if (md == NULL || |
718 | 0 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || |
719 | 0 | EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { |
720 | 0 | printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); |
721 | 0 | rc = TPM_FAIL; |
722 | 0 | } |
723 | 0 | } |
724 | 0 | if (rc == 0) { |
725 | 0 | rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); |
726 | 0 | if (rc) { |
727 | 0 | printf("TPM_RSAPrivateDecrypt: TPM_Malloc failed\n"); |
728 | 0 | } |
729 | 0 | } |
730 | 0 | if (rc == 0) { |
731 | 0 | memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); |
732 | 0 | if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { |
733 | 0 | printf("TPM_RSAPrivateDecrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); |
734 | 0 | rc = TPM_FAIL; |
735 | 0 | } |
736 | 0 | if (rc == 0) { |
737 | 0 | label = NULL; |
738 | 0 | } |
739 | 0 | } |
740 | 0 | break; |
741 | 0 | case TPM_ES_RSAESPKCSv15: |
742 | 0 | if (rc == 0) { |
743 | 0 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { |
744 | 0 | printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESPKCSv15\n"); |
745 | 0 | rc = TPM_FAIL; |
746 | 0 | } |
747 | 0 | } |
748 | 0 | break; |
749 | 0 | default: |
750 | 0 | if (rc == 0) { |
751 | 0 | printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); |
752 | 0 | rc = TPM_INAPPROPRIATE_ENC; |
753 | 0 | } |
754 | 0 | } |
755 | 0 | } |
756 | | |
757 | 0 | if (rc == 0) { |
758 | 0 | outlen = sizeof(buffer); |
759 | 0 | if (EVP_PKEY_decrypt(ctx, buffer, &outlen, |
760 | 0 | encrypt_data, encrypt_data_size) <= 0) { |
761 | 0 | printf("TPM_RSAPrivateDecrypt: EVP_PKEY_decrypt failed\n"); |
762 | 0 | rc = TPM_DECRYPT_ERROR; |
763 | 0 | } |
764 | 0 | if (rc == 0) { |
765 | 0 | if (outlen > decrypt_data_size) { |
766 | 0 | printf("TPM_RSAPrivateDecrypt: Error, decrypt_data_size %zu too small for message size %zu\n", |
767 | 0 | decrypt_data_size, outlen); |
768 | 0 | rc = TPM_DECRYPT_ERROR; |
769 | 0 | } |
770 | 0 | } |
771 | 0 | if (rc == 0) { |
772 | 0 | *decrypt_data_length = (uint32_t)outlen; |
773 | 0 | memcpy(decrypt_data, buffer, outlen); |
774 | 0 | TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); |
775 | 0 | } |
776 | 0 | } |
777 | |
|
778 | 0 | EVP_PKEY_free(pkey); |
779 | 0 | EVP_PKEY_CTX_free(ctx); |
780 | 0 | TPM_Free(label); |
781 | |
|
782 | 0 | return rc; |
783 | 0 | } |
784 | | |
785 | | #endif // libtpms added end |
786 | | |
787 | | /* TPM_RSAPublicEncrypt() pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the public |
788 | | key 'n, e'. |
789 | | */ |
790 | | |
791 | | #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added |
792 | | |
793 | | TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ |
794 | | size_t encrypt_data_size, /* size of encrypted data buffer */ |
795 | | TPM_ENC_SCHEME encScheme, |
796 | | const unsigned char *decrypt_data, /* decrypted data */ |
797 | | size_t decrypt_data_size, |
798 | | unsigned char *narr, /* public modulus */ |
799 | | uint32_t nbytes, |
800 | | unsigned char *earr, /* public exponent */ |
801 | | uint32_t ebytes) |
802 | | { |
803 | | TPM_RESULT rc = 0; |
804 | | int irc; |
805 | | RSA *rsa_pub_key = NULL; |
806 | | unsigned char *padded_data = NULL; |
807 | | |
808 | | printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); |
809 | | /* intermediate buffer for the decrypted but still padded data */ |
810 | | if (rc == 0) { |
811 | | rc = TPM_Malloc(&padded_data, encrypt_data_size); /* freed @2 */ |
812 | | } |
813 | | /* construct the OpenSSL public key object */ |
814 | | if (rc == 0) { |
815 | | rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ |
816 | | narr, /* public modulus */ |
817 | | nbytes, |
818 | | earr, /* public exponent */ |
819 | | ebytes); |
820 | | } |
821 | | if (rc == 0) { |
822 | | if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { |
823 | | irc = RSA_padding_add_PKCS1_OAEP(padded_data, /* to */ |
824 | | encrypt_data_size, /* to length */ |
825 | | decrypt_data, /* from */ |
826 | | decrypt_data_size, /* from length */ |
827 | | tpm_oaep_pad_str, /* encoding parameter */ |
828 | | sizeof(tpm_oaep_pad_str) /* encoding parameter length |
829 | | */ |
830 | | ); |
831 | | if (irc != 1) { |
832 | | printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_OAEP()\n"); |
833 | | rc = TPM_ENCRYPT_ERROR; |
834 | | } |
835 | | else { |
836 | | printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_OAEP() success\n"); |
837 | | } |
838 | | } |
839 | | else if (encScheme == TPM_ES_RSAESPKCSv15) { |
840 | | irc = RSA_padding_add_PKCS1_type_2(padded_data, /* to */ |
841 | | encrypt_data_size, /* to length */ |
842 | | decrypt_data, /* from */ |
843 | | decrypt_data_size); /* from length */ |
844 | | if (irc != 1) { |
845 | | printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_type_2()\n"); |
846 | | rc = TPM_ENCRYPT_ERROR; |
847 | | } |
848 | | else { |
849 | | printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_type_2() success\n"); |
850 | | } |
851 | | } |
852 | | else { |
853 | | printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); |
854 | | rc = TPM_INAPPROPRIATE_ENC; |
855 | | } |
856 | | } |
857 | | if (rc == 0) { |
858 | | printf(" TPM_RSAPublicEncrypt: Padded data size %lu\n", (unsigned long)encrypt_data_size); |
859 | | TPM_PrintFour(" TPM_RSAPublicEncrypt: Padded data", padded_data); |
860 | | /* encrypt with public key. Must pad first and then encrypt because the encrypt |
861 | | call cannot specify an encoding parameter */ |
862 | | /* returns the size of the encrypted data. On error, -1 is returned */ |
863 | | irc = RSA_public_encrypt(encrypt_data_size, /* from length */ |
864 | | padded_data, /* from - the clear text data */ |
865 | | encrypt_data, /* the padded and encrypted data */ |
866 | | rsa_pub_key, /* key */ |
867 | | RSA_NO_PADDING); /* padding */ |
868 | | if (irc < 0) { |
869 | | printf("TPM_RSAPublicEncrypt: Error in RSA_public_encrypt()\n"); |
870 | | rc = TPM_ENCRYPT_ERROR; |
871 | | } |
872 | | } |
873 | | if (rc == 0) { |
874 | | printf(" TPM_RSAPublicEncrypt: RSA_public_encrypt() success\n"); |
875 | | } |
876 | | if (rsa_pub_key != NULL) { |
877 | | RSA_free(rsa_pub_key); /* @1 */ |
878 | | } |
879 | | free(padded_data); /* @2 */ |
880 | | return rc; |
881 | | } |
882 | | |
883 | | #else // libtpms added begin |
884 | | |
885 | | TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ |
886 | | size_t encrypt_data_size, /* size of encrypted data buffer */ |
887 | | TPM_ENC_SCHEME encScheme, |
888 | | const unsigned char *decrypt_data, /* decrypted data */ |
889 | | size_t decrypt_data_size, |
890 | | unsigned char *narr, /* public modulus */ |
891 | | uint32_t nbytes, |
892 | | unsigned char *earr, /* public exponent */ |
893 | | uint32_t ebytes) |
894 | 0 | { |
895 | 0 | TPM_RESULT rc = 0; |
896 | 0 | EVP_PKEY *pkey = NULL; |
897 | 0 | EVP_PKEY_CTX *ctx = NULL; |
898 | 0 | const EVP_MD *md = NULL; |
899 | 0 | unsigned char *label = NULL; |
900 | 0 | size_t outlen; |
901 | |
|
902 | 0 | printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); |
903 | | |
904 | | /* construct the OpenSSL private key object */ |
905 | 0 | if (rc == 0) { |
906 | 0 | rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ |
907 | 0 | narr, /* public modulus */ |
908 | 0 | nbytes, |
909 | 0 | earr, /* public exponent */ |
910 | 0 | ebytes, |
911 | 0 | NULL, /* private exponent */ |
912 | 0 | 0); |
913 | 0 | } |
914 | |
|
915 | 0 | if (rc == 0) { |
916 | 0 | ctx = EVP_PKEY_CTX_new(pkey, NULL); |
917 | 0 | if (ctx == 0) { |
918 | 0 | printf("TPM_RSAqPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); |
919 | 0 | rc = TPM_FAIL; |
920 | 0 | } |
921 | 0 | } |
922 | 0 | if (rc == 0) { |
923 | 0 | if (EVP_PKEY_encrypt_init(ctx) <= 0) { |
924 | 0 | printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); |
925 | 0 | rc = TPM_FAIL; |
926 | 0 | } |
927 | 0 | } |
928 | |
|
929 | 0 | if (rc == 0) { |
930 | 0 | switch (encScheme) { |
931 | 0 | case TPM_ES_RSAESOAEP_SHA1_MGF1: |
932 | 0 | if (rc == 0) { |
933 | 0 | md = EVP_get_digestbyname("sha1"); |
934 | 0 | if (md == NULL || |
935 | 0 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || |
936 | 0 | EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { |
937 | 0 | printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); |
938 | 0 | rc = TPM_FAIL; |
939 | 0 | } |
940 | 0 | } |
941 | 0 | if (rc == 0) { |
942 | 0 | rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); |
943 | 0 | if (rc) { |
944 | 0 | printf("TPM_RSAPublicEncrypt: TPM_Malloc failed\n"); |
945 | 0 | } |
946 | 0 | } |
947 | 0 | if (rc == 0) { |
948 | 0 | memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); |
949 | 0 | if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { |
950 | 0 | printf("TPM_RSAPublicEncrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); |
951 | 0 | rc = TPM_FAIL; |
952 | 0 | } |
953 | 0 | if (rc == 0) { |
954 | 0 | label = NULL; |
955 | 0 | } |
956 | 0 | } |
957 | 0 | break; |
958 | 0 | case TPM_ES_RSAESPKCSv15: |
959 | 0 | if (rc == 0) { |
960 | 0 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { |
961 | 0 | printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESPKCSv15\n"); |
962 | 0 | rc = TPM_FAIL; |
963 | 0 | } |
964 | 0 | } |
965 | 0 | break; |
966 | 0 | default: |
967 | 0 | if (rc == 0) { |
968 | 0 | printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); |
969 | 0 | rc = TPM_INAPPROPRIATE_ENC; |
970 | 0 | } |
971 | 0 | } |
972 | 0 | } |
973 | | |
974 | 0 | if (rc == 0) { |
975 | 0 | outlen = encrypt_data_size; |
976 | 0 | if (EVP_PKEY_encrypt(ctx, encrypt_data, &outlen, |
977 | 0 | decrypt_data, decrypt_data_size) <= 0) { |
978 | 0 | printf("TPM_RSAPublicEncrypt: EVP_PKEY_encrypt failed\n"); |
979 | 0 | rc = TPM_ENCRYPT_ERROR; |
980 | 0 | } |
981 | 0 | } |
982 | |
|
983 | 0 | EVP_PKEY_free(pkey); |
984 | 0 | EVP_PKEY_CTX_free(ctx); |
985 | 0 | TPM_Free(label); |
986 | |
|
987 | 0 | return rc; |
988 | 0 | } |
989 | | |
990 | | #endif // libtpms added end |
991 | | |
992 | | #if USE_FREEBL_CRYPTO_LIBRARY |
993 | | /* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. |
994 | | |
995 | | */ |
996 | | |
997 | | TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, /* output */ |
998 | | uint32_t encrypt_data_size, /* input, size of message buffer */ |
999 | | unsigned char *decrypt_data, /* input */ |
1000 | | uint32_t decrypt_data_size, /* input, size of sig buffer */ |
1001 | | unsigned char *narr, /* public modulus */ |
1002 | | uint32_t nbytes, |
1003 | | unsigned char *earr, /* public exponent */ |
1004 | | uint32_t ebytes) |
1005 | | { |
1006 | | TPM_RESULT rc = 0; |
1007 | | int irc; |
1008 | | RSA *rsa_pub_key = NULL; |
1009 | | |
1010 | | printf(" TPM_RSAPublicEncryptRaw:\n"); |
1011 | | /* the input data size must equal the public key size */ |
1012 | | if (rc == 0) { |
1013 | | if (decrypt_data_size != nbytes) { |
1014 | | printf("TPM_RSAPublicEncryptRaw: Error, decrypt data size is %u not %u\n", |
1015 | | decrypt_data_size, nbytes); |
1016 | | rc = TPM_ENCRYPT_ERROR; |
1017 | | } |
1018 | | } |
1019 | | /* the output data size must equal the public key size */ |
1020 | | if (rc == 0) { |
1021 | | if (encrypt_data_size != nbytes) { |
1022 | | printf("TPM_RSAPublicEncryptRaw: Error, Encrypted data size is %u not %u\n", |
1023 | | encrypt_data_size, nbytes); |
1024 | | rc = TPM_ENCRYPT_ERROR; |
1025 | | } |
1026 | | } |
1027 | | /* construct the OpenSSL public key object */ |
1028 | | if (rc == 0) { |
1029 | | rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ |
1030 | | narr, /* public modulus */ |
1031 | | nbytes, |
1032 | | earr, /* public exponent */ |
1033 | | ebytes); |
1034 | | } |
1035 | | if (rc == 0) { |
1036 | | TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Public modulus", narr); |
1037 | | TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Public exponent", earr, ebytes); |
1038 | | TPM_PrintFourLimit(" TPM_RSAPublicEncryptRaw: Decrypt data", decrypt_data, decrypt_data_size); |
1039 | | /* encrypt the decrypt_data */ |
1040 | | irc = RSA_public_encrypt(decrypt_data_size, /* from length */ |
1041 | | decrypt_data, /* from - the clear text data */ |
1042 | | encrypt_data, /* to - the padded and encrypted data */ |
1043 | | rsa_pub_key, /* key */ |
1044 | | RSA_NO_PADDING); /* padding */ |
1045 | | if (irc < 0) { |
1046 | | printf("TPM_RSAPublicEncryptRaw: Error in RSA_public_encrypt()\n"); |
1047 | | rc = TPM_ENCRYPT_ERROR; |
1048 | | } |
1049 | | } |
1050 | | if (rc == 0) { |
1051 | | TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data); |
1052 | | #if 0 /* NOTE: Uncomment as a debug aid for signature verification */ |
1053 | | TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Padded signed data", |
1054 | | encrypt_data, encrypt_data_size); |
1055 | | #endif |
1056 | | } |
1057 | | if (rsa_pub_key != NULL) { |
1058 | | RSA_free(rsa_pub_key); /* @1 */ |
1059 | | } |
1060 | | return rc; |
1061 | | } |
1062 | | #endif |
1063 | | |
1064 | | /* TPM_RSASign() signs 'message' of size 'message_size' using the private key n,e,d and the |
1065 | | signature scheme 'sigScheme' as specified in PKCS #1 v2.0. |
1066 | | |
1067 | | 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most |
1068 | | 'signature_size'. signature must point to RSA_size(rsa) bytes of memory. |
1069 | | */ |
1070 | | /* Note regarding conversion to EVP_PKEY_sign for the purpose of constant-timeness: |
1071 | | |
1072 | | - TPM_SS_RSASSAPKCS1v15_SHA1: |
1073 | | EVP_PKEY_sign() will call pkey_rsa_sign() which in turn will call RSA_sign() for |
1074 | | RSA_PKCS1_PADDING. This is the same as we do here. |
1075 | | - TPM_SS_RSASSAPKCS1v15_DER: |
1076 | | EVP_PKEY_sign() must not have a message digest since none of the padding choices calls |
1077 | | RSA_padding_add_PKCS1_type_1(), so we would have to do the padding again ourselves. |
1078 | | */ |
1079 | | |
1080 | | TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ |
1081 | | unsigned int *signature_length, /* output, size of signature */ |
1082 | | unsigned int signature_size, /* input, size of signature buffer */ |
1083 | | TPM_SIG_SCHEME sigScheme, /* input, type of signature */ |
1084 | | const unsigned char *message, /* input */ |
1085 | | size_t message_size, /* input */ |
1086 | | unsigned char *narr, /* public modulus */ |
1087 | | uint32_t nbytes, |
1088 | | unsigned char *earr, /* public exponent */ |
1089 | | uint32_t ebytes, |
1090 | | unsigned char *darr, /* private exponent */ |
1091 | | uint32_t dbytes) |
1092 | 0 | { |
1093 | 0 | TPM_RESULT rc = 0; |
1094 | 0 | RSA * rsa_pri_key = NULL; /* freed @1 */ |
1095 | 0 | unsigned int key_size; |
1096 | |
|
1097 | 0 | printf(" TPM_RSASign:\n"); |
1098 | | /* construct the OpenSSL private key object */ |
1099 | 0 | if (rc == 0) { |
1100 | 0 | rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ |
1101 | 0 | narr, /* public modulus */ |
1102 | 0 | nbytes, |
1103 | 0 | earr, /* public exponent */ |
1104 | 0 | ebytes, |
1105 | 0 | darr, /* private exponent */ |
1106 | 0 | dbytes); |
1107 | 0 | } |
1108 | | /* check the size of the output signature buffer */ |
1109 | 0 | if (rc == 0) { |
1110 | 0 | key_size = (unsigned int)RSA_size(rsa_pri_key); /* openSSL returns an int, but never |
1111 | | negative */ |
1112 | 0 | if (signature_size < key_size) { |
1113 | 0 | printf("TPM_RSASign: Error (fatal), buffer %u too small for signature %u\n", |
1114 | 0 | signature_size, key_size); |
1115 | 0 | rc = TPM_FAIL; /* internal error, should never occur */ |
1116 | 0 | } |
1117 | 0 | } |
1118 | | /* determine the signature scheme for the key */ |
1119 | 0 | if (rc == 0) { |
1120 | 0 | switch(sigScheme) { |
1121 | 0 | case TPM_SS_NONE: |
1122 | 0 | printf("TPM_RSASign: Error, sigScheme TPM_SS_NONE\n"); |
1123 | 0 | rc = TPM_INVALID_KEYUSAGE; |
1124 | 0 | break; |
1125 | 0 | case TPM_SS_RSASSAPKCS1v15_SHA1: |
1126 | 0 | case TPM_SS_RSASSAPKCS1v15_INFO: |
1127 | 0 | rc = TPM_RSASignSHA1(signature, |
1128 | 0 | signature_length, |
1129 | 0 | message, |
1130 | 0 | message_size, |
1131 | 0 | rsa_pri_key); |
1132 | 0 | break; |
1133 | 0 | case TPM_SS_RSASSAPKCS1v15_DER: |
1134 | 0 | rc = TPM_RSASignDER(signature, |
1135 | 0 | signature_length, |
1136 | 0 | message, |
1137 | 0 | message_size, |
1138 | 0 | rsa_pri_key); |
1139 | 0 | break; |
1140 | 0 | default: |
1141 | 0 | printf("TPM_RSASign: Error, sigScheme %04hx unknown\n", sigScheme); |
1142 | 0 | rc = TPM_INVALID_KEYUSAGE; |
1143 | 0 | break; |
1144 | 0 | } |
1145 | 0 | } |
1146 | 0 | if (rsa_pri_key != NULL) { |
1147 | 0 | RSA_free(rsa_pri_key); /* @1 */ |
1148 | 0 | } |
1149 | 0 | return rc; |
1150 | 0 | } |
1151 | | |
1152 | | /* TPM_RSASignSHA1() performs the following: |
1153 | | prepend a DER encoded algorithm ID |
1154 | | prepend a type 1 pad |
1155 | | encrypt with the private key |
1156 | | */ |
1157 | | |
1158 | | static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, /* output */ |
1159 | | unsigned int *signature_length, /* output, size of signature */ |
1160 | | const unsigned char *message, /* input */ |
1161 | | size_t message_size, /* input */ |
1162 | | RSA *rsa_pri_key) /* signing private key */ |
1163 | 0 | { |
1164 | 0 | TPM_RESULT rc = 0; |
1165 | 0 | int irc; |
1166 | |
|
1167 | 0 | printf(" TPM_RSASignSHA1:\n"); |
1168 | | /* sanity check, SHA1 messages must be 20 bytes */ |
1169 | 0 | if (rc == 0) { |
1170 | 0 | if (message_size != TPM_DIGEST_SIZE) { |
1171 | 0 | printf("TPM_RSASignSHA1: Error, message size %lu not TPM_DIGEST_SIZE\n", |
1172 | 0 | (unsigned long)message_size ); |
1173 | 0 | rc = TPM_DECRYPT_ERROR; |
1174 | 0 | } |
1175 | 0 | } |
1176 | 0 | if (rc == 0) { |
1177 | | /* type NID_sha1, adds the algorithm identifier and type 1 pad */ |
1178 | 0 | irc = RSA_sign(NID_sha1, /* type */ |
1179 | 0 | message, message_size, |
1180 | 0 | signature, signature_length, |
1181 | 0 | rsa_pri_key); |
1182 | | /* RSA_sign() returns 1 on success, 0 otherwise. */ |
1183 | 0 | if (irc != 1) { |
1184 | 0 | printf("TPM_RSASignSHA1: Error in RSA_sign()\n"); |
1185 | 0 | rc = TPM_DECRYPT_ERROR; |
1186 | 0 | } |
1187 | 0 | } |
1188 | 0 | return rc; |
1189 | 0 | } |
1190 | | |
1191 | | /* TPM_RSASignDER() performs the following: |
1192 | | |
1193 | | prepend a type 1 pad |
1194 | | encrypt with the private key |
1195 | | |
1196 | | The caller must check that the signature buffer is >= the key size. |
1197 | | */ |
1198 | | |
1199 | | static TPM_RESULT TPM_RSASignDER(unsigned char *signature, /* output */ |
1200 | | unsigned int *signature_length, /* output, size of signature */ |
1201 | | const unsigned char *message, /* input */ |
1202 | | size_t message_size, /* input */ |
1203 | | RSA *rsa_pri_key) /* signing private key */ |
1204 | 0 | { |
1205 | 0 | TPM_RESULT rc = 0; |
1206 | 0 | int irc; |
1207 | 0 | int key_size; |
1208 | 0 | unsigned char *message_pad; |
1209 | 0 | int int_sig_len; /* openSSL overloads RSA_private_decrypt return code */ |
1210 | | |
1211 | 0 | printf(" TPM_RSASignDER:\n"); |
1212 | 0 | message_pad = NULL; /* freed @1 */ |
1213 | | /* the padded message size is the same as the key size */ |
1214 | 0 | if (rc == 0) { |
1215 | 0 | key_size = RSA_size(rsa_pri_key); |
1216 | 0 | if (key_size < 0) { |
1217 | 0 | printf(" TPM_RSASignDER: Error (fatal), negative key size %d\n", key_size); |
1218 | 0 | rc = TPM_FAIL; /* should never occur */ |
1219 | 0 | } |
1220 | 0 | } |
1221 | | /* allocate memory for the padded message */ |
1222 | 0 | if (rc == 0) { |
1223 | 0 | printf(" TPM_RSASignDER: key size %d\n", key_size); |
1224 | 0 | rc = TPM_Malloc(&message_pad, key_size); /* freed @1 */ |
1225 | 0 | } |
1226 | | /* PKCS1 type 1 pad the message */ |
1227 | 0 | if (rc == 0) { |
1228 | 0 | printf(" TPM_RSASignDER: Applying PKCS1 type 1 padding, size from %lu to %u\n", |
1229 | 0 | (unsigned long)message_size, key_size); |
1230 | 0 | TPM_PrintFourLimit(" TPM_RSASignDER: Input message", message, message_size); |
1231 | | /* This call checks that the message will fit with the padding */ |
1232 | 0 | irc = RSA_padding_add_PKCS1_type_1(message_pad, /* to */ |
1233 | 0 | key_size, |
1234 | 0 | message, /* from */ |
1235 | 0 | message_size); |
1236 | 0 | if (irc != 1) { |
1237 | 0 | printf("TPM_RSASignDER: Error padding message, size %lu key size %u\n", |
1238 | 0 | (unsigned long)message_size, key_size); |
1239 | 0 | rc = TPM_DECRYPT_ERROR; |
1240 | 0 | } |
1241 | 0 | } |
1242 | | /* raw sign with private key */ |
1243 | 0 | if (rc == 0) { |
1244 | 0 | printf(" TPM_RSASignDER: Encrypting with private key, message size %d\n", key_size); |
1245 | 0 | TPM_PrintFour(" TPM_RSASignDER: Padded message", message_pad); |
1246 | | /* returns the size of the encrypted data. On error, -1 is returned */ |
1247 | 0 | int_sig_len = RSA_private_encrypt(key_size, /* int flen */ |
1248 | 0 | message_pad, /* unsigned char *from, */ |
1249 | 0 | signature, /* unsigned char *to, */ |
1250 | 0 | rsa_pri_key, /* RSA *rsa, */ |
1251 | 0 | RSA_NO_PADDING); /* int padding); */ |
1252 | 0 | if (int_sig_len >= 0) { |
1253 | 0 | *signature_length = (unsigned int)int_sig_len; |
1254 | 0 | } |
1255 | 0 | else { |
1256 | 0 | printf("TPM_RSASignDER: Error in RSA_private_encrypt()\n"); |
1257 | 0 | rc = TPM_DECRYPT_ERROR; |
1258 | 0 | } |
1259 | 0 | } |
1260 | 0 | if (rc == 0) { |
1261 | 0 | TPM_PrintFour(" TPM_RSASignDER: signature", signature); |
1262 | 0 | } |
1263 | 0 | free(message_pad); /* @1 */ |
1264 | 0 | return rc; |
1265 | 0 | } |
1266 | | |
1267 | | /* TPM_RSAVerifySHA1() performs the following: |
1268 | | decrypt the signature |
1269 | | verify and remove type 1 pad |
1270 | | verify and remove DER encoded algorithm ID |
1271 | | verify the signature on the message |
1272 | | */ |
1273 | | |
1274 | | TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, /* input */ |
1275 | | unsigned int signature_size, /* input, size of signature |
1276 | | buffer */ |
1277 | | const unsigned char *message, /* input */ |
1278 | | uint32_t message_size, /* input */ |
1279 | | unsigned char *narr, /* public modulus */ |
1280 | | uint32_t nbytes, |
1281 | | unsigned char *earr, /* public exponent */ |
1282 | | uint32_t ebytes) |
1283 | 0 | { |
1284 | 0 | TPM_RESULT rc = 0; |
1285 | 0 | TPM_BOOL valid; |
1286 | 0 | RSA * rsa_pub_key = NULL; |
1287 | | |
1288 | 0 | printf(" TPM_RSAVerifySHA1:\n"); |
1289 | | /* construct the openSSL public key object from n and e */ |
1290 | 0 | if (rc == 0) { |
1291 | 0 | rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ |
1292 | 0 | narr, /* public modulus */ |
1293 | 0 | nbytes, |
1294 | 0 | earr, /* public exponent */ |
1295 | 0 | ebytes); |
1296 | 0 | } |
1297 | 0 | if (rc == 0) { |
1298 | | /* RSA_verify() returns 1 on successful verification, 0 otherwise. */ |
1299 | 0 | valid = RSA_verify(NID_sha1, |
1300 | 0 | message, message_size, |
1301 | 0 | signature, signature_size, rsa_pub_key); |
1302 | 0 | if (valid != 1) { |
1303 | 0 | printf("TPM_RSAVerifySHA1: Error, bad signature\n"); |
1304 | 0 | rc = TPM_BAD_SIGNATURE; |
1305 | 0 | } |
1306 | 0 | } |
1307 | 0 | if (rsa_pub_key != NULL) { |
1308 | 0 | RSA_free(rsa_pub_key); /* @1 */ |
1309 | 0 | } |
1310 | 0 | return rc; |
1311 | 0 | } |
1312 | | |
1313 | | /* TPM_RSAGetPrivateKey recalculates q (2nd prime factor) and d (private key) from n (public key), e |
1314 | | (public exponent), and p (1st prime factor) |
1315 | | |
1316 | | The private key is validated by dividing the RSA product n by the RSA prime p and verifying that |
1317 | | the remainder is 0. |
1318 | | |
1319 | | 'qarr', darr' must be freed by the caller. |
1320 | | */ |
1321 | | |
1322 | | TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, |
1323 | | uint32_t *dbytes, unsigned char **darr, |
1324 | | uint32_t nbytes, unsigned char *narr, |
1325 | | uint32_t ebytes, unsigned char *earr, |
1326 | | uint32_t pbytes, unsigned char *parr) |
1327 | 0 | { |
1328 | 0 | TPM_RESULT rc = 0; /* TPM return code */ |
1329 | 0 | int irc; /* openSSL return code */ |
1330 | 0 | BIGNUM *brc; /* BIGNUM return code */ |
1331 | |
|
1332 | 0 | BIGNUM *n = NULL; /* public modulus */ |
1333 | 0 | BIGNUM *e = NULL; /* public exponent */ |
1334 | 0 | BIGNUM *d = NULL; /* private exponent */ |
1335 | 0 | BIGNUM *p = NULL; /* secret prime factor */ |
1336 | 0 | BIGNUM *q = NULL; /* secret prime factor */ |
1337 | | /* temporary variables */ |
1338 | 0 | BN_CTX *ctx = NULL; /* freed @5, @6 */ |
1339 | 0 | BIGNUM *r0 = NULL; /* n/p remainder */ |
1340 | 0 | BIGNUM *r1 = NULL; |
1341 | 0 | BIGNUM *r2 = NULL; |
1342 | | |
1343 | | /* set to NULL so caller can free after failure */ |
1344 | 0 | printf(" TPM_RSAGetPrivateKey:\n"); |
1345 | 0 | *qarr = NULL; |
1346 | 0 | *darr = NULL; |
1347 | | /* check input parameters */ |
1348 | 0 | if (rc == 0) { |
1349 | 0 | if ((narr == NULL) || (nbytes == 0)) { |
1350 | 0 | printf("TPM_RSAGetPrivateKey: Error, missing n\n"); |
1351 | 0 | rc = TPM_BAD_PARAMETER; |
1352 | 0 | } |
1353 | 0 | } |
1354 | | /* check input parameters */ |
1355 | 0 | if (rc == 0) { |
1356 | 0 | if ((earr == NULL) || (ebytes == 0)) { |
1357 | 0 | printf("TPM_RSAGetPrivateKey: Error, missing e\n"); |
1358 | 0 | rc = TPM_BAD_PARAMETER; |
1359 | 0 | } |
1360 | 0 | } |
1361 | | /* check input parameters */ |
1362 | 0 | if (rc == 0) { |
1363 | 0 | if ((parr == NULL) || (pbytes == 0)) { |
1364 | 0 | printf("TPM_RSAGetPrivateKey: Error, missing p\n"); |
1365 | 0 | rc = TPM_BAD_PARAMETER; |
1366 | 0 | } |
1367 | 0 | } |
1368 | | /* get some temporary BIGNUM's for use in the calculations */ |
1369 | 0 | if (rc == 0) { |
1370 | 0 | rc = TPM_BN_CTX_new(&ctx); |
1371 | 0 | } |
1372 | 0 | if (rc == 0) { |
1373 | 0 | BN_CTX_start(ctx); /* no return code */ |
1374 | 0 | r0 = BN_CTX_get(ctx); /* sufficient to test return of last 'get' call */ |
1375 | 0 | r1 = BN_CTX_get(ctx); |
1376 | 0 | r2 = BN_CTX_get(ctx); |
1377 | 0 | if (r2 == 0) { |
1378 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_CTX_get()\n"); |
1379 | 0 | TPM_OpenSSL_PrintError(); |
1380 | 0 | rc = TPM_SIZE; |
1381 | 0 | } |
1382 | 0 | } |
1383 | | /* allocate BIGNUM's for q, d */ |
1384 | 0 | if (rc == 0) { |
1385 | 0 | rc = TPM_BN_new((TPM_BIGNUM *)&q); |
1386 | 0 | } |
1387 | 0 | if (rc == 0) { |
1388 | 0 | rc = TPM_BN_new((TPM_BIGNUM *)&d); |
1389 | 0 | } |
1390 | | /* convert n, e, p to BIGNUM's */ |
1391 | 0 | if (rc == 0) { |
1392 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed @1 */ |
1393 | 0 | } |
1394 | 0 | if (rc == 0) { |
1395 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed @2 */ |
1396 | 0 | } |
1397 | 0 | if (rc == 0) { |
1398 | 0 | rc = TPM_bin2bn((TPM_BIGNUM *)&p, parr, pbytes); /* freed @3 */ |
1399 | 0 | if (p) |
1400 | 0 | BN_set_flags(p, BN_FLG_CONSTTIME); // p is private |
1401 | 0 | } |
1402 | | /* calculate q = n/p */ |
1403 | 0 | if (rc == 0) { |
1404 | 0 | irc = BN_div(q, r0, n, p, ctx); /* q = n/p freed @4 */ |
1405 | 0 | if (irc != 1) { /* 1 is success */ |
1406 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_div()\n"); |
1407 | 0 | TPM_OpenSSL_PrintError(); |
1408 | 0 | rc = TPM_BAD_PARAMETER; |
1409 | 0 | } else |
1410 | 0 | BN_set_flags(q, BN_FLG_CONSTTIME); // q is private |
1411 | 0 | } |
1412 | | /* remainder should be zero */ |
1413 | 0 | if (rc == 0) { |
1414 | 0 | irc = BN_is_zero(r0); |
1415 | 0 | if (irc != 1) { /* 1 is success */ |
1416 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_is_zero()\n"); |
1417 | 0 | rc = TPM_BAD_PARAMETER; |
1418 | 0 | } |
1419 | 0 | } |
1420 | | /* calculate r0 = p-1 */ |
1421 | 0 | if (rc == 0) { |
1422 | 0 | irc = BN_sub(r0, p, BN_value_one()); /* r0 = p-1 freed @6 */ |
1423 | 0 | if (irc != 1) { /* 1 is success */ |
1424 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); |
1425 | 0 | TPM_OpenSSL_PrintError(); |
1426 | 0 | rc = TPM_BAD_PARAMETER; |
1427 | 0 | } |
1428 | 0 | } |
1429 | | /* calculate r1 = q-1 */ |
1430 | 0 | if (rc == 0) { |
1431 | 0 | irc = BN_sub(r1, q, BN_value_one()); /* freed @6 */ |
1432 | 0 | if (irc != 1) { /* 1 is success */ |
1433 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); |
1434 | 0 | TPM_OpenSSL_PrintError(); |
1435 | 0 | rc = TPM_BAD_PARAMETER; |
1436 | 0 | } |
1437 | 0 | } |
1438 | | /* calculate r2 = (p-1)(q-1) */ |
1439 | 0 | if (rc == 0) { |
1440 | 0 | irc = BN_mul(r2, r0, r1, ctx); /* freed @6 */ |
1441 | 0 | if (irc != 1) { /* 1 is success */ |
1442 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_mul()\n"); |
1443 | 0 | TPM_OpenSSL_PrintError(); |
1444 | 0 | rc = TPM_BAD_PARAMETER; |
1445 | 0 | } else |
1446 | 0 | BN_set_flags(r2, BN_FLG_CONSTTIME); // r2 is private |
1447 | 0 | } |
1448 | | /* calculate d = multiplicative inverse e mod r0 */ |
1449 | 0 | if (rc == 0) { |
1450 | 0 | brc = BN_mod_inverse(d, e, r2, ctx); /* feed @5 */ |
1451 | 0 | if (brc == NULL) { |
1452 | 0 | printf("TPM_RSAGetPrivateKey: Error in BN_mod_inverse()\n"); |
1453 | 0 | TPM_OpenSSL_PrintError(); |
1454 | 0 | rc = TPM_BAD_PARAMETER; |
1455 | 0 | } |
1456 | 0 | } |
1457 | | /* get q as an array */ |
1458 | 0 | if (rc == 0) { |
1459 | 0 | rc = TPM_bn2binMalloc(qarr, qbytes, (TPM_BIGNUM)q, pbytes); /* freed by caller */ |
1460 | 0 | } |
1461 | | /* get d as an array */ |
1462 | 0 | if (rc == 0) { |
1463 | 0 | TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated q", *qarr); |
1464 | 0 | rc = TPM_bn2binMalloc(darr, dbytes, (TPM_BIGNUM)d, nbytes); /* freed by caller */ |
1465 | 0 | } |
1466 | 0 | if (rc == 0) { |
1467 | 0 | TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated d", *darr); |
1468 | 0 | printf(" TPM_RSAGetPrivateKey: length of n,p,q,d = %u / %u / %u / %u\n", |
1469 | 0 | nbytes, pbytes, *qbytes, *dbytes); |
1470 | 0 | } |
1471 | 0 | BN_free(n); /* @1 */ |
1472 | 0 | BN_free(e); /* @2 */ |
1473 | 0 | BN_free(p); /* @3 */ |
1474 | 0 | BN_free(q); /* @4 */ |
1475 | 0 | BN_free(d); /* @3 */ |
1476 | 0 | BN_CTX_end(ctx); /* @5 */ |
1477 | 0 | BN_CTX_free(ctx); /* @6 */ |
1478 | 0 | return rc; |
1479 | 0 | } |
1480 | | |
1481 | | /* |
1482 | | openSSL wrappers do error logging and transformation of openSSL errors to TPM type errors |
1483 | | */ |
1484 | | |
1485 | | /* TPM_OpenSSL_PrintError() prints a detailed openSSL error trace. |
1486 | | |
1487 | | */ |
1488 | | |
1489 | | static void TPM_OpenSSL_PrintError() |
1490 | 0 | { |
1491 | | /* openssl error printing */ |
1492 | 0 | unsigned long error; |
1493 | 0 | const char *file; |
1494 | 0 | int line; |
1495 | 0 | const char *data; |
1496 | 0 | int flags; |
1497 | |
|
1498 | 0 | error = ERR_get_error_line_data(&file, &line, &data, &flags); |
1499 | 0 | printf("\terror %08lx file %s line %d data %s flags %08x\n", |
1500 | 0 | error, file, line, data, flags); |
1501 | 0 | return; |
1502 | 0 | } |
1503 | | |
1504 | | /* TPM_BN_num_bytes() wraps the openSSL function in a TPM error handler |
1505 | | |
1506 | | Returns number of bytes in the input |
1507 | | */ |
1508 | | |
1509 | | TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in) |
1510 | 0 | { |
1511 | 0 | TPM_RESULT rc = 0; |
1512 | 0 | int i; |
1513 | 0 | BIGNUM *bn = (BIGNUM *)bn_in; |
1514 | | |
1515 | 0 | i = BN_num_bytes(bn); |
1516 | 0 | if (i >= 0) { |
1517 | 0 | *numBytes = (unsigned int)i; |
1518 | 0 | } |
1519 | 0 | else { |
1520 | 0 | printf("TPM_BN_num_bytes: Error (fatal), bytes in BIGNUM is negative\n"); |
1521 | 0 | TPM_OpenSSL_PrintError(); |
1522 | 0 | rc = TPM_FAIL; |
1523 | 0 | } |
1524 | 0 | return rc; |
1525 | 0 | } |
1526 | | |
1527 | | /* TPM_BN_is_one() wraps the openSSL function in a TPM error handler |
1528 | | |
1529 | | Returns success if input is 1 |
1530 | | */ |
1531 | | |
1532 | | TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in) |
1533 | 0 | { |
1534 | 0 | TPM_RESULT rc = 0; |
1535 | 0 | int irc; |
1536 | 0 | BIGNUM *bn = (BIGNUM *)bn_in; |
1537 | | |
1538 | | /* int BN_is_one(BIGNUM *a); |
1539 | | BN_is_one() tests if a equals 0, 1, |
1540 | | BN_is_one() returns 1 if the condition is true, 0 otherwise. */ |
1541 | 0 | irc = BN_is_one(bn); |
1542 | 0 | if (irc != 1) { |
1543 | 0 | printf("TPM_BN_is_one: Error, result is not 1\n"); |
1544 | 0 | rc = TPM_DAA_WRONG_W; |
1545 | 0 | } |
1546 | 0 | return rc; |
1547 | 0 | } |
1548 | | |
1549 | | /* TPM_BN_mod() wraps the openSSL function in a TPM error handler |
1550 | | |
1551 | | r = a mod m |
1552 | | */ |
1553 | | |
1554 | | TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, |
1555 | | const TPM_BIGNUM a_in, |
1556 | | const TPM_BIGNUM m_in) |
1557 | 0 | { |
1558 | 0 | TPM_RESULT rc = 0; |
1559 | 0 | int irc; |
1560 | 0 | BIGNUM *rem = (BIGNUM *)rem_in; |
1561 | 0 | BIGNUM *a = (BIGNUM *)a_in; |
1562 | 0 | BIGNUM *m = (BIGNUM *)m_in; |
1563 | 0 | BN_CTX *ctx = NULL; /* freed @1 */ |
1564 | |
|
1565 | 0 | if (rc == 0) { |
1566 | 0 | rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ |
1567 | 0 | } |
1568 | | /*int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); |
1569 | | BN_mod() corresponds to BN_div() with dv set to NULL. |
1570 | | |
1571 | | int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx); |
1572 | | |
1573 | | BN_div() divides a by d and places the result in dv and the remainder in rem (dv=a/d, |
1574 | | rem=a%d). Either of dv and rem may be NULL, in which case the respective value is not |
1575 | | returned. The result is rounded towards zero; thus if a is negative, the remainder will be |
1576 | | zero or negative. For division by powers of 2, use BN_rshift(3). |
1577 | | |
1578 | | For all functions, 1 is returned for success, 0 on error. The return value should always be |
1579 | | checked |
1580 | | */ |
1581 | 0 | irc = BN_mod(rem, a, m, ctx); |
1582 | 0 | if (irc != 1) { |
1583 | 0 | printf("TPM_BN_mod: Error performing BN_mod()\n"); |
1584 | 0 | TPM_OpenSSL_PrintError(); |
1585 | 0 | rc = TPM_DAA_WRONG_W; |
1586 | 0 | } |
1587 | 0 | BN_CTX_free(ctx); /* @1 */ |
1588 | 0 | return rc; |
1589 | 0 | } |
1590 | | |
1591 | | /* TPM_BN_mask_bits() wraps the openSSL function in a TPM error handler |
1592 | | |
1593 | | erase all but the lowest n bits of bn |
1594 | | bn = bn mod 2^^n |
1595 | | */ |
1596 | | |
1597 | | TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n) |
1598 | 0 | { |
1599 | 0 | TPM_RESULT rc = 0; |
1600 | 0 | int irc; |
1601 | 0 | unsigned int numBytes; |
1602 | 0 | BIGNUM *bn = (BIGNUM *)bn_in; |
1603 | |
|
1604 | 0 | if (rc == 0) { |
1605 | 0 | rc = TPM_BN_num_bytes(&numBytes, bn_in); |
1606 | 0 | } |
1607 | | /* if the BIGNUM is already the correct number of bytes, no need to mask, and BN_mask_bits() |
1608 | | will fail. */ |
1609 | 0 | if (rc == 0) { |
1610 | 0 | if (numBytes > (n / 8)) { |
1611 | | /* BN_mask_bits() truncates a to an n bit number (a&=~((~0)>>;n)). An error occurs if a |
1612 | | already is shorter than n bits. |
1613 | | |
1614 | | int BN_mask_bits(BIGNUM *a, int n); |
1615 | | return 1 for success, 0 on error. |
1616 | | */ |
1617 | 0 | irc = BN_mask_bits(bn, n); |
1618 | 0 | if (irc != 1) { |
1619 | 0 | printf("TPM_BN_mask_bits: Error performing BN_mask_bits()\n"); |
1620 | 0 | TPM_OpenSSL_PrintError(); |
1621 | 0 | rc = TPM_DAA_WRONG_W; |
1622 | 0 | } |
1623 | 0 | } |
1624 | 0 | } |
1625 | 0 | return rc; |
1626 | 0 | } |
1627 | | |
1628 | | /* TPM_BN_rshift() wraps the openSSL function in a TPM error handler |
1629 | | |
1630 | | Shift a right by n bits (discard the lowest n bits) and label the result r |
1631 | | */ |
1632 | | |
1633 | | TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ |
1634 | | TPM_BIGNUM aBignum_in, |
1635 | | int n) |
1636 | 0 | { |
1637 | 0 | TPM_RESULT rc = 0; |
1638 | 0 | int irc; |
1639 | 0 | BIGNUM **rBignum = (BIGNUM **)rBignum_in; |
1640 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1641 | | |
1642 | 0 | printf(" TPM_BN_rshift: n %d\n", n); |
1643 | 0 | if (rc == 0) { |
1644 | 0 | rc = TPM_BN_new(rBignum_in); |
1645 | 0 | } |
1646 | 0 | if (rc == 0) { |
1647 | | /* BN_rshift() shifts a right by n bits and places the result in r (r=a/2^n). |
1648 | | int BN_rshift(BIGNUM *r, BIGNUM *a, int n); |
1649 | | return 1 for success, 0 on error. |
1650 | | */ |
1651 | 0 | irc = BN_rshift(*rBignum, aBignum, n); |
1652 | 0 | if (irc != 1) { |
1653 | 0 | printf("TPM_BN_rshift: Error performing BN_rshift()\n"); |
1654 | 0 | TPM_OpenSSL_PrintError(); |
1655 | 0 | rc = TPM_DAA_WRONG_W; |
1656 | 0 | } |
1657 | 0 | } |
1658 | 0 | return rc; |
1659 | 0 | } |
1660 | | |
1661 | | /* TPM_BN_lshift() wraps the openSSL function in a TPM error handler |
1662 | | |
1663 | | Shift a left by n bits and label the result r |
1664 | | */ |
1665 | | |
1666 | | TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ |
1667 | | TPM_BIGNUM aBignum_in, |
1668 | | int n) |
1669 | 0 | { |
1670 | 0 | TPM_RESULT rc = 0; |
1671 | 0 | int irc; |
1672 | 0 | BIGNUM **rBignum = (BIGNUM **)rBignum_in; |
1673 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1674 | | |
1675 | 0 | printf(" TPM_BN_lshift: n %d\n", n); |
1676 | 0 | if (rc == 0) { |
1677 | 0 | rc = TPM_BN_new(rBignum_in); |
1678 | 0 | } |
1679 | 0 | if (rc == 0) { |
1680 | | /* BN_lshift() shifts a left by n bits and places the result in r (r=a*2^n). |
1681 | | int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); |
1682 | | return 1 for success, 0 on error. |
1683 | | */ |
1684 | 0 | irc = BN_lshift(*rBignum, aBignum, n); |
1685 | 0 | if (irc != 1) { |
1686 | 0 | printf("TPM_lshift: Error performing BN_lshift()\n"); |
1687 | 0 | TPM_OpenSSL_PrintError(); |
1688 | 0 | rc = TPM_DAA_WRONG_W; |
1689 | 0 | } |
1690 | 0 | } |
1691 | 0 | return rc; |
1692 | 0 | } |
1693 | | |
1694 | | /* TPM_BN_add() wraps the openSSL function in a TPM error handler |
1695 | | |
1696 | | Performs R = A + B |
1697 | | |
1698 | | R may be the same as A or B |
1699 | | */ |
1700 | | |
1701 | | TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, |
1702 | | TPM_BIGNUM aBignum_in, |
1703 | | TPM_BIGNUM bBignum_in) |
1704 | 0 | { |
1705 | 0 | TPM_RESULT rc = 0; |
1706 | 0 | int irc; |
1707 | 0 | BIGNUM *rBignum = (BIGNUM *)rBignum_in; |
1708 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1709 | 0 | BIGNUM *bBignum = (BIGNUM *)bBignum_in; |
1710 | |
|
1711 | 0 | printf(" TPM_BN_add:\n"); |
1712 | | /* int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); |
1713 | | BN_add() adds a and b and places the result in r (r=a+b). r may be the same BIGNUM as a or b. |
1714 | | 1 is returned for success, 0 on error. |
1715 | | */ |
1716 | 0 | irc = BN_add(rBignum, aBignum, bBignum); |
1717 | 0 | if (irc != 1) { |
1718 | 0 | printf("TPM_BN_add: Error performing BN_add()\n"); |
1719 | 0 | TPM_OpenSSL_PrintError(); |
1720 | 0 | rc = TPM_DAA_WRONG_W; |
1721 | 0 | } |
1722 | 0 | return rc; |
1723 | 0 | } |
1724 | | |
1725 | | /* TPM_BN_mul() wraps the openSSL function in a TPM error handler |
1726 | | |
1727 | | r = a * b |
1728 | | */ |
1729 | | |
1730 | | TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, |
1731 | | TPM_BIGNUM aBignum_in, |
1732 | | TPM_BIGNUM bBignum_in) |
1733 | 0 | { |
1734 | 0 | TPM_RESULT rc = 0; |
1735 | 0 | int irc; |
1736 | 0 | BN_CTX *ctx; |
1737 | 0 | BIGNUM *rBignum = (BIGNUM *)rBignum_in; |
1738 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1739 | 0 | BIGNUM *bBignum = (BIGNUM *)bBignum_in; |
1740 | |
|
1741 | 0 | printf(" TPM_BN_mul:\n"); |
1742 | 0 | ctx = NULL; /* freed @1 */ |
1743 | 0 | if (rc == 0) { |
1744 | 0 | rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ |
1745 | 0 | } |
1746 | | /* int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); |
1747 | | BN_mul() multiplies a and b and places the result in r (r=a*b). r may be the same BIGNUM as a |
1748 | | or b. |
1749 | | 1 is returned for success, 0 on error. |
1750 | | */ |
1751 | 0 | if (rc == 0) { |
1752 | 0 | irc = BN_mul(rBignum, aBignum, bBignum, ctx); |
1753 | 0 | if (irc != 1) { |
1754 | 0 | printf("TPM_BN_add: Error performing BN_mul()\n"); |
1755 | 0 | TPM_OpenSSL_PrintError(); |
1756 | 0 | rc = TPM_DAA_WRONG_W; |
1757 | 0 | } |
1758 | 0 | } |
1759 | 0 | BN_CTX_free(ctx); /* @1 */ |
1760 | 0 | return rc; |
1761 | 0 | } |
1762 | | |
1763 | | /* TPM_BN_mod_exp() wraps the openSSL function in a TPM error handler |
1764 | | |
1765 | | computes a to the p-th power modulo m (r=a^p % n) |
1766 | | */ |
1767 | | |
1768 | | TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, |
1769 | | TPM_BIGNUM aBignum_in, |
1770 | | TPM_BIGNUM pBignum_in, |
1771 | | TPM_BIGNUM nBignum_in) |
1772 | 0 | { |
1773 | 0 | TPM_RESULT rc = 0; |
1774 | 0 | int irc; |
1775 | 0 | BN_CTX *ctx; |
1776 | 0 | BIGNUM *rBignum = (BIGNUM *)rBignum_in; |
1777 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1778 | 0 | BIGNUM *pBignum = (BIGNUM *)pBignum_in; |
1779 | 0 | BIGNUM *nBignum = (BIGNUM *)nBignum_in; |
1780 | | |
1781 | 0 | printf(" TPM_BN_mod_exp:\n"); |
1782 | 0 | ctx = NULL; /* freed @1 */ |
1783 | 0 | if (rc == 0) { |
1784 | 0 | rc = TPM_BN_CTX_new(&ctx); |
1785 | 0 | } |
1786 | | /* BIGNUM calculation */ |
1787 | | /* int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); |
1788 | | |
1789 | | BN_mod_exp() computes a to the p-th power modulo m (r=a^p % m). This function uses less time |
1790 | | and space than BN_exp(). |
1791 | | |
1792 | | 1 is returned for success, 0 on error. |
1793 | | */ |
1794 | 0 | if (rc == 0) { |
1795 | 0 | printf(" TPM_BN_mod_exp: Calculate mod_exp\n"); |
1796 | 0 | BN_set_flags(pBignum, BN_FLG_CONSTTIME); // p may be private |
1797 | 0 | irc = BN_mod_exp(rBignum, aBignum, pBignum, nBignum, ctx); |
1798 | 0 | if (irc != 1) { |
1799 | 0 | printf("TPM_BN_mod_exp: Error performing BN_mod_exp()\n"); |
1800 | 0 | TPM_OpenSSL_PrintError(); |
1801 | 0 | rc = TPM_DAA_WRONG_W; |
1802 | 0 | } |
1803 | 0 | } |
1804 | 0 | BN_CTX_free(ctx); /* @1 */ |
1805 | 0 | return rc; |
1806 | 0 | } |
1807 | | |
1808 | | /* TPM_BN_Mod_add() wraps the openSSL function in a TPM error handler |
1809 | | |
1810 | | adds a to b modulo m |
1811 | | */ |
1812 | | |
1813 | | TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, |
1814 | | TPM_BIGNUM aBignum_in, |
1815 | | TPM_BIGNUM bBignum_in, |
1816 | | TPM_BIGNUM mBignum_in) |
1817 | 0 | { |
1818 | 0 | TPM_RESULT rc = 0; |
1819 | 0 | int irc; |
1820 | 0 | BN_CTX *ctx; |
1821 | 0 | BIGNUM *rBignum = (BIGNUM *)rBignum_in; |
1822 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1823 | 0 | BIGNUM *bBignum = (BIGNUM *)bBignum_in; |
1824 | 0 | BIGNUM *mBignum = (BIGNUM *)mBignum_in; |
1825 | |
|
1826 | 0 | printf(" TPM_BN_mod_add:\n"); |
1827 | 0 | ctx = NULL; /* freed @1 */ |
1828 | 0 | if (rc == 0) { |
1829 | 0 | rc = TPM_BN_CTX_new(&ctx); |
1830 | 0 | } |
1831 | | /* int BN_mod_add(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); |
1832 | | BN_mod_add() adds a to b modulo m and places the non-negative result in r. |
1833 | | 1 is returned for success, 0 on error. |
1834 | | */ |
1835 | 0 | if (rc == 0) { |
1836 | 0 | irc = BN_mod_add(rBignum, aBignum, bBignum, mBignum, ctx); |
1837 | 0 | if (irc != 1) { |
1838 | 0 | printf("TPM_BN_mod_add: Error performing BN_mod_add()\n"); |
1839 | 0 | TPM_OpenSSL_PrintError(); |
1840 | 0 | rc = TPM_DAA_WRONG_W; |
1841 | 0 | } |
1842 | 0 | } |
1843 | |
|
1844 | 0 | BN_CTX_free(ctx); /* @1 */ |
1845 | 0 | return rc; |
1846 | 0 | } |
1847 | | |
1848 | | /* TPM_BN_mod_mul() wraps the openSSL function in a TPM error handler |
1849 | | |
1850 | | r = (a * b) mod m |
1851 | | */ |
1852 | | |
1853 | | TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, |
1854 | | TPM_BIGNUM aBignum_in, |
1855 | | TPM_BIGNUM bBignum_in, |
1856 | | TPM_BIGNUM mBignum_in) |
1857 | 0 | { |
1858 | 0 | TPM_RESULT rc = 0; |
1859 | 0 | int irc; |
1860 | 0 | BN_CTX *ctx; |
1861 | 0 | BIGNUM *rBignum = (BIGNUM *)rBignum_in; |
1862 | 0 | BIGNUM *aBignum = (BIGNUM *)aBignum_in; |
1863 | 0 | BIGNUM *bBignum = (BIGNUM *)bBignum_in; |
1864 | 0 | BIGNUM *mBignum = (BIGNUM *)mBignum_in; |
1865 | |
|
1866 | 0 | printf(" TPM_BN_mod_mul:\n"); |
1867 | 0 | ctx = NULL; /* freed @1 */ |
1868 | 0 | if (rc == 0) { |
1869 | 0 | rc = TPM_BN_CTX_new(&ctx); |
1870 | 0 | } |
1871 | | /* int BN_mod_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); |
1872 | | BN_mod_mul() multiplies a by b and finds the non-negative remainder respective to modulus m |
1873 | | (r=(a*b) mod m). r may be the same BIGNUM as a or b. |
1874 | | 1 is returned for success, 0 on error. |
1875 | | */ |
1876 | 0 | if (rc == 0) { |
1877 | 0 | irc = BN_mod_mul(rBignum, aBignum, bBignum, mBignum, ctx); |
1878 | 0 | if (irc != 1) { |
1879 | 0 | printf("TPM_BN_mod_mul: Error performing BN_mod_mul()\n"); |
1880 | 0 | TPM_OpenSSL_PrintError(); |
1881 | 0 | rc = TPM_DAA_WRONG_W; |
1882 | 0 | } |
1883 | 0 | } |
1884 | 0 | BN_CTX_free(ctx); /* @1 */ |
1885 | 0 | return rc; |
1886 | 0 | } |
1887 | | |
1888 | | /* TPM_BN_CTX_new() wraps the openSSL function in a TPM error handler */ |
1889 | | |
1890 | | static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx) |
1891 | 0 | { |
1892 | 0 | TPM_RESULT rc = 0; |
1893 | |
|
1894 | 0 | if (rc == 0) { |
1895 | 0 | if (*ctx != NULL) { |
1896 | 0 | printf("TPM_BN_CTX_new: Error (fatal), *ctx %p should be NULL before BN_CTX_new \n", |
1897 | 0 | *ctx); |
1898 | 0 | rc = TPM_FAIL; |
1899 | 0 | } |
1900 | 0 | } |
1901 | 0 | if (rc == 0) { |
1902 | 0 | *ctx = BN_CTX_new(); |
1903 | 0 | if (*ctx == NULL) { |
1904 | 0 | printf("TPM_BN_CTX_new: Error, context is NULL\n"); |
1905 | 0 | TPM_OpenSSL_PrintError(); |
1906 | 0 | rc = TPM_SIZE; |
1907 | |
|
1908 | 0 | } |
1909 | 0 | } |
1910 | 0 | return rc; |
1911 | 0 | } |
1912 | | |
1913 | | /* TPM_BN_new() wraps the openSSL function in a TPM error handler |
1914 | | |
1915 | | Allocates a new bignum |
1916 | | */ |
1917 | | |
1918 | | TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in) |
1919 | 0 | { |
1920 | 0 | TPM_RESULT rc = 0; |
1921 | 0 | BIGNUM **bn = (BIGNUM **)bn_in; |
1922 | |
|
1923 | 0 | *bn = BN_new(); |
1924 | 0 | if (*bn == NULL) { |
1925 | 0 | printf("TPM_BN_new: Error, bn is NULL\n"); |
1926 | 0 | TPM_OpenSSL_PrintError(); |
1927 | 0 | rc = TPM_SIZE; |
1928 | 0 | } |
1929 | 0 | return rc; |
1930 | 0 | } |
1931 | | |
1932 | | /* TPM_BN_free() wraps the openSSL function |
1933 | | |
1934 | | Frees the bignum |
1935 | | */ |
1936 | | |
1937 | | void TPM_BN_free(TPM_BIGNUM bn_in) |
1938 | 0 | { |
1939 | 0 | BIGNUM *bn = (BIGNUM *)bn_in; |
1940 | | |
1941 | 0 | BN_free(bn); |
1942 | 0 | return; |
1943 | 0 | } |
1944 | | |
1945 | | /* TPM_bn2bin wraps the openSSL function in a TPM error handler. |
1946 | | |
1947 | | Converts a bignum to char array |
1948 | | |
1949 | | 'bin' must already be checked for sufficient size. |
1950 | | |
1951 | | int BN_bn2bin(const BIGNUM *a, unsigned char *to); |
1952 | | BN_bn2bin() returns the length of the big-endian number placed at to |
1953 | | */ |
1954 | | |
1955 | | TPM_RESULT TPM_bn2bin(unsigned char *bin, |
1956 | | TPM_BIGNUM bn_in) |
1957 | 0 | { |
1958 | 0 | TPM_RESULT rc = 0; |
1959 | 0 | BN_bn2bin((BIGNUM *)bn_in, bin); |
1960 | 0 | return rc; |
1961 | 0 | } |
1962 | | |
1963 | | |
1964 | | /* TPM_bin2bn() wraps the openSSL function in a TPM error handler |
1965 | | |
1966 | | Converts a char array to bignum |
1967 | | |
1968 | | bn must be freed by the caller. |
1969 | | */ |
1970 | | |
1971 | | TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes) |
1972 | 0 | { |
1973 | 0 | TPM_RESULT rc = 0; |
1974 | 0 | BIGNUM **bn = (BIGNUM **)bn_in; |
1975 | | |
1976 | | /* BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); |
1977 | | |
1978 | | BN_bin2bn() converts the positive integer in big-endian form of length len at s into a BIGNUM |
1979 | | and places it in ret. If ret is NULL, a new BIGNUM is created. |
1980 | | |
1981 | | BN_bin2bn() returns the BIGNUM, NULL on error. |
1982 | | */ |
1983 | 0 | if (rc == 0) { |
1984 | 0 | *bn = BN_bin2bn(bin, bytes, *bn); |
1985 | 0 | if (*bn == NULL) { |
1986 | 0 | printf("TPM_bin2bn: Error in BN_bin2bn\n"); |
1987 | 0 | TPM_OpenSSL_PrintError(); |
1988 | 0 | rc = TPM_SIZE; |
1989 | 0 | } |
1990 | 0 | } |
1991 | 0 | return rc; |
1992 | 0 | } |
1993 | | |
1994 | | /* |
1995 | | Hash Functions |
1996 | | */ |
1997 | | |
1998 | | /* for the openSSL version, TPM_SHA1Context is a SHA_CTX structure */ |
1999 | | |
2000 | | /* TPM_SHA1InitCmd() initializes a platform dependent TPM_SHA1Context structure. |
2001 | | |
2002 | | The structure must be freed using TPM_SHA1Delete() |
2003 | | */ |
2004 | | |
2005 | | TPM_RESULT TPM_SHA1InitCmd(void **context) |
2006 | 0 | { |
2007 | 0 | TPM_RESULT rc = 0; |
2008 | |
|
2009 | 0 | printf(" TPM_SHA1InitCmd:\n"); |
2010 | 0 | if (rc== 0) { |
2011 | 0 | rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); |
2012 | 0 | } |
2013 | 0 | if (rc== 0) { |
2014 | 0 | SHA1_Init(*context); |
2015 | 0 | } |
2016 | 0 | return rc; |
2017 | 0 | } |
2018 | | |
2019 | | /* TPM_SHA1UpdateCmd() adds 'data' of 'length' to the SHA-1 context |
2020 | | */ |
2021 | | |
2022 | | TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length) |
2023 | 0 | { |
2024 | 0 | TPM_RESULT rc = 0; |
2025 | | |
2026 | 0 | printf(" TPM_SHA1Update: length %u\n", length); |
2027 | 0 | if (context != NULL) { |
2028 | 0 | SHA1_Update(context, data, length); |
2029 | 0 | } |
2030 | 0 | else { |
2031 | 0 | printf("TPM_SHA1Update: Error, no existing SHA1 thread\n"); |
2032 | 0 | rc = TPM_SHA_THREAD; |
2033 | 0 | } |
2034 | 0 | return rc; |
2035 | 0 | } |
2036 | | |
2037 | | /* TPM_SHA1FinalCmd() extracts the SHA-1 digest 'md' from the context |
2038 | | */ |
2039 | | |
2040 | | TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context) |
2041 | 0 | { |
2042 | 0 | TPM_RESULT rc = 0; |
2043 | | |
2044 | 0 | printf(" TPM_SHA1FinalCmd:\n"); |
2045 | 0 | if (context != NULL) { |
2046 | 0 | SHA1_Final(md, context); |
2047 | 0 | } |
2048 | 0 | else { |
2049 | 0 | printf("TPM_SHA1FinalCmd: Error, no existing SHA1 thread\n"); |
2050 | 0 | rc = TPM_SHA_THREAD; |
2051 | 0 | } |
2052 | 0 | return rc; |
2053 | 0 | } |
2054 | | |
2055 | | /* TPM_SHA1Delete() zeros and frees the SHA1 context */ |
2056 | | |
2057 | | void TPM_SHA1Delete(void **context) |
2058 | 0 | { |
2059 | 0 | if (*context != NULL) { |
2060 | 0 | printf(" TPM_SHA1Delete:\n"); |
2061 | | /* zero because the SHA1 context might have data left from an HMAC */ |
2062 | 0 | memset(*context, 0, sizeof(SHA_CTX)); |
2063 | 0 | free(*context); |
2064 | 0 | *context = NULL; |
2065 | 0 | } |
2066 | 0 | return; |
2067 | 0 | } |
2068 | | |
2069 | | /* TPM_Sha1Context_Load() is non-portable code to deserialize the OpenSSL SHA1 context. |
2070 | | |
2071 | | If the contextPresent prepended by TPM_Sha1Context_Store() is FALSE, context remains NULL. If |
2072 | | TRUE, context is allocated and loaded. |
2073 | | */ |
2074 | | |
2075 | | TPM_RESULT TPM_Sha1Context_Load(void **context, |
2076 | | unsigned char **stream, |
2077 | | uint32_t *stream_size) |
2078 | 0 | { |
2079 | 0 | TPM_RESULT rc = 0; |
2080 | 0 | size_t i; |
2081 | 0 | SHA_CTX *sha_ctx = NULL; /* initialize to silence hopefully bogus gcc 4.4.4 |
2082 | | warning */ |
2083 | 0 | TPM_BOOL contextPresent; /* is there a context to be loaded */ |
2084 | |
|
2085 | 0 | printf(" TPM_Sha1Context_Load: OpenSSL\n"); |
2086 | | /* TPM_Sha1Context_Store() stored a flag to indicate whether a context should be stored */ |
2087 | 0 | if (rc== 0) { |
2088 | 0 | rc = TPM_LoadBool(&contextPresent, stream, stream_size); |
2089 | 0 | printf(" TPM_Sha1Context_Load: contextPresent %u\n", contextPresent); |
2090 | 0 | } |
2091 | | /* check format tag */ |
2092 | | /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' |
2093 | | on the tag */ |
2094 | 0 | if ((rc== 0) && contextPresent) { |
2095 | 0 | rc = TPM_CheckTag(TPM_TAG_SHA1CONTEXT_OSSL_V1, stream, stream_size); |
2096 | 0 | } |
2097 | 0 | if ((rc== 0) && contextPresent) { |
2098 | 0 | rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); |
2099 | 0 | sha_ctx = (SHA_CTX *)*context; |
2100 | 0 | } |
2101 | | /* load h0 */ |
2102 | 0 | if ((rc== 0) && contextPresent) { |
2103 | 0 | rc = TPM_Load32(&(sha_ctx->h0), stream, stream_size); |
2104 | 0 | } |
2105 | | /* load h1 */ |
2106 | 0 | if ((rc== 0) && contextPresent) { |
2107 | 0 | rc = TPM_Load32(&(sha_ctx->h1), stream, stream_size); |
2108 | 0 | } |
2109 | | /* load h2 */ |
2110 | 0 | if ((rc== 0) && contextPresent) { |
2111 | 0 | rc = TPM_Load32(&(sha_ctx->h2), stream, stream_size); |
2112 | 0 | } |
2113 | | /* load h3 */ |
2114 | 0 | if ((rc== 0) && contextPresent) { |
2115 | 0 | rc = TPM_Load32(&(sha_ctx->h3), stream, stream_size); |
2116 | 0 | } |
2117 | | /* load h4 */ |
2118 | 0 | if ((rc== 0) && contextPresent) { |
2119 | 0 | rc = TPM_Load32(&(sha_ctx->h4), stream, stream_size); |
2120 | 0 | } |
2121 | | /* load Nl */ |
2122 | 0 | if ((rc== 0) && contextPresent) { |
2123 | 0 | rc = TPM_Load32(&(sha_ctx->Nl), stream, stream_size); |
2124 | 0 | } |
2125 | | /* load Nh */ |
2126 | 0 | if ((rc== 0) && contextPresent) { |
2127 | 0 | rc = TPM_Load32(&(sha_ctx->Nh), stream, stream_size); |
2128 | 0 | } |
2129 | | /* load data */ |
2130 | 0 | for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { |
2131 | 0 | rc = TPM_Load32(&(sha_ctx->data[i]), stream, stream_size); |
2132 | 0 | } |
2133 | | /* load num */ |
2134 | 0 | if ((rc== 0) && contextPresent) { |
2135 | 0 | rc = TPM_Load32(&(sha_ctx->num), stream, stream_size); |
2136 | 0 | } |
2137 | 0 | return rc; |
2138 | 0 | } |
2139 | | |
2140 | | /* TPM_Sha1Context_Store() is non-portable code to serialize the OpenSSL SHA1 context. context is |
2141 | | not altered. |
2142 | | |
2143 | | It prepends a contextPresent flag to the stream, FALSE if context is NULL, TRUE if not. |
2144 | | */ |
2145 | | |
2146 | | TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, |
2147 | | void *context) |
2148 | 0 | { |
2149 | 0 | TPM_RESULT rc = 0; |
2150 | 0 | size_t i; |
2151 | 0 | SHA_CTX *sha_ctx = (SHA_CTX *)context; |
2152 | 0 | TPM_BOOL contextPresent; /* is there a context to be stored */ |
2153 | |
|
2154 | 0 | printf(" TPM_Sha1Context_Store: OpenSSL\n"); |
2155 | | /* store contextPresent */ |
2156 | 0 | if (rc == 0) { |
2157 | 0 | if (sha_ctx != NULL) { |
2158 | 0 | printf(" TPM_Sha1Context_Store: Storing context\n"); |
2159 | 0 | contextPresent = TRUE; |
2160 | 0 | } |
2161 | 0 | else { |
2162 | 0 | printf(" TPM_Sha1Context_Store: No context to store\n"); |
2163 | 0 | contextPresent = FALSE; |
2164 | 0 | } |
2165 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &contextPresent, sizeof(TPM_BOOL)); |
2166 | 0 | } |
2167 | | /* overall format tag */ |
2168 | 0 | if ((rc== 0) && contextPresent) { |
2169 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SHA1CONTEXT_OSSL_V1); |
2170 | 0 | } |
2171 | 0 | if ((rc== 0) && contextPresent) { |
2172 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h0); |
2173 | 0 | } |
2174 | 0 | if ((rc== 0) && contextPresent) { |
2175 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h1); |
2176 | 0 | } |
2177 | 0 | if ((rc== 0) && contextPresent) { |
2178 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h2); |
2179 | 0 | } |
2180 | 0 | if ((rc== 0) && contextPresent) { |
2181 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h3); |
2182 | 0 | } |
2183 | 0 | if ((rc== 0) && contextPresent) { |
2184 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h4); |
2185 | 0 | } |
2186 | 0 | if ((rc== 0) && contextPresent) { |
2187 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nl); |
2188 | 0 | } |
2189 | 0 | if ((rc== 0) && contextPresent) { |
2190 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nh); |
2191 | 0 | } |
2192 | 0 | for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { |
2193 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->data[i]); |
2194 | 0 | } |
2195 | 0 | if ((rc== 0) && contextPresent) { |
2196 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->num); |
2197 | 0 | } |
2198 | 0 | return rc; |
2199 | 0 | } |
2200 | | |
2201 | | /* |
2202 | | TPM_SYMMETRIC_KEY_DATA |
2203 | | */ |
2204 | | |
2205 | | /* TPM_SymmetricKeyData_New() allocates memory for and initializes a TPM_SYMMETRIC_KEY_DATA token. |
2206 | | */ |
2207 | | |
2208 | | TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) |
2209 | 0 | { |
2210 | 0 | TPM_RESULT rc = 0; |
2211 | |
|
2212 | 0 | printf(" TPM_SymmetricKeyData_New:\n"); |
2213 | 0 | if (rc == 0) { |
2214 | 0 | rc = TPM_Malloc(tpm_symmetric_key_data, sizeof(TPM_SYMMETRIC_KEY_DATA)); |
2215 | 0 | } |
2216 | 0 | if (rc == 0) { |
2217 | 0 | TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); |
2218 | 0 | } |
2219 | 0 | return rc; |
2220 | 0 | } |
2221 | | |
2222 | | /* TPM_SymmetricKeyData_Free() initializes the key token to wipe secrets. It then frees the |
2223 | | TPM_SYMMETRIC_KEY_DATA token and sets it to NULL. |
2224 | | */ |
2225 | | |
2226 | | void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) |
2227 | 0 | { |
2228 | 0 | printf(" TPM_SymmetricKeyData_Free:\n"); |
2229 | 0 | if (*tpm_symmetric_key_data != NULL) { |
2230 | 0 | TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); |
2231 | 0 | free(*tpm_symmetric_key_data); |
2232 | 0 | *tpm_symmetric_key_data = NULL; |
2233 | 0 | } |
2234 | 0 | return; |
2235 | 0 | } |
2236 | | |
2237 | | #ifdef TPM_DES |
2238 | | |
2239 | | /* TPM_SymmetricKeyData_Init() is DES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA |
2240 | | |
2241 | | It depends on the TPM_SYMMETRIC_KEY_DATA declaration. |
2242 | | */ |
2243 | | |
2244 | | void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2245 | | { |
2246 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2247 | | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2248 | | |
2249 | | printf(" TPM_SymmetricKeyData_Init:\n"); |
2250 | | tpm_symmetric_key_data->tag = TPM_TAG_KEY; |
2251 | | tpm_symmetric_key_data->valid = FALSE; |
2252 | | tpm_symmetric_key_data->fill = 0; |
2253 | | memset(tpm_symmetric_key_data->des_cblock1, 0, sizeof(DES_cblock)); |
2254 | | memset(tpm_symmetric_key_data->des_cblock2, 0, sizeof(DES_cblock)); |
2255 | | memset(tpm_symmetric_key_data->des_cblock3, 0, sizeof(DES_cblock)); |
2256 | | return; |
2257 | | } |
2258 | | |
2259 | | /* TPM_SymmetricKeyData_Load() is DES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA |
2260 | | |
2261 | | It depends on the TPM_SYMMETRIC_KEY_DATA declaration. |
2262 | | */ |
2263 | | |
2264 | | TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, |
2265 | | unsigned char **stream, |
2266 | | uint32_t *stream_size) |
2267 | | { |
2268 | | TPM_RESULT rc = 0; |
2269 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2270 | | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2271 | | |
2272 | | printf(" TPM_SymmetricKeyData_Load:\n"); |
2273 | | /* check tag */ |
2274 | | if (rc == 0) { |
2275 | | rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); |
2276 | | } |
2277 | | /* load valid */ |
2278 | | if (rc == 0) { |
2279 | | rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); |
2280 | | } |
2281 | | /* load fill */ |
2282 | | if (rc == 0) { |
2283 | | rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); |
2284 | | } |
2285 | | /* this assumes that DES_cblock is a consistently packed structure. It is in fact an array of 8 |
2286 | | bytes for openSSL. */ |
2287 | | if (rc == 0) { |
2288 | | rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock), |
2289 | | stream, stream_size); |
2290 | | } |
2291 | | if (rc == 0) { |
2292 | | rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock), |
2293 | | stream, stream_size); |
2294 | | } |
2295 | | if (rc == 0) { |
2296 | | rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock), |
2297 | | stream, stream_size); |
2298 | | } |
2299 | | if (rc == 0) { |
2300 | | TPM_PrintFour(" TPM_SymmetricKeyData_Load: des1", tpm_symmetric_key_data->des_cblock1); |
2301 | | TPM_PrintFour(" TPM_SymmetricKeyData_Load: des2", tpm_symmetric_key_data->des_cblock2); |
2302 | | TPM_PrintFour(" TPM_SymmetricKeyData_Load: des3", tpm_symmetric_key_data->des_cblock3); |
2303 | | } |
2304 | | return rc; |
2305 | | } |
2306 | | |
2307 | | /* TPM_SymmetricKeyData_Store() DES is non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA |
2308 | | |
2309 | | It depends on the TPM_SYMMETRIC_KEY_DATA declaration. |
2310 | | */ |
2311 | | |
2312 | | TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, |
2313 | | const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2314 | | { |
2315 | | TPM_RESULT rc = 0; |
2316 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2317 | | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2318 | | |
2319 | | printf(" TPM_SymmetricKeyData_Store:\n"); |
2320 | | if (rc == 0) { |
2321 | | TPM_PrintFour(" TPM_SymmetricKeyData_Store: des1", tpm_symmetric_key_data->des_cblock1); |
2322 | | TPM_PrintFour(" TPM_SymmetricKeyData_Store: des2", tpm_symmetric_key_data->des_cblock2); |
2323 | | TPM_PrintFour(" TPM_SymmetricKeyData_Store: des3", tpm_symmetric_key_data->des_cblock3); |
2324 | | } |
2325 | | /* store tag */ |
2326 | | if (rc == 0) { |
2327 | | rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); |
2328 | | } |
2329 | | /* store valid */s |
2330 | | if (rc == 0) { |
2331 | | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); |
2332 | | } |
2333 | | /* store fill */ |
2334 | | if (rc == 0) { |
2335 | | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); |
2336 | | } |
2337 | | /* store DES key */ |
2338 | | if (rc == 0) { |
2339 | | rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock)); |
2340 | | } |
2341 | | if (rc == 0) { |
2342 | | rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock)); |
2343 | | } |
2344 | | if (rc == 0) { |
2345 | | rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock)); |
2346 | | } |
2347 | | return rc; |
2348 | | } |
2349 | | |
2350 | | /* TPM_SymmetricKeyData_GenerateKey() is DES non-portable code to generate a symmetric key |
2351 | | |
2352 | | vsymmetric_key must be freed by the caller |
2353 | | */ |
2354 | | |
2355 | | TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2356 | | { |
2357 | | TPM_RESULT rc = 0; |
2358 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2359 | | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2360 | | |
2361 | | printf(" TPM_SymmetricKeyData_GenerateKey:\n"); |
2362 | | /* generate a random key */ |
2363 | | if (rc == 0) { |
2364 | | DES_random_key(&(tpm_symmetric_key_data->des_cblock1)); |
2365 | | DES_random_key(&(tpm_symmetric_key_data->des_cblock2)); |
2366 | | DES_random_key(&(tpm_symmetric_key_data->des_cblock3)); |
2367 | | /* sets the parity of the passed key to odd. */ |
2368 | | DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock1)); |
2369 | | DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock2)); |
2370 | | DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock3)); |
2371 | | TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des1", |
2372 | | tpm_symmetric_key_data->des_cblock1); |
2373 | | TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des2", |
2374 | | tpm_symmetric_key_data->des_cblock2); |
2375 | | TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des3", |
2376 | | tpm_symmetric_key_data->des_cblock3); |
2377 | | tpm_symmetric_key_data->valid = TRUE; |
2378 | | } |
2379 | | return rc; |
2380 | | } |
2381 | | |
2382 | | /* TPM_SymmetricKeyData_Encrypt() is DES non-portable code to encrypt 'decrypt_data' to |
2383 | | 'encrypt_data' |
2384 | | |
2385 | | The stream is padded as per PKCS#7 / RFC2630 |
2386 | | |
2387 | | 'encrypt_data' must be free by the caller |
2388 | | */ |
2389 | | |
2390 | | TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ |
2391 | | uint32_t *encrypt_length, /* output */ |
2392 | | const unsigned char *decrypt_data, /* input */ |
2393 | | uint32_t decrypt_length, /* input */ |
2394 | | const TPM_SYMMETRIC_KEY_TOKEN |
2395 | | tpm_symmetric_key_token) /* input */ |
2396 | | { |
2397 | | TPM_RESULT rc = 0; |
2398 | | uint32_t pad_length; |
2399 | | unsigned char *decrypt_data_pad; |
2400 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2401 | | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2402 | | |
2403 | | printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); |
2404 | | decrypt_data_pad = NULL; /* freed @1 */ |
2405 | | if (rc == 0) { |
2406 | | /* calculate the pad length and padded data length */ |
2407 | | pad_length = TPM_DES_BLOCK_SIZE - (decrypt_length % TPM_DES_BLOCK_SIZE); |
2408 | | *encrypt_length = decrypt_length + pad_length; |
2409 | | printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", |
2410 | | *encrypt_length, pad_length); |
2411 | | /* allocate memory for the encrypted response */ |
2412 | | rc = TPM_Malloc(encrypt_data, *encrypt_length); |
2413 | | } |
2414 | | /* allocate memory for the padded decrypted data */ |
2415 | | if (rc == 0) { |
2416 | | rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); |
2417 | | } |
2418 | | /* pad the decrypted clear text data */ |
2419 | | if (rc == 0) { |
2420 | | /* unpadded original data */ |
2421 | | memcpy(decrypt_data_pad, decrypt_data, decrypt_length); |
2422 | | /* last gets pad = pad length */ |
2423 | | memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); |
2424 | | /* encrypt the padded input to the output */ |
2425 | | rc = TPM_SymmetricKeyData_Crypt(*encrypt_data, |
2426 | | decrypt_data_pad, |
2427 | | *encrypt_length, |
2428 | | tpm_symmetric_key_data, |
2429 | | DES_ENCRYPT, |
2430 | | TPM_ENCRYPT_ERROR); |
2431 | | } |
2432 | | free(decrypt_data_pad); /* @1 */ |
2433 | | return rc; |
2434 | | } |
2435 | | |
2436 | | /* TPM_SymmetricKeyData_Decrypt() is DES non-portable code to decrypt 'encrypt_data' to |
2437 | | 'decrypt_data' |
2438 | | |
2439 | | The stream must be padded as per PKCS#7 / RFC2630 |
2440 | | |
2441 | | decrypt_data must be free by the caller |
2442 | | */ |
2443 | | |
2444 | | TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ |
2445 | | uint32_t *decrypt_length, /* output */ |
2446 | | const unsigned char *encrypt_data, /* input */ |
2447 | | uint32_t encrypt_length, /* input */ |
2448 | | const TPM_SYMMETRIC_KEY_TOKEN |
2449 | | tpm_symmetric_key_data) /* input */ |
2450 | | { |
2451 | | TPM_RESULT rc = 0; |
2452 | | uint32_t pad_length; |
2453 | | uint32_t i; |
2454 | | unsigned char *pad_data; |
2455 | | |
2456 | | printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); |
2457 | | /* sanity check encrypted length */ |
2458 | | if (rc == 0) { |
2459 | | if (encrypt_length < TPM_DES_BLOCK_SIZE) { |
2460 | | printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); |
2461 | | rc = TPM_DECRYPT_ERROR; |
2462 | | } |
2463 | | } |
2464 | | /* allocate memory for the padded decrypted data */ |
2465 | | if (rc == 0) { |
2466 | | rc = TPM_Malloc(decrypt_data, encrypt_length); |
2467 | | } |
2468 | | /* decrypt the input to the padded output */ |
2469 | | if (rc == 0) { |
2470 | | rc = TPM_SymmetricKeyData_Crypt(*decrypt_data, |
2471 | | encrypt_data, |
2472 | | encrypt_length, |
2473 | | tpm_symmetric_key_data, |
2474 | | DES_DECRYPT, |
2475 | | TPM_DECRYPT_ERROR); |
2476 | | } |
2477 | | /* get the pad length */ |
2478 | | if (rc == 0) { |
2479 | | /* get the pad length from the last byte */ |
2480 | | pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); |
2481 | | /* sanity check the pad length */ |
2482 | | printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); |
2483 | | if ((pad_length == 0) || |
2484 | | (pad_length > TPM_DES_BLOCK_SIZE)) { |
2485 | | printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); |
2486 | | rc = TPM_DECRYPT_ERROR; |
2487 | | } |
2488 | | } |
2489 | | if (rc == 0) { |
2490 | | /* get the unpadded length */ |
2491 | | *decrypt_length = encrypt_length - pad_length; |
2492 | | /* pad starting point */ |
2493 | | pad_data = *decrypt_data + *decrypt_length; |
2494 | | /* sanity check the pad */ |
2495 | | for (i = 0 ; i < pad_length ; i++, pad_data++) { |
2496 | | if (*pad_data != pad_length) { |
2497 | | printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", |
2498 | | *pad_data, i); |
2499 | | rc = TPM_DECRYPT_ERROR; |
2500 | | } |
2501 | | } |
2502 | | } |
2503 | | return rc; |
2504 | | } |
2505 | | |
2506 | | /* TPM_SymmetricKeyData_Crypt() is DES common code for openSSL, since encrypt and decrypt use the |
2507 | | same function with an 'enc' flag. |
2508 | | |
2509 | | 'data_in' and 'data_out' must be preallocated arrays of 'length' bytes. 'length' must be a |
2510 | | multiple of TPM_DES_BLOCK_SIZE. |
2511 | | |
2512 | | Returns 'error' on error. |
2513 | | */ |
2514 | | |
2515 | | /* openSSL prototype |
2516 | | |
2517 | | void DES_ede3_cbc_encrypt(const unsigned char *input, |
2518 | | unsigned char *output, long length, DES_key_schedule *ks1, |
2519 | | DES_key_schedule *ks2, DES_key_schedule *ks3, DES_cblock *ivec, |
2520 | | int enc); |
2521 | | */ |
2522 | | |
2523 | | static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, /* output */ |
2524 | | const unsigned char *data_in, /* input */ |
2525 | | uint32_t length, /* input */ |
2526 | | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, /*in*/ |
2527 | | int enc, /* input */ |
2528 | | TPM_RESULT error) /* input */ |
2529 | | { |
2530 | | TPM_RESULT rc = 0; |
2531 | | int irc; |
2532 | | DES_key_schedule des_key_schedule1; |
2533 | | DES_key_schedule des_key_schedule2; |
2534 | | DES_key_schedule des_key_schedule3; |
2535 | | DES_cblock ivec; /* initial chaining vector */ |
2536 | | |
2537 | | if (rc == 0) { |
2538 | | if ((length % TPM_DES_BLOCK_SIZE) != 0) { |
2539 | | printf("TPM_SymmetricKeyData_Crypt: Error, illegal length %u\n", length); |
2540 | | rc = error; /* should never occur */ |
2541 | | } |
2542 | | } |
2543 | | if (rc == 0) { |
2544 | | TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des1", tpm_symmetric_key_data->des_cblock1); |
2545 | | TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des2", tpm_symmetric_key_data->des_cblock2); |
2546 | | TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des3", tpm_symmetric_key_data->des_cblock3); |
2547 | | } |
2548 | | /* Before a DES key can be used, it must be converted into the architecture dependent |
2549 | | DES_key_schedule via the DES_set_key_checked() or DES_set_key_unchecked() function. */ |
2550 | | if (rc == 0) { |
2551 | | irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock1), &des_key_schedule1); |
2552 | | if (irc != 0) { |
2553 | | printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); |
2554 | | rc = error; |
2555 | | } |
2556 | | } |
2557 | | if (rc == 0) { |
2558 | | irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock2), &des_key_schedule2); |
2559 | | if (irc != 0) { |
2560 | | printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); |
2561 | | rc = error; |
2562 | | } |
2563 | | } |
2564 | | if (rc == 0) { |
2565 | | irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock3), &des_key_schedule3); |
2566 | | if (irc != 0) { |
2567 | | printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); |
2568 | | rc = error; |
2569 | | } |
2570 | | } |
2571 | | /* initialize initial chaining vector */ |
2572 | | if (rc == 0) { |
2573 | | TPM_PrintFourLimit(" TPM_SymmetricKeyData_Crypt: Input", data_in, length); |
2574 | | /* encrypt operation */ |
2575 | | memset(&ivec, 0, sizeof(DES_cblock)); |
2576 | | DES_ede3_cbc_encrypt(data_in, |
2577 | | data_out, |
2578 | | length, |
2579 | | &des_key_schedule1, |
2580 | | &des_key_schedule2, |
2581 | | &des_key_schedule3, |
2582 | | &ivec, |
2583 | | enc); |
2584 | | TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: Output", data_out); |
2585 | | } |
2586 | | return rc; |
2587 | | } |
2588 | | |
2589 | | #endif |
2590 | | |
2591 | | #ifdef TPM_AES |
2592 | | |
2593 | | /* TPM_SymmetricKeyData_Init() is AES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA |
2594 | | |
2595 | | It depends on the TPM_SYMMETRIC_KEY_DATA declaration. |
2596 | | */ |
2597 | | |
2598 | | void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2599 | 0 | { |
2600 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2601 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2602 | |
|
2603 | 0 | printf(" TPM_SymmetricKeyData_Init:\n"); |
2604 | 0 | tpm_symmetric_key_data->tag = TPM_TAG_KEY; |
2605 | 0 | tpm_symmetric_key_data->valid = FALSE; |
2606 | 0 | tpm_symmetric_key_data->fill = 0; |
2607 | 0 | memset(tpm_symmetric_key_data->userKey, 0, sizeof(tpm_symmetric_key_data->userKey)); |
2608 | 0 | memset(&(tpm_symmetric_key_data->aes_enc_key), 0, sizeof(tpm_symmetric_key_data->aes_enc_key)); |
2609 | 0 | memset(&(tpm_symmetric_key_data->aes_dec_key), 0, sizeof(tpm_symmetric_key_data->aes_dec_key)); |
2610 | 0 | return; |
2611 | 0 | } |
2612 | | |
2613 | | /* TPM_SymmetricKeyData_Load() is AES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA |
2614 | | |
2615 | | It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. |
2616 | | */ |
2617 | | |
2618 | | TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, |
2619 | | unsigned char **stream, |
2620 | | uint32_t *stream_size) |
2621 | 0 | { |
2622 | 0 | TPM_RESULT rc = 0; |
2623 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2624 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2625 | | |
2626 | 0 | printf(" TPM_SymmetricKeyData_Load:\n"); |
2627 | | /* check tag */ |
2628 | 0 | if (rc == 0) { |
2629 | 0 | rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); |
2630 | 0 | } |
2631 | | /* load valid */ |
2632 | 0 | if (rc == 0) { |
2633 | 0 | rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); |
2634 | 0 | } |
2635 | | /* load fill */ |
2636 | 0 | if (rc == 0) { |
2637 | 0 | rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); |
2638 | 0 | } |
2639 | | /* The AES key is a simple array. */ |
2640 | 0 | if (rc == 0) { |
2641 | 0 | rc = TPM_Loadn(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey), |
2642 | 0 | stream, stream_size); |
2643 | 0 | } |
2644 | | /* reconstruct the internal AES keys */ |
2645 | 0 | if (rc == 0) { |
2646 | 0 | rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); |
2647 | 0 | } |
2648 | 0 | return rc; |
2649 | 0 | } |
2650 | | |
2651 | | /* TPM_SymmetricKeyData_Store() is AES non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA |
2652 | | |
2653 | | It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. |
2654 | | */ |
2655 | | |
2656 | | TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, |
2657 | | const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2658 | 0 | { |
2659 | 0 | TPM_RESULT rc = 0; |
2660 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2661 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2662 | | |
2663 | 0 | printf(" TPM_SymmetricKeyData_Store:\n"); |
2664 | | /* store tag */ |
2665 | 0 | if (rc == 0) { |
2666 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); |
2667 | 0 | } |
2668 | | /* store valid */ |
2669 | 0 | if (rc == 0) { |
2670 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); |
2671 | 0 | } |
2672 | | /* store fill */ |
2673 | 0 | if (rc == 0) { |
2674 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); |
2675 | 0 | } |
2676 | | /* store AES key */ |
2677 | 0 | if (rc == 0) { |
2678 | 0 | rc = TPM_Sbuffer_Append(sbuffer, |
2679 | 0 | tpm_symmetric_key_data->userKey, |
2680 | 0 | sizeof(tpm_symmetric_key_data->userKey)); |
2681 | 0 | } |
2682 | | /* No need to store the internal AES keys. They are reconstructed on load */ |
2683 | 0 | return rc; |
2684 | 0 | } |
2685 | | |
2686 | | /* TPM_SymmetricKeyData_GenerateKey() is AES non-portable code to generate a random symmetric key |
2687 | | |
2688 | | tpm_symmetric_key_data should be initialized before and after use |
2689 | | */ |
2690 | | |
2691 | | TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) |
2692 | 0 | { |
2693 | 0 | TPM_RESULT rc = 0; |
2694 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2695 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2696 | | |
2697 | 0 | printf(" TPM_SymmetricKeyData_GenerateKey:\n"); |
2698 | | /* generate a random key */ |
2699 | 0 | if (rc == 0) { |
2700 | 0 | rc = TPM_Random(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); |
2701 | 0 | } |
2702 | | /* construct the internal AES keys */ |
2703 | 0 | if (rc == 0) { |
2704 | 0 | rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); |
2705 | 0 | } |
2706 | 0 | if (rc == 0) { |
2707 | 0 | tpm_symmetric_key_data->valid = TRUE; |
2708 | 0 | } |
2709 | 0 | return rc; |
2710 | 0 | } |
2711 | | |
2712 | | /* TPM_SymmetricKeyData_SetKey() is AES non-portable code to set a symmetric key from input data |
2713 | | |
2714 | | tpm_symmetric_key_data should be initialized before and after use |
2715 | | */ |
2716 | | |
2717 | | TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, |
2718 | | const unsigned char *key_data, |
2719 | | uint32_t key_data_size) |
2720 | 0 | { |
2721 | 0 | TPM_RESULT rc = 0; |
2722 | | |
2723 | 0 | printf(" TPM_SymmetricKeyData_SetKey:\n"); |
2724 | | /* check the input data size, it can be truncated, but cannot be smaller than the AES key */ |
2725 | 0 | if (rc == 0) { |
2726 | 0 | if (sizeof(tpm_symmetric_key_data->userKey) > key_data_size) { |
2727 | 0 | printf("TPM_SymmetricKeyData_SetKey: Error (fatal), need %lu bytes, received %u\n", |
2728 | 0 | (unsigned long)sizeof(tpm_symmetric_key_data->userKey), key_data_size); |
2729 | 0 | rc = TPM_FAIL; /* should never occur */ |
2730 | 0 | } |
2731 | 0 | } |
2732 | 0 | if (rc == 0) { |
2733 | | /* copy the input data into the AES key structure */ |
2734 | 0 | memcpy(tpm_symmetric_key_data->userKey, key_data, sizeof(tpm_symmetric_key_data->userKey)); |
2735 | | /* construct the internal AES keys */ |
2736 | 0 | rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); |
2737 | 0 | } |
2738 | 0 | if (rc == 0) { |
2739 | 0 | tpm_symmetric_key_data->valid = TRUE; |
2740 | 0 | } |
2741 | 0 | return rc; |
2742 | 0 | } |
2743 | | |
2744 | | /* TPM_SymmetricKeyData_SetKeys() is AES non-portable code to construct the internal AES keys from |
2745 | | the userKey |
2746 | | |
2747 | | tpm_symmetric_key_data should be initialized before and after use |
2748 | | */ |
2749 | | |
2750 | | static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data) |
2751 | 0 | { |
2752 | 0 | TPM_RESULT rc = 0; |
2753 | 0 | int irc; |
2754 | |
|
2755 | 0 | printf(" TPM_SymmetricKeyData_SetKeys:\n"); |
2756 | 0 | if (rc == 0) { |
2757 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_SetKeys: userKey", tpm_symmetric_key_data->userKey); |
2758 | 0 | irc = AES_set_encrypt_key(tpm_symmetric_key_data->userKey, |
2759 | 0 | TPM_AES_BITS, |
2760 | 0 | &(tpm_symmetric_key_data->aes_enc_key)); |
2761 | 0 | if (irc != 0) { |
2762 | 0 | printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating enc key\n"); |
2763 | 0 | TPM_OpenSSL_PrintError(); |
2764 | 0 | rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ |
2765 | 0 | } |
2766 | 0 | } |
2767 | 0 | if (rc == 0) { |
2768 | 0 | irc = AES_set_decrypt_key(tpm_symmetric_key_data->userKey, |
2769 | 0 | TPM_AES_BITS, |
2770 | 0 | &(tpm_symmetric_key_data->aes_dec_key)); |
2771 | 0 | if (irc != 0) { |
2772 | 0 | printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating dec key\n"); |
2773 | 0 | TPM_OpenSSL_PrintError(); |
2774 | 0 | rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ |
2775 | 0 | } |
2776 | 0 | } |
2777 | 0 | return rc; |
2778 | 0 | } |
2779 | | |
2780 | | /* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to |
2781 | | 'encrypt_data' |
2782 | | |
2783 | | The stream is padded as per PKCS#7 / RFC2630 |
2784 | | |
2785 | | 'encrypt_data' must be free by the caller |
2786 | | */ |
2787 | | |
2788 | | TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ |
2789 | | uint32_t *encrypt_length, /* output */ |
2790 | | const unsigned char *decrypt_data, /* input */ |
2791 | | uint32_t decrypt_length, /* input */ |
2792 | | const TPM_SYMMETRIC_KEY_TOKEN |
2793 | | tpm_symmetric_key_token) /* input */ |
2794 | 0 | { |
2795 | 0 | TPM_RESULT rc = 0; |
2796 | 0 | uint32_t pad_length; |
2797 | 0 | unsigned char *decrypt_data_pad; |
2798 | 0 | unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ |
2799 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2800 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2801 | |
|
2802 | 0 | printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); |
2803 | 0 | decrypt_data_pad = NULL; /* freed @1 */ |
2804 | 0 | if (rc == 0) { |
2805 | | /* calculate the pad length and padded data length */ |
2806 | 0 | pad_length = TPM_AES_BLOCK_SIZE - (decrypt_length % TPM_AES_BLOCK_SIZE); |
2807 | 0 | *encrypt_length = decrypt_length + pad_length; |
2808 | 0 | printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", |
2809 | 0 | *encrypt_length, pad_length); |
2810 | | /* allocate memory for the encrypted response */ |
2811 | 0 | rc = TPM_Malloc(encrypt_data, *encrypt_length); |
2812 | 0 | } |
2813 | | /* allocate memory for the padded decrypted data */ |
2814 | 0 | if (rc == 0) { |
2815 | 0 | rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); |
2816 | 0 | } |
2817 | | /* pad the decrypted clear text data */ |
2818 | 0 | if (rc == 0) { |
2819 | | /* unpadded original data */ |
2820 | 0 | memcpy(decrypt_data_pad, decrypt_data, decrypt_length); |
2821 | | /* last gets pad = pad length */ |
2822 | 0 | memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); |
2823 | | /* set the IV */ |
2824 | 0 | memset(ivec, 0, sizeof(ivec)); |
2825 | | /* encrypt the padded input to the output */ |
2826 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); |
2827 | 0 | AES_cbc_encrypt(decrypt_data_pad, |
2828 | 0 | *encrypt_data, |
2829 | 0 | *encrypt_length, |
2830 | 0 | &(tpm_symmetric_key_data->aes_enc_key), |
2831 | 0 | ivec, |
2832 | 0 | AES_ENCRYPT); |
2833 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); |
2834 | 0 | } |
2835 | 0 | free(decrypt_data_pad); /* @1 */ |
2836 | 0 | return rc; |
2837 | 0 | } |
2838 | | |
2839 | | /* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to |
2840 | | 'decrypt_data' |
2841 | | |
2842 | | The stream must be padded as per PKCS#7 / RFC2630 |
2843 | | |
2844 | | decrypt_data must be free by the caller |
2845 | | */ |
2846 | | |
2847 | | TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ |
2848 | | uint32_t *decrypt_length, /* output */ |
2849 | | const unsigned char *encrypt_data, /* input */ |
2850 | | uint32_t encrypt_length, /* input */ |
2851 | | const TPM_SYMMETRIC_KEY_TOKEN |
2852 | | tpm_symmetric_key_token) /* input */ |
2853 | 0 | { |
2854 | 0 | TPM_RESULT rc = 0; |
2855 | 0 | uint32_t pad_length; |
2856 | 0 | uint32_t i; |
2857 | 0 | unsigned char *pad_data; |
2858 | 0 | unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ |
2859 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = |
2860 | 0 | (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; |
2861 | | |
2862 | 0 | printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); |
2863 | | /* sanity check encrypted length */ |
2864 | 0 | if (rc == 0) { |
2865 | 0 | if (encrypt_length < TPM_AES_BLOCK_SIZE) { |
2866 | 0 | printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); |
2867 | 0 | rc = TPM_DECRYPT_ERROR; |
2868 | 0 | } |
2869 | 0 | } |
2870 | | /* allocate memory for the padded decrypted data */ |
2871 | 0 | if (rc == 0) { |
2872 | 0 | rc = TPM_Malloc(decrypt_data, encrypt_length); |
2873 | 0 | } |
2874 | | /* decrypt the input to the padded output */ |
2875 | 0 | if (rc == 0) { |
2876 | | /* set the IV */ |
2877 | 0 | memset(ivec, 0, sizeof(ivec)); |
2878 | | /* decrypt the padded input to the output */ |
2879 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); |
2880 | 0 | AES_cbc_encrypt(encrypt_data, |
2881 | 0 | *decrypt_data, |
2882 | 0 | encrypt_length, |
2883 | 0 | &(tpm_symmetric_key_data->aes_dec_key), |
2884 | 0 | ivec, |
2885 | 0 | AES_DECRYPT); |
2886 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); |
2887 | 0 | } |
2888 | | /* get the pad length */ |
2889 | 0 | if (rc == 0) { |
2890 | | /* get the pad length from the last byte */ |
2891 | 0 | pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); |
2892 | | /* sanity check the pad length */ |
2893 | 0 | printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); |
2894 | 0 | if ((pad_length == 0) || |
2895 | 0 | (pad_length > TPM_AES_BLOCK_SIZE)) { |
2896 | 0 | printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); |
2897 | 0 | rc = TPM_DECRYPT_ERROR; |
2898 | 0 | } |
2899 | 0 | } |
2900 | 0 | if (rc == 0) { |
2901 | | /* get the unpadded length */ |
2902 | 0 | *decrypt_length = encrypt_length - pad_length; |
2903 | | /* pad starting point */ |
2904 | 0 | pad_data = *decrypt_data + *decrypt_length; |
2905 | | /* sanity check the pad */ |
2906 | 0 | for (i = 0 ; i < pad_length ; i++, pad_data++) { |
2907 | 0 | if (*pad_data != pad_length) { |
2908 | 0 | printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", |
2909 | 0 | *pad_data, i); |
2910 | 0 | rc = TPM_DECRYPT_ERROR; |
2911 | 0 | } |
2912 | 0 | } |
2913 | 0 | } |
2914 | 0 | return rc; |
2915 | 0 | } |
2916 | | |
2917 | | /* TPM_SymmetricKeyData_CtrCrypt() does an encrypt or decrypt (they are the same XOR operation with |
2918 | | a CTR mode pad) of 'data_in' to 'data_out'. |
2919 | | |
2920 | | NOTE: This function looks general, but is currently hard coded to AES128. |
2921 | | |
2922 | | 'symmetric key' is the raw key, not converted to a non-portable form |
2923 | | 'ctr_in' is the initial CTR value before possible truncation |
2924 | | */ |
2925 | | |
2926 | | TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, /* output */ |
2927 | | const unsigned char *data_in, /* input */ |
2928 | | uint32_t data_size, /* input */ |
2929 | | const unsigned char *symmetric_key, /* input */ |
2930 | | uint32_t symmetric_key_size, /* input */ |
2931 | | const unsigned char *ctr_in, /* input */ |
2932 | | uint32_t ctr_in_size) /* input */ |
2933 | 0 | { |
2934 | 0 | TPM_RESULT rc = 0; |
2935 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ |
2936 | 0 | unsigned char ctr[TPM_AES_BLOCK_SIZE]; |
2937 | |
|
2938 | 0 | printf(" TPM_SymmetricKeyData_CtrCrypt: data_size %u\n", data_size); |
2939 | | /* allocate memory for the key token. The token is opaque in the API, but at this low level, |
2940 | | the code understands the TPM_SYMMETRIC_KEY_DATA structure */ |
2941 | 0 | if (rc == 0) { |
2942 | 0 | rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); |
2943 | 0 | } |
2944 | | /* convert the raw key to the AES key, truncating as required */ |
2945 | 0 | if (rc == 0) { |
2946 | 0 | rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, |
2947 | 0 | symmetric_key, |
2948 | 0 | symmetric_key_size); |
2949 | 0 | } |
2950 | | /* check the input CTR size, it can be truncated, but cannot be smaller than the AES key */ |
2951 | 0 | if (rc == 0) { |
2952 | 0 | if (ctr_in_size < sizeof(ctr)) { |
2953 | 0 | printf(" TPM_SymmetricKeyData_CtrCrypt: Error (fatal)" |
2954 | 0 | ", CTR size %u too small for AES key\n", ctr_in_size); |
2955 | 0 | rc = TPM_FAIL; /* should never occur */ |
2956 | 0 | } |
2957 | 0 | } |
2958 | 0 | if (rc == 0) { |
2959 | | /* make a truncated copy of CTR, since AES_ctr128_encrypt alters the value */ |
2960 | 0 | memcpy(ctr, ctr_in, sizeof(ctr)); |
2961 | 0 | printf(" TPM_SymmetricKeyData_CtrCrypt: Calling AES in CTR mode\n"); |
2962 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_CtrCrypt: CTR", ctr); |
2963 | 0 | rc = TPM_AES_ctr128_encrypt(data_out, |
2964 | 0 | data_in, |
2965 | 0 | data_size, |
2966 | 0 | &(tpm_symmetric_key_data->aes_enc_key), |
2967 | 0 | ctr); |
2968 | 0 | } |
2969 | 0 | TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); /* @1 */ |
2970 | 0 | return rc; |
2971 | 0 | } |
2972 | | |
2973 | | /* TPM_AES_ctr128_encrypt() is a TPM variant of the openSSL AES_ctr128_encrypt() function that |
2974 | | increments only the low 4 bytes of the counter. |
2975 | | |
2976 | | openSSL increments the entire CTR array. The TPM does not follow that convention. |
2977 | | */ |
2978 | | |
2979 | | static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, |
2980 | | const unsigned char *data_in, |
2981 | | uint32_t data_size, |
2982 | | const AES_KEY *aes_enc_key, |
2983 | | unsigned char ctr[TPM_AES_BLOCK_SIZE]) |
2984 | 0 | { |
2985 | 0 | TPM_RESULT rc = 0; |
2986 | 0 | uint32_t cint; |
2987 | 0 | unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ |
2988 | |
|
2989 | 0 | printf(" TPM_AES_Ctr128_encrypt:\n"); |
2990 | 0 | while (data_size != 0) { |
2991 | 0 | printf(" TPM_AES_Ctr128_encrypt: data_size %lu\n", (unsigned long)data_size); |
2992 | | /* get an XOR pad array by encrypting the CTR with the AES key */ |
2993 | 0 | AES_encrypt(ctr, pad_buffer, aes_enc_key); |
2994 | | /* partial or full last data block */ |
2995 | 0 | if (data_size <= TPM_AES_BLOCK_SIZE) { |
2996 | 0 | TPM_XOR(data_out, data_in, pad_buffer, data_size); |
2997 | 0 | data_size = 0; |
2998 | 0 | } |
2999 | | /* full block, not the last block */ |
3000 | 0 | else { |
3001 | 0 | TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); |
3002 | 0 | data_in += TPM_AES_BLOCK_SIZE; |
3003 | 0 | data_out += TPM_AES_BLOCK_SIZE; |
3004 | 0 | data_size -= TPM_AES_BLOCK_SIZE; |
3005 | 0 | } |
3006 | | /* if not the last block, increment CTR, only the low 4 bytes */ |
3007 | 0 | if (data_size != 0) { |
3008 | | /* CTR is a big endian array, so the low 4 bytes are 12-15 */ |
3009 | 0 | cint = LOAD32(ctr, 12); /* byte array to uint32_t */ |
3010 | 0 | cint++; /* increment */ |
3011 | 0 | STORE32(ctr, 12, cint); /* uint32_t to byte array */ |
3012 | 0 | } |
3013 | 0 | } |
3014 | 0 | return rc; |
3015 | 0 | } |
3016 | | |
3017 | | /* TPM_SymmetricKeyData_OfbCrypt() does an encrypt or decrypt (they are the same XOR operation with |
3018 | | a OFB mode pad) of 'data_in' to 'data_out' |
3019 | | |
3020 | | NOTE: This function looks general, but is currently hard coded to AES128. |
3021 | | |
3022 | | 'symmetric key' is the raw key, not converted to a non-portable form |
3023 | | 'ivec_in' is the initial IV value before possible truncation |
3024 | | */ |
3025 | | |
3026 | | /* openSSL prototype |
3027 | | |
3028 | | void AES_ofb128_encrypt(const unsigned char *in, |
3029 | | unsigned char *out, |
3030 | | const unsigned long length, |
3031 | | const AES_KEY *key, |
3032 | | unsigned char *ivec, |
3033 | | int *num); |
3034 | | */ |
3035 | | |
3036 | | TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, /* output */ |
3037 | | const unsigned char *data_in, /* input */ |
3038 | | uint32_t data_size, /* input */ |
3039 | | const unsigned char *symmetric_key, /* in */ |
3040 | | uint32_t symmetric_key_size, /* in */ |
3041 | | unsigned char *ivec_in, /* input */ |
3042 | | uint32_t ivec_in_size) /* input */ |
3043 | 0 | { |
3044 | 0 | TPM_RESULT rc = 0; |
3045 | 0 | TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ |
3046 | 0 | unsigned char ivec[TPM_AES_BLOCK_SIZE]; |
3047 | 0 | int num; |
3048 | |
|
3049 | 0 | printf(" TPM_SymmetricKeyData_OfbCrypt: data_size %u\n", data_size); |
3050 | | /* allocate memory for the key token. The token is opaque in the API, but at this low level, |
3051 | | the code understands the TPM_SYMMETRIC_KEY_DATA structure */ |
3052 | 0 | if (rc == 0) { |
3053 | 0 | rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); |
3054 | 0 | } |
3055 | | /* convert the raw key to the AES key, truncating as required */ |
3056 | 0 | if (rc == 0) { |
3057 | 0 | rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, |
3058 | 0 | symmetric_key, |
3059 | 0 | symmetric_key_size); |
3060 | 0 | } |
3061 | | /* check the input OFB size, it can be truncated, but cannot be smaller than the AES key */ |
3062 | 0 | if (rc == 0) { |
3063 | 0 | if (ivec_in_size < sizeof(ivec)) { |
3064 | 0 | printf(" TPM_SymmetricKeyData_OfbCrypt: Error (fatal)," |
3065 | 0 | "IV size %u too small for AES key\n", ivec_in_size); |
3066 | 0 | rc = TPM_FAIL; /* should never occur */ |
3067 | 0 | } |
3068 | 0 | } |
3069 | 0 | if (rc == 0) { |
3070 | | /* make a truncated copy of IV, since AES_ofb128_encrypt alters the value */ |
3071 | 0 | memcpy(ivec, ivec_in, sizeof(ivec)); |
3072 | 0 | num = 0; |
3073 | 0 | printf(" TPM_SymmetricKeyData_OfbCrypt: Calling AES in OFB mode\n"); |
3074 | 0 | TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec); |
3075 | 0 | AES_ofb128_encrypt(data_in, |
3076 | 0 | data_out, |
3077 | 0 | data_size, |
3078 | 0 | &(tpm_symmetric_key_data->aes_enc_key), |
3079 | 0 | ivec, |
3080 | 0 | &num); |
3081 | 0 | } |
3082 | 0 | TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); |
3083 | 0 | return rc; |
3084 | 0 | } |
3085 | | |
3086 | | #endif /* TPM_AES */ |