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 //** Includes and defines
36*5c591343SA. Cody Schuffelen
37*5c591343SA. Cody Schuffelen #include "Tpm.h"
38*5c591343SA. Cody Schuffelen
39*5c591343SA. Cody Schuffelen #if RSA_KEY_SIEVE
40*5c591343SA. Cody Schuffelen
41*5c591343SA. Cody Schuffelen #include "CryptPrimeSieve_fp.h"
42*5c591343SA. Cody Schuffelen
43*5c591343SA. Cody Schuffelen // This determines the number of bits in the largest sieve field.
44*5c591343SA. Cody Schuffelen #define MAX_FIELD_SIZE 2048
45*5c591343SA. Cody Schuffelen
46*5c591343SA. Cody Schuffelen extern const uint32_t s_LastPrimeInTable;
47*5c591343SA. Cody Schuffelen extern const uint32_t s_PrimeTableSize;
48*5c591343SA. Cody Schuffelen extern const uint32_t s_PrimesInTable;
49*5c591343SA. Cody Schuffelen extern const unsigned char s_PrimeTable[];
50*5c591343SA. Cody Schuffelen
51*5c591343SA. Cody Schuffelen // This table is set of prime markers. Each entry is the prime value
52*5c591343SA. Cody Schuffelen // for the ((n + 1) * 1024) prime. That is, the entry in s_PrimeMarkers[1]
53*5c591343SA. Cody Schuffelen // is the value for the 2,048th prime. This is used in the PrimeSieve
54*5c591343SA. Cody Schuffelen // to adjust the limit for the prime search. When processing smaller
55*5c591343SA. Cody Schuffelen // prime candidates, fewer primes are checked directly before going to
56*5c591343SA. Cody Schuffelen // Miller-Rabin. As the prime grows, it is worth spending more time eliminating
57*5c591343SA. Cody Schuffelen // primes as, a) the density is lower, and b) the cost of Miller-Rabin is
58*5c591343SA. Cody Schuffelen // higher.
59*5c591343SA. Cody Schuffelen const uint32_t s_PrimeMarkersCount = 6;
60*5c591343SA. Cody Schuffelen const uint32_t s_PrimeMarkers[] = {
61*5c591343SA. Cody Schuffelen 8167, 17881, 28183, 38891, 49871, 60961 };
62*5c591343SA. Cody Schuffelen uint32_t primeLimit;
63*5c591343SA. Cody Schuffelen
64*5c591343SA. Cody Schuffelen //** Functions
65*5c591343SA. Cody Schuffelen
66*5c591343SA. Cody Schuffelen //*** RsaAdjustPrimeLimit()
67*5c591343SA. Cody Schuffelen // This used during the sieve process. The iterator for getting the
68*5c591343SA. Cody Schuffelen // next prime (RsaNextPrime()) will return primes until it hits the
69*5c591343SA. Cody Schuffelen // limit (primeLimit) set up by this function. This causes the sieve
70*5c591343SA. Cody Schuffelen // process to stop when an appropriate number of primes have been
71*5c591343SA. Cody Schuffelen // sieved.
72*5c591343SA. Cody Schuffelen LIB_EXPORT void
RsaAdjustPrimeLimit(uint32_t requestedPrimes)73*5c591343SA. Cody Schuffelen RsaAdjustPrimeLimit(
74*5c591343SA. Cody Schuffelen uint32_t requestedPrimes
75*5c591343SA. Cody Schuffelen )
76*5c591343SA. Cody Schuffelen {
77*5c591343SA. Cody Schuffelen if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable)
78*5c591343SA. Cody Schuffelen requestedPrimes = s_PrimesInTable;
79*5c591343SA. Cody Schuffelen requestedPrimes = (requestedPrimes - 1) / 1024;
80*5c591343SA. Cody Schuffelen if(requestedPrimes < s_PrimeMarkersCount)
81*5c591343SA. Cody Schuffelen primeLimit = s_PrimeMarkers[requestedPrimes];
82*5c591343SA. Cody Schuffelen else
83*5c591343SA. Cody Schuffelen primeLimit = s_LastPrimeInTable;
84*5c591343SA. Cody Schuffelen primeLimit >>= 1;
85*5c591343SA. Cody Schuffelen
86*5c591343SA. Cody Schuffelen }
87*5c591343SA. Cody Schuffelen
88*5c591343SA. Cody Schuffelen //*** RsaNextPrime()
89*5c591343SA. Cody Schuffelen // This the iterator used during the sieve process. The input is the
90*5c591343SA. Cody Schuffelen // last prime returned (or any starting point) and the output is the
91*5c591343SA. Cody Schuffelen // next higher prime. The function returns 0 when the primeLimit is
92*5c591343SA. Cody Schuffelen // reached.
93*5c591343SA. Cody Schuffelen LIB_EXPORT uint32_t
RsaNextPrime(uint32_t lastPrime)94*5c591343SA. Cody Schuffelen RsaNextPrime(
95*5c591343SA. Cody Schuffelen uint32_t lastPrime
96*5c591343SA. Cody Schuffelen )
97*5c591343SA. Cody Schuffelen {
98*5c591343SA. Cody Schuffelen if(lastPrime == 0)
99*5c591343SA. Cody Schuffelen return 0;
100*5c591343SA. Cody Schuffelen lastPrime >>= 1;
101*5c591343SA. Cody Schuffelen for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++)
102*5c591343SA. Cody Schuffelen {
103*5c591343SA. Cody Schuffelen if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1)
104*5c591343SA. Cody Schuffelen return ((lastPrime << 1) + 1);
105*5c591343SA. Cody Schuffelen }
106*5c591343SA. Cody Schuffelen return 0;
107*5c591343SA. Cody Schuffelen }
108*5c591343SA. Cody Schuffelen
109*5c591343SA. Cody Schuffelen // This table contains a previously sieved table. It has
110*5c591343SA. Cody Schuffelen // the bits for 3, 5, and 7 removed. Because of the
111*5c591343SA. Cody Schuffelen // factors, it needs to be aligned to 105 and has
112*5c591343SA. Cody Schuffelen // a repeat of 105.
113*5c591343SA. Cody Schuffelen const BYTE seedValues[] = {
114*5c591343SA. Cody Schuffelen 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c,
115*5c591343SA. Cody Schuffelen 0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96,
116*5c591343SA. Cody Schuffelen 0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99,
117*5c591343SA. Cody Schuffelen 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69,
118*5c591343SA. Cody Schuffelen 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6,
119*5c591343SA. Cody Schuffelen 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb,
120*5c591343SA. Cody Schuffelen 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c,
121*5c591343SA. Cody Schuffelen 0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34,
122*5c591343SA. Cody Schuffelen 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b,
123*5c591343SA. Cody Schuffelen 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45,
124*5c591343SA. Cody Schuffelen 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6,
125*5c591343SA. Cody Schuffelen 0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2,
126*5c591343SA. Cody Schuffelen 0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29,
127*5c591343SA. Cody Schuffelen 0xd1};
128*5c591343SA. Cody Schuffelen
129*5c591343SA. Cody Schuffelen #define USE_NIBBLE
130*5c591343SA. Cody Schuffelen
131*5c591343SA. Cody Schuffelen #ifndef USE_NIBBLE
132*5c591343SA. Cody Schuffelen static const BYTE bitsInByte[256] = {
133*5c591343SA. Cody Schuffelen 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
134*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
135*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
136*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
137*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
138*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
139*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
140*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
141*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
142*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
143*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
144*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
145*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
146*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
147*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
148*5c591343SA. Cody Schuffelen 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
149*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
150*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
151*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
152*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
153*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
154*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
155*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
156*5c591343SA. Cody Schuffelen 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
157*5c591343SA. Cody Schuffelen 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
158*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
159*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
160*5c591343SA. Cody Schuffelen 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
161*5c591343SA. Cody Schuffelen 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
162*5c591343SA. Cody Schuffelen 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
163*5c591343SA. Cody Schuffelen 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
164*5c591343SA. Cody Schuffelen 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08
165*5c591343SA. Cody Schuffelen };
166*5c591343SA. Cody Schuffelen #define BitsInByte(x) bitsInByte[(unsigned char)x]
167*5c591343SA. Cody Schuffelen #else
168*5c591343SA. Cody Schuffelen const BYTE bitsInNibble[16] = {
169*5c591343SA. Cody Schuffelen 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
170*5c591343SA. Cody Schuffelen 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04};
171*5c591343SA. Cody Schuffelen #define BitsInByte(x) \
172*5c591343SA. Cody Schuffelen (bitsInNibble[(unsigned char)(x) & 0xf] \
173*5c591343SA. Cody Schuffelen + bitsInNibble[((unsigned char)(x) >> 4) & 0xf])
174*5c591343SA. Cody Schuffelen #endif
175*5c591343SA. Cody Schuffelen
176*5c591343SA. Cody Schuffelen //*** BitsInArry()
177*5c591343SA. Cody Schuffelen // This function counts the number of bits set in an array of bytes.
178*5c591343SA. Cody Schuffelen static int
BitsInArray(const unsigned char * a,unsigned int aSize)179*5c591343SA. Cody Schuffelen BitsInArray(
180*5c591343SA. Cody Schuffelen const unsigned char *a, // IN: A pointer to an array of bytes
181*5c591343SA. Cody Schuffelen unsigned int aSize // IN: the number of bytes to sum
182*5c591343SA. Cody Schuffelen )
183*5c591343SA. Cody Schuffelen {
184*5c591343SA. Cody Schuffelen int j = 0;
185*5c591343SA. Cody Schuffelen for(; aSize; a++, aSize--)
186*5c591343SA. Cody Schuffelen j += BitsInByte(*a);
187*5c591343SA. Cody Schuffelen return j;
188*5c591343SA. Cody Schuffelen }
189*5c591343SA. Cody Schuffelen
190*5c591343SA. Cody Schuffelen //*** FindNthSetBit()
191*5c591343SA. Cody Schuffelen // This function finds the nth SET bit in a bit array. The 'n' parameter is
192*5c591343SA. Cody Schuffelen // between 1 and the number of bits in the array (always a multiple of 8).
193*5c591343SA. Cody Schuffelen // If called when the array does not have n bits set, it will return -1
194*5c591343SA. Cody Schuffelen // Return Type: unsigned int
195*5c591343SA. Cody Schuffelen // <0 no bit is set or no bit with the requested number is set
196*5c591343SA. Cody Schuffelen // >=0 the number of the bit in the array that is the nth set
197*5c591343SA. Cody Schuffelen LIB_EXPORT int
FindNthSetBit(const UINT16 aSize,const BYTE * a,const UINT32 n)198*5c591343SA. Cody Schuffelen FindNthSetBit(
199*5c591343SA. Cody Schuffelen const UINT16 aSize, // IN: the size of the array to check
200*5c591343SA. Cody Schuffelen const BYTE *a, // IN: the array to check
201*5c591343SA. Cody Schuffelen const UINT32 n // IN, the number of the SET bit
202*5c591343SA. Cody Schuffelen )
203*5c591343SA. Cody Schuffelen {
204*5c591343SA. Cody Schuffelen UINT16 i;
205*5c591343SA. Cody Schuffelen int retValue;
206*5c591343SA. Cody Schuffelen UINT32 sum = 0;
207*5c591343SA. Cody Schuffelen BYTE sel;
208*5c591343SA. Cody Schuffelen
209*5c591343SA. Cody Schuffelen //find the bit
210*5c591343SA. Cody Schuffelen for(i = 0; (i < (int)aSize) && (sum < n); i++)
211*5c591343SA. Cody Schuffelen sum += BitsInByte(a[i]);
212*5c591343SA. Cody Schuffelen i--;
213*5c591343SA. Cody Schuffelen // The chosen bit is in the byte that was just accessed
214*5c591343SA. Cody Schuffelen // Compute the offset to the start of that byte
215*5c591343SA. Cody Schuffelen retValue = i * 8 - 1;
216*5c591343SA. Cody Schuffelen sel = a[i];
217*5c591343SA. Cody Schuffelen // Subtract the bits in the last byte added.
218*5c591343SA. Cody Schuffelen sum -= BitsInByte(sel);
219*5c591343SA. Cody Schuffelen // Now process the byte, one bit at a time.
220*5c591343SA. Cody Schuffelen for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1)
221*5c591343SA. Cody Schuffelen sum += (sel & 1) != 0;
222*5c591343SA. Cody Schuffelen return (sum == n) ? retValue : -1;
223*5c591343SA. Cody Schuffelen }
224*5c591343SA. Cody Schuffelen
225*5c591343SA. Cody Schuffelen typedef struct
226*5c591343SA. Cody Schuffelen {
227*5c591343SA. Cody Schuffelen UINT16 prime;
228*5c591343SA. Cody Schuffelen UINT16 count;
229*5c591343SA. Cody Schuffelen } SIEVE_MARKS;
230*5c591343SA. Cody Schuffelen
231*5c591343SA. Cody Schuffelen const SIEVE_MARKS sieveMarks[5] = {
232*5c591343SA. Cody Schuffelen {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}};
233*5c591343SA. Cody Schuffelen
234*5c591343SA. Cody Schuffelen
235*5c591343SA. Cody Schuffelen //*** PrimeSieve()
236*5c591343SA. Cody Schuffelen // This function does a prime sieve over the input 'field' which has as its
237*5c591343SA. Cody Schuffelen // starting address the value in bnN. Since this initializes the Sieve
238*5c591343SA. Cody Schuffelen // using a precomputed field with the bits associated with 3, 5 and 7 already
239*5c591343SA. Cody Schuffelen // turned off, the value of pnN may need to be adjusted by a few counts to allow
240*5c591343SA. Cody Schuffelen // the precomputed field to be used without modification.
241*5c591343SA. Cody Schuffelen //
242*5c591343SA. Cody Schuffelen // To get better performance, one could address the issue of developing the
243*5c591343SA. Cody Schuffelen // composite numbers. When the size of the prime gets large, the time for doing
244*5c591343SA. Cody Schuffelen // the divisions goes up, noticeably. It could be better to develop larger composite
245*5c591343SA. Cody Schuffelen // numbers even if they need to be bigNum's themselves. The object would be to
246*5c591343SA. Cody Schuffelen // reduce the number of times that the large prime is divided into a few large
247*5c591343SA. Cody Schuffelen // divides and then use smaller divides to get to the final 16 bit (or smaller)
248*5c591343SA. Cody Schuffelen // remainders.
249*5c591343SA. Cody Schuffelen LIB_EXPORT UINT32
PrimeSieve(bigNum bnN,UINT32 fieldSize,BYTE * field)250*5c591343SA. Cody Schuffelen PrimeSieve(
251*5c591343SA. Cody Schuffelen bigNum bnN, // IN/OUT: number to sieve
252*5c591343SA. Cody Schuffelen UINT32 fieldSize, // IN: size of the field area in bytes
253*5c591343SA. Cody Schuffelen BYTE *field // IN: field
254*5c591343SA. Cody Schuffelen )
255*5c591343SA. Cody Schuffelen {
256*5c591343SA. Cody Schuffelen UINT32 i;
257*5c591343SA. Cody Schuffelen UINT32 j;
258*5c591343SA. Cody Schuffelen UINT32 fieldBits = fieldSize * 8;
259*5c591343SA. Cody Schuffelen UINT32 r;
260*5c591343SA. Cody Schuffelen BYTE *pField;
261*5c591343SA. Cody Schuffelen INT32 iter;
262*5c591343SA. Cody Schuffelen UINT32 adjust;
263*5c591343SA. Cody Schuffelen UINT32 mark = 0;
264*5c591343SA. Cody Schuffelen UINT32 count = sieveMarks[0].count;
265*5c591343SA. Cody Schuffelen UINT32 stop = sieveMarks[0].prime;
266*5c591343SA. Cody Schuffelen UINT32 composite;
267*5c591343SA. Cody Schuffelen UINT32 pList[8];
268*5c591343SA. Cody Schuffelen UINT32 next;
269*5c591343SA. Cody Schuffelen
270*5c591343SA. Cody Schuffelen pAssert(field != NULL && bnN != NULL);
271*5c591343SA. Cody Schuffelen
272*5c591343SA. Cody Schuffelen // If the remainder is odd, then subtracting the value will give an even number,
273*5c591343SA. Cody Schuffelen // but we want an odd number, so subtract the 105+rem. Otherwise, just subtract
274*5c591343SA. Cody Schuffelen // the even remainder.
275*5c591343SA. Cody Schuffelen adjust = (UINT32)BnModWord(bnN, 105);
276*5c591343SA. Cody Schuffelen if(adjust & 1)
277*5c591343SA. Cody Schuffelen adjust += 105;
278*5c591343SA. Cody Schuffelen
279*5c591343SA. Cody Schuffelen // Adjust the input number so that it points to the first number in a
280*5c591343SA. Cody Schuffelen // aligned field.
281*5c591343SA. Cody Schuffelen BnSubWord(bnN, bnN, adjust);
282*5c591343SA. Cody Schuffelen // pAssert(BnModWord(bnN, 105) == 0);
283*5c591343SA. Cody Schuffelen pField = field;
284*5c591343SA. Cody Schuffelen for(i = fieldSize; i >= sizeof(seedValues);
285*5c591343SA. Cody Schuffelen pField += sizeof(seedValues), i -= sizeof(seedValues))
286*5c591343SA. Cody Schuffelen {
287*5c591343SA. Cody Schuffelen memcpy(pField, seedValues, sizeof(seedValues));
288*5c591343SA. Cody Schuffelen }
289*5c591343SA. Cody Schuffelen if(i != 0)
290*5c591343SA. Cody Schuffelen memcpy(pField, seedValues, i);
291*5c591343SA. Cody Schuffelen
292*5c591343SA. Cody Schuffelen // Cycle through the primes, clearing bits
293*5c591343SA. Cody Schuffelen // Have already done 3, 5, and 7
294*5c591343SA. Cody Schuffelen iter = 7;
295*5c591343SA. Cody Schuffelen
296*5c591343SA. Cody Schuffelen #define NEXT_PRIME(iter) (iter = RsaNextPrime(iter))
297*5c591343SA. Cody Schuffelen // Get the next N primes where N is determined by the mark in the sieveMarks
298*5c591343SA. Cody Schuffelen while((composite = NEXT_PRIME(iter)) != 0)
299*5c591343SA. Cody Schuffelen {
300*5c591343SA. Cody Schuffelen next = 0;
301*5c591343SA. Cody Schuffelen i = count;
302*5c591343SA. Cody Schuffelen pList[i--] = composite;
303*5c591343SA. Cody Schuffelen for(; i > 0; i--)
304*5c591343SA. Cody Schuffelen {
305*5c591343SA. Cody Schuffelen next = NEXT_PRIME(iter);
306*5c591343SA. Cody Schuffelen pList[i] = next;
307*5c591343SA. Cody Schuffelen if(next != 0)
308*5c591343SA. Cody Schuffelen composite *= next;
309*5c591343SA. Cody Schuffelen }
310*5c591343SA. Cody Schuffelen // Get the remainder when dividing the base field address
311*5c591343SA. Cody Schuffelen // by the composite
312*5c591343SA. Cody Schuffelen composite = (UINT32)BnModWord(bnN, composite);
313*5c591343SA. Cody Schuffelen // 'composite' is divisible by the composite components. for each of the
314*5c591343SA. Cody Schuffelen // composite components, divide 'composite'. That remainder (r) is used to
315*5c591343SA. Cody Schuffelen // pick a starting point for clearing the array. The stride is equal to the
316*5c591343SA. Cody Schuffelen // composite component. Note, the field only contains odd numbers. If the
317*5c591343SA. Cody Schuffelen // field were expanded to contain all numbers, then half of the bits would
318*5c591343SA. Cody Schuffelen // have already been cleared. We can save the trouble of clearing them a
319*5c591343SA. Cody Schuffelen // second time by having a stride of 2*next. Or we can take all of the even
320*5c591343SA. Cody Schuffelen // numbers out of the field and use a stride of 'next'
321*5c591343SA. Cody Schuffelen for(i = count; i > 0; i--)
322*5c591343SA. Cody Schuffelen {
323*5c591343SA. Cody Schuffelen next = pList[i];
324*5c591343SA. Cody Schuffelen if(next == 0)
325*5c591343SA. Cody Schuffelen goto done;
326*5c591343SA. Cody Schuffelen r = composite % next;
327*5c591343SA. Cody Schuffelen // these computations deal with the fact that we have picked a field-sized
328*5c591343SA. Cody Schuffelen // range that is aligned to a 105 count boundary. The problem is, this field
329*5c591343SA. Cody Schuffelen // only contains odd numbers. If we take our prime guess and walk through all
330*5c591343SA. Cody Schuffelen // the numbers using that prime as the 'stride', then every other 'stride' is
331*5c591343SA. Cody Schuffelen // going to be an even number. So, we are actually counting by 2 * the stride
332*5c591343SA. Cody Schuffelen // We want the count to start on an odd number at the start of our field. That
333*5c591343SA. Cody Schuffelen // is, we want to assume that we have counted up to the edge of the field by
334*5c591343SA. Cody Schuffelen // the 'stride' and now we are going to start flipping bits in the field as we
335*5c591343SA. Cody Schuffelen // continue to count up by 'stride'. If we take the base of our field and
336*5c591343SA. Cody Schuffelen // divide by the stride, we find out how much we find out how short the last
337*5c591343SA. Cody Schuffelen // count was from reaching the edge of the bit field. Say we get a quotient of
338*5c591343SA. Cody Schuffelen // 3 and remainder of 1. This means that after 3 strides, we are 1 short of
339*5c591343SA. Cody Schuffelen // the start of the field and the next stride will either land within the
340*5c591343SA. Cody Schuffelen // field or step completely over it. The confounding factor is that our field
341*5c591343SA. Cody Schuffelen // only contains odd numbers and our stride is actually 2 * stride. If the
342*5c591343SA. Cody Schuffelen // quoitent is even, then that means that when we add 2 * stride, we are going
343*5c591343SA. Cody Schuffelen // to hit another even number. So, we have to know if we need to back off
344*5c591343SA. Cody Schuffelen // by 1 stride before we start couting by 2 * stride.
345*5c591343SA. Cody Schuffelen // We can tell from the remainder whether we are on an even or odd
346*5c591343SA. Cody Schuffelen // stride when we hit the beginning of the table. If we are on an odd stride
347*5c591343SA. Cody Schuffelen // (r & 1), we would start half a stride in (next - r)/2. If we are on an
348*5c591343SA. Cody Schuffelen // even stride, we need 0.5 strides (next - r/2) because the table only has
349*5c591343SA. Cody Schuffelen // odd numbers. If the remainder happens to be zero, then the start of the
350*5c591343SA. Cody Schuffelen // table is on stride so no adjustment is necessary.
351*5c591343SA. Cody Schuffelen if(r & 1) j = (next - r) / 2;
352*5c591343SA. Cody Schuffelen else if(r == 0) j = 0;
353*5c591343SA. Cody Schuffelen else j = next - (r / 2);
354*5c591343SA. Cody Schuffelen for(; j < fieldBits; j += next)
355*5c591343SA. Cody Schuffelen ClearBit(j, field, fieldSize);
356*5c591343SA. Cody Schuffelen }
357*5c591343SA. Cody Schuffelen if(next >= stop)
358*5c591343SA. Cody Schuffelen {
359*5c591343SA. Cody Schuffelen mark++;
360*5c591343SA. Cody Schuffelen count = sieveMarks[mark].count;
361*5c591343SA. Cody Schuffelen stop = sieveMarks[mark].prime;
362*5c591343SA. Cody Schuffelen }
363*5c591343SA. Cody Schuffelen }
364*5c591343SA. Cody Schuffelen done:
365*5c591343SA. Cody Schuffelen INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]);
366*5c591343SA. Cody Schuffelen i = BitsInArray(field, fieldSize);
367*5c591343SA. Cody Schuffelen INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i);
368*5c591343SA. Cody Schuffelen INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0));
369*5c591343SA. Cody Schuffelen return i;
370*5c591343SA. Cody Schuffelen }
371*5c591343SA. Cody Schuffelen
372*5c591343SA. Cody Schuffelen
373*5c591343SA. Cody Schuffelen
374*5c591343SA. Cody Schuffelen #ifdef SIEVE_DEBUG
375*5c591343SA. Cody Schuffelen static uint32_t fieldSize = 210;
376*5c591343SA. Cody Schuffelen
377*5c591343SA. Cody Schuffelen //***SetFieldSize()
378*5c591343SA. Cody Schuffelen // Function to set the field size used for prime generation. Used for tuning.
379*5c591343SA. Cody Schuffelen LIB_EXPORT uint32_t
SetFieldSize(uint32_t newFieldSize)380*5c591343SA. Cody Schuffelen SetFieldSize(
381*5c591343SA. Cody Schuffelen uint32_t newFieldSize
382*5c591343SA. Cody Schuffelen )
383*5c591343SA. Cody Schuffelen {
384*5c591343SA. Cody Schuffelen if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE)
385*5c591343SA. Cody Schuffelen fieldSize = MAX_FIELD_SIZE;
386*5c591343SA. Cody Schuffelen else
387*5c591343SA. Cody Schuffelen fieldSize = newFieldSize;
388*5c591343SA. Cody Schuffelen return fieldSize;
389*5c591343SA. Cody Schuffelen }
390*5c591343SA. Cody Schuffelen #endif // SIEVE_DEBUG
391*5c591343SA. Cody Schuffelen
392*5c591343SA. Cody Schuffelen //*** PrimeSelectWithSieve()
393*5c591343SA. Cody Schuffelen // This function will sieve the field around the input prime candidate. If the
394*5c591343SA. Cody Schuffelen // sieve field is not empty, one of the one bits in the field is chosen for testing
395*5c591343SA. Cody Schuffelen // with Miller-Rabin. If the value is prime, 'pnP' is updated with this value
396*5c591343SA. Cody Schuffelen // and the function returns success. If this value is not prime, another
397*5c591343SA. Cody Schuffelen // pseudo-random candidate is chosen and tested. This process repeats until
398*5c591343SA. Cody Schuffelen // all values in the field have been checked. If all bits in the field have
399*5c591343SA. Cody Schuffelen // been checked and none is prime, the function returns FALSE and a new random
400*5c591343SA. Cody Schuffelen // value needs to be chosen.
401*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
402*5c591343SA. Cody Schuffelen // TPM_RC_FAILURE TPM in failure mode, probably due to entropy source
403*5c591343SA. Cody Schuffelen // TPM_RC_SUCCESS candidate is probably prime
404*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative
405*5c591343SA. Cody Schuffelen // in the field
406*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
PrimeSelectWithSieve(bigNum candidate,UINT32 e,RAND_STATE * rand)407*5c591343SA. Cody Schuffelen PrimeSelectWithSieve(
408*5c591343SA. Cody Schuffelen bigNum candidate, // IN/OUT: The candidate to filter
409*5c591343SA. Cody Schuffelen UINT32 e, // IN: the exponent
410*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: the random number generator state
411*5c591343SA. Cody Schuffelen )
412*5c591343SA. Cody Schuffelen {
413*5c591343SA. Cody Schuffelen BYTE field[MAX_FIELD_SIZE];
414*5c591343SA. Cody Schuffelen UINT32 first;
415*5c591343SA. Cody Schuffelen UINT32 ones;
416*5c591343SA. Cody Schuffelen INT32 chosen;
417*5c591343SA. Cody Schuffelen BN_PRIME(test);
418*5c591343SA. Cody Schuffelen UINT32 modE;
419*5c591343SA. Cody Schuffelen #ifndef SIEVE_DEBUG
420*5c591343SA. Cody Schuffelen UINT32 fieldSize = MAX_FIELD_SIZE;
421*5c591343SA. Cody Schuffelen #endif
422*5c591343SA. Cody Schuffelen UINT32 primeSize;
423*5c591343SA. Cody Schuffelen //
424*5c591343SA. Cody Schuffelen // Adjust the field size and prime table list to fit the size of the prime
425*5c591343SA. Cody Schuffelen // being tested. This is done to try to optimize the trade-off between the
426*5c591343SA. Cody Schuffelen // dividing done for sieving and the time for Miller-Rabin. When the size
427*5c591343SA. Cody Schuffelen // of the prime is large, the cost of Miller-Rabin is fairly high, as is the
428*5c591343SA. Cody Schuffelen // cost of the sieving. However, the time for Miller-Rabin goes up considerably
429*5c591343SA. Cody Schuffelen // faster than the cost of dividing by a number of primes.
430*5c591343SA. Cody Schuffelen primeSize = BnSizeInBits(candidate);
431*5c591343SA. Cody Schuffelen
432*5c591343SA. Cody Schuffelen if(primeSize <= 512)
433*5c591343SA. Cody Schuffelen {
434*5c591343SA. Cody Schuffelen RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes
435*5c591343SA. Cody Schuffelen }
436*5c591343SA. Cody Schuffelen else if(primeSize <= 1024)
437*5c591343SA. Cody Schuffelen {
438*5c591343SA. Cody Schuffelen RsaAdjustPrimeLimit(4096); // Use just the first 4K primes
439*5c591343SA. Cody Schuffelen }
440*5c591343SA. Cody Schuffelen else
441*5c591343SA. Cody Schuffelen {
442*5c591343SA. Cody Schuffelen RsaAdjustPrimeLimit(0); // Use all available
443*5c591343SA. Cody Schuffelen }
444*5c591343SA. Cody Schuffelen
445*5c591343SA. Cody Schuffelen // Save the low-order word to use as a search generator and make sure that
446*5c591343SA. Cody Schuffelen // it has some interesting range to it
447*5c591343SA. Cody Schuffelen first = (UINT32)(candidate->d[0] | 0x80000000);
448*5c591343SA. Cody Schuffelen
449*5c591343SA. Cody Schuffelen // Sieve the field
450*5c591343SA. Cody Schuffelen ones = PrimeSieve(candidate, fieldSize, field);
451*5c591343SA. Cody Schuffelen pAssert(ones > 0 && ones < (fieldSize * 8));
452*5c591343SA. Cody Schuffelen for(; ones > 0; ones--)
453*5c591343SA. Cody Schuffelen {
454*5c591343SA. Cody Schuffelen // Decide which bit to look at and find its offset
455*5c591343SA. Cody Schuffelen chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1));
456*5c591343SA. Cody Schuffelen
457*5c591343SA. Cody Schuffelen if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8)))
458*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
459*5c591343SA. Cody Schuffelen
460*5c591343SA. Cody Schuffelen // Set this as the trial prime
461*5c591343SA. Cody Schuffelen BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2));
462*5c591343SA. Cody Schuffelen
463*5c591343SA. Cody Schuffelen // The exponent might not have been one of the tested primes so
464*5c591343SA. Cody Schuffelen // make sure that it isn't divisible and make sure that 0 != (p-1) mod e
465*5c591343SA. Cody Schuffelen // Note: This is the same as 1 != p mod e
466*5c591343SA. Cody Schuffelen modE = (UINT32)BnModWord(test, e);
467*5c591343SA. Cody Schuffelen if((modE != 0) && (modE != 1) && MillerRabin(test, rand))
468*5c591343SA. Cody Schuffelen {
469*5c591343SA. Cody Schuffelen BnCopy(candidate, test);
470*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
471*5c591343SA. Cody Schuffelen }
472*5c591343SA. Cody Schuffelen // Clear the bit just tested
473*5c591343SA. Cody Schuffelen ClearBit(chosen, field, fieldSize);
474*5c591343SA. Cody Schuffelen }
475*5c591343SA. Cody Schuffelen // Ran out of bits and couldn't find a prime in this field
476*5c591343SA. Cody Schuffelen INSTRUMENT_INC(noPrimeFields[PrimeIndex]);
477*5c591343SA. Cody Schuffelen return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT);
478*5c591343SA. Cody Schuffelen }
479*5c591343SA. Cody Schuffelen
480*5c591343SA. Cody Schuffelen #if RSA_INSTRUMENT
481*5c591343SA. Cody Schuffelen static char a[256];
482*5c591343SA. Cody Schuffelen
483*5c591343SA. Cody Schuffelen //*** PrintTuple()
484*5c591343SA. Cody Schuffelen char *
PrintTuple(UINT32 * i)485*5c591343SA. Cody Schuffelen PrintTuple(
486*5c591343SA. Cody Schuffelen UINT32 *i
487*5c591343SA. Cody Schuffelen )
488*5c591343SA. Cody Schuffelen {
489*5c591343SA. Cody Schuffelen sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]);
490*5c591343SA. Cody Schuffelen return a;
491*5c591343SA. Cody Schuffelen }
492*5c591343SA. Cody Schuffelen
493*5c591343SA. Cody Schuffelen #define CLEAR_VALUE(x) memset(x, 0, sizeof(x))
494*5c591343SA. Cody Schuffelen
495*5c591343SA. Cody Schuffelen //*** RsaSimulationEnd()
496*5c591343SA. Cody Schuffelen void
RsaSimulationEnd(void)497*5c591343SA. Cody Schuffelen RsaSimulationEnd(
498*5c591343SA. Cody Schuffelen void
499*5c591343SA. Cody Schuffelen )
500*5c591343SA. Cody Schuffelen {
501*5c591343SA. Cody Schuffelen int i;
502*5c591343SA. Cody Schuffelen UINT32 averages[3];
503*5c591343SA. Cody Schuffelen UINT32 nonFirst = 0;
504*5c591343SA. Cody Schuffelen if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0)
505*5c591343SA. Cody Schuffelen {
506*5c591343SA. Cody Schuffelen printf("Primes generated = %s\n", PrintTuple(PrimeCounts));
507*5c591343SA. Cody Schuffelen printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved));
508*5c591343SA. Cody Schuffelen printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields));
509*5c591343SA. Cody Schuffelen printf("Primes checked with Miller-Rabin = %s\n",
510*5c591343SA. Cody Schuffelen PrintTuple(MillerRabinTrials));
511*5c591343SA. Cody Schuffelen for(i = 0; i < 3; i++)
512*5c591343SA. Cody Schuffelen averages[i] = (totalFieldsSieved[i]
513*5c591343SA. Cody Schuffelen != 0 ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i]
514*5c591343SA. Cody Schuffelen : 0);
515*5c591343SA. Cody Schuffelen printf("Average candidates in field %s\n", PrintTuple(averages));
516*5c591343SA. Cody Schuffelen for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0]));
517*5c591343SA. Cody Schuffelen i++)
518*5c591343SA. Cody Schuffelen nonFirst += failedAtIteration[i];
519*5c591343SA. Cody Schuffelen printf("Miller-Rabin failures not in first round = %d\n", nonFirst);
520*5c591343SA. Cody Schuffelen
521*5c591343SA. Cody Schuffelen }
522*5c591343SA. Cody Schuffelen CLEAR_VALUE(PrimeCounts);
523*5c591343SA. Cody Schuffelen CLEAR_VALUE(totalFieldsSieved);
524*5c591343SA. Cody Schuffelen CLEAR_VALUE(noPrimeFields);
525*5c591343SA. Cody Schuffelen CLEAR_VALUE(MillerRabinTrials);
526*5c591343SA. Cody Schuffelen CLEAR_VALUE(bitsInFieldAfterSieve);
527*5c591343SA. Cody Schuffelen }
528*5c591343SA. Cody Schuffelen
529*5c591343SA. Cody Schuffelen //*** GetSieveStats()
530*5c591343SA. Cody Schuffelen LIB_EXPORT void
GetSieveStats(uint32_t * trials,uint32_t * emptyFields,uint32_t * averageBits)531*5c591343SA. Cody Schuffelen GetSieveStats(
532*5c591343SA. Cody Schuffelen uint32_t *trials,
533*5c591343SA. Cody Schuffelen uint32_t *emptyFields,
534*5c591343SA. Cody Schuffelen uint32_t *averageBits
535*5c591343SA. Cody Schuffelen )
536*5c591343SA. Cody Schuffelen {
537*5c591343SA. Cody Schuffelen uint32_t totalBits;
538*5c591343SA. Cody Schuffelen uint32_t fields;
539*5c591343SA. Cody Schuffelen *trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2];
540*5c591343SA. Cody Schuffelen *emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2];
541*5c591343SA. Cody Schuffelen fields = totalFieldsSieved[0] + totalFieldsSieved[1]
542*5c591343SA. Cody Schuffelen + totalFieldsSieved[2];
543*5c591343SA. Cody Schuffelen totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1]
544*5c591343SA. Cody Schuffelen + bitsInFieldAfterSieve[2];
545*5c591343SA. Cody Schuffelen if(fields != 0)
546*5c591343SA. Cody Schuffelen *averageBits = totalBits / fields;
547*5c591343SA. Cody Schuffelen else
548*5c591343SA. Cody Schuffelen *averageBits = 0;
549*5c591343SA. Cody Schuffelen CLEAR_VALUE(PrimeCounts);
550*5c591343SA. Cody Schuffelen CLEAR_VALUE(totalFieldsSieved);
551*5c591343SA. Cody Schuffelen CLEAR_VALUE(noPrimeFields);
552*5c591343SA. Cody Schuffelen CLEAR_VALUE(MillerRabinTrials);
553*5c591343SA. Cody Schuffelen CLEAR_VALUE(bitsInFieldAfterSieve);
554*5c591343SA. Cody Schuffelen
555*5c591343SA. Cody Schuffelen }
556*5c591343SA. Cody Schuffelen #endif
557*5c591343SA. Cody Schuffelen
558*5c591343SA. Cody Schuffelen #endif // RSA_KEY_SIEVE
559*5c591343SA. Cody Schuffelen
560*5c591343SA. Cody Schuffelen #if !RSA_INSTRUMENT
561*5c591343SA. Cody Schuffelen
562*5c591343SA. Cody Schuffelen //*** RsaSimulationEnd()
563*5c591343SA. Cody Schuffelen // Stub for call when not doing instrumentation.
564*5c591343SA. Cody Schuffelen void
RsaSimulationEnd(void)565*5c591343SA. Cody Schuffelen RsaSimulationEnd(
566*5c591343SA. Cody Schuffelen void
567*5c591343SA. Cody Schuffelen )
568*5c591343SA. Cody Schuffelen {
569*5c591343SA. Cody Schuffelen return;
570*5c591343SA. Cody Schuffelen }
571*5c591343SA. Cody Schuffelen #endif