📄 dsapgimpl.c
字号:
}
/* If the mpIntCtx did not have a GeneratePrime function, or if the
* implementation did not do FIPS and FIPS was requested, then use
* the regular toolkit technique.
*/
if (status == VT_ERROR_FIPS)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGeneratePrimeFips (
subprimeSizeBits, random, SEED, seedLen, subprimeQ);
}
/* If status is not 0 at this point, give up.
* Maybe the mpIntCtx GeneratePrime set status to something other
* than 0 or ERROR_FIPS, or maybe the regular toolkit function set
* it, it doesn't matter, it's an error now.
*/
if (status != 0)
break;
/* Step 6: counter = 0, offset = 2
*/
counter = 0;
offset = 2;
/* This is the beginning of the inner loop: find primeP based on
* the given subprimeQ.
*/
do
{
if (surrCtx != (VoltSurrenderCtx *)0)
{
surrCtx->surrenderInfo.callNumber++;
VOLT_SET_FNCT_LINE (fnctLine)
status = surrCtx->Surrender (
surrCtx->libraryCtx, surrCtx->appData, &(surrCtx->surrenderInfo));
if (status != 0)
break;
}
/* Step 7: Build the primeP starting point by digesting SEED along
* with the offset and a count as many times as necessary to
* generate the appropriate number of bytes.
*/
Z2Memcpy (seedCopy, SEED, *seedLen);
totalLen = bufSize;
kVal = 0;
bufOffset = bufSize;
AddValueToBuffer (seedCopy, *seedLen, offset - 1);
do
{
/* Compute SEED + offset + kVal.
*/
AddValueToBuffer (seedCopy, *seedLen, 1);
kVal++;
/* Digest this value.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VtDigestInit (sha1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtDigestFinal (
sha1, seedCopy, *seedLen, digest, 20, &digestLen);
if (status != 0)
break;
if (digestLen > totalLen)
digestLen = totalLen;
/* "Prepend" the current digest. This is the part of step 8
* that builds W.
*/
bufOffset -= digestLen;
totalLen -= digestLen;
Z2Memcpy (buffer + bufOffset, digest + (20 - digestLen), digestLen);
} while (totalLen > 0);
if (status != 0)
break;
/* Finish step 8, compute X.
*/
/* The FIPS technique actually specifies that W is a value of
* length primeSizeBits - 1, so we need to clear the most
* significant bit of the buffer to get the appropriate W. But
* then we're going to add that bit in to get X, which is
* W + (2 ^ (primeSizeBits - 1)). So at this point, just make
* sure the most significant bit is set.
*/
buffer[0] &= (unsigned char)bitMask;
buffer[0] |= (unsigned char)bitSet;
/* Step 9: c = X mod 2q, p = X - (c - 1)
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->OctetStringToMpInt (0, buffer, bufSize, primeP);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Add (subprimeQ, subprimeQ, expo);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModReduce (primeP, expo, remainder);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (remainder, baseG, remainder);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (primeP, remainder, primeP);
if (status != 0)
break;
/* Step 10: is primeP < 2 ^ (primeSizeBits - 1).
* In other words, is the most significant bit still set?
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->GetBit (primeP, primeSizeBits - 1, &msbit);
if (status == VT_ERROR_MP_INT_RANGE)
status = 0;
if (status != 0)
break;
/* Continuing Step 10, if the bit is set, move on to step 11.
*/
if (msbit != 0)
{
/* Step 11: Is primeP actually prime?
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltRabinMillerTest (primeP, primeSizeBits, random, &isPrime);
if (status != 0)
break;
/* Step 12: If the value is prime, move on to step 15.
*/
if (isPrime != 0)
break;
}
/* Step 13: The candidate "failed", either the msbit was not set
* after the subtraction or it was not prime. Update counter and
* offset.
*/
counter++;
offset += (nVal + 1);
/* Step 14: If counter >= 4096, find a new subprimeQ.
*/
if (counter >= 4096)
break;
/* Step 14: If counter < 4096, try another primeP.
*/
} while (1);
if (status != 0)
break;
/* At this point, we exited the inner loop because either we
* found a prime or the counter hit 4096. If isPrime is not 0, we
* found a prime.
*/
if (isPrime != 0)
break;
} while (1);
if (status != 0)
break;
/* If we reach this point, we have a subprimeQ and a primeP. The
* SEED buffer contains the seed we used and counter is set to the
* value we'll need to return at the address given by the count arg.
*/
*count = counter;
/* Now that we have p and q, compute g. It is
* g = h ^ ((p-1)/q)
* where h is a random number.
*/
/* Find (p-1) / q
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->MpIntToMpInt (primeP, expo);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (expo, 0, 0);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Divide (expo, subprimeQ, expo, remainder);
if (status != 0)
break;
/* Generate a random h < p.
*/
do
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGenerateRandomBytes (random, buffer, bufSize);
if (status != 0)
break;
buffer[0] = 2;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->OctetStringToMpInt (0, buffer, /**/1/*/bufSize/*/, hVal); /* FIX */
if (status != 0)
break;
/* compute g
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModExp (hVal, expo, primeP, baseG);
if (status != 0)
break;
/* Make sure baseG is not a small number.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->MpIntToInt (baseG, 1, &msbit);
/* If status is 0, the g computed fit into an unsigned int,
* that's small, try again with new random material.
*/
if (status == 0)
continue;
/* If status is VT_ERROR_MP_INT_RANGE, the number is big enough, we're
* done. Make sure status is 0.
* If status was some other error, pass it along.
*/
if (status == VT_ERROR_MP_INT_RANGE)
status = 0;
break;
} while (1);
} while (0);
if (callNumber != (unsigned int *)0)
*callNumber = callNum;
if (buffer != (unsigned char *)0)
Z2Free (buffer);
mpCtx->DestroyMpInt (&remainder);
mpCtx->DestroyMpInt (&expo);
VtDestroyAlgorithmObject (&sha1);
VOLT_LOG_ERROR_COMPARE (
status, (VtLibCtx)libCtx, status, errorType, fnctLine,
"VoltGeneratePQG", (char *)0)
return (status);
}
static void AddValueToBuffer (
unsigned char *buffer,
unsigned int bufferLen,
UInt32 increment
)
{
unsigned int indexB, indexI;
unsigned char carry, val;
unsigned char vector[4];
VOLT_SET_UINT32 (increment, vector)
/* Add the four words of the increment to the low four words of the
* buffer.
*/
carry = 0;
for (indexI = 4, indexB = bufferLen; indexI > 0; --indexI, --indexB)
{
val = carry + vector[indexI - 1];
if (val >= carry)
carry = 0;
buffer[indexB - 1] += val;
if (buffer[indexB - 1] < val)
carry = 1;
}
/* If there's no carry, we're done.
*/
if (carry == 0)
return;
/* Propagate the carry through the buffer (ignoring any carry beyond
* the most significant byte.
*/
for (; indexB > 0; --indexB)
{
buffer[indexB - 1] += 1;
if (buffer[indexB - 1] != 0)
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -