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 basic conversion functions that will convert TPM2B
37*5c591343SA. Cody Schuffelen // to/from the internal format. The internal format is a bigNum,
38*5c591343SA. Cody Schuffelen //
39*5c591343SA. Cody Schuffelen
40*5c591343SA. Cody Schuffelen //** Includes
41*5c591343SA. Cody Schuffelen
42*5c591343SA. Cody Schuffelen #include "Tpm.h"
43*5c591343SA. Cody Schuffelen
44*5c591343SA. Cody Schuffelen //** Functions
45*5c591343SA. Cody Schuffelen
46*5c591343SA. Cody Schuffelen //*** BnFromBytes()
47*5c591343SA. Cody Schuffelen // This function will convert a big-endian byte array to the internal number
48*5c591343SA. Cody Schuffelen // format. If bn is NULL, then the output is NULL. If bytes is null or the
49*5c591343SA. Cody Schuffelen // required size is 0, then the output is set to zero
50*5c591343SA. Cody Schuffelen LIB_EXPORT bigNum
BnFromBytes(bigNum bn,const BYTE * bytes,NUMBYTES nBytes)51*5c591343SA. Cody Schuffelen BnFromBytes(
52*5c591343SA. Cody Schuffelen bigNum bn,
53*5c591343SA. Cody Schuffelen const BYTE *bytes,
54*5c591343SA. Cody Schuffelen NUMBYTES nBytes
55*5c591343SA. Cody Schuffelen )
56*5c591343SA. Cody Schuffelen {
57*5c591343SA. Cody Schuffelen const BYTE *pFrom; // 'p' points to the least significant bytes of source
58*5c591343SA. Cody Schuffelen BYTE *pTo; // points to least significant bytes of destination
59*5c591343SA. Cody Schuffelen crypt_uword_t size;
60*5c591343SA. Cody Schuffelen //
61*5c591343SA. Cody Schuffelen
62*5c591343SA. Cody Schuffelen size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0;
63*5c591343SA. Cody Schuffelen
64*5c591343SA. Cody Schuffelen // If nothing in, nothing out
65*5c591343SA. Cody Schuffelen if(bn == NULL)
66*5c591343SA. Cody Schuffelen return NULL;
67*5c591343SA. Cody Schuffelen
68*5c591343SA. Cody Schuffelen // make sure things fit
69*5c591343SA. Cody Schuffelen pAssert(BnGetAllocated(bn) >= size);
70*5c591343SA. Cody Schuffelen
71*5c591343SA. Cody Schuffelen if(size > 0)
72*5c591343SA. Cody Schuffelen {
73*5c591343SA. Cody Schuffelen // Clear the topmost word in case it is not filled with data
74*5c591343SA. Cody Schuffelen bn->d[size - 1] = 0;
75*5c591343SA. Cody Schuffelen // Moving the input bytes from the end of the list (LSB) end
76*5c591343SA. Cody Schuffelen pFrom = bytes + nBytes - 1;
77*5c591343SA. Cody Schuffelen // To the LS0 of the LSW of the bigNum.
78*5c591343SA. Cody Schuffelen pTo = (BYTE *)bn->d;
79*5c591343SA. Cody Schuffelen for(; nBytes != 0; nBytes--)
80*5c591343SA. Cody Schuffelen *pTo++ = *pFrom--;
81*5c591343SA. Cody Schuffelen // For a little-endian machine, the conversion is a straight byte
82*5c591343SA. Cody Schuffelen // reversal. For a big-endian machine, we have to put the words in
83*5c591343SA. Cody Schuffelen // big-endian byte order
84*5c591343SA. Cody Schuffelen #if BIG_ENDIAN_TPM
85*5c591343SA. Cody Schuffelen {
86*5c591343SA. Cody Schuffelen crypt_word_t t;
87*5c591343SA. Cody Schuffelen for(t = (crypt_word_t)size - 1; t >= 0; t--)
88*5c591343SA. Cody Schuffelen bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]);
89*5c591343SA. Cody Schuffelen }
90*5c591343SA. Cody Schuffelen #endif
91*5c591343SA. Cody Schuffelen }
92*5c591343SA. Cody Schuffelen BnSetTop(bn, size);
93*5c591343SA. Cody Schuffelen return bn;
94*5c591343SA. Cody Schuffelen }
95*5c591343SA. Cody Schuffelen
96*5c591343SA. Cody Schuffelen //*** BnFrom2B()
97*5c591343SA. Cody Schuffelen // Convert an TPM2B to a BIG_NUM.
98*5c591343SA. Cody Schuffelen // If the input value does not exist, or the output does not exist, or the input
99*5c591343SA. Cody Schuffelen // will not fit into the output the function returns NULL
100*5c591343SA. Cody Schuffelen LIB_EXPORT bigNum
BnFrom2B(bigNum bn,const TPM2B * a2B)101*5c591343SA. Cody Schuffelen BnFrom2B(
102*5c591343SA. Cody Schuffelen bigNum bn, // OUT:
103*5c591343SA. Cody Schuffelen const TPM2B *a2B // IN: number to convert
104*5c591343SA. Cody Schuffelen )
105*5c591343SA. Cody Schuffelen {
106*5c591343SA. Cody Schuffelen if(a2B != NULL)
107*5c591343SA. Cody Schuffelen return BnFromBytes(bn, a2B->buffer, a2B->size);
108*5c591343SA. Cody Schuffelen // Make sure that the number has an initialized value rather than whatever
109*5c591343SA. Cody Schuffelen // was there before
110*5c591343SA. Cody Schuffelen BnSetTop(bn, 0); // Function accepts NULL
111*5c591343SA. Cody Schuffelen return NULL;
112*5c591343SA. Cody Schuffelen }
113*5c591343SA. Cody Schuffelen
114*5c591343SA. Cody Schuffelen //*** BnFromHex()
115*5c591343SA. Cody Schuffelen // Convert a hex string into a bigNum. This is primarily used in debugging.
116*5c591343SA. Cody Schuffelen LIB_EXPORT bigNum
BnFromHex(bigNum bn,const char * hex)117*5c591343SA. Cody Schuffelen BnFromHex(
118*5c591343SA. Cody Schuffelen bigNum bn, // OUT:
119*5c591343SA. Cody Schuffelen const char *hex // IN:
120*5c591343SA. Cody Schuffelen )
121*5c591343SA. Cody Schuffelen {
122*5c591343SA. Cody Schuffelen #define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) \
123*5c591343SA. Cody Schuffelen : ((a) > 'A') ? ('A' - 10) : '0'))
124*5c591343SA. Cody Schuffelen unsigned i;
125*5c591343SA. Cody Schuffelen unsigned wordCount;
126*5c591343SA. Cody Schuffelen const char *p;
127*5c591343SA. Cody Schuffelen BYTE *d = (BYTE *)&(bn->d[0]);
128*5c591343SA. Cody Schuffelen //
129*5c591343SA. Cody Schuffelen pAssert(bn && hex);
130*5c591343SA. Cody Schuffelen i = (unsigned)strlen(hex);
131*5c591343SA. Cody Schuffelen wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2);
132*5c591343SA. Cody Schuffelen if((i == 0) || (wordCount >= BnGetAllocated(bn)))
133*5c591343SA. Cody Schuffelen BnSetWord(bn, 0);
134*5c591343SA. Cody Schuffelen else
135*5c591343SA. Cody Schuffelen {
136*5c591343SA. Cody Schuffelen bn->d[wordCount - 1] = 0;
137*5c591343SA. Cody Schuffelen p = hex + i - 1;
138*5c591343SA. Cody Schuffelen for(;i > 1; i -= 2)
139*5c591343SA. Cody Schuffelen {
140*5c591343SA. Cody Schuffelen BYTE a;
141*5c591343SA. Cody Schuffelen a = FromHex(*p);
142*5c591343SA. Cody Schuffelen p--;
143*5c591343SA. Cody Schuffelen *d++ = a + (FromHex(*p) << 4);
144*5c591343SA. Cody Schuffelen p--;
145*5c591343SA. Cody Schuffelen }
146*5c591343SA. Cody Schuffelen if(i == 1)
147*5c591343SA. Cody Schuffelen *d = FromHex(*p);
148*5c591343SA. Cody Schuffelen }
149*5c591343SA. Cody Schuffelen #if !BIG_ENDIAN_TPM
150*5c591343SA. Cody Schuffelen for(i = 0; i < wordCount; i++)
151*5c591343SA. Cody Schuffelen bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]);
152*5c591343SA. Cody Schuffelen #endif // BIG_ENDIAN_TPM
153*5c591343SA. Cody Schuffelen BnSetTop(bn, wordCount);
154*5c591343SA. Cody Schuffelen return bn;
155*5c591343SA. Cody Schuffelen }
156*5c591343SA. Cody Schuffelen
157*5c591343SA. Cody Schuffelen //*** BnToBytes()
158*5c591343SA. Cody Schuffelen // This function converts a BIG_NUM to a byte array. It converts the bigNum to a
159*5c591343SA. Cody Schuffelen // big-endian byte string and sets 'size' to the normalized value. If 'size' is an
160*5c591343SA. Cody Schuffelen // input 0, then the receiving buffer is guaranteed to be large enough for the result
161*5c591343SA. Cody Schuffelen // and the size will be set to the size required for bigNum (leading zeros
162*5c591343SA. Cody Schuffelen // suppressed).
163*5c591343SA. Cody Schuffelen //
164*5c591343SA. Cody Schuffelen // The conversion for a little-endian machine simply requires that all significant
165*5c591343SA. Cody Schuffelen // bytes of the bigNum be reversed. For a big-endian machine, rather than
166*5c591343SA. Cody Schuffelen // unpack each word individually, the bigNum is converted to little-endian words,
167*5c591343SA. Cody Schuffelen // copied, and then converted back to big-endian.
168*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
BnToBytes(bigConst bn,BYTE * buffer,NUMBYTES * size)169*5c591343SA. Cody Schuffelen BnToBytes(
170*5c591343SA. Cody Schuffelen bigConst bn,
171*5c591343SA. Cody Schuffelen BYTE *buffer,
172*5c591343SA. Cody Schuffelen NUMBYTES *size // This the number of bytes that are
173*5c591343SA. Cody Schuffelen // available in the buffer. The result
174*5c591343SA. Cody Schuffelen // should be this big.
175*5c591343SA. Cody Schuffelen )
176*5c591343SA. Cody Schuffelen {
177*5c591343SA. Cody Schuffelen crypt_uword_t requiredSize;
178*5c591343SA. Cody Schuffelen BYTE *pFrom;
179*5c591343SA. Cody Schuffelen BYTE *pTo;
180*5c591343SA. Cody Schuffelen crypt_uword_t count;
181*5c591343SA. Cody Schuffelen //
182*5c591343SA. Cody Schuffelen // validate inputs
183*5c591343SA. Cody Schuffelen pAssert(bn && buffer && size);
184*5c591343SA. Cody Schuffelen
185*5c591343SA. Cody Schuffelen requiredSize = (BnSizeInBits(bn) + 7) / 8;
186*5c591343SA. Cody Schuffelen if(requiredSize == 0)
187*5c591343SA. Cody Schuffelen {
188*5c591343SA. Cody Schuffelen // If the input value is 0, return a byte of zero
189*5c591343SA. Cody Schuffelen *size = 1;
190*5c591343SA. Cody Schuffelen *buffer = 0;
191*5c591343SA. Cody Schuffelen }
192*5c591343SA. Cody Schuffelen else
193*5c591343SA. Cody Schuffelen {
194*5c591343SA. Cody Schuffelen #if BIG_ENDIAN_TPM
195*5c591343SA. Cody Schuffelen // Copy the constant input value into a modifiable value
196*5c591343SA. Cody Schuffelen BN_VAR(bnL, LARGEST_NUMBER_BITS * 2);
197*5c591343SA. Cody Schuffelen BnCopy(bnL, bn);
198*5c591343SA. Cody Schuffelen // byte swap the words in the local value to make them little-endian
199*5c591343SA. Cody Schuffelen for(count = 0; count < bnL->size; count++)
200*5c591343SA. Cody Schuffelen bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]);
201*5c591343SA. Cody Schuffelen bn = (bigConst)bnL;
202*5c591343SA. Cody Schuffelen #endif
203*5c591343SA. Cody Schuffelen if(*size == 0)
204*5c591343SA. Cody Schuffelen *size = (NUMBYTES)requiredSize;
205*5c591343SA. Cody Schuffelen pAssert(requiredSize <= *size);
206*5c591343SA. Cody Schuffelen // Byte swap the number (not words but the whole value)
207*5c591343SA. Cody Schuffelen count = *size;
208*5c591343SA. Cody Schuffelen // Start from the least significant word and offset to the most significant
209*5c591343SA. Cody Schuffelen // byte which is in some high word
210*5c591343SA. Cody Schuffelen pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1;
211*5c591343SA. Cody Schuffelen pTo = buffer;
212*5c591343SA. Cody Schuffelen
213*5c591343SA. Cody Schuffelen // If the number of output bytes is larger than the number bytes required
214*5c591343SA. Cody Schuffelen // for the input number, pad with zeros
215*5c591343SA. Cody Schuffelen for(count = *size; count > requiredSize; count--)
216*5c591343SA. Cody Schuffelen *pTo++ = 0;
217*5c591343SA. Cody Schuffelen // Move the most significant byte at the end of the BigNum to the next most
218*5c591343SA. Cody Schuffelen // significant byte position of the 2B and repeat for all significant bytes.
219*5c591343SA. Cody Schuffelen for(; requiredSize > 0; requiredSize--)
220*5c591343SA. Cody Schuffelen *pTo++ = *pFrom--;
221*5c591343SA. Cody Schuffelen }
222*5c591343SA. Cody Schuffelen return TRUE;
223*5c591343SA. Cody Schuffelen }
224*5c591343SA. Cody Schuffelen
225*5c591343SA. Cody Schuffelen //*** BnTo2B()
226*5c591343SA. Cody Schuffelen // Function to convert a BIG_NUM to TPM2B.
227*5c591343SA. Cody Schuffelen // The TPM2B size is set to the requested 'size' which may require padding.
228*5c591343SA. Cody Schuffelen // If 'size' is non-zero and less than required by the value in 'bn' then an error
229*5c591343SA. Cody Schuffelen // is returned. If 'size' is zero, then the TPM2B is assumed to be large enough
230*5c591343SA. Cody Schuffelen // for the data and a2b->size will be adjusted accordingly.
231*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
BnTo2B(bigConst bn,TPM2B * a2B,NUMBYTES size)232*5c591343SA. Cody Schuffelen BnTo2B(
233*5c591343SA. Cody Schuffelen bigConst bn, // IN:
234*5c591343SA. Cody Schuffelen TPM2B *a2B, // OUT:
235*5c591343SA. Cody Schuffelen NUMBYTES size // IN: the desired size
236*5c591343SA. Cody Schuffelen )
237*5c591343SA. Cody Schuffelen {
238*5c591343SA. Cody Schuffelen // Set the output size
239*5c591343SA. Cody Schuffelen if(bn && a2B)
240*5c591343SA. Cody Schuffelen {
241*5c591343SA. Cody Schuffelen a2B->size = size;
242*5c591343SA. Cody Schuffelen return BnToBytes(bn, a2B->buffer, &a2B->size);
243*5c591343SA. Cody Schuffelen }
244*5c591343SA. Cody Schuffelen return FALSE;
245*5c591343SA. Cody Schuffelen }
246*5c591343SA. Cody Schuffelen
247*5c591343SA. Cody Schuffelen #if ALG_ECC
248*5c591343SA. Cody Schuffelen
249*5c591343SA. Cody Schuffelen //*** BnPointFrom2B()
250*5c591343SA. Cody Schuffelen // Function to create a BIG_POINT structure from a 2B point.
251*5c591343SA. Cody Schuffelen // A point is going to be two ECC values in the same buffer. The values are going
252*5c591343SA. Cody Schuffelen // to be the size of the modulus. They are in modular form.
253*5c591343SA. Cody Schuffelen LIB_EXPORT bn_point_t *
BnPointFrom2B(bigPoint ecP,TPMS_ECC_POINT * p)254*5c591343SA. Cody Schuffelen BnPointFrom2B(
255*5c591343SA. Cody Schuffelen bigPoint ecP, // OUT: the preallocated point structure
256*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *p // IN: the number to convert
257*5c591343SA. Cody Schuffelen )
258*5c591343SA. Cody Schuffelen {
259*5c591343SA. Cody Schuffelen if(p == NULL)
260*5c591343SA. Cody Schuffelen return NULL;
261*5c591343SA. Cody Schuffelen
262*5c591343SA. Cody Schuffelen if(NULL != ecP)
263*5c591343SA. Cody Schuffelen {
264*5c591343SA. Cody Schuffelen BnFrom2B(ecP->x, &p->x.b);
265*5c591343SA. Cody Schuffelen BnFrom2B(ecP->y, &p->y.b);
266*5c591343SA. Cody Schuffelen BnSetWord(ecP->z, 1);
267*5c591343SA. Cody Schuffelen }
268*5c591343SA. Cody Schuffelen return ecP;
269*5c591343SA. Cody Schuffelen }
270*5c591343SA. Cody Schuffelen
271*5c591343SA. Cody Schuffelen //*** BnPointTo2B()
272*5c591343SA. Cody Schuffelen // This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT
273*5c591343SA. Cody Schuffelen // contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters
274*5c591343SA. Cody Schuffelen // is dependent on the maximum EC key size used in an implementation.
275*5c591343SA. Cody Schuffelen // The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B
276*5c591343SA. Cody Schuffelen // values, each as large as a MAX_ECC_PARAMETER_BYTES
277*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
BnPointTo2B(TPMS_ECC_POINT * p,bigPoint ecP,bigCurve E)278*5c591343SA. Cody Schuffelen BnPointTo2B(
279*5c591343SA. Cody Schuffelen TPMS_ECC_POINT *p, // OUT: the converted 2B structure
280*5c591343SA. Cody Schuffelen bigPoint ecP, // IN: the values to be converted
281*5c591343SA. Cody Schuffelen bigCurve E // IN: curve descriptor for the point
282*5c591343SA. Cody Schuffelen )
283*5c591343SA. Cody Schuffelen {
284*5c591343SA. Cody Schuffelen UINT16 size;
285*5c591343SA. Cody Schuffelen //
286*5c591343SA. Cody Schuffelen pAssert(p && ecP && E);
287*5c591343SA. Cody Schuffelen pAssert(BnEqualWord(ecP->z, 1));
288*5c591343SA. Cody Schuffelen // BnMsb is the bit number of the MSB. This is one less than the number of bits
289*5c591343SA. Cody Schuffelen size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E))));
290*5c591343SA. Cody Schuffelen BnTo2B(ecP->x, &p->x.b, size);
291*5c591343SA. Cody Schuffelen BnTo2B(ecP->y, &p->y.b, size);
292*5c591343SA. Cody Schuffelen return TRUE;
293*5c591343SA. Cody Schuffelen }
294*5c591343SA. Cody Schuffelen
295*5c591343SA. Cody Schuffelen #endif // ALG_ECC