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 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