xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.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 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