Coverage Report

Created: 2026-06-10 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */