📄 dhpgimpl.c
字号:
/* Copyright 2005-2006, Voltage Security, all rights reserved.
*/
#include "vibecrypto.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "paramobj.h"
#include "mpint.h"
#include "dh.h"
#include "prime.h"
#include "surrender.h"
#include "errorctx.h"
int DHGenerateParameters (
VtParameterObject paramObj,
VtRandomObject random
)
{
int status;
unsigned int seedLen, counter, callNumber;
VoltParameterObject *obj = (VoltParameterObject *)paramObj;
VoltDHParamGenCtx *dhParamGenCtx =
(VoltDHParamGenCtx *)(obj->localGenerateCtx);
VtRandomObject randomToUse;
VoltMpIntCtx *mpCtx = obj->mpCtx;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltMpInt *primeP = (VoltMpInt *)0;
VoltMpInt *subprimeQ = (VoltMpInt *)0;
VoltMpInt *baseG = (VoltMpInt *)0;
VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
unsigned char SEED[20];
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* If the object already contains parameters, error.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_PARAM_OBJ;
if (obj->paramData != (Pointer)0)
break;
/* If there's a surrender ctx, call the Surrender function.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_GET_OBJECT_SURR_CTX (surrCtx, obj);
VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_DH_PARAM_GEN, 0, 1)
/* If there's no random object, get one from the libCtx.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_NO_RANDOM_OBJECT;
randomToUse = random;
if (random == (VtRandomObject)0)
{
randomToUse = (VtRandomObject)VoltGetLibCtxInfo (
(VtLibCtx)libCtx, VOLT_LIB_CTX_INFO_TYPE_RANDOM);
if (randomToUse == (VtRandomObject)0)
break;
}
/* Make sure the random object is valid.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_RANDOM_OBJ;
if (VOLT_OBJECT_TYPE_NOT_EQUAL (randomToUse, VOLT_OBJECT_TYPE_RANDOM))
break;
/* Create the MPInt's.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &primeP);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &subprimeQ);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &baseG);
if (status != 0)
break;
/* Generate p, q, and g following X9.42.
*/
VOLT_SET_FNCT_LINE (fnctLine)
callNumber = 1;
status = VoltGeneratePQGX942 (
mpCtx, surrCtx, VT_SURRENDER_FNCT_DH_PARAM_GEN, &callNumber,
dhParamGenCtx->primeSizeBits, 160, randomToUse,
primeP, subprimeQ, baseG, SEED, &seedLen, &counter);
if (status != 0)
break;
/* If that succeeded, set the object with the values.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltAddDHParametersMpInt (
obj, primeP, subprimeQ, baseG, SEED, seedLen, counter);
if (status != 0)
break;
/* If there's a surrender ctx, call it for the last time.
*/
VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_DH_PARAM_GEN, 0, 0)
} while (0);
Z2Memset (SEED, 0, sizeof (SEED));
if (mpCtx != (VoltMpIntCtx *)0)
{
mpCtx->DestroyMpInt (&primeP);
mpCtx->DestroyMpInt (&subprimeQ);
mpCtx->DestroyMpInt (&baseG);
}
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, paramObj, status, 0, errorType,
(char *)0, "DHGenerateParameters", fnctLine, (char *)0)
return (status);
}
int VoltGeneratePQGX942 (
VoltMpIntCtx *mpCtx,
VoltSurrenderCtx *surrCtx,
unsigned int surrFlag,
unsigned int *callNumber,
unsigned int primeSizeBits,
unsigned int subprimeSizeBits,
VtRandomObject random,
VoltMpInt *primeP,
VoltMpInt *subprimeQ,
VoltMpInt *baseG,
unsigned char *SEED,
unsigned int *seedLen,
unsigned int *count
)
{
int status, cmpResult;
unsigned int callNum, sLen, mPrime, digestLen;
unsigned int index, lLimit, nLimit, pGenCounter, isPrime;
unsigned char *buffer = (unsigned char *)0;
unsigned char *rBuf, *digest;
VoltLibCtx *libCtx = (VoltLibCtx *)(mpCtx->voltObject.libraryCtx);
VtAlgorithmObject sha1 = (VtAlgorithmObject)0;
VoltMpInt *currentP = (VoltMpInt *)0;
VoltMpInt *temp = (VoltMpInt *)0;
VoltMpInt *expo = (VoltMpInt *)0;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
callNum = 1;
if (callNumber != (unsigned int *)0)
callNum = *callNumber;
do
{
/* For now, the toolkit supports only 1024-bit DH prime p and
* 160-bit subprime q.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_PARAM_LENGTH;
if ( (primeSizeBits != 1024) || (subprimeSizeBits != 160) )
break;
/* We'll need this later on.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplSHA1, (Pointer)0, &sha1);
if (status != 0)
break;
/* For this implementation, the seedLen is the number of bytes
* needed to hold subprimeSizeBits.
*/
sLen = (subprimeSizeBits + 7) / 8;
*seedLen = sLen;
/* Create the mpInt's we'll need.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, ¤tP);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &temp);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &expo);
if (status != 0)
break;
/* Use baseG as a temp to add 1 later on.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->IntToMpInt (0, 1, baseG);
if (status != 0)
break;
/* After we find the subprime, we'll need a buffer to hold the
* primeP starting point. While we're at it, allocate space for
* a copy of SEED that we'll be able to manipulate, and a digest
* buffer.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_MEMORY;
buffer = (unsigned char *)Z2Malloc (sLen + 20, VOLT_MEMORY_SENSITIVE);
if (buffer == (unsigned char *)0)
break;
rBuf = buffer;
digest = rBuf + sLen;
/* Step 1: m' = ceil (subprimeBits / 160). This is used in the
* computation of the subprime (a subroutine), but also used as
* input to a digest function.
*/
mPrime = (subprimeSizeBits + 159) / 160;
/* Step 2: This is the number of blocks we'll have to build to get
* a starting point for the primeP.
*/
lLimit = (primeSizeBits + 159) / 160;
/* Step 3: This will form a p generation count limit.
*/
nLimit = (primeSizeBits + 1023) / 1024;
/* Steps 2 - 8: Generate the subprime. See the comments in
* VoltGeneratePrimeX942 for more on steps 2 - 8.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGeneratePrimeX942 (
subprimeSizeBits, random, SEED, seedLen, subprimeQ);
if (status != 0)
break;
/* Step 9: set pGenCounter to 0.
*/
pGenCounter = 0;
/* Steps 10 - 18 are a loop.
*/
do
{
VOLT_SET_ERROR_TYPE (errorType, 0)
callNum++;
VOLT_CALL_SURRENDER (surrCtx, surrFlag, 0, callNum)
/* Step 10: Initialize R = seed + 2m' + (lLimit * pGenCounter)
*/
Z2Memcpy (rBuf, SEED, sLen);
VoltAddValueToBuffer (rBuf, sLen, (UInt32)(mPrime * 2));
VoltAddValueToBuffer (rBuf, sLen, (UInt32)(lLimit * pGenCounter));
/* Step 11: Set p to 0.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->IntToMpInt (0, 0, currentP);
if (status != 0)
break;
/* Step 12: For i = 0 to lLimit, generate blocks.
*/
for (index = 0; index < lLimit; ++index)
{
/* Compute SHA1 (R + i)
*/
if (index != 0)
VoltAddValueToBuffer (rBuf, sLen, 1);
VOLT_SET_FNCT_LINE (fnctLine)
status = VtDigestInit (sha1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtDigestFinal (sha1, rBuf, sLen, digest, 20, &digestLen);
if (status != 0)
break;
/* Add this to the current value we're building.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->OctetStringToMpInt (0, digest, digestLen, temp);
if (status != 0)
break;
/* We actually add 2^(160i).
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ShiftLeftBits (temp, index * 160);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Add (temp, currentP, currentP);
if (status != 0)
break;
}
if (status != 0)
break;
/* Step 13: p = p mod 2 ^ L, then make sure the ms bit is set.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->IntToMpInt (0, 1, temp);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ShiftLeftBits (temp, primeSizeBits);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModReduce (currentP, temp, primeP);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (primeP, primeSizeBits - 1, 1);
if (status != 0)
break;
/* Step 14: set p = p - (p mod 2q) + 1
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Add (subprimeQ, subprimeQ, temp);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModReduce (primeP, temp, currentP);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (primeP, currentP, primeP);
if (status != 0)
break;
/* We had set baseG with 1.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Add (primeP, baseG, primeP);
if (status != 0)
break;
/* Step 15: If the value is still the appropriate bit length,
* test for primality.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->GetBitLength (primeP, &index);
if (status != 0)
break;
if (index == primeSizeBits)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltRabinMillerTest (
primeP, primeSizeBits, 50, random, &isPrime);
if (status != 0)
break;
/* If this came back prime, we're done.
*/
if (isPrime != 0)
break;
}
/* We don't have a prime yet. Increment pGenCounter.
*/
pGenCounter++;
/* If it's too large, we couldn't find a prime.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_NO_PRIME_FOUND;
if (pGenCounter > (4096 * nLimit))
break;
} while (1);
if (status != 0)
break;
*count = pGenCounter;
/* Now that we have p and q, construct g. This is section B.2 in
* X9.42.
*/
/* Step 1: find j = (p -1) / q.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (primeP, baseG, temp);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Divide (temp, subprimeQ, expo, baseG);
if (status != 0)
break;
/* Try g-base candidates until finding one that succeeds.
*/
callNum++;
VOLT_CALL_SURRENDER (surrCtx, surrFlag, 0, callNum)
for (index = 5; index < 1000000; index += 2)
{
/* Step 2: Set g to a value not yet tried.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->IntToMpInt (0, index, temp);
if (status != 0)
break;
/* Step 3: Compute g ^ j mod p
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModExp (temp, expo, primeP, baseG);
if (status != 0)
break;
/* step 4: If g now != 1, we're done, we found our value.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->IntToMpInt (0, 1, temp);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Compare (baseG, temp, &cmpResult);
if (status != 0)
break;
if (cmpResult != 0)
break;
}
} while (0);
if (callNumber != (unsigned int *)0)
*callNumber = callNum;
if (buffer != (unsigned char *)0)
Z2Free (buffer);
mpCtx->DestroyMpInt (¤tP);
mpCtx->DestroyMpInt (&temp);
mpCtx->DestroyMpInt (&expo);
VtDestroyAlgorithmObject (&sha1);
VOLT_LOG_ERROR_COMPARE (
status, (VtLibCtx)libCtx, status, errorType, fnctLine,
"VoltGeneratePQGX942", (char *)0)
return (status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -