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//
17TPM_RC
18TPM2_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