Coverage Report

Created: 2026-02-26 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtpms/src/tpm12/tpm_cryptoh.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*    High Level Platform Independent Cryptography      */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*        $Id: tpm_cryptoh.c 4540 2011-04-07 18:51:34Z 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
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <stdarg.h>
44
45
#include "tpm_admin.h"
46
#include "tpm_auth.h"
47
#include "tpm_crypto.h"
48
#include "tpm_debug.h"
49
#include "tpm_digest.h"
50
#include "tpm_error.h"
51
#include "tpm_io.h"
52
#include "tpm_memory.h"
53
#include "tpm_migration.h"
54
#include "tpm_nonce.h"
55
#include "tpm_key.h"
56
#include "tpm_pcr.h"
57
#include "tpm_process.h"
58
#include "tpm_store.h"
59
#include "tpm_ver.h"
60
61
#include "tpm_cryptoh.h"
62
63
/* local prototypes */
64
65
static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, 
66
          uint32_t length0, unsigned char *buffer0,
67
          va_list ap);
68
static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC hmac,
69
            const TPM_SECRET key,
70
            va_list ap);
71
72
static TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue,
73
           void **sha1_context,
74
           TPM_SIZED_BUFFER *hashData);
75
76
/*
77
  TPM_SIGN_INFO
78
*/
79
80
/* TPM_SignInfo_Init()
81
82
   sets members to default values
83
   sets all pointers to NULL and sizes to 0
84
   always succeeds - no return code
85
*/
86
87
void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info)
88
0
{
89
0
    printf(" TPM_SignInfo_Init:\n");
90
0
    memset(tpm_sign_info->fixed, 0, TPM_SIGN_INFO_FIXED_SIZE); 
91
0
    TPM_Nonce_Init(tpm_sign_info->replay);
92
0
    TPM_SizedBuffer_Init(&(tpm_sign_info->data));
93
0
    return;
94
0
}
95
96
/* TPM_SignInfo_Store()
97
   
98
   serialize the structure to a stream contained in 'sbuffer'
99
   returns 0 or error codes
100
*/
101
102
TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer,
103
            const TPM_SIGN_INFO *tpm_sign_info)
104
0
{
105
0
    TPM_RESULT    rc = 0;
106
107
0
    printf(" TPM_SignInfo_Store:\n");
108
    /* store the tag */
109
0
    if (rc == 0) {
110
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SIGNINFO);
111
0
    }
112
    /* store the fixed */
113
0
    if (rc == 0) {
114
0
  rc = TPM_Sbuffer_Append(sbuffer, tpm_sign_info->fixed, TPM_SIGN_INFO_FIXED_SIZE);
115
0
    }
116
    /* store the replay */
117
0
    if (rc == 0) {
118
0
  rc = TPM_Nonce_Store(sbuffer, tpm_sign_info->replay);
119
0
    }
120
    /* store the dataLen and data */
121
0
    if (rc == 0) {
122
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sign_info->data));
123
0
    }
124
0
    if (rc == 0) {
125
0
  const unsigned char *buffer;
126
0
  uint32_t length;
127
0
  TPM_Sbuffer_Get(sbuffer, &buffer, &length);
128
0
  TPM_PrintAll("  TPM_SignInfo_Store: Buffer", buffer, length);
129
0
    }
130
0
    return rc;
131
0
}
132
133
/* TPM_SignInfo_Delete()
134
135
   No-OP if the parameter is NULL, else:
136
   frees memory allocated for the sign_info
137
   sets pointers to NULL
138
   calls TPM_SignInfo_Init to set members back to default values
139
   The sign_info itself is not freed
140
*/   
141
142
void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info)
143
0
{
144
0
    printf(" TPM_SignInfo_Delete:\n");
145
0
    if (tpm_sign_info != NULL) {
146
0
  TPM_SizedBuffer_Delete(&(tpm_sign_info->data));
147
0
  TPM_SignInfo_Init(tpm_sign_info);
148
0
    }
149
0
    return;
150
0
}
151
152
/*
153
  TPM_CERTIFY_INFO
154
*/
155
156
/* TPM_CertifyInfo_Init()
157
158
   sets members to default values
159
   sets all pointers to NULL and sizes to 0
160
   always succeeds - no return code
161
*/
162
163
void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info)
164
0
{
165
0
    printf(" TPM_CertifyInfo_Init:\n");
166
0
    TPM_StructVer_Init(&(tpm_certify_info->version));
167
0
    tpm_certify_info->keyUsage = TPM_KEY_UNINITIALIZED;
168
0
    tpm_certify_info->keyFlags = 0;
169
0
    tpm_certify_info->authDataUsage = TPM_AUTH_ALWAYS;
170
0
    TPM_KeyParms_Init(&(tpm_certify_info->algorithmParms));
171
0
    TPM_Digest_Init(tpm_certify_info->pubkeyDigest);
172
0
    TPM_Nonce_Init(tpm_certify_info->data);
173
0
    tpm_certify_info->parentPCRStatus = TRUE;
174
0
    TPM_SizedBuffer_Init(&(tpm_certify_info->pcrInfo));
175
0
    tpm_certify_info->tpm_pcr_info = NULL;
176
0
    return;
177
0
}
178
179
#if 0
180
/* TPM_CertifyInfo_Load()
181
182
   deserialize the structure from a 'stream'
183
   'stream_size' is checked for sufficient data
184
   returns 0 or error codes
185
   
186
   Before use, call TPM_CertifyInfo_Init()
187
   After use, call TPM_CertifyInfo_Delete() to free memory
188
189
   NOTE: Never called.
190
*/
191
192
TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info,
193
        unsigned char **stream,
194
        uint32_t *stream_size)
195
{
196
    TPM_RESULT    rc = 0;
197
198
    printf(" TPM_CertifyInfo_Load:\n");
199
    /* load version */
200
    if (rc == 0) {
201
  rc = TPM_StructVer_Load(&(tpm_certify_info->version), stream, stream_size);
202
    }
203
    /* check ver immediately to ease debugging */
204
    if (rc == 0) {
205
  rc = TPM_StructVer_CheckVer(&(tpm_certify_info->version));
206
    }
207
    /* load keyUsage */
208
    if (rc == 0) {
209
  rc = TPM_Load16(&(tpm_certify_info->keyUsage), stream, stream_size);
210
    }
211
    /* load keyFlags */
212
    if (rc == 0) {
213
  rc = TPM_KeyFlags_Load(&(tpm_certify_info->keyFlags), stream, stream_size);
214
    }
215
    /* load authDataUsage */
216
    if (rc == 0) {
217
  rc = TPM_Load8(&(tpm_certify_info->authDataUsage), stream, stream_size);
218
    }
219
    /* load algorithmParms */
220
    if (rc == 0) {
221
  rc = TPM_KeyParms_Load(&(tpm_certify_info->algorithmParms), stream, stream_size);
222
    }
223
    /* load pubkeyDigest */
224
    if (rc == 0) {
225
  rc = TPM_Digest_Load(tpm_certify_info->pubkeyDigest, stream, stream_size);
226
    }
227
    /* load data */
228
    if (rc == 0) {
229
  rc = TPM_Nonce_Load(tpm_certify_info->data, stream, stream_size);
230
    }
231
    /* load parentPCRStatus */
232
    if (rc == 0) {
233
  rc = TPM_LoadBool(&(tpm_certify_info->parentPCRStatus), stream, stream_size);
234
    }
235
    /* load pcrInfo */
236
    if (rc == 0) {
237
  rc = TPM_SizedBuffer_Load(&(tpm_certify_info->pcrInfo), stream, stream_size);
238
    }
239
    /* set TPM_PCR_INFO tpm_pcr_info cache from pcrInfo */
240
    if (rc == 0) {
241
  rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_certify_info->tpm_pcr_info),
242
            &(tpm_certify_info->pcrInfo));
243
    }
244
    return rc;
245
}
246
#endif
247
248
/* TPM_CertifyInfo_Store()
249
   
250
   serialize the structure to a stream contained in 'sbuffer'
251
   returns 0 or error codes
252
*/
253
254
TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer,
255
         TPM_CERTIFY_INFO *tpm_certify_info)
256
0
{
257
0
    TPM_RESULT    rc = 0;
258
259
0
    printf(" TPM_CertifyInfo_Store:\n");
260
    /* store version */
261
0
    if (rc == 0) {
262
0
  rc = TPM_StructVer_Store(sbuffer, &(tpm_certify_info->version));
263
0
    }
264
    /* store keyUsage */
265
0
    if (rc == 0) {
266
0
  rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info->keyUsage);
267
0
    }
268
    /* store keyFlags */
269
0
    if (rc == 0) {
270
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info->keyFlags);
271
0
    }
272
    /* store authDataUsage */
273
0
    if (rc == 0) {
274
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->authDataUsage),
275
0
        sizeof(TPM_AUTH_DATA_USAGE)); 
276
0
    }
277
    /* store algorithmParms */
278
0
    if (rc == 0) {
279
0
  rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info->algorithmParms));
280
0
    }
281
    /* store pubkeyDigest */
282
0
    if (rc == 0) {
283
0
  rc = TPM_Digest_Store(sbuffer, tpm_certify_info->pubkeyDigest);
284
0
    }
285
    /* store data */
286
0
    if (rc == 0) {
287
0
  rc = TPM_Nonce_Store(sbuffer, tpm_certify_info->data);
288
0
    }
289
    /* store parentPCRStatus */
290
0
    if (rc == 0) {
291
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->parentPCRStatus),
292
0
        sizeof(TPM_BOOL));
293
0
    }
294
    /* copy cache to pcrInfo */
295
0
    if (rc == 0) {
296
0
  rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info->pcrInfo),
297
0
            tpm_certify_info->tpm_pcr_info,
298
0
            (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store);
299
0
    }
300
    /* copy pcrInfo to sbuffer */
301
0
    if (rc == 0) {
302
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info->pcrInfo));
303
0
    }
304
0
    return rc;
305
0
}
306
307
/* TPM_CertifyInfo_Delete()
308
309
   No-OP if the parameter is NULL, else:
310
   frees memory allocated for the object
311
   sets pointers to NULL
312
   calls TPM_CertifyInfo_Init to set members back to default values
313
   The object itself is not freed
314
*/   
315
316
void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info)
317
0
{
318
0
    printf(" TPM_CertifyInfo_Delete:\n");
319
0
    if (tpm_certify_info != NULL) {
320
0
  TPM_KeyParms_Delete(&(tpm_certify_info->algorithmParms));
321
  /* pcrInfo */
322
0
  TPM_SizedBuffer_Delete(&(tpm_certify_info->pcrInfo));
323
  /* pcr cache */
324
0
  TPM_PCRInfo_Delete(tpm_certify_info->tpm_pcr_info);
325
0
  free(tpm_certify_info->tpm_pcr_info);
326
0
  TPM_CertifyInfo_Init(tpm_certify_info);
327
0
    }
328
0
    return;
329
0
}
330
331
/* TPM_CertifyInfo_Set() fills in tpm_certify_info with the information from the key pointed to be
332
   tpm_key
333
*/
334
335
TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info,
336
             TPM_KEY *tpm_key)
337
0
{
338
0
    TPM_RESULT    rc = 0;
339
340
0
    printf(" TPM_CertifyInfo_Set:\n");
341
0
    if (rc == 0) {
342
0
  tpm_certify_info->keyUsage = tpm_key->keyUsage;
343
0
  tpm_certify_info->keyFlags = tpm_key->keyFlags;
344
0
  tpm_certify_info->authDataUsage = tpm_key->authDataUsage;
345
0
  rc = TPM_KeyParms_Copy(&(tpm_certify_info->algorithmParms),
346
0
             &(tpm_key->algorithmParms));
347
0
    }
348
    /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY
349
       representation of the key to be certified */
350
0
    if (rc == 0) {
351
0
  rc = TPM_SHA1(tpm_certify_info->pubkeyDigest,
352
0
          tpm_key->pubKey.size, tpm_key->pubKey.buffer,
353
0
          0, NULL);
354
0
    }
355
0
    return rc;
356
0
}
357
358
/*
359
  TPM_CERTIFY_INFO2
360
*/
361
362
/* TPM_CertifyInfo2_Init()
363
364
   sets members to default values
365
   sets all pointers to NULL and sizes to 0
366
   always succeeds - no return code
367
*/
368
369
void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2)
370
0
{
371
0
    printf(" TPM_CertifyInfo2_Init:\n");
372
0
    tpm_certify_info2->fill = 0x00;
373
0
    tpm_certify_info2->payloadType = TPM_PT_ASYM;
374
0
    tpm_certify_info2->keyUsage = TPM_KEY_UNINITIALIZED;
375
0
    tpm_certify_info2->keyFlags = 0;
376
0
    tpm_certify_info2->authDataUsage = TPM_AUTH_ALWAYS;
377
0
    TPM_KeyParms_Init(&(tpm_certify_info2->algorithmParms));
378
0
    TPM_Digest_Init(tpm_certify_info2->pubkeyDigest);
379
0
    TPM_Nonce_Init(tpm_certify_info2->data);
380
0
    tpm_certify_info2->parentPCRStatus = TRUE;
381
0
    TPM_SizedBuffer_Init(&(tpm_certify_info2->pcrInfo));
382
0
    TPM_SizedBuffer_Init(&(tpm_certify_info2->migrationAuthority));
383
0
    tpm_certify_info2->tpm_pcr_info_short = NULL;
384
0
    return;
385
0
}
386
387
#if 0
388
/* TPM_CertifyInfo2_Load()
389
390
   deserialize the structure from a 'stream'
391
   'stream_size' is checked for sufficient data
392
   returns 0 or error codes
393
   
394
   Before use, call TPM_CertifyInfo2_Init()
395
   After use, call TPM_CertifyInfo2_Delete() to free memory
396
*/
397
398
TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2,
399
         unsigned char **stream,
400
         uint32_t *stream_size)
401
{
402
    TPM_RESULT    rc = 0;
403
404
    printf(" TPM_CertifyInfo2_Load:\n");
405
    /* check tag */
406
    if (rc == 0) {
407
  rc = TPM_CheckTag(TPM_TAG_CERTIFY_INFO2, stream, stream_size);
408
    }
409
    /* load fill */
410
    if (rc == 0) {
411
  rc = TPM_Load8(&(tpm_certify_info2->fill), stream, stream_size);
412
    }
413
    /* check fill immediately to ease debugging */
414
    if (rc == 0) {
415
  if (tpm_certify_info2->fill != 0x00) {
416
      printf("TPM_CertifyInfo2_Load: Error checking fill %02x\n", tpm_certify_info2->fill);
417
      rc = TPM_INVALID_STRUCTURE;
418
  }
419
    }
420
    /* load payloadType */
421
    if (rc == 0) {
422
  rc = TPM_Load8(&(tpm_certify_info2->payloadType), stream, stream_size);
423
    }
424
    /* load keyUsage */
425
    if (rc == 0) {
426
  rc = TPM_Load16(&(tpm_certify_info2->keyUsage), stream, stream_size);
427
    }
428
    /* load keyFlags */
429
    if (rc == 0) {
430
  rc = TPM_KeyFlags_Load(&(tpm_certify_info2->keyFlags), stream, stream_size);
431
    }
432
    /* load authDataUsage */
433
    if (rc == 0) {
434
  rc = TPM_Load8(&(tpm_certify_info2->authDataUsage), stream, stream_size);
435
    }
436
    /* load algorithmParms */
437
    if (rc == 0) {
438
  rc = TPM_KeyParms_Load(&(tpm_certify_info2->algorithmParms), stream, stream_size);
439
    }
440
    /* load pubkeyDigest */
441
    if (rc == 0) {
442
  rc = TPM_Digest_Load(tpm_certify_info2->pubkeyDigest, stream, stream_size);
443
    }
444
    /* load data */
445
    if (rc == 0) {
446
  rc = TPM_Nonce_Load(tpm_certify_info2->data, stream, stream_size);
447
    }
448
    /* load parentPCRStatus */
449
    if (rc == 0) {
450
  rc = TPM_LoadBool(&(tpm_certify_info2->parentPCRStatus), stream, stream_size);
451
    }
452
    /* load pcrInfo */
453
    if (rc == 0) {
454
  rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->pcrInfo), stream, stream_size);
455
    }
456
    /* set TPM_PCR_INFO2 tpm_pcr_info cache from pcrInfo */
457
    if (rc == 0) {
458
  rc = TPM_PCRInfoShort_CreateFromBuffer(&(tpm_certify_info2->tpm_pcr_info_short),
459
                 &(tpm_certify_info2->pcrInfo));
460
    }
461
    /* load migrationAuthority */
462
    if (rc == 0) {
463
  rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->migrationAuthority), stream, stream_size);
464
    }
465
    /* check migrationAuthority immediately to ease debugging */
466
    if (rc == 0) {
467
  if ((tpm_certify_info2->migrationAuthority.buffer != NULL) &&
468
      (tpm_certify_info2->migrationAuthority.size != TPM_DIGEST_SIZE)) {
469
      printf("TPM_CertifyInfo2_Load: Error checking migrationAuthority %p, %u\n",
470
       tpm_certify_info2->migrationAuthority.buffer,
471
       tpm_certify_info2->migrationAuthority.size);
472
      rc = TPM_INVALID_STRUCTURE;
473
  }
474
    }
475
    return rc;
476
}
477
#endif
478
479
/* TPM_CertifyInfo2_Store()
480
   
481
   serialize the structure to a stream contained in 'sbuffer'
482
   returns 0 or error codes
483
*/
484
485
TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer,
486
         TPM_CERTIFY_INFO2 *tpm_certify_info2)
487
0
{
488
0
    TPM_RESULT    rc = 0;
489
490
0
    printf(" TPM_CertifyInfo2_Store:\n");
491
    /* store tag */
492
0
    if (rc == 0) {
493
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CERTIFY_INFO2);
494
0
    }
495
    /* store fill */
496
0
    if (rc == 0) {
497
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->fill), sizeof(BYTE));
498
0
    }
499
    /* store payloadType */
500
0
    if (rc == 0) {
501
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->payloadType),
502
0
        sizeof(TPM_PAYLOAD_TYPE));
503
0
    }
504
    /* store keyUsage */
505
0
    if (rc == 0) {
506
0
  rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info2->keyUsage);
507
0
    }
508
    /* store keyFlags */
509
0
    if (rc == 0) {
510
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info2->keyFlags);
511
0
    }
512
    /* store authDataUsage */
513
0
    if (rc == 0) {
514
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->authDataUsage),
515
0
        sizeof(TPM_AUTH_DATA_USAGE)); 
516
0
    }
517
    /* store algorithmParms */
518
0
    if (rc == 0) {
519
0
  rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info2->algorithmParms));
520
0
    }
521
    /* store pubkeyDigest */
522
0
    if (rc == 0) {
523
0
  rc = TPM_Digest_Store(sbuffer, tpm_certify_info2->pubkeyDigest);
524
0
    }
525
    /* store data */
526
0
    if (rc == 0) {
527
0
  rc = TPM_Nonce_Store(sbuffer, tpm_certify_info2->data);
528
0
    }
529
    /* store parentPCRStatus */
530
0
    if (rc == 0) {
531
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->parentPCRStatus),
532
0
        sizeof(TPM_BOOL));
533
0
    }
534
    /* copy cache to pcrInfo */
535
0
    if (rc == 0) {
536
0
  rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info2->pcrInfo),
537
0
            tpm_certify_info2->tpm_pcr_info_short,
538
0
            (TPM_STORE_FUNCTION_T)TPM_PCRInfoShort_Store);
539
0
    }
540
    /* copy pcrInfo to sbuffer */
541
0
    if (rc == 0) {
542
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->pcrInfo));
543
0
    }
544
    /* store migrationAuthority */
545
0
    if (rc == 0) {
546
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->migrationAuthority));
547
0
    }
548
0
    return rc;
549
0
}
550
551
/* TPM_CertifyInfo2_Delete()
552
553
   No-OP if the parameter is NULL, else:
554
   frees memory allocated for the object
555
   sets pointers to NULL
556
   calls TPM_CertifyInfo2_Init to set members back to default values
557
   The object itself is not freed
558
*/   
559
560
void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2)
561
0
{
562
0
    printf(" TPM_CertifyInfo2_Delete:\n");
563
0
    if (tpm_certify_info2 != NULL) {
564
0
  TPM_KeyParms_Delete(&(tpm_certify_info2->algorithmParms));
565
  /* pcrInfo */
566
0
  TPM_SizedBuffer_Delete(&(tpm_certify_info2->pcrInfo));
567
  /* pcr cache */
568
0
  TPM_PCRInfoShort_Delete(tpm_certify_info2->tpm_pcr_info_short);
569
0
  free(tpm_certify_info2->tpm_pcr_info_short);
570
0
  TPM_SizedBuffer_Delete(&(tpm_certify_info2->migrationAuthority));
571
0
  TPM_CertifyInfo2_Init(tpm_certify_info2);
572
0
    }
573
0
    return;
574
0
}
575
576
/* TPM_CertifyInfo2_Set() fills in tpm_certify_info2 with the information from the key pointed to by
577
   tpm_key.
578
579
*/
580
581
TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2,
582
             TPM_KEY *tpm_key)
583
0
{
584
0
    TPM_RESULT    rc = 0;
585
0
    TPM_STORE_ASYMKEY *tpm_store_asymkey;
586
587
0
    printf(" TPM_CertifyInfo_Set:\n");
588
    /* get the TPM_STORE_ASYMKEY object */
589
0
    if (rc == 0) {
590
0
  rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key);
591
0
    }
592
0
    if (rc == 0) {
593
0
  tpm_certify_info2->payloadType = tpm_store_asymkey->payload;
594
0
  tpm_certify_info2->keyUsage = tpm_key->keyUsage;
595
0
  tpm_certify_info2->keyFlags = tpm_key->keyFlags;
596
0
  tpm_certify_info2->authDataUsage = tpm_key->authDataUsage;
597
0
  rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key);
598
0
    }
599
0
    if (rc == 0) {
600
0
  rc = TPM_KeyParms_Copy(&(tpm_certify_info2->algorithmParms),
601
0
             &(tpm_key->algorithmParms));
602
0
    }
603
    /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY
604
       representation of the key to be certified */
605
0
    if (rc == 0) {
606
0
  rc = TPM_SHA1(tpm_certify_info2->pubkeyDigest,
607
0
          tpm_key->pubKey.size, tpm_key->pubKey.buffer,
608
0
          0, NULL);
609
0
    }
610
0
    return rc;
611
0
}
612
613
/*
614
  TPM_SYMMETRIC_KEY
615
*/
616
617
/* TPM_SymmetricKey_Init()
618
619
   sets members to default values
620
   sets all pointers to NULL and sizes to 0
621
   always succeeds - no return code
622
*/
623
624
void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key)
625
0
{
626
0
    printf(" TPM_SymmetricKey_Init:\n");
627
0
    tpm_symmetric_key->algId = 0;
628
0
    tpm_symmetric_key->encScheme = TPM_ES_NONE;
629
0
    tpm_symmetric_key->size = 0;
630
0
    tpm_symmetric_key->data = NULL;
631
0
    return;
632
0
}
633
634
/* TPM_SymmetricKey_Load()
635
636
   deserialize the structure from a 'stream'
637
   'stream_size' is checked for sufficient data
638
   returns 0 or error codes
639
   
640
   Before use, call TPM_SymmetricKey_Init()
641
   After use, call TPM_SymmetricKey_Delete() to free memory
642
*/
643
644
TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key,
645
         unsigned char **stream,
646
         uint32_t *stream_size)
647
0
{
648
0
    TPM_RESULT    rc = 0;
649
650
0
    printf(" TPM_SymmetricKey_Load:\n");
651
    /* load algId */
652
0
    if (rc == 0) {
653
0
  rc = TPM_Load32(&(tpm_symmetric_key->algId), stream, stream_size);
654
0
    }
655
    /* load encScheme */
656
0
    if (rc == 0) {
657
0
  rc = TPM_Load16(&(tpm_symmetric_key->encScheme), stream, stream_size);
658
0
    }
659
    /* load size */
660
0
    if (rc == 0) {
661
0
  rc = TPM_Load16(&(tpm_symmetric_key->size), stream, stream_size);
662
0
    }
663
    /* allocate memory for the data */
664
0
    if ((rc == 0) && (tpm_symmetric_key->size > 0)) {
665
0
  rc = TPM_Malloc(&(tpm_symmetric_key->data), tpm_symmetric_key->size);
666
0
    }
667
    /* load data */
668
0
    if ((rc == 0) && (tpm_symmetric_key->size > 0)) {
669
0
  rc = TPM_Loadn(tpm_symmetric_key->data, tpm_symmetric_key->size, stream, stream_size);
670
0
    }
671
0
    return rc;
672
0
}
673
674
/* TPM_SymmetricKey_Store()
675
   
676
   serialize the structure to a stream contained in 'sbuffer'
677
   returns 0 or error codes
678
*/
679
680
TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer,
681
          const TPM_SYMMETRIC_KEY *tpm_symmetric_key)
682
0
{
683
0
    TPM_RESULT    rc = 0;
684
685
0
    printf(" TPM_SymmetricKey_Store:\n");
686
    /* store algId */
687
0
    if (rc == 0) {
688
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_symmetric_key->algId);
689
0
    }
690
    /* store encScheme */
691
0
    if (rc == 0) {
692
0
  rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->encScheme);
693
0
    }
694
    /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */
695
    /* store size */
696
0
    if (rc == 0) {
697
0
  rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->size);
698
0
    }
699
    /* store data */
700
0
    if (rc == 0) {
701
0
  rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key->data, tpm_symmetric_key->size);
702
0
    }
703
0
    return rc;
704
0
}
705
706
/* TPM_SymmetricKey_Delete()
707
708
   No-OP if the parameter is NULL, else:
709
   frees memory allocated for the object
710
   sets pointers to NULL
711
   calls TPM_SymmetricKey_Init to set members back to default values
712
   The object itself is not freed
713
*/   
714
715
void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key)
716
0
{
717
0
    printf(" TPM_SymmetricKey_Delete:\n");
718
0
    if (tpm_symmetric_key != NULL) {
719
0
  free(tpm_symmetric_key->data);
720
0
  TPM_SymmetricKey_Init(tpm_symmetric_key);
721
0
    }
722
0
    return;
723
0
}
724
725
/* TPM_SymmetricKeyData_EncryptSbuffer() encrypts 'sbuffer' to 'encrypt_data'
726
727
   Padding is included, so the output may be larger than the input.
728
729
   'encrypt_data' must be free by the caller
730
*/
731
732
TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data,
733
                 TPM_STORE_BUFFER *sbuffer,
734
                 const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data)
735
0
{
736
0
    TPM_RESULT    rc = 0;
737
0
    const unsigned char *decrypt_data;    /* serialization buffer */
738
0
    uint32_t    decrypt_data_size;  /* serialization size */
739
740
0
    printf(" TPM_SymmetricKeyData_EncryptSbuffer:\n");
741
0
    if (rc == 0) {
742
  /* get the serialization results */
743
0
  TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size);
744
  /* platform dependent symmetric key encrypt */
745
0
  rc = TPM_SymmetricKeyData_Encrypt(&(encrypt_data->buffer),  /* output, caller frees */
746
0
            &(encrypt_data->size),  /* output */
747
0
            decrypt_data,     /* input */
748
0
            decrypt_data_size,    /* input */
749
0
            tpm_symmetric_key_data);
750
0
    }
751
0
    return rc;
752
0
}
753
754
/* TPM_SymmetricKeyData_StreamCrypt() encrypts or decrypts 'data_in' to 'data_out '
755
756
   It assumes that the size of data_out and data_in are equal, and that a stream cipher mode is
757
   used.  For the supported stream ciphers, encrypt and decrypt are equivalent, so no direction flag
758
   is required.
759
760
   AES 128 with CTR or OFB modes are supported.  For CTR mode, pad is the initial count.  For OFB
761
   mode, pad is the IV.
762
*/
763
764
TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out,    /* output */
765
              const unsigned char *data_in, /* input */
766
              uint32_t data_size,     /* input */
767
              TPM_ALGORITHM_ID algId,   /* algorithm */
768
              TPM_ENC_SCHEME encScheme,   /* mode */
769
              const unsigned char *symmetric_key, /* input */
770
              uint32_t symmetric_key_size,  /* input */
771
              unsigned char *pad_in,    /* input */
772
              uint32_t pad_in_size)   /* input */
773
0
{
774
0
    TPM_RESULT    rc = 0;
775
776
0
    printf(" TPM_SymmetricKeyData_StreamCrypt:\n");
777
0
    switch (algId) {
778
0
      case TPM_ALG_AES128:
779
0
  switch (encScheme) {
780
0
    case TPM_ES_SYM_CTR:
781
0
      rc = TPM_SymmetricKeyData_CtrCrypt(data_out,
782
0
                 data_in,
783
0
                 data_size,
784
0
                 symmetric_key,
785
0
                 symmetric_key_size,
786
0
                 pad_in,
787
0
                 pad_in_size);
788
0
      break;
789
0
    case TPM_ES_SYM_OFB:
790
0
      rc = TPM_SymmetricKeyData_OfbCrypt(data_out,
791
0
                 data_in,
792
0
                 data_size,
793
0
                 symmetric_key,
794
0
                 symmetric_key_size,
795
0
                 pad_in,
796
0
                 pad_in_size);
797
0
      break;
798
0
    default:
799
0
      printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad AES128 encScheme %04x\n",
800
0
       encScheme);
801
0
      rc = TPM_INAPPROPRIATE_ENC;
802
0
      break;
803
0
  }
804
0
  break;
805
0
      default:
806
0
  printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad algID %08x\n", algId);
807
0
  rc = TPM_INAPPROPRIATE_ENC;
808
0
  break;
809
0
    }
810
0
    return rc;
811
0
}
812
813
/* These functions perform high-level, platform independent functions.
814
   They call the lower level, platform dependent crypto functions in
815
   tpm_crypto.c
816
*/
817
818
/* TPM_SHA1Sbuffer() calculates the SHA-1 digest of a TPM_STORE_BUFFER.
819
820
   This is commonly used when calculating a digest on a serialized structure.  Structures are
821
   serialized to a TPM_STORE_BUFFER.
822
823
   The TPM_STORE_BUFFER is not deleted.
824
*/
825
826
TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest,
827
         TPM_STORE_BUFFER *sbuffer)
828
0
{
829
0
    TPM_RESULT    rc = 0;
830
0
    const unsigned char *buffer;  /* serialized buffer */
831
0
    uint32_t    length;   /* serialization length */
832
833
0
    printf(" TPM_SHA1Sbuffer:\n");
834
0
    if (rc == 0) {
835
  /* get the components of the TPM_STORE_BUFFER */
836
0
  TPM_Sbuffer_Get(sbuffer, &buffer, &length);
837
0
  TPM_PrintFour("  TPM_SHA1Sbuffer: input", buffer);
838
  /* hash the serialized buffer to tpm_digest */
839
0
  rc = TPM_SHA1(tpm_digest,
840
0
          length, buffer,
841
0
          0, NULL);
842
0
    }   
843
0
    return rc;
844
0
}
845
846
/* TPM_SHA1_GenerateStructure() generates a SHA-1 digest of a structure.  It serializes the
847
   structure and hashes the result.
848
849
   tpmStructure is the structure to be serialized
850
   storeFunction is the serialization function for the structure
851
*/
852
853
TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest,
854
              void *tpmStructure,
855
              TPM_STORE_FUNCTION_T storeFunction)
856
0
{
857
0
    TPM_RESULT    rc = 0;
858
0
    TPM_STORE_BUFFER  sbuffer;  /* serialized tpmStructure */
859
860
0
    printf(" TPM_SHA1_GenerateStructure:\n");
861
0
    TPM_Sbuffer_Init(&sbuffer);       /* freed @1 */
862
    /* Serialize the structure */
863
0
    if (rc == 0) {
864
0
  rc = storeFunction(&sbuffer, tpmStructure);
865
0
    }   
866
    /* hash the serialized buffer to tpm_hmac */
867
0
    if (rc == 0) {
868
0
  rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer);
869
0
    }
870
0
    TPM_Sbuffer_Delete(&sbuffer);     /* @1 */
871
0
    return rc;
872
0
}
873
874
/* TPM_SHA1_CheckStructure() generates a SHA-1 digest of a structure.  It serializes the structure
875
   and hashes the result.  It compares the result to 'expected_digest' and returns 'error' on
876
   mismatch.
877
878
   tpmStructure is the structure to be serialized
879
   storeFunction is the serialization function for the structure
880
*/
881
882
883
884
TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest,
885
           void *tpmStructure,
886
           TPM_STORE_FUNCTION_T storeFunction,
887
           TPM_RESULT error)
888
0
{
889
0
    TPM_RESULT    rc = 0;
890
0
    TPM_DIGEST    actual_digest;
891
892
0
    printf(" TPM_SHA1_CheckStructure:\n");
893
    /* hash the serialized buffer to tpm_digest */
894
0
    if (rc == 0) {
895
0
  rc = TPM_SHA1_GenerateStructure(actual_digest, tpmStructure, storeFunction);
896
0
    }
897
    /* check the digests */
898
0
    if (rc == 0) {
899
0
  rc = TPM_Digest_Compare(actual_digest, expected_digest);
900
0
  if (rc != 0) {
901
0
      rc = error;
902
0
  }
903
0
    }
904
0
    return rc;
905
0
}
906
907
/* TPM_SHA1() can be called directly to hash a list of streams.
908
909
   The ... arguments to be hashed are a list of the form
910
  size_t length, unsigned char *buffer
911
   terminated by a 0 length
912
 */
913
914
TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...)
915
0
{
916
0
    TPM_RESULT  rc = 0;
917
0
    va_list ap;
918
919
0
    printf(" TPM_SHA1:\n");
920
0
    va_start(ap, md);
921
0
    rc = TPM_SHA1_valist(md, 0, NULL, ap);
922
0
    va_end(ap);
923
0
    return rc;
924
0
}
925
926
/* TPM_SHA1_Check() digests the list of streams and compares the result to 'digest_expect'
927
 */
928
929
TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...)
930
0
{
931
0
    TPM_RESULT  rc = 0;
932
0
    TPM_DIGEST  digest_actual;
933
0
    va_list ap;
934
935
0
    printf(" TPM_SHA1_Check:\n");
936
0
    if (rc == 0) {
937
0
  va_start(ap, digest_expect);
938
0
  rc = TPM_SHA1_valist(digest_actual, 0, NULL, ap);
939
0
  va_end(ap);
940
0
    }
941
0
    if (rc == 0) {
942
0
  rc = TPM_Digest_Compare(digest_expect, digest_actual);
943
0
    }
944
0
    return rc;
945
0
}
946
947
/* TPM_SHA1_valist() is the internal function, called with the va_list already created.
948
949
   It is called from TPM_SHA1() to do a simple hash.  Typically length0==0 and buffer0==NULL.
950
951
   It can also be called from the HMAC function to hash the variable number of input parameters.  In
952
   that case, the va_list for the text is already formed.  length0 and buffer0 are used to input the
953
   padded key.
954
*/
955
956
static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md,
957
          uint32_t length0, unsigned char *buffer0,
958
          va_list ap)
959
0
{
960
0
    TPM_RESULT    rc = 0;
961
0
    uint32_t    length;
962
0
    unsigned char *buffer;
963
0
    void    *context = NULL; /* platform dependent context */
964
0
    TPM_BOOL    done = FALSE;
965
    
966
0
    printf(" TPM_SHA1_valist:\n");
967
0
    if (rc == 0) {
968
0
  rc = TPM_SHA1InitCmd(&context);
969
0
    }
970
0
    if (rc == 0) { 
971
0
  if (length0 !=0) {   /* optional first text block */
972
0
      printf("  TPM_SHA1_valist: Digesting %u bytes\n", length0);
973
0
      rc = TPM_SHA1UpdateCmd(context, buffer0, length0);  /* hash the buffer */
974
0
  }
975
0
    }
976
0
    while ((rc == 0) && !done) {
977
0
  length = va_arg(ap, uint32_t);   /* first vararg is the length */
978
0
  if (length != 0) {     /* loop until a zero length argument terminates */
979
0
      buffer = va_arg(ap, unsigned char *);  /* second vararg is the array */
980
0
      printf("  TPM_SHA1_valist: Digesting %u bytes\n", length);
981
0
      rc = TPM_SHA1UpdateCmd(context, buffer, length);  /* hash the buffer */
982
0
  }
983
0
  else {
984
0
      done = TRUE;
985
0
  }
986
0
    }
987
0
    if (rc == 0) {
988
0
  rc = TPM_SHA1FinalCmd(md, context);
989
0
    }
990
0
    if (rc == 0) {
991
0
  TPM_PrintFour("  TPM_SHA1_valist: Digest", md);
992
0
    }   
993
    /* call TPM_SHA1Delete even if there was an error */
994
0
    TPM_SHA1Delete(&context);
995
0
    return rc;
996
0
}
997
998
/* TPM_HMAC_GenerateSbuffer() calculates the HMAC digest of a TPM_STORE_BUFFER.
999
1000
   This is commonly used when calculating an HMAC on a serialized structure.  Structures are
1001
   serialized to a TPM_STORE_BUFFER.
1002
1003
   The TPM_STORE_BUFFER is not deleted.
1004
*/
1005
1006
TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac,
1007
            const TPM_SECRET hmac_key,
1008
            TPM_STORE_BUFFER *sbuffer)
1009
0
{
1010
0
    TPM_RESULT    rc = 0;
1011
0
    const unsigned char *buffer;  /* serialized buffer */
1012
0
    uint32_t    length;   /* serialization length */
1013
1014
0
    printf(" TPM_HMAC_GenerateSbuffer:\n");
1015
0
    if (rc == 0) {
1016
  /* get the components of the TPM_STORE_BUFFER */
1017
0
  TPM_Sbuffer_Get(sbuffer, &buffer, &length);
1018
  /* HMAC the serialized buffer to tpm_hmac */
1019
0
  rc = TPM_HMAC_Generate(tpm_hmac,
1020
0
             hmac_key,
1021
0
             length, buffer,
1022
0
             0, NULL);
1023
0
    }   
1024
0
    return rc;
1025
0
}
1026
1027
/* TPM_HMAC_GenerateStructure() generates an HMAC of a structure.  It serializes the structure and
1028
   HMAC's the result.
1029
1030
   hmacKey is the HMAC key
1031
   tpmStructure is the structure to be serialized
1032
   storeFunction is the serialization function for the structure
1033
*/
1034
1035
TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac,
1036
              const TPM_SECRET hmac_key,
1037
              void *tpmStructure,
1038
              TPM_STORE_FUNCTION_T storeFunction)
1039
0
{
1040
0
    TPM_RESULT    rc = 0;
1041
0
    TPM_STORE_BUFFER  sbuffer;  /* serialized tpmStructure */
1042
1043
0
    printf(" TPM_HMAC_GenerateStructure:\n");
1044
0
    TPM_Sbuffer_Init(&sbuffer);       /* freed @1 */
1045
    /* Serialize the structure */
1046
0
    if (rc == 0) {
1047
0
  rc = storeFunction(&sbuffer, tpmStructure);
1048
0
    }   
1049
    /* hash the serialized buffer to tpm_hmac */
1050
0
    if (rc == 0) {
1051
0
  rc = TPM_HMAC_GenerateSbuffer(tpm_hmac, hmac_key, &sbuffer);
1052
0
    }
1053
0
    TPM_Sbuffer_Delete(&sbuffer);     /* @1 */
1054
0
    return rc;
1055
0
}
1056
    
1057
/* TPM_HMAC_Generate() can be called directly to HMAC a list of streams.
1058
   
1059
   The ... arguments are a message list of the form
1060
  size_t length, unsigned char *buffer
1061
   terminated by a 0 length
1062
*/
1063
1064
TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac,
1065
           const TPM_SECRET hmac_key,
1066
           ...)
1067
0
{
1068
0
    TPM_RESULT    rc = 0;
1069
0
    va_list   ap;
1070
    
1071
0
    printf(" TPM_HMAC_Generate:\n");
1072
0
    va_start(ap, hmac_key);
1073
0
    rc = TPM_HMAC_Generatevalist(tpm_hmac, hmac_key, ap);
1074
0
    va_end(ap);
1075
0
    return rc;
1076
0
}
1077
1078
/* TPM_HMAC_Generatevalist() is the internal function, called with the va_list already created.
1079
1080
   It is called from TPM_HMAC_Generate() and TPM_HMAC_Check() with the va_list for the text already
1081
   formed.
1082
*/
1083
1084
0
#define TPM_HMAC_BLOCK_SIZE 64
1085
1086
static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC tpm_hmac,
1087
            const TPM_SECRET key,
1088
            va_list ap)
1089
0
{
1090
0
    TPM_RESULT    rc = 0;
1091
0
    unsigned char ipad[TPM_HMAC_BLOCK_SIZE];
1092
0
    unsigned char opad[TPM_HMAC_BLOCK_SIZE];
1093
0
    size_t    i;
1094
0
    TPM_DIGEST    inner_hash;
1095
1096
0
    printf(" TPM_HMAC_Generatevalist:\n");
1097
    /* calculate key XOR ipad and key XOR opad */
1098
0
    if (rc == 0) {
1099
  /* first part, key XOR pad */
1100
0
  for (i = 0 ; i < TPM_AUTHDATA_SIZE ; i++) {
1101
0
      ipad[i] = key[i] ^ 0x36;  /* magic numbers from RFC 2104 */
1102
0
      opad[i] = key[i] ^ 0x5c;
1103
0
  }
1104
  /* second part, 0x00 XOR pad */
1105
0
  memset(ipad + TPM_AUTHDATA_SIZE, 0x36, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE);
1106
0
  memset(opad + TPM_AUTHDATA_SIZE, 0x5c, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE);
1107
  /* calculate the inner hash, hash the key XOR ipad and the text */
1108
0
  rc = TPM_SHA1_valist(inner_hash,
1109
0
           TPM_HMAC_BLOCK_SIZE, ipad, ap);
1110
0
    }
1111
    /* hash the key XOR opad and the previous hash */
1112
0
    if (rc == 0) {
1113
0
  rc = TPM_SHA1(tpm_hmac,
1114
0
          TPM_HMAC_BLOCK_SIZE, opad,
1115
0
          TPM_DIGEST_SIZE, inner_hash,
1116
0
          0, NULL);
1117
0
    }
1118
0
    if (rc == 0) {
1119
0
  TPM_PrintFour(" TPM_HMAC_Generatevalist: HMAC", tpm_hmac);
1120
0
    }   
1121
0
    return rc;
1122
0
}
1123
1124
/* TPM_HMAC_CheckSbuffer() checks the HMAC of a TPM_STORE_BUFFER.
1125
1126
   This is commonly used when checking an HMAC on a serialized structure.  Structures are serialized
1127
   to a TPM_STORE_BUFFER.
1128
1129
   The TPM_STORE_BUFFER is not deleted.
1130
*/
1131
1132
TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid,     /* result */
1133
         TPM_HMAC expect,   /* expected */
1134
         const TPM_SECRET hmac_key, /* key */
1135
         TPM_STORE_BUFFER *sbuffer) /* data stream */
1136
0
{
1137
0
    TPM_RESULT    rc = 0;
1138
0
    const unsigned char *buffer;  /* serialized buffer */
1139
0
    uint32_t    length;   /* serialization length */
1140
1141
0
    printf(" TPM_HMAC_CheckSbuffer:\n");
1142
0
    if (rc == 0) {
1143
  /* get the components of the TPM_STORE_BUFFER */
1144
0
  TPM_Sbuffer_Get(sbuffer, &buffer, &length);
1145
  /* HMAC the serialized buffer to tpm_hmac */
1146
0
  rc = TPM_HMAC_Check(valid,
1147
0
          expect,
1148
0
          hmac_key,
1149
0
          length, buffer,
1150
0
          0, NULL);
1151
0
    }   
1152
0
    return rc;
1153
0
}
1154
1155
/* TPM_HMAC_Check() can be called directly to check the HMAC of a list of streams.
1156
   
1157
   The ... arguments are a list of the form
1158
     size_t length, unsigned char *buffer
1159
   terminated by a 0 length
1160
1161
*/
1162
1163
TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid,
1164
        TPM_HMAC expect,
1165
        const TPM_SECRET key,
1166
        ...)
1167
0
{
1168
0
    TPM_RESULT    rc = 0;
1169
0
    va_list   ap;
1170
0
    TPM_HMAC    actual;
1171
0
    int     result;
1172
1173
0
    printf(" TPM_HMAC_Check:\n");
1174
0
    va_start(ap, key);
1175
0
    if (rc == 0) {
1176
0
  rc = TPM_HMAC_Generatevalist(actual, key, ap);
1177
0
    }
1178
0
    if (rc == 0) {
1179
0
  TPM_PrintFour("  TPM_HMAC_Check: Calculated", actual);
1180
0
  TPM_PrintFour("  TPM_HMAC_Check: Received  ", expect);
1181
0
  result = memcmp(expect, actual, TPM_DIGEST_SIZE);
1182
0
  if (result == 0) {
1183
0
      *valid = TRUE;
1184
0
  }
1185
0
  else {
1186
0
      *valid = FALSE;
1187
0
  }
1188
0
    }
1189
0
    va_end(ap);
1190
0
    return rc;
1191
0
}
1192
1193
/* TPM_HMAC_CheckStructure() is a generic function that checks the integrity HMAC of a structure.
1194
1195
   hmacKey is the HMAC key
1196
   tpmStructure is the structure to be serialized
1197
   expect is the expected HMAC, a member of the structure
1198
   storeFunction is the serialization function for the structure
1199
   error is the failure return code
1200
1201
   The function saves a copy of the expected HMAC, and then NULL's the structure member.  It
1202
   serializes the structure, generates an HMAC, and compares it to the expected value.
1203
1204
   As a side effect, the structure member is zeroed.
1205
*/
1206
1207
TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key,
1208
           void *tpmStructure,
1209
           TPM_HMAC expect,
1210
           TPM_STORE_FUNCTION_T storeFunction,
1211
           TPM_RESULT error)
1212
0
{
1213
0
    TPM_RESULT    rc = 0;
1214
0
    TPM_STORE_BUFFER  sbuffer;  /* serialized tpmStructure */
1215
0
    TPM_HMAC    saveExpect;
1216
0
    TPM_BOOL    valid;
1217
1218
0
    printf(" TPM_HMAC_CheckStructure:\n");
1219
0
    TPM_Sbuffer_Init(&sbuffer);     /* freed @1 */
1220
0
    if (rc == 0) {
1221
0
  TPM_Digest_Copy(saveExpect, expect);  /* save the expected value */
1222
0
  TPM_Digest_Init(expect);    /* set value in structure to NULL */
1223
0
  rc = storeFunction(&sbuffer,
1224
0
         tpmStructure);
1225
0
    }
1226
    /* verify the HMAC of the serialized structure */
1227
0
    if (rc == 0) {
1228
0
  rc = TPM_HMAC_CheckSbuffer(&valid,    /* result */
1229
0
           saveExpect,    /* expected */
1230
0
           hmac_key,    /* key */
1231
0
           &sbuffer);   /* data stream */
1232
0
    }
1233
0
    if (rc == 0) {
1234
0
  if (!valid) {
1235
0
      printf("TPM_HMAC_CheckStructure: Error checking HMAC\n");
1236
0
      rc = error;
1237
0
  }
1238
0
    }
1239
0
    TPM_Sbuffer_Delete(&sbuffer);   /* @1 */
1240
0
    return rc;
1241
0
}
1242
1243
/* TPM_XOR XOR's 'in1' and 'in2' of 'length', putting the result in 'out'
1244
1245
*/
1246
1247
void TPM_XOR(unsigned char *out,
1248
       const unsigned char *in1,
1249
       const unsigned char *in2,
1250
       size_t length)
1251
0
{
1252
0
    size_t i;
1253
    
1254
0
    for (i = 0 ; i < length ; i++) {
1255
0
  out[i] = in1[i] ^ in2[i];
1256
0
    }
1257
0
    return;
1258
0
}
1259
1260
/* TPM_MGF1() generates an MGF1 'array' of length 'arrayLen' from 'seed' of length 'seedlen'
1261
1262
   The openSSL DLL doesn't export MGF1 in Windows or Linux 1.0.0, so this version is created from
1263
   scratch.
1264
   
1265
   Algorithm and comments (not the code) from:
1266
1267
   PKCS #1: RSA Cryptography Specifications Version 2.1 B.2.1 MGF1
1268
1269
   Prototype designed to be compatible with openSSL
1270
1271
   MGF1 is a Mask Generation Function based on a hash function.
1272
   
1273
   MGF1 (mgfSeed, maskLen)
1274
1275
   Options:     
1276
1277
   Hash hash function (hLen denotes the length in octets of the hash 
1278
   function output)
1279
1280
   Input:
1281
   
1282
   mgfSeed         seed from which mask is generated, an octet string
1283
   maskLen         intended length in octets of the mask, at most 2^32(hLen)
1284
1285
   Output:      
1286
   mask            mask, an octet string of length l; or "mask too long"
1287
1288
   Error:          "mask too long'
1289
*/
1290
1291
TPM_RESULT TPM_MGF1(unsigned char       *mask,
1292
                    uint32_t            maskLen,
1293
                    const unsigned char *mgfSeed,
1294
                    uint32_t    mgfSeedlen)
1295
0
{
1296
0
    TPM_RESULT    rc = 0;
1297
0
    unsigned char       counter[4];     /* 4 octets */
1298
0
    uint32_t          count;          /* counter as an integral type */
1299
0
    uint32_t    outLen;
1300
0
    TPM_DIGEST          lastDigest;     
1301
    
1302
0
    printf(" TPM_MGF1: Output length %u\n", maskLen);
1303
0
    if (rc == 0) {
1304
        /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */
1305
0
        if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) {        /*constant condition*/
1306
0
            printf(" TPM_MGF1: Error (fatal), Output length too large for 32 bit counter\n");
1307
0
            rc = TPM_FAIL;              /* should never occur */
1308
0
        }
1309
0
    }
1310
    /* 1.If l > 2^32(hLen), output "mask too long" and stop. */
1311
    /* NOTE Checked by caller */
1312
    /* 2. Let T be the empty octet string. */
1313
    /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */
1314
0
    for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) {
1315
  /* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */
1316
  /* C = I2OSP(counter, 4) NOTE Basically big endian */
1317
0
        uint32_t count_n = htonl(count);
1318
0
  memcpy(counter, &count_n, 4);
1319
  /* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */
1320
  /* T = T || Hash (mgfSeed || C) */
1321
  /* If the entire digest is needed for the mask */
1322
0
  if ((outLen + TPM_DIGEST_SIZE) < maskLen) {
1323
0
      rc = TPM_SHA1(mask + outLen,
1324
0
        mgfSeedlen, mgfSeed,
1325
0
        4, counter,
1326
0
        0, NULL);
1327
0
      outLen += TPM_DIGEST_SIZE;
1328
0
  }
1329
  /* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */
1330
0
  else {
1331
      /* hash to a temporary digest variable */
1332
0
      rc = TPM_SHA1(lastDigest,
1333
0
        mgfSeedlen, mgfSeed,
1334
0
        4, counter,
1335
0
        0, NULL);
1336
      /* copy what's needed */
1337
0
      memcpy(mask + outLen, lastDigest, maskLen - outLen);
1338
0
      outLen = maskLen;           /* outLen = outLen + maskLen - outLen */
1339
0
  }
1340
0
    }
1341
    /* 4.Output the leading l octets of T as the octet string mask. */
1342
0
    return rc;
1343
0
}
1344
1345
/* TPM_MGF1_GenerateArray() generates an array of length arrayLen using the varargs as the seed.
1346
1347
   Since the seed is a known length, it is passed in rather that extracted from the varargs.  If the
1348
   seed length turns out to be wrong once the varargs are parsed, TPM_FAIL is returned.
1349
1350
   'array' must be freed by the caller.
1351
*/
1352
1353
TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array,
1354
          uint32_t arrayLen,
1355
          uint32_t seedLen,
1356
          ...)
1357
0
{
1358
0
    TPM_RESULT    rc = 0;
1359
0
    va_list   ap;
1360
0
    unsigned char *seed;    /* constructed MGF1 seed */
1361
0
    size_t    vaLength; /* next seed segment length */
1362
0
    unsigned char *vaBuffer;  /* next seed segment buffer */
1363
0
    uint32_t    seedLeft; /* remaining seed bytes required */
1364
0
    unsigned char *seedBuffer;  /* running pointer to the seed array */
1365
0
    TPM_BOOL    done = FALSE; /* done when a vaLength == 0 is reached */
1366
1367
0
    printf(" TPM_MGF1_GenerateArray: arrayLen %u seedLen %u\n", arrayLen, seedLen);
1368
0
    seed = NULL;   /* freed @1 */
1369
0
    *array = NULL;   /* freed by caller */
1370
0
    va_start(ap, seedLen);
1371
    /* allocate temporary memory for the seed */
1372
0
    if (rc == 0) {
1373
0
  rc = TPM_Malloc(&seed, seedLen);
1374
0
  seedBuffer = seed;
1375
0
  seedLeft = seedLen;
1376
0
    }
1377
    /* construct the seed */
1378
0
    while ((rc == 0) && !done) {
1379
0
  vaLength = (size_t)va_arg(ap, uint32_t);   /* first vararg is the length */
1380
0
  if (vaLength != 0) {     /* loop until a zero length argument terminates */
1381
0
      if (rc == 0) {
1382
0
    printf("  TPM_MGF1_GenerateArray: Appending %lu bytes\n", (unsigned long)vaLength);
1383
0
    if (vaLength > seedLeft) {
1384
0
        printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too small\n");
1385
0
        rc = TPM_FAIL; /* internal error, should never occur */
1386
0
    }
1387
0
      }
1388
0
      if (rc == 0) {
1389
0
    vaBuffer = va_arg(ap, unsigned char *); /* second vararg is the array */
1390
0
    memcpy(seedBuffer, vaBuffer, vaLength);
1391
0
    seedBuffer += vaLength;
1392
0
    seedLeft-= vaLength;
1393
0
      }
1394
0
  }
1395
0
  else {
1396
0
      done = TRUE;
1397
0
      if (seedLeft != 0) {
1398
0
    printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too large by %u\n",
1399
0
           seedLeft);
1400
0
    rc = TPM_FAIL; /* internal error, should never occur */
1401
0
      }
1402
0
  }
1403
0
    }
1404
    /* allocate memory for the array */
1405
0
    if (rc == 0) {
1406
0
  rc = TPM_Malloc(array, arrayLen);
1407
0
    }
1408
    /* generate the MGF1 array */
1409
0
    if (rc == 0) {
1410
0
  rc = TPM_MGF1(*array,   // libtpms changed: assign rc
1411
0
          arrayLen,
1412
0
          seed,
1413
0
          seedLen);
1414
0
  TPM_PrintFour("  TPM_MGF1_GenerateArray: MGF1", *array);
1415
0
    }
1416
0
    va_end(ap);
1417
0
    free(seed);   /* @1 */
1418
0
    return rc;
1419
0
}
1420
1421
/* TPM_bn2binMalloc() allocates a buffer 'bin' and loads it from 'bn'.
1422
   'bytes' is set to the allocated size of 'bin'.
1423
1424
   If padBytes is non-zero, 'bin' is padded with leading zeros if necessary, so that 'bytes' will
1425
   equal 'padBytes'.  This is used when TPM data structures expect a fixed length while the crypto
1426
   library 'bn to bin' function might truncates leading zeros.
1427
1428
   '*bin' must be freed by the caller
1429
*/
1430
1431
TPM_RESULT TPM_bn2binMalloc(unsigned char **bin,  /* freed by caller */
1432
          unsigned int *bytes,
1433
          TPM_BIGNUM bn,
1434
          uint32_t padBytes)
1435
0
{
1436
0
    TPM_RESULT  rc = 0;
1437
1438
0
    printf("   TPM_bn2binMalloc: padBytes %u\n", padBytes);
1439
    /* number of bytes required in the bin array */
1440
0
    if (rc == 0) {
1441
0
        rc = TPM_BN_num_bytes(bytes, bn);
1442
0
    }
1443
    /* calculate the array size to malloc */
1444
0
    if (rc == 0) {
1445
        /* padBytes 0 says that no padding is required */
1446
0
        if (padBytes == 0) {
1447
0
            padBytes = *bytes;  /* setting equal yields no padding */
1448
0
        }       
1449
  /* if the array with padding is still less than the number of bytes required by the bignum,
1450
     this function fails */
1451
0
        if (padBytes < *bytes) {
1452
0
            printf("TPM_bn2binMalloc: Error, "
1453
0
                   "padBytes %u less than BN bytes %u\n", padBytes, *bytes);
1454
0
            rc = TPM_SIZE;
1455
0
        }
1456
  /* log if padding is occurring */
1457
0
        if (padBytes != *bytes) {
1458
0
            printf("   TPM_bn2binMalloc: padBytes %u bytes %u\n", padBytes, *bytes);
1459
0
        }
1460
0
    }
1461
    /* allocate for the padded array */
1462
0
    if (rc == 0) {
1463
0
        rc = TPM_Malloc(bin, padBytes);
1464
0
  *bytes = padBytes;
1465
0
    }
1466
    /* call the bignum to bin conversion */
1467
0
    if (rc == 0) {
1468
0
  rc = TPM_bn2binArray(*bin, padBytes, bn);
1469
0
    }
1470
0
    return rc;
1471
0
}
1472
1473
/* TPM_bn2binArray() loads the array 'bin' of size 'bytes' from 'bn'
1474
1475
   The data from 'bn' is right justified and zero padded.
1476
*/
1477
1478
TPM_RESULT TPM_bn2binArray(unsigned char *bin,
1479
         unsigned int bytes,
1480
         TPM_BIGNUM bn)
1481
0
{
1482
0
    TPM_RESULT    rc = 0;
1483
0
    unsigned int  numBytes;
1484
1485
0
    printf("   TPM_bn2binArray: size %u\n", bytes);
1486
0
    if (rc == 0) {
1487
  /* zero pad */
1488
0
  memset(bin, 0, bytes);
1489
  /* bytes required for the bignum */
1490
0
  rc = TPM_BN_num_bytes(&numBytes, bn);
1491
0
    }
1492
    /* if the array is less than the number of bytes required by the bignum, this function fails */
1493
0
    if (rc == 0) {
1494
0
  printf("   TPM_bn2binArray: numBytes in bignum %u\n", numBytes);
1495
0
  if (numBytes > bytes) {
1496
0
            printf("TPM_bn2binArray: Error, "
1497
0
                   "BN bytes %u greater than array bytes %u\n", numBytes, bytes);
1498
0
            rc = TPM_SIZE;
1499
0
  }
1500
0
    }
1501
0
    if (rc == 0) {
1502
  /* if there are bytes in the bignum (it is not zero) */
1503
0
  if (numBytes  > 0) {
1504
0
      rc = TPM_bn2bin(bin + bytes - numBytes, /* store right justified */
1505
0
          bn);
1506
0
  }
1507
0
    }
1508
0
    return rc;
1509
0
}
1510
1511
/* TPM_2bin2bn() converts two byte arrays to a positive BIGNUM.
1512
1513
   The two byte arrays are concatenated.  The concatenation is used to create the BIGNUM.
1514
1515
   bignum must be freed by the caller.
1516
*/
1517
1518
TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in,         /* freed by caller */
1519
                       const unsigned char *bin0, uint32_t size0,
1520
                       const unsigned char *bin1, uint32_t size1)
1521
0
{
1522
0
    TPM_RESULT          rc = 0;         /* TPM return code */
1523
0
    TPM_STORE_BUFFER    sBuffer;        /* used of >1 element or first element is negative */
1524
0
    const unsigned char *buffer;
1525
0
    uint32_t    size;
1526
    
1527
0
    printf("  TPM_bin2bn:\n");
1528
0
    TPM_Sbuffer_Init(&sBuffer);         /* freed @1 */
1529
    /* append the first element */
1530
0
    if (rc == 0) {
1531
0
        rc = TPM_Sbuffer_Append(&sBuffer, bin0, size0);
1532
0
    }
1533
    /* append the next element */
1534
0
    if (rc == 0) {
1535
0
        rc = TPM_Sbuffer_Append(&sBuffer, bin1, size1);
1536
0
    }
1537
    /* create the BIGNUM from the array */
1538
0
    if (rc == 0) {
1539
0
        TPM_Sbuffer_Get(&sBuffer, &buffer, &size);
1540
        /* create the BIGNUM */
1541
0
        rc = TPM_bin2bn(bignum_in, buffer, size);  /* freed by caller */
1542
0
    }
1543
0
    TPM_Sbuffer_Delete(&sBuffer);               /* @1 */
1544
0
    return rc;
1545
0
}
1546
1547
/* TPM_RSAPrivateDecryptMalloc() allocates a buffer 'decrypt_data' of size 'decrypt_data_size'
1548
   and then calls TPM_RSAPrivateDecryptH().
1549
*/
1550
1551
TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data,  /* decrypted data */
1552
               uint32_t *decrypt_data_length, /* length of data put into
1553
                     decrypt_data */
1554
               unsigned char *encrypt_data,
1555
               uint32_t encrypt_data_size,
1556
               TPM_KEY *tpm_key)
1557
0
{
1558
0
    TPM_RESULT    rc = 0;
1559
1560
    /* allocate space for the decrypted blob */
1561
0
    printf(" TPM_RSAPrivateDecryptMalloc: Return max data size %u bytes\n",
1562
0
     tpm_key->pubKey.size);
1563
0
    if (rc == 0) {
1564
0
  rc = TPM_Malloc(decrypt_data, tpm_key->pubKey.size);
1565
0
    }
1566
0
    if (rc == 0) {
1567
0
  rc = TPM_RSAPrivateDecryptH(*decrypt_data,
1568
0
            decrypt_data_length,
1569
0
            tpm_key->pubKey.size,
1570
0
            encrypt_data,
1571
0
            encrypt_data_size,
1572
0
            tpm_key);
1573
0
    }
1574
0
    return rc;
1575
0
}
1576
1577
/* TPM_RSAPrivateDecryptH() decrypts 'encrypt_data' using the private key in
1578
   'tpm_key' and 'decrypt_data_length' bytes are moved to 'decrypt_data'.
1579
1580
   'decrypt_data_length' is at most 'decrypt_data_size'.
1581
*/
1582
1583
TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data,  /* decrypted data */
1584
          uint32_t *decrypt_data_length,  /* length of data put into
1585
                     decrypt_data */
1586
          uint32_t decrypt_data_size, /* size of decrypt_data buffer */
1587
          unsigned char *encrypt_data,
1588
          uint32_t encrypt_data_size,
1589
          TPM_KEY *tpm_key)
1590
0
{
1591
0
    TPM_RESULT    rc = 0;
1592
0
    unsigned char *narr;    /* public modulus */
1593
0
    uint32_t    nbytes;
1594
0
    unsigned char *earr;    /* public exponent */
1595
0
    uint32_t    ebytes;
1596
0
    unsigned char *darr;    /* private exponent */
1597
0
    uint32_t    dbytes;
1598
1599
0
    printf(" TPM_RSAPrivateDecryptH: Data size %u bytes\n", encrypt_data_size);
1600
0
    TPM_PrintFourLimit("  TPM_RSAPrivateDecryptH: Encrypt data", encrypt_data, encrypt_data_size);
1601
0
    if (rc == 0) {
1602
0
  if (tpm_key == NULL) {
1603
0
      printf("TPM_RSAPrivateDecryptH: Error, NULL key\n");
1604
0
      rc = TPM_DECRYPT_ERROR;
1605
0
  }
1606
0
    }
1607
    /* extract the public key from TPM_KEY */
1608
0
    if (rc == 0) {
1609
0
  rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key);
1610
0
    }  
1611
    /* extract the private key from TPM_KEY */
1612
0
    if (rc == 0) {
1613
0
  rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key);
1614
0
    }
1615
    /* extract the exponent from TPM_KEY */
1616
0
    if (rc == 0) {
1617
0
  rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key);
1618
0
    }
1619
    /* check the key size vs the data size */
1620
0
    if (rc == 0) {
1621
0
  if (encrypt_data_size > nbytes) {
1622
0
      printf("TPM_RSAPrivateDecryptH: Error, data size too long for key size %u bytes\n",
1623
0
       nbytes);
1624
0
      rc = TPM_BAD_DATASIZE;
1625
0
  }
1626
0
    }
1627
0
    if (rc == 0) {
1628
  /* debug printing */
1629
0
  printf("  TPM_RSAPrivateDecryptH: Public key length %u\n", nbytes);
1630
0
  printf("  TPM_RSAPrivateDecryptH: Private key length %u\n", dbytes);
1631
0
  TPM_PrintFour("  TPM_RSAPrivateDecryptH: Public key", narr);
1632
0
  printf("  TPM_RSAPrivateDecryptH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]);
1633
0
  TPM_PrintFour("  TPM_RSAPrivateDecryptH: Private key", darr);
1634
  /* decrypt with private key */
1635
0
  rc = TPM_RSAPrivateDecrypt(decrypt_data,  /* decrypted data */
1636
0
           decrypt_data_length, /* length of data put into decrypt_data */
1637
0
           decrypt_data_size, /* size of decrypt_data buffer */
1638
0
           tpm_key->algorithmParms.encScheme, /* encryption scheme */
1639
0
           encrypt_data,  /* encrypted data */
1640
0
           encrypt_data_size,
1641
0
           narr,    /* public modulus */
1642
0
           nbytes,
1643
0
           earr,    /* public exponent */
1644
0
           ebytes,
1645
0
           darr,    /* private exponent */
1646
0
           dbytes);
1647
0
    }
1648
0
    if (rc == 0) {
1649
0
  TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Decrypt data", decrypt_data, *decrypt_data_length);
1650
0
    }
1651
0
    return rc;
1652
0
}
1653
1654
/* TPM_RSAPublicEncryptSbuffer_Key() encrypts 'sbuffer' using the public key in 'tpm_key' and
1655
   puts the results in 'encData'
1656
*/
1657
1658
TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data,
1659
             TPM_STORE_BUFFER *sbuffer,
1660
             TPM_KEY *tpm_key)
1661
0
{
1662
0
    TPM_RESULT    rc = 0;
1663
0
    const unsigned char *decrypt_data;    /* serialization buffer */
1664
0
    uint32_t    decrypt_data_size;  /* serialization size */
1665
1666
0
    printf(" TPM_RSAPublicEncryptSbuffer_Key:\n");
1667
    /* get the serialization results */
1668
0
    TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size);
1669
    /* encrypt the serialization buffer with the public key, and place
1670
       the result in the enc_data buffer */
1671
0
    rc = TPM_RSAPublicEncrypt_Key(enc_data,
1672
0
          decrypt_data,
1673
0
          decrypt_data_size,
1674
0
          tpm_key);
1675
0
    return rc;
1676
0
}
1677
1678
/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_key' and
1679
   puts the results in 'encData'
1680
*/
1681
1682
TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data,
1683
            const unsigned char *decrypt_data,
1684
            size_t decrypt_data_size,
1685
            TPM_KEY *tpm_key)
1686
0
{
1687
0
    TPM_RESULT    rc = 0;
1688
0
    unsigned char *narr;     /* public modulus */
1689
0
    uint32_t    nbytes;
1690
0
    unsigned char *earr;     /* public exponent */
1691
0
    uint32_t    ebytes;
1692
    
1693
0
    printf(" TPM_RSAPublicEncrypt_Key: Data size %lu bytes\n", (unsigned long)decrypt_data_size);
1694
0
    if (rc == 0) {
1695
0
  if (tpm_key == NULL) {
1696
0
      printf("TPM_RSAPublicEncrypt_Key: Error, NULL key\n");
1697
0
      rc = TPM_ENCRYPT_ERROR;
1698
0
  }
1699
0
    }
1700
    /* extract the public key from TPM_KEY */
1701
0
    if (rc == 0) {
1702
0
  rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key);
1703
0
    }
1704
    /* extract the exponent from TPM_KEY */
1705
0
    if (rc == 0) {
1706
0
  rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key);
1707
0
    }
1708
0
    if (rc == 0) {
1709
0
  rc = TPM_RSAPublicEncrypt_Common(enc_data,
1710
0
           decrypt_data,
1711
0
           decrypt_data_size,
1712
0
           tpm_key->algorithmParms.encScheme, /* encryption scheme */
1713
0
           narr,
1714
0
           nbytes,
1715
0
           earr,
1716
0
           ebytes);
1717
0
    }
1718
0
    return rc;
1719
0
}
1720
1721
/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_pubkey' and
1722
   puts the results in 'encData'
1723
*/
1724
1725
TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data,
1726
               const unsigned char *decrypt_data,
1727
               size_t decrypt_data_size,
1728
               TPM_PUBKEY *tpm_pubkey)
1729
0
{
1730
0
    TPM_RESULT    rc = 0;
1731
0
    unsigned char *narr;     /* public modulus */
1732
0
    uint32_t    nbytes;
1733
0
    unsigned char *earr;     /* public exponent */
1734
0
    uint32_t    ebytes;
1735
    
1736
0
    printf(" TPM_RSAPublicEncrypt_Pubkey: Data size %lu bytes\n", (unsigned long)decrypt_data_size);
1737
0
    if (rc == 0) {
1738
0
  if (tpm_pubkey == NULL) {
1739
0
      printf("TPM_RSAPublicEncrypt_Pubkey: Error, NULL key\n");
1740
0
      rc = TPM_ENCRYPT_ERROR;
1741
0
  }
1742
0
    }
1743
    /* extract the public key from TPM_PUBKEY */
1744
0
    if (rc == 0) {
1745
0
  rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey);
1746
0
    }
1747
    /* extract the exponent from TPM_KEY */
1748
0
    if (rc == 0) {
1749
0
  rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey);
1750
0
    }
1751
0
    if (rc == 0) {
1752
0
  rc = TPM_RSAPublicEncrypt_Common(enc_data,
1753
0
           decrypt_data,
1754
0
           decrypt_data_size,
1755
0
           tpm_pubkey->algorithmParms.encScheme,
1756
0
           narr,
1757
0
           nbytes,
1758
0
           earr,
1759
0
           ebytes);
1760
0
    }
1761
0
    return rc;
1762
0
}
1763
1764
/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key modulus and
1765
   exponent, and puts the results in 'encData'
1766
*/
1767
1768
TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data,
1769
               const unsigned char *decrypt_data,
1770
               size_t decrypt_data_size,
1771
               TPM_ENC_SCHEME encScheme,
1772
               unsigned char  *narr,     /* public modulus */
1773
               uint32_t   nbytes,
1774
               unsigned char  *earr,     /* public exponent */
1775
               uint32_t   ebytes)
1776
1777
0
{
1778
0
    TPM_RESULT    rc = 0;
1779
0
    unsigned char *encrypt_data = NULL;
1780
    
1781
0
    printf(" TPM_RSAPublicEncrypt_Common: Data size %lu bytes\n", (unsigned long)decrypt_data_size);
1782
0
    TPM_PrintFourLimit(" TPM_RSAPublicEncrypt_Common: Decrypt data", decrypt_data, decrypt_data_size);
1783
    /* check the key size vs the data size */
1784
0
    if (rc == 0) {
1785
0
  if (decrypt_data_size > nbytes) {
1786
0
      printf("TPM_RSAPublicEncrypt_Common: Error, data size too long for key size %u bytes\n",
1787
0
       nbytes);
1788
0
      rc = TPM_BAD_DATASIZE;
1789
0
  }
1790
0
    }
1791
    /* allocate an array for the encrypted data */
1792
0
    if (rc == 0) {
1793
0
  rc = TPM_Malloc(&encrypt_data, nbytes);
1794
0
    }
1795
    /* pad and encrypt the data */
1796
0
    if (rc == 0) {
1797
0
  TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Public key", narr);
1798
0
  printf(" TPM_RSAPublicEncrypt_Common: Exponent %02x %02x %02x\n",
1799
0
         earr[0], earr[1], earr[2]);
1800
0
  rc = TPM_RSAPublicEncrypt(encrypt_data,   /* encrypted data */
1801
0
          nbytes,   /* encrypted data size */
1802
0
          encScheme,    /* encryption scheme */
1803
0
          decrypt_data,   /* decrypted data */
1804
0
          decrypt_data_size,
1805
0
          narr,     /* public modulus */
1806
0
          nbytes,
1807
0
          earr,     /* public exponent */
1808
0
          ebytes);
1809
0
    }
1810
    /* copy the result to the sized buffer */
1811
0
    if (rc == 0) {
1812
0
  printf("  TPM_RSAPublicEncrypt_Common: Encrypt data size %u\n", nbytes);
1813
0
  TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Encrypt data", encrypt_data);
1814
0
  rc = TPM_SizedBuffer_Set(enc_data, nbytes, encrypt_data);
1815
0
    }
1816
0
    free(encrypt_data); /* @1 */
1817
0
    return rc;
1818
0
}
1819
1820
/*
1821
  Signing Functions
1822
1823
  These commands show the TPM command and the allowed signature schemes:
1824
1825
        SHA DER INFO
1826
  TPM_GetAuditDigestSigned  y n y
1827
  TPM_CertifyKey    y n y
1828
  TPM_CertifyKey2   y n y
1829
  TPM_CertifySelfTest   y n y
1830
  TPM_Quote     y n y
1831
  TPM_Quote2      y n y
1832
  TPM_Sign      y y y
1833
  TPM_MakeIdentity    y n y
1834
  TPM_GetCapabilitySigned y n y
1835
*/
1836
1837
/* TPM_RSASignToSizedBuffer() signs 'message' using the private key in 'tpm_key' and places the
1838
   result in 'signature'
1839
1840
   'signature' should be initialized and deleted by the caller
1841
*/
1842
1843
TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature,
1844
            const unsigned char *message, /* input */
1845
            size_t message_size,    /* input */
1846
            TPM_KEY *tpm_key)   /* input, signing key */
1847
0
{
1848
0
    TPM_RESULT    rc = 0;
1849
0
    TPM_RSA_KEY_PARMS *rsa_key_parms;
1850
0
    unsigned int  signature_length;
1851
    
1852
0
    printf(" TPM_RSASignToSizedBuffer: Message size %lu bytes\n", (unsigned long)message_size);
1853
0
    if (rc == 0) {
1854
0
  rc = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms,
1855
0
           &(tpm_key->algorithmParms));
1856
0
    }
1857
    /* allocating space for the signature */
1858
0
    if (rc == 0) {
1859
0
  rc = TPM_SizedBuffer_Allocate(signature, (rsa_key_parms->keyLength)/CHAR_BIT);
1860
0
    }
1861
    /* sign */
1862
0
    if (rc == 0) {
1863
0
  rc = TPM_RSASignH(signature->buffer,  /* output signature */
1864
0
        &signature_length,  /* output, size of signature */
1865
0
        signature->size,  /* input, size of signature buffer */
1866
0
        message,    /* message */
1867
0
        message_size,   /* message size */
1868
0
        tpm_key);   /* input, signing key */
1869
0
    }
1870
    /* sanity check on signature */
1871
0
    if (rc == 0) {
1872
0
  if (signature_length != signature->size) {
1873
0
      printf("TPM_RSASignToSizedBuffer: Error (fatal) signature_length %u sigSize %u\n",
1874
0
       signature_length, signature->size);
1875
0
      rc = TPM_FAIL; /* internal error, should never occur */
1876
0
  }
1877
0
    }
1878
0
    return rc;
1879
0
}
1880
    
1881
1882
/* TPM_RSASignH() signs 'message' using the private key in 'tpm_key'.  'signature_length' bytes are
1883
   moved to 'signature'.
1884
1885
   'signature_length' is at most 'signature_size'.
1886
*/
1887
1888
TPM_RESULT TPM_RSASignH(unsigned char *signature,   /* output */
1889
      unsigned int *signature_length,   /* output, size of signature */
1890
      unsigned int signature_size,  /* input, size of signature buffer */
1891
      const unsigned char *message, /* input */
1892
      size_t message_size,    /* input */
1893
      TPM_KEY *tpm_key)   /* input, signing key */
1894
0
{
1895
0
    TPM_RESULT    rc = 0;
1896
0
    unsigned char *narr;     /* public modulus */
1897
0
    uint32_t    nbytes;
1898
0
    unsigned char *earr;     /* public exponent */
1899
0
    uint32_t    ebytes;
1900
0
    unsigned char *darr;    /* private exponent */
1901
0
    uint32_t    dbytes;
1902
    
1903
0
    printf(" TPM_RSASignH: Message size %lu bytes\n", (unsigned long)message_size);
1904
0
    TPM_PrintFourLimit("  TPM_RSASignH: Message", message, message_size);
1905
    /* extract the public key from TPM_KEY */
1906
0
    if (rc == 0) {
1907
0
  rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key);
1908
0
    }  
1909
    /* extract the private key from TPM_KEY */
1910
0
    if (rc == 0) {
1911
0
  rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key);
1912
0
    }
1913
    /* extract the exponent from TPM_KEY */
1914
0
    if (rc == 0) {
1915
0
  rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key);
1916
0
    }
1917
0
    if (rc == 0) {
1918
  /* debug printing */
1919
0
  TPM_PrintFour("  TPM_RSASignH: Public key", narr);
1920
0
  printf("  TPM_RSASignH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]);
1921
0
  TPM_PrintFour("  TPM_RSASignH: Private key", darr);
1922
  /* sign with private key */
1923
0
  rc = TPM_RSASign(signature,   /* output */
1924
0
       signature_length,  /* output, size of signature */
1925
0
       signature_size,  /* input, size of signature buffer */
1926
0
       tpm_key->algorithmParms.sigScheme, /* input, type of signature */
1927
0
       message, /* input */
1928
0
       message_size,  /* input */
1929
0
       narr,    /* public modulus */
1930
0
       nbytes,
1931
0
       earr,    /* public exponent */
1932
0
       ebytes,
1933
0
       darr,    /* private exponent */
1934
0
       dbytes);
1935
0
    }
1936
0
    if (rc == 0) {
1937
0
  TPM_PrintFour("  TPM_RSASignH: Signature", signature);
1938
0
    }
1939
0
    return rc;
1940
0
}
1941
1942
/* TPM_RSAVerifyH() verifies 'message' using the TPM format public key in 'tpm_pubkey'
1943
*/
1944
1945
TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature,  /* input */
1946
        const unsigned char *message, /* input */
1947
        uint32_t message_size,  /* input */
1948
        TPM_PUBKEY *tpm_pubkey) /* input, verify key */
1949
0
{
1950
0
    TPM_RESULT    rc = 0;
1951
0
    unsigned char *narr;     /* public modulus */
1952
0
    uint32_t    nbytes;
1953
0
    unsigned char *earr;     /* public exponent */
1954
0
    uint32_t    ebytes;
1955
1956
0
    printf(" TPM_RSAVerifyH: Message size %u bytes\n", message_size);
1957
    /* extract the public key from TPM_PUBKEY */
1958
0
    if (rc == 0) {
1959
0
  rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey);
1960
0
    }
1961
    /* extract the exponent from TPM_PUBKEY */
1962
0
    if (rc == 0) {
1963
0
  rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey);
1964
0
    }
1965
0
    if (rc == 0) {
1966
  /* debug printing */
1967
0
  TPM_PrintFour("  TPM_RSAVerifyH: Public key", narr);
1968
0
        TPM_PrintAll("  TPM_RSAVerifyH: Public exponent", earr, ebytes);
1969
  /* verify with public key */
1970
0
  rc = TPM_RSAVerify(signature->buffer, /* input signature buffer */
1971
0
         signature->size, /* input, size of signature buffer */
1972
0
         tpm_pubkey->algorithmParms.sigScheme, /* input, type of signature */
1973
0
         message,   /* message */
1974
0
         message_size,  /* message size */
1975
0
         narr,    /* public modulus */
1976
0
         nbytes,
1977
0
         earr,    /* public exponent */
1978
0
         ebytes);
1979
0
    }
1980
0
    return rc;
1981
0
}
1982
1983
/* TPM_RSAVerify() verifies the 'signature' of size 'signature_size' on the 'message' of size
1984
   'message_size' using the public key n,e and the signature scheme 'sigScheme' as specified in PKCS
1985
   #1 v2.0.
1986
*/
1987
1988
TPM_RESULT TPM_RSAVerify(unsigned char *signature,      /* input */
1989
                         unsigned int   signature_size, /* input, size of signature buffer */
1990
                         TPM_SIG_SCHEME sigScheme,      /* input, type of signature */
1991
                         const unsigned char *message,  /* input */
1992
                         uint32_t   message_size,   /* input */
1993
                         unsigned char *narr,           /* public modulus */
1994
                         uint32_t   nbytes,
1995
                         unsigned char *earr,           /* public exponent */
1996
                         uint32_t   ebytes)
1997
0
{
1998
0
    TPM_RESULT  rc = 0;
1999
    
2000
0
    printf(" TPM_RSAVerify:\n");
2001
    /* determine the signature scheme for the key */
2002
0
    if (rc == 0) {
2003
0
        switch(sigScheme) {
2004
0
          case TPM_SS_NONE:
2005
0
            printf("TPM_RSAVerify: Error, sigScheme TPM_SS_NONE\n");
2006
0
            rc = TPM_INVALID_KEYUSAGE;
2007
0
            break;
2008
0
          case TPM_SS_RSASSAPKCS1v15_SHA1:
2009
0
          case TPM_SS_RSASSAPKCS1v15_INFO:
2010
0
            rc = TPM_RSAVerifySHA1(signature,
2011
0
                                   signature_size,
2012
0
                                   message,
2013
0
                                   message_size,
2014
0
           narr,    /* public modulus */
2015
0
           nbytes,
2016
0
           earr,    /* public exponent */
2017
0
           ebytes);
2018
0
            break;
2019
0
          case TPM_SS_RSASSAPKCS1v15_DER:
2020
0
            printf("TPM_RSAVerify: Error, sigScheme %04hx unsupported\n", sigScheme);
2021
0
            rc = TPM_INVALID_KEYUSAGE;
2022
0
            break;
2023
0
          default:
2024
0
            printf("TPM_RSAVerify: Error, sigScheme %04hx unknown\n", sigScheme);
2025
0
            rc = TPM_INVALID_KEYUSAGE;
2026
0
            break;
2027
0
        }
2028
0
    }
2029
0
    return rc;
2030
0
}
2031
2032
/*
2033
  OAEP Padding 
2034
*/
2035
2036
/* TPM_RSA_padding_add_PKCS1_OAEP() is a variation of the the openSSL function
2037
2038
   int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
2039
   unsigned char *f, int fl, unsigned char *p, int pl);
2040
2041
   It is used for TPM migration.  The "encoding parameter" pl is replaced by pHash and the generated
2042
   random seed is replaced by a seed parameter.
2043
2044
   This function was independently written from the PKCS1 specification "9.1.1.1 Encoding
2045
   Operation", intended to be unencumbered by any license.
2046
2047
2048
   | seed | pHash |    PS      | 01 |      Message        |
2049
2050
   SHA1   SHA1              flen
2051
2052
   | <-       emLen            -> |
2053
   | db
2054
   | maskDb
2055
   |        dbMask               |
2056
   | seedMask
2057
   | maskSeed
2058
*/
2059
2060
TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen,
2061
            const unsigned char *from, uint32_t fLen,
2062
            const unsigned char *pHash,   /* input 20 bytes */
2063
            const unsigned char *seed)    /* input 20 bytes */
2064
0
{ 
2065
0
    TPM_RESULT  rc = 0;
2066
0
    unsigned char *dbMask;
2067
0
    unsigned char *db;
2068
0
    unsigned char *maskedDb;
2069
0
    unsigned char *seedMask;
2070
0
    unsigned char *maskedSeed;
2071
2072
0
    printf(" TPM_RSA_padding_add_PKCS1_OAEP: fLen %d emLen %d\n", fLen, emLen);
2073
0
    TPM_PrintFourLimit("  TPM_RSA_padding_add_PKCS1_OAEP: from", from, fLen);
2074
0
    TPM_PrintFour("  TPM_RSA_padding_add_PKCS1_OAEP: pHash", pHash);
2075
0
    TPM_PrintFour("  TPM_RSA_padding_add_PKCS1_OAEP: seed", seed);
2076
    
2077
0
    dbMask = NULL;     /* freed @1 */
2078
2079
    /* 1. If the length of P is greater than the input limitation for */
2080
    /* the hash function (2^61-1 octets for SHA-1) then output "parameter */
2081
    /* string too long" and stop. */
2082
    /* NOTE Not done, pHash is input directly */
2083
    /* 2. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */
2084
0
    if (rc == 0) {
2085
0
  if (emLen < ((2 * TPM_DIGEST_SIZE) + 1 + fLen)) {
2086
0
      printf("TPM_RSA_padding_add_PKCS1_OAEP: Error, "
2087
0
       "message length %u too large for encoded length %u\n", fLen, emLen);
2088
0
      rc = TPM_ENCRYPT_ERROR;
2089
0
  }
2090
0
    }
2091
    /* 3. Generate an octet string PS consisting of emLen-||M||-2hLen-1 zero octets. The length of
2092
       PS may be 0. */
2093
    /* NOTE Created directly in DB (step 5) */
2094
2095
    /* 4. Let pHash = Hash(P), an octet string of length hLen. */
2096
    /* NOTE pHash is input directly */
2097
2098
    /* 5. Concatenate pHash, PS, the message M, and other padding to form a data block DB as: DB =
2099
       pHash || PS || 01 || M */
2100
0
    if (rc == 0) {
2101
  /* NOTE Since db is eventually maskedDb, part of em, create directly in em */
2102
0
  db = em + TPM_DIGEST_SIZE;
2103
0
  memcpy(db, pHash, TPM_DIGEST_SIZE);        /* pHash */
2104
0
  memset(db + TPM_DIGEST_SIZE, 0,          /* PS */
2105
0
         emLen - fLen - (2 * TPM_DIGEST_SIZE) - 1);
2106
  /* PSlen = emlen - flen - (2 * TPM_DIGEST_SIZE) - 1
2107
     0x01 index = TPM_DIGEST_SIZE + PSlen
2108
     = TPM_DIGEST_SIZE + emlen - flen - (2 * TPM_DIGEST_SIZE) - 1
2109
     = emlen - fLen - TPM_DIGEST_SIZE - 1 */
2110
0
  db[emLen - fLen - TPM_DIGEST_SIZE - 1] = 0x01;
2111
0
  memcpy(db + emLen - fLen - TPM_DIGEST_SIZE, from, fLen);  /* M */
2112
2113
  /* 6. Generate a random octet string seed of length hLen. */
2114
  /* NOTE seed is input directly */
2115
2116
  /* 7. Let dbMask = MGF(seed, emLen-hLen). */
2117
0
  rc = TPM_Malloc(&dbMask, emLen - TPM_DIGEST_SIZE);
2118
0
    }
2119
0
    if (rc == 0) {
2120
0
  rc = TPM_MGF1(dbMask, emLen - TPM_DIGEST_SIZE, seed, TPM_DIGEST_SIZE);
2121
0
    }
2122
0
    if (rc == 0) {
2123
  /* 8. Let maskedDB = DB \xor dbMask. */
2124
  /* NOTE Since maskedDB is eventually em, XOR directly to em */
2125
0
  maskedDb = em + TPM_DIGEST_SIZE;
2126
0
  TPM_XOR(maskedDb, db, dbMask, emLen - TPM_DIGEST_SIZE);
2127
2128
  /* 9. Let seedMask = MGF(maskedDB, hLen). */
2129
  /* NOTE Since seedMask is eventually em, create directly to em */
2130
0
  seedMask = em;
2131
0
  rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDb, emLen - TPM_DIGEST_SIZE);
2132
0
    }
2133
0
    if (rc == 0) {
2134
  /* 10. Let maskedSeed = seed \xor seedMask. */
2135
  /* NOTE Since maskedSeed is eventually em, create directly to em */
2136
0
  maskedSeed = em;
2137
0
  TPM_XOR(maskedSeed, seed, seedMask, TPM_DIGEST_SIZE);
2138
2139
  /* 11. Let EM = maskedSeed || maskedDB. */
2140
  /* NOTE Created directly in em */
2141
  
2142
  /* 12. Output EM. */
2143
0
  TPM_PrintFourLimit("  TPM_RSA_padding_add_PKCS1_OAEP: em", em, emLen);
2144
0
    }
2145
0
    free(dbMask);   /* @1 */
2146
0
    return rc;
2147
0
}
2148
2149
/* TPM_RSA_padding_check_PKCS1_OAEP() is a variation of the openSSL function
2150
2151
   int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
2152
   unsigned char *f, int fl, int rsa_len, unsigned char *p, int pl);
2153
   
2154
   It is used for TPM key migration.  In addition to the message 'to' and message length 'tlen', the
2155
   seed and 'pHash are returned.
2156
2157
   This function was independently written from the PKCS1 specification "9.1.1.2 Decoding
2158
   Operation", intended to be unencumbered by the any license.
2159
2160
   |  seed  |  pHash  |   PS       | 01 |    Message        |
2161
   SHA1     SHA1
2162
   | <-       emLen            -> |
2163
   
2164
   | maskedSeed
2165
   | seedMask
2166
   | maskedDB
2167
   | db
2168
   | <-    dbMask           -> |
2169
   
2170
*/
2171
2172
TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, 
2173
              const unsigned char *em, uint32_t emLen,
2174
              unsigned char *pHash, /* output 20 bytes */
2175
              unsigned char *seed)  /* output 20 bytes */
2176
0
{
2177
0
    TPM_RESULT    rc = 0;
2178
0
    const unsigned char *maskedSeed;
2179
0
    const unsigned char *maskedDB;
2180
0
    uint32_t    dbLen;
2181
0
    unsigned char *dbMask;
2182
0
    unsigned char *seedMask;
2183
0
    unsigned char *db;
2184
0
    size_t    i;
2185
2186
0
    printf(" TPM_RSA_padding_check_PKCS1_OAEP: emLen %d tSize %d\n", emLen, tSize);
2187
0
    TPM_PrintFourLimit("  TPM_RSA_padding_check_PKCS1_OAEP: em", em, emLen);
2188
2189
0
    dbMask = NULL;     /* freed @1 */
2190
    
2191
    /* 1. If the length of P is greater than the input limitation for the hash function (2^61-1
2192
       octets for SHA-1) then output "parameter string too long" and stop. */
2193
    /* NOTE There is no P input.  pHash is calculated for the output, but no comparison is
2194
       performed. */
2195
2196
    /* 2. If ||EM|| < 2hLen+1, then output "decoding error" and stop. */
2197
0
    if (rc == 0) {
2198
0
  if (emLen < (2 * TPM_DIGEST_SIZE) + 1) {
2199
0
      printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, encoded length %u too small\n", emLen);
2200
0
      rc = TPM_DECRYPT_ERROR;
2201
0
  }
2202
0
    }
2203
0
    if (rc == 0) {
2204
  /* 3. Let maskedSeed be the first hLen octets of EM and let maskedDB be the remaining ||EM||
2205
     - hLen octets. */
2206
0
  maskedSeed = em;
2207
0
  maskedDB = em + TPM_DIGEST_SIZE;
2208
0
  dbLen = emLen - TPM_DIGEST_SIZE;
2209
  /* 4. Let seedMask = MGF(maskedDB, hLen). */
2210
  /* NOTE Created directly in seed */ 
2211
0
  seedMask = seed;
2212
0
  rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDB, dbLen);
2213
0
    }
2214
0
    if (rc == 0) {
2215
  /* 5. Let seed = maskedSeed \xor seedMask. */
2216
0
  TPM_XOR(seed, maskedSeed, seedMask, TPM_DIGEST_SIZE);
2217
  /* 6. Let dbMask = MGF(seed, ||EM|| - hLen). */
2218
0
  rc = TPM_Malloc(&dbMask, dbLen);
2219
0
    }
2220
0
    if (rc == 0) {
2221
0
  rc = TPM_MGF1(dbMask, dbLen, seed, TPM_DIGEST_SIZE);
2222
0
    }
2223
0
    if (rc == 0) {
2224
  /* 7. Let DB = maskedDB \xor dbMask. */
2225
  /* NOTE XOR back to dbMask, since dbMask no longer needed */
2226
0
  db = dbMask;
2227
0
  TPM_XOR(db, maskedDB, dbMask, dbLen);
2228
  /* 8. Let pHash = Hash(P), an octet string of length hLen. */
2229
  /* NOTE pHash is input directly */
2230
  /* 9. Separate DB into an octet string pHash' consisting of the first hLen octets of DB,
2231
     ... */
2232
0
  memcpy(pHash, db, TPM_DIGEST_SIZE);
2233
  /* ... a (possibly empty) octet string PS consisting of consecutive zero octets following
2234
     pHash', and a message M as: DB = pHash' || PS || 01 || M */
2235
0
  for (i = TPM_DIGEST_SIZE; i < dbLen; i++) {
2236
0
      if (db[i] != 0x00) {
2237
0
    break;  /* skip the PS segment */
2238
0
      }
2239
0
  }
2240
  /* If there is no 01 octet to separate PS from M, output "decoding error" and stop. */
2241
0
  if (i == dbLen) {
2242
0
      printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n");
2243
0
      rc = TPM_DECRYPT_ERROR;
2244
0
  }
2245
0
    }
2246
0
    if (rc == 0) {
2247
0
  if (db[i] != 0x01) {
2248
0
      printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n");
2249
0
      rc = TPM_DECRYPT_ERROR;
2250
0
  }
2251
0
    }
2252
    /* 10. If pHash' does not equal pHash, output "decoding error" and stop. */
2253
    /* NOTE No pHash input to compare */
2254
    /* 11. Output M. */
2255
0
    if (rc == 0) {
2256
0
  i++;  /* skip the 0x01 to the beginning of the message M */
2257
0
  *tLen = dbLen - i;
2258
0
  if (*tLen > tSize) {
2259
0
      printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, tSize %u too small for message %u\n",
2260
0
       tSize, *tLen);
2261
0
      rc = TPM_DECRYPT_ERROR;
2262
0
  }
2263
0
    }
2264
0
    if (rc == 0) {
2265
0
  memcpy(to, db + i, *tLen);
2266
0
  printf("  TPM_RSA_padding_check_PKCS1_OAEP: tLen %d \n", *tLen);
2267
0
  TPM_PrintFourLimit("  TPM_RSA_padding_check_PKCS1_OAEP: to", to, *tLen);
2268
0
  TPM_PrintFour("  TPM_RSA_padding_check_PKCS1_OAEP: pHash", pHash);
2269
0
  TPM_PrintFour("  TPM_RSA_padding_check_PKCS1_OAEP: seed", seed);
2270
0
    }
2271
0
    free(dbMask);   /* @1 */
2272
0
    return rc;
2273
0
}
2274
2275
/* TPM_RSA_exponent_verify() validates the public exponent against a list of legal values.  Some
2276
   values (e.g. even numbers) will have the key generator.
2277
*/
2278
2279
TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent)
2280
0
{
2281
0
    TPM_RESULT rc = 0;
2282
0
    size_t i;
2283
0
    int found;
2284
2285
0
    static const unsigned long legalExponent[] = { 3,5,7,17,257,65537 };
2286
    
2287
0
    for (i = 0, found = FALSE ;
2288
0
   !found && (i < (sizeof(legalExponent) / sizeof (unsigned long))) ;
2289
0
   i++) {
2290
2291
0
  if (exponent == legalExponent[i]) {
2292
0
      found = TRUE;
2293
0
  }
2294
0
    }
2295
0
    if (!found) {
2296
0
  printf("TPM_RSA_exponent_verify: Error, public exponent %lu is illegal\n", exponent );
2297
0
  rc = TPM_BAD_KEY_PROPERTY;
2298
0
    }
2299
0
    return rc;
2300
0
}
2301
2302
/* SHA1 and HMAC test driver
2303
2304
   Returns TPM_FAILEDSELFTEST on error
2305
*/
2306
2307
TPM_RESULT TPM_CryptoTest(void)
2308
0
{
2309
0
    TPM_RESULT  rc = 0;
2310
0
    int   not_equal;
2311
0
    TPM_BOOL  valid;
2312
    
2313
    /* SHA1 */
2314
0
    unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
2315
0
    unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C,
2316
0
             0x3B,0xD2,0x6E,0xBA,0xAE,
2317
0
             0x4A,0xA1,0xF9,0x51,0x29,
2318
0
             0xE5,0xE5,0x46,0x70,0xF1};
2319
0
    TPM_DIGEST  actual;
2320
0
    uint32_t  actual_size;
2321
2322
    /* HMAC */
2323
0
    unsigned char key2[] = {0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,
2324
0
          0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa};
2325
0
    unsigned char expect2[] = {0x12,0x5d,0x73,0x42,0xb9,0xac,0x11,0xcd,0x91,0xa3,
2326
0
             0x9a,0xf4,0x8a,0xa1,0x7b,0x4f,0x63,0xf1,0x75,0xd3};
2327
    /* data  0xdd repeated 50 times */
2328
0
    unsigned char data2[50];
2329
2330
    /* oaep tests */
2331
0
    const unsigned char oaep_pad_str[] = { 'T', 'C', 'P', 'A' };
2332
0
    unsigned char pHash_in[TPM_DIGEST_SIZE];
2333
0
    unsigned char pHash_out[TPM_DIGEST_SIZE];
2334
0
    unsigned char seed_in[TPM_DIGEST_SIZE] = {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
2335
0
                0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
2336
0
                0xf0,0xf1,0xf2,0xf3};
2337
0
    unsigned char seed_out[TPM_DIGEST_SIZE];
2338
0
    unsigned char oaep_in[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
2339
0
    unsigned char oaep_pad[256];
2340
0
    unsigned char oaep_out[8];
2341
0
    uint32_t    oeap_length;
2342
2343
    /* symmetric key with pad */
2344
0
    TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data = NULL; /* opaque structure, freed @7 */
2345
0
    unsigned char clrStream[64];  /* expected */
2346
0
    unsigned char *encStream; /* encrypted */
2347
0
    uint32_t    encSize;
2348
0
    unsigned char *decStream; /* actual */
2349
0
    uint32_t    decSize;
2350
2351
    /* symmetric key ctr and ofb mode */
2352
0
    TPM_SECRET    symKey;
2353
0
    TPM_NONCE   pad;    /* CTR or IV */
2354
0
    TPM_ENCAUTH   symClear;
2355
0
    TPM_ENCAUTH   symEnc;
2356
0
    TPM_ENCAUTH   symDec;
2357
    
2358
    /* RSA encrypt and decrypt, sign and verify */
2359
0
    unsigned char *n;   /* public key - modulus */
2360
0
    unsigned char *p;   /* private key prime */
2361
0
    unsigned char *q;   /* private key prime */
2362
0
    unsigned char *d;   /* private key (private exponent) */
2363
0
    unsigned char encrypt_data[2048/8];   /* encrypted data */
2364
0
    unsigned char signature[2048/8];    /* signature; libtpms added */
2365
2366
0
    printf(" TPM_CryptoTest:\n");
2367
0
    encStream = NULL;   /* freed @1 */
2368
0
    decStream = NULL;   /* freed @2 */
2369
0
    n = NULL;     /* freed @3 */
2370
0
    p = NULL;     /* freed @4 */
2371
0
    q = NULL;     /* freed @5 */
2372
0
    d = NULL;     /* freed @6 */
2373
    
2374
0
    if (rc == 0) {
2375
0
  printf(" TPM_CryptoTest: Test 1 - SHA1 one part\n");
2376
0
  rc = TPM_SHA1(actual,
2377
0
          (uint32_t)sizeof(buffer1) - 1, buffer1,
2378
0
          0, NULL);
2379
0
    }
2380
0
    if (rc == 0) {
2381
0
  not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE);
2382
0
  if (not_equal) {
2383
0
      printf("TPM_CryptoTest: Error in test 1\n");
2384
0
      TPM_PrintFour("\texpect", expect1);
2385
0
      TPM_PrintFour("\tactual", actual);
2386
0
      rc = TPM_FAILEDSELFTEST;
2387
0
  }
2388
0
    }
2389
0
    if (rc == 0) {
2390
0
  printf(" TPM_CryptoTest: Test 2 - SHA1 two parts\n");
2391
0
  rc = TPM_SHA1(actual,
2392
0
          16, buffer1,  /* first 16 */
2393
0
          (uint32_t)sizeof(buffer1) - 17, buffer1 + 16, /* rest */
2394
0
          0, NULL);
2395
0
    }
2396
0
    if (rc == 0) {
2397
0
  not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE);
2398
0
  if (not_equal) {
2399
0
      printf("TPM_CryptoTest: Error in test 2\n");
2400
0
      TPM_PrintFour("\texpect", expect1);
2401
0
      TPM_PrintFour("\tactual", actual);
2402
0
      rc = TPM_FAILEDSELFTEST;
2403
0
  }
2404
0
    }
2405
0
    if (rc == 0) {
2406
0
  printf(" TPM_CryptoTest: Test 3 - HMAC generate - one part\n");
2407
0
  memset(data2, 0xdd, 50);
2408
0
  rc = TPM_HMAC_Generate(actual,
2409
0
             key2,
2410
0
             50, data2,
2411
0
             0, NULL);
2412
0
    }
2413
0
    if (rc == 0) {
2414
0
  not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE);
2415
0
  if (not_equal) {
2416
0
      printf("TPM_CryptoTest: Error in test 3\n");
2417
0
      TPM_PrintFour("\texpect", expect1);
2418
0
      TPM_PrintFour("\tactual", actual);
2419
0
      rc = TPM_FAILEDSELFTEST;
2420
0
  }
2421
0
    }
2422
0
    if (rc == 0) {
2423
0
  printf(" TPM_CryptoTest: Test 4 - HMAC generate - two parts\n");
2424
0
  memset(data2, 0xdd, 50);
2425
0
  rc = TPM_HMAC_Generate(actual,
2426
0
             key2,
2427
0
             20, data2,
2428
0
             30, data2 + 20,
2429
0
             0, NULL);
2430
0
    }
2431
0
    if (rc == 0) {
2432
0
  not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE);
2433
0
  if (not_equal) {
2434
0
      printf("TPM_CryptoTest: Error in test 3\n");
2435
0
      TPM_PrintFour("\texpect", expect2);
2436
0
      TPM_PrintFour("\tactual", actual);
2437
0
      rc = TPM_FAILEDSELFTEST;
2438
0
  }
2439
0
    }
2440
0
    if (rc == 0) {
2441
0
  printf(" TPM_CryptoTest: Test 4 - HMAC check - two parts\n");
2442
0
  memset(data2, 0xdd, 50);
2443
0
  rc = TPM_HMAC_Check(&valid,
2444
0
          expect2,
2445
0
          key2,
2446
0
          20, data2,
2447
0
          30, data2 + 20,
2448
0
          0, NULL);
2449
0
    }
2450
0
    if (rc == 0) {
2451
0
  if (!valid) {
2452
0
      printf("TPM_CryptoTest: Error in test 4\n");
2453
0
      TPM_PrintFour("\texpect", expect1);
2454
0
      TPM_PrintFour("\tactual", actual);
2455
0
      rc = TPM_FAILEDSELFTEST;
2456
0
  }
2457
0
    }
2458
0
    if (rc == 0) {
2459
0
  printf(" TPM_CryptoTest: Test 5 - OAEP add and check\n");
2460
0
  rc = TPM_SHA1(pHash_in,
2461
0
          sizeof(oaep_pad_str), oaep_pad_str,
2462
0
          0, NULL);
2463
0
    }
2464
0
    if (rc == 0) {
2465
0
  rc = TPM_RSA_padding_add_PKCS1_OAEP(oaep_pad, sizeof(oaep_pad),
2466
0
              oaep_in, sizeof(oaep_in),
2467
0
              pHash_in, seed_in);
2468
0
    }
2469
0
    if (rc == 0) {
2470
0
  rc = TPM_RSA_padding_check_PKCS1_OAEP(oaep_out, &oeap_length, sizeof(oaep_out),
2471
0
                oaep_pad, sizeof(oaep_pad),
2472
0
                pHash_out,
2473
0
                seed_out);
2474
0
    }
2475
0
    if (rc == 0) {
2476
0
  if (oeap_length != sizeof(oaep_out)) {
2477
0
      printf("TPM_CryptoTest: Error in test 5, expect length %lu, actual length %u\n",
2478
0
       (unsigned long)sizeof(oaep_out), oeap_length);
2479
0
      rc = TPM_FAILEDSELFTEST;
2480
0
  }
2481
0
    }
2482
0
    if (rc == 0) {
2483
0
  not_equal = memcmp(oaep_in, oaep_out, sizeof(oaep_out));
2484
0
  if (not_equal) {
2485
0
      printf("TPM_CryptoTest: Error in test 5 oaep\n");
2486
0
      TPM_PrintFour("\tin ", oaep_in);
2487
0
      TPM_PrintFour("\tout", oaep_out);
2488
0
      rc = TPM_FAILEDSELFTEST;
2489
0
  }
2490
0
    }
2491
0
    if (rc == 0) {
2492
0
  not_equal = memcmp(pHash_in, pHash_out, sizeof(pHash_in));
2493
0
  if (not_equal) {
2494
0
      printf("TPM_CryptoTest: Error in test 5 pHash\n");
2495
0
      TPM_PrintFour("\tpHash_in ", pHash_in);
2496
0
      TPM_PrintFour("\tpHash_out", pHash_out);
2497
0
      rc = TPM_FAILEDSELFTEST;
2498
0
  }
2499
0
    }
2500
0
    if (rc == 0) {
2501
0
  not_equal = memcmp(seed_in, seed_out, sizeof(seed_in));
2502
0
  if (not_equal) {
2503
0
      printf("TPM_CryptoTest: Error in test 5 seed\n");
2504
0
      TPM_PrintFour("\tseed_in ", seed_in);
2505
0
      TPM_PrintFour("\tseed_out", seed_out);
2506
0
      rc = TPM_FAILEDSELFTEST;
2507
0
  }
2508
0
    }
2509
0
    if (rc == 0) {
2510
0
  printf(" TPM_CryptoTest: Test 6 - Symmetric key with PKCS pad test\n");
2511
  /* allocate memory for the key token */
2512
0
  rc = TPM_SymmetricKeyData_New(&tpm_symmetric_key_data); /* freed @7 */
2513
0
    }
2514
    /* generate a key */
2515
0
    if (rc == 0) {
2516
0
  rc = TPM_SymmetricKeyData_GenerateKey(tpm_symmetric_key_data);
2517
0
    }
2518
    /* generate clear text */
2519
0
    if (rc == 0) {
2520
0
  rc = TPM_Random(clrStream, sizeof(clrStream));
2521
0
    }
2522
    /* symmetric encrypt */
2523
0
    if (rc == 0) {
2524
0
  rc = TPM_SymmetricKeyData_Encrypt(&encStream,   /* output, freed @1 */
2525
0
            &encSize,     /* output */
2526
0
            clrStream,      /* input */
2527
0
            sizeof(clrStream),    /* input */
2528
0
            tpm_symmetric_key_data);  /* key */
2529
0
    }
2530
    /* symmetric decrypt */
2531
0
    if (rc == 0) {
2532
0
  rc = TPM_SymmetricKeyData_Decrypt(&decStream,   /* output, freed by caller */
2533
0
            &decSize,     /* output */
2534
0
            encStream,      /* input */
2535
0
            encSize,      /* input */
2536
0
            tpm_symmetric_key_data);  /* key */
2537
0
    }
2538
    /* symmetric compare */
2539
0
    if (rc == 0) {
2540
0
  if (sizeof(clrStream) != decSize) {
2541
0
      printf("TPM_CryptoTest: Error in test 6, in %lu, out %u\n",
2542
0
       (unsigned long)sizeof(clrStream), decSize);
2543
0
      rc = TPM_FAILEDSELFTEST;
2544
0
  }
2545
0
    }
2546
0
    if (rc == 0) {
2547
0
  not_equal = memcmp(clrStream, decStream, sizeof(clrStream));
2548
0
  if (not_equal) {
2549
0
      printf("TPM_CryptoTest: Error in test 6\n");
2550
0
      TPM_PrintFour("\tclear stream  in", clrStream);
2551
0
      TPM_PrintFour("\tdecrypted stream", decStream);
2552
0
      rc = TPM_FAILEDSELFTEST;
2553
0
  }
2554
0
    }
2555
0
    if (rc == 0) {
2556
0
  printf(" TPM_CryptoTest: Test 7 - Symmetric key with CTR mode\n");
2557
  /* generate a key */
2558
0
  rc = TPM_Random(symKey, TPM_SECRET_SIZE);
2559
0
    }
2560
    /* generate CTR */
2561
0
    if (rc == 0) {
2562
0
  rc = TPM_Random(pad, TPM_NONCE_SIZE);
2563
0
    }
2564
    /* generate clear text */
2565
0
    if (rc == 0) {
2566
0
  rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE);
2567
0
    }
2568
0
    if (rc == 0) {
2569
0
  rc = TPM_SymmetricKeyData_CtrCrypt(symEnc,      /* output */
2570
0
             symClear,      /* input */
2571
0
             TPM_AUTHDATA_SIZE,   /* input */
2572
0
             symKey,      /* in */
2573
0
             TPM_SECRET_SIZE,   /* in */
2574
0
             pad,       /* input */
2575
0
             TPM_NONCE_SIZE);    /* input */
2576
0
    }
2577
0
    if (rc == 0) {
2578
0
  rc = TPM_SymmetricKeyData_CtrCrypt(symDec,      /* output */
2579
0
             symEnc,      /* input */
2580
0
             TPM_AUTHDATA_SIZE,   /* input */
2581
0
             symKey,      /* in */
2582
0
             TPM_SECRET_SIZE,   /* in */
2583
0
             pad,       /* input */
2584
0
             TPM_NONCE_SIZE);    /* input */
2585
0
    }
2586
    /* symmetric compare */
2587
0
    if (rc == 0) {
2588
0
  rc = TPM_Secret_Compare(symDec, symClear);
2589
0
  if (rc != 0) {
2590
0
      printf("TPM_CryptoTest: Error in test 8\n");
2591
0
      TPM_PrintFour("\tclear stream  in", symClear);
2592
0
      TPM_PrintFour("\tdecrypted stream", symDec);
2593
0
  }
2594
0
    }
2595
0
    if (rc == 0) {
2596
0
  printf(" TPM_CryptoTest: Test 8 - Symmetric key with OFB mode\n");
2597
  /* generate a key */
2598
0
  rc = TPM_Random(symKey, TPM_SECRET_SIZE);
2599
0
    }
2600
    /* generate IV */
2601
0
    if (rc == 0) {
2602
0
  rc = TPM_Random(pad, TPM_NONCE_SIZE);
2603
0
    }
2604
    /* generate clear text */
2605
0
    if (rc == 0) {
2606
0
  rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE);
2607
0
    }
2608
0
    if (rc == 0) {
2609
0
  rc = TPM_SymmetricKeyData_OfbCrypt(symEnc,      /* output */
2610
0
             symClear,      /* input */
2611
0
             TPM_AUTHDATA_SIZE,   /* input */
2612
0
             symKey,      /* in */
2613
0
             TPM_SECRET_SIZE,   /* in */
2614
0
             pad,       /* input */
2615
0
             TPM_NONCE_SIZE);    /* input */
2616
0
    }
2617
0
    if (rc == 0) {
2618
0
  rc = TPM_SymmetricKeyData_OfbCrypt(symDec,      /* output */
2619
0
             symEnc,      /* input */
2620
0
             TPM_AUTHDATA_SIZE,   /* input */
2621
0
             symKey,      /* in */
2622
0
             TPM_SECRET_SIZE,   /* in */
2623
0
             pad,       /* input */
2624
0
             TPM_NONCE_SIZE);    /* input */
2625
0
    }
2626
    /* symmetric compare */
2627
0
    if (rc == 0) {
2628
0
  rc = TPM_Secret_Compare(symDec, symClear);
2629
0
  if (rc != 0) {
2630
0
      printf("TPM_CryptoTest: Error in test 8\n");
2631
0
      TPM_PrintFour("\tclear stream  in", symClear);
2632
0
      TPM_PrintFour("\tdecrypted stream", symDec);
2633
0
  }
2634
0
    }
2635
    /* RSA OAEP encrypt and decrypt */
2636
0
    if (rc == 0) {
2637
0
  printf(" TPM_CryptoTest: Test 9 - RSA encrypt with OAEP padding\n");
2638
  /* generate a key */
2639
0
  rc = TPM_RSAGenerateKeyPair(&n,       /* public key - modulus */
2640
0
            &p,       /* private key prime */
2641
0
            &q,       /* private key prime */
2642
0
            &d,       /* private key (private exponent) */
2643
0
            2048,     /* key size in bits */
2644
0
            tpm_default_rsa_exponent, /* public exponent as an array */
2645
0
            3);
2646
0
    }
2647
    /* encrypt */
2648
0
    if (rc == 0) {
2649
0
  rc = TPM_RSAPublicEncrypt(encrypt_data,     /* encrypted data */
2650
0
          sizeof(encrypt_data),   /* size of encrypted data buffer */
2651
0
          TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */
2652
0
          expect1,      /* decrypted data */
2653
0
          sizeof(expect1),
2654
0
          n,        /* public modulus */
2655
0
          2048/8,
2656
0
          tpm_default_rsa_exponent, /* public exponent */
2657
0
          3);
2658
0
    }
2659
0
    if (rc == 0) {
2660
0
  rc = TPM_RSAPrivateDecrypt(actual,      /* decrypted data */
2661
0
           &actual_size,    /* length of data put into
2662
                   decrypt_data */
2663
0
           TPM_DIGEST_SIZE,   /* size of decrypt_data buffer */
2664
0
           TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */
2665
0
           encrypt_data,    /* encrypted data */
2666
0
           sizeof(encrypt_data),
2667
0
           n,       /* public modulus */
2668
0
           2048/8,
2669
0
           tpm_default_rsa_exponent,  /* public exponent */
2670
0
           3,
2671
0
           d,       /* private exponent */
2672
0
           2048/8);
2673
0
    }
2674
0
    if (rc == 0) {
2675
0
  if (actual_size != TPM_DIGEST_SIZE) {
2676
0
      printf("TPM_CryptoTest: Error in test 9, expect length %u, actual length %u\n",
2677
0
       TPM_DIGEST_SIZE, actual_size);
2678
0
      rc = TPM_FAILEDSELFTEST;
2679
0
  }
2680
0
    }
2681
0
    if (rc == 0) {
2682
0
  not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE);
2683
0
  if (not_equal) {
2684
0
      printf("TPM_CryptoTest: Error in test 9\n");
2685
0
      TPM_PrintFour("\tin ", expect1);
2686
0
      TPM_PrintFour("\tout", actual);
2687
0
      rc = TPM_FAILEDSELFTEST;
2688
0
  }
2689
0
    }
2690
    /* RSA PKCS1 pad, encrypt and decrypt */
2691
0
    if (rc == 0) {
2692
0
  printf(" TPM_CryptoTest: Test 10 - RSA encrypt with PKCS padding\n");
2693
  /* encrypt */
2694
0
  rc = TPM_RSAPublicEncrypt(encrypt_data,     /* encrypted data */
2695
0
          sizeof(encrypt_data),   /* size of encrypted data buffer */
2696
0
          TPM_ES_RSAESPKCSv15,   /* TPM_ENC_SCHEME */
2697
0
          expect1,      /* decrypted data */
2698
0
          sizeof(expect1),
2699
0
          n,        /* public modulus */
2700
0
          2048/8,
2701
0
          tpm_default_rsa_exponent, /* public exponent */
2702
0
          3);
2703
0
    }
2704
    /* decrypt */
2705
0
    if (rc == 0) {
2706
0
  rc = TPM_RSAPrivateDecrypt(actual,      /* decrypted data */
2707
0
           &actual_size,    /* length of data put into
2708
                   decrypt_data */
2709
0
           TPM_DIGEST_SIZE,   /* size of decrypt_data buffer */
2710
0
           TPM_ES_RSAESPKCSv15,   /* TPM_ENC_SCHEME */
2711
0
           encrypt_data,    /* encrypted data */
2712
0
           sizeof(encrypt_data),
2713
0
           n,       /* public modulus */
2714
0
           2048/8,
2715
0
           tpm_default_rsa_exponent,  /* public exponent */
2716
0
           3,
2717
0
           d,       /* private exponent */
2718
0
           2048/8);
2719
0
    }
2720
    /* check length after padding removed */
2721
0
    if (rc == 0) {
2722
0
  if (actual_size != TPM_DIGEST_SIZE) {
2723
0
      printf("TPM_CryptoTest: Error in test 10, expect length %u, actual length %u\n",
2724
0
       TPM_DIGEST_SIZE, actual_size);
2725
0
      rc = TPM_FAILEDSELFTEST;
2726
0
  }
2727
0
    }
2728
    /* check data */
2729
0
    if (rc == 0) {
2730
0
  not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE);
2731
0
  if (not_equal) {
2732
0
      printf("TPM_CryptoTest: Error in test 10\n");
2733
0
      TPM_PrintFour("\tin ", expect1);
2734
0
      TPM_PrintFour("\tout", actual);
2735
0
      rc = TPM_FAILEDSELFTEST;
2736
0
  }
2737
0
    }
2738
2739
// libtpms added begin
2740
2741
0
    if (rc == 0) {
2742
0
  printf(" TPM_CryptoTest: Test 11a - RSA sign with PKCS1v15 padding\n");
2743
0
  rc = TPM_RSASign(signature,
2744
0
       &actual_size,
2745
0
       sizeof(signature),
2746
0
       TPM_SS_RSASSAPKCS1v15_SHA1,
2747
0
       expect1,
2748
0
       sizeof(expect1),
2749
0
       n,       /* public modulus */
2750
0
       2048/8,
2751
0
       tpm_default_rsa_exponent,  /* public exponent */
2752
0
       3,
2753
0
       d,       /* private exponent */
2754
0
       2048/8);
2755
0
    }
2756
0
    if (rc == 0) {
2757
0
  rc = TPM_RSAVerify(signature,   /* input signature buffer */
2758
0
         sizeof(signature), /* input, size of signature buffer */
2759
0
         TPM_SS_RSASSAPKCS1v15_SHA1, /* input, type of signature */
2760
0
         expect1,   /* message */
2761
0
         sizeof(expect1), /* message size */
2762
0
         n,     /* public modulus */
2763
0
         2048/8,
2764
0
         tpm_default_rsa_exponent,/* public exponent */
2765
0
         3);
2766
0
    }
2767
2768
#if 0
2769
    /* Verification with TPM_SS_RSASSAPKCS1v15_DER is not supported */
2770
    if (rc == 0) {
2771
  printf(" TPM_CryptoTest: Test 11b - RSA sign with PKCS1v15_DER padding\n");
2772
  rc = TPM_RSASign(signature,
2773
       &actual_size,
2774
       sizeof(signature),
2775
       TPM_SS_RSASSAPKCS1v15_DER,
2776
       expect1,
2777
       sizeof(expect1),
2778
       n,       /* public modulus */
2779
       2048/8,
2780
       tpm_default_rsa_exponent,  /* public exponent */
2781
       3,
2782
       d,       /* private exponent */
2783
       2048/8);
2784
    }
2785
    if (rc == 0) {
2786
  rc = TPM_RSAVerify(signature,   /* input signature buffer */
2787
         sizeof(signature), /* input, size of signature buffer */
2788
         TPM_SS_RSASSAPKCS1v15_DER, /* input, type of signature */
2789
         expect1,   /* message */
2790
         sizeof(expect1), /* message size */
2791
         n,     /* public modulus */
2792
         2048/8,
2793
         tpm_default_rsa_exponent,/* public exponent */
2794
         3);
2795
    }
2796
#endif // libtpms added end
2797
2798
    /* run library specific self tests as required */
2799
0
    if (rc == 0) {
2800
0
  rc = TPM_Crypto_TestSpecific();
2801
0
    }
2802
0
    if (rc != 0) {
2803
0
  rc = TPM_FAILEDSELFTEST;
2804
0
    }
2805
0
    free(encStream);          /* @1 */
2806
0
    free(decStream);          /* @2 */
2807
0
    free(n);            /* @3 */
2808
0
    free(p);            /* @4 */
2809
0
    free(q);            /* @5 */
2810
0
    free(d);            /* @6 */
2811
0
    TPM_SymmetricKeyData_Free(&tpm_symmetric_key_data); /* @7 */
2812
0
    return rc;
2813
0
}
2814
2815
/* 13.5 TPM_Sign rev 111
2816
2817
   The Sign command signs data and returns the resulting digital signature.
2818
2819
   The TPM does not allow TPM_Sign with a TPM_KEY_IDENTITY (AIK) because TPM_Sign can sign arbitrary
2820
   data and could be used to fake a quote.  (This could have been relaxed to allow TPM_Sign with an
2821
   AIK if the signature scheme is _INFO For an _INFO key, the metadata prevents TPM_Sign from faking
2822
   a quote.)
2823
2824
   The TPM MUST support all values of areaToSignSize that are legal for the defined signature scheme
2825
   and key size. The maximum value of areaToSignSize is determined by the defined signature scheme
2826
   and key size.
2827
2828
   In the case of PKCS1v15_SHA1 the areaToSignSize MUST be TPM_DIGEST (the hash size of a sha1
2829
   operation - see 8.5.1 TPM_SS_RSASSAPKCS1v15_SHA1). In the case of PKCS1v15_DER the maximum size
2830
   of areaToSign is k - 11 octets, where k is limited by the key size (see 8.5.2
2831
   TPM_SS_RSASSAPKCS1v15_DER).
2832
*/
2833
2834
TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state,
2835
          TPM_STORE_BUFFER *response,
2836
          TPM_TAG tag,
2837
          uint32_t paramSize,
2838
          TPM_COMMAND_CODE ordinal,
2839
          unsigned char *command,
2840
          TPM_TRANSPORT_INTERNAL *transportInternal)
2841
0
{
2842
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
2843
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
2844
2845
    /* input parameters */
2846
0
    TPM_KEY_HANDLE  keyHandle;  /* The keyHandle identifier of a loaded key that can perform
2847
             digital signatures. */
2848
0
    TPM_SIZED_BUFFER  areaToSign; /* The value to sign */
2849
0
    TPM_AUTHHANDLE  authHandle; /* The authorization handle used for keyHandle authorization
2850
           */
2851
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
2852
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization handle */
2853
0
    TPM_AUTHDATA  privAuth; /* The authorization digest that authorizes the use of
2854
             keyHandle. HMAC key: key.usageAuth */
2855
    /* processing parameters */
2856
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
2857
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
2858
0
    TPM_DIGEST      inParamDigest;
2859
0
    TPM_BOOL      auditStatus  ;    /* audit the ordinal */
2860
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
2861
0
    TPM_BOOL      authHandleValid = FALSE;
2862
0
    TPM_SECRET      *hmacKey;
2863
0
    TPM_KEY     *key = NULL;     /* the key specified by keyHandle */
2864
0
    TPM_RSA_KEY_PARMS   *rsa_key_parms;     /* for key */
2865
0
    TPM_BOOL      parentPCRStatus;
2866
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
2867
0
    TPM_SECRET      *keyUsageAuth;
2868
0
    TPM_SIGN_INFO   tpm_sign_info;
2869
0
    const unsigned char   *S1_data;     /* data to be signed */
2870
0
    uint32_t      S1_size;
2871
0
    TPM_DIGEST      infoDigest;     /* TPM_SIGN_INFO structure digest */
2872
0
    TPM_STORE_BUFFER    sbuffer;
2873
    
2874
    /* output parameters */
2875
0
    uint32_t    outParamStart;  /* starting point of outParam's */
2876
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
2877
0
    TPM_DIGEST    outParamDigest;
2878
0
    TPM_SIZED_BUFFER  sig;    /* The resulting digital signature. */
2879
2880
0
    printf("TPM_Process_Sign: Ordinal Entry\n");
2881
0
    TPM_SizedBuffer_Init(&areaToSign);  /* freed @1 */
2882
0
    TPM_SignInfo_Init(&tpm_sign_info);  /* freed @2 */
2883
0
    TPM_Sbuffer_Init(&sbuffer);   /* freed @3 */
2884
0
    TPM_SizedBuffer_Init(&sig);   /* freed @4 */
2885
    /*
2886
      get inputs
2887
    */
2888
    /*  get keyHandle parameter */
2889
0
    if (returnCode == TPM_SUCCESS) {
2890
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
2891
0
    }
2892
    /* save the starting point of inParam's for authorization and auditing */
2893
0
    inParamStart = command;
2894
0
    if (returnCode == TPM_SUCCESS) {
2895
0
  printf("TPM_Process_Sign: keyHandle %08x\n", keyHandle);
2896
  /* get areaToSignSize and areaToSign parameters */
2897
0
  returnCode = TPM_SizedBuffer_Load(&areaToSign, &command, &paramSize); /* freed @1 */
2898
0
    }
2899
0
    if (returnCode == TPM_SUCCESS) {
2900
0
  printf("TPM_Process_Sign: Signing %u bytes\n", areaToSign.size);
2901
0
    }
2902
    /* save the ending point of inParam's for authorization and auditing */
2903
0
    inParamEnd = command;
2904
    /* digest the input parameters */
2905
0
    if (returnCode == TPM_SUCCESS) {
2906
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
2907
0
            &auditStatus,   /* output */
2908
0
            &transportEncrypt,  /* output */
2909
0
            tpm_state,
2910
0
            tag,
2911
0
            ordinal,
2912
0
            inParamStart,
2913
0
            inParamEnd,
2914
0
            transportInternal);
2915
0
    }
2916
    /* check state */
2917
0
    if (returnCode == TPM_SUCCESS) {
2918
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2919
0
    }
2920
    /* check tag */
2921
0
    if (returnCode == TPM_SUCCESS) {
2922
0
  returnCode = TPM_CheckRequestTag10(tag);
2923
0
    }
2924
    /* get the optional 'below the line' authorization parameters */
2925
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2926
0
  returnCode = TPM_AuthParams_Get(&authHandle,
2927
0
          &authHandleValid,
2928
0
          nonceOdd,
2929
0
          &continueAuthSession,
2930
0
          privAuth,
2931
0
          &command, &paramSize);
2932
0
    }
2933
0
    if (returnCode == TPM_SUCCESS) {
2934
0
  if (paramSize != 0) {
2935
0
      printf("TPM_Process_Sign: Error, command has %u extra bytes\n", paramSize);
2936
0
      returnCode = TPM_BAD_PARAM_SIZE;
2937
0
  }
2938
0
    }
2939
    /* do not terminate sessions if the command did not parse correctly */
2940
0
    if (returnCode != TPM_SUCCESS) {
2941
0
  authHandleValid = FALSE;
2942
0
    }
2943
    /*
2944
      Processing
2945
    */
2946
    /* get the key corresponding to the keyHandle parameter */
2947
0
    if (returnCode == TPM_SUCCESS) {
2948
0
  returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
2949
0
             FALSE,   /* not r/o, used to sign */
2950
0
             FALSE,   /* do not ignore PCRs */
2951
0
             FALSE);  /* cannot use EK */
2952
0
    }
2953
    /* check TPM_AUTH_DATA_USAGE authDataUsage */
2954
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
2955
0
  if (key->authDataUsage != TPM_AUTH_NEVER) {
2956
0
      printf("TPM_Process_Sign: Error, authorization required\n");
2957
0
      returnCode = TPM_AUTHFAIL;
2958
0
  }
2959
0
    }
2960
    /* get keyHandle -> usageAuth */
2961
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2962
0
  returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
2963
0
    }   
2964
    /* get the session data */
2965
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2966
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
2967
0
                &hmacKey,
2968
0
                tpm_state,
2969
0
                authHandle,
2970
0
                TPM_PID_NONE,
2971
0
                TPM_ET_KEYHANDLE,
2972
0
                ordinal,
2973
0
                key,
2974
0
                keyUsageAuth,   /* OIAP */
2975
0
                key->tpm_store_asymkey->pubDataDigest); /* OSAP */
2976
0
    }
2977
    /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */
2978
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2979
0
  returnCode = TPM_Authdata_Check(tpm_state,
2980
0
          *hmacKey,   /* HMAC key */
2981
0
          inParamDigest,
2982
0
          auth_session_data,  /* authorization session */
2983
0
          nonceOdd,   /* Nonce generated by system
2984
                   associated with authHandle */
2985
0
          continueAuthSession,
2986
0
          privAuth);  /* Authorization digest for input */
2987
0
    }
2988
    /* 2. If the areaToSignSize is 0 the TPM returns TPM_BAD_PARAMETER. */
2989
0
    if (returnCode == TPM_SUCCESS) {
2990
0
  if (areaToSign.size == 0) {
2991
0
      printf("TPM_Process_Sign: Error, areaToSignSize is 0\n");
2992
0
      returnCode = TPM_BAD_PARAMETER;
2993
0
  }
2994
0
    }
2995
    /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, if not return
2996
       the error code TPM_INVALID_KEYUSAGE */
2997
0
    if (returnCode == TPM_SUCCESS) {
2998
0
  if ((key->keyUsage != TPM_KEY_SIGNING) && ((key->keyUsage) != TPM_KEY_LEGACY)) {
2999
0
      printf("TPM_Process_Sign: Error, keyUsage %04hx is invalid\n", key->keyUsage);
3000
0
      returnCode = TPM_INVALID_KEYUSAGE;
3001
0
  }
3002
0
    }
3003
    /* 4. The TPM verifies that the signature scheme and key size can properly sign the areaToSign
3004
       parameter.  NOTE Done in 5. - 7.*/
3005
    /* get key -> TPM_RSA_KEY_PARMS */
3006
0
    if (returnCode == TPM_SUCCESS) {
3007
0
  returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms,
3008
0
             &(key->algorithmParms));
3009
0
    }
3010
0
    if (returnCode == TPM_SUCCESS) {
3011
  /* 5. If signature scheme is TPM_SS_RSASSAPKCS1v15_SHA1 then */
3012
0
  if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {
3013
0
      printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1\n");
3014
      /* a. Validate that areaToSignSize is 20 return TPM_BAD_PARAMETER on error */
3015
0
      if (returnCode == TPM_SUCCESS) {
3016
0
    if (areaToSign.size != TPM_DIGEST_SIZE) {
3017
0
        printf("TPM_Process_Sign: Error, areaToSignSize %d should be %u\n",
3018
0
         areaToSign.size, TPM_DIGEST_SIZE);
3019
0
        returnCode = TPM_BAD_PARAMETER;
3020
0
    }
3021
0
      }
3022
      /* b. Set S1 to areaToSign */
3023
0
      if (returnCode == TPM_SUCCESS) {
3024
0
    S1_size = areaToSign.size;
3025
0
    S1_data = areaToSign.buffer;
3026
0
      }
3027
0
  }
3028
  /* 6. Else if signature scheme is TPM_SS_RSASSAPKCS1v15_DER then */
3029
0
  else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_DER) {
3030
0
      printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_DER\n");
3031
      /* a. Validate that areaToSignSize is at least 11 bytes less than the key size, return
3032
         TPM_BAD_PARAMETER on error */
3033
0
      if (returnCode == TPM_SUCCESS) {
3034
0
    if (areaToSign.size > (((rsa_key_parms->keyLength)/CHAR_BIT) - 11)) {
3035
0
        printf("TPM_Process_Sign: Error, areaToSignSize %d should be 11-%u\n",
3036
0
         areaToSign.size, ((rsa_key_parms->keyLength)/CHAR_BIT));
3037
0
        returnCode = TPM_BAD_PARAMETER;
3038
0
    }
3039
0
      } 
3040
      /* b. Set S1 to areaToSign */
3041
0
      if (returnCode == TPM_SUCCESS) {
3042
0
    S1_size = areaToSign.size;
3043
0
    S1_data = areaToSign.buffer;
3044
0
      }
3045
0
  }
3046
  /* 7. else if signature scheme is TPM_SS_RSASSAPKCS1v15_INFO then */
3047
0
  else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) {
3048
0
      printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_INFO\n");
3049
0
      if (returnCode == TPM_SUCCESS) {
3050
    /* a. Create S2 a TPM_SIGN_INFO structure */
3051
    /* NOTE: Done by TPM_SignInfo_Init() */
3052
    /* b. Set S2 -> fixed to "SIGN" */
3053
0
    memcpy(tpm_sign_info.fixed, "SIGN", TPM_SIGN_INFO_FIXED_SIZE);
3054
    /* c.i. If nonceOdd is not present due to an unauthorized command return
3055
       TPM_BAD_PARAMETER */
3056
0
    if (tag == TPM_TAG_RQU_COMMAND) {
3057
0
        printf("TPM_Process_Sign: Error, TPM_SS_RSASSAPKCS1v15_INFO and no auth\n");
3058
0
        returnCode = TPM_BAD_PARAMETER;
3059
0
    }
3060
0
      }
3061
0
      if (returnCode == TPM_SUCCESS) {
3062
    /* c. Set S2 -> replay to nonceOdd */
3063
0
    TPM_Nonce_Copy(tpm_sign_info.replay, nonceOdd);
3064
    /* d. Set S2 -> dataLen to areaToSignSize */
3065
    /* e. Set S2 -> data to areaToSign */
3066
0
    returnCode = TPM_SizedBuffer_Copy(&(tpm_sign_info.data), &areaToSign);
3067
0
      }
3068
      /* f. Set S1 to the SHA-1(S2) */
3069
0
      if (returnCode == TPM_SUCCESS) {
3070
0
    returnCode = TPM_SHA1_GenerateStructure(infoDigest,
3071
0
              &tpm_sign_info,
3072
0
              (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store);
3073
0
    S1_size = TPM_DIGEST_SIZE;
3074
0
    S1_data = infoDigest;
3075
0
      }
3076
0
  }
3077
  /* 8. Else return TPM_INVALID_KEYUSAGE */
3078
0
  else {
3079
0
      printf("TPM_Process_Sign: Error, sigScheme %04hx\n", key->algorithmParms.sigScheme);
3080
0
      returnCode = TPM_INVALID_KEYUSAGE;
3081
0
  }
3082
0
    }
3083
    /* 9. The TPM computes the signature, sig, using the key referenced by keyHandle using S1 as the
3084
       value to sign */
3085
0
    if (returnCode == TPM_SUCCESS) {
3086
0
  TPM_PrintAll("TPM_Process_Sign: Digest to sign", S1_data, S1_size);
3087
0
  returnCode = TPM_RSASignToSizedBuffer(&sig,   /* signature */
3088
0
                S1_data,    /* message */
3089
0
                S1_size,    /* message size */
3090
0
                key);   /* input, signing key */
3091
0
    }
3092
    /*
3093
      response
3094
    */
3095
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3096
0
    if (rcf == 0) {
3097
0
  printf("TPM_Process_Sign: Ordinal returnCode %08x %u\n",
3098
0
         returnCode, returnCode);
3099
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3100
0
    }
3101
    /* success response, append the rest of the parameters.  */
3102
0
    if (rcf == 0) {
3103
0
  if (returnCode == TPM_SUCCESS) {
3104
      /* checkpoint the beginning of the outParam's */
3105
0
      outParamStart = response->buffer_current - response->buffer;
3106
      /* 10. Return the computed signature in Sig */
3107
0
      returnCode = TPM_SizedBuffer_Store(response, &sig);
3108
      /* checkpoint the end of the outParam's */
3109
0
      outParamEnd = response->buffer_current - response->buffer;
3110
0
  }
3111
  /* digest the above the line output parameters */
3112
0
  if (returnCode == TPM_SUCCESS) {
3113
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3114
0
                 auditStatus, /* input audit status */
3115
0
                 transportEncrypt,
3116
0
                 tag,     
3117
0
                 returnCode,
3118
0
                 ordinal,   /* command ordinal */
3119
0
                 response->buffer + outParamStart,  /* start */
3120
0
                 outParamEnd - outParamStart);  /* length */
3121
0
  }
3122
  /* calculate and set the below the line parameters */
3123
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3124
0
      returnCode = TPM_AuthParams_Set(response,
3125
0
              *hmacKey, /* owner HMAC key */
3126
0
              auth_session_data,
3127
0
              outParamDigest,
3128
0
              nonceOdd,
3129
0
              continueAuthSession);
3130
0
  }
3131
  /* audit if required */
3132
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3133
0
      returnCode = TPM_ProcessAudit(tpm_state,
3134
0
            transportEncrypt,
3135
0
            inParamDigest,
3136
0
            outParamDigest,
3137
0
            ordinal);
3138
0
  }
3139
  /* adjust the initial response */
3140
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3141
0
    }
3142
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
3143
0
    if (((rcf != 0) ||
3144
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
3145
0
   !continueAuthSession) &&
3146
0
  authHandleValid) {
3147
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
3148
0
    }
3149
    /*
3150
      cleanup
3151
    */
3152
0
    TPM_SizedBuffer_Delete(&areaToSign);  /* @1 */
3153
0
    TPM_SignInfo_Delete(&tpm_sign_info);  /* @2 */
3154
0
    TPM_Sbuffer_Delete(&sbuffer);   /* @3 */
3155
0
    TPM_SizedBuffer_Delete(&sig);   /* @4 */
3156
0
    return rcf;
3157
0
}
3158
3159
/* 13.1 TPM_SHA1Start rev 96
3160
3161
   This capability starts the process of calculating a SHA-1 digest.
3162
3163
   The exposure of the SHA-1 processing is a convenience to platforms in a mode that do not have
3164
   sufficient memory to perform SHA-1 themselves. As such the use of SHA-1 is restrictive on the
3165
   TPM.
3166
3167
   The TPM may not allow any other types of processing during the execution of a SHA-1
3168
   session. There is only one SHA-1 session active on a TPM.  The exclusivity of a SHA-1 
3169
   context is due to the relatively large volatile buffer it requires in order to hold the 
3170
   intermediate results between the SHA-1 context commands.  This buffer can be in 
3171
   contradiction to other command needs.
3172
3173
   After the execution of SHA1Start, and prior to SHA1End, the receipt of any command other than
3174
   SHA1Update will cause the invalidation of the SHA-1 session.
3175
*/
3176
3177
TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state,
3178
         TPM_STORE_BUFFER *response,
3179
         TPM_TAG tag,
3180
         uint32_t paramSize,
3181
         TPM_COMMAND_CODE ordinal,
3182
         unsigned char *command,
3183
         TPM_TRANSPORT_INTERNAL *transportInternal)
3184
0
{
3185
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3186
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3187
3188
    /* input parameters  - none */
3189
3190
    /* processing parameters */
3191
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3192
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3193
0
    TPM_DIGEST      inParamDigest;
3194
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3195
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3196
3197
    /* output parameters */
3198
0
    uint32_t    outParamStart;      /* starting point of outParam's */
3199
0
    uint32_t    outParamEnd;      /* ending point of outParam's */
3200
0
    TPM_DIGEST    outParamDigest;
3201
0
    uint32_t maxNumBytes = TPM_SHA1_MAXNUMBYTES; /* Maximum number of bytes that can be sent
3202
                 to TPM_SHA1Update. Must be a multiple of
3203
                 64 bytes. */
3204
3205
0
    printf("TPM_Process_SHA1Start: Ordinal Entry\n");
3206
    /*
3207
      get inputs
3208
    */
3209
    /* save the starting point of inParam's for authorization and auditing */
3210
0
    inParamStart = command;
3211
    /* save the ending point of inParam's for authorization and auditing */
3212
0
    inParamEnd = command;
3213
    /* digest the input parameters */
3214
0
    if (returnCode == TPM_SUCCESS) {
3215
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3216
0
            &auditStatus,   /* output */
3217
0
            &transportEncrypt,  /* output */
3218
0
            tpm_state,
3219
0
            tag,
3220
0
            ordinal,
3221
0
            inParamStart,
3222
0
            inParamEnd,
3223
0
            transportInternal);
3224
0
    }
3225
    /* check state */
3226
0
    if (returnCode == TPM_SUCCESS) {
3227
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
3228
0
                 TPM_CHECK_NO_LOCKOUT));
3229
0
    }
3230
    /* check tag */
3231
0
    if (returnCode == TPM_SUCCESS) {
3232
0
  returnCode = TPM_CheckRequestTag0(tag);
3233
0
    }
3234
0
    if (returnCode == TPM_SUCCESS) {
3235
0
  if (paramSize != 0) {
3236
0
      printf("TPM_Process_SHA1Start: Error, command has %u extra bytes\n",
3237
0
       paramSize);
3238
0
      returnCode = TPM_BAD_PARAM_SIZE;
3239
0
  }
3240
0
    }
3241
    /*
3242
      Processing
3243
    */
3244
    /* This capability prepares the TPM for a subsequent TPM_SHA1Update, TPM_SHA1Complete or
3245
       TPM_SHA1CompleteExtend command. The capability SHALL open a thread that calculates a SHA-1
3246
       digest.
3247
    */
3248
0
    if (returnCode == TPM_SUCCESS) {
3249
0
  if (transportInternal == NULL) {
3250
0
      tpm_state->transportHandle = 0; /* SHA-1 thread not within transport */
3251
0
  }
3252
0
  else {
3253
0
      tpm_state->transportHandle = transportInternal->transHandle; /* SHA-1 thread within
3254
                      transport */
3255
0
  }
3256
0
  returnCode = TPM_SHA1InitCmd(&(tpm_state->sha1_context));
3257
0
    }
3258
    /*
3259
      response
3260
    */
3261
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3262
0
    if (rcf == 0) {
3263
0
  printf("TPM_Process_SHA1Start: Ordinal returnCode %08x %u\n",
3264
0
         returnCode, returnCode);
3265
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3266
0
    }
3267
    /* success response, append the rest of the parameters.  */
3268
0
    if (rcf == 0) {
3269
0
  if (returnCode == TPM_SUCCESS) {
3270
      /* checkpoint the beginning of the outParam's */
3271
0
      outParamStart = response->buffer_current - response->buffer;
3272
      /* append maxNumBytes */
3273
0
      returnCode = TPM_Sbuffer_Append32(response, maxNumBytes);
3274
      /* checkpoint the end of the outParam's */
3275
0
      outParamEnd = response->buffer_current - response->buffer;
3276
0
  }
3277
  /* digest the above the line output parameters */
3278
0
  if (returnCode == TPM_SUCCESS) {
3279
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3280
0
                 auditStatus, /* input audit status */
3281
0
                 transportEncrypt,
3282
0
                 tag,     
3283
0
                 returnCode,
3284
0
                 ordinal,   /* command ordinal */
3285
0
                 response->buffer + outParamStart,  /* start */
3286
0
                 outParamEnd - outParamStart);  /* length */
3287
0
  }
3288
  /* audit if required */
3289
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3290
0
      returnCode = TPM_ProcessAudit(tpm_state,
3291
0
            transportEncrypt,
3292
0
            inParamDigest,
3293
0
            outParamDigest,
3294
0
            ordinal);
3295
0
  }
3296
  /* adjust the initial response */
3297
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3298
0
    }
3299
0
    return rcf;
3300
0
}
3301
3302
/* 13.2 TPM_SHA1Update rev 114
3303
3304
   This capability inputs complete blocks of data into a pending SHA-1 digest. At the end of the
3305
   process, the digest remains pending.
3306
*/
3307
3308
TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state,
3309
          TPM_STORE_BUFFER *response,
3310
          TPM_TAG tag,
3311
          uint32_t paramSize,
3312
          TPM_COMMAND_CODE ordinal,
3313
          unsigned char *command,
3314
          TPM_TRANSPORT_INTERNAL *transportInternal)
3315
0
{
3316
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3317
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3318
3319
    /* input parameters */
3320
0
    TPM_SIZED_BUFFER  hashData; /* Bytes to be hashed */
3321
3322
    /* processing parameters */
3323
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3324
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3325
0
    TPM_DIGEST      inParamDigest;
3326
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3327
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3328
3329
    /* output parameters */
3330
0
    uint32_t    outParamStart;  /* starting point of outParam's */
3331
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
3332
0
    TPM_DIGEST    outParamDigest;
3333
3334
0
    printf("TPM_Process_SHA1Update: Ordinal Entry\n");
3335
0
    TPM_SizedBuffer_Init(&hashData);  /* freed @1 */
3336
    /*
3337
      get inputs
3338
    */
3339
    /* save the starting point of inParam's for authorization and auditing */
3340
0
    inParamStart = command;
3341
    /* load hashData */
3342
0
    if (returnCode == TPM_SUCCESS) {
3343
0
  returnCode = TPM_SizedBuffer_Load(&hashData, &command, &paramSize);
3344
0
    }
3345
    /* save the ending point of inParam's for authorization and auditing */
3346
0
    inParamEnd = command;
3347
    /* digest the input parameters */
3348
0
    if (returnCode == TPM_SUCCESS) {
3349
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3350
0
            &auditStatus,   /* output */
3351
0
            &transportEncrypt,  /* output */
3352
0
            tpm_state,
3353
0
            tag,
3354
0
            ordinal,
3355
0
            inParamStart,
3356
0
            inParamEnd,
3357
0
            transportInternal);
3358
0
    }
3359
    /* check state */
3360
0
    if (returnCode == TPM_SUCCESS) {
3361
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
3362
0
                 TPM_CHECK_NO_LOCKOUT));
3363
0
    }
3364
    /* check tag */
3365
0
    if (returnCode == TPM_SUCCESS) {
3366
0
  returnCode = TPM_CheckRequestTag0(tag);
3367
0
    }
3368
0
    if (returnCode == TPM_SUCCESS) {
3369
0
  if (paramSize != 0) {
3370
0
      printf("TPM_Process_SHA1Update: Error, command has %u extra bytes\n",
3371
0
       paramSize);
3372
0
      returnCode = TPM_BAD_PARAM_SIZE;
3373
0
  }
3374
0
    }
3375
    /*
3376
      Processing
3377
    */
3378
    /* This command SHALL incorporate complete blocks of data into the digest of an existing SHA-1
3379
       thread. Only integral numbers of complete blocks (64 bytes each) can be processed.
3380
    */
3381
    /* 1. If there is no existing SHA-1 thread, return TPM_SHA_THREAD */
3382
0
    if (returnCode == TPM_SUCCESS) {
3383
0
  if (tpm_state->sha1_context == NULL) {
3384
0
      printf("TPM_Process_SHA1Update: Error, no existing SHA1 thread\n");
3385
0
      returnCode = TPM_SHA_THREAD;
3386
0
  }
3387
0
    }
3388
    /* 2. If numBytes is not a multiple of 64 */
3389
0
    if (returnCode == TPM_SUCCESS) {
3390
0
  printf("TPM_Process_SHA1Update: numBytes %u bytes\n", hashData.size);
3391
0
  if ((hashData.size % 64) != 0) {
3392
0
      printf("TPM_Process_SHA1Update: Error, numBytes not integral number of blocks\n");
3393
      /* a. Return TPM_SHA_ERROR */
3394
0
      returnCode = TPM_SHA_ERROR;
3395
      /* b. The TPM MAY terminate the SHA-1 thread */
3396
0
      TPM_SHA1Delete(&(tpm_state->sha1_context));
3397
0
  }
3398
0
    }
3399
    /* 3. If numBytes is greater than maxNumBytes returned by TPM_SHA1Start */
3400
0
    if (returnCode == TPM_SUCCESS) {
3401
0
  if (hashData.size > TPM_SHA1_MAXNUMBYTES) {
3402
      /* a. Return TPM_SHA_ERROR */
3403
0
      returnCode = TPM_SHA_ERROR;
3404
      /* b. The TPM MAY terminate the SHA-1 thread */
3405
0
      TPM_SHA1Delete(&(tpm_state->sha1_context));
3406
0
  }
3407
0
    }
3408
    /* 4. Incorporate hashData into the digest of the existing SHA-1 thread. */
3409
0
    if (returnCode == TPM_SUCCESS) {
3410
0
  returnCode = TPM_SHA1UpdateCmd(tpm_state->sha1_context, hashData.buffer, hashData.size);
3411
0
    }
3412
    /*
3413
      response
3414
    */
3415
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3416
0
    if (rcf == 0) {
3417
0
  printf("TPM_Process_SHA1Update: Ordinal returnCode %08x %u\n",
3418
0
         returnCode, returnCode);
3419
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3420
0
    }
3421
    /* success response, append the rest of the parameters.  */
3422
0
    if (rcf == 0) {
3423
0
  if (returnCode == TPM_SUCCESS) {
3424
      /* checkpoint the beginning of the outParam's */
3425
0
      outParamStart = response->buffer_current - response->buffer;
3426
      /* checkpoint the end of the outParam's */
3427
0
      outParamEnd = response->buffer_current - response->buffer;
3428
0
  }
3429
  /* digest the above the line output parameters */
3430
0
  if (returnCode == TPM_SUCCESS) {
3431
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3432
0
                 auditStatus, /* input audit status */
3433
0
                 transportEncrypt,
3434
0
                 tag,     
3435
0
                 returnCode,
3436
0
                 ordinal,   /* command ordinal */
3437
0
                 response->buffer + outParamStart,  /* start */
3438
0
                 outParamEnd - outParamStart);  /* length */
3439
0
  }
3440
  /* audit if required */
3441
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3442
0
      returnCode = TPM_ProcessAudit(tpm_state,
3443
0
            transportEncrypt,
3444
0
            inParamDigest,
3445
0
            outParamDigest,
3446
0
            ordinal);
3447
0
  }
3448
  /* adjust the initial response */
3449
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3450
0
    }
3451
    /*
3452
      cleanup
3453
    */
3454
0
    TPM_SizedBuffer_Delete(&hashData);  /* @1 */
3455
0
    return rcf;
3456
0
}
3457
3458
/* 13.3 TPM_SHA1Complete rev 87
3459
3460
   This capability terminates a pending SHA-1 calculation.
3461
*/
3462
3463
TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state,
3464
            TPM_STORE_BUFFER *response,
3465
            TPM_TAG tag,
3466
            uint32_t paramSize,
3467
            TPM_COMMAND_CODE ordinal,
3468
            unsigned char *command,
3469
            TPM_TRANSPORT_INTERNAL *transportInternal)
3470
0
{
3471
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3472
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3473
3474
    /* input parameters */
3475
0
    TPM_SIZED_BUFFER  hashData; /* Final bytes to be hashed */
3476
3477
    /* processing parameters */
3478
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3479
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3480
0
    TPM_DIGEST      inParamDigest;
3481
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3482
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3483
3484
    /* output parameters */
3485
0
    uint32_t    outParamStart;  /* starting point of outParam's */
3486
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
3487
0
    TPM_DIGEST    outParamDigest;
3488
0
    TPM_DIGEST    hashValue;  /* The output of the SHA-1 hash. */
3489
0
    TPM_SizedBuffer_Init(&hashData);  /* freed @1 */
3490
3491
0
    printf("TPM_Process_SHA1Complete: Ordinal Entry\n");
3492
    /*
3493
      get inputs
3494
    */
3495
    /* save the starting point of inParam's for authorization and auditing */
3496
0
    inParamStart = command;
3497
    /* load hashData */
3498
0
    if (returnCode == TPM_SUCCESS) {
3499
0
  returnCode = TPM_SizedBuffer_Load(&hashData, &command, &paramSize);
3500
0
    }
3501
    /* save the ending point of inParam's for authorization and auditing */
3502
0
    inParamEnd = command;
3503
    /* digest the input parameters */
3504
0
    if (returnCode == TPM_SUCCESS) {
3505
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3506
0
            &auditStatus,   /* output */
3507
0
            &transportEncrypt,  /* output */
3508
0
            tpm_state,
3509
0
            tag,
3510
0
            ordinal,
3511
0
            inParamStart,
3512
0
            inParamEnd,
3513
0
            transportInternal);
3514
0
    }
3515
    /* check state */
3516
0
    if (returnCode == TPM_SUCCESS) {
3517
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
3518
0
                 TPM_CHECK_NO_LOCKOUT));
3519
0
    }
3520
    /* check tag */
3521
0
    if (returnCode == TPM_SUCCESS) {
3522
0
  returnCode = TPM_CheckRequestTag0(tag);
3523
0
    }
3524
0
    if (returnCode == TPM_SUCCESS) {
3525
0
  if (paramSize != 0) {
3526
0
      printf("TPM_Process_SHA1Complete: Error, command has %u extra bytes\n",
3527
0
       paramSize);
3528
0
      returnCode = TPM_BAD_PARAM_SIZE;
3529
0
  }
3530
0
    }
3531
    /*
3532
      Processing
3533
    */
3534
    /* This command SHALL incorporate a partial or complete block of data into the digest of an
3535
       existing SHA-1 thread, and terminate that thread. hashDataSize MAY have values in the range
3536
       of 0 through 64, inclusive.  If the SHA-1 thread has received no bytes the TPM SHALL
3537
       calculate the SHA-1 of the empty buffer.
3538
    */
3539
0
    if (returnCode == TPM_SUCCESS) {
3540
0
  returnCode = TPM_SHA1CompleteCommon(hashValue,
3541
0
              &(tpm_state->sha1_context),
3542
0
              &hashData);
3543
0
    }
3544
    /*
3545
      response
3546
    */
3547
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3548
0
    if (rcf == 0) {
3549
0
  printf("TPM_Process_SHA1Complete: Ordinal returnCode %08x %u\n",
3550
0
         returnCode, returnCode);
3551
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3552
0
    }
3553
    /* success response, append the rest of the parameters.  */
3554
0
    if (rcf == 0) {
3555
0
  if (returnCode == TPM_SUCCESS) {
3556
      /* checkpoint the beginning of the outParam's */
3557
0
      outParamStart = response->buffer_current - response->buffer;
3558
      /* append hashValue */
3559
0
      returnCode = TPM_Digest_Store(response, hashValue);
3560
      /* checkpoint the end of the outParam's */
3561
0
      outParamEnd = response->buffer_current - response->buffer;
3562
0
  }
3563
  /* digest the above the line output parameters */
3564
0
  if (returnCode == TPM_SUCCESS) {
3565
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3566
0
                 auditStatus, /* input audit status */
3567
0
                 transportEncrypt,
3568
0
                 tag,     
3569
0
                 returnCode,
3570
0
                 ordinal,   /* command ordinal */
3571
0
                 response->buffer + outParamStart,  /* start */
3572
0
                 outParamEnd - outParamStart);  /* length */
3573
0
  }
3574
  /* audit if required */
3575
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3576
0
      returnCode = TPM_ProcessAudit(tpm_state,
3577
0
            transportEncrypt,
3578
0
            inParamDigest,
3579
0
            outParamDigest,
3580
0
            ordinal);
3581
0
  }
3582
  /* adjust the initial response */
3583
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3584
0
    }
3585
    /*
3586
      cleanup
3587
    */
3588
0
    TPM_SizedBuffer_Delete(&hashData);  /* @1 */
3589
0
    return rcf;
3590
0
}
3591
3592
/* 13.4 TPM_SHA1CompleteExtend rev 109
3593
3594
   This capability terminates a pending SHA-1 calculation and EXTENDS the result into a Platform
3595
   Configuration Register using a SHA-1 hash process.
3596
3597
   This command is designed to complete a hash sequence and extend a PCR in memory-less
3598
   environments.
3599
3600
   This command SHALL incorporate a partial or complete block of data into the digest of an existing
3601
   SHA-1 thread, EXTEND the resultant digest into a PCR, and terminate the thread. hashDataSize MAY
3602
   have values in the range of 0 through 64, inclusive.
3603
*/
3604
3605
TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state,
3606
            TPM_STORE_BUFFER *response,
3607
            TPM_TAG tag,
3608
            uint32_t paramSize,
3609
            TPM_COMMAND_CODE ordinal,
3610
            unsigned char *command,
3611
            TPM_TRANSPORT_INTERNAL *transportInternal)
3612
0
{
3613
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3614
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3615
3616
    /* input parameters */
3617
0
    TPM_PCRINDEX  pcrNum;   /* Index of the PCR to be modified */
3618
0
    TPM_SIZED_BUFFER  hashData; /* Final bytes to be hashed */
3619
3620
    /* processing parameters */
3621
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3622
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3623
0
    TPM_DIGEST      inParamDigest;
3624
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3625
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3626
3627
    /* output parameters */
3628
0
    uint32_t    outParamStart;  /* starting point of outParam's */
3629
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
3630
0
    TPM_DIGEST    outParamDigest;
3631
0
    TPM_DIGEST    h1HashValue;  /* The output of the SHA-1 hash. */
3632
0
    TPM_PCRVALUE  outDigest;  /* The PCR value after execution of the command. */
3633
    
3634
0
    printf("TPM_Process_SHA1CompleteExtend: Ordinal Entry\n");
3635
0
    TPM_SizedBuffer_Init(&hashData);  /* freed @1 */
3636
    /*
3637
      get inputs
3638
    */
3639
    /* save the starting point of inParam's for authorization and auditing */
3640
0
    inParamStart = command;
3641
    /* get pcrNum */ 
3642
0
    if (returnCode == TPM_SUCCESS) {
3643
0
  returnCode = TPM_Load32(&pcrNum, &command, &paramSize);
3644
0
    }
3645
    /* get hashData */
3646
0
    if (returnCode == TPM_SUCCESS) {
3647
0
  printf("TPM_Process_SHA1CompleteExtend: pcrNum %u\n", pcrNum);
3648
0
  returnCode = TPM_SizedBuffer_Load(&hashData, &command, &paramSize);
3649
0
    }
3650
    /* save the ending point of inParam's for authorization and auditing */
3651
0
    inParamEnd = command;
3652
    /* digest the input parameters */
3653
0
    if (returnCode == TPM_SUCCESS) {
3654
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3655
0
            &auditStatus,   /* output */
3656
0
            &transportEncrypt,  /* output */
3657
0
            tpm_state,
3658
0
            tag,
3659
0
            ordinal,
3660
0
            inParamStart,
3661
0
            inParamEnd,
3662
0
            transportInternal);
3663
0
    }
3664
    /* check state */
3665
0
    if (returnCode == TPM_SUCCESS) {
3666
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
3667
0
                 TPM_CHECK_NO_LOCKOUT));
3668
0
    }
3669
    /* check tag */
3670
0
    if (returnCode == TPM_SUCCESS) {
3671
0
  returnCode = TPM_CheckRequestTag0(tag);
3672
0
    }
3673
0
    if (returnCode == TPM_SUCCESS) {
3674
0
  if (paramSize != 0) {
3675
0
      printf("TPM_Process_SHA1CompleteExtend: Error, command has %u extra bytes\n",
3676
0
       paramSize);
3677
0
      returnCode = TPM_BAD_PARAM_SIZE;
3678
0
  }
3679
0
    }
3680
    /*
3681
      Processing
3682
    */
3683
    /* 1. 1.Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */
3684
    /* 2. Map V1 to TPM_STANY_DATA */
3685
    /* 3. Map L1 to V1 -> localityModifier */
3686
    /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> pcrAttrib
3687
    [PCRIndex]. pcrExtendLocal, return TPM_BAD_LOCALITY */
3688
    /* NOTE Done in TPM_ExtendCommon() */
3689
    /* 5. Create H1 the TPM_DIGEST of the SHA-1 session ensuring that hashData, if any, is  */
3690
    /* added to the SHA-1 session */
3691
0
    if (returnCode == TPM_SUCCESS) {
3692
0
  returnCode = TPM_SHA1CompleteCommon(h1HashValue,
3693
0
              &(tpm_state->sha1_context),
3694
0
              &hashData);
3695
0
    }
3696
    /* 6. Perform the actions of TPM_Extend using H1 as the data and pcrNum as the PCR to extend */
3697
0
    if (returnCode == TPM_SUCCESS) {
3698
0
  returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, h1HashValue);
3699
0
    }
3700
    /*
3701
      response
3702
    */
3703
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3704
0
    if (rcf == 0) {
3705
0
  printf("TPM_Process_SHA1CompleteExtend: Ordinal returnCode %08x %u\n",
3706
0
         returnCode, returnCode);
3707
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3708
0
    }
3709
    /* success response, append the rest of the parameters.  */
3710
0
    if (rcf == 0) {
3711
0
  if (returnCode == TPM_SUCCESS) {
3712
      /* checkpoint the beginning of the outParam's */
3713
0
      outParamStart = response->buffer_current - response->buffer;
3714
      /* append hashValue */
3715
0
      returnCode = TPM_Digest_Store(response, h1HashValue);
3716
0
  }
3717
  /* append outDigest */
3718
0
  if (returnCode == TPM_SUCCESS) {
3719
0
      returnCode = TPM_Digest_Store(response, outDigest);
3720
      /* checkpoint the end of the outParam's */
3721
0
      outParamEnd = response->buffer_current - response->buffer;
3722
0
  }
3723
  /* digest the above the line output parameters */
3724
0
  if (returnCode == TPM_SUCCESS) {
3725
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3726
0
                 auditStatus, /* input audit status */
3727
0
                 transportEncrypt,
3728
0
                 tag,     
3729
0
                 returnCode,
3730
0
                 ordinal,   /* command ordinal */
3731
0
                 response->buffer + outParamStart,  /* start */
3732
0
                 outParamEnd - outParamStart);  /* length */
3733
0
  }
3734
  /* audit if required */
3735
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3736
0
      returnCode = TPM_ProcessAudit(tpm_state,
3737
0
            transportEncrypt,
3738
0
            inParamDigest,
3739
0
            outParamDigest,
3740
0
            ordinal);
3741
0
  }
3742
  /* adjust the initial response */
3743
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3744
0
    }
3745
    /*
3746
      cleanup
3747
    */
3748
0
    TPM_SizedBuffer_Delete(&hashData);  /* @1 */
3749
0
    return rcf;
3750
0
}
3751
3752
/* TPM_SHA1CompleteCommon() is common code for TPM_Process_SHA1Complete() and
3753
   TPM_Process_SHA1CompleteExtend()
3754
*/
3755
3756
TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue,   /* output: digest */
3757
          void **sha1_context,    /* IO: SHA1 context */
3758
          TPM_SIZED_BUFFER *hashData) /* final data to be hashed */
3759
0
{
3760
0
    TPM_RESULT  rc = 0;
3761
3762
    /* The TPM specification says that the last data chunk must be 0-64 bytes */
3763
0
    printf("TPM_SHA1CompleteCommon: %u bytes\n", hashData->size);
3764
0
    if (rc == 0) {
3765
0
  if (hashData->size > 64) {
3766
0
      printf("TPM_SHA1CompleteCommon: Error, hashDataSize %u not 0-64\n",
3767
0
       hashData->size);
3768
0
      rc = TPM_SHA_ERROR;
3769
0
  }
3770
0
    }
3771
    /* cannot call SHA1Complete() before SHA1Start() */
3772
0
    if (rc == 0) {
3773
0
  if (*sha1_context == NULL) {
3774
0
      printf("TPM_SHA1CompleteCommon: Error, no existing SHA1 thread\n");
3775
0
      rc = TPM_SHA_THREAD;
3776
0
  }
3777
0
    }
3778
0
    if ((rc == 0) && (hashData->size != 0)) {
3779
0
  rc = TPM_SHA1UpdateCmd(*sha1_context, hashData->buffer, hashData->size);
3780
0
    }
3781
0
    if (rc == 0) {
3782
0
  rc = TPM_SHA1FinalCmd(hashValue, *sha1_context);
3783
0
    }
3784
    /* the SHA1 thread should be terminated even if there is an error */
3785
0
    TPM_SHA1Delete(sha1_context);
3786
0
    return rc;
3787
0
}
3788
3789
/* 13.6 TPM_GetRandom rev 87
3790
3791
   GetRandom returns the next bytesRequested bytes from the random number generator to the caller.
3792
3793
   It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG
3794
   bytes such that the frequency of bytesRequested being more than the number of bytes available is
3795
   an infrequent occurrence.
3796
*/
3797
3798
TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state,
3799
         TPM_STORE_BUFFER *response,
3800
         TPM_TAG tag,
3801
         uint32_t paramSize,
3802
         TPM_COMMAND_CODE ordinal,
3803
         unsigned char *command,
3804
         TPM_TRANSPORT_INTERNAL *transportInternal)
3805
0
{
3806
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3807
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3808
3809
    /* input parameters */
3810
0
    uint32_t    bytesRequested; /* Number of bytes to return */
3811
3812
    /* processing parameters */
3813
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3814
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3815
0
    TPM_DIGEST      inParamDigest;
3816
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3817
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3818
3819
    /* output parameters */
3820
0
    uint32_t    outParamStart;  /* starting point of outParam's */
3821
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
3822
0
    TPM_DIGEST    outParamDigest;
3823
0
    TPM_SIZED_BUFFER  randomBytes;  /* The returned bytes */
3824
3825
0
    printf("TPM_Process_GetRandom: Ordinal Entry\n");
3826
0
    TPM_SizedBuffer_Init(&randomBytes); /* freed @1 */
3827
    /*
3828
      get inputs
3829
    */
3830
    /* save the starting point of inParam's for authorization and auditing */
3831
0
    inParamStart = command;
3832
    /* get bytesRequested parameter */
3833
0
    if (returnCode == TPM_SUCCESS) {
3834
0
  returnCode = TPM_Load32(&bytesRequested, &command, &paramSize);
3835
0
    }
3836
    /* save the ending point of inParam's for authorization and auditing */
3837
0
    inParamEnd = command;
3838
    /* digest the input parameters */
3839
0
    if (returnCode == TPM_SUCCESS) {
3840
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3841
0
            &auditStatus,   /* output */
3842
0
            &transportEncrypt,  /* output */
3843
0
            tpm_state,
3844
0
            tag,
3845
0
            ordinal,
3846
0
            inParamStart,
3847
0
            inParamEnd,
3848
0
            transportInternal);
3849
0
    }
3850
    /* check state */
3851
0
    if (returnCode == TPM_SUCCESS) {
3852
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
3853
0
    }
3854
    /* check tag */
3855
0
    if (returnCode == TPM_SUCCESS) {
3856
0
  returnCode = TPM_CheckRequestTag0(tag);
3857
0
    }
3858
0
    if (returnCode == TPM_SUCCESS) {
3859
0
  if (paramSize != 0) {
3860
0
      printf("TPM_Process_GetRandom: Error, command has %u extra bytes\n",
3861
0
       paramSize);
3862
0
      returnCode = TPM_BAD_PARAM_SIZE;
3863
0
  }
3864
0
    }
3865
    /*
3866
      Processing
3867
    */
3868
    /* 1. The TPM determines if amount bytesRequested is available from the TPM. */
3869
0
    if (returnCode == TPM_SUCCESS) {
3870
0
  printf("TPM_Process_GetRandom: bytesRequested %u\n", bytesRequested);
3871
0
  if (bytesRequested > TPM_RANDOM_MAX) {
3872
0
      bytesRequested = TPM_RANDOM_MAX;
3873
0
      printf("TPM_Process_GetRandom: bytes available %u\n", bytesRequested);
3874
0
  }
3875
0
    }
3876
    /* 2. Set randomBytesSize to the number of bytes available from the RNG. This number MAY be less
3877
       than bytesRequested. */
3878
0
    if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) {
3879
0
  returnCode = TPM_SizedBuffer_Allocate(&randomBytes, bytesRequested);
3880
0
    }
3881
    /* 3. Set randomBytes to the next randomBytesSize bytes from the RNG */
3882
0
    if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) {
3883
0
  returnCode = TPM_Random(randomBytes.buffer, bytesRequested);
3884
0
    }
3885
    /*
3886
      response
3887
    */
3888
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3889
0
    if (rcf == 0) {
3890
0
  printf("TPM_Process_GetRandom: Ordinal returnCode %08x %u\n",
3891
0
         returnCode, returnCode);
3892
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3893
0
    }
3894
    /* success response, append the rest of the parameters.  */
3895
0
    if (rcf == 0) {
3896
0
  if (returnCode == TPM_SUCCESS) {
3897
      /* checkpoint the beginning of the outParam's */
3898
0
      outParamStart = response->buffer_current - response->buffer;
3899
      /* append randomBytes */
3900
0
      returnCode = TPM_SizedBuffer_Store(response, &randomBytes);
3901
      /* checkpoint the end of the outParam's */
3902
0
      outParamEnd = response->buffer_current - response->buffer;
3903
0
  }
3904
  /* digest the above the line output parameters */
3905
0
  if (returnCode == TPM_SUCCESS) {
3906
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3907
0
                 auditStatus, /* input audit status */
3908
0
                 transportEncrypt,
3909
0
                 tag,     
3910
0
                 returnCode,
3911
0
                 ordinal,   /* command ordinal */
3912
0
                 response->buffer + outParamStart,  /* start */
3913
0
                 outParamEnd - outParamStart);  /* length */
3914
0
  }
3915
  /* audit if required */
3916
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3917
0
      returnCode = TPM_ProcessAudit(tpm_state,
3918
0
            transportEncrypt,
3919
0
            inParamDigest,
3920
0
            outParamDigest,
3921
0
            ordinal);
3922
0
  }
3923
  /* adjust the initial response */
3924
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3925
0
    }
3926
    /*
3927
      cleanup
3928
    */
3929
0
    TPM_SizedBuffer_Delete(&randomBytes); /* freed @1 */
3930
0
    return rcf;
3931
0
}
3932
3933
/* 13.7 TPM_StirRandom rev 109
3934
3935
   StirRandom adds entropy to the RNG state.
3936
*/
3937
3938
TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state,
3939
          TPM_STORE_BUFFER *response,
3940
          TPM_TAG tag,
3941
          uint32_t paramSize,
3942
          TPM_COMMAND_CODE ordinal,
3943
          unsigned char *command,
3944
          TPM_TRANSPORT_INTERNAL *transportInternal)
3945
0
{
3946
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3947
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3948
3949
    /* input parameters */
3950
0
    TPM_SIZED_BUFFER  inData;   /* Data to add entropy to RNG state,
3951
             Number of bytes of input */
3952
3953
    /* processing parameters */
3954
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3955
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3956
0
    TPM_DIGEST      inParamDigest;
3957
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3958
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3959
3960
    /* output parameters */
3961
0
    uint32_t    outParamStart;  /* starting point of outParam's */
3962
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
3963
0
    TPM_DIGEST    outParamDigest;
3964
3965
0
    printf("TPM_Process_StirRandom: Ordinal Entry\n");
3966
0
    TPM_SizedBuffer_Init(&inData);  /* freed @1 */
3967
    /*
3968
      get inputs
3969
    */
3970
    /* save the starting point of inParam's for authorization and auditing */
3971
0
    inParamStart = command;
3972
    /* get inData parameter */
3973
0
    if (returnCode == TPM_SUCCESS) {
3974
0
  returnCode = TPM_SizedBuffer_Load(&inData, &command, &paramSize);
3975
0
    }
3976
    /* save the ending point of inParam's for authorization and auditing */
3977
0
    inParamEnd = command;
3978
    /* digest the input parameters */
3979
0
    if (returnCode == TPM_SUCCESS) {
3980
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3981
0
            &auditStatus,   /* output */
3982
0
            &transportEncrypt,  /* output */
3983
0
            tpm_state,
3984
0
            tag,
3985
0
            ordinal,
3986
0
            inParamStart,
3987
0
            inParamEnd,
3988
0
            transportInternal);
3989
0
    }
3990
    /* check state */
3991
0
    if (returnCode == TPM_SUCCESS) {
3992
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
3993
0
    }
3994
    /* check tag */
3995
0
    if (returnCode == TPM_SUCCESS) {
3996
0
  returnCode = TPM_CheckRequestTag0(tag);
3997
0
    }
3998
0
    if (returnCode == TPM_SUCCESS) {
3999
0
  if (paramSize != 0) {
4000
0
      printf("TPM_Process_StirRandom: Error, command has %u extra bytes\n",
4001
0
       paramSize);
4002
0
      returnCode = TPM_BAD_PARAM_SIZE;
4003
0
  }
4004
0
    }
4005
    /*
4006
      Processing
4007
    */
4008
    /* 1. If dataSize is not less than 256 bytes, the TPM MAY return TPM_BAD_PARAMETER. */
4009
    /* The TPM updates the state of the current RNG using the appropriate mixing function. */
4010
0
    if (returnCode == TPM_SUCCESS) {
4011
0
  returnCode = TPM_StirRandomCmd(&inData);
4012
0
    }
4013
    /*
4014
      response
4015
    */
4016
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
4017
0
    if (rcf == 0) {
4018
0
  printf("TPM_Process_StirRandom: Ordinal returnCode %08x %u\n",
4019
0
         returnCode, returnCode);
4020
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
4021
0
    }
4022
0
    if (rcf == 0) {
4023
0
  if (returnCode == TPM_SUCCESS) {
4024
      /* checkpoint the beginning of the outParam's */
4025
0
      outParamStart = response->buffer_current - response->buffer;
4026
      /* checkpoint the end of the outParam's */
4027
0
      outParamEnd = response->buffer_current - response->buffer;
4028
0
  }
4029
  /* digest the above the line output parameters */
4030
0
  if (returnCode == TPM_SUCCESS) {
4031
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
4032
0
                 auditStatus, /* input audit status */
4033
0
                 transportEncrypt,
4034
0
                 tag,     
4035
0
                 returnCode,
4036
0
                 ordinal,   /* command ordinal */
4037
0
                 response->buffer + outParamStart,  /* start */
4038
0
                 outParamEnd - outParamStart);  /* length */
4039
0
  }
4040
  /* audit if required */
4041
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
4042
0
      returnCode = TPM_ProcessAudit(tpm_state,
4043
0
            transportEncrypt,
4044
0
            inParamDigest,
4045
0
            outParamDigest,
4046
0
            ordinal);
4047
0
  }
4048
  /* adjust the initial response */
4049
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
4050
0
    }
4051
    /*
4052
      cleanup
4053
    */
4054
0
    TPM_SizedBuffer_Delete(&inData);  /* @1 */
4055
0
    return rcf;
4056
0
}
4057
4058
/* 13.8 TPM_CertifyKey rev 107
4059
4060
   The TPM_CertifyKey operation allows one key to certify the public portion of another key.  A TPM
4061
   identity key may be used to certify non-migratable keys but is not permitted to certify migratory
4062
   keys or certified migration keys. As such, it allows the TPM to make the statement "this key is
4063
   held in a TPM-shielded location, and it will never be revealed." For this statement to have
4064
   veracity, the Challenger must trust the policies used by the entity that issued the identity and
4065
   the maintenance policy of the TPM manufacturer.
4066
   
4067
   Signing and legacy keys may be used to certify both migratable and non-migratable keys. Then the
4068
   usefulness of a certificate depends on the trust in the certifying key by the recipient of the
4069
   certificate.
4070
   
4071
   The key to be certified must be loaded before TPM_CertifyKey is called.
4072
   
4073
   The determination to use the TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 on the output is based on
4074
   which PCRs and what localities the certified key is restricted to. A key to be certified that
4075
   does not have locality restrictions and which uses no PCRs greater than PCR #15 will cause this
4076
   command to return and sign a TPM_CERTIFY_INFO structure, which provides compatibility with V1.1
4077
   TPMs.
4078
   
4079
   When this command is run to certify all other keys (those that use PCR #16 or higher, as well as
4080
   those limited by locality in any way), it will return and sign a TPM_CERTIFY_INFO2 structure.
4081
   
4082
   TPM_CertifyKey does not support the case where (a) the certifying key requires a usage
4083
   authorization to be provided but (b) the key-to-be-certified does not. In such cases,
4084
   TPM_CertifyKey2 must be used.
4085
   
4086
   If a command tag (in the parameter array) specifies only one authorisation session, then the TPM
4087
   convention is that the first session listed is ignored (authDataUsage must be TPM_AUTH_NEVER for
4088
   this key) and the incoming session data is used for the second auth session in the list. In
4089
   TPM_CertifyKey, the first session is the certifying key and the second session is the
4090
   key-to-be-certified. In TPM_CertifyKey2, the first session is the key-to-be-certified and the
4091
   second session is the certifying key.
4092
*/
4093
4094
TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state,
4095
          TPM_STORE_BUFFER *response,
4096
          TPM_TAG tag,
4097
          uint32_t paramSize,
4098
          TPM_COMMAND_CODE ordinal,
4099
          unsigned char *command,
4100
          TPM_TRANSPORT_INTERNAL *transportInternal)
4101
0
{
4102
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
4103
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
4104
4105
    /* input parameters */
4106
0
    TPM_KEY_HANDLE  certHandle; /* Handle of the key to be used to certify the key. */
4107
0
    TPM_KEY_HANDLE  keyHandle;  /* Handle of the key to be certified. */
4108
0
    TPM_NONCE   antiReplay; /* 160 bits of externally supplied data (typically a nonce
4109
             provided to prevent replay-attacks) */
4110
0
    TPM_AUTHHANDLE  certAuthHandle; /* The authorization session handle used for certHandle. */
4111
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with certAuthHandle
4112
             */
4113
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization session
4114
               handle */
4115
0
    TPM_AUTHDATA  certAuth; /* The authorization session digest for inputs and
4116
             certHandle. HMAC key: certKey.auth. */
4117
0
    TPM_AUTHHANDLE  keyAuthHandle;  /* The authorization session handle used for the key to be
4118
             signed. */
4119
0
    TPM_NONCE   keynonceOdd;  /* Nonce generated by system associated with keyAuthHandle
4120
             */
4121
0
    TPM_BOOL  continueKeySession = TRUE; /* The continue use flag for the authorization session
4122
               handle */
4123
0
    TPM_AUTHDATA  keyAuth;  /* The authorization session digest for the inputs and key
4124
             to be signed. HMAC key: key.usageAuth. */
4125
                 
4126
    /* processing parameters */
4127
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
4128
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
4129
0
    TPM_DIGEST      inParamDigest;
4130
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
4131
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
4132
0
    TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */
4133
0
    TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */
4134
0
    TPM_BOOL      certAuthHandleValid = FALSE;
4135
0
    TPM_BOOL      keyAuthHandleValid = FALSE;
4136
0
    TPM_SECRET      *certHmacKey;
4137
0
    TPM_SECRET      *targetHmacKey;
4138
0
    TPM_BOOL      certPCRStatus;
4139
0
    TPM_BOOL      targetPCRStatus;
4140
0
    TPM_KEY     *certKey = NULL; /* the key specified by certHandle */
4141
0
    TPM_KEY     *targetKey = NULL; /* the key specified by keyHandle */
4142
0
    TPM_SECRET      *certKeyUsageAuth;
4143
0
    TPM_SECRET      *targetKeyUsageAuth;
4144
0
    TPM_BOOL      pcrUsage;
4145
0
    TPM_LOCALITY_SELECTION  localityAtRelease;
4146
0
    int       v1Version;    /* TPM 1.1 or TPM 1.2 */
4147
0
    int       certifyType = 0;  /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 */
4148
0
    TPM_DIGEST      m1Digest;   /* digest of certifyInfo */
4149
4150
    /* output parameters */
4151
0
    uint32_t      outParamStart;  /* starting point of outParam's */
4152
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
4153
0
    TPM_DIGEST      outParamDigest;
4154
0
    TPM_CERTIFY_INFO    certifyInfo;  /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 structure
4155
               that provides information relative to keyhandle
4156
               NOTE This is c1 in the Actions. */
4157
0
    TPM_CERTIFY_INFO2   certifyInfo2;
4158
0
    TPM_SIZED_BUFFER    outData;  /* The signature of certifyInfo */
4159
4160
0
    printf("TPM_Process_CertifyKey: Ordinal Entry\n");
4161
0
    TPM_CertifyInfo_Init(&certifyInfo);   /* freed @1 */
4162
0
    TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @2 */
4163
0
    TPM_SizedBuffer_Init(&outData);   /* freed @3 */
4164
    /*
4165
      get inputs
4166
    */
4167
    /* get certHandle parameter */
4168
0
    if (returnCode == TPM_SUCCESS) {
4169
0
  returnCode = TPM_Load32(&certHandle, &command, &paramSize);
4170
0
    }
4171
    /* get keyHandle parameter */
4172
0
    if (returnCode == TPM_SUCCESS) {
4173
0
  printf("TPM_Process_CertifyKey: certHandle %08x\n", certHandle);
4174
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
4175
0
    }
4176
    /* save the starting point of inParam's for authorization and auditing */
4177
0
    inParamStart = command;
4178
    /* get antiReplay parameter */
4179
0
    if (returnCode == TPM_SUCCESS) {
4180
0
  printf("TPM_Process_CertifyKey: keyHandle %08x\n", keyHandle);
4181
0
  returnCode = TPM_Nonce_Load(antiReplay, &command, &paramSize);
4182
0
    }
4183
    /* save the ending point of inParam's for authorization and auditing */
4184
0
    inParamEnd = command;
4185
    /* digest the input parameters */
4186
0
    if (returnCode == TPM_SUCCESS) {
4187
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
4188
0
            &auditStatus,   /* output */
4189
0
            &transportEncrypt,  /* output */
4190
0
            tpm_state,
4191
0
            tag,
4192
0
            ordinal,
4193
0
            inParamStart,
4194
0
            inParamEnd,
4195
0
            transportInternal);
4196
0
    }
4197
    /* check state */
4198
0
    if (returnCode == TPM_SUCCESS) {
4199
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
4200
0
    }
4201
    /* check tag */
4202
0
    if (returnCode == TPM_SUCCESS) {
4203
0
  returnCode = TPM_CheckRequestTag210(tag);
4204
0
    }
4205
    /* get the optional 'below the line' authorization parameters */
4206
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4207
0
  returnCode = TPM_AuthParams_Get(&certAuthHandle,
4208
0
          &certAuthHandleValid,
4209
0
          nonceOdd,
4210
0
          &continueAuthSession,
4211
0
          certAuth,
4212
0
          &command, &paramSize);
4213
0
    }
4214
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4215
0
  printf("TPM_Process_CertifyKey: certAuthHandle %08x\n", certAuthHandle);
4216
0
    }
4217
    /* get the optional 'below the line' authorization parameters */
4218
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4219
0
  returnCode = TPM_AuthParams_Get(&keyAuthHandle,
4220
0
          &keyAuthHandleValid,
4221
0
          keynonceOdd,
4222
0
          &continueKeySession,
4223
0
          keyAuth,
4224
0
          &command, &paramSize);
4225
0
    }
4226
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4227
0
  printf("TPM_Process_CertifyKey: keyAuthHandle %08x\n", keyAuthHandle); 
4228
0
    }
4229
0
    if (returnCode == TPM_SUCCESS) {
4230
0
  if (paramSize != 0) {
4231
0
      printf("TPM_Process_CertifyKey: Error, command has %u extra bytes\n",
4232
0
       paramSize);
4233
0
      returnCode = TPM_BAD_PARAM_SIZE;
4234
0
  }
4235
0
    }
4236
    /* do not terminate sessions if the command did not parse correctly */
4237
0
    if (returnCode != TPM_SUCCESS) {
4238
0
  certAuthHandleValid = FALSE;
4239
0
  keyAuthHandleValid = FALSE;
4240
0
    }
4241
    /*
4242
      Processing
4243
    */
4244
    /* get the key corresponding to the certHandle parameter */
4245
0
    if (returnCode == TPM_SUCCESS) {
4246
0
  returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle,
4247
0
             FALSE,   /* not read-only */
4248
0
             FALSE,   /* do not ignore PCRs */
4249
0
             FALSE);  /* cannot use EK */
4250
0
    }
4251
    /* get the key corresponding to the keyHandle parameter */
4252
0
    if (returnCode == TPM_SUCCESS) {
4253
0
  returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle,
4254
0
             FALSE,   /* not read-only */
4255
0
             FALSE,   /* do not ignore PCRs */
4256
0
             FALSE);  /* cannot use EK */
4257
0
    }
4258
    /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of
4259
       TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */
4260
0
    if (returnCode == TPM_SUCCESS) {
4261
0
  if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) &&
4262
0
      (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) {
4263
0
      printf("TPM_Process_CertifyKey: Error, invalid certKey sigScheme %04hx\n",
4264
0
       certKey->algorithmParms.sigScheme);
4265
0
      returnCode = TPM_BAD_KEY_PROPERTY;
4266
0
  }
4267
0
    }
4268
    /* 2. Verify command and key AuthData values */
4269
    /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */
4270
    /* i. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key
4271
       pointed to by certHandle, return TPM_AUTHFAIL on error */
4272
    /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key
4273
       pointed to by keyHandle, return TPM_AUTH2FAIL on error */
4274
    /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */
4275
    /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return
4276
       TPM_AUTHFAIL on error. */
4277
    /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key
4278
       pointed to by keyHandle, return TPM_AUTHFAIL on error */
4279
    /* c. else if tag is TPM_TAG_RQU_COMMAND */
4280
    /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return
4281
       TPM_AUTHFAIL on error. */
4282
    /* ii. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key
4283
       referenced by keyHandle, return TPM_AUTHFAIL on error. */
4284
4285
    /* NOTE: Simplified the above logic as follows */
4286
    /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */
4287
    /* get certHandle -> usageAuth */
4288
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4289
0
  returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey);
4290
0
    }   
4291
    /* get the first session data */
4292
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4293
0
  returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data,
4294
0
                &certHmacKey,
4295
0
                tpm_state,
4296
0
                certAuthHandle,
4297
0
                TPM_PID_NONE,
4298
0
                TPM_ET_KEYHANDLE,
4299
0
                ordinal,
4300
0
                certKey,
4301
0
                certKeyUsageAuth,     /* OIAP */
4302
0
                certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
4303
0
    }
4304
    /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key
4305
       pointed to by certHandle, return TPM_AUTHFAIL on error */
4306
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4307
0
  returnCode = TPM_Authdata_Check(tpm_state,
4308
0
          *certHmacKey,   /* HMAC key */
4309
0
          inParamDigest,
4310
0
          cert_auth_session_data, /* authorization session */
4311
0
          nonceOdd,   /* Nonce generated by system
4312
                   associated with authHandle */
4313
0
          continueAuthSession,
4314
0
          certAuth);    /* Authorization digest for input */
4315
0
    }
4316
    /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */
4317
    /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return
4318
       TPM_AUTHFAIL on error. */
4319
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
4320
0
  if (certKey->authDataUsage != TPM_AUTH_NEVER) {
4321
0
      printf("TPM_Process_CertifyKey: Error, cert key authorization required\n");
4322
0
      returnCode = TPM_AUTHFAIL;
4323
0
  }
4324
0
    }
4325
    /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of
4326
       authorization data */
4327
    /* get keyHandle -> usageAuth */
4328
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4329
0
  returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey);
4330
0
    }
4331
    /* get the second session data */
4332
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4333
0
  returnCode = TPM_AuthSessions_GetData(&target_auth_session_data,
4334
0
                &targetHmacKey,
4335
0
                tpm_state,
4336
0
                keyAuthHandle,
4337
0
                TPM_PID_NONE,
4338
0
                TPM_ET_KEYHANDLE,
4339
0
                ordinal,
4340
0
                targetKey,
4341
0
                targetKeyUsageAuth,   /* OIAP */
4342
0
                targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/
4343
0
    }
4344
    /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key
4345
       pointed to by keyHandle, return TPM_AUTH2FAIL on error */
4346
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4347
0
  returnCode = TPM_Auth2data_Check(tpm_state,
4348
0
           *targetHmacKey,    /* HMAC key */
4349
0
           inParamDigest,
4350
0
           target_auth_session_data,  /* authorization session */
4351
0
           keynonceOdd,   /* Nonce generated by system
4352
                   associated with authHandle */
4353
0
           continueKeySession,
4354
0
           keyAuth);    /* Authorization digest for input */
4355
0
    }
4356
    /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced
4357
       by keyHandle, return TPM_AUTHFAIL on error. */
4358
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
4359
0
  if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) {
4360
0
      printf("TPM_Process_CertifyKey: Error, target key authorization required\n");
4361
0
      returnCode = TPM_AUTHFAIL;
4362
0
  }
4363
0
    }
4364
    /* 3. If keyHandle -> payload is not TPM_PT_ASYM, return TPM_INVALID_KEYUSAGE. */
4365
0
    if (returnCode == TPM_SUCCESS) {
4366
0
  if (targetKey->tpm_store_asymkey->payload != TPM_PT_ASYM) {
4367
0
      printf("TPM_Process_CertifyKey: Error, target key invalid payload %02x\n",
4368
0
       targetKey->tpm_store_asymkey->payload);
4369
0
      returnCode = TPM_INVALID_KEYUSAGE;
4370
0
  }
4371
0
    }  
4372
    /* 4. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is
4373
       TPM_KEY_IDENTITY) */
4374
0
    if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) {
4375
  /* a. If keyHandle -> keyflags -> keyInfo -> migratable is TRUE return TPM_MIGRATEFAIL */
4376
0
  if (targetKey->keyFlags & TPM_MIGRATABLE) {
4377
0
      printf("TPM_Process_CertifyKey: Error, target key is migratable\n");
4378
0
      returnCode = TPM_MIGRATEFAIL;
4379
0
  }
4380
0
    }
4381
    /* 5. Validate that certHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_IDENTITY or TPM_KEY_LEGACY,
4382
       if not return TPM_INVALID_KEYUSAGE */
4383
0
    if (returnCode == TPM_SUCCESS) {
4384
0
  printf("TPM_Process_CertifyKey: certHandle -> keyUsage %04hx\n", certKey->keyUsage);
4385
0
  if ((certKey->keyUsage != TPM_KEY_SIGNING) &&
4386
0
      ((certKey->keyUsage) != TPM_KEY_IDENTITY) &&
4387
0
      ((certKey->keyUsage) != TPM_KEY_LEGACY)) {
4388
0
      printf("TPM_Process_CertifyKey: Error, certHandle -> keyUsage %04hx is invalid\n",
4389
0
       certKey->keyUsage);
4390
0
      returnCode = TPM_INVALID_KEYUSAGE;
4391
0
  }
4392
0
    }
4393
    /* 6. Validate that keyHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_STORAGE, TPM_KEY_IDENTITY,
4394
       TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */
4395
0
    if (returnCode == TPM_SUCCESS) {
4396
0
  printf("TPM_Process_CertifyKey: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage);
4397
0
  if ((targetKey->keyUsage != TPM_KEY_SIGNING) &&
4398
0
      ((targetKey->keyUsage) != TPM_KEY_STORAGE) &&
4399
0
      ((targetKey->keyUsage) != TPM_KEY_IDENTITY) &&
4400
0
      ((targetKey->keyUsage) != TPM_KEY_BIND) &&
4401
0
      ((targetKey->keyUsage) != TPM_KEY_LEGACY)) {
4402
0
      printf("TPM_Process_CertifyKey: Error, keyHandle -> keyUsage %04hx is invalid\n",
4403
0
       targetKey->keyUsage);
4404
0
      returnCode = TPM_INVALID_KEYUSAGE;
4405
0
  }
4406
0
    }
4407
    /* 7. If keyHandle -> digestAtRelease requires the use of PCRs 16 or higher to calculate or if
4408
       keyHandle -> localityAtRelease is not 0x1F */
4409
    /* get PCR usage 16 and higher */
4410
0
    if (returnCode == TPM_SUCCESS) {
4411
0
  returnCode = TPM_Key_GetPCRUsage(&pcrUsage, targetKey, 2);
4412
0
    }
4413
    /* get localityAtRelease */
4414
0
    if (returnCode == TPM_SUCCESS) {
4415
0
  returnCode = TPM_Key_GetLocalityAtRelease(&localityAtRelease, targetKey);
4416
0
    }
4417
0
    if (returnCode == TPM_SUCCESS) {
4418
0
  if (pcrUsage || (localityAtRelease != TPM_LOC_ALL)) {
4419
      /* a. Set V1 to 1.2 */
4420
0
      v1Version = 2;  /* locality or >2 PCR's */
4421
0
  }
4422
  /* 8. Else */
4423
0
  else {
4424
      /* a. Set V1 to 1.1 */
4425
0
      v1Version = 1;  /* no locality and <= 2 PCR's */
4426
0
  }
4427
0
    }
4428
0
    if (returnCode == TPM_SUCCESS) {
4429
0
  printf("TPM_Process_CertifyKey: V1 %d\n", v1Version);
4430
  /* 9. If keyHandle -> pcrInfoSize is not 0 */
4431
0
  if (targetKey->pcrInfo.size != 0) {
4432
0
      printf("TPM_Process_CertifyKey: Setting PCR info from key\n");
4433
      /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */
4434
      /* i. Create a digestAtRelease according to the specified PCR registers and
4435
         compare to keyHandle -> digestAtRelease and if a mismatch return
4436
         TPM_WRONGPCRVAL */
4437
      /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */
4438
      /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */
4439
      /* b. If V1 is 1.1 */
4440
0
      if (v1Version == 1) {
4441
0
    certifyType = 1;
4442
    /* i. Create C1 a TPM_CERTIFY_INFO structure */
4443
    /* NOTE: Done by TPM_CertifyInfo_Init() */
4444
    /* ii. Fill in C1 with the information from the key pointed to by keyHandle */
4445
    /* NOTE: Done in common _Set() code below */
4446
    /* iii. The TPM MUST set c1 -> pcrInfoSize to 44. */
4447
    /* iv. The TPM MUST set c1 -> pcrInfo to a TPM_PCR_INFO structure properly filled
4448
       out using the information from keyHandle. */
4449
    /* This function actually creates the cache, which is serialized later */
4450
0
    if (returnCode == TPM_SUCCESS) {
4451
0
        returnCode = TPM_PCRInfo_CreateFromKey(&(certifyInfo.tpm_pcr_info),
4452
0
                 targetKey);
4453
0
    }
4454
    /* v. The TPM MUST set c1 -> digestAtCreation to 20 bytes of 0x00. */
4455
0
    if (returnCode == TPM_SUCCESS) {
4456
0
        TPM_Digest_Init(certifyInfo.tpm_pcr_info->digestAtCreation);
4457
0
    }
4458
0
      }
4459
      /* c. Else */
4460
0
      else {
4461
0
    certifyType = 2;
4462
    /* i. Create C1 a TPM_CERTIFY_INFO2 structure */
4463
    /* NOTE: Done by TPM_CertifyInfo2_Init() */
4464
    /* ii. Fill in C1 with the information from the key pointed to by keyHandle */
4465
    /* NOTE: Done in common _Set() code below */
4466
    /* iii. Set C1 -> pcrInfoSize to the size of an appropriate TPM_PCR_INFO_SHORT
4467
       structure. */
4468
    /* iv. Set C1 -> pcrInfo to a properly filled out TPM_PCR_INFO_SHORT structure,
4469
       using the information from keyHandle. */
4470
    /* This function actually creates the cache, which is serialized later */
4471
0
    if (returnCode == TPM_SUCCESS) {
4472
0
        returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), 
4473
0
                targetKey);
4474
0
    }
4475
    /* v. Set C1 -> migrationAuthoritySize to 0 */
4476
    /* NOTE: Done by TPM_CertifyInfo2_Init() */
4477
0
      }
4478
0
  }
4479
  /* 10. Else */
4480
0
  else {
4481
0
      certifyType = 1;
4482
      /* a. Create C1 a TPM_CERTIFY_INFO structure */
4483
      /* NOTE: Done by TPM_CertifyInfo_Init() */
4484
      /* b. Fill in C1 with the information from the key pointed to be keyHandle */
4485
      /* NOTE: Done in common _Set() code below */
4486
      /* c. The TPM MUST set c1 -> pcrInfoSize to 0 */
4487
      /* NOTE: Done by TPM_CertifyInfo_Init() */
4488
0
  }
4489
0
    }
4490
    /* 11. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that
4491
       <key> is the actual public modulus, and does not include any structure formatting. */
4492
    /* 12. Set C1 -> pubKeyDigest to H1 */
4493
    /* NOTE: Done by TPM_CertifyInfo_Set() or TPM_CertifyInfo2_Set() */
4494
    /* 13. The TPM copies the antiReplay parameter to c1 -> data. */
4495
    /* Set C1 -> parentPCRStatus to the value from keyHandle NOTE: Implied in specification */
4496
    /* Fill in C1 with the information from the key pointed to by keyHandle */
4497
0
    if (returnCode == TPM_SUCCESS) {
4498
0
  printf("TPM_Process_CertifyKey: Setting certifyInfo from target key\n");
4499
0
  if (certifyType == 1) {
4500
0
      TPM_Digest_Copy(certifyInfo.data, antiReplay);
4501
0
      certifyInfo.parentPCRStatus = targetPCRStatus;
4502
0
      returnCode = TPM_CertifyInfo_Set(&certifyInfo, targetKey);
4503
0
  }  
4504
0
  else {
4505
0
      TPM_Digest_Copy(certifyInfo2.data, antiReplay);
4506
0
      certifyInfo2.parentPCRStatus = targetPCRStatus;
4507
0
      returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey);
4508
0
  }
4509
0
    }
4510
    /* 14. The TPM sets certifyInfo to C1. */
4511
    /* NOTE Created as certifyInfo or certifyInfo2 */
4512
    /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1. */
4513
0
    if (returnCode == TPM_SUCCESS) {
4514
0
  printf("TPM_Process_CertifyKey: Digesting certifyInfo\n");
4515
0
  if (certifyType == 1) {
4516
0
      returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo,
4517
0
                (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store);
4518
0
  }  
4519
0
  else {
4520
0
      returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2,
4521
0
                (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store);
4522
0
  }
4523
0
    }
4524
    /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob
4525
       is returned in outData. */
4526
0
    if (returnCode == TPM_SUCCESS) {
4527
0
  printf("TPM_Process_CertifyKey: Signing certifyInfo digest with certifying key\n");
4528
0
  returnCode = TPM_RSASignToSizedBuffer(&outData,   /* signature */
4529
0
                m1Digest,   /* message */
4530
0
                TPM_DIGEST_SIZE, /* message size */
4531
0
                certKey);   /* input, signing key */
4532
0
    }
4533
    /*
4534
      response
4535
    */
4536
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
4537
0
    if (rcf == 0) {
4538
0
  printf("TPM_Process_CertifyKey: Ordinal returnCode %08x %u\n",
4539
0
         returnCode, returnCode);
4540
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
4541
0
    }
4542
    /* success response, append the rest of the parameters.  */
4543
0
    if (rcf == 0) {
4544
0
  if (returnCode == TPM_SUCCESS) {
4545
      /* checkpoint the beginning of the outParam's */
4546
0
      outParamStart = response->buffer_current - response->buffer;
4547
      /* Return certifyInfo */
4548
0
      if (certifyType == 1) {
4549
0
    returnCode = TPM_CertifyInfo_Store(response, &certifyInfo);
4550
0
      }  
4551
0
      else {
4552
0
    returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2);
4553
0
      }
4554
0
  }
4555
0
  if (returnCode == TPM_SUCCESS) {
4556
      /* Return outData */
4557
0
      returnCode = TPM_SizedBuffer_Store(response, &outData);
4558
      /* checkpoint the end of the outParam's */
4559
0
      outParamEnd = response->buffer_current - response->buffer;
4560
0
  }
4561
  /* digest the above the line output parameters */
4562
0
  if (returnCode == TPM_SUCCESS) {
4563
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
4564
0
                 auditStatus, /* input audit status */
4565
0
                 transportEncrypt,
4566
0
                 tag,     
4567
0
                 returnCode,
4568
0
                 ordinal,   /* command ordinal */
4569
0
                 response->buffer + outParamStart,  /* start */
4570
0
                 outParamEnd - outParamStart);  /* length */
4571
0
  }
4572
  /* calculate and set the below the line parameters */
4573
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4574
0
      returnCode = TPM_AuthParams_Set(response,
4575
0
              *certHmacKey,   /* HMAC key */
4576
0
              cert_auth_session_data,
4577
0
              outParamDigest,
4578
0
              nonceOdd,
4579
0
              continueAuthSession);
4580
0
  }
4581
  /* calculate and set the below the line parameters */
4582
0
  if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4583
0
      returnCode = TPM_AuthParams_Set(response,
4584
0
              *targetHmacKey,   /* HMAC key */
4585
0
              target_auth_session_data,
4586
0
              outParamDigest,
4587
0
              keynonceOdd,
4588
0
              continueKeySession);
4589
0
  }
4590
  /* audit if required */
4591
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
4592
0
      returnCode = TPM_ProcessAudit(tpm_state,
4593
0
            transportEncrypt,
4594
0
            inParamDigest,
4595
0
            outParamDigest,
4596
0
            ordinal);
4597
0
  }
4598
  /* adjust the initial response */
4599
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
4600
0
    }
4601
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
4602
0
    if (((rcf != 0) ||
4603
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
4604
0
   !continueKeySession) &&
4605
0
  keyAuthHandleValid) {
4606
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle);
4607
0
    }
4608
0
    if (((rcf != 0) ||
4609
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
4610
0
   !continueAuthSession) &&
4611
0
  certAuthHandleValid) {
4612
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle);
4613
0
    }
4614
    /*
4615
      cleanup
4616
    */
4617
0
    TPM_CertifyInfo_Delete(&certifyInfo); /* @1 */
4618
0
    TPM_CertifyInfo2_Delete(&certifyInfo2); /* @2 */
4619
0
    TPM_SizedBuffer_Delete(&outData);   /* @3 */
4620
0
    return rcf;
4621
0
}
4622
4623
/* 13.9 TPM_CertifyKey2 rev 107
4624
4625
   This command is based on TPM_CertifyKey, but includes the ability to certify a Certifiable
4626
   Migration Key (CMK), which requires extra input parameters.
4627
4628
   TPM_CertifyKey2 always produces a TPM_CERTIFY_INFO2 structure.
4629
4630
   TPM_CertifyKey2 does not support the case where (a) the key-to-be-certified requires a usage
4631
   authorization to be provided but (b) the certifying key does not.
4632
4633
   If a command tag (in the parameter array) specifies only one authorisation session, then the TPM
4634
   convention is that the first session listed is ignored (authDataUsage must be
4635
   TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER for this key) and the incoming session data is used for
4636
   the second auth session in the list. In TPM_CertifyKey2, the first session is the key to be
4637
   certified and the second session is the certifying key.
4638
*/
4639
4640
TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state,
4641
           TPM_STORE_BUFFER *response,
4642
           TPM_TAG tag,
4643
           uint32_t paramSize,
4644
           TPM_COMMAND_CODE ordinal,
4645
           unsigned char *command,
4646
           TPM_TRANSPORT_INTERNAL *transportInternal)
4647
0
{
4648
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
4649
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
4650
4651
    /* input parameters */
4652
0
    TPM_KEY_HANDLE  keyHandle;  /* Handle of the key to be certified. */
4653
0
    TPM_KEY_HANDLE  certHandle; /* Handle of the key to be used to certify the key. */
4654
0
    TPM_DIGEST    migrationPubDigest; /* The digest of a TPM_MSA_COMPOSITE structure,
4655
               containing at least one public key of a Migration
4656
               Authority */
4657
0
    TPM_NONCE   antiReplay; /* 160 bits of externally supplied data (typically a nonce
4658
             provided to prevent replay-attacks) */
4659
0
    TPM_AUTHHANDLE  keyAuthHandle;  /* The authorization session handle used for the key to be
4660
             signed.  */
4661
0
    TPM_NONCE   keynonceOdd;  /* Nonce generated by system associated with keyAuthHandle
4662
             */
4663
0
    TPM_BOOL  continueKeySession; /* The continue use flag for the authorization session
4664
             handle */
4665
0
    TPM_AUTHDATA  keyAuth;  /* The authorization session digest for the inputs and key
4666
             to be signed. HMAC key: key.usageAuth. */
4667
0
    TPM_AUTHHANDLE  certAuthHandle; /* The authorization session handle used for certHandle.  */
4668
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with certAuthHandle
4669
             */
4670
0
    TPM_BOOL  continueAuthSession;  /* The continue use flag for the authorization session
4671
             handle */
4672
0
    TPM_AUTHDATA   certAuth;  /* Authorization HMAC key: certKey.auth. */
4673
4674
    /* processing parameters */
4675
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
4676
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
4677
0
    TPM_DIGEST      inParamDigest;
4678
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
4679
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
4680
0
    TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */
4681
0
    TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */
4682
0
    TPM_BOOL      certAuthHandleValid = FALSE;
4683
0
    TPM_BOOL      keyAuthHandleValid = FALSE;
4684
0
    TPM_SECRET      *certHmacKey;
4685
0
    TPM_SECRET      *targetHmacKey;
4686
0
    TPM_BOOL      certPCRStatus;
4687
0
    TPM_BOOL      targetPCRStatus;
4688
0
    TPM_KEY     *certKey = NULL; /* the key specified by certHandle */
4689
0
    TPM_KEY     *targetKey = NULL; /* the key specified by keyHandle */
4690
0
    TPM_SECRET      *certKeyUsageAuth;
4691
0
    TPM_SECRET      *targetKeyUsageAuth;
4692
0
    TPM_STORE_ASYMKEY   *targetStoreAsymkey;
4693
0
    TPM_CMK_MIGAUTH   m2CmkMigauth;
4694
0
    TPM_BOOL      hmacValid;      
4695
0
    TPM_DIGEST      migrationAuthority;
4696
0
    TPM_DIGEST      m1Digest;   /* digest of certifyInfo */
4697
4698
    /* output parameters */
4699
0
    uint32_t      outParamStart;  /* starting point of outParam's */
4700
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
4701
0
    TPM_DIGEST      outParamDigest;
4702
0
    TPM_CERTIFY_INFO2   certifyInfo2; /* TPM_CERTIFY_INFO2 relative to keyHandle */
4703
0
    TPM_SIZED_BUFFER    outData;  /* The signed public key. */
4704
4705
0
    printf("TPM_Process_CertifyKey2: Ordinal Entry\n");
4706
0
    TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @1 */
4707
0
    TPM_SizedBuffer_Init(&outData);   /* freed @2 */
4708
0
    TPM_CmkMigauth_Init(&m2CmkMigauth);   /* freed @3 */
4709
    /*
4710
      get inputs
4711
    */
4712
    /* get keyHandle parameter */
4713
0
    if (returnCode == TPM_SUCCESS) {
4714
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
4715
0
    }
4716
    /* get certHandle parameter */
4717
0
    if (returnCode == TPM_SUCCESS) {
4718
0
  printf("TPM_Process_CertifyKey2: keyHandle %08x\n", keyHandle);
4719
0
  returnCode = TPM_Load32(&certHandle, &command, &paramSize);
4720
0
    }
4721
    /* save the starting point of inParam's for authorization and auditing */
4722
0
    inParamStart = command;
4723
    /* get antiReplay parameter */
4724
0
    if (returnCode == TPM_SUCCESS) {
4725
0
  printf("TPM_Process_CertifyKey2: certHandle %08x\n", certHandle);
4726
  /* get the migrationPubDigest parameter */
4727
0
  returnCode = TPM_Digest_Load(migrationPubDigest, &command, &paramSize);
4728
0
    }
4729
    /* get the antiReplay parameter */
4730
0
    if (returnCode == TPM_SUCCESS) {
4731
0
  returnCode = TPM_Nonce_Load(antiReplay, &command, &paramSize);
4732
0
    }
4733
    /* save the ending point of inParam's for authorization and auditing */
4734
0
    inParamEnd = command;
4735
    /* digest the input parameters */
4736
0
    if (returnCode == TPM_SUCCESS) {
4737
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
4738
0
            &auditStatus,   /* output */
4739
0
            &transportEncrypt,  /* output */
4740
0
            tpm_state,
4741
0
            tag,
4742
0
            ordinal,
4743
0
            inParamStart,
4744
0
            inParamEnd,
4745
0
            transportInternal);
4746
0
    }
4747
    /* check state */
4748
0
    if (returnCode == TPM_SUCCESS) {
4749
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
4750
0
    }
4751
    /* check tag */
4752
0
    if (returnCode == TPM_SUCCESS) {
4753
0
  returnCode = TPM_CheckRequestTag210(tag);
4754
0
    }
4755
    /* get the optional 'below the line' authorization parameters */
4756
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4757
0
  returnCode = TPM_AuthParams_Get(&keyAuthHandle,
4758
0
          &keyAuthHandleValid,
4759
0
          keynonceOdd,
4760
0
          &continueKeySession,
4761
0
          keyAuth,
4762
0
          &command, &paramSize);
4763
0
    }
4764
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4765
0
  printf("TPM_Process_CertifyKey2: keyAuthHandle %08x\n", keyAuthHandle);
4766
0
    }
4767
    /* get the optional 'below the line' authorization parameters */
4768
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4769
0
  returnCode = TPM_AuthParams_Get(&certAuthHandle,
4770
0
          &certAuthHandleValid,
4771
0
          nonceOdd,
4772
0
          &continueAuthSession,
4773
0
          certAuth,
4774
0
          &command, &paramSize);
4775
0
    }
4776
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4777
0
  printf("TPM_Process_CertifyKey2: certAuthHandle %08x\n", certAuthHandle); 
4778
0
    }
4779
0
    if (returnCode == TPM_SUCCESS) {
4780
0
  if (paramSize != 0) {
4781
0
      printf("TPM_Process_CertifyKey2: Error, command has %u extra bytes\n",
4782
0
       paramSize);
4783
0
      returnCode = TPM_BAD_PARAM_SIZE;
4784
0
  }
4785
0
    }
4786
    /* do not terminate sessions if the command did not parse correctly */
4787
0
    if (returnCode != TPM_SUCCESS) {
4788
0
  certAuthHandleValid = FALSE;
4789
0
  keyAuthHandleValid = FALSE;
4790
0
    }
4791
    /*
4792
      Processing
4793
    */
4794
    /* get the keys corresponding to the certHandle and keyHandle parameters */
4795
0
    if (returnCode == TPM_SUCCESS) {
4796
0
  returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle,
4797
0
             FALSE,   /* not read-only */
4798
0
             FALSE,   /* do not ignore PCRs */
4799
0
             FALSE);  /* cannot use EK */
4800
0
    }
4801
0
    if (returnCode == TPM_SUCCESS) {
4802
0
  returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle,
4803
0
             FALSE,   /* not read-only */
4804
0
             FALSE,   /* do not ignore PCRs */
4805
0
             FALSE);  /* cannot use EK */
4806
0
    }
4807
    /* get the TPM_STORE_ASYMKEY cache for the target TPM_KEY */
4808
0
    if (returnCode == TPM_SUCCESS) {
4809
0
  returnCode = TPM_Key_GetStoreAsymkey(&targetStoreAsymkey, targetKey);
4810
0
    }   
4811
    /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of
4812
       TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */
4813
0
    if (returnCode == TPM_SUCCESS) {
4814
0
  if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) &&
4815
0
      (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) {
4816
0
      printf("TPM_Process_CertifyKey2: Error, invalid certKey sigScheme %04hx\n",
4817
0
       certKey->algorithmParms.sigScheme);
4818
0
      returnCode = TPM_BAD_KEY_PROPERTY;
4819
0
  }
4820
0
    }
4821
    /* 2. Verify command and key AuthData values: */
4822
    /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */
4823
    /* i. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key
4824
       pointed to by keyHandle, return TPM_AUTHFAIL on error */
4825
    /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key
4826
       pointed to by certHandle, return TPM_AUTH2FAIL on error */
4827
    /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */
4828
    /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key
4829
       referenced by keyHandle, return TPM_AUTHFAIL on error */
4830
    /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key
4831
       pointed to by certHandle, return TPM_AUTHFAIL on error */
4832
    /* c. else if tag is TPM_TAG_RQU_COMMAND */
4833
    /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key
4834
       referenced by keyHandle, return TPM_AUTHFAIL on error */
4835
    /* ii. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return
4836
       TPM_AUTHFAIL on error. */
4837
    /* NOTE: Simplified the above logic as follows */
4838
    /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */
4839
    /* get keyHandle -> usageAuth */
4840
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4841
0
  returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey);
4842
0
    }   
4843
    /* get the first session data */
4844
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4845
0
  returnCode = TPM_AuthSessions_GetData(&target_auth_session_data,
4846
0
                &targetHmacKey,
4847
0
                tpm_state,
4848
0
                keyAuthHandle,
4849
0
                TPM_PID_NONE,
4850
0
                TPM_ET_KEYHANDLE,
4851
0
                ordinal,
4852
0
                targetKey,
4853
0
                targetKeyUsageAuth,     /* OIAP */
4854
0
                targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/
4855
0
    }
4856
    /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key
4857
       pointed to by keyHandle, return TPM_AUTHFAIL on error */
4858
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
4859
0
  returnCode = TPM_Authdata_Check(tpm_state,
4860
0
          *targetHmacKey,   /* HMAC key */
4861
0
          inParamDigest,
4862
0
          target_auth_session_data, /* authorization session */
4863
0
          keynonceOdd,    /* Nonce generated by system
4864
                   associated with authHandle */
4865
0
          continueKeySession,
4866
0
          keyAuth);   /* Authorization digest for input */
4867
0
    }
4868
    /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */
4869
    /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced
4870
       by keyHandle, return TPM_AUTHFAIL on error. */
4871
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
4872
0
  if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) {
4873
0
      printf("TPM_Process_CertifyKey2: Error, target key authorization required\n");
4874
0
      returnCode = TPM_AUTHFAIL;
4875
0
  }
4876
0
    }
4877
    /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of
4878
       authorization data */
4879
    /* get certHandle -> usageAuth */
4880
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4881
0
  returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey);
4882
0
    }
4883
    /* get the second session data */
4884
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4885
0
  returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data,
4886
0
                &certHmacKey,
4887
0
                tpm_state,
4888
0
                certAuthHandle,
4889
0
                TPM_PID_NONE,
4890
0
                TPM_ET_KEYHANDLE,
4891
0
                ordinal,
4892
0
                certKey,
4893
0
                certKeyUsageAuth,     /* OIAP */
4894
0
                certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
4895
0
    }
4896
    /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key
4897
       pointed to by certHandle, return TPM_AUTH2FAIL on error */
4898
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
4899
0
  returnCode = TPM_Auth2data_Check(tpm_state,
4900
0
           *certHmacKey,      /* HMAC key */
4901
0
           inParamDigest,
4902
0
           cert_auth_session_data,  /* authorization session */
4903
0
           nonceOdd,    /* Nonce generated by system
4904
                   associated with authHandle */
4905
0
           continueAuthSession,
4906
0
           certAuth);   /* Authorization digest for input */
4907
0
    }
4908
    /* If the command is TPM_TAG_RQU_COMMAND */
4909
    /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return
4910
       TPM_AUTHFAIL on error. */
4911
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
4912
0
  if (certKey->authDataUsage != TPM_AUTH_NEVER) {
4913
0
      printf("TPM_Process_CertifyKey2: Error, cert key authorization required\n");
4914
0
      returnCode = TPM_AUTHFAIL;
4915
0
  }
4916
0
    }
4917
    /* 3. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is
4918
       TPM_KEY_IDENTITY) */
4919
0
    if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) {
4920
  /* a. If keyHandle -> keyFlags -> migratable is TRUE and
4921
     [keyHandle -> keyFlags-> migrateAuthority is FALSE or
4922
      (keyHandle -> payload != TPM_PT_MIGRATE_RESTRICTED and
4923
      keyHandle -> payload != TPM_PT_MIGRATE_EXTERNAL)]
4924
      return TPM_MIGRATEFAIL */
4925
0
  if ((targetKey->keyFlags & TPM_MIGRATABLE) &&
4926
0
      (!(targetKey->keyFlags & TPM_MIGRATEAUTHORITY) ||
4927
0
       ((targetStoreAsymkey->payload != TPM_PT_MIGRATE_RESTRICTED) &&
4928
0
        (targetStoreAsymkey->payload != TPM_PT_MIGRATE_EXTERNAL)))) {
4929
0
      printf("TPM_Process_CertifyKey2: Error, target key migrate fail\n");
4930
0
      returnCode = TPM_MIGRATEFAIL;
4931
0
  }
4932
0
    }
4933
    /* 4. Validate that certHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or
4934
       TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */
4935
0
    if (returnCode == TPM_SUCCESS) {
4936
0
  printf("TPM_Process_CertifyKey2: certHandle ->keyUsage %04hx\n", certKey->keyUsage);
4937
0
  if ((certKey->keyUsage != TPM_KEY_SIGNING) &&
4938
0
      ((certKey->keyUsage) != TPM_KEY_IDENTITY) &&
4939
0
      ((certKey->keyUsage) != TPM_KEY_LEGACY)) {
4940
0
      printf("TPM_Process_CertifyKey2: Error, keyUsage %04hx is invalid\n",
4941
0
       certKey->keyUsage);
4942
0
      returnCode = TPM_INVALID_KEYUSAGE;
4943
0
  }
4944
0
    }
4945
    /* 5. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY,
4946
       TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */
4947
0
    if (returnCode == TPM_SUCCESS) {
4948
0
  printf("TPM_Process_CertifyKey2: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage);
4949
0
  if ((targetKey->keyUsage != TPM_KEY_SIGNING) &&
4950
0
      ((targetKey->keyUsage) != TPM_KEY_STORAGE) &&
4951
0
      ((targetKey->keyUsage) != TPM_KEY_IDENTITY) &&
4952
0
      ((targetKey->keyUsage) != TPM_KEY_BIND) &&
4953
0
      ((targetKey->keyUsage) != TPM_KEY_LEGACY)) {
4954
0
      printf("TPM_Process_CertifyKey2: Error, keyHandle -> keyUsage %04hx is invalid\n",
4955
0
       targetKey->keyUsage);
4956
0
      returnCode = TPM_INVALID_KEYUSAGE;
4957
0
  }
4958
0
    }
4959
    /* 6. The TPM SHALL create a c1 a TPM_CERTIFY_INFO2 structure from the key pointed to by
4960
       keyHandle */
4961
0
    if (returnCode == TPM_SUCCESS) {
4962
0
  returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey);
4963
0
    }
4964
    /* 7. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that
4965
       <key> is the actual public modulus, and does not include any structure formatting. */
4966
    /* 8. Set C1 -> pubKeyDigest to H1 */
4967
    /* NOTE: Done by TPM_CertifyInfo2_Set() */
4968
0
    if (returnCode == TPM_SUCCESS) {
4969
  /* 9. Copy the antiReplay parameter to c1 -> data */
4970
0
  TPM_Digest_Copy(certifyInfo2.data, antiReplay);
4971
  /* 10. Copy other keyHandle parameters into C1 */
4972
0
  certifyInfo2.parentPCRStatus = targetPCRStatus;
4973
  /* 11. If keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */
4974
0
  if ((targetStoreAsymkey->payload == TPM_PT_MIGRATE_RESTRICTED) ||
4975
0
      (targetStoreAsymkey->payload == TPM_PT_MIGRATE_EXTERNAL)) {
4976
0
      printf("TPM_Process_CertifyKey2: "
4977
0
       "TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n");
4978
      /* a. create thisPubKey, a TPM_PUBKEY structure containing the public key, algorithm and
4979
         parameters corresponding to keyHandle */
4980
      /* NOTE Not required.  Digest is created directly below */
4981
      /* b. Verify that the migration authorization is valid for this key */
4982
      /* i. Create M2 a TPM_CMK_MIGAUTH structure */
4983
      /* NOTE Done by TPM_CmkMigauth_Init() */
4984
0
      if (returnCode == TPM_SUCCESS) {
4985
    /* ii. Set M2 -> msaDigest to migrationPubDigest */
4986
0
    TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationPubDigest );
4987
    /* iii. Set M2 -> pubKeyDigest to SHA-1[thisPubKey] */
4988
0
    returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, targetKey);
4989
0
      }
4990
      /* iv. Verify that [keyHandle -> migrationAuth] == HMAC(M2) signed by using tpmProof as
4991
         the secret and return error TPM_MA_SOURCE on mismatch */
4992
0
      if (returnCode == TPM_SUCCESS) {
4993
0
    printf("TPM_Process_CertifyKey2: Check migrationAuth\n");
4994
0
    returnCode =
4995
0
        TPM_CmkMigauth_CheckHMAC(&hmacValid,        /* result */
4996
0
               targetStoreAsymkey->migrationAuth,   /* expect */
4997
0
               tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */
4998
0
               &m2CmkMigauth);
4999
0
      }
5000
0
      if (returnCode == TPM_SUCCESS) {
5001
0
    if (!hmacValid) {
5002
0
        printf("TPM_Process_CertifyKey2: Error, Invalid migrationAuth\n");
5003
0
        returnCode = TPM_MA_SOURCE;
5004
0
    }
5005
0
      }
5006
      /* c. Set C1 -> migrationAuthority = SHA-1(migrationPubDigest || keyHandle -> payload)
5007
         */
5008
0
      if (returnCode == TPM_SUCCESS) {
5009
0
    printf("TPM_Process_CertifyKey2: Set migrationAuthority\n");
5010
0
    returnCode = TPM_SHA1(migrationAuthority,
5011
0
              TPM_DIGEST_SIZE, migrationPubDigest,
5012
0
              sizeof(TPM_PAYLOAD_TYPE), &(targetStoreAsymkey->payload),
5013
0
              0, NULL);
5014
0
      }
5015
0
      if (returnCode == TPM_SUCCESS) {
5016
0
    returnCode = TPM_SizedBuffer_Set(&(certifyInfo2.migrationAuthority),
5017
0
             TPM_DIGEST_SIZE, migrationAuthority);
5018
0
      }     
5019
      /* d. if keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED */
5020
      /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_RESTRICTED */
5021
      /* e. if keyHandle -> payload == TPM_PT_MIGRATE_EXTERNAL */
5022
      /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_EXTERNAL */
5023
      /* NOTE: Done by TPM_CertifyInfo2_Set() */
5024
0
  }
5025
  /* 12. Else */
5026
0
  else {
5027
0
      printf("TPM_Process_CertifyKey2: "
5028
0
       " Not TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n");
5029
      /* a. set C1 -> migrationAuthority = NULL */
5030
      /* b. set C1 -> migrationAuthoritySize = 0 */
5031
      /* NOTE: Done by TPM_CertifyInfo2_Init() */
5032
      /* c. Set C1 -> payloadType = TPM_PT_ASYM */
5033
0
      certifyInfo2.payloadType = TPM_PT_ASYM;
5034
0
  }
5035
0
    }
5036
0
    if (returnCode == TPM_SUCCESS) {
5037
  /* 13. If keyHandle -> pcrInfoSize is not 0 */
5038
0
  if (targetKey->pcrInfo.size != 0) {
5039
0
      printf("TPM_Process_CertifyKey2: Setting PCR info from key\n");
5040
      /* a. The TPM MUST set c1 -> pcrInfoSize to match the pcrInfoSize from the keyHandle
5041
         key. */
5042
      /* b. The TPM MUST set c1 -> pcrInfo to match the pcrInfo from the keyHandle key */
5043
      /* This function actually creates the cache, which is serialized later */
5044
0
      if (returnCode == TPM_SUCCESS) {
5045
0
    returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short),
5046
0
                  targetKey);
5047
0
      }
5048
      /* c. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */
5049
      /* i. Create a digestAtRelease according to the specified PCR registers and compare to
5050
         keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */
5051
      /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */
5052
      /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */
5053
0
  }
5054
  /* 14. Else */
5055
  /* a. The TPM MUST set c1 -> pcrInfoSize to 0 */
5056
  /* NOTE: Done by TPM_CertifyInfo2_Init() */
5057
0
    }
5058
    /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1 */
5059
0
    if (returnCode == TPM_SUCCESS) {
5060
0
  printf("TPM_Process_CertifyKey2: Digesting certifyInfo\n");
5061
0
  returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2,
5062
0
            (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store);
5063
0
    }
5064
    /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob
5065
       is returned in outData */
5066
0
    if (returnCode == TPM_SUCCESS) {
5067
0
  printf("TPM_Process_CertifyKey2: Signing certifyInfo digest\n");
5068
0
  returnCode = TPM_RSASignToSizedBuffer(&outData,   /* signature */
5069
0
                m1Digest,   /* message */
5070
0
                TPM_DIGEST_SIZE, /* message size */
5071
0
                certKey);   /* input, signing key */
5072
0
    }
5073
    /*
5074
      response
5075
    */
5076
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
5077
0
    if (rcf == 0) {
5078
0
  printf("TPM_Process_CertifyKey2: Ordinal returnCode %08x %u\n",
5079
0
         returnCode, returnCode);
5080
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
5081
0
    }
5082
    /* success response, append the rest of the parameters.  */
5083
0
    if (rcf == 0) {
5084
0
  if (returnCode == TPM_SUCCESS) {
5085
      /* checkpoint the beginning of the outParam's */
5086
0
      outParamStart = response->buffer_current - response->buffer;
5087
      /* Return certifyInfo */
5088
0
      returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2);
5089
0
  }
5090
0
  if (returnCode == TPM_SUCCESS) {
5091
      /* Return outData */
5092
0
      returnCode = TPM_SizedBuffer_Store(response, &outData);
5093
      /* checkpoint the end of the outParam's */
5094
0
      outParamEnd = response->buffer_current - response->buffer;
5095
0
  }
5096
  /* digest the above the line output parameters */
5097
0
  if (returnCode == TPM_SUCCESS) {
5098
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
5099
0
                 auditStatus, /* input audit status */
5100
0
                 transportEncrypt,
5101
0
                 tag,     
5102
0
                 returnCode,
5103
0
                 ordinal,   /* command ordinal */
5104
0
                 response->buffer + outParamStart,  /* start */
5105
0
                 outParamEnd - outParamStart);  /* length */
5106
0
  }
5107
  /* calculate and set the below the line parameters */
5108
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
5109
0
      returnCode = TPM_AuthParams_Set(response,
5110
0
              *targetHmacKey,   /* HMAC key */
5111
0
              target_auth_session_data,
5112
0
              outParamDigest,
5113
0
              keynonceOdd,
5114
0
              continueKeySession);
5115
0
  }
5116
  /* calculate and set the below the line parameters */
5117
0
  if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) {
5118
0
      returnCode = TPM_AuthParams_Set(response,
5119
0
              *certHmacKey,   /* HMAC key */
5120
0
              cert_auth_session_data,
5121
0
              outParamDigest,
5122
0
              nonceOdd,
5123
0
              continueAuthSession);
5124
0
  }
5125
  /* audit if required */
5126
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
5127
0
      returnCode = TPM_ProcessAudit(tpm_state,
5128
0
            transportEncrypt,
5129
0
            inParamDigest,
5130
0
            outParamDigest,
5131
0
            ordinal);
5132
0
  }
5133
  /* adjust the initial response */
5134
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
5135
0
    }
5136
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
5137
0
    if (((rcf != 0) ||
5138
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
5139
0
   !continueKeySession) &&
5140
0
  keyAuthHandleValid) {
5141
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle);
5142
0
    }
5143
0
    if (((rcf != 0) ||
5144
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
5145
0
   !continueAuthSession) &&
5146
0
  certAuthHandleValid) {
5147
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle);
5148
0
    }
5149
    /*
5150
      cleanup
5151
    */
5152
0
    TPM_CertifyInfo2_Delete(&certifyInfo2); /* @1 */
5153
0
    TPM_SizedBuffer_Delete(&outData);   /* @2 */
5154
0
    TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @3 */
5155
0
    return rcf;
5156
0
}
5157
5158
/* 28.3 TPM_CertifySelfTest rev 94
5159
5160
  CertifySelfTest causes the TPM to perform a full self-test and return an authenticated value if
5161
  the test passes.
5162
5163
  If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM
5164
  and the caller have AuthData.
5165
5166
  If a caller requires proof for a third party, the signing key must be one whose signature is
5167
  trusted by the third party. A TPM-identity key may be suitable.
5168
5169
  Information returned by TPM_CertifySelfTest MUST NOT aid identification of an individual TPM.
5170
*/
5171
5172
TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state,
5173
               TPM_STORE_BUFFER *response,
5174
               TPM_TAG tag,
5175
               uint32_t paramSize,
5176
               TPM_COMMAND_CODE ordinal,
5177
               unsigned char *command,
5178
               TPM_TRANSPORT_INTERNAL *transportInternal)
5179
0
{
5180
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
5181
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
5182
5183
    /* input parameters */
5184
0
    TPM_KEY_HANDLE  keyHandle;  /* The keyHandle identifier of a loaded key that can perform
5185
             digital signatures. */
5186
0
    TPM_NONCE   antiReplay; /* AntiReplay nonce to prevent replay of messages */
5187
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for keyHandle
5188
             authorization */
5189
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
5190
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization session
5191
               handle */
5192
0
    TPM_AUTHDATA  privAuth; /* The authorization session digest that authorizes the
5193
             inputs and use of keyHandle. HMAC key: key.usageAuth */
5194
5195
    /* processing parameters */
5196
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
5197
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
5198
0
    TPM_DIGEST      inParamDigest;
5199
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
5200
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
5201
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
5202
0
    TPM_BOOL      authHandleValid = FALSE;
5203
0
    TPM_SECRET      *hmacKey;
5204
0
    TPM_KEY     *sigKey;      /* from keyHandle */
5205
0
    TPM_BOOL      sigKeyPCRStatus;
5206
0
    TPM_SECRET      *sigKeyUsageAuth;
5207
0
    TPM_COMMAND_CODE    nOrdinal;     /* ordinal in nbo */
5208
0
    TPM_DIGEST      m2Digest;     /* message to sign */
5209
5210
    /* output parameters */
5211
0
    uint32_t      outParamStart;  /* starting point of outParam's */
5212
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
5213
0
    TPM_DIGEST      outParamDigest;
5214
0
    TPM_SIZED_BUFFER    sig;    /* The resulting digital signature. */
5215
5216
0
    printf("TPM_Process_CertifySelfTest: Ordinal Entry\n");
5217
0
    TPM_SizedBuffer_Init(&sig);     /* freed @1 */
5218
    /*
5219
      get inputs
5220
    */
5221
    /* get keyHandle parameter */
5222
0
    if (returnCode == TPM_SUCCESS) {
5223
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
5224
0
    }
5225
    /* save the starting point of inParam's for authorization and auditing */
5226
0
    inParamStart = command;
5227
    /* get the antiReplay parameter */
5228
0
    if (returnCode == TPM_SUCCESS) {
5229
0
  printf("TPM_Process_CertifySelfTest: keyHandle %08x\n", keyHandle);
5230
0
  returnCode = TPM_Nonce_Load(antiReplay, &command, &paramSize);
5231
0
    }
5232
    /* save the ending point of inParam's for authorization and auditing */
5233
0
    inParamEnd = command;
5234
    /* digest the input parameters */
5235
0
    if (returnCode == TPM_SUCCESS) {
5236
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
5237
0
            &auditStatus,   /* output */
5238
0
            &transportEncrypt,  /* output */
5239
0
            tpm_state,
5240
0
            tag,
5241
0
            ordinal,
5242
0
            inParamStart,
5243
0
            inParamEnd,
5244
0
            transportInternal);
5245
0
    }
5246
    /* check state */
5247
0
    if (returnCode == TPM_SUCCESS) {
5248
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
5249
0
    }
5250
    /* check tag */
5251
0
    if (returnCode == TPM_SUCCESS) {
5252
0
  returnCode = TPM_CheckRequestTag10(tag);
5253
0
    }
5254
    /* get the optional 'below the line' authorization parameters */
5255
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
5256
0
  returnCode = TPM_AuthParams_Get(&authHandle,
5257
0
          &authHandleValid,
5258
0
          nonceOdd,
5259
0
          &continueAuthSession,
5260
0
          privAuth,
5261
0
          &command, &paramSize);
5262
0
    }
5263
0
    if (returnCode == TPM_SUCCESS) {
5264
0
  if (paramSize != 0) {
5265
0
      printf("TPM_Process_CertifySelfTest: Error, command has %u extra bytes\n",
5266
0
       paramSize);
5267
0
      returnCode = TPM_BAD_PARAM_SIZE;
5268
0
  }
5269
0
    }
5270
    /* do not terminate sessions if the command did not parse correctly */
5271
0
    if (returnCode != TPM_SUCCESS) {
5272
0
  authHandleValid = FALSE;
5273
0
    }
5274
    /*
5275
      Processing
5276
    */
5277
    /* 1. The TPM SHALL perform TPM_SelfTestFull. If the test fails the TPM returns the appropriate
5278
       error code. */
5279
0
    if (returnCode == TPM_SUCCESS) {
5280
0
  printf("TPM_Process_CertifySelfTest: Running self test\n");
5281
0
  returnCode = TPM_SelfTestFullCmd(tpm_state);
5282
0
    }
5283
    /* 2. After successful completion of the self-test the TPM then validates the authorization to
5284
       use the key pointed to by keyHandle */
5285
0
    if (returnCode == TPM_SUCCESS) {
5286
0
  returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &sigKeyPCRStatus, tpm_state, keyHandle,
5287
0
             FALSE,   /* not read-only */
5288
0
             FALSE,   /* do not ignore PCRs */
5289
0
             FALSE);  /* cannot use EK */
5290
0
    }
5291
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){
5292
0
  if (sigKey->authDataUsage != TPM_AUTH_NEVER) { 
5293
0
      printf("TPM_Process_CertifySelfTest: Error, authorization required\n");
5294
0
      returnCode = TPM_AUTHFAIL;
5295
0
  }
5296
0
    }
5297
    /* get keyHandle -> usageAuth */
5298
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
5299
0
  returnCode = TPM_Key_GetUsageAuth(&sigKeyUsageAuth, sigKey);
5300
0
    }   
5301
    /* get the session data */
5302
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
5303
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
5304
0
                &hmacKey,
5305
0
                tpm_state,
5306
0
                authHandle,
5307
0
                TPM_PID_NONE,
5308
0
                TPM_ET_KEYHANDLE,
5309
0
                ordinal,
5310
0
                sigKey,
5311
0
                sigKeyUsageAuth,    /* OIAP */
5312
0
                sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
5313
0
    }
5314
    /* Validate the command parameters using privAuth */
5315
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
5316
0
  returnCode = TPM_Authdata_Check(tpm_state,
5317
0
          *hmacKey,   /* HMAC key */
5318
0
          inParamDigest,
5319
0
          auth_session_data,  /* authorization session */
5320
0
          nonceOdd,   /* Nonce generated by system
5321
                   associated with authHandle */
5322
0
          continueAuthSession,
5323
0
          privAuth);    /* Authorization digest for input */
5324
0
    }
5325
    /* a. If the key pointed to by keyHandle has a signature scheme that is not
5326
       TPM_SS_RSASSAPKCS1v15_SHA1, the TPM may either return TPM_BAD_SCHEME or may return
5327
       TPM_SUCCESS and a vendor specific signature. */
5328
0
    if (returnCode == TPM_SUCCESS) {
5329
0
  if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {
5330
0
      printf("TPM_Process_CertifySelfTest: Error, invalid sigKey sigScheme %04hx\n",
5331
0
       sigKey->algorithmParms.sigScheme);
5332
0
      returnCode = TPM_BAD_SCHEME;
5333
0
  }
5334
0
    }
5335
    /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or
5336
       TPM_KEY_IDENTITY. */
5337
0
    if (returnCode == TPM_SUCCESS) {
5338
0
  if ((sigKey->keyUsage != TPM_KEY_SIGNING) &&
5339
0
      (sigKey->keyUsage != TPM_KEY_LEGACY) &&
5340
0
      (sigKey->keyUsage != TPM_KEY_IDENTITY)) {
5341
0
      printf("TPM_Process_CertifySelfTest: Error, Illegal keyUsage %04hx\n",
5342
0
       sigKey->keyUsage);
5343
0
      returnCode = TPM_INVALID_KEYUSAGE;
5344
0
  }
5345
0
    }  
5346
    /* 3. Create t1 the NOT null terminated string of "Test Passed" */
5347
    /* 4. The TPM creates m2 the message to sign by concatenating t1 || AntiReplay || ordinal. */
5348
0
    if (returnCode == TPM_SUCCESS) {
5349
0
  nOrdinal = htonl(ordinal);
5350
0
  returnCode = TPM_SHA1(m2Digest,
5351
0
            sizeof("Test Passed") - 1, "Test Passed",
5352
0
            TPM_NONCE_SIZE, antiReplay,
5353
0
            sizeof(TPM_COMMAND_CODE), &nOrdinal,
5354
0
            0, NULL);
5355
0
    }
5356
    /* 5. The TPM signs the SHA-1 of m2 using the key identified by keyHandle, and returns the
5357
       signature as sig. */
5358
0
    if (returnCode == TPM_SUCCESS) {
5359
0
  printf("TPM_Process_CertifySelfTest: Signing certifyInfo digest\n");
5360
0
  returnCode = TPM_RSASignToSizedBuffer(&sig,   /* signature */
5361
0
                m2Digest,   /* message */
5362
0
                TPM_DIGEST_SIZE, /* message size */
5363
0
                sigKey);    /* input, signing key */
5364
0
    }
5365
    /*
5366
      response
5367
    */
5368
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
5369
0
    if (rcf == 0) {
5370
0
  printf("TPM_Process_CertifySelfTest: Ordinal returnCode %08x %u\n",
5371
0
         returnCode, returnCode);
5372
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
5373
0
    }
5374
    /* success response, append the rest of the parameters.  */
5375
0
    if (rcf == 0) {
5376
0
  if (returnCode == TPM_SUCCESS) {
5377
      /* checkpoint the beginning of the outParam's */
5378
0
      outParamStart = response->buffer_current - response->buffer;
5379
      /* return sig */
5380
0
      returnCode = TPM_SizedBuffer_Store(response, &sig);
5381
      /* checkpoint the end of the outParam's */
5382
0
      outParamEnd = response->buffer_current - response->buffer;
5383
0
  }
5384
  /* digest the above the line output parameters */
5385
0
  if (returnCode == TPM_SUCCESS) {
5386
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
5387
0
                 auditStatus, /* input audit status */
5388
0
                 transportEncrypt,
5389
0
                 tag,     
5390
0
                 returnCode,
5391
0
                 ordinal,   /* command ordinal */
5392
0
                 response->buffer + outParamStart,  /* start */
5393
0
                 outParamEnd - outParamStart);  /* length */
5394
0
  }
5395
  /* calculate and set the below the line parameters */
5396
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
5397
0
      returnCode = TPM_AuthParams_Set(response,
5398
0
              *hmacKey,   /* owner HMAC key */
5399
0
              auth_session_data,
5400
0
              outParamDigest,
5401
0
              nonceOdd,
5402
0
              continueAuthSession);
5403
0
  }
5404
  /* audit if required */
5405
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
5406
0
      returnCode = TPM_ProcessAudit(tpm_state,
5407
0
            transportEncrypt,
5408
0
            inParamDigest,
5409
0
            outParamDigest,
5410
0
            ordinal);
5411
0
  }
5412
  /* adjust the initial response */
5413
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
5414
0
    }
5415
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
5416
0
    if (((rcf != 0) ||
5417
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
5418
0
   !continueAuthSession) &&
5419
0
  authHandleValid) {
5420
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
5421
0
    }
5422
    /*
5423
      cleanup
5424
    */
5425
0
    TPM_SizedBuffer_Delete(&sig);     /* @1 */
5426
0
    return rcf;
5427
0
}