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