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

📄 writeenv.c

📁 voltage 公司提供的一个开发Ibe的工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
   )
{
  int status;
  unsigned int index, encryptedDataLen, encContentInfoLen;
  unsigned int seqLen, expLen, totalLen, tempLen, outputLen, offset;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7WriteEnvCtx *envCtx = (VoltPkcs7WriteEnvCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  unsigned char *temp;
  unsigned char envDataOid[VoltP7EnvDataOidBytesLen] =
    { VoltP7EnvDataOidBytes };
  unsigned char dataOid[VoltP7DataOidBytesLen] = { VoltP7DataOidBytes };

  do
  {
    /* The state must be INIT or UPDATE.
     */
    if (obj->state == VOLT_P7_STATE_ENV_WRITE_INIT)
    {
      /* Check to see if the inputDataLen exceeds the amount specified
       * by calling SetPkcs7Param with the DataLen param.
       */
      status = VT_ERROR_INVALID_INPUT_LENGTH;
      if (inputDataLen > obj->dataLen)
        break;

      /* Determine outputLen. It will be the length of the "prefix"
       * plus the length of the input data.
       * The prefix is the following
       *   30 len                                contentInfo
       *      06 len <EnvelopedData OID>         contentType
       *      A0 len                             EXPLICIT content
       *         30 len                          EnvelopeedData
       *            02 01 00                     version
       *            31 len                       RecipientInfos
       *               <recipients>
       *            30 len                       EncryptedContentInfo
       *               06 len <Data OID>         contentType
       *               30 len <rest of algID>    contentEncryptionAlg
       *               80 len                    IMPLICIT encContent
       */
      /* Work up from the bottom. Start with the A0 len. The length of
       * the encryptedContent might not be the same as the length of
       * the input data itself (because of padding, for example).
       */
      status = VtEncryptInit (envCtx->symEncryptor, envCtx->symKey);
      if (status != 0)
        break;

      /* Call EncryptFinal with no output buffer to get length.
       * For the moment, this does not work with NULL input, so compute
       * it explicitly.
       */
/*      status = VtEncryptFinal (
        envCtx->symEncryptor, random, (unsigned char *)0, obj->dataLen,
        (unsigned char *)0, 0, &encryptedDataLen);
      if (status == 0)
        status = VT_ERROR_GENERAL;
      if (status != VT_ERROR_BUFFER_TOO_SMALL)
        break;
*/
      /* Currently, this code supports only block ciphers in CBC mode
       * with P5 padding. So this is how to compute outputLen.
       */
      encryptedDataLen = obj->dataLen / envCtx->blockSize;
      if (envCtx->blockSize != 1)
        encryptedDataLen++;
      encryptedDataLen *= envCtx->blockSize;

      /* Add in the total length of encrypted data so all other lengths
       * will be computed correctly. Then later on, subtract the amount
       * of encryptedData we will not output.
       */
      outputLen = VoltDetermineDerLengthLen (encryptedDataLen);
      outputLen += (1 + encryptedDataLen);

      /* Add in the symmetric encryption algID and the Data OID.
       * Don't add amounts twice.
       */
      encContentInfoLen =
        outputLen + envCtx->symEncryptorAlgId.len + VoltP7DataOidBytesLen + 2;
      outputLen = VoltDetermineDerLengthLen (encContentInfoLen);
      outputLen += encContentInfoLen + 1;

      /* What is the SET OF for RecipientInfos going to be? Add in the
       * varsion.
       */
      outputLen += VoltDetermineDerLengthLen (envCtx->totalRecipInfoLen);
      outputLen += envCtx->totalRecipInfoLen + 4;

      /* Now add in the SEQUENCE that is the EnvelopedData.
       */
      seqLen = outputLen;
      outputLen += VoltDetermineDerLengthLen (outputLen);
      outputLen++;

      /* Next is the EXPLICIT.
       */
      expLen = outputLen;
      outputLen += VoltDetermineDerLengthLen (outputLen);
      outputLen++;

      /* Add in the EnvelopedData OID.
       */
      outputLen += VoltP7EnvDataOidBytesLen + 2;

      /* Now comes the overall SEQUENCE.
       */
      totalLen = outputLen;
      outputLen += VoltDetermineDerLengthLen (outputLen);
      outputLen++;

      /* If the actual inputLen is not the same as what the total input
       * len is going to be, subtract off the encryptedDataLen, then add
       * the actual inputLen.
       */
      if (inputDataLen != obj->dataLen)
      {
        outputLen -= encryptedDataLen;

        /* For the moment, this does not work with NULL input, so compute
         * it explicitly.
         */
/*        status = VtEncryptUpdate (
          envCtx->symEncryptor, random, (unsigned char *)0, inputDataLen,
          (unsigned char *)0, 0, &tempLen);
        if (status == 0)
          status = VT_ERROR_GENERAL;
        if (status != VT_ERROR_BUFFER_TOO_SMALL)
          break;
 */
        index = inputDataLen / envCtx->blockSize;
        tempLen = index * envCtx->blockSize;

        outputLen += tempLen;
      }

      /* Is the buffer big enough?
       */
      status = VT_ERROR_BUFFER_TOO_SMALL;
      *messageLen = outputLen;
      if (bufferSize < outputLen)
        break;

      /* If the caller passed NULL input with non-zero inputLen, they
       * just wanted the length, don't process.
       */
      if ( (inputData == (unsigned char *)0) && (inputDataLen != 0) )
        break;

      /* The buffer is big enough, write out the prefix.
       * First, the 30 len of the overall contentInfo.
       */
      offset = VoltWriteDerTagAndLen (message, 0x30, totalLen);
      /* Write out the EnvelopedData OID.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x06, VoltP7EnvDataOidBytesLen);
      Z2Memcpy (message + offset, envDataOid, VoltP7EnvDataOidBytesLen);
      offset += VoltP7EnvDataOidBytesLen;
      /* EXPLICIT.
       */
      offset += VoltWriteDerTagAndLen (message + offset, 0xA0, expLen);
      /* SEQUENCE.
       */
      offset += VoltWriteDerTagAndLen (message + offset, 0x30, seqLen);
      /* version (we support only version 0).
       */
      message[offset] = 0x02;
      offset++;
      message[offset] = 0x01;
      offset++;
      message[offset] = 0x00;
      offset++;
      /* SET OF.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x31, envCtx->totalRecipInfoLen);
      /* Write out each of the RecipientInfos.
       */
      for (index = 0; index < envCtx->recipientsCount; ++index)
      {
        if (envCtx->recipients[index].idRef == (VtIdentityObject)0)
          continue;

        status = VT_ERROR_INVALID_INPUT;
        temp = message + offset;
        outputLen = i2d_Asn1RecipientInfo (
          envCtx->recipients[index].recipInfo, &temp);
        if (outputLen != envCtx->recipients[index].recipInfoLen)
          break;

        offset += outputLen;
        status = 0;
      }
      /* Next is the EncryptedContentInfo.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x30, encContentInfoLen);
      /* The OID of the data being encrypted: Data.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x06, VoltP7DataOidBytesLen);
      Z2Memcpy (message + offset, dataOid, VoltP7DataOidBytesLen);
      offset += VoltP7DataOidBytesLen;
      /* The symmetric algorithm ID.
       */
      Z2Memcpy (
        message + offset, envCtx->symEncryptorAlgId.data,
        envCtx->symEncryptorAlgId.len);
      offset += envCtx->symEncryptorAlgId.len;
      /* EncryptedContent, IMPLICIT.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x80, encryptedDataLen);
    }
    else if (obj->state == VOLT_P7_STATE_ENV_WRITE_UPDATE)
    {
      /* If Update, make sure the amount of input does not exceed the
       * dataLen.
       */
      status = VT_ERROR_INVALID_INPUT_LENGTH;
      if ((inputDataLen + obj->inputLen) > obj->dataLen)
        break;

      /* Is the output buffer big enough?
       */
      *messageLen = 0;
      status = 0;
      if (inputDataLen == 0)
        break;

      tempLen = inputDataLen + envCtx->unprocessedDataLen;

      /* If this is the last of the input data, we'll call
       * EncryptFinal, if not, we'll call EncryptUpdate.
       */
      if ((inputDataLen + obj->inputLen) < obj->dataLen)
      {
        /* For the moment, this does not work with NULL input, so
         * compute the required output size explicitly.
         */
/*        status = VtEncryptUpdate (
          envCtx->symEncryptor, random, (unsigned char *)0, inputDataLen,
          (unsigned char *)0, 0, &tempLen);
 */
        index = tempLen / envCtx->blockSize;
        tempLen = index * envCtx->blockSize;
        status = VT_ERROR_BUFFER_TOO_SMALL;
      }
      else
      {
        /* For the moment, this does not work with NULL input, so
         * compute the required output size explicitly.
         */
/*        status = VtEncryptFinal (
          envCtx->symEncryptor, random, inputData, inputDataLen,
          (unsigned char *)0, 0, &tempLen);
 */
        index = tempLen / envCtx->blockSize;
        if (envCtx->blockSize != 1)
          index++;
        tempLen = index * envCtx->blockSize;
        status = VT_ERROR_BUFFER_TOO_SMALL;
      }
      if (status == 0)
        status = VT_ERROR_GENERAL;
      if (status != VT_ERROR_BUFFER_TOO_SMALL)
        break;

      *messageLen = tempLen;
      if (bufferSize < tempLen)
        break;

      /* If the caller passed NULL input with non-zero inputLen, they
       * just wanted the length, don't process.
       */
      if ( (inputData == (unsigned char *)0) && (inputDataLen != 0) )
        break;

      offset = 0;
    }
    else
    {
      status = VT_ERROR_INVALID_CALL_ORDER;
      break;
    }

    /* Encrypt the bytes given.
     */
    if ((inputDataLen + obj->inputLen) < obj->dataLen)
    {
      /* For the moment we need to compute unprocessedDataLen. When we
       * fix the NULL input issue, we can get rid of this.
       */
      tempLen = inputDataLen + envCtx->unprocessedDataLen;
      index = tempLen / envCtx->blockSize;
      envCtx->unprocessedDataLen = tempLen - (index * envCtx->blockSize);
      status = VtEncryptUpdate (
        envCtx->symEncryptor, random, inputData, inputDataLen,
        message + offset, bufferSize - offset, &tempLen);
    }
    else
    {
      envCtx->unprocessedDataLen = 0;
      status = VtEncryptFinal (
        envCtx->symEncryptor, random, inputData, inputDataLen,
        message + offset, bufferSize - offset, &tempLen);
    }
    if (status != 0)
      break;

    obj->inputLen += inputDataLen;

    obj->state = VOLT_P7_STATE_ENV_WRITE_UPDATE;

  } while (0);

  return (status);
}

int VoltP7EnvWriteFinal (
   VtPkcs7Object pkcs7Obj,
   VtRandomObject random,
   unsigned char *inputData,
   unsigned int inputDataLen,
   unsigned char *message,
   unsigned int bufferSize,
   unsigned int *messageLen
   )
{
  int status;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;

  *messageLen = 0;

⌨️ 快捷键说明

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