Coverage Report

Created: 2026-07-16 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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