/src/ibmswtpm2/src/BnConvert.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* conversion functions that will convert TPM2B to/from internal format */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: BnConvert.c 1311 2018-08-23 21:39:29Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 10.2.2 BnConvert.c */ |
63 | | /* 10.2.2.1 Introduction */ |
64 | | /* This file contains the basic conversion functions that will convert TPM2B to/from the internal |
65 | | format. The internal format is a bigNum, */ |
66 | | /* 10.2.2.2 Includes */ |
67 | | #include "Tpm.h" |
68 | | /* 10.2.2.3 Functions */ |
69 | | /* 10.2.2.3.1 BnFromBytes() */ |
70 | | /* This function will convert a big-endian byte array to the internal number format. If bn is NULL, |
71 | | then the output is NULL. If bytes is null or the required size is 0, then the output is set to |
72 | | zero */ |
73 | | LIB_EXPORT bigNum |
74 | | BnFromBytes( |
75 | | bigNum bn, |
76 | | const BYTE *bytes, |
77 | | NUMBYTES nBytes |
78 | | ) |
79 | 0 | { |
80 | 0 | const BYTE *pFrom; // 'p' points to the least significant bytes of source |
81 | 0 | BYTE *pTo; // points to least significant bytes of destination |
82 | 0 | crypt_uword_t size; |
83 | | // |
84 | 0 | size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0; |
85 | | // If nothing in, nothing out |
86 | 0 | if(bn == NULL) |
87 | 0 | return NULL; |
88 | | // make sure things fit |
89 | 0 | pAssert(BnGetAllocated(bn) >= size); |
90 | 0 | if(size > 0) |
91 | 0 | { |
92 | | // Clear the topmost word in case it is not filled with data |
93 | 0 | bn->d[size - 1] = 0; |
94 | | // Moving the input bytes from the end of the list (LSB) end |
95 | 0 | pFrom = bytes + nBytes - 1; |
96 | | // To the LS0 of the LSW of the bigNum. |
97 | 0 | pTo = (BYTE *)bn->d; |
98 | 0 | for(; nBytes != 0; nBytes--) |
99 | 0 | *pTo++ = *pFrom--; |
100 | | // For a little-endian machine, the conversion is a straight byte |
101 | | // reversal. For a big-endian machine, we have to put the words in |
102 | | // big-endian byte order |
103 | | #if BIG_ENDIAN_TPM |
104 | | { |
105 | | crypt_word_t t; |
106 | | for(t = (crypt_word_t)size - 1; t >= 0; t--) |
107 | | bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]); |
108 | | } |
109 | | #endif |
110 | 0 | } |
111 | 0 | BnSetTop(bn, size); |
112 | 0 | return bn; |
113 | 0 | } |
114 | | /* 10.2.2.3.2 BnFrom2B() */ |
115 | | /* Convert an TPM2B to a BIG_NUM. If the input value does not exist, or the output does not exist, |
116 | | or the input will not fit into the output the function returns NULL */ |
117 | | LIB_EXPORT bigNum |
118 | | BnFrom2B( |
119 | | bigNum bn, // OUT: |
120 | | const TPM2B *a2B // IN: number to convert |
121 | | ) |
122 | 0 | { |
123 | 0 | if(a2B != NULL) |
124 | 0 | return BnFromBytes(bn, a2B->buffer, a2B->size); |
125 | | // Make sure that the number has an initialized value rather than whatever |
126 | | // was there before |
127 | 0 | BnSetTop(bn, 0); // Function accepts NULL |
128 | 0 | return NULL; |
129 | 0 | } |
130 | | /* 10.2.2.3.3 BnFromHex() */ |
131 | | /* Convert a hex string into a bigNum. This is primarily used in debugging. */ |
132 | | LIB_EXPORT bigNum |
133 | | BnFromHex( |
134 | | bigNum bn, // OUT: |
135 | | const char *hex // IN: |
136 | | ) |
137 | 0 | { |
138 | 0 | #define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) \ |
139 | 0 | : ((a) > 'A') ? ('A' - 10) : '0')) |
140 | 0 | unsigned i; |
141 | 0 | unsigned wordCount; |
142 | 0 | const char *p; |
143 | 0 | BYTE *d = (BYTE *)&(bn->d[0]); |
144 | | // |
145 | 0 | pAssert(bn && hex); |
146 | 0 | i = strlen(hex); |
147 | 0 | wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2); |
148 | 0 | if((i == 0) || (wordCount >= BnGetAllocated(bn))) |
149 | 0 | BnSetWord(bn, 0); |
150 | 0 | else |
151 | 0 | { |
152 | 0 | bn->d[wordCount - 1] = 0; |
153 | 0 | p = hex + i - 1; |
154 | 0 | for(;i > 1; i -= 2) |
155 | 0 | { |
156 | 0 | BYTE a; |
157 | 0 | a = FromHex(*p); |
158 | 0 | p--; |
159 | 0 | *d++ = a + (FromHex(*p) << 4); |
160 | 0 | p--; |
161 | 0 | } |
162 | 0 | if(i == 1) |
163 | 0 | *d = FromHex(*p); |
164 | 0 | } |
165 | 0 | #if !BIG_ENDIAN_TPM |
166 | 0 | for(i = 0; i < wordCount; i++) |
167 | 0 | bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]); |
168 | 0 | #endif // BIG_ENDIAN_TPM |
169 | 0 | BnSetTop(bn, wordCount); |
170 | 0 | return bn; |
171 | 0 | } |
172 | | /* 10.2.2.3.4 BnToBytes() */ |
173 | | /* This function converts a BIG_NUM to a byte array. It converts the bigNum to a big-endian byte |
174 | | string and sets size to the normalized value. If size is an input 0, then the receiving buffer is |
175 | | guaranteed to be large enough for the result and the size will be set to the size required for |
176 | | bigNum (leading zeros suppressed). */ |
177 | | /* The conversion for a little-endian machine simply requires that all significant bytes of the |
178 | | bigNum be reversed. For a big-endian machine, rather than unpack each word individually, |
179 | | the bigNum is converted to little-endian words, copied, and then converted back to big-endian. */ |
180 | | LIB_EXPORT BOOL |
181 | | BnToBytes( |
182 | | bigConst bn, |
183 | | BYTE *buffer, |
184 | | NUMBYTES *size // This the number of bytes that are |
185 | | // available in the buffer. The result |
186 | | // should be this big. |
187 | | ) |
188 | 0 | { |
189 | 0 | crypt_uword_t requiredSize; |
190 | 0 | BYTE *pFrom; |
191 | 0 | BYTE *pTo; |
192 | 0 | crypt_uword_t count; |
193 | | // |
194 | | // validate inputs |
195 | 0 | pAssert(bn && buffer && size); |
196 | 0 | requiredSize = (BnSizeInBits(bn) + 7) / 8; |
197 | 0 | if(requiredSize == 0) |
198 | 0 | { |
199 | | // If the input value is 0, return a byte of zero |
200 | 0 | *size = 1; |
201 | 0 | *buffer = 0; |
202 | 0 | } |
203 | 0 | else |
204 | 0 | { |
205 | | #if BIG_ENDIAN_TPM |
206 | | // Copy the constant input value into a modifiable value |
207 | | BN_VAR(bnL, LARGEST_NUMBER_BITS * 2); |
208 | | BnCopy(bnL, bn); |
209 | | // byte swap the words in the local value to make them little-endian |
210 | | for(count = 0; count < bnL->size; count++) |
211 | | bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]); |
212 | | bn = (bigConst)bnL; |
213 | | #endif |
214 | 0 | if(*size == 0) |
215 | 0 | *size = (NUMBYTES)requiredSize; |
216 | 0 | pAssert(requiredSize <= *size); |
217 | | // Byte swap the number (not words but the whole value) |
218 | 0 | count = *size; |
219 | | // Start from the least significant word and offset to the most significant |
220 | | // byte which is in some high word |
221 | 0 | pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1; |
222 | 0 | pTo = buffer; |
223 | | // If the number of output bytes is larger than the number bytes required |
224 | | // for the input number, pad with zeros |
225 | 0 | for(count = *size; count > requiredSize; count--) |
226 | 0 | *pTo++ = 0; |
227 | | // Move the most significant byte at the end of the BigNum to the next most |
228 | | // significant byte position of the 2B and repeat for all significant bytes. |
229 | 0 | for(; requiredSize > 0; requiredSize--) |
230 | 0 | *pTo++ = *pFrom--; |
231 | 0 | } |
232 | 0 | return TRUE; |
233 | 0 | } |
234 | | /* 10.2.2.3.5 BnTo2B() */ |
235 | | /* Function to convert a BIG_NUM to TPM2B. The TPM2B size is set to the requested size which may |
236 | | require padding. If size is non-zero and less than required by the value in bn then an error is |
237 | | returned. If size is zero, then the TPM2B is assumed to be large enough for the data and |
238 | | a2b->size will be adjusted accordingly. */ |
239 | | LIB_EXPORT BOOL |
240 | | BnTo2B( |
241 | | bigConst bn, // IN: |
242 | | TPM2B *a2B, // OUT: |
243 | | NUMBYTES size // IN: the desired size |
244 | | ) |
245 | 0 | { |
246 | | // Set the output size |
247 | 0 | if(bn && a2B) |
248 | 0 | { |
249 | 0 | a2B->size = size; |
250 | 0 | return BnToBytes(bn, a2B->buffer, &a2B->size); |
251 | 0 | } |
252 | 0 | return FALSE; |
253 | 0 | } |
254 | | #if ALG_ECC |
255 | | /* 10.2.2.3.6 BnPointFrom2B() */ |
256 | | /* Function to create a BIG_POINT structure from a 2B point. A point is going to be two ECC values |
257 | | in the same buffer. The values are going to be the size of the modulus. They are in modular |
258 | | form. */ |
259 | | LIB_EXPORT bn_point_t * |
260 | | BnPointFrom2B( |
261 | | bigPoint ecP, // OUT: the preallocated point structure |
262 | | TPMS_ECC_POINT *p // IN: the number to convert |
263 | | ) |
264 | 0 | { |
265 | 0 | if(p == NULL) |
266 | 0 | return NULL; |
267 | 0 | if(NULL != ecP) |
268 | 0 | { |
269 | 0 | BnFrom2B(ecP->x, &p->x.b); |
270 | 0 | BnFrom2B(ecP->y, &p->y.b); |
271 | 0 | BnSetWord(ecP->z, 1); |
272 | 0 | } |
273 | 0 | return ecP; |
274 | 0 | } |
275 | | /* 10.2.2.3.7 BnPointTo2B() */ |
276 | | /* This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT contains two |
277 | | TPM2B_ECC_PARAMETER values. The maximum size of the parameters is dependent on the maximum EC key |
278 | | size used in an implementation. The presumption is that the TPMS_ECC_POINT is large enough to |
279 | | hold 2 TPM2B values, each as large as a MAX_ECC_PARAMETER_BYTES */ |
280 | | LIB_EXPORT BOOL |
281 | | BnPointTo2B( |
282 | | TPMS_ECC_POINT *p, // OUT: the converted 2B structure |
283 | | bigPoint ecP, // IN: the values to be converted |
284 | | bigCurve E // IN: curve descriptor for the point |
285 | | ) |
286 | 0 | { |
287 | 0 | UINT16 size; |
288 | | // |
289 | 0 | pAssert(p && ecP && E); |
290 | 0 | pAssert(BnEqualWord(ecP->z, 1)); |
291 | | // BnMsb is the bit number of the MSB. This is one less than the number of bits |
292 | 0 | size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E)))); |
293 | 0 | BnTo2B(ecP->x, &p->x.b, size); |
294 | 0 | BnTo2B(ecP->y, &p->y.b, size); |
295 | 0 | return TRUE; |
296 | 0 | } |
297 | | #endif // TPM_ALG_ECC |