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