Coverage Report

Created: 2025-07-09 06:11

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