1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "Tpm.h"
36 #include "StartAuthSession_fp.h"
37
38 #if CC_StartAuthSession // Conditional expansion of this file
39
40 /*(See part 3 specification)
41 // Start an authorization session
42 */
43 // Return Type: TPM_RC
44 // TPM_RC_ATTRIBUTES 'tpmKey' does not reference a decrypt key
45 // TPM_RC_CONTEXT_GAP the difference between the most recently created
46 // active context and the oldest active context is at
47 // the limits of the TPM
48 // TPM_RC_HANDLE input decrypt key handle only has public portion
49 // loaded
50 // TPM_RC_MODE 'symmetric' specifies a block cipher but the mode
51 // is not TPM_ALG_CFB.
52 // TPM_RC_SESSION_HANDLES no session handle is available
53 // TPM_RC_SESSION_MEMORY no more slots for loading a session
54 // TPM_RC_SIZE nonce less than 16 octets or greater than the size
55 // of the digest produced by 'authHash'
56 // TPM_RC_VALUE secret size does not match decrypt key type; or the
57 // recovered secret is larger than the digest size of
58 // the nameAlg of 'tpmKey'; or, for an RSA decrypt key,
59 // if 'encryptedSecret' is greater than the
60 // public modulus of 'tpmKey'.
61 TPM_RC
TPM2_StartAuthSession(StartAuthSession_In * in,StartAuthSession_Out * out)62 TPM2_StartAuthSession(
63 StartAuthSession_In *in, // IN: input parameter buffer
64 StartAuthSession_Out *out // OUT: output parameter buffer
65 )
66 {
67 TPM_RC result = TPM_RC_SUCCESS;
68 OBJECT *tpmKey; // TPM key for decrypt salt
69 TPM2B_DATA salt;
70
71 // Input Validation
72
73 // Check input nonce size. IT should be at least 16 bytes but not larger
74 // than the digest size of session hash.
75 if(in->nonceCaller.t.size < 16
76 || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash))
77 return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller;
78
79 // If an decrypt key is passed in, check its validation
80 if(in->tpmKey != TPM_RH_NULL)
81 {
82 // Get pointer to loaded decrypt key
83 tpmKey = HandleToObject(in->tpmKey);
84
85 // key must be asymmetric with its sensitive area loaded. Since this
86 // command does not require authorization, the presence of the sensitive
87 // area was not already checked as it is with most other commands that
88 // use the sensitive are so check it here
89 if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type))
90 return TPM_RCS_KEY + RC_StartAuthSession_tpmKey;
91 // secret size cannot be 0
92 if(in->encryptedSalt.t.size == 0)
93 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
94 // Decrypting salt requires accessing the private portion of a key.
95 // Therefore, tmpKey can not be a key with only public portion loaded
96 if(tpmKey->attributes.publicOnly)
97 return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey;
98 // HMAC session input handle check.
99 // tpmKey should be a decryption key
100 if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
101 return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey;
102 // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
103 // may be returned at this point
104 result = CryptSecretDecrypt(tpmKey, &in->nonceCaller, SECRET_KEY,
105 &in->encryptedSalt, &salt);
106 if(result != TPM_RC_SUCCESS)
107 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
108 }
109 else
110 {
111 // secret size must be 0
112 if(in->encryptedSalt.t.size != 0)
113 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
114 salt.t.size = 0;
115 }
116 switch(HandleGetType(in->bind))
117 {
118 case TPM_HT_TRANSIENT:
119 {
120 OBJECT *object = HandleToObject(in->bind);
121 // If the bind handle references a transient object, make sure that we
122 // can get to the authorization value. Also, make sure that the object
123 // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then
124 // it might be possible to bind to an object where the authValue is
125 // known. This does not create a real issue in that, if you know the
126 // authorization value, you can actually bind to the object. However,
127 // there is a potential
128 if(object->attributes.publicOnly == SET)
129 return TPM_RCS_HANDLE + RC_StartAuthSession_bind;
130 break;
131 }
132 case TPM_HT_NV_INDEX:
133 // a PIN index can't be a bind object
134 {
135 NV_INDEX *nvIndex = NvGetIndexInfo(in->bind, NULL);
136 if(IsNvPinPassIndex(nvIndex->publicArea.attributes)
137 || IsNvPinFailIndex(nvIndex->publicArea.attributes))
138 return TPM_RCS_HANDLE + RC_StartAuthSession_bind;
139 break;
140 }
141 default:
142 break;
143 }
144 // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR)
145 // then the mode must be CFB.
146 if(in->symmetric.algorithm != TPM_ALG_NULL
147 && in->symmetric.algorithm != TPM_ALG_XOR
148 && in->symmetric.mode.sym != TPM_ALG_CFB)
149 return TPM_RCS_MODE + RC_StartAuthSession_symmetric;
150
151 // Internal Data Update and command output
152
153 // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES
154 // or TPM_RC_SESSION_MEMORY errors may be returned at this point.
155 //
156 // The detailed actions for creating the session context are not shown here
157 // as the details are implementation dependent
158 // SessionCreate sets the output handle and nonceTPM
159 result = SessionCreate(in->sessionType, in->authHash, &in->nonceCaller,
160 &in->symmetric, in->bind, &salt, &out->sessionHandle,
161 &out->nonceTPM);
162 return result;
163 }
164
165 #endif // CC_StartAuthSession