/* Microsoft Reference Implementation for TPM 2.0 * * The copyright in this software is being made available under the BSD License, * included below. This software may be subject to other third party and * contributor rights, including patent rights, and no such rights are granted * under this license. * * Copyright (c) Microsoft Corporation * * All rights reserved. * * BSD License * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Tpm.h" #include "StartAuthSession_fp.h" #if CC_StartAuthSession // Conditional expansion of this file /*(See part 3 specification) // Start an authorization session */ // Return Type: TPM_RC // TPM_RC_ATTRIBUTES 'tpmKey' does not reference a decrypt key // TPM_RC_CONTEXT_GAP the difference between the most recently created // active context and the oldest active context is at // the limits of the TPM // TPM_RC_HANDLE input decrypt key handle only has public portion // loaded // TPM_RC_MODE 'symmetric' specifies a block cipher but the mode // is not TPM_ALG_CFB. // TPM_RC_SESSION_HANDLES no session handle is available // TPM_RC_SESSION_MEMORY no more slots for loading a session // TPM_RC_SIZE nonce less than 16 octets or greater than the size // of the digest produced by 'authHash' // TPM_RC_VALUE secret size does not match decrypt key type; or the // recovered secret is larger than the digest size of // the nameAlg of 'tpmKey'; or, for an RSA decrypt key, // if 'encryptedSecret' is greater than the // public modulus of 'tpmKey'. TPM_RC TPM2_StartAuthSession( StartAuthSession_In *in, // IN: input parameter buffer StartAuthSession_Out *out // OUT: output parameter buffer ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *tpmKey; // TPM key for decrypt salt TPM2B_DATA salt; // Input Validation // Check input nonce size. IT should be at least 16 bytes but not larger // than the digest size of session hash. if(in->nonceCaller.t.size < 16 || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash)) return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller; // If an decrypt key is passed in, check its validation if(in->tpmKey != TPM_RH_NULL) { // Get pointer to loaded decrypt key tpmKey = HandleToObject(in->tpmKey); // key must be asymmetric with its sensitive area loaded. Since this // command does not require authorization, the presence of the sensitive // area was not already checked as it is with most other commands that // use the sensitive are so check it here if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type)) return TPM_RCS_KEY + RC_StartAuthSession_tpmKey; // secret size cannot be 0 if(in->encryptedSalt.t.size == 0) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; // Decrypting salt requires accessing the private portion of a key. // Therefore, tmpKey can not be a key with only public portion loaded if(tpmKey->attributes.publicOnly) return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey; // HMAC session input handle check. // tpmKey should be a decryption key if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey; // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors // may be returned at this point result = CryptSecretDecrypt(tpmKey, &in->nonceCaller, SECRET_KEY, &in->encryptedSalt, &salt); if(result != TPM_RC_SUCCESS) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; } else { // secret size must be 0 if(in->encryptedSalt.t.size != 0) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; salt.t.size = 0; } switch(HandleGetType(in->bind)) { case TPM_HT_TRANSIENT: { OBJECT *object = HandleToObject(in->bind); // If the bind handle references a transient object, make sure that we // can get to the authorization value. Also, make sure that the object // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then // it might be possible to bind to an object where the authValue is // known. This does not create a real issue in that, if you know the // authorization value, you can actually bind to the object. However, // there is a potential if(object->attributes.publicOnly == SET) return TPM_RCS_HANDLE + RC_StartAuthSession_bind; break; } case TPM_HT_NV_INDEX: // a PIN index can't be a bind object { NV_INDEX *nvIndex = NvGetIndexInfo(in->bind, NULL); if(IsNvPinPassIndex(nvIndex->publicArea.attributes) || IsNvPinFailIndex(nvIndex->publicArea.attributes)) return TPM_RCS_HANDLE + RC_StartAuthSession_bind; break; } default: break; } // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR) // then the mode must be CFB. if(in->symmetric.algorithm != TPM_ALG_NULL && in->symmetric.algorithm != TPM_ALG_XOR && in->symmetric.mode.sym != TPM_ALG_CFB) return TPM_RCS_MODE + RC_StartAuthSession_symmetric; // Internal Data Update and command output // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES // or TPM_RC_SESSION_MEMORY errors may be returned at this point. // // The detailed actions for creating the session context are not shown here // as the details are implementation dependent // SessionCreate sets the output handle and nonceTPM result = SessionCreate(in->sessionType, in->authHash, &in->nonceCaller, &in->symmetric, in->bind, &salt, &out->sessionHandle, &out->nonceTPM); return result; } #endif // CC_StartAuthSession