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