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

📄 readsign.c

📁 IBE是一种非对称密码技术
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
 */
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "p7obj.h"
#include "certobj.h"
#include "vcert.h"
#include "certvfyctx.h"
#include "vfylist.h"
#include "distobj.h"
#include "vtime.h"
#include "digest.h"
#include "errorctx.h"

/* Decode each of the attributes in the authAttributes field of the
 * given signerInfo. This function will build an array of
 * Asn1P9Attribute pointers, as many pointers as are authenticate
 * attributes. It will then create (Asn1P9Attribute_new) the objects
 * and decode (d2i_Asn1P9Attribute) each of the attributes. It will
 * return the array and the count.
 * <p>The caller must destroy each of the objects (Asn1P9Attribute_free)
 * and free the memory that is the array.
 *
 * @param libCtx The libCtx to use.
 * @param signerInfo The specific signerInfo from which the
 * authenticated attributes are to be extracted.
 * @param attributes The address where this function will deposit the
 * created array.
 * @param attributeCount The address where this function will deposit
 * the number of Asn1P9Attribute objects it created.
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV DecodeAuthAttributesAlloc VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   Asn1SignerInfo *signerInfo,
   Asn1P9Attribute ***attributes,
   unsigned int *attributeCount
));

/* This function finds the attribute in the array that matches the
 * given flag, then compares the value in the attribute object with the
 * given baseValue. If there is no attribute to match or if the value
 * does not compare equally to the baseValue, the routine sets
 * verifyResult to FALSE.
 * <p>This function also expects that the attribute has only one value
 * (a P9 attribute is actually a SET OF values) and that the value is
 * an "atomic" ASN.1 type (an OID or OCTET STRING, for example).
 * <p>The flag indicates what to look for. Currently, the following are
 * supported.
 * <pre>
 * <code>
 *   VOLT_P9_ATTRIBUTE_CONTENT_TYPE
 *   VOLT_P9_ATTRIBUTE_DIGEST
 * </code>
 * </pre>
 * <p>This function will set the verifyResult to 0 if it does not
 * verify, but will not set it to nonzero if it does. That is, the
 * caller must initialize the value to 1. This is so that a series of
 * calls to this function can be cumulative, so that it is possible to
 * call this function more than once to verify several attributes. If
 * one fails and the next succeeds, the success will not overwrite the
 * failure.
 *
 * @param libCtx The libCtx to use.
 * @param flag What attribute to search for.
 * @param attributes The array to search.
 * @param attributeCount The number of attributes in the array.
 * @param baseValue The value to match.
 * @param baseValueLen The length, in bytes, of the baseValue.
 * @param vfyFailList The VerifyFailureList to use if the verification
 * fails.
 * @param verifyResult The address where the function will place the
 * verification result (0 for FALSE, does not verify; and nonzero for
 * TRUE, verifies)
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV VerifyAuthAttribute VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   unsigned int flag,
   Asn1P9Attribute **attributes,
   unsigned int attributeCount,
   unsigned char *baseValue,
   unsigned int baseValueLen,
   VtVerifyFailureList vfyFailList,
   unsigned int *verifyResult
));

#define VOLT_P9_ATTRIBUTE_CONTENT_TYPE  3
#define VOLT_P9_ATTRIBUTE_DIGEST        4

/* This function looks through the array of attributes until finding
 * the one with the given OID. If it can't find an attribute with that
 * OID, it returns the INVALID_ENCODING_ERROR.
 * <p>The function sets the unsigned int at the address index to the
 * index in the array of the attribute with the matching OID.
 * <p>This function does no arg checking, it assumes a valid array and
 * valid OID to check.
 *
 * @param libCtx The libCtx to use.
 * @param oid The OID to match.
 * @param oidLen The length, in bytes, of the OID.
 * @param attributes The array to search.
 * @param attributeCount The number of attributes in the array.
 * @param index The address where the routine will deposit the index
 * into the array of the attribute with the matching OID.
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV FindAuthAttribute VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   unsigned char *oid,
   unsigned int oidLen,
   Asn1P9Attribute **attributes,
   unsigned int attributeCount,
   unsigned int *index
));

/* Build a cert object from the encoding, then add it to the list of
 * msgCerts in the readCtx. This function will grow the array of
 * msgCerts, if necessary.
 */
static int VOLT_CALLING_CONV AddCertToList VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   VoltPkcs7ReadSignCtx *readCtx,
   unsigned char *certDer,
   unsigned int certDerLen
));

/* Build a SignerInfo object from the encoding, then add it to the
 * list of signerInfos in the readCtx. This function will grow the
 * array of signerInfos, if necessary.
 */
static int VOLT_CALLING_CONV AddSignerInfoToList VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   VoltPkcs7ReadSignCtx *readCtx,
   unsigned char *encoding,
   unsigned int encodingLen
));

int VoltP7ReadSignedInit (
   VtPkcs7Object pkcs7Obj
   )
{
  int status;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VOLT_DECLARE_FNCT_LINE (fnctLine)

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

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

  } while (0);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, pkcs7Obj, status, 0, VT_ERROR_TYPE_PRIMARY,
    (char *)0, "VoltP7ReadSignedInit", fnctLine, (char *)0)

  return (status);
}

int VoltP7ReadSignedUpdate (
   VtPkcs7Object pkcs7Obj,
   unsigned char *message,
   unsigned int messageLen,
   unsigned int *bytesRead,
   unsigned char *outputData,
   unsigned int bufferSize,
   unsigned int *outputDataLen
   )
{
  int status;
  unsigned int messageRead, length;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7ReadSignCtx *readCtx = (VoltPkcs7ReadSignCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VoltDerElement *derElement = &(readCtx->currentElement);
  unsigned char p7Oid[VoltP7SignDataOidBytesLen] = { VoltP7SignDataOidBytes };
  VtSetAlgIdInfo algIdInfo;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  *bytesRead = 0;
  *outputDataLen = 0;

  switch (obj->state)
  {
    default:
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_CALL_ORDER;
      break;

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

    case VOLT_P7_STATE_SIGN_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.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      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?
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_ENCODING;
      if (derElement->valueLen != VoltP7SignDataOidBytesLen)
        break;
      if (Z2Memcmp (
        p7Oid, derElement->element + 2, VoltP7SignDataOidBytesLen) != 0)
        break;

      obj->state = VOLT_P7_STATE_SIGN_READ_SD_OID;

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

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

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

      obj->state = VOLT_P7_STATE_SIGN_READ_EXP_1;

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

    case VOLT_P7_STATE_SIGN_READ_EXP_1:
      /* Now it's the version.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      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?
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_UNSUPPORTED;
      if (derElement->valueLen != 1)
        break;

      if (derElement->element[2] != 1)
        break;

      obj->state = VOLT_P7_STATE_SIGN_READ_VERSION;

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

    case VOLT_P7_STATE_SIGN_READ_VERSION:
      /* Next up is the SET OF digest algorithm ID's. This
       * implementation can operate with only one digest algorithm.
       * "Cheat" a little bit, pass the SET OF tag as the explicitTag,
       * and the SEQUENCE as the tag. We'll get the SET OF as the
       * explicit and the contents of the first (presumably only)
       * digest algID in the element buffer.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, VOLT_SET_TAG, VOLT_SEQUENCE_TAG, 1,
        derElement, &messageRead);
      if (status != 0)
        break;

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

      /* Make sure there's only one digest alg. If more than one, error.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_UNSUPPORTED;
      if (derElement->explicitLen != derElement->elementLen)
        break;

      /* Build a digest object from this
       */
      algIdInfo.derCoders = readCtx->DerCoders;
      algIdInfo.derCoderCount = readCtx->derCoderCount;
      algIdInfo.berEncoding = derElement->element;
      algIdInfo.maxEncodingLen = derElement->elementLen;
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtCreateAlgorithmObject (
        (VtLibCtx)libCtx, VtAlgorithmImplAlgId, (Pointer)&algIdInfo,
        &(readCtx->digestObj));
      if (status != 0)
        break;

      obj->state = VOLT_P7_STATE_SIGN_READ_DIGEST;

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

    case VOLT_P7_STATE_SIGN_READ_DIGEST:
      /* Now read the contentInfo, the data to verify. Start with the
       * SEQUENCE and OID. Do this by "cheating", setting the
       * explicitTag to the SEQUENCE, thereby capturing both the
       * SEQUENCE tag and the first element, the OID.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      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.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_UNSUPPORTED;
      p7Oid[VoltP7SignDataOidBytesLen - 1] = VOLT_P7_OID_BYTE_DATA;
      if (derElement->valueLen != VoltP7SignDataOidBytesLen)
        break;
      if (Z2Memcmp (
        p7Oid, derElement->element + 2, VoltP7SignDataOidBytesLen) != 0)
        break;

      /* Copy this OID into the readCtx.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_MEMORY;
      readCtx->contentOid = (unsigned char *)Z2Realloc (
        readCtx->contentOid, VoltP7SignDataOidBytesLen);
      if (readCtx->contentOid == (unsigned char *)0)
        break;

      Z2Memcpy (readCtx->contentOid, p7Oid, VoltP7SignDataOidBytesLen);
      readCtx->contentOidLen = VoltP7SignDataOidBytesLen;

      obj->state = VOLT_P7_STATE_SIGN_READ_DATA_OID;

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

    case VOLT_P7_STATE_SIGN_READ_DATA_OID:
      /* We expect to see an EXPLICIT then OCTET STRING.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltGetNextDerElement (
        libCtx, message, messageLen, 0xA0, VOLT_OCTET_STRING_TAG, 0,
        derElement, &messageRead);

⌨️ 快捷键说明

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