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 "ZGen_2Phase_fp.h"
37
38 #if CC_ZGen_2Phase // Conditional expansion of this file
39
40 // This command uses the TPM to recover one or two Z values in a two phase key
41 // exchange protocol
42 // Return Type: TPM_RC
43 // TPM_RC_ATTRIBUTES key referenced by 'keyA' is restricted or
44 // not a decrypt key
45 // TPM_RC_ECC_POINT 'inQsB' or 'inQeB' is not on the curve of
46 // the key reference by 'keyA'
47 // TPM_RC_KEY key referenced by 'keyA' is not an ECC key
48 // TPM_RC_SCHEME the scheme of the key referenced by 'keyA'
49 // is not TPM_ALG_NULL, TPM_ALG_ECDH,
50 // TPM_ALG_ECMQV or TPM_ALG_SM2
51 TPM_RC
TPM2_ZGen_2Phase(ZGen_2Phase_In * in,ZGen_2Phase_Out * out)52 TPM2_ZGen_2Phase(
53 ZGen_2Phase_In *in, // IN: input parameter list
54 ZGen_2Phase_Out *out // OUT: output parameter list
55 )
56 {
57 TPM_RC result;
58 OBJECT *eccKey;
59 TPM2B_ECC_PARAMETER r;
60 TPM_ALG_ID scheme;
61
62 // Input Validation
63
64 eccKey = HandleToObject(in->keyA);
65
66 // keyA must be an ECC key
67 if(eccKey->publicArea.type != TPM_ALG_ECC)
68 return TPM_RCS_KEY + RC_ZGen_2Phase_keyA;
69
70 // keyA must not be restricted and must be a decrypt key
71 if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
72 || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
73 return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA;
74
75 // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise
76 // the input scheme must be the same as the scheme of keyA
77 scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme;
78 if(scheme != TPM_ALG_NULL)
79 {
80 if(scheme != in->inScheme)
81 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
82 }
83 else
84 scheme = in->inScheme;
85 if(scheme == TPM_ALG_NULL)
86 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
87
88 // Input points must be on the curve of keyA
89 if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
90 &in->inQsB.point))
91 return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB;
92
93 if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
94 &in->inQeB.point))
95 return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB;
96
97 if(!CryptGenerateR(&r, &in->counter,
98 eccKey->publicArea.parameters.eccDetail.curveID,
99 NULL))
100 return TPM_RCS_VALUE + RC_ZGen_2Phase_counter;
101
102 // Command Output
103
104 result =
105 CryptEcc2PhaseKeyExchange(&out->outZ1.point,
106 &out->outZ2.point,
107 eccKey->publicArea.parameters.eccDetail.curveID,
108 scheme,
109 &eccKey->sensitive.sensitive.ecc,
110 &r,
111 &in->inQsB.point,
112 &in->inQeB.point);
113 if(result == TPM_RC_SCHEME)
114 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
115
116 if(result == TPM_RC_SUCCESS)
117 CryptEndCommit(in->counter);
118
119 return result;
120 }
121 #endif // CC_ZGen_2Phase