📄 rsakgimpl.c
字号:
/* Copyright 2005-2006, Voltage Security, all rights reserved.
*/
#include "vibecrypto.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "keyobj.h"
#include "rsa.h"
#include "mpint.h"
#include "prime.h"
#include "fipsmodule.h"
#include "surrender.h"
#include "errorctx.h"
/* Set the given public key object with the info from the rsaGenCtx.
* <p>This function does no arg checking, it is the responsibility of
* the caller not to make mistakes.
*
* @param libCtx The library context to use.
* @param rsaGenCtx The Key Gen context, contains the modulus and
* public exponent.
* @param pubKey The created but empty object to set.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV SetRSAPubKeyObject VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltRsaKeyGenCtx *rsaGenCtx,
VtKeyObject pubKey
));
/* Set the given private key object with the info from the rsaGenCtx.
* <p>This function does no arg checking, it is the responsibility of
* the caller not to make mistakes.
*
* @param libCtx The library context to use.
* @param rsaGenCtx The Key Gen context, contains the modulus, private
* exponent, and CRT info.
* @param priKey The created but empty object to set.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV SetRSAPriKeyObject VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltRsaKeyGenCtx *rsaGenCtx,
VtKeyObject priKey
));
int RSAGenerateKeyPair (
VtKeyObject priKey,
VtKeyObject pubKey,
VtRandomObject random
)
{
int status, cmpResult;
unsigned int sign, count, bitLen, callNum;
VoltKeyObject *priObj = (VoltKeyObject *)priKey;
VoltKeyObject *pubObj = (VoltKeyObject *)pubKey;
VoltLibCtx *libCtx = (VoltLibCtx *)(priObj->voltObject.libraryCtx);
VoltMpIntCtx *mpCtx = priObj->mpCtx;
VoltRsaKeyGenCtx *rsaGenCtx = (VoltRsaKeyGenCtx *)(priObj->localGenerateCtx);
VtRandomObject randomToUse;
VoltMpInt *prime1 = (VoltMpInt *)0;
VoltMpInt *prime2 = (VoltMpInt *)0;
VoltMpInt *pubExpo = (VoltMpInt *)0;
VoltMpInt *priExpo = (VoltMpInt *)0;
VoltMpInt *modulus = (VoltMpInt *)0;
VoltMpInt *lambda = (VoltMpInt *)0;
VoltMpInt *expo1 = (VoltMpInt *)0;
VoltMpInt *expo2 = (VoltMpInt *)0;
VoltMpInt *coeff = (VoltMpInt *)0;
VoltMpInt *temp;
VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* 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;
/* If there's a surrender ctx, call the Surrender function.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_GET_OBJECT_SURR_CTX (surrCtx, priObj);
/* If the surrender ctx is not in the private key, look in the
* public key.
*/
if (surrCtx == (VoltSurrenderCtx *)0)
VOLT_GET_OBJECT_SURR_CTX (surrCtx, pubObj);
callNum = 1;
VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_RSA_KEY_GEN, 0, callNum)
/* Build an mpInt out of the pubExpo to use when checking for
* relative prime.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &pubExpo);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->OctetStringToMpInt (
0, rsaGenCtx->pubExpo.data, rsaGenCtx->pubExpo.len, pubExpo);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &prime1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &prime2);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &modulus);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &lambda);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &priExpo);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &expo1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &expo2);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &coeff);
if (status != 0)
break;
count = 0;
do
{
/* It's very unlikely that we won't be able to find a key pair,
* but just to make sure we don't end up in an infinite loop, put
* this check here.
*/
VOLT_SET_FNCT_LINE (fnctLine)
count++;
status = VT_ERROR_BAD_KEY_GEN;
if (count > 100)
break;
callNum++;
VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_RSA_KEY_GEN, 0, callNum)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGeneratePrimeX931 (
rsaGenCtx->prime1Bits, randomToUse, surrCtx,
VT_SURRENDER_FNCT_RSA_KEY_GEN, &callNum, pubExpo, prime1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGeneratePrimeX931 (
rsaGenCtx->prime2Bits, randomToUse, surrCtx,
VT_SURRENDER_FNCT_RSA_KEY_GEN, &callNum, pubExpo, prime2);
if (status != 0)
break;
/* Make sure prime1 > prime2
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Compare (prime1, prime2, &cmpResult);
if (status != 0)
break;
/* This is not likely to happen, but what the heck, let's check
* for it.
*/
if (cmpResult == 0)
continue;
/* If prime1 < prime2, swap them.
*/
if (cmpResult < 0)
{
temp = prime1;
prime1 = prime2;
prime2 = temp;
}
/* X9.31 requires that the primes be sufficiently far apart.
* Use coeff as a temp variable.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (prime1, prime2, coeff);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->GetBitLength (coeff, &bitLen);
if (status != 0)
break;
if (bitLen < (rsaGenCtx->prime1Bits - 98))
continue;
/* Now that we have two primes, find the modulus and private
* exponent.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Multiply (prime1, prime2, modulus);
if (status != 0)
break;
/* We need LCM [ (p - 1), (q - 1) ].
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (prime1, 0, 0);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (prime2, 0, 0);
if (status != 0)
break;
/* Find phi, then GCD ( p-1, q-1 )
* Use expo1 and expo2 as temp variables.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Multiply (prime1, prime2, expo1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->GCD (prime1, prime2, expo2);
if (status != 0)
break;
/* The private expo is e inverse mod phi.
* Or the private expo is e inverse mod LCM(p-1,q-1).
* phi = (p-1)*(q-1) and the LCM (lambda) is phi / GCD(p-1,q-1)
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Divide (expo1, expo2, lambda, coeff);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModInvert (pubExpo, lambda, priExpo);
if (status != 0)
{
if (status == VT_ERROR_NO_INVERSE)
continue;
break;
}
/* Get the bit length of the priExpo, X9.31 says d must be at
* least half as long as the modulus.
* Use sign as a temp variable.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->GetBitLength (priExpo, &bitLen);
if (status != 0)
break;
sign = rsaGenCtx->prime1Bits + rsaGenCtx->prime2Bits;
sign >>= 1;
if (bitLen < sign)
continue;
/* Now compute the CRT values. First are the two exponents.
* expo1 = priExpo mod (p - 1)
* expo2 = priExpo mod (q - 1)
* Note that the contents of prime1 and prime2 are (p - 1) and
* (q - 1), that was to compute phi.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModReduce (priExpo, prime1, expo1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModReduce (priExpo, prime2, expo2);
if (status != 0)
break;
/* We no longer have use for (p - 1) and (q - 1). In fact, we need
* p and q to compute the coefficient.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (prime1, 0, 1);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->SetBit (prime2, 0, 1);
if (status != 0)
break;
/* Compute the CRT coefficient, it is q inverse mod p.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModInvert (prime2, prime1, coeff);
break;
} while (1);
if (status != 0)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -