xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
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