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

📄 readenv.c

📁 voltage 公司提供的一个开发Ibe的工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright 2003-2005, Voltage Security, all rights reserved.
 */
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "p7obj.h"
#include "reciplist.h"

/* Build an Asn1RecipientInfo object from the encoding, then add it to
 * the list of recipInfos in the readCtx. This function will grow the
 * array of recipInfos, if necessary.
 * <p>This function will also add the identity represented by the
 * recipientInfo to the identity list in the readCtx.
 */
static int VOLT_CALLING_CONV AddRecipientInfoToList VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   VoltPkcs7ReadEnvCtx *readCtx,
   unsigned char *recipInfoDer,
   unsigned int recipInfoDerLen
));

/* The readCtx contains a private key with which to decrypt the session
 * key. It also contains the index of the chosen recipient. Go into the
 * RecipientInfo of that index to find the algorithm to use (algID) and
 * the encrypted key data. Decrypt the data and store it in the
 * symKeyData field of the readCtx.
 */
static int VOLT_CALLING_CONV DecryptSessionKeyData VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   VoltPkcs7Object *obj,
   VoltPkcs7ReadEnvCtx *readCtx
));

int VoltP7ReadEnvelopedInit (
   VtPkcs7Object pkcs7Obj
   )
{
  int status;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7ReadEnvCtx *readCtx = (VoltPkcs7ReadEnvCtx *)(obj->localCtx);
  VtBase64Info base64Info;

  do
  {
    /* The state must be VOLT_P7_STATE_ENV_READ_SET, if not, we're
     * not allowed to call ReadInit.
     */
    status = VT_ERROR_INVALID_CALL_ORDER;
    if (obj->state != VOLT_P7_STATE_ENV_READ_SET)
      break;

    /* Build a Base64 object, we'll need it later and we might as build
     * one, rather than building a new one again and again.
     */
    base64Info.base64BlockSize = 76;
    base64Info.newLineCharacter = VT_BASE64_NO_NEW_LINE;
    base64Info.errorCheck = VT_BASE64_NO_ERROR_CHECK;
    status = VtCreateAlgorithmObject (
      obj->voltObject.libraryCtx, VtAlgorithmImplBase64, (Pointer)&base64Info,
      &(readCtx->base64));
    if (status != 0)
      break;

    /* Create an empty identityList, we'll need it later.
     */
    status = VtCreateIdentityList (
      obj->voltObject.libraryCtx, VtIdentityListImplMpCtx,
      (Pointer)(readCtx->mpCtx), &(readCtx->recipList));
    if (status != 0)
      break;

    /* Set the state to INIT.
     */
    obj->state = VOLT_P7_STATE_ENV_READ_INIT;
    status = 0;

  } while (0);

  return (status);
}

int VoltP7ReadEnvelopedUpdate (
   VtPkcs7Object pkcs7Obj,
   unsigned char *message,
   unsigned int messageLen,
   unsigned int *bytesRead,
   unsigned char *outputData,
   unsigned int bufferSize,
   unsigned int *outputDataLen
   )
{
  int status;
  unsigned int index, offset, lengthLen, valueLen, messageRead, algorithm;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7ReadEnvCtx *readCtx = (VoltPkcs7ReadEnvCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VtKeyObject symKey = (VtKeyObject)0;
  VoltDerElement *derElement = &(readCtx->currentElement);
  VtSetAlgIdInfo algIdInfo;
  VtDerCoderInfo coderInfo;
  unsigned char p7Oid[VoltP7EnvDataOidBytesLen] = { VoltP7EnvDataOidBytes };

  *bytesRead = 0;
  *outputDataLen = 0;

  switch (obj->state)
  {
    default:
      status = VT_ERROR_INVALID_CALL_ORDER;
      break;

    case VOLT_P7_STATE_ENV_READ_COMPLETE:
      /* If we're done, don't read anything.
       */
      status = 0;
      break;

    case VOLT_P7_STATE_ENV_READ_INIT:
      /* The first thing to do is read the ContentInfo SEQUENCE.
       * "Cheat" a little bit and set the explicitTag to the outer
       * SEQUENCE, then we can capture the SEQUENCE and the OID at the
       * same time.
       */
      obj->state = VOLT_P7_STATE_ENV_READ_ED_OID;

    case VOLT_P7_STATE_ENV_READ_ED_OID:
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, VOLT_SEQUENCE_TAG, VOLT_OID_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Is this the SignedData OID?
       */
      status = VT_ERROR_INVALID_ENCODING;
      offset = derElement->elementLen - derElement->tlvLen;
      if (derElement->tlvLen != VoltP7EnvDataOidBytesLen)
        break;
      if (Z2Memcmp (
        p7Oid, derElement->element + offset, VoltP7EnvDataOidBytesLen) != 0)
        break;

      /* Move on to the next element.
       */
      status = 0;
      obj->state = VOLT_P7_STATE_ENV_READ_EXP;

      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);
      if (messageLen == 0)
        break;

    case VOLT_P7_STATE_ENV_READ_EXP:
      /* We now have the EnvelopedData. It starts with the EXPLICIT.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0xA0, VOLT_SEQUENCE_TAG, 0,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Move on to the next element.
       */
      obj->state = VOLT_P7_STATE_ENV_READ_VERSION;

      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);
      if (messageLen == 0)
        break;

    case VOLT_P7_STATE_ENV_READ_VERSION:
      /* Now it's the version.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0, VOLT_INTEGER_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Is this the expected version?
       */
      status = VT_ERROR_UNSUPPORTED;
      if (derElement->tlvLen != 1)
        break;

      offset = derElement->elementLen - derElement->tlvLen;
      if (derElement->element[offset] != 0)
        break;

      /* Move on to the next element.
       */
      status = 0;
      obj->state = VOLT_P7_STATE_ENV_READ_RI_LEN;

      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);
      if (messageLen == 0)
        break;

    case VOLT_P7_STATE_ENV_READ_RI_LEN:
      /* The next element is the SET OF RecipientInfos. Get the SET OF
       * length.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0, VOLT_SET_TAG, 0,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Keep the length around so we know when we have no more
       * RecipientInfos.
       */
      readCtx->currentLen = derElement->tlvLen;

      /* Move on to the next element.
       */
      obj->state = VOLT_P7_STATE_ENV_READ_RI_DATA;

      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);
      if (messageLen == 0)
        break;

VoltP7StateSignReadRiData:
    case VOLT_P7_STATE_ENV_READ_RI_DATA:
      /* Read in the next RecipientInfo.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0, VOLT_SEQUENCE_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* We kept the total length of all the RecipientInfos, now that
       * we've read one, subtract its length from the total.
       */
      readCtx->currentLen -= derElement->elementLen;

      /* Add this RecipientInfo to the list of RecipientInfos.
       * If this subroutine can't decode the identity, just ignore it.
       * So if the error is INVALID_ENCODING or UNKNOWN_SCHEMA, don't
       * bail, just move on. Return other errors, but if there's an
       * unknown identity, it's probably not one the app is interest in.
       */
      status = AddRecipientInfoToList (
        libCtx, readCtx, derElement->element, derElement->elementLen);
      if ( (status == VT_ERROR_INVALID_ENCODING) ||
           (status == VT_ERROR_UNKNOWN_SCHEMA) )
        status = 0;
      if (status != 0)
        break;

      /* Move on to the next element.
       */
      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);

      /* There may be more RecipientInfos, check readCtx->currentLen to
       * see. If there are no more, move on to PREPARE_ENC, whether or
       * not there is more message to read. If there are more
       * recipientInfos, make sure there's still more message, then go
       * back to the start of this state.
       * Note from the programmer: Notice the goto statement.
       * Normally I don't like them, but in this case it really works.
       */
      if (readCtx->currentLen != 0)
      {
        if (messageLen == 0)
          break;
        goto VoltP7StateSignReadRiData;
      }

      /* If that was the last RecipientInfo, make sure we were actually
       * able to read at least one, then set the state to indicate
       * we're moving on to the next element.
       */
      status = VT_ERROR_NO_ID_IN_P7_MESSAGE;
      if (readCtx->recipInfoCount == 0)
        break;

      obj->state = VOLT_P7_STATE_ENV_READ_PREPARE_ENC;

    case VOLT_P7_STATE_ENV_READ_PREPARE_ENC:
      /* In order to read the encrypted content, we need the decryption
       * object and decryption key. In order to get the decryption key
       * we need to decrypt the encrypted key from one of the
       * recipientInfos. If we have one chosen, decrypt. If not, we may
       * be able to choose one if we have the private key to use
       * already.
       */
      status = VT_ERROR_CHOOSE_RECIPIENT;
      if (readCtx->chosenRecipient < 0)
      {
        if (readCtx->priKeyRef == (VtKeyObject)0)
          break;

        /* We have a private key. Which identity belongs to that
         * private key? We have to go through the recipInfos to find
         * the ID matching the one passed in with the private key.
         */
        status = VoltFindIdInList (
          libCtx, readCtx->specifiedIdentity, readCtx->recipList, &index);
        if (status != 0)
          break;

        /* Set the chosen recipient.
         */
        readCtx->chosenRecipient = (int)index;
      }

      /* Build the symmetric decryption alg object and the symmetric
       * key. This call will need to decrypt the session key in the
       * RecipientInfo of the chosen recipient.
       */
      status = DecryptSessionKeyData (libCtx, obj, readCtx);
      if (status != 0)
        break;

      /* We have the session key data, set the state so we'll read
       * encrypted content. Then check to see if there's any message to
       * read.
       */
      obj->state = VOLT_P7_STATE_ENV_READ_ENC_CONTENT;
      if (messageLen == 0)
        break;

    case VOLT_P7_STATE_ENV_READ_ENC_CONTENT:
      /* The first part of encrypted content is the SEQUENCE then an
       * OID. "Cheat" by reading the SEQUENCE as the explicitTag.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, VOLT_SEQUENCE_TAG, VOLT_OID_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Is this the Data OID?
       * First, set the buffer containing the OID to hold the Data OID.
       */
      status = VT_ERROR_UNSUPPORTED;
      p7Oid[VoltP7SignDataOidBytesLen - 1] = VOLT_P7_OID_BYTE_DATA;
      offset = derElement->elementLen - derElement->tlvLen;
      if (derElement->tlvLen != VoltP7EnvDataOidBytesLen)
        break;
      if (Z2Memcmp (
        p7Oid, derElement->element + offset, VoltP7EnvDataOidBytesLen) != 0)
        break;

      /* Move on to the next element.
       */
      status = 0;
      obj->state = VOLT_P7_STATE_ENV_READ_SYM_ALG_ID;

      message += messageRead;
      messageLen -= messageRead;
      VoltResetDerElement (derElement);
      if (messageLen == 0)
        break;

    case VOLT_P7_STATE_ENV_READ_SYM_ALG_ID:
      /* Read the symmetric algID.
       */
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0, VOLT_SEQUENCE_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

      *bytesRead += messageRead;
      if (derElement->complete == 0)
        break;

      /* Build an algorithm object using the algId in the RecipientInfo.
       */
      algIdInfo.derCoders = readCtx->DerCoders;
      algIdInfo.derCoderCount = readCtx->derCoderCount;
      algIdInfo.berEncoding = derElement->element;
      algIdInfo.maxEncodingLen = derElement->elementLen;
      status = VtCreateAlgorithmObject (
        (VtLibCtx)libCtx, VtAlgorithmImplAlgId, (Pointer)&algIdInfo,
        &(readCtx->decryptor));
      if (status != 0)
        break;

      /* Get the KeyParam to use when building a key object. Do this by
       * calling the DerCoder's asking for the algorithm.
       */
      offset = derElement->elementLen - derElement->tlvLen;
      status = VoltDecodeDerLength (
        derElement->element + offset, derElement->elementLen - offset,
        &lengthLen, &valueLen);
      coderInfo.info.getAlgData.libCtx = libCtx;
      coderInfo.info.getAlgData.oid =
        derElement->element + offset + lengthLen + 1;
      coderInfo.info.getAlgData.oidLen = valueLen;

⌨️ 快捷键说明

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