⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rsakgimpl.c

📁 IBE是一种非对称密码技术
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -