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

📄 rsaencimpl.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 "algobj.h"
#include "cipher.h"
#include "rsa.h"
#include "mpint.h"
#include "errorctx.h"
#include "surrender.h"

int RSAEncryptGetOutputSize (
   VoltAlgorithmObject *obj,
   unsigned int callFlag,
   unsigned char *input,
   unsigned int inputLen,
   unsigned int *outputSize,
   unsigned int *leftovers,
   VtRandomObject random
   )
{
  int status;
  unsigned int totalLen, blockCount;
  VoltCipherClassCtx *cipherCtx = (VoltCipherClassCtx *)(obj->classCtx);
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  totalLen = inputLen + cipherCtx->unprocessedDataLen;
  status = 0;

  switch (callFlag)
  {
    case VOLT_CALLER_ENCRYPT_UPDATE:
      /* If there's padding, we're not allowed to call this function.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      if (cipherCtx->Pad != (VPad)0)
        status = VT_ERROR_INVALID_CALL_ORDER;

      /* How many blocks of input? That's how many blocks of output,
       * then multiply by the block size to get the total length.
       * The leftovers consist of data after the full blocks. However,
       * don't count any data in the unprocessedData buffer. The first
       * leftovers computation is the leftovers of the totalLen. If the
       * totalLen does not make up one block, we need to adjust to
       * count only the new bytes.
       */
      blockCount = totalLen / cipherCtx->plainBlockSize;
      *outputSize = blockCount * cipherCtx->cipherBlockSize;
      *leftovers = totalLen - (blockCount * cipherCtx->plainBlockSize);
      if (inputLen < *leftovers)
        *leftovers = inputLen;
      break;

    case VOLT_CALLER_ENCRYPT_FINAL:
      /* If there's padding, the outputSize will be one block and the
       * entire input len will be leftovers. We only allow one total
       * block of input, though, so make sure we don't have more.
       */
      if (cipherCtx->Pad != (VPad)0)
      {
        VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
        VOLT_SET_FNCT_LINE (fnctLine)
        if (totalLen >= cipherCtx->plainBlockSize)
          status = VT_ERROR_INVALID_INPUT_LENGTH;

        *outputSize = cipherCtx->cipherBlockSize;
        *leftovers = inputLen;
        break;
      }

      /* If no padding, input and output are the same, the input must
       * be a multiple of the block size.
       */
      blockCount = totalLen / cipherCtx->plainBlockSize;
      *outputSize = blockCount * cipherCtx->cipherBlockSize;
      *leftovers = 0;
      totalLen -= (blockCount * cipherCtx->plainBlockSize);

      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      if (totalLen != 0)
        status = VT_ERROR_INVALID_INPUT_LENGTH;

      break;

    case VOLT_CALLER_DECRYPT_UPDATE:
      /* If there's padding, we're not allowed to call this function.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      if (cipherCtx->Unpad != (VUnpad)0)
        status = VT_ERROR_INVALID_CALL_ORDER;

      /* How many blocks of input? That's how many blocks of output,
       * then multiply by the block size to get the total length.
       * The leftovers consist of data after the full blocks. However,
       * don't count any data in the unprocessedData buffer. The first
       * leftovers computation is the leftovers of the totalLen. If the
       * totalLen does not make up one block, we need to adjust to
       * count only the new bytes.
       */
      blockCount = totalLen / cipherCtx->cipherBlockSize;
      *outputSize = blockCount * cipherCtx->plainBlockSize;
      *leftovers = totalLen - (blockCount * cipherCtx->cipherBlockSize);
      if (inputLen < *leftovers)
        *leftovers = inputLen;
      break;

    case VOLT_CALLER_DECRYPT_FINAL:
      /* If there's padding, the outputSize will be at most one block
       * and the entire block will be leftovers (to strip padding). We
       * only allow one total block of input, though, so make sure we
       * don't have more.
       */
      if (cipherCtx->Unpad != (VUnpad)0)
      {
        VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
        VOLT_SET_FNCT_LINE (fnctLine)
        if (totalLen != cipherCtx->cipherBlockSize)
          status = VT_ERROR_INVALID_INPUT_LENGTH;

        /* After padding, the output will be less, but we don't know
         * until decrypting, so this is the max output length.
         */
        *outputSize = cipherCtx->plainBlockSize;
        *leftovers = cipherCtx->plainBlockSize;
        break;
      }

      /* If no padding, input and output are the same, the input must
       * be a multiple of the block size.
       */
      blockCount = totalLen / cipherCtx->cipherBlockSize;
      *outputSize = blockCount * cipherCtx->plainBlockSize;
      *leftovers = 0;
      totalLen -= (blockCount * cipherCtx->cipherBlockSize);

      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      if (totalLen != 0)
        status = VT_ERROR_INVALID_INPUT_LENGTH;

      break;

    default:
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_CALL_ORDER;
  }

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, obj, status, 0, errorType,
    (char *)0, "RSAEncryptGetOutputSize", fnctLine, (char *)0)

  return (status);
}

int RSAEncryptInit (
   VoltAlgorithmObject *algObj,
   VoltKeyObject *keyObj
   )
{
  int status;
  unsigned int blockSize;
  VoltCipherClassCtx *cipherCtx = (VoltCipherClassCtx *)(algObj->classCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(algObj->voltObject.libraryCtx);
  VtRSAPubKeyInfo *getKeyInfo;
  VoltRsaPublicKey *newData;
  VoltMpIntCtx *mpCtx;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  do
  {
    /* Make sure the key matches the algorithm object.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_INVALID_KEY_OBJ;
    if ((keyObj->keyType & VOLT_KEY_TYPE_MASK_ASYM_ALG) != VOLT_KEY_ALG_RSA)
      break;

    /* Only a public key is allowed to encrypt.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    if ((keyObj->keyType & VOLT_KEY_TYPE_PUBLIC) == 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    if (keyObj->mpCtx == (VoltMpIntCtx *)0)
      break;

    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtGetKeyParam (
      (VtKeyObject)keyObj, VtKeyParamRSAPublicEncrypt, (Pointer *)&getKeyInfo);
    if (status != 0)
      break;

    /* If there's a localCipherCtx, get rid of it.
     */
    if ( (cipherCtx->localCipherCtx != (Pointer)0) &&
         (cipherCtx->LocalCipherCtxDestroy != (VCtxDestroy)0) )
      cipherCtx->LocalCipherCtxDestroy (
        (Pointer)algObj, cipherCtx->localCipherCtx);

    cipherCtx->localCipherCtx = (Pointer)0;
    cipherCtx->LocalCipherCtxDestroy = (VCtxDestroy)0;

    /* Clone the mpCtx.
     */
    if (algObj->mpCtx != (VoltMpIntCtx *)0)
      VtDestroyMpIntCtx ((VtMpIntCtx *)&(algObj->mpCtx));

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtCloneObject (
      (Pointer)(keyObj->mpCtx), (Pointer *)&(algObj->mpCtx));
    if (status != 0)
      break;

    mpCtx = algObj->mpCtx;

    /* Clear the cipherCtx for a new Init.
     */
    cipherCtx->unprocessedDataLen = 0;
    cipherCtx->plainBlockSize = 0;
    cipherCtx->cipherBlockSize = 0;

    /* Copy the key data over to the cipherCtx.
     * First, we need the struct that holds the elements.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    cipherCtx->localCipherCtx = Z2Malloc (sizeof (VoltRsaPublicKey), 0);
    if (cipherCtx->localCipherCtx == (Pointer)0)
      break;
    Z2Memset (cipherCtx->localCipherCtx, 0, sizeof (VoltRsaPublicKey));

    cipherCtx->LocalCipherCtxDestroy = RSAKeyDataDestroy;
    newData = (VoltRsaPublicKey *)(cipherCtx->localCipherCtx);
    newData->type = VOLT_KEY_TYPE_PUBLIC;

    /* Create the mpInts.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &(newData->modulus));
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &(newData->pubExpo));
    if (status != 0)
      break;

    /* Copy the values.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->OctetStringToMpInt (
      0, getKeyInfo->modulus.data, getKeyInfo->modulus.len, newData->modulus);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->OctetStringToMpInt (
      0, getKeyInfo->pubExpo.data, getKeyInfo->pubExpo.len, newData->pubExpo);
    if (status != 0)
      break;

    /* Get the block size. We're expecting BUFFER_TOO_SMALL.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->GetBitLength (newData->modulus, &blockSize);
    if (status != 0)
      break;

    blockSize = (blockSize + 7) / 8;

    cipherCtx->plainBlockSize = blockSize;
    cipherCtx->cipherBlockSize = blockSize;

    /* We need the unprocessedData buffer to be blockSize bytes big.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    cipherCtx->unprocessedData = (unsigned char *)Z2Realloc (
      cipherCtx->unprocessedData, blockSize);
    if (cipherCtx->unprocessedData == (unsigned char *)0)
      break;

    status = 0;

  } while (0);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, algObj, status, 0, errorType,
    (char *)0, "RSAEncryptInit", fnctLine, (char *)0)

  return (status);
}

int RSAEncryptUpdate (
   VoltAlgorithmObject *algObj,
   VtRandomObject random,
   unsigned char *dataToEncrypt,
   unsigned int dataToEncryptLen,
   unsigned char *encryptedData
   )
{
  int status;
  unsigned int blockSize, outputLen, sign;
  VoltCipherClassCtx *cipherCtx = (VoltCipherClassCtx *)(algObj->classCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(algObj->voltObject.libraryCtx);
  VoltRsaPublicKey *keyData = (VoltRsaPublicKey *)(cipherCtx->localCipherCtx);
  VoltMpIntCtx *mpCtx;
  VoltMpInt *base = (VoltMpInt *)0;
  VoltMpInt *result = (VoltMpInt *)0;
  VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  do
  {
    /* If there's a surrender ctx, call the Surrender function.
     */
    VOLT_GET_OBJECT_SURR_CTX (surrCtx, algObj);
    VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_RSA_ENCRYPT, 3, 1)

    mpCtx = keyData->modulus->mpCtx;
    blockSize = cipherCtx->plainBlockSize;

    /* Create mpInts to hold the data to encrypt and the encrypted data.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &base);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &result);
    if (status != 0)
      break;

    while (dataToEncryptLen >= blockSize)
    {
      /* Get the block of data as an mpInt.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->OctetStringToMpInt (0, dataToEncrypt, blockSize, base);
      if (status != 0)
        break;

      VOLT_CALL_SURRENDER (surrCtx, VT_SURRENDER_FNCT_RSA_ENCRYPT, 3, 2)

      /* Encryption is modExp.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->ModExp (
        base, keyData->pubExpo, keyData->modulus, result);
      if (status != 0)
        break;

      /* Place the result as an octet string into the output buffer.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->MpIntToOctetString (
        result, &sign, encryptedData, blockSize, &outputLen);
      if (status != 0)
        break;

      /* If the outputLen < blockSize, we want to prepend 00 bytes.
       */
      if (outputLen < blockSize)
      {
        /* Use sign as a temp variable.
         */
        sign = blockSize - outputLen;
        Z2Memmove (encryptedData + sign, encryptedData, outputLen);
        Z2Memset (encryptedData, 0, sign);
      }

      dataToEncryptLen -= blockSize;
      dataToEncrypt += blockSize;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -