1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen //
37*5c591343SA. Cody Schuffelen // This module contains the interfaces to the CryptoEngine and provides
38*5c591343SA. Cody Schuffelen // miscellaneous cryptographic functions in support of the TPM.
39*5c591343SA. Cody Schuffelen //
40*5c591343SA. Cody Schuffelen
41*5c591343SA. Cody Schuffelen //** Includes
42*5c591343SA. Cody Schuffelen #include "Tpm.h"
43*5c591343SA. Cody Schuffelen
44*5c591343SA. Cody Schuffelen //****************************************************************************/
45*5c591343SA. Cody Schuffelen //** Hash/HMAC Functions
46*5c591343SA. Cody Schuffelen //****************************************************************************/
47*5c591343SA. Cody Schuffelen
48*5c591343SA. Cody Schuffelen //*** CryptHmacSign()
49*5c591343SA. Cody Schuffelen // Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a
50*5c591343SA. Cody Schuffelen // message.
51*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
52*5c591343SA. Cody Schuffelen // TPM_RC_HASH not a valid hash
53*5c591343SA. Cody Schuffelen static TPM_RC
CryptHmacSign(TPMT_SIGNATURE * signature,OBJECT * signKey,TPM2B_DIGEST * hashData)54*5c591343SA. Cody Schuffelen CryptHmacSign(
55*5c591343SA. Cody Schuffelen TPMT_SIGNATURE *signature, // OUT: signature
56*5c591343SA. Cody Schuffelen OBJECT *signKey, // IN: HMAC key sign the hash
57*5c591343SA. Cody Schuffelen TPM2B_DIGEST *hashData // IN: hash to be signed
58*5c591343SA. Cody Schuffelen )
59*5c591343SA. Cody Schuffelen {
60*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
61*5c591343SA. Cody Schuffelen UINT32 digestSize;
62*5c591343SA. Cody Schuffelen
63*5c591343SA. Cody Schuffelen digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg,
64*5c591343SA. Cody Schuffelen &signKey->sensitive.sensitive.bits.b);
65*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &hashData->b);
66*5c591343SA. Cody Schuffelen CryptHmacEnd(&hmacState, digestSize,
67*5c591343SA. Cody Schuffelen (BYTE *)&signature->signature.hmac.digest);
68*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
69*5c591343SA. Cody Schuffelen }
70*5c591343SA. Cody Schuffelen
71*5c591343SA. Cody Schuffelen //*** CryptHMACVerifySignature()
72*5c591343SA. Cody Schuffelen // This function will verify a signature signed by a HMAC key.
73*5c591343SA. Cody Schuffelen // Note that a caller needs to prepare 'signature' with the signature algorithm
74*5c591343SA. Cody Schuffelen // (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds a
75*5c591343SA. Cody Schuffelen // signature of that type.
76*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
77*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME not the proper scheme for this key type
78*5c591343SA. Cody Schuffelen // TPM_RC_SIGNATURE if invalid input or signature is not genuine
79*5c591343SA. Cody Schuffelen static TPM_RC
CryptHMACVerifySignature(OBJECT * signKey,TPM2B_DIGEST * hashData,TPMT_SIGNATURE * signature)80*5c591343SA. Cody Schuffelen CryptHMACVerifySignature(
81*5c591343SA. Cody Schuffelen OBJECT *signKey, // IN: HMAC key signed the hash
82*5c591343SA. Cody Schuffelen TPM2B_DIGEST *hashData, // IN: digest being verified
83*5c591343SA. Cody Schuffelen TPMT_SIGNATURE *signature // IN: signature to be verified
84*5c591343SA. Cody Schuffelen )
85*5c591343SA. Cody Schuffelen {
86*5c591343SA. Cody Schuffelen TPMT_SIGNATURE test;
87*5c591343SA. Cody Schuffelen TPMT_KEYEDHASH_SCHEME *keyScheme =
88*5c591343SA. Cody Schuffelen &signKey->publicArea.parameters.keyedHashDetail.scheme;
89*5c591343SA. Cody Schuffelen //
90*5c591343SA. Cody Schuffelen if((signature->sigAlg != TPM_ALG_HMAC)
91*5c591343SA. Cody Schuffelen || (signature->signature.hmac.hashAlg == TPM_ALG_NULL))
92*5c591343SA. Cody Schuffelen return TPM_RC_SCHEME;
93*5c591343SA. Cody Schuffelen // This check is not really needed for verification purposes. However, it does
94*5c591343SA. Cody Schuffelen // prevent someone from trying to validate a signature using a weaker hash
95*5c591343SA. Cody Schuffelen // algorithm than otherwise allowed by the key. That is, a key with a scheme
96*5c591343SA. Cody Schuffelen // other than TMP_ALG_NULL can only be used to validate signatures that have
97*5c591343SA. Cody Schuffelen // a matching scheme.
98*5c591343SA. Cody Schuffelen if((keyScheme->scheme != TPM_ALG_NULL)
99*5c591343SA. Cody Schuffelen && ((keyScheme->scheme != signature->sigAlg)
100*5c591343SA. Cody Schuffelen || (keyScheme->details.hmac.hashAlg
101*5c591343SA. Cody Schuffelen != signature->signature.any.hashAlg)))
102*5c591343SA. Cody Schuffelen return TPM_RC_SIGNATURE;
103*5c591343SA. Cody Schuffelen test.sigAlg = signature->sigAlg;
104*5c591343SA. Cody Schuffelen test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg;
105*5c591343SA. Cody Schuffelen
106*5c591343SA. Cody Schuffelen CryptHmacSign(&test, signKey, hashData);
107*5c591343SA. Cody Schuffelen
108*5c591343SA. Cody Schuffelen // Compare digest
109*5c591343SA. Cody Schuffelen if(!MemoryEqual(&test.signature.hmac.digest,
110*5c591343SA. Cody Schuffelen &signature->signature.hmac.digest,
111*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(signature->signature.any.hashAlg)))
112*5c591343SA. Cody Schuffelen return TPM_RC_SIGNATURE;
113*5c591343SA. Cody Schuffelen
114*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
115*5c591343SA. Cody Schuffelen }
116*5c591343SA. Cody Schuffelen
117*5c591343SA. Cody Schuffelen //*** CryptGenerateKeyedHash()
118*5c591343SA. Cody Schuffelen // This function creates a keyedHash object.
119*5c591343SA. Cody Schuffelen // Return type: TPM_RC
120*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT cannot get values from random number generator
121*5c591343SA. Cody Schuffelen // TPM_RC_SIZE sensitive data size is larger than allowed for
122*5c591343SA. Cody Schuffelen // the scheme
123*5c591343SA. Cody Schuffelen static TPM_RC
CryptGenerateKeyedHash(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)124*5c591343SA. Cody Schuffelen CryptGenerateKeyedHash(
125*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea, // IN/OUT: the public area template
126*5c591343SA. Cody Schuffelen // for the new key.
127*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive, // OUT: sensitive area
128*5c591343SA. Cody Schuffelen TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
129*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: "entropy" source
130*5c591343SA. Cody Schuffelen )
131*5c591343SA. Cody Schuffelen {
132*5c591343SA. Cody Schuffelen TPMT_KEYEDHASH_SCHEME *scheme;
133*5c591343SA. Cody Schuffelen TPM_ALG_ID hashAlg;
134*5c591343SA. Cody Schuffelen UINT16 digestSize;
135*5c591343SA. Cody Schuffelen
136*5c591343SA. Cody Schuffelen scheme = &publicArea->parameters.keyedHashDetail.scheme;
137*5c591343SA. Cody Schuffelen
138*5c591343SA. Cody Schuffelen if(publicArea->type != TPM_ALG_KEYEDHASH)
139*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
140*5c591343SA. Cody Schuffelen
141*5c591343SA. Cody Schuffelen // Pick the limiting hash algorithm
142*5c591343SA. Cody Schuffelen if(scheme->scheme == TPM_ALG_NULL)
143*5c591343SA. Cody Schuffelen hashAlg = publicArea->nameAlg;
144*5c591343SA. Cody Schuffelen else if(scheme->scheme == TPM_ALG_XOR)
145*5c591343SA. Cody Schuffelen hashAlg = scheme->details.xor.hashAlg;
146*5c591343SA. Cody Schuffelen else
147*5c591343SA. Cody Schuffelen hashAlg = scheme->details.hmac.hashAlg;
148*5c591343SA. Cody Schuffelen digestSize = CryptHashGetDigestSize(hashAlg);
149*5c591343SA. Cody Schuffelen
150*5c591343SA. Cody Schuffelen // if this is a signing or a decryption key, then the limit
151*5c591343SA. Cody Schuffelen // for the data size is the block size of the hash. This limit
152*5c591343SA. Cody Schuffelen // is set because larger values have lower entropy because of the
153*5c591343SA. Cody Schuffelen // HMAC function. The lower limit is 1/2 the size of the digest
154*5c591343SA. Cody Schuffelen //
155*5c591343SA. Cody Schuffelen //If the user provided the key, check that it is a proper size
156*5c591343SA. Cody Schuffelen if(sensitiveCreate->data.t.size != 0)
157*5c591343SA. Cody Schuffelen {
158*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
159*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
160*5c591343SA. Cody Schuffelen {
161*5c591343SA. Cody Schuffelen if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg))
162*5c591343SA. Cody Schuffelen return TPM_RC_SIZE;
163*5c591343SA. Cody Schuffelen #if 0 // May make this a FIPS-mode requirement
164*5c591343SA. Cody Schuffelen if(sensitiveCreate->data.t.size < (digestSize / 2))
165*5c591343SA. Cody Schuffelen return TPM_RC_SIZE;
166*5c591343SA. Cody Schuffelen #endif
167*5c591343SA. Cody Schuffelen }
168*5c591343SA. Cody Schuffelen // If this is a data blob, then anything that will get past the unmarshaling
169*5c591343SA. Cody Schuffelen // is OK
170*5c591343SA. Cody Schuffelen MemoryCopy2B(&sensitive->sensitive.bits.b, &sensitiveCreate->data.b,
171*5c591343SA. Cody Schuffelen sizeof(sensitive->sensitive.bits.t.buffer));
172*5c591343SA. Cody Schuffelen }
173*5c591343SA. Cody Schuffelen else
174*5c591343SA. Cody Schuffelen {
175*5c591343SA. Cody Schuffelen // The TPM is going to generate the data so set the size to be the
176*5c591343SA. Cody Schuffelen // size of the digest of the algorithm
177*5c591343SA. Cody Schuffelen sensitive->sensitive.bits.t.size =
178*5c591343SA. Cody Schuffelen DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize);
179*5c591343SA. Cody Schuffelen if(sensitive->sensitive.bits.t.size == 0)
180*5c591343SA. Cody Schuffelen return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT;
181*5c591343SA. Cody Schuffelen }
182*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
183*5c591343SA. Cody Schuffelen }
184*5c591343SA. Cody Schuffelen
185*5c591343SA. Cody Schuffelen //*** CryptIsSchemeAnonymous()
186*5c591343SA. Cody Schuffelen // This function is used to test a scheme to see if it is an anonymous scheme
187*5c591343SA. Cody Schuffelen // The only anonymous scheme is ECDAA. ECDAA can be used to do things
188*5c591343SA. Cody Schuffelen // like U-Prove.
189*5c591343SA. Cody Schuffelen BOOL
CryptIsSchemeAnonymous(TPM_ALG_ID scheme)190*5c591343SA. Cody Schuffelen CryptIsSchemeAnonymous(
191*5c591343SA. Cody Schuffelen TPM_ALG_ID scheme // IN: the scheme algorithm to test
192*5c591343SA. Cody Schuffelen )
193*5c591343SA. Cody Schuffelen {
194*5c591343SA. Cody Schuffelen return scheme == TPM_ALG_ECDAA;
195*5c591343SA. Cody Schuffelen }
196*5c591343SA. Cody Schuffelen
197*5c591343SA. Cody Schuffelen //**** ************************************************************************
198*5c591343SA. Cody Schuffelen //** Symmetric Functions
199*5c591343SA. Cody Schuffelen //**** ************************************************************************
200*5c591343SA. Cody Schuffelen
201*5c591343SA. Cody Schuffelen //*** ParmDecryptSym()
202*5c591343SA. Cody Schuffelen // This function performs parameter decryption using symmetric block cipher.
203*5c591343SA. Cody Schuffelen /*(See Part 1 specification)
204*5c591343SA. Cody Schuffelen // Symmetric parameter decryption
205*5c591343SA. Cody Schuffelen // When parameter decryption uses a symmetric block cipher, a decryption
206*5c591343SA. Cody Schuffelen // key and IV will be generated from:
207*5c591343SA. Cody Schuffelen // KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits) (24)
208*5c591343SA. Cody Schuffelen // Where:
209*5c591343SA. Cody Schuffelen // hash the hash function associated with the session
210*5c591343SA. Cody Schuffelen // sessionAuth the sessionAuth associated with the session
211*5c591343SA. Cody Schuffelen // nonceNewer nonceCaller for a command
212*5c591343SA. Cody Schuffelen // nonceOlder nonceTPM for a command
213*5c591343SA. Cody Schuffelen // bits the number of bits required for the symmetric key
214*5c591343SA. Cody Schuffelen // plus an IV
215*5c591343SA. Cody Schuffelen */
216*5c591343SA. Cody Schuffelen void
ParmDecryptSym(TPM_ALG_ID symAlg,TPM_ALG_ID hash,UINT16 keySizeInBits,TPM2B * key,TPM2B * nonceCaller,TPM2B * nonceTpm,UINT32 dataSize,BYTE * data)217*5c591343SA. Cody Schuffelen ParmDecryptSym(
218*5c591343SA. Cody Schuffelen TPM_ALG_ID symAlg, // IN: the symmetric algorithm
219*5c591343SA. Cody Schuffelen TPM_ALG_ID hash, // IN: hash algorithm for KDFa
220*5c591343SA. Cody Schuffelen UINT16 keySizeInBits, // IN: the key size in bits
221*5c591343SA. Cody Schuffelen TPM2B *key, // IN: KDF HMAC key
222*5c591343SA. Cody Schuffelen TPM2B *nonceCaller, // IN: nonce caller
223*5c591343SA. Cody Schuffelen TPM2B *nonceTpm, // IN: nonce TPM
224*5c591343SA. Cody Schuffelen UINT32 dataSize, // IN: size of parameter buffer
225*5c591343SA. Cody Schuffelen BYTE *data // OUT: buffer to be decrypted
226*5c591343SA. Cody Schuffelen )
227*5c591343SA. Cody Schuffelen {
228*5c591343SA. Cody Schuffelen // KDF output buffer
229*5c591343SA. Cody Schuffelen // It contains parameters for the CFB encryption
230*5c591343SA. Cody Schuffelen // From MSB to LSB, they are the key and iv
231*5c591343SA. Cody Schuffelen BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
232*5c591343SA. Cody Schuffelen // Symmetric key size in byte
233*5c591343SA. Cody Schuffelen UINT16 keySize = (keySizeInBits + 7) / 8;
234*5c591343SA. Cody Schuffelen TPM2B_IV iv;
235*5c591343SA. Cody Schuffelen
236*5c591343SA. Cody Schuffelen iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
237*5c591343SA. Cody Schuffelen // If there is decryption to do...
238*5c591343SA. Cody Schuffelen if(iv.t.size > 0)
239*5c591343SA. Cody Schuffelen {
240*5c591343SA. Cody Schuffelen // Generate key and iv
241*5c591343SA. Cody Schuffelen CryptKDFa(hash, key, CFB_KEY, nonceCaller, nonceTpm,
242*5c591343SA. Cody Schuffelen keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
243*5c591343SA. Cody Schuffelen MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
244*5c591343SA. Cody Schuffelen
245*5c591343SA. Cody Schuffelen CryptSymmetricDecrypt(data, symAlg, keySizeInBits, symParmString,
246*5c591343SA. Cody Schuffelen &iv, TPM_ALG_CFB, dataSize, data);
247*5c591343SA. Cody Schuffelen }
248*5c591343SA. Cody Schuffelen return;
249*5c591343SA. Cody Schuffelen }
250*5c591343SA. Cody Schuffelen
251*5c591343SA. Cody Schuffelen //*** ParmEncryptSym()
252*5c591343SA. Cody Schuffelen // This function performs parameter encryption using symmetric block cipher.
253*5c591343SA. Cody Schuffelen /*(See part 1 specification)
254*5c591343SA. Cody Schuffelen // When parameter decryption uses a symmetric block cipher, an encryption
255*5c591343SA. Cody Schuffelen // key and IV will be generated from:
256*5c591343SA. Cody Schuffelen // KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits) (24)
257*5c591343SA. Cody Schuffelen // Where:
258*5c591343SA. Cody Schuffelen // hash the hash function associated with the session
259*5c591343SA. Cody Schuffelen // sessionAuth the sessionAuth associated with the session
260*5c591343SA. Cody Schuffelen // nonceNewer nonceTPM for a response
261*5c591343SA. Cody Schuffelen // nonceOlder nonceCaller for a response
262*5c591343SA. Cody Schuffelen // bits the number of bits required for the symmetric key
263*5c591343SA. Cody Schuffelen // plus an IV
264*5c591343SA. Cody Schuffelen */
265*5c591343SA. Cody Schuffelen void
ParmEncryptSym(TPM_ALG_ID symAlg,TPM_ALG_ID hash,UINT16 keySizeInBits,TPM2B * key,TPM2B * nonceCaller,TPM2B * nonceTpm,UINT32 dataSize,BYTE * data)266*5c591343SA. Cody Schuffelen ParmEncryptSym(
267*5c591343SA. Cody Schuffelen TPM_ALG_ID symAlg, // IN: symmetric algorithm
268*5c591343SA. Cody Schuffelen TPM_ALG_ID hash, // IN: hash algorithm for KDFa
269*5c591343SA. Cody Schuffelen UINT16 keySizeInBits, // IN: symmetric key size in bits
270*5c591343SA. Cody Schuffelen TPM2B *key, // IN: KDF HMAC key
271*5c591343SA. Cody Schuffelen TPM2B *nonceCaller, // IN: nonce caller
272*5c591343SA. Cody Schuffelen TPM2B *nonceTpm, // IN: nonce TPM
273*5c591343SA. Cody Schuffelen UINT32 dataSize, // IN: size of parameter buffer
274*5c591343SA. Cody Schuffelen BYTE *data // OUT: buffer to be encrypted
275*5c591343SA. Cody Schuffelen )
276*5c591343SA. Cody Schuffelen {
277*5c591343SA. Cody Schuffelen // KDF output buffer
278*5c591343SA. Cody Schuffelen // It contains parameters for the CFB encryption
279*5c591343SA. Cody Schuffelen BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
280*5c591343SA. Cody Schuffelen
281*5c591343SA. Cody Schuffelen // Symmetric key size in bytes
282*5c591343SA. Cody Schuffelen UINT16 keySize = (keySizeInBits + 7) / 8;
283*5c591343SA. Cody Schuffelen
284*5c591343SA. Cody Schuffelen TPM2B_IV iv;
285*5c591343SA. Cody Schuffelen
286*5c591343SA. Cody Schuffelen iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
287*5c591343SA. Cody Schuffelen // See if there is any encryption to do
288*5c591343SA. Cody Schuffelen if(iv.t.size > 0)
289*5c591343SA. Cody Schuffelen {
290*5c591343SA. Cody Schuffelen // Generate key and iv
291*5c591343SA. Cody Schuffelen CryptKDFa(hash, key, CFB_KEY, nonceTpm, nonceCaller,
292*5c591343SA. Cody Schuffelen keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
293*5c591343SA. Cody Schuffelen MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
294*5c591343SA. Cody Schuffelen
295*5c591343SA. Cody Schuffelen CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv,
296*5c591343SA. Cody Schuffelen TPM_ALG_CFB, dataSize, data);
297*5c591343SA. Cody Schuffelen }
298*5c591343SA. Cody Schuffelen return;
299*5c591343SA. Cody Schuffelen }
300*5c591343SA. Cody Schuffelen
301*5c591343SA. Cody Schuffelen //*** CryptGenerateKeySymmetric()
302*5c591343SA. Cody Schuffelen // This function generates a symmetric cipher key. The derivation process is
303*5c591343SA. Cody Schuffelen // determined by the type of the provided 'rand'
304*5c591343SA. Cody Schuffelen // Return type: TPM_RC
305*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT cannot get a random value
306*5c591343SA. Cody Schuffelen // TPM_RC_KEY_SIZE key size in the public area does not match the size
307*5c591343SA. Cody Schuffelen // in the sensitive creation area
308*5c591343SA. Cody Schuffelen // TPM_RC_KEY provided key value is not allowed
309*5c591343SA. Cody Schuffelen static TPM_RC
CryptGenerateKeySymmetric(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)310*5c591343SA. Cody Schuffelen CryptGenerateKeySymmetric(
311*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
312*5c591343SA. Cody Schuffelen // for the new key.
313*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive, // OUT: sensitive area
314*5c591343SA. Cody Schuffelen TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
315*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: the "entropy" source for
316*5c591343SA. Cody Schuffelen )
317*5c591343SA. Cody Schuffelen {
318*5c591343SA. Cody Schuffelen UINT16 keyBits = publicArea->parameters.symDetail.sym.keyBits.sym;
319*5c591343SA. Cody Schuffelen TPM_RC result;
320*5c591343SA. Cody Schuffelen //
321*5c591343SA. Cody Schuffelen // only do multiples of RADIX_BITS
322*5c591343SA. Cody Schuffelen if((keyBits % RADIX_BITS) != 0)
323*5c591343SA. Cody Schuffelen return TPM_RC_KEY_SIZE;
324*5c591343SA. Cody Schuffelen // If this is not a new key, then the provided key data must be the right size
325*5c591343SA. Cody Schuffelen if(sensitiveCreate->data.t.size != 0)
326*5c591343SA. Cody Schuffelen {
327*5c591343SA. Cody Schuffelen result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym,
328*5c591343SA. Cody Schuffelen (TPM2B_SYM_KEY *)&sensitiveCreate->data);
329*5c591343SA. Cody Schuffelen if(result == TPM_RC_SUCCESS)
330*5c591343SA. Cody Schuffelen MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
331*5c591343SA. Cody Schuffelen sizeof(sensitive->sensitive.sym.t.buffer));
332*5c591343SA. Cody Schuffelen }
333*5c591343SA. Cody Schuffelen #if ALG_TDES
334*5c591343SA. Cody Schuffelen else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES)
335*5c591343SA. Cody Schuffelen {
336*5c591343SA. Cody Schuffelen result = CryptGenerateKeyDes(publicArea, sensitive, rand);
337*5c591343SA. Cody Schuffelen }
338*5c591343SA. Cody Schuffelen #endif
339*5c591343SA. Cody Schuffelen else
340*5c591343SA. Cody Schuffelen {
341*5c591343SA. Cody Schuffelen sensitive->sensitive.sym.t.size =
342*5c591343SA. Cody Schuffelen DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer,
343*5c591343SA. Cody Schuffelen BITS_TO_BYTES(keyBits));
344*5c591343SA. Cody Schuffelen if(g_inFailureMode)
345*5c591343SA. Cody Schuffelen result = TPM_RC_FAILURE;
346*5c591343SA. Cody Schuffelen else if(sensitive->sensitive.sym.t.size == 0)
347*5c591343SA. Cody Schuffelen result = TPM_RC_NO_RESULT;
348*5c591343SA. Cody Schuffelen else
349*5c591343SA. Cody Schuffelen result = TPM_RC_SUCCESS;
350*5c591343SA. Cody Schuffelen }
351*5c591343SA. Cody Schuffelen return result;
352*5c591343SA. Cody Schuffelen }
353*5c591343SA. Cody Schuffelen
354*5c591343SA. Cody Schuffelen //*** CryptXORObfuscation()
355*5c591343SA. Cody Schuffelen // This function implements XOR obfuscation. It should not be called if the
356*5c591343SA. Cody Schuffelen // hash algorithm is not implemented. The only return value from this function
357*5c591343SA. Cody Schuffelen // is TPM_RC_SUCCESS.
358*5c591343SA. Cody Schuffelen void
CryptXORObfuscation(TPM_ALG_ID hash,TPM2B * key,TPM2B * contextU,TPM2B * contextV,UINT32 dataSize,BYTE * data)359*5c591343SA. Cody Schuffelen CryptXORObfuscation(
360*5c591343SA. Cody Schuffelen TPM_ALG_ID hash, // IN: hash algorithm for KDF
361*5c591343SA. Cody Schuffelen TPM2B *key, // IN: KDF key
362*5c591343SA. Cody Schuffelen TPM2B *contextU, // IN: contextU
363*5c591343SA. Cody Schuffelen TPM2B *contextV, // IN: contextV
364*5c591343SA. Cody Schuffelen UINT32 dataSize, // IN: size of data buffer
365*5c591343SA. Cody Schuffelen BYTE *data // IN/OUT: data to be XORed in place
366*5c591343SA. Cody Schuffelen )
367*5c591343SA. Cody Schuffelen {
368*5c591343SA. Cody Schuffelen BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer
369*5c591343SA. Cody Schuffelen BYTE *pm;
370*5c591343SA. Cody Schuffelen UINT32 i;
371*5c591343SA. Cody Schuffelen UINT32 counter = 0;
372*5c591343SA. Cody Schuffelen UINT16 hLen = CryptHashGetDigestSize(hash);
373*5c591343SA. Cody Schuffelen UINT32 requestSize = dataSize * 8;
374*5c591343SA. Cody Schuffelen INT32 remainBytes = (INT32)dataSize;
375*5c591343SA. Cody Schuffelen
376*5c591343SA. Cody Schuffelen pAssert((key != NULL) && (data != NULL) && (hLen != 0));
377*5c591343SA. Cody Schuffelen
378*5c591343SA. Cody Schuffelen // Call KDFa to generate XOR mask
379*5c591343SA. Cody Schuffelen for(; remainBytes > 0; remainBytes -= hLen)
380*5c591343SA. Cody Schuffelen {
381*5c591343SA. Cody Schuffelen // Make a call to KDFa to get next iteration
382*5c591343SA. Cody Schuffelen CryptKDFa(hash, key, XOR_KEY, contextU, contextV,
383*5c591343SA. Cody Schuffelen requestSize, mask, &counter, TRUE);
384*5c591343SA. Cody Schuffelen
385*5c591343SA. Cody Schuffelen // XOR next piece of the data
386*5c591343SA. Cody Schuffelen pm = mask;
387*5c591343SA. Cody Schuffelen for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
388*5c591343SA. Cody Schuffelen *data++ ^= *pm++;
389*5c591343SA. Cody Schuffelen }
390*5c591343SA. Cody Schuffelen return;
391*5c591343SA. Cody Schuffelen }
392*5c591343SA. Cody Schuffelen
393*5c591343SA. Cody Schuffelen //****************************************************************************
394*5c591343SA. Cody Schuffelen //** Initialization and shut down
395*5c591343SA. Cody Schuffelen //****************************************************************************
396*5c591343SA. Cody Schuffelen
397*5c591343SA. Cody Schuffelen //*** CryptInit()
398*5c591343SA. Cody Schuffelen // This function is called when the TPM receives a _TPM_Init indication.
399*5c591343SA. Cody Schuffelen //
400*5c591343SA. Cody Schuffelen // NOTE: The hash algorithms do not have to be tested, they just need to be
401*5c591343SA. Cody Schuffelen // available. They have to be tested before the TPM can accept HMAC authorization
402*5c591343SA. Cody Schuffelen // or return any result that relies on a hash algorithm.
403*5c591343SA. Cody Schuffelen // Return Type: BOOL
404*5c591343SA. Cody Schuffelen // TRUE(1) initializations succeeded
405*5c591343SA. Cody Schuffelen // FALSE(0) initialization failed and caller should place the TPM into
406*5c591343SA. Cody Schuffelen // Failure Mode
407*5c591343SA. Cody Schuffelen BOOL
CryptInit(void)408*5c591343SA. Cody Schuffelen CryptInit(
409*5c591343SA. Cody Schuffelen void
410*5c591343SA. Cody Schuffelen )
411*5c591343SA. Cody Schuffelen {
412*5c591343SA. Cody Schuffelen BOOL ok;
413*5c591343SA. Cody Schuffelen // Initialize the vector of implemented algorithms
414*5c591343SA. Cody Schuffelen AlgorithmGetImplementedVector(&g_implementedAlgorithms);
415*5c591343SA. Cody Schuffelen
416*5c591343SA. Cody Schuffelen // Indicate that all test are necessary
417*5c591343SA. Cody Schuffelen CryptInitializeToTest();
418*5c591343SA. Cody Schuffelen
419*5c591343SA. Cody Schuffelen // Do any library initializations that are necessary. If any fails,
420*5c591343SA. Cody Schuffelen // the caller should go into failure mode;
421*5c591343SA. Cody Schuffelen ok = SupportLibInit();
422*5c591343SA. Cody Schuffelen ok = ok && CryptSymInit();
423*5c591343SA. Cody Schuffelen ok = ok && CryptRandInit();
424*5c591343SA. Cody Schuffelen ok = ok && CryptHashInit();
425*5c591343SA. Cody Schuffelen #if ALG_RSA
426*5c591343SA. Cody Schuffelen ok = ok && CryptRsaInit();
427*5c591343SA. Cody Schuffelen #endif // ALG_RSA
428*5c591343SA. Cody Schuffelen #if ALG_ECC
429*5c591343SA. Cody Schuffelen ok = ok && CryptEccInit();
430*5c591343SA. Cody Schuffelen #endif // ALG_ECC
431*5c591343SA. Cody Schuffelen return ok;
432*5c591343SA. Cody Schuffelen }
433*5c591343SA. Cody Schuffelen
434*5c591343SA. Cody Schuffelen //*** CryptStartup()
435*5c591343SA. Cody Schuffelen // This function is called by TPM2_Startup() to initialize the functions in
436*5c591343SA. Cody Schuffelen // this cryptographic library and in the provided CryptoLibrary. This function
437*5c591343SA. Cody Schuffelen // and CryptUtilInit() are both provided so that the implementation may move the
438*5c591343SA. Cody Schuffelen // initialization around to get the best interaction.
439*5c591343SA. Cody Schuffelen // Return Type: BOOL
440*5c591343SA. Cody Schuffelen // TRUE(1) startup succeeded
441*5c591343SA. Cody Schuffelen // FALSE(0) startup failed and caller should place the TPM into
442*5c591343SA. Cody Schuffelen // Failure Mode
443*5c591343SA. Cody Schuffelen BOOL
CryptStartup(STARTUP_TYPE type)444*5c591343SA. Cody Schuffelen CryptStartup(
445*5c591343SA. Cody Schuffelen STARTUP_TYPE type // IN: the startup type
446*5c591343SA. Cody Schuffelen )
447*5c591343SA. Cody Schuffelen {
448*5c591343SA. Cody Schuffelen BOOL OK;
449*5c591343SA. Cody Schuffelen NOT_REFERENCED(type);
450*5c591343SA. Cody Schuffelen
451*5c591343SA. Cody Schuffelen OK = CryptSymStartup() && CryptRandStartup() && CryptHashStartup()
452*5c591343SA. Cody Schuffelen #if ALG_RSA
453*5c591343SA. Cody Schuffelen && CryptRsaStartup()
454*5c591343SA. Cody Schuffelen #endif // ALG_RSA
455*5c591343SA. Cody Schuffelen #if ALG_ECC
456*5c591343SA. Cody Schuffelen && CryptEccStartup()
457*5c591343SA. Cody Schuffelen #endif // ALG_ECC
458*5c591343SA. Cody Schuffelen ;
459*5c591343SA. Cody Schuffelen #if ALG_ECC
460*5c591343SA. Cody Schuffelen // Don't directly check for SU_RESET because that is the default
461*5c591343SA. Cody Schuffelen if(OK && (type != SU_RESTART) && (type != SU_RESUME))
462*5c591343SA. Cody Schuffelen {
463*5c591343SA. Cody Schuffelen // If the shutdown was orderly, then the values recovered from NV will
464*5c591343SA. Cody Schuffelen // be OK to use.
465*5c591343SA. Cody Schuffelen // Get a new random commit nonce
466*5c591343SA. Cody Schuffelen gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
467*5c591343SA. Cody Schuffelen CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
468*5c591343SA. Cody Schuffelen // Reset the counter and commit array
469*5c591343SA. Cody Schuffelen gr.commitCounter = 0;
470*5c591343SA. Cody Schuffelen MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
471*5c591343SA. Cody Schuffelen }
472*5c591343SA. Cody Schuffelen #endif // ALG_ECC
473*5c591343SA. Cody Schuffelen return OK;
474*5c591343SA. Cody Schuffelen }
475*5c591343SA. Cody Schuffelen
476*5c591343SA. Cody Schuffelen //****************************************************************************
477*5c591343SA. Cody Schuffelen //** Algorithm-Independent Functions
478*5c591343SA. Cody Schuffelen //****************************************************************************
479*5c591343SA. Cody Schuffelen //*** Introduction
480*5c591343SA. Cody Schuffelen // These functions are used generically when a function of a general type
481*5c591343SA. Cody Schuffelen // (e.g., symmetric encryption) is required. The functions will modify the
482*5c591343SA. Cody Schuffelen // parameters as required to interface to the indicated algorithms.
483*5c591343SA. Cody Schuffelen //
484*5c591343SA. Cody Schuffelen //*** CryptIsAsymAlgorithm()
485*5c591343SA. Cody Schuffelen // This function indicates if an algorithm is an asymmetric algorithm.
486*5c591343SA. Cody Schuffelen // Return Type: BOOL
487*5c591343SA. Cody Schuffelen // TRUE(1) if it is an asymmetric algorithm
488*5c591343SA. Cody Schuffelen // FALSE(0) if it is not an asymmetric algorithm
489*5c591343SA. Cody Schuffelen BOOL
CryptIsAsymAlgorithm(TPM_ALG_ID algID)490*5c591343SA. Cody Schuffelen CryptIsAsymAlgorithm(
491*5c591343SA. Cody Schuffelen TPM_ALG_ID algID // IN: algorithm ID
492*5c591343SA. Cody Schuffelen )
493*5c591343SA. Cody Schuffelen {
494*5c591343SA. Cody Schuffelen switch(algID)
495*5c591343SA. Cody Schuffelen {
496*5c591343SA. Cody Schuffelen #if ALG_RSA
497*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
498*5c591343SA. Cody Schuffelen #endif
499*5c591343SA. Cody Schuffelen #if ALG_ECC
500*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
501*5c591343SA. Cody Schuffelen #endif
502*5c591343SA. Cody Schuffelen return TRUE;
503*5c591343SA. Cody Schuffelen break;
504*5c591343SA. Cody Schuffelen default:
505*5c591343SA. Cody Schuffelen break;
506*5c591343SA. Cody Schuffelen }
507*5c591343SA. Cody Schuffelen return FALSE;
508*5c591343SA. Cody Schuffelen }
509*5c591343SA. Cody Schuffelen
510*5c591343SA. Cody Schuffelen //*** CryptSecretEncrypt()
511*5c591343SA. Cody Schuffelen // This function creates a secret value and its associated secret structure using
512*5c591343SA. Cody Schuffelen // an asymmetric algorithm.
513*5c591343SA. Cody Schuffelen //
514*5c591343SA. Cody Schuffelen // This function is used by TPM2_Rewrap() TPM2_MakeCredential(),
515*5c591343SA. Cody Schuffelen // and TPM2_Duplicate().
516*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
517*5c591343SA. Cody Schuffelen // TPM_RC_ATTRIBUTES 'keyHandle' does not reference a valid decryption key
518*5c591343SA. Cody Schuffelen // TPM_RC_KEY invalid ECC key (public point is not on the curve)
519*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME RSA key with an unsupported padding scheme
520*5c591343SA. Cody Schuffelen // TPM_RC_VALUE numeric value of the data to be decrypted is greater
521*5c591343SA. Cody Schuffelen // than the RSA key modulus
522*5c591343SA. Cody Schuffelen TPM_RC
CryptSecretEncrypt(OBJECT * encryptKey,const TPM2B * label,TPM2B_DATA * data,TPM2B_ENCRYPTED_SECRET * secret)523*5c591343SA. Cody Schuffelen CryptSecretEncrypt(
524*5c591343SA. Cody Schuffelen OBJECT *encryptKey, // IN: encryption key object
525*5c591343SA. Cody Schuffelen const TPM2B *label, // IN: a null-terminated string as L
526*5c591343SA. Cody Schuffelen TPM2B_DATA *data, // OUT: secret value
527*5c591343SA. Cody Schuffelen TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure
528*5c591343SA. Cody Schuffelen )
529*5c591343SA. Cody Schuffelen {
530*5c591343SA. Cody Schuffelen TPMT_RSA_DECRYPT scheme;
531*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
532*5c591343SA. Cody Schuffelen //
533*5c591343SA. Cody Schuffelen if(data == NULL || secret == NULL)
534*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
535*5c591343SA. Cody Schuffelen
536*5c591343SA. Cody Schuffelen // The output secret value has the size of the digest produced by the nameAlg.
537*5c591343SA. Cody Schuffelen data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg);
538*5c591343SA. Cody Schuffelen // The encryption scheme is OAEP using the nameAlg of the encrypt key.
539*5c591343SA. Cody Schuffelen scheme.scheme = TPM_ALG_OAEP;
540*5c591343SA. Cody Schuffelen scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg;
541*5c591343SA. Cody Schuffelen
542*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
543*5c591343SA. Cody Schuffelen return TPM_RC_ATTRIBUTES;
544*5c591343SA. Cody Schuffelen switch(encryptKey->publicArea.type)
545*5c591343SA. Cody Schuffelen {
546*5c591343SA. Cody Schuffelen #if ALG_RSA
547*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
548*5c591343SA. Cody Schuffelen {
549*5c591343SA. Cody Schuffelen // Create secret data from RNG
550*5c591343SA. Cody Schuffelen CryptRandomGenerate(data->t.size, data->t.buffer);
551*5c591343SA. Cody Schuffelen
552*5c591343SA. Cody Schuffelen // Encrypt the data by RSA OAEP into encrypted secret
553*5c591343SA. Cody Schuffelen result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA *)secret, &data->b,
554*5c591343SA. Cody Schuffelen encryptKey, &scheme, label, NULL);
555*5c591343SA. Cody Schuffelen }
556*5c591343SA. Cody Schuffelen break;
557*5c591343SA. Cody Schuffelen #endif // ALG_RSA
558*5c591343SA. Cody Schuffelen
559*5c591343SA. Cody Schuffelen #if ALG_ECC
560*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
561*5c591343SA. Cody Schuffelen {
562*5c591343SA. Cody Schuffelen TPMS_ECC_POINT eccPublic;
563*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER eccPrivate;
564*5c591343SA. Cody Schuffelen TPMS_ECC_POINT eccSecret;
565*5c591343SA. Cody Schuffelen BYTE *buffer = secret->t.secret;
566*5c591343SA. Cody Schuffelen
567*5c591343SA. Cody Schuffelen // Need to make sure that the public point of the key is on the
568*5c591343SA. Cody Schuffelen // curve defined by the key.
569*5c591343SA. Cody Schuffelen if(!CryptEccIsPointOnCurve(
570*5c591343SA. Cody Schuffelen encryptKey->publicArea.parameters.eccDetail.curveID,
571*5c591343SA. Cody Schuffelen &encryptKey->publicArea.unique.ecc))
572*5c591343SA. Cody Schuffelen result = TPM_RC_KEY;
573*5c591343SA. Cody Schuffelen else
574*5c591343SA. Cody Schuffelen {
575*5c591343SA. Cody Schuffelen // Call crypto engine to create an auxiliary ECC key
576*5c591343SA. Cody Schuffelen // We assume crypt engine initialization should always success.
577*5c591343SA. Cody Schuffelen // Otherwise, TPM should go to failure mode.
578*5c591343SA. Cody Schuffelen
579*5c591343SA. Cody Schuffelen CryptEccNewKeyPair(&eccPublic, &eccPrivate,
580*5c591343SA. Cody Schuffelen encryptKey->publicArea.parameters.eccDetail.curveID);
581*5c591343SA. Cody Schuffelen // Marshal ECC public to secret structure. This will be used by the
582*5c591343SA. Cody Schuffelen // recipient to decrypt the secret with their private key.
583*5c591343SA. Cody Schuffelen secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);
584*5c591343SA. Cody Schuffelen
585*5c591343SA. Cody Schuffelen // Compute ECDH shared secret which is R = [d]Q where d is the
586*5c591343SA. Cody Schuffelen // private part of the ephemeral key and Q is the public part of a
587*5c591343SA. Cody Schuffelen // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
588*5c591343SA. Cody Schuffelen // because the auxiliary ECC key is just created according to the
589*5c591343SA. Cody Schuffelen // parameters of input ECC encrypt key.
590*5c591343SA. Cody Schuffelen if(CryptEccPointMultiply(&eccSecret,
591*5c591343SA. Cody Schuffelen encryptKey->publicArea.parameters.eccDetail.curveID,
592*5c591343SA. Cody Schuffelen &encryptKey->publicArea.unique.ecc, &eccPrivate,
593*5c591343SA. Cody Schuffelen NULL, NULL)
594*5c591343SA. Cody Schuffelen != TPM_RC_SUCCESS)
595*5c591343SA. Cody Schuffelen result = TPM_RC_KEY;
596*5c591343SA. Cody Schuffelen else
597*5c591343SA. Cody Schuffelen {
598*5c591343SA. Cody Schuffelen // The secret value is computed from Z using KDFe as:
599*5c591343SA. Cody Schuffelen // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
600*5c591343SA. Cody Schuffelen // Where:
601*5c591343SA. Cody Schuffelen // HashID the nameAlg of the decrypt key
602*5c591343SA. Cody Schuffelen // Z the x coordinate (Px) of the product (P) of the point
603*5c591343SA. Cody Schuffelen // (Q) of the secret and the private x coordinate (de,V)
604*5c591343SA. Cody Schuffelen // of the decryption key
605*5c591343SA. Cody Schuffelen // Use a null-terminated string containing "SECRET"
606*5c591343SA. Cody Schuffelen // PartyUInfo the x coordinate of the point in the secret
607*5c591343SA. Cody Schuffelen // (Qe,U )
608*5c591343SA. Cody Schuffelen // PartyVInfo the x coordinate of the public key (Qs,V )
609*5c591343SA. Cody Schuffelen // bits the number of bits in the digest of HashID
610*5c591343SA. Cody Schuffelen // Retrieve seed from KDFe
611*5c591343SA. Cody Schuffelen CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
612*5c591343SA. Cody Schuffelen label, &eccPublic.x.b,
613*5c591343SA. Cody Schuffelen &encryptKey->publicArea.unique.ecc.x.b,
614*5c591343SA. Cody Schuffelen data->t.size * 8, data->t.buffer);
615*5c591343SA. Cody Schuffelen }
616*5c591343SA. Cody Schuffelen }
617*5c591343SA. Cody Schuffelen }
618*5c591343SA. Cody Schuffelen break;
619*5c591343SA. Cody Schuffelen #endif // ALG_ECC
620*5c591343SA. Cody Schuffelen default:
621*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
622*5c591343SA. Cody Schuffelen break;
623*5c591343SA. Cody Schuffelen }
624*5c591343SA. Cody Schuffelen return result;
625*5c591343SA. Cody Schuffelen }
626*5c591343SA. Cody Schuffelen
627*5c591343SA. Cody Schuffelen //*** CryptSecretDecrypt()
628*5c591343SA. Cody Schuffelen // Decrypt a secret value by asymmetric (or symmetric) algorithm
629*5c591343SA. Cody Schuffelen // This function is used for ActivateCredential and Import for asymmetric
630*5c591343SA. Cody Schuffelen // decryption, and StartAuthSession for both asymmetric and symmetric
631*5c591343SA. Cody Schuffelen // decryption process
632*5c591343SA. Cody Schuffelen //
633*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
634*5c591343SA. Cody Schuffelen // TPM_RC_ATTRIBUTES RSA key is not a decryption key
635*5c591343SA. Cody Schuffelen // TPM_RC_BINDING Invalid RSA key (public and private parts are not
636*5c591343SA. Cody Schuffelen // cryptographically bound.
637*5c591343SA. Cody Schuffelen // TPM_RC_ECC_POINT ECC point in the secret is not on the curve
638*5c591343SA. Cody Schuffelen // TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret
639*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity
640*5c591343SA. Cody Schuffelen // TPM_RC_SIZE data to decrypt is not of the same size as RSA key
641*5c591343SA. Cody Schuffelen // TPM_RC_VALUE For RSA key, numeric value of the encrypted data is
642*5c591343SA. Cody Schuffelen // greater than the modulus, or the recovered data is
643*5c591343SA. Cody Schuffelen // larger than the output buffer.
644*5c591343SA. Cody Schuffelen // For keyedHash or symmetric key, the secret is
645*5c591343SA. Cody Schuffelen // larger than the size of the digest produced by
646*5c591343SA. Cody Schuffelen // the name algorithm.
647*5c591343SA. Cody Schuffelen // TPM_RC_FAILURE internal error
648*5c591343SA. Cody Schuffelen TPM_RC
CryptSecretDecrypt(OBJECT * decryptKey,TPM2B_NONCE * nonceCaller,const TPM2B * label,TPM2B_ENCRYPTED_SECRET * secret,TPM2B_DATA * data)649*5c591343SA. Cody Schuffelen CryptSecretDecrypt(
650*5c591343SA. Cody Schuffelen OBJECT *decryptKey, // IN: decrypt key
651*5c591343SA. Cody Schuffelen TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for
652*5c591343SA. Cody Schuffelen // symmetric decryption. For
653*5c591343SA. Cody Schuffelen // asymmetric decryption, this
654*5c591343SA. Cody Schuffelen // parameter is NULL
655*5c591343SA. Cody Schuffelen const TPM2B *label, // IN: a value for L
656*5c591343SA. Cody Schuffelen TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret
657*5c591343SA. Cody Schuffelen TPM2B_DATA *data // OUT: decrypted secret value
658*5c591343SA. Cody Schuffelen )
659*5c591343SA. Cody Schuffelen {
660*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
661*5c591343SA. Cody Schuffelen
662*5c591343SA. Cody Schuffelen // Decryption for secret
663*5c591343SA. Cody Schuffelen switch(decryptKey->publicArea.type)
664*5c591343SA. Cody Schuffelen {
665*5c591343SA. Cody Schuffelen #if ALG_RSA
666*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
667*5c591343SA. Cody Schuffelen {
668*5c591343SA. Cody Schuffelen TPMT_RSA_DECRYPT scheme;
669*5c591343SA. Cody Schuffelen TPMT_RSA_SCHEME *keyScheme
670*5c591343SA. Cody Schuffelen = &decryptKey->publicArea.parameters.rsaDetail.scheme;
671*5c591343SA. Cody Schuffelen UINT16 digestSize;
672*5c591343SA. Cody Schuffelen
673*5c591343SA. Cody Schuffelen scheme = *(TPMT_RSA_DECRYPT *)keyScheme;
674*5c591343SA. Cody Schuffelen // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and
675*5c591343SA. Cody Schuffelen // set the algorithm to the name algorithm.
676*5c591343SA. Cody Schuffelen if(scheme.scheme == TPM_ALG_NULL)
677*5c591343SA. Cody Schuffelen {
678*5c591343SA. Cody Schuffelen // Use OAEP scheme
679*5c591343SA. Cody Schuffelen scheme.scheme = TPM_ALG_OAEP;
680*5c591343SA. Cody Schuffelen scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
681*5c591343SA. Cody Schuffelen }
682*5c591343SA. Cody Schuffelen // use the digestSize as an indicator of whether or not the scheme
683*5c591343SA. Cody Schuffelen // is using a supported hash algorithm.
684*5c591343SA. Cody Schuffelen // Note: depending on the scheme used for encryption, a hashAlg might
685*5c591343SA. Cody Schuffelen // not be needed. However, the return value has to have some upper
686*5c591343SA. Cody Schuffelen // limit on the size. In this case, it is the size of the digest of the
687*5c591343SA. Cody Schuffelen // hash algorithm. It is checked after the decryption is done but, there
688*5c591343SA. Cody Schuffelen // is no point in doing the decryption if the size is going to be
689*5c591343SA. Cody Schuffelen // 'wrong' anyway.
690*5c591343SA. Cody Schuffelen digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg);
691*5c591343SA. Cody Schuffelen if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0)
692*5c591343SA. Cody Schuffelen return TPM_RC_SCHEME;
693*5c591343SA. Cody Schuffelen
694*5c591343SA. Cody Schuffelen // Set the output buffer capacity
695*5c591343SA. Cody Schuffelen data->t.size = sizeof(data->t.buffer);
696*5c591343SA. Cody Schuffelen
697*5c591343SA. Cody Schuffelen // Decrypt seed by RSA OAEP
698*5c591343SA. Cody Schuffelen result = CryptRsaDecrypt(&data->b, &secret->b,
699*5c591343SA. Cody Schuffelen decryptKey, &scheme, label);
700*5c591343SA. Cody Schuffelen if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize))
701*5c591343SA. Cody Schuffelen result = TPM_RC_VALUE;
702*5c591343SA. Cody Schuffelen }
703*5c591343SA. Cody Schuffelen break;
704*5c591343SA. Cody Schuffelen #endif // ALG_RSA
705*5c591343SA. Cody Schuffelen #if ALG_ECC
706*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
707*5c591343SA. Cody Schuffelen {
708*5c591343SA. Cody Schuffelen TPMS_ECC_POINT eccPublic;
709*5c591343SA. Cody Schuffelen TPMS_ECC_POINT eccSecret;
710*5c591343SA. Cody Schuffelen BYTE *buffer = secret->t.secret;
711*5c591343SA. Cody Schuffelen INT32 size = secret->t.size;
712*5c591343SA. Cody Schuffelen
713*5c591343SA. Cody Schuffelen // Retrieve ECC point from secret buffer
714*5c591343SA. Cody Schuffelen result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
715*5c591343SA. Cody Schuffelen if(result == TPM_RC_SUCCESS)
716*5c591343SA. Cody Schuffelen {
717*5c591343SA. Cody Schuffelen result = CryptEccPointMultiply(&eccSecret,
718*5c591343SA. Cody Schuffelen decryptKey->publicArea.parameters.eccDetail.curveID,
719*5c591343SA. Cody Schuffelen &eccPublic, &decryptKey->sensitive.sensitive.ecc,
720*5c591343SA. Cody Schuffelen NULL, NULL);
721*5c591343SA. Cody Schuffelen if(result == TPM_RC_SUCCESS)
722*5c591343SA. Cody Schuffelen {
723*5c591343SA. Cody Schuffelen // Set the size of the "recovered" secret value to be the size
724*5c591343SA. Cody Schuffelen // of the digest produced by the nameAlg.
725*5c591343SA. Cody Schuffelen data->t.size =
726*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(decryptKey->publicArea.nameAlg);
727*5c591343SA. Cody Schuffelen
728*5c591343SA. Cody Schuffelen // The secret value is computed from Z using KDFe as:
729*5c591343SA. Cody Schuffelen // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
730*5c591343SA. Cody Schuffelen // Where:
731*5c591343SA. Cody Schuffelen // HashID -- the nameAlg of the decrypt key
732*5c591343SA. Cody Schuffelen // Z -- the x coordinate (Px) of the product (P) of the point
733*5c591343SA. Cody Schuffelen // (Q) of the secret and the private x coordinate (de,V)
734*5c591343SA. Cody Schuffelen // of the decryption key
735*5c591343SA. Cody Schuffelen // Use -- a null-terminated string containing "SECRET"
736*5c591343SA. Cody Schuffelen // PartyUInfo -- the x coordinate of the point in the secret
737*5c591343SA. Cody Schuffelen // (Qe,U )
738*5c591343SA. Cody Schuffelen // PartyVInfo -- the x coordinate of the public key (Qs,V )
739*5c591343SA. Cody Schuffelen // bits -- the number of bits in the digest of HashID
740*5c591343SA. Cody Schuffelen // Retrieve seed from KDFe
741*5c591343SA. Cody Schuffelen CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,
742*5c591343SA. Cody Schuffelen &eccPublic.x.b,
743*5c591343SA. Cody Schuffelen &decryptKey->publicArea.unique.ecc.x.b,
744*5c591343SA. Cody Schuffelen data->t.size * 8, data->t.buffer);
745*5c591343SA. Cody Schuffelen }
746*5c591343SA. Cody Schuffelen }
747*5c591343SA. Cody Schuffelen }
748*5c591343SA. Cody Schuffelen break;
749*5c591343SA. Cody Schuffelen #endif // ALG_ECC
750*5c591343SA. Cody Schuffelen #if !ALG_KEYEDHASH
751*5c591343SA. Cody Schuffelen # error "KEYEDHASH support is required"
752*5c591343SA. Cody Schuffelen #endif
753*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
754*5c591343SA. Cody Schuffelen // The seed size can not be bigger than the digest size of nameAlg
755*5c591343SA. Cody Schuffelen if(secret->t.size >
756*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
757*5c591343SA. Cody Schuffelen result = TPM_RC_VALUE;
758*5c591343SA. Cody Schuffelen else
759*5c591343SA. Cody Schuffelen {
760*5c591343SA. Cody Schuffelen // Retrieve seed by XOR Obfuscation:
761*5c591343SA. Cody Schuffelen // seed = XOR(secret, hash, key, nonceCaller, nullNonce)
762*5c591343SA. Cody Schuffelen // where:
763*5c591343SA. Cody Schuffelen // secret the secret parameter from the TPM2_StartAuthHMAC
764*5c591343SA. Cody Schuffelen // command that contains the seed value
765*5c591343SA. Cody Schuffelen // hash nameAlg of tpmKey
766*5c591343SA. Cody Schuffelen // key the key or data value in the object referenced by
767*5c591343SA. Cody Schuffelen // entityHandle in the TPM2_StartAuthHMAC command
768*5c591343SA. Cody Schuffelen // nonceCaller the parameter from the TPM2_StartAuthHMAC command
769*5c591343SA. Cody Schuffelen // nullNonce a zero-length nonce
770*5c591343SA. Cody Schuffelen // XOR Obfuscation in place
771*5c591343SA. Cody Schuffelen CryptXORObfuscation(decryptKey->publicArea.nameAlg,
772*5c591343SA. Cody Schuffelen &decryptKey->sensitive.sensitive.bits.b,
773*5c591343SA. Cody Schuffelen &nonceCaller->b, NULL,
774*5c591343SA. Cody Schuffelen secret->t.size, secret->t.secret);
775*5c591343SA. Cody Schuffelen // Copy decrypted seed
776*5c591343SA. Cody Schuffelen MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
777*5c591343SA. Cody Schuffelen }
778*5c591343SA. Cody Schuffelen break;
779*5c591343SA. Cody Schuffelen case TPM_ALG_SYMCIPHER:
780*5c591343SA. Cody Schuffelen {
781*5c591343SA. Cody Schuffelen TPM2B_IV iv = {{0}};
782*5c591343SA. Cody Schuffelen TPMT_SYM_DEF_OBJECT *symDef;
783*5c591343SA. Cody Schuffelen // The seed size can not be bigger than the digest size of nameAlg
784*5c591343SA. Cody Schuffelen if(secret->t.size >
785*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
786*5c591343SA. Cody Schuffelen result = TPM_RC_VALUE;
787*5c591343SA. Cody Schuffelen else
788*5c591343SA. Cody Schuffelen {
789*5c591343SA. Cody Schuffelen symDef = &decryptKey->publicArea.parameters.symDetail.sym;
790*5c591343SA. Cody Schuffelen iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
791*5c591343SA. Cody Schuffelen symDef->keyBits.sym);
792*5c591343SA. Cody Schuffelen if(iv.t.size == 0)
793*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
794*5c591343SA. Cody Schuffelen if(nonceCaller->t.size >= iv.t.size)
795*5c591343SA. Cody Schuffelen {
796*5c591343SA. Cody Schuffelen MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size);
797*5c591343SA. Cody Schuffelen }
798*5c591343SA. Cody Schuffelen else
799*5c591343SA. Cody Schuffelen {
800*5c591343SA. Cody Schuffelen if(nonceCaller->t.size > sizeof(iv.t.buffer))
801*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
802*5c591343SA. Cody Schuffelen MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,
803*5c591343SA. Cody Schuffelen nonceCaller->t.size);
804*5c591343SA. Cody Schuffelen }
805*5c591343SA. Cody Schuffelen // make sure secret will fit
806*5c591343SA. Cody Schuffelen if(secret->t.size > data->t.size)
807*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
808*5c591343SA. Cody Schuffelen data->t.size = secret->t.size;
809*5c591343SA. Cody Schuffelen // CFB decrypt, using nonceCaller as iv
810*5c591343SA. Cody Schuffelen CryptSymmetricDecrypt(data->t.buffer, symDef->algorithm,
811*5c591343SA. Cody Schuffelen symDef->keyBits.sym,
812*5c591343SA. Cody Schuffelen decryptKey->sensitive.sensitive.sym.t.buffer,
813*5c591343SA. Cody Schuffelen &iv, TPM_ALG_CFB, secret->t.size,
814*5c591343SA. Cody Schuffelen secret->t.secret);
815*5c591343SA. Cody Schuffelen }
816*5c591343SA. Cody Schuffelen }
817*5c591343SA. Cody Schuffelen break;
818*5c591343SA. Cody Schuffelen default:
819*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
820*5c591343SA. Cody Schuffelen break;
821*5c591343SA. Cody Schuffelen }
822*5c591343SA. Cody Schuffelen return result;
823*5c591343SA. Cody Schuffelen }
824*5c591343SA. Cody Schuffelen
825*5c591343SA. Cody Schuffelen //*** CryptParameterEncryption()
826*5c591343SA. Cody Schuffelen // This function does in-place encryption of a response parameter.
827*5c591343SA. Cody Schuffelen void
CryptParameterEncryption(TPM_HANDLE handle,TPM2B * nonceCaller,UINT16 leadingSizeInByte,TPM2B_AUTH * extraKey,BYTE * buffer)828*5c591343SA. Cody Schuffelen CryptParameterEncryption(
829*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: encrypt session handle
830*5c591343SA. Cody Schuffelen TPM2B *nonceCaller, // IN: nonce caller
831*5c591343SA. Cody Schuffelen UINT16 leadingSizeInByte, // IN: the size of the leading size field in
832*5c591343SA. Cody Schuffelen // bytes
833*5c591343SA. Cody Schuffelen TPM2B_AUTH *extraKey, // IN: additional key material other than
834*5c591343SA. Cody Schuffelen // sessionAuth
835*5c591343SA. Cody Schuffelen BYTE *buffer // IN/OUT: parameter buffer to be encrypted
836*5c591343SA. Cody Schuffelen )
837*5c591343SA. Cody Schuffelen {
838*5c591343SA. Cody Schuffelen SESSION *session = SessionGet(handle); // encrypt session
839*5c591343SA. Cody Schuffelen TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer)
840*5c591343SA. Cody Schuffelen + sizeof(session->sessionKey.t.buffer)));
841*5c591343SA. Cody Schuffelen TPM2B_TEMP_KEY key; // encryption key
842*5c591343SA. Cody Schuffelen UINT32 cipherSize = 0; // size of cipher text
843*5c591343SA. Cody Schuffelen //
844*5c591343SA. Cody Schuffelen // Retrieve encrypted data size.
845*5c591343SA. Cody Schuffelen if(leadingSizeInByte == 2)
846*5c591343SA. Cody Schuffelen {
847*5c591343SA. Cody Schuffelen // Extract the first two bytes as the size field as the data size
848*5c591343SA. Cody Schuffelen // encrypt
849*5c591343SA. Cody Schuffelen cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
850*5c591343SA. Cody Schuffelen // advance the buffer
851*5c591343SA. Cody Schuffelen buffer = &buffer[2];
852*5c591343SA. Cody Schuffelen }
853*5c591343SA. Cody Schuffelen #ifdef TPM4B
854*5c591343SA. Cody Schuffelen else if(leadingSizeInByte == 4)
855*5c591343SA. Cody Schuffelen {
856*5c591343SA. Cody Schuffelen // use the first four bytes to indicate the number of bytes to encrypt
857*5c591343SA. Cody Schuffelen cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
858*5c591343SA. Cody Schuffelen //advance pointer
859*5c591343SA. Cody Schuffelen buffer = &buffer[4];
860*5c591343SA. Cody Schuffelen }
861*5c591343SA. Cody Schuffelen #endif
862*5c591343SA. Cody Schuffelen else
863*5c591343SA. Cody Schuffelen {
864*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
865*5c591343SA. Cody Schuffelen }
866*5c591343SA. Cody Schuffelen
867*5c591343SA. Cody Schuffelen // Compute encryption key by concatenating sessionKey with extra key
868*5c591343SA. Cody Schuffelen MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
869*5c591343SA. Cody Schuffelen MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
870*5c591343SA. Cody Schuffelen
871*5c591343SA. Cody Schuffelen if(session->symmetric.algorithm == TPM_ALG_XOR)
872*5c591343SA. Cody Schuffelen
873*5c591343SA. Cody Schuffelen // XOR parameter encryption formulation:
874*5c591343SA. Cody Schuffelen // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
875*5c591343SA. Cody Schuffelen CryptXORObfuscation(session->authHashAlg, &(key.b),
876*5c591343SA. Cody Schuffelen &(session->nonceTPM.b),
877*5c591343SA. Cody Schuffelen nonceCaller, cipherSize, buffer);
878*5c591343SA. Cody Schuffelen else
879*5c591343SA. Cody Schuffelen ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
880*5c591343SA. Cody Schuffelen session->symmetric.keyBits.aes, &(key.b),
881*5c591343SA. Cody Schuffelen nonceCaller, &(session->nonceTPM.b),
882*5c591343SA. Cody Schuffelen cipherSize, buffer);
883*5c591343SA. Cody Schuffelen return;
884*5c591343SA. Cody Schuffelen }
885*5c591343SA. Cody Schuffelen
886*5c591343SA. Cody Schuffelen //*** CryptParameterDecryption()
887*5c591343SA. Cody Schuffelen // This function does in-place decryption of a command parameter.
888*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
889*5c591343SA. Cody Schuffelen // TPM_RC_SIZE The number of bytes in the input buffer is less than
890*5c591343SA. Cody Schuffelen // the number of bytes to be decrypted.
891*5c591343SA. Cody Schuffelen TPM_RC
CryptParameterDecryption(TPM_HANDLE handle,TPM2B * nonceCaller,UINT32 bufferSize,UINT16 leadingSizeInByte,TPM2B_AUTH * extraKey,BYTE * buffer)892*5c591343SA. Cody Schuffelen CryptParameterDecryption(
893*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: encrypted session handle
894*5c591343SA. Cody Schuffelen TPM2B *nonceCaller, // IN: nonce caller
895*5c591343SA. Cody Schuffelen UINT32 bufferSize, // IN: size of parameter buffer
896*5c591343SA. Cody Schuffelen UINT16 leadingSizeInByte, // IN: the size of the leading size field in
897*5c591343SA. Cody Schuffelen // byte
898*5c591343SA. Cody Schuffelen TPM2B_AUTH *extraKey, // IN: the authValue
899*5c591343SA. Cody Schuffelen BYTE *buffer // IN/OUT: parameter buffer to be decrypted
900*5c591343SA. Cody Schuffelen )
901*5c591343SA. Cody Schuffelen {
902*5c591343SA. Cody Schuffelen SESSION *session = SessionGet(handle); // encrypt session
903*5c591343SA. Cody Schuffelen // The HMAC key is going to be the concatenation of the session key and any
904*5c591343SA. Cody Schuffelen // additional key material (like the authValue). The size of both of these
905*5c591343SA. Cody Schuffelen // is the size of the buffer which can contain a TPMT_HA.
906*5c591343SA. Cody Schuffelen TPM2B_TYPE(HMAC_KEY, (sizeof(extraKey->t.buffer)
907*5c591343SA. Cody Schuffelen + sizeof(session->sessionKey.t.buffer)));
908*5c591343SA. Cody Schuffelen TPM2B_HMAC_KEY key; // decryption key
909*5c591343SA. Cody Schuffelen UINT32 cipherSize = 0; // size of cipher text
910*5c591343SA. Cody Schuffelen //
911*5c591343SA. Cody Schuffelen // Retrieve encrypted data size.
912*5c591343SA. Cody Schuffelen if(leadingSizeInByte == 2)
913*5c591343SA. Cody Schuffelen {
914*5c591343SA. Cody Schuffelen // The first two bytes of the buffer are the size of the
915*5c591343SA. Cody Schuffelen // data to be decrypted
916*5c591343SA. Cody Schuffelen cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
917*5c591343SA. Cody Schuffelen buffer = &buffer[2]; // advance the buffer
918*5c591343SA. Cody Schuffelen }
919*5c591343SA. Cody Schuffelen #ifdef TPM4B
920*5c591343SA. Cody Schuffelen else if(leadingSizeInByte == 4)
921*5c591343SA. Cody Schuffelen {
922*5c591343SA. Cody Schuffelen // the leading size is four bytes so get the four byte size field
923*5c591343SA. Cody Schuffelen cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
924*5c591343SA. Cody Schuffelen buffer = &buffer[4]; //advance pointer
925*5c591343SA. Cody Schuffelen }
926*5c591343SA. Cody Schuffelen #endif
927*5c591343SA. Cody Schuffelen else
928*5c591343SA. Cody Schuffelen {
929*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
930*5c591343SA. Cody Schuffelen }
931*5c591343SA. Cody Schuffelen if(cipherSize > bufferSize)
932*5c591343SA. Cody Schuffelen return TPM_RC_SIZE;
933*5c591343SA. Cody Schuffelen
934*5c591343SA. Cody Schuffelen // Compute decryption key by concatenating sessionAuth with extra input key
935*5c591343SA. Cody Schuffelen MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
936*5c591343SA. Cody Schuffelen MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
937*5c591343SA. Cody Schuffelen
938*5c591343SA. Cody Schuffelen if(session->symmetric.algorithm == TPM_ALG_XOR)
939*5c591343SA. Cody Schuffelen // XOR parameter decryption formulation:
940*5c591343SA. Cody Schuffelen // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
941*5c591343SA. Cody Schuffelen // Call XOR obfuscation function
942*5c591343SA. Cody Schuffelen CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,
943*5c591343SA. Cody Schuffelen &(session->nonceTPM.b), cipherSize, buffer);
944*5c591343SA. Cody Schuffelen else
945*5c591343SA. Cody Schuffelen // Assume that it is one of the symmetric block ciphers.
946*5c591343SA. Cody Schuffelen ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,
947*5c591343SA. Cody Schuffelen session->symmetric.keyBits.sym,
948*5c591343SA. Cody Schuffelen &key.b, nonceCaller, &session->nonceTPM.b,
949*5c591343SA. Cody Schuffelen cipherSize, buffer);
950*5c591343SA. Cody Schuffelen
951*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
952*5c591343SA. Cody Schuffelen }
953*5c591343SA. Cody Schuffelen
954*5c591343SA. Cody Schuffelen //*** CryptComputeSymmetricUnique()
955*5c591343SA. Cody Schuffelen // This function computes the unique field in public area for symmetric objects.
956*5c591343SA. Cody Schuffelen void
CryptComputeSymmetricUnique(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM2B_DIGEST * unique)957*5c591343SA. Cody Schuffelen CryptComputeSymmetricUnique(
958*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea, // IN: the object's public area
959*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area
960*5c591343SA. Cody Schuffelen TPM2B_DIGEST *unique // OUT: unique buffer
961*5c591343SA. Cody Schuffelen )
962*5c591343SA. Cody Schuffelen {
963*5c591343SA. Cody Schuffelen // For parents (symmetric and derivation), use an HMAC to compute
964*5c591343SA. Cody Schuffelen // the 'unique' field
965*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
966*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt))
967*5c591343SA. Cody Schuffelen {
968*5c591343SA. Cody Schuffelen // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive)
969*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
970*5c591343SA. Cody Schuffelen unique->b.size = CryptHmacStart2B(&hmacState, publicArea->nameAlg,
971*5c591343SA. Cody Schuffelen &sensitive->seedValue.b);
972*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState,
973*5c591343SA. Cody Schuffelen &sensitive->sensitive.any.b);
974*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &unique->b);
975*5c591343SA. Cody Schuffelen }
976*5c591343SA. Cody Schuffelen else
977*5c591343SA. Cody Schuffelen {
978*5c591343SA. Cody Schuffelen HASH_STATE hashState;
979*5c591343SA. Cody Schuffelen // Unique := Hash(sensitive->seedValue || sensitive->sensitive)
980*5c591343SA. Cody Schuffelen unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg);
981*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b);
982*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b);
983*5c591343SA. Cody Schuffelen CryptHashEnd2B(&hashState, &unique->b);
984*5c591343SA. Cody Schuffelen }
985*5c591343SA. Cody Schuffelen return;
986*5c591343SA. Cody Schuffelen }
987*5c591343SA. Cody Schuffelen
988*5c591343SA. Cody Schuffelen //*** CryptCreateObject()
989*5c591343SA. Cody Schuffelen // This function creates an object.
990*5c591343SA. Cody Schuffelen // For an asymmetric key, it will create a key pair and, for a parent key, a seed
991*5c591343SA. Cody Schuffelen // value for child protections.
992*5c591343SA. Cody Schuffelen //
993*5c591343SA. Cody Schuffelen // For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will
994*5c591343SA. Cody Schuffelen // create a secret key if the caller did not provide one. It will create a random
995*5c591343SA. Cody Schuffelen // secret seed value that is hashed with the secret value to create the public
996*5c591343SA. Cody Schuffelen // unique value.
997*5c591343SA. Cody Schuffelen //
998*5c591343SA. Cody Schuffelen // 'publicArea', 'sensitive', and 'sensitiveCreate' are the only required parameters
999*5c591343SA. Cody Schuffelen // and are the only ones that are used by TPM2_Create(). The other parameters
1000*5c591343SA. Cody Schuffelen // are optional and are used when the generated Object needs to be deterministic.
1001*5c591343SA. Cody Schuffelen // This is the case for both Primary Objects and Derived Objects.
1002*5c591343SA. Cody Schuffelen //
1003*5c591343SA. Cody Schuffelen // When a seed value is provided, a RAND_STATE will be populated and used for
1004*5c591343SA. Cody Schuffelen // all operations in the object generation that require a random number. In the
1005*5c591343SA. Cody Schuffelen // simplest case, TPM2_CreatePrimary() will use 'seed', 'label' and 'context' with
1006*5c591343SA. Cody Schuffelen // context being the hash of the template. If the Primary Object is in
1007*5c591343SA. Cody Schuffelen // the Endorsement hierarchy, it will also populate 'proof' with ehProof.
1008*5c591343SA. Cody Schuffelen //
1009*5c591343SA. Cody Schuffelen // For derived keys, 'seed' will be the secret value from the parent, 'label' and
1010*5c591343SA. Cody Schuffelen // 'context' will be set according to the parameters of TPM2_CreateLoaded() and
1011*5c591343SA. Cody Schuffelen // 'hashAlg' will be set which causes the RAND_STATE to be a KDF generator.
1012*5c591343SA. Cody Schuffelen //
1013*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1014*5c591343SA. Cody Schuffelen // TPM_RC_KEY a provided key is not an allowed value
1015*5c591343SA. Cody Schuffelen // TPM_RC_KEY_SIZE key size in the public area does not match the size
1016*5c591343SA. Cody Schuffelen // in the sensitive creation area for a symmetric key
1017*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT unable to get random values (only in derivation)
1018*5c591343SA. Cody Schuffelen // TPM_RC_RANGE for an RSA key, the exponent is not supported
1019*5c591343SA. Cody Schuffelen // TPM_RC_SIZE sensitive data size is larger than allowed for the
1020*5c591343SA. Cody Schuffelen // scheme for a keyed hash object
1021*5c591343SA. Cody Schuffelen // TPM_RC_VALUE exponent is not prime or could not find a prime using
1022*5c591343SA. Cody Schuffelen // the provided parameters for an RSA key;
1023*5c591343SA. Cody Schuffelen // unsupported name algorithm for an ECC key
1024*5c591343SA. Cody Schuffelen TPM_RC
CryptCreateObject(OBJECT * object,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)1025*5c591343SA. Cody Schuffelen CryptCreateObject(
1026*5c591343SA. Cody Schuffelen OBJECT *object, // IN: new object structure pointer
1027*5c591343SA. Cody Schuffelen TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation
1028*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: the random number generator
1029*5c591343SA. Cody Schuffelen // to use
1030*5c591343SA. Cody Schuffelen )
1031*5c591343SA. Cody Schuffelen {
1032*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea = &object->publicArea;
1033*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive = &object->sensitive;
1034*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1035*5c591343SA. Cody Schuffelen //
1036*5c591343SA. Cody Schuffelen // Set the sensitive type for the object
1037*5c591343SA. Cody Schuffelen sensitive->sensitiveType = publicArea->type;
1038*5c591343SA. Cody Schuffelen
1039*5c591343SA. Cody Schuffelen // For all objects, copy the initial authorization data
1040*5c591343SA. Cody Schuffelen sensitive->authValue = sensitiveCreate->userAuth;
1041*5c591343SA. Cody Schuffelen
1042*5c591343SA. Cody Schuffelen // If the TPM is the source of the data, set the size of the provided data to
1043*5c591343SA. Cody Schuffelen // zero so that there's no confusion about what to do.
1044*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->objectAttributes,
1045*5c591343SA. Cody Schuffelen TPMA_OBJECT, sensitiveDataOrigin))
1046*5c591343SA. Cody Schuffelen sensitiveCreate->data.t.size = 0;
1047*5c591343SA. Cody Schuffelen
1048*5c591343SA. Cody Schuffelen // Generate the key and unique fields for the asymmetric keys and just the
1049*5c591343SA. Cody Schuffelen // sensitive value for symmetric object
1050*5c591343SA. Cody Schuffelen switch(publicArea->type)
1051*5c591343SA. Cody Schuffelen {
1052*5c591343SA. Cody Schuffelen #if ALG_RSA
1053*5c591343SA. Cody Schuffelen // Create RSA key
1054*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1055*5c591343SA. Cody Schuffelen // RSA uses full object so that it has a place to put the private
1056*5c591343SA. Cody Schuffelen // exponent
1057*5c591343SA. Cody Schuffelen result = CryptRsaGenerateKey(publicArea, sensitive, rand);
1058*5c591343SA. Cody Schuffelen break;
1059*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1060*5c591343SA. Cody Schuffelen
1061*5c591343SA. Cody Schuffelen #if ALG_ECC
1062*5c591343SA. Cody Schuffelen // Create ECC key
1063*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1064*5c591343SA. Cody Schuffelen result = CryptEccGenerateKey(publicArea, sensitive, rand);
1065*5c591343SA. Cody Schuffelen break;
1066*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1067*5c591343SA. Cody Schuffelen case TPM_ALG_SYMCIPHER:
1068*5c591343SA. Cody Schuffelen result = CryptGenerateKeySymmetric(publicArea, sensitive,
1069*5c591343SA. Cody Schuffelen sensitiveCreate, rand);
1070*5c591343SA. Cody Schuffelen break;
1071*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
1072*5c591343SA. Cody Schuffelen result = CryptGenerateKeyedHash(publicArea, sensitive,
1073*5c591343SA. Cody Schuffelen sensitiveCreate, rand);
1074*5c591343SA. Cody Schuffelen break;
1075*5c591343SA. Cody Schuffelen default:
1076*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
1077*5c591343SA. Cody Schuffelen break;
1078*5c591343SA. Cody Schuffelen }
1079*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1080*5c591343SA. Cody Schuffelen return result;
1081*5c591343SA. Cody Schuffelen // Create the sensitive seed value
1082*5c591343SA. Cody Schuffelen // If this is a primary key in the endorsement hierarchy, stir the DRBG state
1083*5c591343SA. Cody Schuffelen // This implementation uses both shProof and ehProof to make sure that there
1084*5c591343SA. Cody Schuffelen // is no leakage of either.
1085*5c591343SA. Cody Schuffelen if(object->attributes.primary && object->attributes.epsHierarchy)
1086*5c591343SA. Cody Schuffelen {
1087*5c591343SA. Cody Schuffelen DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b);
1088*5c591343SA. Cody Schuffelen DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b);
1089*5c591343SA. Cody Schuffelen }
1090*5c591343SA. Cody Schuffelen // Generate a seedValue that is the size of the digest produced by nameAlg
1091*5c591343SA. Cody Schuffelen sensitive->seedValue.t.size =
1092*5c591343SA. Cody Schuffelen DRBG_Generate(rand, sensitive->seedValue.t.buffer,
1093*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(publicArea->nameAlg));
1094*5c591343SA. Cody Schuffelen if(g_inFailureMode)
1095*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
1096*5c591343SA. Cody Schuffelen else if(sensitive->seedValue.t.size == 0)
1097*5c591343SA. Cody Schuffelen return TPM_RC_NO_RESULT;
1098*5c591343SA. Cody Schuffelen // For symmetric objects, need to compute the unique value for the public area
1099*5c591343SA. Cody Schuffelen if(publicArea->type == TPM_ALG_SYMCIPHER
1100*5c591343SA. Cody Schuffelen || publicArea->type == TPM_ALG_KEYEDHASH)
1101*5c591343SA. Cody Schuffelen {
1102*5c591343SA. Cody Schuffelen CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym);
1103*5c591343SA. Cody Schuffelen }
1104*5c591343SA. Cody Schuffelen else
1105*5c591343SA. Cody Schuffelen {
1106*5c591343SA. Cody Schuffelen // if this is an asymmetric key and it isn't a parent, then
1107*5c591343SA. Cody Schuffelen // get rid of the seed.
1108*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
1109*5c591343SA. Cody Schuffelen || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
1110*5c591343SA. Cody Schuffelen memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue));
1111*5c591343SA. Cody Schuffelen }
1112*5c591343SA. Cody Schuffelen // Compute the name
1113*5c591343SA. Cody Schuffelen PublicMarshalAndComputeName(publicArea, &object->name);
1114*5c591343SA. Cody Schuffelen return result;
1115*5c591343SA. Cody Schuffelen }
1116*5c591343SA. Cody Schuffelen
1117*5c591343SA. Cody Schuffelen //*** CryptGetSignHashAlg()
1118*5c591343SA. Cody Schuffelen // Get the hash algorithm of signature from a TPMT_SIGNATURE structure.
1119*5c591343SA. Cody Schuffelen // It assumes the signature is not NULL
1120*5c591343SA. Cody Schuffelen // This is a function for easy access
1121*5c591343SA. Cody Schuffelen TPMI_ALG_HASH
CryptGetSignHashAlg(TPMT_SIGNATURE * auth)1122*5c591343SA. Cody Schuffelen CryptGetSignHashAlg(
1123*5c591343SA. Cody Schuffelen TPMT_SIGNATURE *auth // IN: signature
1124*5c591343SA. Cody Schuffelen )
1125*5c591343SA. Cody Schuffelen {
1126*5c591343SA. Cody Schuffelen if(auth->sigAlg == TPM_ALG_NULL)
1127*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
1128*5c591343SA. Cody Schuffelen
1129*5c591343SA. Cody Schuffelen // Get authHash algorithm based on signing scheme
1130*5c591343SA. Cody Schuffelen switch(auth->sigAlg)
1131*5c591343SA. Cody Schuffelen {
1132*5c591343SA. Cody Schuffelen #if ALG_RSA
1133*5c591343SA. Cody Schuffelen // If RSA is supported, both RSASSA and RSAPSS are required
1134*5c591343SA. Cody Schuffelen # if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS
1135*5c591343SA. Cody Schuffelen # error "RSASSA and RSAPSS are required for RSA"
1136*5c591343SA. Cody Schuffelen # endif
1137*5c591343SA. Cody Schuffelen case TPM_ALG_RSASSA:
1138*5c591343SA. Cody Schuffelen return auth->signature.rsassa.hash;
1139*5c591343SA. Cody Schuffelen case TPM_ALG_RSAPSS:
1140*5c591343SA. Cody Schuffelen return auth->signature.rsapss.hash;
1141*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1142*5c591343SA. Cody Schuffelen
1143*5c591343SA. Cody Schuffelen #if ALG_ECC
1144*5c591343SA. Cody Schuffelen // If ECC is defined, ECDSA is mandatory
1145*5c591343SA. Cody Schuffelen # if !ALG_ECDSA
1146*5c591343SA. Cody Schuffelen # error "ECDSA is requried for ECC"
1147*5c591343SA. Cody Schuffelen # endif
1148*5c591343SA. Cody Schuffelen case TPM_ALG_ECDSA:
1149*5c591343SA. Cody Schuffelen // SM2 and ECSCHNORR are optional
1150*5c591343SA. Cody Schuffelen
1151*5c591343SA. Cody Schuffelen # if ALG_SM2
1152*5c591343SA. Cody Schuffelen case TPM_ALG_SM2:
1153*5c591343SA. Cody Schuffelen # endif
1154*5c591343SA. Cody Schuffelen # if ALG_ECSCHNORR
1155*5c591343SA. Cody Schuffelen case TPM_ALG_ECSCHNORR:
1156*5c591343SA. Cody Schuffelen # endif
1157*5c591343SA. Cody Schuffelen //all ECC signatures look the same
1158*5c591343SA. Cody Schuffelen return auth->signature.ecdsa.hash;
1159*5c591343SA. Cody Schuffelen
1160*5c591343SA. Cody Schuffelen # if ALG_ECDAA
1161*5c591343SA. Cody Schuffelen // Don't know how to verify an ECDAA signature
1162*5c591343SA. Cody Schuffelen case TPM_ALG_ECDAA:
1163*5c591343SA. Cody Schuffelen break;
1164*5c591343SA. Cody Schuffelen # endif
1165*5c591343SA. Cody Schuffelen
1166*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1167*5c591343SA. Cody Schuffelen
1168*5c591343SA. Cody Schuffelen case TPM_ALG_HMAC:
1169*5c591343SA. Cody Schuffelen return auth->signature.hmac.hashAlg;
1170*5c591343SA. Cody Schuffelen
1171*5c591343SA. Cody Schuffelen default:
1172*5c591343SA. Cody Schuffelen break;
1173*5c591343SA. Cody Schuffelen }
1174*5c591343SA. Cody Schuffelen return TPM_ALG_NULL;
1175*5c591343SA. Cody Schuffelen }
1176*5c591343SA. Cody Schuffelen
1177*5c591343SA. Cody Schuffelen //*** CryptIsSplitSign()
1178*5c591343SA. Cody Schuffelen // This function us used to determine if the signing operation is a split
1179*5c591343SA. Cody Schuffelen // signing operation that required a TPM2_Commit().
1180*5c591343SA. Cody Schuffelen //
1181*5c591343SA. Cody Schuffelen BOOL
CryptIsSplitSign(TPM_ALG_ID scheme)1182*5c591343SA. Cody Schuffelen CryptIsSplitSign(
1183*5c591343SA. Cody Schuffelen TPM_ALG_ID scheme // IN: the algorithm selector
1184*5c591343SA. Cody Schuffelen )
1185*5c591343SA. Cody Schuffelen {
1186*5c591343SA. Cody Schuffelen switch(scheme)
1187*5c591343SA. Cody Schuffelen {
1188*5c591343SA. Cody Schuffelen # if ALG_ECDAA
1189*5c591343SA. Cody Schuffelen case TPM_ALG_ECDAA:
1190*5c591343SA. Cody Schuffelen return TRUE;
1191*5c591343SA. Cody Schuffelen break;
1192*5c591343SA. Cody Schuffelen # endif // ALG_ECDAA
1193*5c591343SA. Cody Schuffelen default:
1194*5c591343SA. Cody Schuffelen return FALSE;
1195*5c591343SA. Cody Schuffelen break;
1196*5c591343SA. Cody Schuffelen }
1197*5c591343SA. Cody Schuffelen }
1198*5c591343SA. Cody Schuffelen
1199*5c591343SA. Cody Schuffelen //*** CryptIsAsymSignScheme()
1200*5c591343SA. Cody Schuffelen // This function indicates if a scheme algorithm is a sign algorithm.
1201*5c591343SA. Cody Schuffelen BOOL
CryptIsAsymSignScheme(TPMI_ALG_PUBLIC publicType,TPMI_ALG_ASYM_SCHEME scheme)1202*5c591343SA. Cody Schuffelen CryptIsAsymSignScheme(
1203*5c591343SA. Cody Schuffelen TPMI_ALG_PUBLIC publicType, // IN: Type of the object
1204*5c591343SA. Cody Schuffelen TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme
1205*5c591343SA. Cody Schuffelen )
1206*5c591343SA. Cody Schuffelen {
1207*5c591343SA. Cody Schuffelen BOOL isSignScheme = TRUE;
1208*5c591343SA. Cody Schuffelen
1209*5c591343SA. Cody Schuffelen switch(publicType)
1210*5c591343SA. Cody Schuffelen {
1211*5c591343SA. Cody Schuffelen #if ALG_RSA
1212*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1213*5c591343SA. Cody Schuffelen switch(scheme)
1214*5c591343SA. Cody Schuffelen {
1215*5c591343SA. Cody Schuffelen # if !ALG_RSASSA || !ALG_RSAPSS
1216*5c591343SA. Cody Schuffelen # error "RSASSA and PSAPSS required if RSA used."
1217*5c591343SA. Cody Schuffelen # endif
1218*5c591343SA. Cody Schuffelen case TPM_ALG_RSASSA:
1219*5c591343SA. Cody Schuffelen case TPM_ALG_RSAPSS:
1220*5c591343SA. Cody Schuffelen break;
1221*5c591343SA. Cody Schuffelen default:
1222*5c591343SA. Cody Schuffelen isSignScheme = FALSE;
1223*5c591343SA. Cody Schuffelen break;
1224*5c591343SA. Cody Schuffelen }
1225*5c591343SA. Cody Schuffelen break;
1226*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1227*5c591343SA. Cody Schuffelen
1228*5c591343SA. Cody Schuffelen #if ALG_ECC
1229*5c591343SA. Cody Schuffelen // If ECC is implemented ECDSA is required
1230*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1231*5c591343SA. Cody Schuffelen switch(scheme)
1232*5c591343SA. Cody Schuffelen {
1233*5c591343SA. Cody Schuffelen // Support for ECDSA is required for ECC
1234*5c591343SA. Cody Schuffelen case TPM_ALG_ECDSA:
1235*5c591343SA. Cody Schuffelen #if ALG_ECDAA // ECDAA is optional
1236*5c591343SA. Cody Schuffelen case TPM_ALG_ECDAA:
1237*5c591343SA. Cody Schuffelen #endif
1238*5c591343SA. Cody Schuffelen #if ALG_ECSCHNORR // Schnorr is also optional
1239*5c591343SA. Cody Schuffelen case TPM_ALG_ECSCHNORR:
1240*5c591343SA. Cody Schuffelen #endif
1241*5c591343SA. Cody Schuffelen #if ALG_SM2 // SM2 is optional
1242*5c591343SA. Cody Schuffelen case TPM_ALG_SM2:
1243*5c591343SA. Cody Schuffelen #endif
1244*5c591343SA. Cody Schuffelen break;
1245*5c591343SA. Cody Schuffelen default:
1246*5c591343SA. Cody Schuffelen isSignScheme = FALSE;
1247*5c591343SA. Cody Schuffelen break;
1248*5c591343SA. Cody Schuffelen }
1249*5c591343SA. Cody Schuffelen break;
1250*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1251*5c591343SA. Cody Schuffelen default:
1252*5c591343SA. Cody Schuffelen isSignScheme = FALSE;
1253*5c591343SA. Cody Schuffelen break;
1254*5c591343SA. Cody Schuffelen }
1255*5c591343SA. Cody Schuffelen return isSignScheme;
1256*5c591343SA. Cody Schuffelen }
1257*5c591343SA. Cody Schuffelen
1258*5c591343SA. Cody Schuffelen //*** CryptIsAsymDecryptScheme()
1259*5c591343SA. Cody Schuffelen // This function indicate if a scheme algorithm is a decrypt algorithm.
1260*5c591343SA. Cody Schuffelen BOOL
CryptIsAsymDecryptScheme(TPMI_ALG_PUBLIC publicType,TPMI_ALG_ASYM_SCHEME scheme)1261*5c591343SA. Cody Schuffelen CryptIsAsymDecryptScheme(
1262*5c591343SA. Cody Schuffelen TPMI_ALG_PUBLIC publicType, // IN: Type of the object
1263*5c591343SA. Cody Schuffelen TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme
1264*5c591343SA. Cody Schuffelen )
1265*5c591343SA. Cody Schuffelen {
1266*5c591343SA. Cody Schuffelen BOOL isDecryptScheme = TRUE;
1267*5c591343SA. Cody Schuffelen
1268*5c591343SA. Cody Schuffelen switch(publicType)
1269*5c591343SA. Cody Schuffelen {
1270*5c591343SA. Cody Schuffelen #if ALG_RSA
1271*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1272*5c591343SA. Cody Schuffelen switch(scheme)
1273*5c591343SA. Cody Schuffelen {
1274*5c591343SA. Cody Schuffelen case TPM_ALG_RSAES:
1275*5c591343SA. Cody Schuffelen case TPM_ALG_OAEP:
1276*5c591343SA. Cody Schuffelen break;
1277*5c591343SA. Cody Schuffelen default:
1278*5c591343SA. Cody Schuffelen isDecryptScheme = FALSE;
1279*5c591343SA. Cody Schuffelen break;
1280*5c591343SA. Cody Schuffelen }
1281*5c591343SA. Cody Schuffelen break;
1282*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1283*5c591343SA. Cody Schuffelen
1284*5c591343SA. Cody Schuffelen #if ALG_ECC
1285*5c591343SA. Cody Schuffelen // If ECC is implemented ECDH is required
1286*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1287*5c591343SA. Cody Schuffelen switch(scheme)
1288*5c591343SA. Cody Schuffelen {
1289*5c591343SA. Cody Schuffelen #if !ALG_ECDH
1290*5c591343SA. Cody Schuffelen # error "ECDH is required for ECC"
1291*5c591343SA. Cody Schuffelen #endif
1292*5c591343SA. Cody Schuffelen case TPM_ALG_ECDH:
1293*5c591343SA. Cody Schuffelen #if ALG_SM2
1294*5c591343SA. Cody Schuffelen case TPM_ALG_SM2:
1295*5c591343SA. Cody Schuffelen #endif
1296*5c591343SA. Cody Schuffelen #if ALG_ECMQV
1297*5c591343SA. Cody Schuffelen case TPM_ALG_ECMQV:
1298*5c591343SA. Cody Schuffelen #endif
1299*5c591343SA. Cody Schuffelen break;
1300*5c591343SA. Cody Schuffelen default:
1301*5c591343SA. Cody Schuffelen isDecryptScheme = FALSE;
1302*5c591343SA. Cody Schuffelen break;
1303*5c591343SA. Cody Schuffelen }
1304*5c591343SA. Cody Schuffelen break;
1305*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1306*5c591343SA. Cody Schuffelen default:
1307*5c591343SA. Cody Schuffelen isDecryptScheme = FALSE;
1308*5c591343SA. Cody Schuffelen break;
1309*5c591343SA. Cody Schuffelen }
1310*5c591343SA. Cody Schuffelen return isDecryptScheme;
1311*5c591343SA. Cody Schuffelen }
1312*5c591343SA. Cody Schuffelen
1313*5c591343SA. Cody Schuffelen //*** CryptSelectSignScheme()
1314*5c591343SA. Cody Schuffelen // This function is used by the attestation and signing commands. It implements
1315*5c591343SA. Cody Schuffelen // the rules for selecting the signature scheme to use in signing. This function
1316*5c591343SA. Cody Schuffelen // requires that the signing key either be TPM_RH_NULL or be loaded.
1317*5c591343SA. Cody Schuffelen //
1318*5c591343SA. Cody Schuffelen // If a default scheme is defined in object, the default scheme should be chosen,
1319*5c591343SA. Cody Schuffelen // otherwise, the input scheme should be chosen.
1320*5c591343SA. Cody Schuffelen // In the case that both object and input scheme has a non-NULL scheme
1321*5c591343SA. Cody Schuffelen // algorithm, if the schemes are compatible, the input scheme will be chosen.
1322*5c591343SA. Cody Schuffelen //
1323*5c591343SA. Cody Schuffelen // This function should not be called if 'signObject->publicArea.type' ==
1324*5c591343SA. Cody Schuffelen // ALG_SYMCIPHER.
1325*5c591343SA. Cody Schuffelen //
1326*5c591343SA. Cody Schuffelen // Return Type: BOOL
1327*5c591343SA. Cody Schuffelen // TRUE(1) scheme selected
1328*5c591343SA. Cody Schuffelen // FALSE(0) both 'scheme' and key's default scheme are empty; or
1329*5c591343SA. Cody Schuffelen // 'scheme' is empty while key's default scheme requires
1330*5c591343SA. Cody Schuffelen // explicit input scheme (split signing); or
1331*5c591343SA. Cody Schuffelen // non-empty default key scheme differs from 'scheme'
1332*5c591343SA. Cody Schuffelen BOOL
CryptSelectSignScheme(OBJECT * signObject,TPMT_SIG_SCHEME * scheme)1333*5c591343SA. Cody Schuffelen CryptSelectSignScheme(
1334*5c591343SA. Cody Schuffelen OBJECT *signObject, // IN: signing key
1335*5c591343SA. Cody Schuffelen TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme
1336*5c591343SA. Cody Schuffelen )
1337*5c591343SA. Cody Schuffelen {
1338*5c591343SA. Cody Schuffelen TPMT_SIG_SCHEME *objectScheme;
1339*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea;
1340*5c591343SA. Cody Schuffelen BOOL OK;
1341*5c591343SA. Cody Schuffelen
1342*5c591343SA. Cody Schuffelen // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
1343*5c591343SA. Cody Schuffelen // of the setting of scheme
1344*5c591343SA. Cody Schuffelen if(signObject == NULL)
1345*5c591343SA. Cody Schuffelen {
1346*5c591343SA. Cody Schuffelen OK = TRUE;
1347*5c591343SA. Cody Schuffelen scheme->scheme = TPM_ALG_NULL;
1348*5c591343SA. Cody Schuffelen scheme->details.any.hashAlg = TPM_ALG_NULL;
1349*5c591343SA. Cody Schuffelen }
1350*5c591343SA. Cody Schuffelen else
1351*5c591343SA. Cody Schuffelen {
1352*5c591343SA. Cody Schuffelen // assignment to save typing.
1353*5c591343SA. Cody Schuffelen publicArea = &signObject->publicArea;
1354*5c591343SA. Cody Schuffelen
1355*5c591343SA. Cody Schuffelen // A symmetric cipher can be used to encrypt and decrypt but it can't
1356*5c591343SA. Cody Schuffelen // be used for signing
1357*5c591343SA. Cody Schuffelen if(publicArea->type == TPM_ALG_SYMCIPHER)
1358*5c591343SA. Cody Schuffelen return FALSE;
1359*5c591343SA. Cody Schuffelen // Point to the scheme object
1360*5c591343SA. Cody Schuffelen if(CryptIsAsymAlgorithm(publicArea->type))
1361*5c591343SA. Cody Schuffelen objectScheme =
1362*5c591343SA. Cody Schuffelen (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme;
1363*5c591343SA. Cody Schuffelen else
1364*5c591343SA. Cody Schuffelen objectScheme =
1365*5c591343SA. Cody Schuffelen (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme;
1366*5c591343SA. Cody Schuffelen
1367*5c591343SA. Cody Schuffelen // If the object doesn't have a default scheme, then use the
1368*5c591343SA. Cody Schuffelen // input scheme.
1369*5c591343SA. Cody Schuffelen if(objectScheme->scheme == TPM_ALG_NULL)
1370*5c591343SA. Cody Schuffelen {
1371*5c591343SA. Cody Schuffelen // Input and default can't both be NULL
1372*5c591343SA. Cody Schuffelen OK = (scheme->scheme != TPM_ALG_NULL);
1373*5c591343SA. Cody Schuffelen // Assume that the scheme is compatible with the key. If not,
1374*5c591343SA. Cody Schuffelen // an error will be generated in the signing operation.
1375*5c591343SA. Cody Schuffelen }
1376*5c591343SA. Cody Schuffelen else if(scheme->scheme == TPM_ALG_NULL)
1377*5c591343SA. Cody Schuffelen {
1378*5c591343SA. Cody Schuffelen // input scheme is NULL so use default
1379*5c591343SA. Cody Schuffelen
1380*5c591343SA. Cody Schuffelen // First, check to see if the default requires that the caller
1381*5c591343SA. Cody Schuffelen // provided scheme data
1382*5c591343SA. Cody Schuffelen OK = !CryptIsSplitSign(objectScheme->scheme);
1383*5c591343SA. Cody Schuffelen if(OK)
1384*5c591343SA. Cody Schuffelen {
1385*5c591343SA. Cody Schuffelen // The object has a scheme and the input is TPM_ALG_NULL so copy
1386*5c591343SA. Cody Schuffelen // the object scheme as the final scheme. It is better to use a
1387*5c591343SA. Cody Schuffelen // structure copy than a copy of the individual fields.
1388*5c591343SA. Cody Schuffelen *scheme = *objectScheme;
1389*5c591343SA. Cody Schuffelen }
1390*5c591343SA. Cody Schuffelen }
1391*5c591343SA. Cody Schuffelen else
1392*5c591343SA. Cody Schuffelen {
1393*5c591343SA. Cody Schuffelen // Both input and object have scheme selectors
1394*5c591343SA. Cody Schuffelen // If the scheme and the hash are not the same then...
1395*5c591343SA. Cody Schuffelen // NOTE: the reason that there is no copy here is that the input
1396*5c591343SA. Cody Schuffelen // might contain extra data for a split signing scheme and that
1397*5c591343SA. Cody Schuffelen // data is not in the object so, it has to be preserved.
1398*5c591343SA. Cody Schuffelen OK = (objectScheme->scheme == scheme->scheme)
1399*5c591343SA. Cody Schuffelen && (objectScheme->details.any.hashAlg
1400*5c591343SA. Cody Schuffelen == scheme->details.any.hashAlg);
1401*5c591343SA. Cody Schuffelen }
1402*5c591343SA. Cody Schuffelen }
1403*5c591343SA. Cody Schuffelen return OK;
1404*5c591343SA. Cody Schuffelen }
1405*5c591343SA. Cody Schuffelen
1406*5c591343SA. Cody Schuffelen //*** CryptSign()
1407*5c591343SA. Cody Schuffelen // Sign a digest with asymmetric key or HMAC.
1408*5c591343SA. Cody Schuffelen // This function is called by attestation commands and the generic TPM2_Sign
1409*5c591343SA. Cody Schuffelen // command.
1410*5c591343SA. Cody Schuffelen // This function checks the key scheme and digest size. It does not
1411*5c591343SA. Cody Schuffelen // check if the sign operation is allowed for restricted key. It should be
1412*5c591343SA. Cody Schuffelen // checked before the function is called.
1413*5c591343SA. Cody Schuffelen // The function will assert if the key is not a signing key.
1414*5c591343SA. Cody Schuffelen //
1415*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1416*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME 'signScheme' is not compatible with the signing key type
1417*5c591343SA. Cody Schuffelen // TPM_RC_VALUE 'digest' value is greater than the modulus of
1418*5c591343SA. Cody Schuffelen // 'signHandle' or size of 'hashData' does not match hash
1419*5c591343SA. Cody Schuffelen // algorithm in'signScheme' (for an RSA key);
1420*5c591343SA. Cody Schuffelen // invalid commit status or failed to generate "r" value
1421*5c591343SA. Cody Schuffelen // (for an ECC key)
1422*5c591343SA. Cody Schuffelen TPM_RC
CryptSign(OBJECT * signKey,TPMT_SIG_SCHEME * signScheme,TPM2B_DIGEST * digest,TPMT_SIGNATURE * signature)1423*5c591343SA. Cody Schuffelen CryptSign(
1424*5c591343SA. Cody Schuffelen OBJECT *signKey, // IN: signing key
1425*5c591343SA. Cody Schuffelen TPMT_SIG_SCHEME *signScheme, // IN: sign scheme.
1426*5c591343SA. Cody Schuffelen TPM2B_DIGEST *digest, // IN: The digest being signed
1427*5c591343SA. Cody Schuffelen TPMT_SIGNATURE *signature // OUT: signature
1428*5c591343SA. Cody Schuffelen )
1429*5c591343SA. Cody Schuffelen {
1430*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SCHEME;
1431*5c591343SA. Cody Schuffelen
1432*5c591343SA. Cody Schuffelen // Initialize signature scheme
1433*5c591343SA. Cody Schuffelen signature->sigAlg = signScheme->scheme;
1434*5c591343SA. Cody Schuffelen
1435*5c591343SA. Cody Schuffelen // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL,
1436*5c591343SA. Cody Schuffelen // then we are done
1437*5c591343SA. Cody Schuffelen if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL))
1438*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1439*5c591343SA. Cody Schuffelen
1440*5c591343SA. Cody Schuffelen // Initialize signature hash
1441*5c591343SA. Cody Schuffelen // Note: need to do the check for TPM_ALG_NULL first because the null scheme
1442*5c591343SA. Cody Schuffelen // doesn't have a hashAlg member.
1443*5c591343SA. Cody Schuffelen signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
1444*5c591343SA. Cody Schuffelen
1445*5c591343SA. Cody Schuffelen // perform sign operation based on different key type
1446*5c591343SA. Cody Schuffelen switch(signKey->publicArea.type)
1447*5c591343SA. Cody Schuffelen {
1448*5c591343SA. Cody Schuffelen #if ALG_RSA
1449*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1450*5c591343SA. Cody Schuffelen result = CryptRsaSign(signature, signKey, digest, NULL);
1451*5c591343SA. Cody Schuffelen break;
1452*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1453*5c591343SA. Cody Schuffelen #if ALG_ECC
1454*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1455*5c591343SA. Cody Schuffelen // The reason that signScheme is passed to CryptEccSign but not to the
1456*5c591343SA. Cody Schuffelen // other signing methods is that the signing for ECC may be split and
1457*5c591343SA. Cody Schuffelen // need the 'r' value that is in the scheme but not in the signature.
1458*5c591343SA. Cody Schuffelen result = CryptEccSign(signature, signKey, digest,
1459*5c591343SA. Cody Schuffelen (TPMT_ECC_SCHEME *)signScheme, NULL);
1460*5c591343SA. Cody Schuffelen break;
1461*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1462*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
1463*5c591343SA. Cody Schuffelen result = CryptHmacSign(signature, signKey, digest);
1464*5c591343SA. Cody Schuffelen break;
1465*5c591343SA. Cody Schuffelen default:
1466*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
1467*5c591343SA. Cody Schuffelen break;
1468*5c591343SA. Cody Schuffelen }
1469*5c591343SA. Cody Schuffelen return result;
1470*5c591343SA. Cody Schuffelen }
1471*5c591343SA. Cody Schuffelen
1472*5c591343SA. Cody Schuffelen //*** CryptValidateSignature()
1473*5c591343SA. Cody Schuffelen // This function is used to verify a signature. It is called by
1474*5c591343SA. Cody Schuffelen // TPM2_VerifySignature() and TPM2_PolicySigned.
1475*5c591343SA. Cody Schuffelen //
1476*5c591343SA. Cody Schuffelen // Since this operation only requires use of a public key, no consistency
1477*5c591343SA. Cody Schuffelen // checks are necessary for the key to signature type because a caller can load
1478*5c591343SA. Cody Schuffelen // any public key that they like with any scheme that they like. This routine
1479*5c591343SA. Cody Schuffelen // simply makes sure that the signature is correct, whatever the type.
1480*5c591343SA. Cody Schuffelen //
1481*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1482*5c591343SA. Cody Schuffelen // TPM_RC_SIGNATURE the signature is not genuine
1483*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME the scheme is not supported
1484*5c591343SA. Cody Schuffelen // TPM_RC_HANDLE an HMAC key was selected but the
1485*5c591343SA. Cody Schuffelen // private part of the key is not loaded
1486*5c591343SA. Cody Schuffelen TPM_RC
CryptValidateSignature(TPMI_DH_OBJECT keyHandle,TPM2B_DIGEST * digest,TPMT_SIGNATURE * signature)1487*5c591343SA. Cody Schuffelen CryptValidateSignature(
1488*5c591343SA. Cody Schuffelen TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key
1489*5c591343SA. Cody Schuffelen TPM2B_DIGEST *digest, // IN: The digest being validated
1490*5c591343SA. Cody Schuffelen TPMT_SIGNATURE *signature // IN: signature
1491*5c591343SA. Cody Schuffelen )
1492*5c591343SA. Cody Schuffelen {
1493*5c591343SA. Cody Schuffelen // NOTE: HandleToObject will either return a pointer to a loaded object or
1494*5c591343SA. Cody Schuffelen // will assert. It will never return a non-valid value. This makes it save
1495*5c591343SA. Cody Schuffelen // to initialize 'publicArea' with the return value from HandleToObject()
1496*5c591343SA. Cody Schuffelen // without checking it first.
1497*5c591343SA. Cody Schuffelen OBJECT *signObject = HandleToObject(keyHandle);
1498*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea = &signObject->publicArea;
1499*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SCHEME;
1500*5c591343SA. Cody Schuffelen
1501*5c591343SA. Cody Schuffelen // The input unmarshaling should prevent any input signature from being
1502*5c591343SA. Cody Schuffelen // a NULL signature, but just in case
1503*5c591343SA. Cody Schuffelen if(signature->sigAlg == TPM_ALG_NULL)
1504*5c591343SA. Cody Schuffelen return TPM_RC_SIGNATURE;
1505*5c591343SA. Cody Schuffelen
1506*5c591343SA. Cody Schuffelen switch(publicArea->type)
1507*5c591343SA. Cody Schuffelen {
1508*5c591343SA. Cody Schuffelen #if ALG_RSA
1509*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1510*5c591343SA. Cody Schuffelen {
1511*5c591343SA. Cody Schuffelen //
1512*5c591343SA. Cody Schuffelen // Call RSA code to verify signature
1513*5c591343SA. Cody Schuffelen result = CryptRsaValidateSignature(signature, signObject, digest);
1514*5c591343SA. Cody Schuffelen break;
1515*5c591343SA. Cody Schuffelen }
1516*5c591343SA. Cody Schuffelen #endif // ALG_RSA
1517*5c591343SA. Cody Schuffelen
1518*5c591343SA. Cody Schuffelen #if ALG_ECC
1519*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1520*5c591343SA. Cody Schuffelen result = CryptEccValidateSignature(signature, signObject, digest);
1521*5c591343SA. Cody Schuffelen break;
1522*5c591343SA. Cody Schuffelen #endif // ALG_ECC
1523*5c591343SA. Cody Schuffelen
1524*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
1525*5c591343SA. Cody Schuffelen if(signObject->attributes.publicOnly)
1526*5c591343SA. Cody Schuffelen result = TPM_RCS_HANDLE;
1527*5c591343SA. Cody Schuffelen else
1528*5c591343SA. Cody Schuffelen result = CryptHMACVerifySignature(signObject, digest, signature);
1529*5c591343SA. Cody Schuffelen break;
1530*5c591343SA. Cody Schuffelen default:
1531*5c591343SA. Cody Schuffelen break;
1532*5c591343SA. Cody Schuffelen }
1533*5c591343SA. Cody Schuffelen return result;
1534*5c591343SA. Cody Schuffelen }
1535*5c591343SA. Cody Schuffelen
1536*5c591343SA. Cody Schuffelen //*** CryptGetTestResult
1537*5c591343SA. Cody Schuffelen // This function returns the results of a self-test function.
1538*5c591343SA. Cody Schuffelen // Note: the behavior in this function is NOT the correct behavior for a real
1539*5c591343SA. Cody Schuffelen // TPM implementation. An artificial behavior is placed here due to the
1540*5c591343SA. Cody Schuffelen // limitation of a software simulation environment. For the correct behavior,
1541*5c591343SA. Cody Schuffelen // consult the part 3 specification for TPM2_GetTestResult().
1542*5c591343SA. Cody Schuffelen TPM_RC
CryptGetTestResult(TPM2B_MAX_BUFFER * outData)1543*5c591343SA. Cody Schuffelen CryptGetTestResult(
1544*5c591343SA. Cody Schuffelen TPM2B_MAX_BUFFER *outData // OUT: test result data
1545*5c591343SA. Cody Schuffelen )
1546*5c591343SA. Cody Schuffelen {
1547*5c591343SA. Cody Schuffelen outData->t.size = 0;
1548*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1549*5c591343SA. Cody Schuffelen }
1550*5c591343SA. Cody Schuffelen
1551*5c591343SA. Cody Schuffelen //*** CryptValidateKeys()
1552*5c591343SA. Cody Schuffelen // This function is used to verify that the key material of and object is valid.
1553*5c591343SA. Cody Schuffelen // For a 'publicOnly' object, the key is verified for size and, if it is an ECC
1554*5c591343SA. Cody Schuffelen // key, it is verified to be on the specified curve. For a key with a sensitive
1555*5c591343SA. Cody Schuffelen // area, the binding between the public and private parts of the key are verified.
1556*5c591343SA. Cody Schuffelen // If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area
1557*5c591343SA. Cody Schuffelen // is verified but the public portion is not verified, unless the key is an RSA key.
1558*5c591343SA. Cody Schuffelen // For an RSA key, the reason for loading the sensitive area is to use it. The
1559*5c591343SA. Cody Schuffelen // only way to use a private RSA key is to compute the private exponent. To compute
1560*5c591343SA. Cody Schuffelen // the private exponent, the public modulus is used.
1561*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1562*5c591343SA. Cody Schuffelen // TPM_RC_BINDING the public and private parts are not cryptographically
1563*5c591343SA. Cody Schuffelen // bound
1564*5c591343SA. Cody Schuffelen // TPM_RC_HASH cannot have a publicOnly key with nameAlg of TPM_ALG_NULL
1565*5c591343SA. Cody Schuffelen // TPM_RC_KEY the public unique is not valid
1566*5c591343SA. Cody Schuffelen // TPM_RC_KEY_SIZE the private area key is not valid
1567*5c591343SA. Cody Schuffelen // TPM_RC_TYPE the types of the sensitive and private parts do not match
1568*5c591343SA. Cody Schuffelen TPM_RC
CryptValidateKeys(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM_RC blamePublic,TPM_RC blameSensitive)1569*5c591343SA. Cody Schuffelen CryptValidateKeys(
1570*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea,
1571*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive,
1572*5c591343SA. Cody Schuffelen TPM_RC blamePublic,
1573*5c591343SA. Cody Schuffelen TPM_RC blameSensitive
1574*5c591343SA. Cody Schuffelen )
1575*5c591343SA. Cody Schuffelen {
1576*5c591343SA. Cody Schuffelen TPM_RC result;
1577*5c591343SA. Cody Schuffelen UINT16 keySizeInBytes;
1578*5c591343SA. Cody Schuffelen UINT16 digestSize = CryptHashGetDigestSize(publicArea->nameAlg);
1579*5c591343SA. Cody Schuffelen TPMU_PUBLIC_PARMS *params = &publicArea->parameters;
1580*5c591343SA. Cody Schuffelen TPMU_PUBLIC_ID *unique = &publicArea->unique;
1581*5c591343SA. Cody Schuffelen
1582*5c591343SA. Cody Schuffelen if(sensitive != NULL)
1583*5c591343SA. Cody Schuffelen {
1584*5c591343SA. Cody Schuffelen // Make sure that the types of the public and sensitive are compatible
1585*5c591343SA. Cody Schuffelen if(publicArea->type != sensitive->sensitiveType)
1586*5c591343SA. Cody Schuffelen return TPM_RCS_TYPE + blameSensitive;
1587*5c591343SA. Cody Schuffelen // Make sure that the authValue is not bigger than allowed
1588*5c591343SA. Cody Schuffelen // If there is no name algorithm, then the size just needs to be less than
1589*5c591343SA. Cody Schuffelen // the maximum size of the buffer used for authorization. That size check
1590*5c591343SA. Cody Schuffelen // was made during unmarshaling of the sensitive area
1591*5c591343SA. Cody Schuffelen if((sensitive->authValue.t.size) > digestSize && (digestSize > 0))
1592*5c591343SA. Cody Schuffelen return TPM_RCS_SIZE + blameSensitive;
1593*5c591343SA. Cody Schuffelen }
1594*5c591343SA. Cody Schuffelen switch(publicArea->type)
1595*5c591343SA. Cody Schuffelen {
1596*5c591343SA. Cody Schuffelen #if ALG_RSA
1597*5c591343SA. Cody Schuffelen case TPM_ALG_RSA:
1598*5c591343SA. Cody Schuffelen keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits);
1599*5c591343SA. Cody Schuffelen
1600*5c591343SA. Cody Schuffelen // Regardless of whether there is a sensitive area, the public modulus
1601*5c591343SA. Cody Schuffelen // needs to have the correct size. Otherwise, it can't be used for
1602*5c591343SA. Cody Schuffelen // any public key operation nor can it be used to compute the private
1603*5c591343SA. Cody Schuffelen // exponent.
1604*5c591343SA. Cody Schuffelen // NOTE: This implementation only supports key sizes that are multiples
1605*5c591343SA. Cody Schuffelen // of 1024 bits which means that the MSb of the 0th byte will always be
1606*5c591343SA. Cody Schuffelen // SET in any prime and in the public modulus.
1607*5c591343SA. Cody Schuffelen if((unique->rsa.t.size != keySizeInBytes)
1608*5c591343SA. Cody Schuffelen || (unique->rsa.t.buffer[0] < 0x80))
1609*5c591343SA. Cody Schuffelen return TPM_RCS_KEY + blamePublic;
1610*5c591343SA. Cody Schuffelen if(params->rsaDetail.exponent != 0
1611*5c591343SA. Cody Schuffelen && params->rsaDetail.exponent < 7)
1612*5c591343SA. Cody Schuffelen return TPM_RCS_VALUE + blamePublic;
1613*5c591343SA. Cody Schuffelen if(sensitive != NULL)
1614*5c591343SA. Cody Schuffelen {
1615*5c591343SA. Cody Schuffelen // If there is a sensitive area, it has to be the correct size
1616*5c591343SA. Cody Schuffelen // including having the correct high order bit SET.
1617*5c591343SA. Cody Schuffelen if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes)
1618*5c591343SA. Cody Schuffelen || (sensitive->sensitive.rsa.t.buffer[0] < 0x80))
1619*5c591343SA. Cody Schuffelen return TPM_RCS_KEY_SIZE + blameSensitive;
1620*5c591343SA. Cody Schuffelen }
1621*5c591343SA. Cody Schuffelen break;
1622*5c591343SA. Cody Schuffelen #endif
1623*5c591343SA. Cody Schuffelen #if ALG_ECC
1624*5c591343SA. Cody Schuffelen case TPM_ALG_ECC:
1625*5c591343SA. Cody Schuffelen {
1626*5c591343SA. Cody Schuffelen TPMI_ECC_CURVE curveId;
1627*5c591343SA. Cody Schuffelen curveId = params->eccDetail.curveID;
1628*5c591343SA. Cody Schuffelen keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId));
1629*5c591343SA. Cody Schuffelen if(sensitive == NULL)
1630*5c591343SA. Cody Schuffelen {
1631*5c591343SA. Cody Schuffelen // Validate the public key size
1632*5c591343SA. Cody Schuffelen if(unique->ecc.x.t.size != keySizeInBytes
1633*5c591343SA. Cody Schuffelen || unique->ecc.y.t.size != keySizeInBytes)
1634*5c591343SA. Cody Schuffelen return TPM_RCS_KEY + blamePublic;
1635*5c591343SA. Cody Schuffelen if(publicArea->nameAlg != TPM_ALG_NULL)
1636*5c591343SA. Cody Schuffelen {
1637*5c591343SA. Cody Schuffelen if(!CryptEccIsPointOnCurve(curveId, &unique->ecc))
1638*5c591343SA. Cody Schuffelen return TPM_RCS_ECC_POINT + blamePublic;
1639*5c591343SA. Cody Schuffelen }
1640*5c591343SA. Cody Schuffelen }
1641*5c591343SA. Cody Schuffelen else
1642*5c591343SA. Cody Schuffelen {
1643*5c591343SA. Cody Schuffelen // If the nameAlg is TPM_ALG_NULL, then only verify that the
1644*5c591343SA. Cody Schuffelen // private part of the key is OK.
1645*5c591343SA. Cody Schuffelen if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc,
1646*5c591343SA. Cody Schuffelen curveId))
1647*5c591343SA. Cody Schuffelen return TPM_RCS_KEY_SIZE;
1648*5c591343SA. Cody Schuffelen if(publicArea->nameAlg != TPM_ALG_NULL)
1649*5c591343SA. Cody Schuffelen {
1650*5c591343SA. Cody Schuffelen // Full key load, verify that the public point belongs to the
1651*5c591343SA. Cody Schuffelen // private key.
1652*5c591343SA. Cody Schuffelen TPMS_ECC_POINT toCompare;
1653*5c591343SA. Cody Schuffelen result = CryptEccPointMultiply(&toCompare, curveId, NULL,
1654*5c591343SA. Cody Schuffelen &sensitive->sensitive.ecc,
1655*5c591343SA. Cody Schuffelen NULL, NULL);
1656*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1657*5c591343SA. Cody Schuffelen return TPM_RCS_BINDING;
1658*5c591343SA. Cody Schuffelen else
1659*5c591343SA. Cody Schuffelen {
1660*5c591343SA. Cody Schuffelen // Make sure that the private key generated the public key.
1661*5c591343SA. Cody Schuffelen // The input values and the values produced by the point
1662*5c591343SA. Cody Schuffelen // multiply may not be the same size so adjust the computed
1663*5c591343SA. Cody Schuffelen // value to match the size of the input value by adding or
1664*5c591343SA. Cody Schuffelen // removing zeros.
1665*5c591343SA. Cody Schuffelen AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size);
1666*5c591343SA. Cody Schuffelen AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size);
1667*5c591343SA. Cody Schuffelen if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b)
1668*5c591343SA. Cody Schuffelen || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b))
1669*5c591343SA. Cody Schuffelen return TPM_RCS_BINDING;
1670*5c591343SA. Cody Schuffelen }
1671*5c591343SA. Cody Schuffelen }
1672*5c591343SA. Cody Schuffelen }
1673*5c591343SA. Cody Schuffelen break;
1674*5c591343SA. Cody Schuffelen }
1675*5c591343SA. Cody Schuffelen #endif
1676*5c591343SA. Cody Schuffelen default:
1677*5c591343SA. Cody Schuffelen // Checks for SYMCIPHER and KEYEDHASH are largely the same
1678*5c591343SA. Cody Schuffelen // If public area has a nameAlg, then validate the public area size
1679*5c591343SA. Cody Schuffelen // and if there is also a sensitive area, validate the binding
1680*5c591343SA. Cody Schuffelen
1681*5c591343SA. Cody Schuffelen // For consistency, if the object is public-only just make sure that
1682*5c591343SA. Cody Schuffelen // the unique field is consistent with the name algorithm
1683*5c591343SA. Cody Schuffelen if(sensitive == NULL)
1684*5c591343SA. Cody Schuffelen {
1685*5c591343SA. Cody Schuffelen if(unique->sym.t.size != digestSize)
1686*5c591343SA. Cody Schuffelen return TPM_RCS_KEY + blamePublic;
1687*5c591343SA. Cody Schuffelen }
1688*5c591343SA. Cody Schuffelen else
1689*5c591343SA. Cody Schuffelen {
1690*5c591343SA. Cody Schuffelen // Make sure that the key size in the sensitive area is consistent.
1691*5c591343SA. Cody Schuffelen if(publicArea->type == TPM_ALG_SYMCIPHER)
1692*5c591343SA. Cody Schuffelen {
1693*5c591343SA. Cody Schuffelen result = CryptSymKeyValidate(¶ms->symDetail.sym,
1694*5c591343SA. Cody Schuffelen &sensitive->sensitive.sym);
1695*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1696*5c591343SA. Cody Schuffelen return result + blameSensitive;
1697*5c591343SA. Cody Schuffelen }
1698*5c591343SA. Cody Schuffelen else
1699*5c591343SA. Cody Schuffelen {
1700*5c591343SA. Cody Schuffelen // For a keyed hash object, the key has to be less than the
1701*5c591343SA. Cody Schuffelen // smaller of the block size of the hash used in the scheme or
1702*5c591343SA. Cody Schuffelen // 128 bytes. The worst case value is limited by the
1703*5c591343SA. Cody Schuffelen // unmarshaling code so the only thing left to be checked is
1704*5c591343SA. Cody Schuffelen // that it does not exceed the block size of the hash.
1705*5c591343SA. Cody Schuffelen // by the hash algorithm of the scheme.
1706*5c591343SA. Cody Schuffelen TPMT_KEYEDHASH_SCHEME *scheme;
1707*5c591343SA. Cody Schuffelen UINT16 maxSize;
1708*5c591343SA. Cody Schuffelen scheme = ¶ms->keyedHashDetail.scheme;
1709*5c591343SA. Cody Schuffelen if(scheme->scheme == TPM_ALG_XOR)
1710*5c591343SA. Cody Schuffelen {
1711*5c591343SA. Cody Schuffelen maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg);
1712*5c591343SA. Cody Schuffelen }
1713*5c591343SA. Cody Schuffelen else if(scheme->scheme == TPM_ALG_HMAC)
1714*5c591343SA. Cody Schuffelen {
1715*5c591343SA. Cody Schuffelen maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg);
1716*5c591343SA. Cody Schuffelen }
1717*5c591343SA. Cody Schuffelen else if(scheme->scheme == TPM_ALG_NULL)
1718*5c591343SA. Cody Schuffelen {
1719*5c591343SA. Cody Schuffelen // Not signing or xor so must be a data block
1720*5c591343SA. Cody Schuffelen maxSize = 128;
1721*5c591343SA. Cody Schuffelen }
1722*5c591343SA. Cody Schuffelen else
1723*5c591343SA. Cody Schuffelen return TPM_RCS_SCHEME + blamePublic;
1724*5c591343SA. Cody Schuffelen if(sensitive->sensitive.bits.t.size > maxSize)
1725*5c591343SA. Cody Schuffelen return TPM_RCS_KEY_SIZE + blameSensitive;
1726*5c591343SA. Cody Schuffelen }
1727*5c591343SA. Cody Schuffelen // If there is a nameAlg, check the binding
1728*5c591343SA. Cody Schuffelen if(publicArea->nameAlg != TPM_ALG_NULL)
1729*5c591343SA. Cody Schuffelen {
1730*5c591343SA. Cody Schuffelen TPM2B_DIGEST compare;
1731*5c591343SA. Cody Schuffelen if(sensitive->seedValue.t.size != digestSize)
1732*5c591343SA. Cody Schuffelen return TPM_RCS_KEY_SIZE + blameSensitive;
1733*5c591343SA. Cody Schuffelen
1734*5c591343SA. Cody Schuffelen CryptComputeSymmetricUnique(publicArea, sensitive, &compare);
1735*5c591343SA. Cody Schuffelen if(!MemoryEqual2B(&unique->sym.b, &compare.b))
1736*5c591343SA. Cody Schuffelen return TPM_RC_BINDING;
1737*5c591343SA. Cody Schuffelen }
1738*5c591343SA. Cody Schuffelen }
1739*5c591343SA. Cody Schuffelen break;
1740*5c591343SA. Cody Schuffelen }
1741*5c591343SA. Cody Schuffelen // For a parent, need to check that the seedValue is the correct size for
1742*5c591343SA. Cody Schuffelen // protections. It should be at least half the size of the nameAlg
1743*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
1744*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
1745*5c591343SA. Cody Schuffelen && sensitive != NULL
1746*5c591343SA. Cody Schuffelen && publicArea->nameAlg != TPM_ALG_NULL)
1747*5c591343SA. Cody Schuffelen {
1748*5c591343SA. Cody Schuffelen if((sensitive->seedValue.t.size < (digestSize / 2))
1749*5c591343SA. Cody Schuffelen || (sensitive->seedValue.t.size > digestSize))
1750*5c591343SA. Cody Schuffelen return TPM_RCS_SIZE + blameSensitive;
1751*5c591343SA. Cody Schuffelen }
1752*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1753*5c591343SA. Cody Schuffelen }
1754*5c591343SA. Cody Schuffelen
1755*5c591343SA. Cody Schuffelen //*** CryptSelectMac()
1756*5c591343SA. Cody Schuffelen // This function is used to set the MAC scheme based on the key parameters and
1757*5c591343SA. Cody Schuffelen // the input scheme.
1758*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1759*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME the scheme is not a valid mac scheme
1760*5c591343SA. Cody Schuffelen // TPM_RC_TYPE the input key is not a type that supports a mac
1761*5c591343SA. Cody Schuffelen // TPM_RC_VALUE the input scheme and the key scheme are not compatible
1762*5c591343SA. Cody Schuffelen TPM_RC
CryptSelectMac(TPMT_PUBLIC * publicArea,TPMI_ALG_MAC_SCHEME * inMac)1763*5c591343SA. Cody Schuffelen CryptSelectMac(
1764*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea,
1765*5c591343SA. Cody Schuffelen TPMI_ALG_MAC_SCHEME *inMac
1766*5c591343SA. Cody Schuffelen )
1767*5c591343SA. Cody Schuffelen {
1768*5c591343SA. Cody Schuffelen TPM_ALG_ID macAlg = TPM_ALG_NULL;
1769*5c591343SA. Cody Schuffelen switch(publicArea->type)
1770*5c591343SA. Cody Schuffelen {
1771*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
1772*5c591343SA. Cody Schuffelen {
1773*5c591343SA. Cody Schuffelen // Local value to keep lines from getting too long
1774*5c591343SA. Cody Schuffelen TPMT_KEYEDHASH_SCHEME *scheme;
1775*5c591343SA. Cody Schuffelen scheme = &publicArea->parameters.keyedHashDetail.scheme;
1776*5c591343SA. Cody Schuffelen // Expect that the scheme is either HMAC or NULL
1777*5c591343SA. Cody Schuffelen if(scheme->scheme != TPM_ALG_NULL)
1778*5c591343SA. Cody Schuffelen macAlg = scheme->details.hmac.hashAlg;
1779*5c591343SA. Cody Schuffelen break;
1780*5c591343SA. Cody Schuffelen }
1781*5c591343SA. Cody Schuffelen case TPM_ALG_SYMCIPHER:
1782*5c591343SA. Cody Schuffelen {
1783*5c591343SA. Cody Schuffelen TPMT_SYM_DEF_OBJECT *scheme;
1784*5c591343SA. Cody Schuffelen scheme = &publicArea->parameters.symDetail.sym;
1785*5c591343SA. Cody Schuffelen // Expect that the scheme is either valid symmetric cipher or NULL
1786*5c591343SA. Cody Schuffelen if(scheme->algorithm != TPM_ALG_NULL)
1787*5c591343SA. Cody Schuffelen macAlg = scheme->mode.sym;
1788*5c591343SA. Cody Schuffelen break;
1789*5c591343SA. Cody Schuffelen }
1790*5c591343SA. Cody Schuffelen default:
1791*5c591343SA. Cody Schuffelen return TPM_RCS_TYPE;
1792*5c591343SA. Cody Schuffelen }
1793*5c591343SA. Cody Schuffelen // If the input value is not TPM_ALG_NULL ...
1794*5c591343SA. Cody Schuffelen if(*inMac != TPM_ALG_NULL)
1795*5c591343SA. Cody Schuffelen {
1796*5c591343SA. Cody Schuffelen // ... then either the scheme in the key must be TPM_ALG_NULL or the input
1797*5c591343SA. Cody Schuffelen // value must match
1798*5c591343SA. Cody Schuffelen if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg))
1799*5c591343SA. Cody Schuffelen return TPM_RCS_VALUE;
1800*5c591343SA. Cody Schuffelen }
1801*5c591343SA. Cody Schuffelen else
1802*5c591343SA. Cody Schuffelen {
1803*5c591343SA. Cody Schuffelen // Since the input value is TPM_ALG_NULL, then the key value can't be
1804*5c591343SA. Cody Schuffelen // TPM_ALG_NULL
1805*5c591343SA. Cody Schuffelen if(macAlg == TPM_ALG_NULL)
1806*5c591343SA. Cody Schuffelen return TPM_RCS_VALUE;
1807*5c591343SA. Cody Schuffelen *inMac = macAlg;
1808*5c591343SA. Cody Schuffelen }
1809*5c591343SA. Cody Schuffelen if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
1810*5c591343SA. Cody Schuffelen return TPM_RCS_SCHEME;
1811*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1812*5c591343SA. Cody Schuffelen }
1813*5c591343SA. Cody Schuffelen
1814*5c591343SA. Cody Schuffelen //*** CryptMacIsValidForKey()
1815*5c591343SA. Cody Schuffelen // Check to see if the key type is compatible with the mac type
1816*5c591343SA. Cody Schuffelen BOOL
CryptMacIsValidForKey(TPM_ALG_ID keyType,TPM_ALG_ID macAlg,BOOL flag)1817*5c591343SA. Cody Schuffelen CryptMacIsValidForKey(
1818*5c591343SA. Cody Schuffelen TPM_ALG_ID keyType,
1819*5c591343SA. Cody Schuffelen TPM_ALG_ID macAlg,
1820*5c591343SA. Cody Schuffelen BOOL flag
1821*5c591343SA. Cody Schuffelen )
1822*5c591343SA. Cody Schuffelen {
1823*5c591343SA. Cody Schuffelen switch(keyType)
1824*5c591343SA. Cody Schuffelen {
1825*5c591343SA. Cody Schuffelen case TPM_ALG_KEYEDHASH:
1826*5c591343SA. Cody Schuffelen return CryptHashIsValidAlg(macAlg, flag);
1827*5c591343SA. Cody Schuffelen break;
1828*5c591343SA. Cody Schuffelen case TPM_ALG_SYMCIPHER:
1829*5c591343SA. Cody Schuffelen return CryptSmacIsValidAlg(macAlg, flag);
1830*5c591343SA. Cody Schuffelen break;
1831*5c591343SA. Cody Schuffelen default:
1832*5c591343SA. Cody Schuffelen break;
1833*5c591343SA. Cody Schuffelen }
1834*5c591343SA. Cody Schuffelen return FALSE;
1835*5c591343SA. Cody Schuffelen }
1836*5c591343SA. Cody Schuffelen
1837*5c591343SA. Cody Schuffelen //*** CryptSmacIsValidAlg()
1838*5c591343SA. Cody Schuffelen // This function is used to test if an algorithm is a supported SMAC algorithm. It
1839*5c591343SA. Cody Schuffelen // needs to be updated as new algorithms are added.
1840*5c591343SA. Cody Schuffelen BOOL
CryptSmacIsValidAlg(TPM_ALG_ID alg,BOOL FLAG)1841*5c591343SA. Cody Schuffelen CryptSmacIsValidAlg(
1842*5c591343SA. Cody Schuffelen TPM_ALG_ID alg,
1843*5c591343SA. Cody Schuffelen BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid
1844*5c591343SA. Cody Schuffelen )
1845*5c591343SA. Cody Schuffelen {
1846*5c591343SA. Cody Schuffelen switch (alg)
1847*5c591343SA. Cody Schuffelen {
1848*5c591343SA. Cody Schuffelen #if ALG_CMAC
1849*5c591343SA. Cody Schuffelen case TPM_ALG_CMAC:
1850*5c591343SA. Cody Schuffelen return TRUE;
1851*5c591343SA. Cody Schuffelen break;
1852*5c591343SA. Cody Schuffelen #endif
1853*5c591343SA. Cody Schuffelen case TPM_ALG_NULL:
1854*5c591343SA. Cody Schuffelen return FLAG;
1855*5c591343SA. Cody Schuffelen break;
1856*5c591343SA. Cody Schuffelen default:
1857*5c591343SA. Cody Schuffelen return FALSE;
1858*5c591343SA. Cody Schuffelen }
1859*5c591343SA. Cody Schuffelen }
1860*5c591343SA. Cody Schuffelen
1861*5c591343SA. Cody Schuffelen //*** CryptSymModeIsValid()
1862*5c591343SA. Cody Schuffelen // Function checks to see if an algorithm ID is a valid, symmetric block cipher
1863*5c591343SA. Cody Schuffelen // mode for the TPM. If 'flag' is SET, them TPM_ALG_NULL is a valid mode.
1864*5c591343SA. Cody Schuffelen // not include the modes used for SMAC
1865*5c591343SA. Cody Schuffelen BOOL
CryptSymModeIsValid(TPM_ALG_ID mode,BOOL flag)1866*5c591343SA. Cody Schuffelen CryptSymModeIsValid(
1867*5c591343SA. Cody Schuffelen TPM_ALG_ID mode,
1868*5c591343SA. Cody Schuffelen BOOL flag
1869*5c591343SA. Cody Schuffelen )
1870*5c591343SA. Cody Schuffelen {
1871*5c591343SA. Cody Schuffelen switch(mode)
1872*5c591343SA. Cody Schuffelen {
1873*5c591343SA. Cody Schuffelen #if ALG_CTR
1874*5c591343SA. Cody Schuffelen case TPM_ALG_CTR:
1875*5c591343SA. Cody Schuffelen #endif // ALG_CTR
1876*5c591343SA. Cody Schuffelen #if ALG_OFB
1877*5c591343SA. Cody Schuffelen case TPM_ALG_OFB:
1878*5c591343SA. Cody Schuffelen #endif // ALG_OFB
1879*5c591343SA. Cody Schuffelen #if ALG_CBC
1880*5c591343SA. Cody Schuffelen case TPM_ALG_CBC:
1881*5c591343SA. Cody Schuffelen #endif // ALG_CBC
1882*5c591343SA. Cody Schuffelen #if ALG_CFB
1883*5c591343SA. Cody Schuffelen case TPM_ALG_CFB:
1884*5c591343SA. Cody Schuffelen #endif // ALG_CFB
1885*5c591343SA. Cody Schuffelen #if ALG_ECB
1886*5c591343SA. Cody Schuffelen case TPM_ALG_ECB:
1887*5c591343SA. Cody Schuffelen #endif // ALG_ECB
1888*5c591343SA. Cody Schuffelen return TRUE;
1889*5c591343SA. Cody Schuffelen case TPM_ALG_NULL:
1890*5c591343SA. Cody Schuffelen return flag;
1891*5c591343SA. Cody Schuffelen break;
1892*5c591343SA. Cody Schuffelen default:
1893*5c591343SA. Cody Schuffelen break;
1894*5c591343SA. Cody Schuffelen }
1895*5c591343SA. Cody Schuffelen return FALSE;
1896*5c591343SA. Cody Schuffelen }
1897*5c591343SA. Cody Schuffelen
1898*5c591343SA. Cody Schuffelen
1899*5c591343SA. Cody Schuffelen
1900