• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2037

05 Dec 2025 06:50PM UTC coverage: 77.185% (-0.03%) from 77.213%
#2037

push

travis-ci

web-flow
Merge 73eca8c26 into 4f71e9b45

992 of 1176 new or added lines in 85 files covered. (84.35%)

1748 existing lines in 62 files now uncovered.

36357 of 47104 relevant lines covered (77.18%)

125949.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.3
/src/tpm2/TpmMath_Util.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
//** Introduction
4
// This file contains utility functions to help using the external Math library
5
#include "Tpm.h"
6
#include "TpmMath_Util_fp.h"
7

8
//*** TpmMath_IntFrom2B()
9
// Convert an TPM2B to a Crypt_Int.
10
// If the input value does not exist, or the output does not exist, or the input
11
// will not fit into the output the function returns NULL
12
LIB_EXPORT Crypt_Int* TpmMath_IntFrom2B(Crypt_Int*   value,  // OUT:
53,611✔
13
                                        const TPM2B* a2B     // IN: number to convert
14
)
15
{
16
    if(value != NULL && a2B != NULL)
53,611✔
17
        return ExtMath_IntFromBytes(value, a2B->buffer, a2B->size);
53,077✔
18
    return NULL;
19
}
20

21
//*** TpmMath_IntTo2B()
22
//
23
// Function to convert a Crypt_Int to TPM2B. The TPM2B bytes are
24
// always in big-endian ordering (most significant byte first). If 'size' is
25
// non-zero and less than required by `value` then an error is returned. If
26
// `size` is non-zero and larger than `value`, the result buffer is padded
27
// with zeros. If `size` is zero, then the TPM2B is assumed to be large enough
28
// for the data and a2b->size will be adjusted accordingly.
29
LIB_EXPORT BOOL TpmMath_IntTo2B(
2,212✔
30
    const Crypt_Int* value,  // IN: value to convert
31
    TPM2B*           a2B,    // OUT: buffer for output
32
    NUMBYTES         size    // IN: Size of output buffer - see comments.
33
)
34
{
35
    // Set the output size
36
    if(value && a2B)
2,212✔
37
    {
38
        a2B->size = size;
2,212✔
39
        return ExtMath_IntToBytes(value, a2B->buffer, &a2B->size);
2,212✔
40
    }
41
    return FALSE;
42
}
43

44
//*** TpmMath_GetRandomBits()
45
// This function gets random bits for use in various places.
46
//
47
// One consequence of the generation scheme is that, if the number of bits requested
48
// is not a multiple of 8, then the high-order bits are set to zero. This would come
49
// into play when generating a 521-bit ECC key. A 66-byte (528-bit) value is
50
// generated and the high order 7 bits are masked off (CLEAR).
51
// In this situation, the highest order byte is the first byte (big-endian/TPM2B format)
52
//  Return Type: BOOL
53
//      TRUE(1)         success
54
//      FALSE(0)        failure
55
#if 0                                                                                // libtpms added
56
LIB_EXPORT BOOL TpmMath_GetRandomBits(BYTE* pBuffer, size_t bits, RAND_STATE* rand)
57
{
58
    // buffer is assumed to be large enough for the number of bits rounded up to
59
    // bytes.
60
    NUMBYTES byteCount = (NUMBYTES)BITS_TO_BYTES(bits);
61
    if(DRBG_Generate(rand, pBuffer, byteCount) == byteCount)
62
    {
63
        // now flip the buffer order - this exists only to maintain
64
        // compatibility with existing Known-value tests that expect the
65
        // GetRandomInteger behavior of generating the value in little-endian
66
        // order.
67
        BYTE* pFrom = pBuffer + byteCount - 1;
68
        BYTE* pTo   = pBuffer;
69
        while(pTo < pFrom)
70
        {
71
            BYTE t = *pTo;
72
            *pTo   = *pFrom;
73
            *pFrom = t;
74
            pTo++;
75
            pFrom--;
76
        }
77
        // For a little-endian machine, the conversion is a straight byte
78
        // reversal, done above. For a big-endian machine, we have to put the
79
        // words in big-endian byte order.  COMPATIBILITY NOTE: This code does
80
        // not exactly reproduce the original code, because the original big-num
81
        // code always generated data in units of crypt_word_t sizes.  I.e. you
82
        // couldn't generate just 9 bits for example.  This revised version of
83
        // the function could; and would generate 2 bytes with the first byte
84
        // masked to 1 bit.  In order to avoid running over the buffer when
85
        // swapping crypt_uword_t blocks, this loop intentionally doesn't swap
86
        // the last word if it is smaller than crypt_word_t size (which is the
87
        // same as saying the buffer isn't an integral number of crypt_word_t
88
        // units.) This is okay in this particular case _because_ this whole
89
        // block of swapping code is to maintain compatibilty with existing
90
        // KNOWN ANSWER TESTS, and said existing tests use sizes that this
91
        // assumption is true for.  Any new code with a different size where
92
        // this last partial value isn't swapped will be creating a new KAT, and
93
        // thus any (cryptographically valid) value is still random; swapping
94
        // doesn't make a cryptographic random buffer more or less random, so
95
        // the failure to swap is fine.
96
#if BIG_ENDIAN_TPM
97
        crypt_uword_t* pTemp = (crypt_uword_t*)pBuffer;
98
        for(size_t t = 0; t < (byteCount / sizeof(crypt_uword_t)); t++)
99
            *pTemp = SWAP_CRYPT_WORD(*pTemp);
100
#endif
101
        // if the number of bits % 8 != 0, mask the high order (first) byte to the relevant number of bits
102
        // bits % 8     desired mask   right-shift of 0xFF
103
        //     0           0xFF             0 = (8 - 0) % 8
104
        //     1           0x01             7 = (8 - 1) % 8
105
        //     2           0x03             6 = (8 - 2) % 8
106
        //     ... etc ...
107
        //     7           0x7F             1 = (8 - 7) % 8
108
        int  excessBits = bits % 8;
109
        static const BYTE mask[8] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};        // libtpms changed: fix
110
        pBuffer[0] &= mask[excessBits];                                                        // libtpms changed: fix
111
        return TRUE;
112
    }
113
    return FALSE;
114
}
115
#endif                                                                                        // libtpms added
116

117
//*** TpmMath_GetRandomInteger()
118
// This function gets random bits for use in various places. To make sure that the
119
// number is generated in a portable format, it is created as a TPM2B and then
120
// converted to the internal format.
121
//
122
// One consequence of the generation scheme is that, if the number of bits requested
123
// is not a multiple of 8, then the high-order bits are set to zero. This would come
124
// into play when generating a 521-bit ECC key. A 66-byte (528-bit) value is
125
// generated an the high order 7 bits are masked off (CLEAR).
126
//  Return Type: BOOL
127
//      TRUE(1)         success
128
//      FALSE(0)        failure
129
LIB_EXPORT BOOL TpmMath_GetRandomInteger(Crypt_Int* n, size_t bits, RAND_STATE* rand)
50,223✔
130
{
131
    // Since this could be used for ECC key generation using the extra bits method,
132
    // make sure that the value is large enough
133
    TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8);
50,223✔
134
    TPM2B_LARGEST large;
50,223✔
135
    //
136
    large.b.size = (UINT16)BITS_TO_BYTES(bits);
50,223✔
137
    if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size)
50,223✔
138
    {
139
        if(TpmMath_IntFrom2B(n, &large.b) != NULL)
50,223✔
140
        {
141
            if(ExtMath_MaskBits(n, (crypt_uword_t)bits))
50,223✔
142
                return TRUE;
50,223✔
143
        }
144
    }
145
    return FALSE;
146
}
147

148
//*** BnGenerateRandomInRange()
149
// This function is used to generate a random number r in the range 1 <= r < limit.
150
// The function gets a random number of bits that is the size of limit. There is some
151
// some probability that the returned number is going to be greater than or equal
152
// to the limit. If it is, try again. There is no more than 50% chance that the
153
// next number is also greater, so try again. We keep trying until we get a
154
// value that meets the criteria. Since limit is very often a number with a LOT of
155
// high order ones, this rarely would need a second try.
156
//  Return Type: BOOL
157
//      TRUE(1)         success
158
//      FALSE(0)        failure ('limit' is too small)
159
LIB_EXPORT BOOL TpmMath_GetRandomInRange(
216✔
160
    Crypt_Int* dest, const Crypt_Int* limit, RAND_STATE* rand)
161
{
162
    size_t bits = ExtMath_SizeInBits(limit);
216✔
163
    //
164
    if(bits < 2)
216✔
165
    {
UNCOV
166
        ExtMath_SetWord(dest, 0);
×
UNCOV
167
        return FALSE;
×
168
    }
169
    else
170
    {
171
        while(TpmMath_GetRandomInteger(dest, bits, rand)
297✔
172
              && (ExtMath_IsZero(dest) || (ExtMath_UnsignedCmp(dest, limit) >= 0)))
297✔
173
            ;
174
    }
175
    return !_plat__InFailureMode();
216✔
176
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc