1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "StartAuthSession_fp.h"
10 //
11 //
12 //     Error Returns                     Meaning
13 //
14 //     TPM_RC_ATTRIBUTES                 tpmKey does not reference a decrypt key
15 //     TPM_RC_CONTEXT_GAP                the difference between the most recently created active context and
16 //                                       the oldest active context is at the limits of the TPM
17 //     TPM_RC_HANDLE                     input decrypt key handle only has public portion loaded
18 //     TPM_RC_MODE                       symmetric specifies a block cipher but the mode is not
19 //                                       TPM_ALG_CFB.
20 //     TPM_RC_SESSION_HANDLES            no session handle is available
21 //     TPM_RC_SESSION_MEMORY             no more slots for loading a session
22 //     TPM_RC_SIZE                       nonce less than 16 octets or greater than the size of the digest
23 //                                       produced by authHash
24 //     TPM_RC_VALUE                      secret size does not match decrypt key type; or the recovered secret
25 //                                       is larger than the digest size of the nameAlg of tpmKey; or, for an
26 //                                       RSA decrypt key, if encryptedSecret is greater than the public
27 //                                       exponent of tpmKey.
28 //
29 TPM_RC
TPM2_StartAuthSession(StartAuthSession_In * in,StartAuthSession_Out * out)30 TPM2_StartAuthSession(
31    StartAuthSession_In       *in,                   // IN: input parameter buffer
32    StartAuthSession_Out      *out                   // OUT: output parameter buffer
33    )
34 {
35    TPM_RC                     result = TPM_RC_SUCCESS;
36    OBJECT                    *tpmKey;                // TPM key for decrypt salt
37    SESSION                   *session;               // session internal data
38    TPM2B_DATA                 salt;
39 
40 // Input Validation
41 
42    // Check input nonce size. IT should be at least 16 bytes but not larger
43    // than the digest size of session hash.
44    if(    in->nonceCaller.t.size < 16
45        || in->nonceCaller.t.size > CryptGetHashDigestSize(in->authHash))
46        return TPM_RC_SIZE + RC_StartAuthSession_nonceCaller;
47 
48    // If an decrypt key is passed in, check its validation
49    if(in->tpmKey != TPM_RH_NULL)
50    {
51        // secret size cannot be 0
52        if(in->encryptedSalt.t.size == 0)
53            return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
54 
55        // Get pointer to loaded decrypt key
56        tpmKey = ObjectGet(in->tpmKey);
57 
58        // Decrypting salt requires accessing the private portion of a key.
59        // Therefore, tmpKey can not be a key with only public portion loaded
60        if(tpmKey->attributes.publicOnly)
61            return TPM_RC_HANDLE + RC_StartAuthSession_tpmKey;
62 
63        // HMAC session input handle check.
64          // tpmKey should be a decryption key
65          if(tpmKey->publicArea.objectAttributes.decrypt != SET)
66              return TPM_RC_ATTRIBUTES + RC_StartAuthSession_tpmKey;
67 
68          // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
69          // may be returned at this point
70          result = CryptSecretDecrypt(in->tpmKey, &in->nonceCaller, "SECRET",
71                                      &in->encryptedSalt, &salt);
72          if(result != TPM_RC_SUCCESS)
73              return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
74 
75   }
76   else
77   {
78       // secret size must be 0
79       if(in->encryptedSalt.t.size != 0)
80           return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
81       salt.t.size = 0;
82   }
83   // If the bind handle references a transient object, make sure that the
84   // sensitive area is loaded so that the authValue can be accessed.
85   if(     HandleGetType(in->bind) == TPM_HT_TRANSIENT
86       && ObjectGet(in->bind)->attributes.publicOnly == SET)
87       return TPM_RC_HANDLE + RC_StartAuthSession_bind;
88 
89   // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR)
90   // then the mode must be CFB.
91   if(    in->symmetric.algorithm != TPM_ALG_NULL
92       && in->symmetric.algorithm != TPM_ALG_XOR
93       && in->symmetric.mode.sym != TPM_ALG_CFB)
94       return TPM_RC_MODE + RC_StartAuthSession_symmetric;
95 
96 // Internal Data Update
97 
98   // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES
99   // or TPM_RC_SESSION_MEMORY errors may be returned returned at this point.
100   //
101   // The detailed actions for creating the session context are not shown here
102   // as the details are implementation dependent
103   // SessionCreate sets the output handle
104   result = SessionCreate(in->sessionType, in->authHash,
105                          &in->nonceCaller, &in->symmetric,
106                          in->bind, &salt, &out->sessionHandle);
107 
108   if(result != TPM_RC_SUCCESS)
109       return result;
110 
111 // Command Output
112 
113   // Get session pointer
114   session = SessionGet(out->sessionHandle);
115 
116   // Copy nonceTPM
117   out->nonceTPM = session->nonceTPM;
118 
119    return TPM_RC_SUCCESS;
120 }
121