1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen // This file contains the functions that are used for the two-phase, ECC,
37*5c591343SA. Cody Schuffelen // key-exchange protocols
38*5c591343SA. Cody Schuffelen
39*5c591343SA. Cody Schuffelen
40*5c591343SA. Cody Schuffelen #include "Tpm.h"
41*5c591343SA. Cody Schuffelen
42*5c591343SA. Cody Schuffelen #if CC_ZGen_2Phase == YES
43*5c591343SA. Cody Schuffelen
44*5c591343SA. Cody Schuffelen //** Functions
45*5c591343SA. Cody Schuffelen
46*5c591343SA. Cody Schuffelen #if ALG_ECMQV
47*5c591343SA. Cody Schuffelen
48*5c591343SA. Cody Schuffelen //*** avf1()
49*5c591343SA. Cody Schuffelen // This function does the associated value computation required by MQV key
50*5c591343SA. Cody Schuffelen // exchange.
51*5c591343SA. Cody Schuffelen // Process:
52*5c591343SA. Cody Schuffelen // 1. Convert 'xQ' to an integer 'xqi' using the convention specified in Appendix C.3.
53*5c591343SA. Cody Schuffelen // 2. Calculate
54*5c591343SA. Cody Schuffelen // xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)).
55*5c591343SA. Cody Schuffelen // 3. Calculate the associate value function
56*5c591343SA. Cody Schuffelen // avf(Q) = xqm + 2ceil(f / 2)
57*5c591343SA. Cody Schuffelen // Always returns TRUE(1).
58*5c591343SA. Cody Schuffelen static BOOL
avf1(bigNum bnX,bigNum bnN)59*5c591343SA. Cody Schuffelen avf1(
60*5c591343SA. Cody Schuffelen bigNum bnX, // IN/OUT: the reduced value
61*5c591343SA. Cody Schuffelen bigNum bnN // IN: the order of the curve
62*5c591343SA. Cody Schuffelen )
63*5c591343SA. Cody Schuffelen {
64*5c591343SA. Cody Schuffelen // compute f = 2^(ceil(ceil(log2(n)) / 2))
65*5c591343SA. Cody Schuffelen int f = (BnSizeInBits(bnN) + 1) / 2;
66*5c591343SA. Cody Schuffelen // x' = 2^f + (x mod 2^f)
67*5c591343SA. Cody Schuffelen BnMaskBits(bnX, f); // This is mod 2*2^f but it doesn't matter because
68*5c591343SA. Cody Schuffelen // the next operation will SET the extra bit anyway
69*5c591343SA. Cody Schuffelen BnSetBit(bnX, f);
70*5c591343SA. Cody Schuffelen return TRUE;
71*5c591343SA. Cody Schuffelen }
72*5c591343SA. Cody Schuffelen
73*5c591343SA. Cody Schuffelen //*** C_2_2_MQV()
74*5c591343SA. Cody Schuffelen // This function performs the key exchange defined in SP800-56A
75*5c591343SA. Cody Schuffelen // 6.1.1.4 Full MQV, C(2, 2, ECC MQV).
76*5c591343SA. Cody Schuffelen //
77*5c591343SA. Cody Schuffelen // CAUTION: Implementation of this function may require use of essential claims in
78*5c591343SA. Cody Schuffelen // patents not owned by TCG members.
79*5c591343SA. Cody Schuffelen //
80*5c591343SA. Cody Schuffelen // Points 'QsB' and 'QeB' are required to be on the curve of 'inQsA'. The function
81*5c591343SA. Cody Schuffelen // will fail, possibly catastrophically, if this is not the case.
82*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
83*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT the value for dsA does not give a valid point on the
84*5c591343SA. Cody Schuffelen // curve
85*5c591343SA. Cody Schuffelen static TPM_RC
C_2_2_MQV(TPMS_ECC_POINT * outZ,TPM_ECC_CURVE curveId,TPM2B_ECC_PARAMETER * dsA,TPM2B_ECC_PARAMETER * deA,TPMS_ECC_POINT * QsB,TPMS_ECC_POINT * QeB)86*5c591343SA. Cody Schuffelen C_2_2_MQV(
87*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZ, // OUT: the computed point
88*5c591343SA. Cody Schuffelen TPM_ECC_CURVE curveId, // IN: the curve for the computations
89*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
90*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
91*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QsB, // IN: static public party B key
92*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
93*5c591343SA. Cody Schuffelen )
94*5c591343SA. Cody Schuffelen {
95*5c591343SA. Cody Schuffelen CURVE_INITIALIZED(E, curveId);
96*5c591343SA. Cody Schuffelen const ECC_CURVE_DATA *C;
97*5c591343SA. Cody Schuffelen POINT(pQeA);
98*5c591343SA. Cody Schuffelen POINT_INITIALIZED(pQeB, QeB);
99*5c591343SA. Cody Schuffelen POINT_INITIALIZED(pQsB, QsB);
100*5c591343SA. Cody Schuffelen ECC_NUM(bnTa);
101*5c591343SA. Cody Schuffelen ECC_INITIALIZED(bnDeA, deA);
102*5c591343SA. Cody Schuffelen ECC_INITIALIZED(bnDsA, dsA);
103*5c591343SA. Cody Schuffelen ECC_NUM(bnN);
104*5c591343SA. Cody Schuffelen ECC_NUM(bnXeB);
105*5c591343SA. Cody Schuffelen TPM_RC retVal;
106*5c591343SA. Cody Schuffelen //
107*5c591343SA. Cody Schuffelen // Parameter checks
108*5c591343SA. Cody Schuffelen if(E == NULL)
109*5c591343SA. Cody Schuffelen ERROR_RETURN(TPM_RC_VALUE);
110*5c591343SA. Cody Schuffelen pAssert(outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL
111*5c591343SA. Cody Schuffelen && dsA != NULL);
112*5c591343SA. Cody Schuffelen C = AccessCurveData(E);
113*5c591343SA. Cody Schuffelen // Process:
114*5c591343SA. Cody Schuffelen // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
115*5c591343SA. Cody Schuffelen // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
116*5c591343SA. Cody Schuffelen // 3. If P = O, output an error indicator.
117*5c591343SA. Cody Schuffelen // 4. Z=xP, where xP is the x-coordinate of P.
118*5c591343SA. Cody Schuffelen
119*5c591343SA. Cody Schuffelen // Compute the public ephemeral key pQeA = [de,A]G
120*5c591343SA. Cody Schuffelen if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E))
121*5c591343SA. Cody Schuffelen != TPM_RC_SUCCESS)
122*5c591343SA. Cody Schuffelen goto Exit;
123*5c591343SA. Cody Schuffelen
124*5c591343SA. Cody Schuffelen // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
125*5c591343SA. Cody Schuffelen // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
126*5c591343SA. Cody Schuffelen // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n
127*5c591343SA. Cody Schuffelen // Ta = avf(XeA);
128*5c591343SA. Cody Schuffelen BnCopy(bnTa, pQeA->x);
129*5c591343SA. Cody Schuffelen avf1(bnTa, bnN);
130*5c591343SA. Cody Schuffelen // do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
131*5c591343SA. Cody Schuffelen BnModMult(bnTa, bnDsA, bnTa, bnN);
132*5c591343SA. Cody Schuffelen // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
133*5c591343SA. Cody Schuffelen BnAdd(bnTa, bnTa, bnDeA);
134*5c591343SA. Cody Schuffelen BnMod(bnTa, bnN);
135*5c591343SA. Cody Schuffelen
136*5c591343SA. Cody Schuffelen // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
137*5c591343SA. Cody Schuffelen // Put this in because almost every case of h is == 1 so skip the call when
138*5c591343SA. Cody Schuffelen // not necessary.
139*5c591343SA. Cody Schuffelen if(!BnEqualWord(CurveGetCofactor(C), 1))
140*5c591343SA. Cody Schuffelen // Cofactor is not 1 so compute Ta := Ta * h mod n
141*5c591343SA. Cody Schuffelen BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C));
142*5c591343SA. Cody Schuffelen
143*5c591343SA. Cody Schuffelen // Now that 'tA' is (h * 'tA' mod n)
144*5c591343SA. Cody Schuffelen // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
145*5c591343SA. Cody Schuffelen
146*5c591343SA. Cody Schuffelen // first, compute XeB = avf(XeB)
147*5c591343SA. Cody Schuffelen avf1(bnXeB, bnN);
148*5c591343SA. Cody Schuffelen
149*5c591343SA. Cody Schuffelen // QsB := [XeB]QsB
150*5c591343SA. Cody Schuffelen BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E);
151*5c591343SA. Cody Schuffelen BnEccAdd(pQeB, pQeB, pQsB, E);
152*5c591343SA. Cody Schuffelen
153*5c591343SA. Cody Schuffelen // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
154*5c591343SA. Cody Schuffelen // If the result is not the point at infinity, return QeB
155*5c591343SA. Cody Schuffelen BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E);
156*5c591343SA. Cody Schuffelen if(BnEqualZero(pQeB->z))
157*5c591343SA. Cody Schuffelen ERROR_RETURN(TPM_RC_NO_RESULT);
158*5c591343SA. Cody Schuffelen // Convert BIGNUM E to TPM2B E
159*5c591343SA. Cody Schuffelen BnPointTo2B(outZ, pQeB, E);
160*5c591343SA. Cody Schuffelen
161*5c591343SA. Cody Schuffelen Exit:
162*5c591343SA. Cody Schuffelen CURVE_FREE(E);
163*5c591343SA. Cody Schuffelen return retVal;
164*5c591343SA. Cody Schuffelen }
165*5c591343SA. Cody Schuffelen
166*5c591343SA. Cody Schuffelen #endif // ALG_ECMQV
167*5c591343SA. Cody Schuffelen
168*5c591343SA. Cody Schuffelen //*** C_2_2_ECDH()
169*5c591343SA. Cody Schuffelen // This function performs the two phase key exchange defined in SP800-56A,
170*5c591343SA. Cody Schuffelen // 6.1.1.2 Full Unified Model, C(2, 2, ECC CDH).
171*5c591343SA. Cody Schuffelen //
172*5c591343SA. Cody Schuffelen static TPM_RC
C_2_2_ECDH(TPMS_ECC_POINT * outZs,TPMS_ECC_POINT * outZe,TPM_ECC_CURVE curveId,TPM2B_ECC_PARAMETER * dsA,TPM2B_ECC_PARAMETER * deA,TPMS_ECC_POINT * QsB,TPMS_ECC_POINT * QeB)173*5c591343SA. Cody Schuffelen C_2_2_ECDH(
174*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZs, // OUT: Zs
175*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZe, // OUT: Ze
176*5c591343SA. Cody Schuffelen TPM_ECC_CURVE curveId, // IN: the curve for the computations
177*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
178*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
179*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QsB, // IN: static public party B key
180*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
181*5c591343SA. Cody Schuffelen )
182*5c591343SA. Cody Schuffelen {
183*5c591343SA. Cody Schuffelen CURVE_INITIALIZED(E, curveId);
184*5c591343SA. Cody Schuffelen ECC_INITIALIZED(bnAs, dsA);
185*5c591343SA. Cody Schuffelen ECC_INITIALIZED(bnAe, deA);
186*5c591343SA. Cody Schuffelen POINT_INITIALIZED(ecBs, QsB);
187*5c591343SA. Cody Schuffelen POINT_INITIALIZED(ecBe, QeB);
188*5c591343SA. Cody Schuffelen POINT(ecZ);
189*5c591343SA. Cody Schuffelen TPM_RC retVal;
190*5c591343SA. Cody Schuffelen //
191*5c591343SA. Cody Schuffelen // Parameter checks
192*5c591343SA. Cody Schuffelen if(E == NULL)
193*5c591343SA. Cody Schuffelen ERROR_RETURN(TPM_RC_CURVE);
194*5c591343SA. Cody Schuffelen pAssert(outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL
195*5c591343SA. Cody Schuffelen && QeB != NULL);
196*5c591343SA. Cody Schuffelen
197*5c591343SA. Cody Schuffelen // Do the point multiply for the Zs value ([dsA]QsB)
198*5c591343SA. Cody Schuffelen retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E);
199*5c591343SA. Cody Schuffelen if(retVal == TPM_RC_SUCCESS)
200*5c591343SA. Cody Schuffelen {
201*5c591343SA. Cody Schuffelen // Convert the Zs value.
202*5c591343SA. Cody Schuffelen BnPointTo2B(outZs, ecZ, E);
203*5c591343SA. Cody Schuffelen // Do the point multiply for the Ze value ([deA]QeB)
204*5c591343SA. Cody Schuffelen retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E);
205*5c591343SA. Cody Schuffelen if(retVal == TPM_RC_SUCCESS)
206*5c591343SA. Cody Schuffelen BnPointTo2B(outZe, ecZ, E);
207*5c591343SA. Cody Schuffelen }
208*5c591343SA. Cody Schuffelen Exit:
209*5c591343SA. Cody Schuffelen CURVE_FREE(E);
210*5c591343SA. Cody Schuffelen return retVal;
211*5c591343SA. Cody Schuffelen }
212*5c591343SA. Cody Schuffelen
213*5c591343SA. Cody Schuffelen //*** CryptEcc2PhaseKeyExchange()
214*5c591343SA. Cody Schuffelen // This function is the dispatch routine for the EC key exchange functions that use
215*5c591343SA. Cody Schuffelen // two ephemeral and two static keys.
216*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
217*5c591343SA. Cody Schuffelen // TPM_RC_SCHEME scheme is not defined
218*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
CryptEcc2PhaseKeyExchange(TPMS_ECC_POINT * outZ1,TPMS_ECC_POINT * outZ2,TPM_ECC_CURVE curveId,TPM_ALG_ID scheme,TPM2B_ECC_PARAMETER * dsA,TPM2B_ECC_PARAMETER * deA,TPMS_ECC_POINT * QsB,TPMS_ECC_POINT * QeB)219*5c591343SA. Cody Schuffelen CryptEcc2PhaseKeyExchange(
220*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZ1, // OUT: a computed point
221*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZ2, // OUT: and optional second point
222*5c591343SA. Cody Schuffelen TPM_ECC_CURVE curveId, // IN: the curve for the computations
223*5c591343SA. Cody Schuffelen TPM_ALG_ID scheme, // IN: the key exchange scheme
224*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
225*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
226*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QsB, // IN: static public party B key
227*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
228*5c591343SA. Cody Schuffelen )
229*5c591343SA. Cody Schuffelen {
230*5c591343SA. Cody Schuffelen pAssert(outZ1 != NULL
231*5c591343SA. Cody Schuffelen && dsA != NULL && deA != NULL
232*5c591343SA. Cody Schuffelen && QsB != NULL && QeB != NULL);
233*5c591343SA. Cody Schuffelen
234*5c591343SA. Cody Schuffelen // Initialize the output points so that they are empty until one of the
235*5c591343SA. Cody Schuffelen // functions decides otherwise
236*5c591343SA. Cody Schuffelen outZ1->x.b.size = 0;
237*5c591343SA. Cody Schuffelen outZ1->y.b.size = 0;
238*5c591343SA. Cody Schuffelen if(outZ2 != NULL)
239*5c591343SA. Cody Schuffelen {
240*5c591343SA. Cody Schuffelen outZ2->x.b.size = 0;
241*5c591343SA. Cody Schuffelen outZ2->y.b.size = 0;
242*5c591343SA. Cody Schuffelen }
243*5c591343SA. Cody Schuffelen switch(scheme)
244*5c591343SA. Cody Schuffelen {
245*5c591343SA. Cody Schuffelen case TPM_ALG_ECDH:
246*5c591343SA. Cody Schuffelen return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
247*5c591343SA. Cody Schuffelen break;
248*5c591343SA. Cody Schuffelen #if ALG_ECMQV
249*5c591343SA. Cody Schuffelen case TPM_ALG_ECMQV:
250*5c591343SA. Cody Schuffelen return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
251*5c591343SA. Cody Schuffelen break;
252*5c591343SA. Cody Schuffelen #endif
253*5c591343SA. Cody Schuffelen #if ALG_SM2
254*5c591343SA. Cody Schuffelen case TPM_ALG_SM2:
255*5c591343SA. Cody Schuffelen return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB);
256*5c591343SA. Cody Schuffelen break;
257*5c591343SA. Cody Schuffelen #endif
258*5c591343SA. Cody Schuffelen default:
259*5c591343SA. Cody Schuffelen return TPM_RC_SCHEME;
260*5c591343SA. Cody Schuffelen }
261*5c591343SA. Cody Schuffelen }
262*5c591343SA. Cody Schuffelen
263*5c591343SA. Cody Schuffelen #if ALG_SM2
264*5c591343SA. Cody Schuffelen
265*5c591343SA. Cody Schuffelen //*** ComputeWForSM2()
266*5c591343SA. Cody Schuffelen // Compute the value for w used by SM2
267*5c591343SA. Cody Schuffelen static UINT32
ComputeWForSM2(bigCurve E)268*5c591343SA. Cody Schuffelen ComputeWForSM2(
269*5c591343SA. Cody Schuffelen bigCurve E
270*5c591343SA. Cody Schuffelen )
271*5c591343SA. Cody Schuffelen {
272*5c591343SA. Cody Schuffelen // w := ceil(ceil(log2(n)) / 2) - 1
273*5c591343SA. Cody Schuffelen return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1);
274*5c591343SA. Cody Schuffelen }
275*5c591343SA. Cody Schuffelen
276*5c591343SA. Cody Schuffelen //*** avfSm2()
277*5c591343SA. Cody Schuffelen // This function does the associated value computation required by SM2 key
278*5c591343SA. Cody Schuffelen // exchange. This is different from the avf() in the international standards
279*5c591343SA. Cody Schuffelen // because it returns a value that is half the size of the value returned by the
280*5c591343SA. Cody Schuffelen // standard avf(). For example, if 'n' is 15, 'Ws' ('w' in the standard) is 2 but
281*5c591343SA. Cody Schuffelen // the 'W' here is 1. This means that an input value of 14 (1110b) would return a
282*5c591343SA. Cody Schuffelen // value of 110b with the standard but 10b with the scheme in SM2.
283*5c591343SA. Cody Schuffelen static bigNum
avfSm2(bigNum bn,UINT32 w)284*5c591343SA. Cody Schuffelen avfSm2(
285*5c591343SA. Cody Schuffelen bigNum bn, // IN/OUT: the reduced value
286*5c591343SA. Cody Schuffelen UINT32 w // IN: the value of w
287*5c591343SA. Cody Schuffelen )
288*5c591343SA. Cody Schuffelen {
289*5c591343SA. Cody Schuffelen // a) set w := ceil(ceil(log2(n)) / 2) - 1
290*5c591343SA. Cody Schuffelen // b) set x' := 2^w + ( x & (2^w - 1))
291*5c591343SA. Cody Schuffelen // This is just like the avf for MQV where x' = 2^w + (x mod 2^w)
292*5c591343SA. Cody Schuffelen
293*5c591343SA. Cody Schuffelen BnMaskBits(bn, w); // as with avf1, this is too big by a factor of 2 but
294*5c591343SA. Cody Schuffelen // it doesn't matter because we SET the extra bit
295*5c591343SA. Cody Schuffelen // anyway
296*5c591343SA. Cody Schuffelen BnSetBit(bn, w);
297*5c591343SA. Cody Schuffelen return bn;
298*5c591343SA. Cody Schuffelen }
299*5c591343SA. Cody Schuffelen
300*5c591343SA. Cody Schuffelen //*** SM2KeyExchange()
301*5c591343SA. Cody Schuffelen // This function performs the key exchange defined in SM2.
302*5c591343SA. Cody Schuffelen // The first step is to compute
303*5c591343SA. Cody Schuffelen // 'tA' = ('dsA' + 'deA' avf(Xe,A)) mod 'n'
304*5c591343SA. Cody Schuffelen // Then, compute the 'Z' value from
305*5c591343SA. Cody Schuffelen // 'outZ' = ('h' 'tA' mod 'n') ('QsA' + [avf('QeB.x')]('QeB')).
306*5c591343SA. Cody Schuffelen // The function will compute the ephemeral public key from the ephemeral
307*5c591343SA. Cody Schuffelen // private key.
308*5c591343SA. Cody Schuffelen // All points are required to be on the curve of 'inQsA'. The function will fail
309*5c591343SA. Cody Schuffelen // catastrophically if this is not the case
310*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
311*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT the value for dsA does not give a valid point on the
312*5c591343SA. Cody Schuffelen // curve
313*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
SM2KeyExchange(TPMS_ECC_POINT * outZ,TPM_ECC_CURVE curveId,TPM2B_ECC_PARAMETER * dsAIn,TPM2B_ECC_PARAMETER * deAIn,TPMS_ECC_POINT * QsBIn,TPMS_ECC_POINT * QeBIn)314*5c591343SA. Cody Schuffelen SM2KeyExchange(
315*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *outZ, // OUT: the computed point
316*5c591343SA. Cody Schuffelen TPM_ECC_CURVE curveId, // IN: the curve for the computations
317*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key
318*5c591343SA. Cody Schuffelen TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key
319*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QsBIn, // IN: static public party B key
320*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key
321*5c591343SA. Cody Schuffelen )
322*5c591343SA. Cody Schuffelen {
323*5c591343SA. Cody Schuffelen CURVE_INITIALIZED(E, curveId);
324*5c591343SA. Cody Schuffelen const ECC_CURVE_DATA *C;
325*5c591343SA. Cody Schuffelen ECC_INITIALIZED(dsA, dsAIn);
326*5c591343SA. Cody Schuffelen ECC_INITIALIZED(deA, deAIn);
327*5c591343SA. Cody Schuffelen POINT_INITIALIZED(QsB, QsBIn);
328*5c591343SA. Cody Schuffelen POINT_INITIALIZED(QeB, QeBIn);
329*5c591343SA. Cody Schuffelen BN_WORD_INITIALIZED(One, 1);
330*5c591343SA. Cody Schuffelen POINT(QeA);
331*5c591343SA. Cody Schuffelen ECC_NUM(XeB);
332*5c591343SA. Cody Schuffelen POINT(Z);
333*5c591343SA. Cody Schuffelen ECC_NUM(Ta);
334*5c591343SA. Cody Schuffelen UINT32 w;
335*5c591343SA. Cody Schuffelen TPM_RC retVal = TPM_RC_NO_RESULT;
336*5c591343SA. Cody Schuffelen //
337*5c591343SA. Cody Schuffelen // Parameter checks
338*5c591343SA. Cody Schuffelen if(E == NULL)
339*5c591343SA. Cody Schuffelen ERROR_RETURN(TPM_RC_CURVE);
340*5c591343SA. Cody Schuffelen C = AccessCurveData(E);
341*5c591343SA. Cody Schuffelen pAssert(outZ != NULL && dsA != NULL && deA != NULL && QsB != NULL
342*5c591343SA. Cody Schuffelen && QeB != NULL);
343*5c591343SA. Cody Schuffelen
344*5c591343SA. Cody Schuffelen // Compute the value for w
345*5c591343SA. Cody Schuffelen w = ComputeWForSM2(E);
346*5c591343SA. Cody Schuffelen
347*5c591343SA. Cody Schuffelen // Compute the public ephemeral key pQeA = [de,A]G
348*5c591343SA. Cody Schuffelen if(!BnEccModMult(QeA, CurveGetG(C), deA, E))
349*5c591343SA. Cody Schuffelen goto Exit;
350*5c591343SA. Cody Schuffelen
351*5c591343SA. Cody Schuffelen // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
352*5c591343SA. Cody Schuffelen // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n
353*5c591343SA. Cody Schuffelen // Ta = avf(XeA);
354*5c591343SA. Cody Schuffelen // do Ta = de,A * Ta = deA * avf(XeA)
355*5c591343SA. Cody Schuffelen BnMult(Ta, deA, avfSm2(QeA->x, w));
356*5c591343SA. Cody Schuffelen // now Ta = dsA + Ta = dsA + deA * avf(XeA)
357*5c591343SA. Cody Schuffelen BnAdd(Ta, dsA, Ta);
358*5c591343SA. Cody Schuffelen BnMod(Ta, CurveGetOrder(C));
359*5c591343SA. Cody Schuffelen
360*5c591343SA. Cody Schuffelen // outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4)
361*5c591343SA. Cody Schuffelen // Put this in because almost every case of h is == 1 so skip the call when
362*5c591343SA. Cody Schuffelen // not necessary.
363*5c591343SA. Cody Schuffelen if(!BnEqualWord(CurveGetCofactor(C), 1))
364*5c591343SA. Cody Schuffelen // Cofactor is not 1 so compute Ta := Ta * h mod n
365*5c591343SA. Cody Schuffelen BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C));
366*5c591343SA. Cody Schuffelen // Now that 'tA' is (h * 'tA' mod n)
367*5c591343SA. Cody Schuffelen // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)).
368*5c591343SA. Cody Schuffelen BnCopy(XeB, QeB->x);
369*5c591343SA. Cody Schuffelen if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E))
370*5c591343SA. Cody Schuffelen goto Exit;
371*5c591343SA. Cody Schuffelen // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
372*5c591343SA. Cody Schuffelen if(!BnEccModMult(Z, Z, Ta, E))
373*5c591343SA. Cody Schuffelen goto Exit;
374*5c591343SA. Cody Schuffelen // Convert BIGNUM E to TPM2B E
375*5c591343SA. Cody Schuffelen BnPointTo2B(outZ, Z, E);
376*5c591343SA. Cody Schuffelen retVal = TPM_RC_SUCCESS;
377*5c591343SA. Cody Schuffelen Exit:
378*5c591343SA. Cody Schuffelen CURVE_FREE(E);
379*5c591343SA. Cody Schuffelen return retVal;
380*5c591343SA. Cody Schuffelen }
381*5c591343SA. Cody Schuffelen #endif
382*5c591343SA. Cody Schuffelen
383*5c591343SA. Cody Schuffelen #endif // CC_ZGen_2Phase