Coverage Report

Created: 2026-06-30 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtpms/src/tpm2/AttestationCommands.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*         Attestation Commands         */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: AttestationCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source CoDe must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2021       */
59
/*                    */
60
/********************************************************************************/
61
62
#include "Tpm.h"
63
#include "Attest_spt_fp.h"
64
#include "Certify_fp.h"
65
#if CC_Certify  // Conditional expansion of this file
66
TPM_RC
67
TPM2_Certify(
68
       Certify_In      *in,            // IN: input parameter list
69
       Certify_Out     *out            // OUT: output parameter list
70
       )
71
0
{
72
0
    TPMS_ATTEST             certifyInfo;
73
0
    OBJECT                  *signObject = HandleToObject(in->signHandle);
74
0
    OBJECT                  *certifiedObject = HandleToObject(in->objectHandle);
75
    // Input validation
76
0
    if(!IsSigningObject(signObject))
77
0
  return TPM_RCS_KEY + RC_Certify_signHandle;
78
0
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
79
0
  return TPM_RCS_SCHEME + RC_Certify_inScheme;
80
    // Command Output
81
    // Filling in attest information
82
    // Common fields
83
0
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
84
0
         &certifyInfo);
85
    // Certify specific fields
86
0
    certifyInfo.type = TPM_ST_ATTEST_CERTIFY;
87
    // NOTE: the certified object is not allowed to be TPM_ALG_NULL so
88
    // 'certifiedObject' will never be NULL
89
0
    pAssert_RC(certifiedObject != NULL);  // should have been filtered earlier.
90
0
    certifyInfo.attested.certify.name = certifiedObject->name;
91
92
    // When using an anonymous signing scheme, need to set the qualified Name to the
93
    // empty buffer to avoid correlation between keys
94
0
    if(CryptIsSchemeAnonymous(in->inScheme.scheme))
95
0
  certifyInfo.attested.certify.qualifiedName.t.size = 0;
96
0
    else
97
0
  certifyInfo.attested.certify.qualifiedName = certifiedObject->qualifiedName;
98
99
    // Sign attestation structure.  A NULL signature will be returned if
100
    // signHandle is TPM_RH_NULL.  A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
101
    // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned
102
    // by SignAttestInfo()
103
0
    return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
104
0
        &in->qualifyingData, &out->certifyInfo, &out->signature);
105
0
}
106
#endif // CC_Certify
107
#include "Tpm.h"
108
#include "Attest_spt_fp.h"
109
#include "CertifyCreation_fp.h"
110
#if CC_CertifyCreation  // Conditional expansion of this file
111
TPM_RC
112
TPM2_CertifyCreation(
113
         CertifyCreation_In      *in,            // IN: input parameter list
114
         CertifyCreation_Out     *out            // OUT: output parameter list
115
         )
116
0
{
117
0
    TPMT_TK_CREATION        ticket;
118
0
    TPMS_ATTEST             certifyInfo;
119
0
    OBJECT                  *certified = HandleToObject(in->objectHandle);
120
0
    OBJECT                  *signObject = HandleToObject(in->signHandle);
121
    // Input Validation
122
0
    if(!IsSigningObject(signObject))
123
0
  return TPM_RCS_KEY + RC_CertifyCreation_signHandle;
124
0
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
125
0
  return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme;
126
127
0
    pAssert_RC(certified != NULL);
128
    // CertifyCreation specific input validation
129
    // Re-compute ticket
130
0
    TicketComputeCreation(in->creationTicket.hierarchy, &certified->name,
131
0
        &in->creationHash, &ticket);
132
    // Compare ticket
133
0
    if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b))
134
0
  return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket;
135
    // Command Output
136
    // Common fields
137
0
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
138
0
         &certifyInfo);
139
    // CertifyCreation specific fields
140
    // Attestation type
141
0
    certifyInfo.type = TPM_ST_ATTEST_CREATION;
142
0
    certifyInfo.attested.creation.objectName = certified->name;
143
    // Copy the creationHash
144
0
    certifyInfo.attested.creation.creationHash = in->creationHash;
145
    // Sign attestation structure.  A NULL signature will be returned if
146
    // signObject is TPM_RH_NULL.  A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
147
    // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
148
    // this point
149
0
    return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
150
0
        &in->qualifyingData, &out->certifyInfo,
151
0
        &out->signature);
152
0
}
153
#endif // CC_CertifyCreation
154
#include "Tpm.h"
155
#include "Attest_spt_fp.h"
156
#include "GetSessionAuditDigest_fp.h"
157
#if CC_GetSessionAuditDigest  // Conditional expansion of this file
158
TPM_RC
159
TPM2_GetSessionAuditDigest(
160
         GetSessionAuditDigest_In    *in,            // IN: input parameter list
161
         GetSessionAuditDigest_Out   *out            // OUT: output parameter list
162
         )
163
0
{
164
0
    SESSION* session = SessionGet(in->sessionHandle);
165
0
    pAssert_RC(session);
166
0
    TPMS_ATTEST auditInfo;
167
0
    OBJECT*     signObject = HandleToObject(in->signHandle);
168
    // Input Validation
169
0
    if(!IsSigningObject(signObject))
170
0
  return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle;
171
0
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
172
0
  return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme;
173
    // session must be an audit session
174
0
    if(session->attributes.isAudit == CLEAR)
175
0
  return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle;
176
    // Command Output
177
    // Fill in attest information common fields
178
0
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
179
0
         &auditInfo);
180
    // SessionAuditDigest specific fields
181
0
    auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT;
182
0
    auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest;
183
    // Exclusive audit session
184
0
    auditInfo.attested.sessionAudit.exclusiveSession
185
0
  = (g_exclusiveAuditSession == in->sessionHandle);
186
    // Sign attestation structure.  A NULL signature will be returned if
187
    // signObject is NULL.
188
0
    return SignAttestInfo(signObject, &in->inScheme, &auditInfo,
189
0
        &in->qualifyingData, &out->auditInfo,
190
0
        &out->signature);
191
0
}
192
#endif // CC_GetSessionAuditDigest
193
#include "Tpm.h"
194
#include "Attest_spt_fp.h"
195
#include "GetCommandAuditDigest_fp.h"
196
#if CC_GetCommandAuditDigest  // Conditional expansion of this file
197
TPM_RC
198
TPM2_GetCommandAuditDigest(
199
         GetCommandAuditDigest_In    *in,            // IN: input parameter list
200
         GetCommandAuditDigest_Out   *out            // OUT: output parameter list
201
         )
202
0
{
203
0
    TPM_RC                  result;
204
0
    TPMS_ATTEST             auditInfo;
205
0
    OBJECT                 *signObject = HandleToObject(in->signHandle);
206
    // Input validation
207
0
    if(!IsSigningObject(signObject))
208
0
  return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle;
209
0
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
210
0
  return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme;
211
    // Command Output
212
    // Fill in attest information common fields
213
0
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
214
0
         &auditInfo);
215
    // CommandAuditDigest specific fields
216
0
    auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT;
217
0
    auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg;
218
0
    auditInfo.attested.commandAudit.auditCounter = gp.auditCounter;
219
    // Copy command audit log
220
0
    auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest;
221
0
    CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest);
222
    // Sign attestation structure.  A NULL signature will be returned if
223
    // signHandle is TPM_RH_NULL.  A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
224
    // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
225
    // this point
226
0
    result = SignAttestInfo(signObject, &in->inScheme, &auditInfo,
227
0
          &in->qualifyingData, &out->auditInfo,
228
0
          &out->signature);
229
    // Internal Data Update
230
0
    if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL)
231
  // Reset log
232
0
  gr.commandAuditDigest.t.size = 0;
233
0
    return result;
234
0
}
235
#endif // CC_GetCommandAuditDigest
236
#include "Tpm.h"
237
#include "Attest_spt_fp.h"
238
#include "GetTime_fp.h"
239
#if CC_GetTime  // Conditional expansion of this file
240
TPM_RC
241
TPM2_GetTime(
242
       GetTime_In      *in,            // IN: input parameter list
243
       GetTime_Out     *out            // OUT: output parameter list
244
       )
245
0
{
246
0
    TPMS_ATTEST             timeInfo;
247
0
    OBJECT                 *signObject = HandleToObject(in->signHandle);
248
    // Input Validation
249
0
    if(!IsSigningObject(signObject))
250
0
  return TPM_RCS_KEY + RC_GetTime_signHandle;
251
0
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
252
0
  return TPM_RCS_SCHEME + RC_GetTime_inScheme;
253
    // Command Output
254
    // Fill in attest common fields
255
0
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &timeInfo);
256
    // GetClock specific fields
257
0
    timeInfo.type = TPM_ST_ATTEST_TIME;
258
0
    timeInfo.attested.time.time.time = g_time;
259
0
    TimeFillInfo(&timeInfo.attested.time.time.clockInfo);
260
    // Firmware version in plain text
261
0
    timeInfo.attested.time.firmwareVersion
262
0
  = (((UINT64)gp.firmwareV1) << 32) + gp.firmwareV2;
263
    // Sign attestation structure.  A NULL signature will be returned if
264
    // signObject is NULL.
265
0
    return SignAttestInfo(signObject, &in->inScheme, &timeInfo, &in->qualifyingData,
266
0
        &out->timeInfo, &out->signature);
267
0
}
268
#endif // CC_GetTime
269
#include "Tpm.h"
270
#include "CertifyX509_fp.h"
271
#include "X509.h"
272
#include "TpmASN1_fp.h"
273
#include "X509_spt_fp.h"
274
#include "Attest_spt_fp.h"
275
#if CC_CertifyX509 // Conditional expansion of this file
276
#if CERTIFYX509_DEBUG
277
#  include "tpm_to_platform_interface.h"
278
#endif
279
280
/* Error Returns  Meaning*/
281
/* TPM_RC_ATTRIBUTES  the attributes of objectHandle are not compatible with the KeyUsage() or TPMA_OBJECT values in the extensions fields */
282
/* TPM_RC_BINDING the public and private portions of the key are not properly bound. */
283
/* TPM_RC_HASH  the hash algorithm in the scheme is not supported */
284
/* TPM_RC_KEY signHandle does not reference a signing key; */
285
/* TPM_RC_SCHEME  the scheme is not compatible with sign key type, or input scheme is not compatible with default scheme, or the chosen scheme is not a valid sign scheme */
286
    /* TPM_RC_VALUE most likely a problem with the format of partialCertificate */
287
TPM_RC
288
TPM2_CertifyX509(
289
     CertifyX509_In          *in,          // IN: input parameter list
290
     CertifyX509_Out         *out            // OUT: output parameter list
291
     )
292
0
{
293
0
    TPM_RC                   result;
294
0
    OBJECT                  *signKey = HandleToObject(in->signHandle);
295
0
    OBJECT                  *object = HandleToObject(in->objectHandle);
296
0
    HASH_STATE               hash;
297
0
    INT16                    length;        // length for a tagged element
298
0
    ASN1UnmarshalContext     ctx;
299
0
    ASN1MarshalContext       ctxOut;
300
0
    pAssert_RC(object != NULL);
301
302
    // certTBS holds an array of pointers and lengths. Each entry references the
303
    // corresponding value in a TBSCertificate structure. For example, the 1th
304
    // element references the version number
305
0
    stringRef                certTBS[REF_COUNT] = {{0}};
306
0
#define ALLOWED_SEQUENCES   (SUBJECT_PUBLIC_KEY_REF - SIGNATURE_REF)
307
0
    stringRef                partial[ALLOWED_SEQUENCES] = {{0}};
308
0
    INT16                    countOfSequences = 0;
309
0
    INT16                    i;
310
    //
311
#if CERTIFYX509_DEBUG
312
    DebugFileInit();
313
    DebugDumpBuffer(in->partialCertificate.t.size, in->partialCertificate.t.buffer,
314
        "partialCertificate");
315
#endif
316
317
    // Input Validation
318
0
    if(in->reserved.b.size != 0)
319
0
  return TPM_RC_SIZE + RC_CertifyX509_reserved;
320
    // signing key must be able to sign
321
0
    if(!IsSigningObject(signKey))
322
0
  return TPM_RCS_KEY + RC_CertifyX509_signHandle;
323
    // Pick a scheme for sign.  If the input sign scheme is not compatible with
324
    // the default scheme, return an error.
325
0
    if(!CryptSelectSignScheme(signKey, &in->inScheme))
326
0
  return TPM_RCS_SCHEME + RC_CertifyX509_inScheme;
327
    // Make sure that the public Key encoding is known
328
0
    if(X509AddPublicKey(NULL, object) == 0)
329
0
  return TPM_RCS_ASYMMETRIC + RC_CertifyX509_objectHandle;
330
    // Unbundle 'partialCertificate'.
331
    // Initialize the unmarshaling context
332
0
    if(!ASN1UnmarshalContextInitialize(&ctx, in->partialCertificate.t.size,
333
0
               in->partialCertificate.t.buffer))
334
0
  return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
335
    // Make sure that this is a constructed SEQUENCE
336
0
    length = ASN1NextTag(&ctx);
337
    // Must be a constructed SEQUENCE that uses all of the input parameter
338
0
    if((ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE))
339
0
       || ((ctx.offset + length) != in->partialCertificate.t.size))
340
0
  return TPM_RCS_SIZE + RC_CertifyX509_partialCertificate;
341
    
342
    // This scans through the contents of the outermost SEQUENCE. This would be the
343
    // 'issuer', 'validity', 'subject', 'issuerUniqueID' (optional),
344
    // 'subjectUniqueID' (optional), and 'extensions.'
345
0
    while(ctx.offset < ctx.size)
346
0
  {
347
0
      INT16           startOfElement = ctx.offset;
348
      //
349
      // Read the next tag and length field.
350
0
      length = ASN1NextTag(&ctx);
351
0
      if(length < 0)
352
0
    break;
353
0
      if(ctx.tag == ASN1_CONSTRUCTED_SEQUENCE)
354
0
          {
355
0
              partial[countOfSequences].buf = &ctx.buffer[startOfElement];
356
0
              ctx.offset += length;
357
0
              partial[countOfSequences].len = (INT16)ctx.offset - startOfElement;
358
0
              if(++countOfSequences > ALLOWED_SEQUENCES)
359
0
                  break;
360
0
          }
361
0
      else if(ctx.tag  == X509_EXTENSIONS)
362
0
          {
363
0
              if(certTBS[EXTENSIONS_REF].len != 0)
364
0
                  return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
365
0
              certTBS[EXTENSIONS_REF].buf = &ctx.buffer[startOfElement];
366
0
              ctx.offset += length;
367
0
              certTBS[EXTENSIONS_REF].len =
368
0
                  (INT16)ctx.offset - startOfElement;
369
0
          }
370
0
      else
371
0
    return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
372
0
  }
373
    // Make sure that we used all of the data and found at least the required
374
    // number of elements.
375
0
    if((ctx.offset != ctx.size) || (countOfSequences < 3)
376
0
       || (countOfSequences > 4)
377
0
       || (certTBS[EXTENSIONS_REF].buf == NULL))
378
0
  return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
379
    // Now that we know how many sequences there were, we can put them where they
380
    // belong
381
0
    for(i = 0; i < countOfSequences; i++)
382
0
  certTBS[SUBJECT_KEY_REF - i] = partial[countOfSequences - 1 - i];
383
384
    // If only three SEQUENCES, then the TPM needs to produce the signature algorithm.
385
    // See if it can
386
0
    if((countOfSequences == 3) &&
387
0
       (X509AddSigningAlgorithm(NULL, signKey, &in->inScheme) == 0))
388
0
  return TPM_RCS_SCHEME + RC_CertifyX509_signHandle;
389
390
    // Process the extensions
391
0
    result = X509ProcessExtensions(object, &certTBS[EXTENSIONS_REF]);
392
0
    if(result != TPM_RC_SUCCESS)
393
  // If the extension has the TPMA_OBJECT extension and the attributes don't
394
  // match, then the error code will be TPM_RCS_ATTRIBUTES. Otherwise, the error
395
  // indicates a malformed partialCertificate.
396
0
  return result + ((result == TPM_RCS_ATTRIBUTES)
397
0
       ? RC_CertifyX509_objectHandle
398
0
       : RC_CertifyX509_partialCertificate);
399
    // Command Output
400
    // Create the addedToCertificate values
401
402
    // Build the addedToCertificate from the bottom up.
403
    // Initialize the context structure
404
0
    ASN1InitialializeMarshalContext(&ctxOut, sizeof(out->addedToCertificate.t.buffer),
405
0
            out->addedToCertificate.t.buffer);
406
    // Place a marker for the overall context
407
0
    ASN1StartMarshalContext(&ctxOut);  // SEQUENCE for addedToCertificate
408
409
    // Add the subject public key descriptor
410
0
    certTBS[SUBJECT_PUBLIC_KEY_REF].len = X509AddPublicKey(&ctxOut, object);
411
0
    certTBS[SUBJECT_PUBLIC_KEY_REF].buf = ctxOut.buffer + ctxOut.offset;
412
    // If the caller didn't provide the algorithm identifier, create it
413
0
    if(certTBS[SIGNATURE_REF].len == 0)
414
0
  {
415
0
      certTBS[SIGNATURE_REF].len = X509AddSigningAlgorithm(&ctxOut, signKey,
416
0
                 &in->inScheme);
417
0
      certTBS[SIGNATURE_REF].buf = ctxOut.buffer + ctxOut.offset;
418
0
  }
419
    // Create the serial number value. Use the out->tbsDigest as scratch.
420
0
    {
421
0
  TPM2B                   *digest = &out->tbsDigest.b;
422
  //
423
0
  digest->size = (INT16)CryptHashStart(&hash, signKey->publicArea.nameAlg);
424
0
  pAssert(digest->size != 0);
425
426
  // The serial number size is the smaller of the digest and the vendor-defined
427
  // value
428
0
  digest->size = MIN(digest->size, SIZE_OF_X509_SERIAL_NUMBER);
429
  // Add all the parts of the certificate other than the serial number
430
  // and version number
431
0
  for(i = SIGNATURE_REF; i < REF_COUNT; i++)
432
0
      CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf);
433
  // throw in the Name of the signing key...
434
0
  CryptDigestUpdate2B(&hash, &signKey->name.b);
435
  // ...and the Name of the signed key.
436
0
  CryptDigestUpdate2B(&hash, &object->name.b);
437
  // Done
438
0
  CryptHashEnd2B(&hash, digest);
439
0
    }
440
441
    // Add the serial number
442
0
    certTBS[SERIAL_NUMBER_REF].len =
443
0
  ASN1PushInteger(&ctxOut, out->tbsDigest.t.size, out->tbsDigest.t.buffer);
444
0
    certTBS[SERIAL_NUMBER_REF].buf = ctxOut.buffer + ctxOut.offset;
445
446
    // Add the static version number
447
0
    ASN1StartMarshalContext(&ctxOut);
448
0
    ASN1PushUINT(&ctxOut, 2);
449
0
    certTBS[VERSION_REF].len =
450
0
  ASN1EndEncapsulation(&ctxOut, ASN1_APPLICAIION_SPECIFIC);
451
0
    certTBS[VERSION_REF].buf = ctxOut.buffer + ctxOut.offset;
452
453
    // Create a fake tag and length for the TBS in the space used for
454
    // 'addedToCertificate'
455
0
    {
456
0
  for(length = 0, i = 0; i < REF_COUNT; i++)
457
0
      length += certTBS[i].len;
458
  // Put a fake tag and length into the buffer for use in the tbsDigest
459
0
  certTBS[ENCODED_SIZE_REF].len =
460
0
      ASN1PushTagAndLength(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE, length);
461
0
  certTBS[ENCODED_SIZE_REF].buf = ctxOut.buffer + ctxOut.offset;
462
  // Restore the buffer pointer to add back the number of octets used for the
463
  // tag and length
464
0
  ctxOut.offset += certTBS[ENCODED_SIZE_REF].len;
465
0
    }
466
    // sanity check
467
0
    if(ctxOut.offset < 0)
468
0
  return TPM_RC_FAILURE;
469
    // Create the tbsDigest to sign
470
0
    out->tbsDigest.t.size = CryptHashStart(&hash, in->inScheme.details.any.hashAlg);
471
0
    for(i = 0; i < REF_COUNT; i++)
472
0
  CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf);
473
0
    CryptHashEnd2B(&hash, &out->tbsDigest.b);
474
475
#if CERTIFYX509_DEBUG
476
    {
477
  BYTE                 fullTBS[4096];
478
  BYTE                *fill = fullTBS;
479
  int                  j;
480
  for (j = 0; j < REF_COUNT; j++)
481
      {
482
    MemoryCopy(fill, certTBS[j].buf, certTBS[j].len);
483
    fill += certTBS[j].len;
484
      }
485
  DebugDumpBuffer((int)(fill - &fullTBS[0]), fullTBS, "\nfull TBS");
486
    }
487
#endif
488
489
    // Finish up the processing of addedToCertificate
490
    // Create the actual tag and length for the addedToCertificate structure
491
0
    out->addedToCertificate.t.size =
492
0
  ASN1EndEncapsulation(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE);
493
    // Now move all the addedToContext to the start of the buffer
494
0
    MemoryCopy(out->addedToCertificate.t.buffer, ctxOut.buffer + ctxOut.offset,
495
0
         out->addedToCertificate.t.size);
496
#if CERTIFYX509_DEBUG
497
    DebugDumpBuffer(out->addedToCertificate.t.size, out->addedToCertificate.t.buffer,
498
        "\naddedToCertificate");
499
#endif
500
    // only thing missing is the signature
501
0
    result = CryptSign(signKey, &in->inScheme, &out->tbsDigest, &out->signature);
502
503
0
    return result;
504
0
}
505
#endif // CC_CertifyX509