1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "Sign_fp.h"
10 #include "Attest_spt_fp.h"
11 //
12 //
13 //     Error Returns                     Meaning
14 //
15 //     TPM_RC_BINDING                    The public and private portions of the key are not properly bound.
16 //     TPM_RC_KEY                        signHandle does not reference a signing key;
17 //     TPM_RC_SCHEME                     the scheme is not compatible with sign key type, or input scheme is
18 //                                       not compatible with default scheme, or the chosen scheme is not a
19 //                                       valid sign scheme
20 //     TPM_RC_TICKET                     validation is not a valid ticket
21 //     TPM_RC_VALUE                      the value to sign is larger than allowed for the type of keyHandle
22 //
23 TPM_RC
TPM2_Sign(Sign_In * in,Sign_Out * out)24 TPM2_Sign(
25    Sign_In          *in,                   // IN: input parameter list
26    Sign_Out         *out                   // OUT: output parameter list
27    )
28 {
29    TPM_RC                     result;
30    TPMT_TK_HASHCHECK          ticket;
31    OBJECT                    *signKey;
32 
33 // Input Validation
34    // Get sign key pointer
35    signKey = ObjectGet(in->keyHandle);
36 
37    // pick a scheme for sign. If the input sign scheme is not compatible with
38    // the default scheme, return an error.
39    result = CryptSelectSignScheme(in->keyHandle, &in->inScheme);
40    if(result != TPM_RC_SUCCESS)
41    {
42        if(result == TPM_RC_KEY)
43            return TPM_RC_KEY + RC_Sign_keyHandle;
44        else
45            return RcSafeAddToResult(result, RC_Sign_inScheme);
46    }
47 
48    // If validation is provided, or the key is restricted, check the ticket
49    if(   in->validation.digest.t.size != 0
50       || signKey->publicArea.objectAttributes.restricted == SET)
51    {
52        // Compute and compare ticket
53        TicketComputeHashCheck(in->validation.hierarchy,
54                               in->inScheme.details.any.hashAlg,
55                               &in->digest, &ticket);
56 
57        if(!Memory2BEqual(&in->validation.digest.b, &ticket.digest.b))
58            return TPM_RC_TICKET + RC_Sign_validation;
59    }
60    else
61    // If we don't have a ticket, at least verify that the provided 'digest'
62    // is the size of the scheme hashAlg digest.
63    // NOTE: this does not guarantee that the 'digest' is actually produced using
64    // the indicated hash algorithm, but at least it might be.
65    {
66        if(       in->digest.t.size
67              != CryptGetHashDigestSize(in->inScheme.details.any.hashAlg))
68              return TPM_RC_SIZE + RC_Sign_digest;
69    }
70 
71 // Command Output
72    // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME
73    // error may be returned at this point
74    result = CryptSign(in->keyHandle, &in->inScheme, &in->digest, &out->signature);
75 
76    return result;
77 }
78