C++程序  |  951行  |  31.95 KB

// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 4: Supporting Routines
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include       "OsslCryptoEngine.h"
#ifdef       TPM_ALG_RSA
//
//     This file produces no code unless the compile switch is set to cause it to generate code.
//
#ifdef          RSA_KEY_SIEVE                          //%
#include        "RsaKeySieve.h"
//
//     This next line will show up in the header file for this code. It will make the local functions public when
//     debugging.
//
//%#ifdef       RSA_DEBUG
//
//
//      Bit Manipulation Functions
//
//          Introduction
//
//     These functions operate on a bit array. A bit array is an array of bytes with the 0th byte being the byte
//     with the lowest memory address. Within the byte, bit 0 is the least significant bit.
//
//          ClearBit()
//
//     This function will CLEAR a bit in a bit array.
//
void
ClearBit(
    unsigned char         *a,                     // IN: A pointer to an array of byte
    int                    i                      // IN: the number of the bit to CLEAR
    )
{
    a[i >> 3] &= 0xff ^ (1 << (i & 7));
}
//
//
//          SetBit()
//
//     Function to SET a bit in a bit array.
//
void
SetBit(
    unsigned char         *a,                     // IN: A pointer to an array of byte
    int                    i                      // IN: the number of the bit to SET
    )
{
    a[i >> 3] |= (1 << (i & 7));
}
//
//
//          IsBitSet()
//
//     Function to test if a bit in a bit array is SET.
//
//
//
//
//     Return Value                      Meaning
//
//     0                                 bit is CLEAR
//     1                                 bit is SET
//
UINT32
IsBitSet(
    unsigned char       *a,                   // IN: A pointer to an array of byte
    int                  i                    // IN: the number of the bit to test
    )
{
    return ((a[i >> 3] & (1 << (i & 7))) != 0);
}
//
//
//        BitsInArry()
//
//     This function counts the number of bits set in an array of bytes.
//
int
BitsInArray(
    unsigned char       *a,                   // IN: A pointer to an array of byte
    int                  i                    // IN: the number of bytes to sum
    )
{
    int     j = 0;
    for(; i ; i--)
        j += bitsInByte[*a++];
    return j;
}
//
//
//        FindNthSetBit()
//
//     This function finds the nth SET bit in a bit array. The caller should check that the offset of the returned
//     value is not out of range. If called when the array does not have n bits set, it will return a fatal error
//
UINT32
FindNthSetBit(
    const UINT16         aSize,               // IN: the size of the array to check
    const BYTE          *a,                   // IN: the array to check
    const UINT32         n                    // IN, the number of the SET bit
    )
{
    UINT32          i;
    const BYTE     *pA = a;
    UINT32          retValue;
    BYTE            sel;
    (aSize);
    //find the bit
    for(i = 0; i < n; i += bitsInByte[*pA++]);
    // The chosen bit is in the byte that was just accessed
    // Compute the offset to the start of that byte
    pA--;
    retValue = (UINT32)(pA - a) * 8;
    // Subtract the bits in the last byte added.
    i -= bitsInByte[*pA];
    // Now process the byte, one bit at a time.
    for(sel = *pA; sel != 0 ; sel = sel >> 1)
    {
        if(sel & 1)
        {
            i += 1;
            if(i == n)
                return retValue;
        }
        retValue += 1;
    }
    FAIL(FATAL_ERROR_INTERNAL);
}
//
//
//       Miscellaneous Functions
//
//          RandomForRsa()
//
//      This function uses a special form of KDFa() to produces a pseudo random sequence. It's input is a
//      structure that contains pointers to a pre-computed set of hash contexts that are set up for the HMAC
//      computations using the seed.
//      This function will test that ktx.outer will not wrap to zero if incremented. If so, the function returns FALSE.
//      Otherwise, the ktx.outer is incremented before each number is generated.
//
void
RandomForRsa(
    KDFa_CONTEXT        *ktx,                // IN: a context for the KDF
    const char          *label,              // IN: a use qualifying label
    TPM2B               *p                   // OUT: the pseudo random result
    )
{
    INT16                           i;
    UINT32                          inner;
    BYTE                            swapped[4];
    UINT16                          fill;
    BYTE                            *pb;
    UINT16                          lLen = 0;
    UINT16                          digestSize = _cpri__GetDigestSize(ktx->hashAlg);
    CPRI_HASH_STATE                 h;      // the working hash context
    if(label != NULL)
        for(lLen = 0; label[lLen++];);
    fill = digestSize;
    pb = p->buffer;
    inner = 0;
    *(ktx->outer) += 1;
    for(i = p->size; i > 0; i -= digestSize)
    {
        inner++;
         // Initialize the HMAC with saved state
         _cpri__CopyHashState(&h, &(ktx->iPadCtx));
         // Hash the inner counter (the one that changes on each HMAC iteration)
         UINT32_TO_BYTE_ARRAY(inner, swapped);
         _cpri__UpdateHash(&h, 4, swapped);
         if(lLen != 0)
             _cpri__UpdateHash(&h, lLen, (BYTE *)label);
         // Is there any party 1 data
         if(ktx->extra != NULL)
             _cpri__UpdateHash(&h, ktx->extra->size, ktx->extra->buffer);
        // Include the outer counter (the one that changes on each prime
        // prime candidate generation
        UINT32_TO_BYTE_ARRAY(*(ktx->outer), swapped);
        _cpri__UpdateHash(&h, 4, swapped);
        _cpri__UpdateHash(&h, 2, (BYTE *)&ktx->keySizeInBits);
        if(i < fill)
            fill = i;
        _cpri__CompleteHash(&h, fill, pb);
        // Restart the oPad hash
        _cpri__CopyHashState(&h, &(ktx->oPadCtx));
        // Add the last hashed data
        _cpri__UpdateHash(&h, fill, pb);
        // gives a completed HMAC
        _cpri__CompleteHash(&h, fill, pb);
        pb += fill;
   }
   return;
}
//
//
//         MillerRabinRounds()
//
//      Function returns the number of Miller-Rabin rounds necessary to give an error probability equal to the
//      security strength of the prime. These values are from FIPS 186-3.
//
UINT32
MillerRabinRounds(
   UINT32               bits                 // IN: Number of bits in the RSA prime
   )
{
   if(bits < 511) return 8;            // don't really expect this
   if(bits < 1536) return 5;           // for 512 and 1K primes
   return 4;                           // for 3K public modulus and greater
}
//
//
//         MillerRabin()
//
//      This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the number. I all
//      likelihood, if the number is not prime, the first test fails.
//      If a KDFa(), PRNG context is provide (ktx), then it is used to provide the random values. Otherwise, the
//      random numbers are retrieved from the random number generator.
//
//      Return Value                      Meaning
//
//      TRUE                              probably prime
//      FALSE                             composite
//
BOOL
MillerRabin(
   BIGNUM              *bnW,
   int                  iterations,
   KDFa_CONTEXT        *ktx,
   BN_CTX              *context
   )
{
   BIGNUM         *bnWm1;
   BIGNUM         *bnM;
   BIGNUM         *bnB;
   BIGNUM         *bnZ;
   BOOL         ret = FALSE;   // Assumed composite for easy exit
   TPM2B_TYPE(MAX_PRIME, MAX_RSA_KEY_BYTES/2);
   TPM2B_MAX_PRIME    b;
   int          a;
   int          j;
   int          wLen;
   int          i;
   pAssert(BN_is_bit_set(bnW, 0));
   INSTRUMENT_INC(MillerRabinTrials);    // Instrumentation
   BN_CTX_start(context);
   bnWm1 = BN_CTX_get(context);
   bnB = BN_CTX_get(context);
   bnZ = BN_CTX_get(context);
   bnM = BN_CTX_get(context);
   if(bnM == NULL)
       FAIL(FATAL_ERROR_ALLOCATION);
// Let a be the largest integer such that 2^a divides w1.
   BN_copy(bnWm1, bnW);
   BN_sub_word(bnWm1, 1);
   // Since w is odd (w-1) is even so start at bit number 1 rather than 0
   for(a = 1; !BN_is_bit_set(bnWm1, a); a++);
// 2. m = (w1) / 2^a
   BN_rshift(bnM, bnWm1, a);
// 3. wlen = len (w).
   wLen = BN_num_bits(bnW);
   pAssert((wLen & 7) == 0);
   // Set the size for the random number
   b.b.size = (UINT16)(wLen + 7)/8;
// 4. For i = 1 to iterations do
   for(i = 0; i < iterations ; i++)
   {
//  Obtain a string b of wlen bits from an RBG.
step4point1:
       // In the reference implementation, wLen is always a multiple of 8
       if(ktx != NULL)
            RandomForRsa(ktx, "Miller-Rabin witness", &b.b);
       else
            _cpri__GenerateRandom(b.t.size, b.t.buffer);
        if(BN_bin2bn(b.t.buffer, b.t.size, bnB) == NULL)
            FAIL(FATAL_ERROR_ALLOCATION);
//  If ((b 1) or (b w1)), then go to step 4.1.
       if(BN_is_zero(bnB))
           goto step4point1;
       if(BN_is_one(bnB))
           goto step4point1;
       if(BN_ucmp(bnB, bnWm1) >= 0)
           goto step4point1;
//  z = b^m mod w.
       if(BN_mod_exp(bnZ, bnB, bnM, bnW, context) != 1)
           FAIL(FATAL_ERROR_ALLOCATION);
//  If ((z = 1) or (z = w 1)), then go to step 4.7.
       if(BN_is_one(bnZ) || BN_ucmp(bnZ, bnWm1) == 0)
           goto step4point7;
//  For j = 1 to a 1 do.
       for(j = 1; j < a; j++)
       {
//  z = z^2 mod w.
           if(BN_mod_mul(bnZ, bnZ, bnZ, bnW, context) != 1)
               FAIL(FATAL_ERROR_ALLOCATION);
//  If (z = w1), then go to step 4.7.
           if(BN_ucmp(bnZ, bnWm1) == 0)
               goto step4point7;
//  If (z = 1), then go to step 4.6.
            if(BN_is_one(bnZ))
                goto step4point6;
       }
//  Return COMPOSITE.
step4point6:
       if(i > 9)
            INSTRUMENT_INC(failedAtIteration[9]);
       else
            INSTRUMENT_INC(failedAtIteration[i]);
       goto end;
//  Continue. Comment: Increment i for the do-loop in step 4.
step4point7:
       continue;
   }
// 5. Return PROBABLY PRIME
   ret = TRUE;
end:
   BN_CTX_end(context);
   return ret;
}
//
//
//         NextPrime()
//
//      This function is used to access the next prime number in the sequence of primes. It requires a pre-
//      initialized iterator.
//
UINT32
NextPrime(
   PRIME_ITERATOR      *iter
   )
{
   if(iter->index >= iter->final)
       return (iter->lastPrime = 0);
   return (iter->lastPrime += primeDiffTable[iter->index++]);
}
//
//
//         AdjustNumberOfPrimes()
//
//      Modifies the input parameter to be a valid value for the number of primes. The adjusted value is either the
//      input value rounded up to the next 512 bytes boundary or the maximum value of the implementation. If
//      the input is 0, the return is set to the maximum.
//
UINT32
AdjustNumberOfPrimes(
   UINT32               p
   )
{
   p = ((p + 511) / 512) * 512;
//
      if(p == 0 || p > PRIME_DIFF_TABLE_BYTES)
          p = PRIME_DIFF_TABLE_BYTES;
      return p;
}
//
//
//          PrimeInit()
//
//      This function is used to initialize the prime sequence generator iterator. The iterator is initialized and
//      returns the first prime that is equal to the requested starting value. If the starting value is no a prime, then
//      the iterator is initialized to the next higher prime number.
//
UINT32
PrimeInit(
      UINT32             first,              // IN: the initial prime
      PRIME_ITERATOR    *iter,               // IN/OUT: the iterator structure
      UINT32             primes              // IN: the table length
      )
{
      iter->lastPrime = 1;
      iter->index = 0;
      iter->final = AdjustNumberOfPrimes(primes);
      while(iter->lastPrime < first)
          NextPrime(iter);
      return iter->lastPrime;
}
//
//
//          SetDefaultNumberOfPrimes()
//
//      This macro sets the default number of primes to the indicated value.
//
//%#define SetDefaultNumberOfPrimes(p) (primeTableBytes = AdjustNumberOfPrimes(p))
//
//
//          IsPrimeWord()
//
//      Checks to see if a UINT32 is prime
//
//      Return Value                      Meaning
//
//      TRUE                              number is prime
//      FAIL                              number is not prime
//
BOOL
IsPrimeWord(
      UINT32              p                  // IN: number to test
      )
{
#if defined RSA_KEY_SIEVE && (PRIME_DIFF_TABLE_BYTES >= 6542)
      UINT32       test;
      UINT32       index;
      UINT32       stop;
      if((p & 1) == 0)
          return FALSE;
      if(p == 1 || p == 3)
          return TRUE;
      // Get a high value for the stopping point
      for(index = p, stop = 0; index; index >>= 2)
        stop = (stop << 1) + 1;
    stop++;
    // If the full prime difference value table is present, can check here
    test = 3;
    for(index = 1; index < PRIME_DIFF_TABLE_BYTES; index += 1)
    {
        if((p % test) == 0)
            return (p == test);
        if(test > stop)
            return TRUE;
        test += primeDiffTable[index];
    }
    return TRUE;
#else
   BYTE        b[4];
   if(p == RSA_DEFAULT_PUBLIC_EXPONENT || p == 1 || p == 3 )
       return TRUE;
   if((p & 1) == 0)
       return FALSE;
   UINT32_TO_BYTE_ARRAY(p,b);
   return _math__IsPrime(p);
#endif
}
typedef struct {
   UINT16      prime;
   UINT16      count;
} SIEVE_MARKS;
const SIEVE_MARKS sieveMarks[5] = {
   {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}};
//
//
//          PrimeSieve()
//
//      This function does a prime sieve over the input field which has as its starting address the value in bnN.
//      Since this initializes the Sieve using a pre-computed field with the bits associated with 3, 5 and 7 already
//      turned off, the value of pnN may need to be adjusted by a few counts to allow the pre-computed field to
//      be used without modification. The fieldSize parameter must be 2^N + 1 and is probably not useful if it is
//      less than 129 bytes (1024 bits).
//
UINT32
PrimeSieve(
    BIGNUM        *bnN,            //   IN/OUT: number to sieve
    UINT32         fieldSize,      //   IN: size of the field area in bytes
    BYTE          *field,          //   IN: field
    UINT32         primes          //   IN: the number of primes to use
    )
{
    UINT32              i;
    UINT32              j;
    UINT32              fieldBits = fieldSize * 8;
    UINT32              r;
    const BYTE         *p1;
    BYTE               *p2;
    PRIME_ITERATOR      iter;
    UINT32              adjust;
    UINT32              mark = 0;
    UINT32              count = sieveMarks[0].count;
    UINT32              stop = sieveMarks[0].prime;
    UINT32              composite;
//      UINT64              test;           //DEBUG
   pAssert(field != NULL && bnN != NULL);
   // Need to have a field that has a size of 2^n + 1 bytes
   pAssert(BitsInArray((BYTE *)&fieldSize, 2) == 2);
   primes = AdjustNumberOfPrimes(primes);
   // If the remainder is odd, then subtracting the value
   // will give an even number, but we want an odd number,
   // so subtract the 105+rem. Otherwise, just subtract
   // the even remainder.
   adjust = BN_mod_word(bnN,105);
   if(adjust & 1)
       adjust += 105;
   // seed the field
   // This starts the pointer at the nearest byte to the input value
   p1 = &seedValues[adjust/16];
   // Reduce the number of bytes to transfer by the amount skipped
   j = sizeof(seedValues) - adjust/16;
   adjust = adjust % 16;
   BN_sub_word(bnN, adjust);
   adjust >>= 1;
   // This offsets the field
   p2 = field;
   for(i = fieldSize; i > 0; i--)
   {
       *p2++ = *p1++;
       if(--j == 0)
       {
           j = sizeof(seedValues);
           p1 = seedValues;
       }
   }
   // Mask the first bits in the field and the last byte in order to eliminate
   // bytes not in the field from consideration.
   field[0] &= 0xff << adjust;
   field[fieldSize-1] &= 0xff >> (8 - adjust);
   // Cycle through the primes, clearing bits
   // Have already done 3, 5, and 7
   PrimeInit(7, &iter, primes);
   // Get the next N primes where N is determined by the mark in the sieveMarks
   while((composite = NextPrime(&iter)) != 0)
   {
       UINT32 pList[8];
       UINT32   next = 0;
       i = count;
       pList[i--] = composite;
       for(; i > 0; i--)
       {
           next = NextPrime(&iter);
           pList[i] = next;
           if(next != 0)
               composite *= next;
       }
       composite = BN_mod_word(bnN, composite);
       for(i = count; i > 0; i--)
       {
           next = pList[i];
           if(next == 0)
               goto done;
           r = composite % next;
              if(r & 1)           j = (next - r)/2;
              else if(r == 0)     j = 0;
              else                j = next - r/2;
              for(; j < fieldBits; j += next)
                  ClearBit(field, j);
         }
         if(next >= stop)
         {
             mark++;
             count = sieveMarks[mark].count;
             stop = sieveMarks[mark].prime;
         }
   }
done:
   INSTRUMENT_INC(totalFieldsSieved);
   i = BitsInArray(field, fieldSize);
   if(i == 0) INSTRUMENT_INC(emptyFieldsSieved);
   return i;
}
//
//
//       PrimeSelectWithSieve()
//
//      This function will sieve the field around the input prime candidate. If the sieve field is not empty, one of
//      the one bits in the field is chosen for testing with Miller-Rabin. If the value is prime, pnP is updated with
//      this value and the function returns success. If this value is not prime, another pseudo-random candidate
//      is chosen and tested. This process repeats until all values in the field have been checked. If all bits in the
//      field have been checked and none is prime, the function returns FALSE and a new random value needs
//      to be chosen.
//
BOOL
PrimeSelectWithSieve(
   BIGNUM               *bnP,                    // IN/OUT: The candidate to filter
   KDFa_CONTEXT         *ktx,                    // IN: KDFa iterator structure
   UINT32                e,                      // IN: the exponent
   BN_CTX               *context                 // IN: the big number context to play in
#ifdef RSA_DEBUG                                  //%
  ,UINT16                fieldSize,              // IN: number of bytes in the field, as
                                                 //     determined by the caller
   UINT16            primes                      // IN: number of primes to use.
#endif                                            //%
)
{
   BYTE              field[MAX_FIELD_SIZE];
   UINT32            first;
   UINT32            ones;
   INT32             chosen;
   UINT32            rounds = MillerRabinRounds(BN_num_bits(bnP));
#ifndef RSA_DEBUG
   UINT32            primes;
   UINT32            fieldSize;
   // Adjust the field size and prime table list to fit the size of the prime
   // being tested.
   primes = BN_num_bits(bnP);
   if(primes <= 512)
   {
       primes = AdjustNumberOfPrimes(2048);
       fieldSize = 65;
   }
   else if(primes <= 1024)
   {
       primes = AdjustNumberOfPrimes(4096);
       fieldSize = 129;
   }
//
   else
   {
       primes = AdjustNumberOfPrimes(0);             // Set to the maximum
       fieldSize = MAX_FIELD_SIZE;
   }
   if(fieldSize > MAX_FIELD_SIZE)
       fieldSize = MAX_FIELD_SIZE;
#endif
    // Save the low-order word to use as a search generator and make sure that
    // it has some interesting range to it
    first = bnP->d[0] | 0x80000000;
   // Align to field boundary
   bnP->d[0] &= ~((UINT32)(fieldSize-3));
   pAssert(BN_is_bit_set(bnP, 0));
   bnP->d[0] &= (UINT32_MAX << (FIELD_POWER + 1)) + 1;
   ones = PrimeSieve(bnP, fieldSize, field, primes);
#ifdef RSA_FILTER_DEBUG
   pAssert(ones == BitsInArray(field, defaultFieldSize));
#endif
   for(; ones > 0; ones--)
   {
#ifdef RSA_FILTER_DEBUG
       if(ones != BitsInArray(field, defaultFieldSize))
           FAIL(FATAL_ERROR_INTERNAL);
#endif
       // Decide which bit to look at and find its offset
       if(ones == 1)
           ones = ones;
       chosen = FindNthSetBit(defaultFieldSize, field,((first % ones) + 1));
       if(chosen >= ((defaultFieldSize) * 8))
           FAIL(FATAL_ERROR_INTERNAL);
         // Set this as the trial prime
         BN_add_word(bnP, chosen * 2);
         // Use MR to see if this is prime
         if(MillerRabin(bnP, rounds, ktx, context))
         {
             // Final check is to make sure that 0 != (p-1) mod e
             // This is the same as -1 != p mod e ; or
             // (e - 1) != p mod e
             if((e <= 3) || (BN_mod_word(bnP, e) != (e-1)))
                 return TRUE;
         }
         // Back out the bit number
         BN_sub_word(bnP, chosen * 2);
         // Clear the bit just tested
         ClearBit(field, chosen);
}
    // Ran out of bits and couldn't find a prime in this field
    INSTRUMENT_INC(noPrimeFields);
    return FALSE;
}
//
//
//       AdjustPrimeCandiate()
//
//      This function adjusts the candidate prime so that it is odd and > root(2)/2. This allows the product of these
//      two numbers to be .5, which, in fixed point notation means that the most significant bit is 1. For this
//      routine, the root(2)/2 is approximated with 0xB505 which is, in fixed point is 0.7071075439453125 or an
//      error of 0.0001%. Just setting the upper two bits would give a value > 0.75 which is an error of > 6%.
//
//
//      Given the amount of time all the other computations take, reducing the error is not much of a cost, but it
//      isn't totally required either.
//      The function also puts the number on a field boundary.
//
void
AdjustPrimeCandidate(
   BYTE                *a,
   UINT16               len
   )
{
   UINT16    highBytes;
   highBytes = BYTE_ARRAY_TO_UINT16(a);
   // This is fixed point arithmetic on 16-bit values
   highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16;
   highBytes += 0xB505;
   UINT16_TO_BYTE_ARRAY(highBytes, a);
   a[len-1] |= 1;
}
//
//
//       GeneratateRamdomPrime()
//
void
GenerateRandomPrime(
   TPM2B  *p,
   BN_CTX *ctx
#ifdef RSA_DEBUG               //%
  ,UINT16  field,
   UINT16  primes
#endif                         //%
   )
{
   BIGNUM *bnP;
   BN_CTX *context;
   if(ctx == NULL) context = BN_CTX_new();
   else context = ctx;
   if(context == NULL)
       FAIL(FATAL_ERROR_ALLOCATION);
   BN_CTX_start(context);
   bnP = BN_CTX_get(context);
   while(TRUE)
   {
       _cpri__GenerateRandom(p->size, p->buffer);
       p->buffer[p->size-1] |= 1;
       p->buffer[0] |= 0x80;
       BN_bin2bn(p->buffer, p->size, bnP);
#ifdef RSA_DEBUG
       if(PrimeSelectWithSieve(bnP, NULL, 0, context, field, primes))
#else
       if(PrimeSelectWithSieve(bnP, NULL, 0, context))
#endif
           break;
   }
   BnTo2B(p, bnP, (UINT16)BN_num_bytes(bnP));
   BN_CTX_end(context);
   if(ctx == NULL)
       BN_CTX_free(context);
   return;
}
KDFa_CONTEXT *
KDFaContextStart(
    KDFa_CONTEXT        *ktx,                //   IN/OUT:   the context structure to initialize
    TPM2B               *seed,               //   IN: the   seed for the digest proce
    TPM_ALG_ID           hashAlg,            //   IN: the   hash algorithm
    TPM2B               *extra,              //   IN: the   extra data
    UINT32              *outer,              //   IN: the   outer iteration counter
    UINT16               keySizeInBit
    )
{
    UINT16                     digestSize = _cpri__GetDigestSize(hashAlg);
    TPM2B_HASH_BLOCK           oPadKey;
    if(seed == NULL)
        return NULL;
    pAssert(ktx != NULL && outer != NULL && digestSize != 0);
   // Start the hash using the seed and get the intermediate hash value
   _cpri__StartHMAC(hashAlg, FALSE, &(ktx->iPadCtx), seed->size, seed->buffer,
                    &oPadKey.b);
   _cpri__StartHash(hashAlg, FALSE, &(ktx->oPadCtx));
   _cpri__UpdateHash(&(ktx->oPadCtx), oPadKey.b.size, oPadKey.b.buffer);
   ktx->extra = extra;
   ktx->hashAlg = hashAlg;
   ktx->outer = outer;
   ktx->keySizeInBits = keySizeInBits;
   return ktx;
}
void
KDFaContextEnd(
    KDFa_CONTEXT        *ktx                 // IN/OUT: the context structure to close
    )
{
    if(ktx != NULL)
    {
        // Close out the hash sessions
        _cpri__CompleteHash(&(ktx->iPadCtx), 0, NULL);
        _cpri__CompleteHash(&(ktx->oPadCtx), 0, NULL);
    }
}
//%#endif
//
//
//       Public Function
//
//         Introduction
//
//      This is the external entry for this replacement function. All this file provides is the substitute function to
//      generate an RSA key. If the compiler settings are set appropriately, this this function will be used instead
//      of the similarly named function in CpriRSA.c.
//
//         _cpri__GenerateKeyRSA()
//
//      Generate an RSA key from a provided seed
//
//      Return Value                     Meaning
//
//      CRYPT_FAIL                       exponent is not prime or is less than 3; or could not find a prime using
//                                       the provided parameters
//      CRYPT_CANCEL                     operation was canceled
//
LIB_EXPORT CRYPT_RESULT
_cpri__GenerateKeyRSA(
   TPM2B              *n,               // OUT: The public modulus
   TPM2B              *p,               // OUT: One of the prime factors of n
   UINT16              keySizeInBits,   // IN: Size of the public modulus in bits
   UINT32              e,               // IN: The public exponent
   TPM_ALG_ID          hashAlg,         // IN: hash algorithm to use in the key
                                        //     generation process
   TPM2B              *seed,            // IN: the seed to use
   const char         *label,           // IN: A label for the generation process.
   TPM2B              *extra,           // IN: Party 1 data for the KDF
   UINT32             *counter          // IN/OUT: Counter value to allow KDF
                                        //         iteration to be propagated across
                                        //         multiple routines
#ifdef RSA_DEBUG                         //%
  ,UINT16              primes,          // IN: number of primes to test
   UINT16              fieldSize        // IN: the field size to use
#endif                                   //%
   )
{
   CRYPT_RESULT             retVal;
   UINT32                   myCounter = 0;
   UINT32                  *pCtr = (counter == NULL) ? &myCounter : counter;
   KDFa_CONTEXT             ktx;
   KDFa_CONTEXT            *ktxPtr;
   UINT32                   i;
   BIGNUM                  *bnP;
   BIGNUM                  *bnQ;
   BIGNUM                  *bnT;
   BIGNUM                  *bnE;
   BIGNUM                  *bnN;
   BN_CTX                  *context;
   // Make sure that the required pointers are provided
   pAssert(n != NULL && p != NULL);
   // If the seed is provided, then use KDFa for generation of the 'random'
   // values
   ktxPtr = KDFaContextStart(&ktx, seed, hashAlg, extra, pCtr, keySizeInBits);
   n->size = keySizeInBits/8;
   p->size = n->size / 2;
   // Validate exponent
   if(e == 0 || e == RSA_DEFAULT_PUBLIC_EXPONENT)
       e = RSA_DEFAULT_PUBLIC_EXPONENT;
   else
       if(!IsPrimeWord(e))
           return CRYPT_FAIL;
   // Get structures for the big number representations
   context = BN_CTX_new();
   BN_CTX_start(context);
   bnP = BN_CTX_get(context);
   bnQ = BN_CTX_get(context);
   bnT = BN_CTX_get(context);
   bnE = BN_CTX_get(context);
   bnN = BN_CTX_get(context);
   if(bnN == NULL)
       FAIL(FATAL_ERROR_INTERNAL);
   //   Set Q to zero. This is used as a flag. The prime is computed in P. When a
   //   new prime is found, Q is checked to see if it is zero. If so, P is copied
   //   to Q and a new P is found. When both P and Q are non-zero, the modulus and
   //   private exponent are computed and a trial encryption/decryption is
   //   performed. If the encrypt/decrypt fails, assume that at least one of the
   //   primes is composite. Since we don't know which one, set Q to zero and start
   // over and find a new pair of primes.
   BN_zero(bnQ);
   BN_set_word(bnE, e);
   // Each call to generate a random value will increment ktx.outer
   // it doesn't matter if ktx.outer wraps. This lets the caller
   // use the initial value of the counter for additional entropy.
   for(i = 0; i < UINT32_MAX; i++)
   {
       if(_plat__IsCanceled())
       {
            retVal = CRYPT_CANCEL;
            goto end;
       }
       // Get a random prime candidate.
       if(seed == NULL)
            _cpri__GenerateRandom(p->size, p->buffer);
       else
            RandomForRsa(&ktx, label, p);
       AdjustPrimeCandidate(p->buffer, p->size);
         // Convert the candidate to a BN
         if(BN_bin2bn(p->buffer, p->size, bnP) == NULL)
             FAIL(FATAL_ERROR_INTERNAL);
         // If this is the second prime, make sure that it differs from the
         // first prime by at least 2^100. Since BIGNUMS use words, the check
         // below will make sure they are different by at least 128 bits
         if(!BN_is_zero(bnQ))
         { // bnQ is non-zero, we have a first value
             UINT32       *pP = (UINT32 *)(&bnP->d[4]);
             UINT32       *pQ = (UINT32 *)(&bnQ->d[4]);
             INT32        k = ((INT32)bnP->top) - 4;
             for(;k > 0; k--)
                 if(*pP++ != *pQ++)
                     break;
             // Didn't find any difference so go get a new value
             if(k == 0)
                 continue;
         }
         // If PrimeSelectWithSieve   returns success, bnP is a prime,
#ifdef    RSA_DEBUG
         if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context, fieldSize, primes))
#else
         if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context))
#endif
              continue;      // If not, get another
         // Found a prime, is this the first or second.
         if(BN_is_zero(bnQ))
         {    // copy p to q and compute another prime in p
              BN_copy(bnQ, bnP);
              continue;
         }
         //Form the public modulus
        if(    BN_mul(bnN, bnP, bnQ, context) != 1
            || BN_num_bits(bnN) != keySizeInBits)
              FAIL(FATAL_ERROR_INTERNAL);
        // Save the public modulus
        BnTo2B(n, bnN, n->size);
        // And one prime
        BnTo2B(p, bnP, p->size);
#ifdef EXTENDED_CHECKS
       // Finish by making sure that we can form the modular inverse of PHI
       // with respect to the public exponent
       // Compute PHI = (p - 1)(q - 1) = n - p - q + 1
        // Make sure that we can form the modular inverse
        if(    BN_sub(bnT, bnN, bnP) != 1
            || BN_sub(bnT, bnT, bnQ) != 1
            || BN_add_word(bnT, 1) != 1)
             FAIL(FATAL_ERROR_INTERNAL);
        // find d such that (Phi * d) mod e ==1
        // If there isn't then we are broken because we took the step
        // of making sure that the prime != 1 mod e so the modular inverse
        // must exist
        if(    BN_mod_inverse(bnT, bnE, bnT, context) == NULL
            || BN_is_zero(bnT))
             FAIL(FATAL_ERROR_INTERNAL);
        // And, finally, do a trial encryption decryption
        {
            TPM2B_TYPE(RSA_KEY, MAX_RSA_KEY_BYTES);
            TPM2B_RSA_KEY        r;
            r.t.size = sizeof(r.t.buffer);
            // If we are using a seed, then results must be reproducible on each
            // call. Otherwise, just get a random number
            if(seed == NULL)
                _cpri__GenerateRandom(keySizeInBits/8, r.t.buffer);
            else
                RandomForRsa(&ktx, label, &r.b);
             // Make sure that the number is smaller than the public modulus
             r.t.buffer[0] &= 0x7F;
                    // Convert
             if(    BN_bin2bn(r.t.buffer, r.t.size, bnP) == NULL
                    // Encrypt with the public exponent
                 || BN_mod_exp(bnQ, bnP, bnE, bnN, context) != 1
                    // Decrypt with the private exponent
                 || BN_mod_exp(bnQ, bnQ, bnT, bnN, context) != 1)
                  FAIL(FATAL_ERROR_INTERNAL);
             // If the starting and ending values are not the same, start over )-;
             if(BN_ucmp(bnP, bnQ) != 0)
             {
                  BN_zero(bnQ);
                  continue;
             }
       }
#endif // EXTENDED_CHECKS
       retVal = CRYPT_SUCCESS;
       goto end;
   }
   retVal = CRYPT_FAIL;
end:
   KDFaContextEnd(&ktx);
   // Free up allocated BN values
   BN_CTX_end(context);
   BN_CTX_free(context);
   return retVal;
}
#endif              //%
#endif // TPM_ALG_RSA