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 "ECDH_KeyGen_fp.h"
10 #ifdef TPM_ALG_ECC
11 //
12 //
13 //     Error Returns                     Meaning
14 //
15 //     TPM_RC_KEY                        keyHandle does not reference a non-restricted decryption ECC key
16 //
17 TPM_RC
TPM2_ECDH_KeyGen(ECDH_KeyGen_In * in,ECDH_KeyGen_Out * out)18 TPM2_ECDH_KeyGen(
19    ECDH_KeyGen_In        *in,                 // IN: input parameter list
20    ECDH_KeyGen_Out       *out                 // OUT: output parameter list
21    )
22 {
23    OBJECT                    *eccKey;
24    TPM2B_ECC_PARAMETER        sensitive;
25    TPM_RC                     result;
26 
27 // Input Validation
28 
29    eccKey = ObjectGet(in->keyHandle);
30 
31    // Input key must be a non-restricted, decrypt ECC key
32    if(   eccKey->publicArea.type != TPM_ALG_ECC)
33        return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
34 
35    if(     eccKey->publicArea.objectAttributes.restricted == SET
36       ||   eccKey->publicArea.objectAttributes.decrypt != SET
37      )
38        return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
39 
40 // Command Output
41    do
42    {
43        // Create ephemeral ECC key
44        CryptNewEccKey(eccKey->publicArea.parameters.eccDetail.curveID,
45                       &out->pubPoint.t.point, &sensitive);
46 
47        out->pubPoint.t.size = TPMS_ECC_POINT_Marshal(&out->pubPoint.t.point,
48                               NULL, NULL);
49 
50        // Compute Z
51        result = CryptEccPointMultiply(&out->zPoint.t.point,
52                                   eccKey->publicArea.parameters.eccDetail.curveID,
53                                   &sensitive, &eccKey->publicArea.unique.ecc);
54        // The point in the key is not on the curve. Indicate that the key is bad.
55        if(result == TPM_RC_ECC_POINT)
56            return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
57        // The other possible error is TPM_RC_NO_RESULT indicating that the
58        // multiplication resulted in the point at infinity, so get a new
59        // random key and start over (hardly ever happens).
60    }
61    while(result == TPM_RC_NO_RESULT);
62 
63    if(result == TPM_RC_SUCCESS)
64        // Marshal the values to generate the point.
65        out->zPoint.t.size = TPMS_ECC_POINT_Marshal(&out->zPoint.t.point,
66                                                    NULL, NULL);
67 
68    return result;
69 }
70 #endif
71