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

📄 writeenv.c

📁 IBE是一种非对称密码技术
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
 */
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "p7obj.h"
#include "idobj.h"
#include "algobj.h"
#include "derhelp.h"
#include "oidlist.h"
#include "errorctx.h"

/* Set up the OpenSSL ASN.1 templates.
 */
ASN1_SEQUENCE (Asn1EncryptedInfo) =
{
  ASN1_SIMPLE (Asn1EncryptedInfo, contentType, Asn1ObjectId),
  ASN1_SIMPLE (Asn1EncryptedInfo, algId, Asn1Encoded),
  ASN1_IMP (Asn1EncryptedInfo, encryptedContent, Asn1EncryptedContent, 0)
} ASN1_SEQUENCE_END (Asn1EncryptedInfo);

IMPLEMENT_ASN1_FUNCTIONS (Asn1EncryptedInfo)

ASN1_SEQUENCE (Asn1EnvelopedData) =
{
  ASN1_SIMPLE (Asn1EnvelopedData, version, ASN1_INTEGER),
  ASN1_SET_OF (Asn1EnvelopedData, recipInfo, Asn1RecipientInfo),
  ASN1_SIMPLE (Asn1EnvelopedData, encryptedInfo, Asn1EncryptedInfo)
} ASN1_SEQUENCE_END (Asn1EnvelopedData);

IMPLEMENT_ASN1_FUNCTIONS (Asn1EnvelopedData)

ASN1_SEQUENCE (Asn1EnvelopedContent) =
{
  ASN1_SIMPLE (Asn1EnvelopedContent, contentType, Asn1ObjectId),
  ASN1_EXP (Asn1EnvelopedContent, envelopedData, Asn1EnvelopedData, 0)
} ASN1_SEQUENCE_END (Asn1EnvelopedContent);

IMPLEMENT_ASN1_FUNCTIONS (Asn1EnvelopedContent)

/* The identity object should contain an encoded ID. Build the
 * identity-based IssuerAndSerialNumber out of it.
 *
 *  IssuerAndSerialNumber ::= SEQUENCE {
 *    issuer Name,
 *    serialNumber CertificateSerialNumber }
 *
 *  CertificateSerialNumber  ::=  INTEGER
 *
 * The serialNumber is always 1 (02 01 01).
 * <p>The Name will contain one Attribute (OID: id-at-name), which is the
 * PrintableString of the Base64 encoded identity string.
 *
 *   Name ::= CHOICE {
 *    RDNSequence }
 *
 *   RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
 *
 *   RelativeDistinguishedName ::=
 *     SET OF AttributeTypeAndValue
 *
 *   AttributeTypeAndValue ::= SEQUENCE {
 *     type     AttributeType,
 *     value    AttributeValue }
 *
 *   AttributeType ::= OBJECT IDENTIFIER
 *
 *   AttributeValue ::= ANY DEFINED BY AttributeType
 *
 * The IssuerAndSerialNumber in this context will then be fixed at
 *
 *   30 len                           SEQ: IssuerAndSerialNumber
 *     30 len                           SEQ OF RDN
 *        31 len                          SET OF Attribute
 *           30 len                         SEQ: Attribute
 *              06 03                         OID
 *                 55 04 29
 *              13 len                        value (ANY, PrintableString)
 *                 <Base64 of encoded ID>
 *     02 01                            INTEGER: serialNumber
 *        01
 *
 * This function will allocate the space necessary to hold the encoding
 * and return the new buffer and its length. It is the responsibility
 * of the caller to free that memory.
 * <p>This function assumes that the identity has been encoded and that
 * it exists in the encoding field of the VoltIdentityObject. The
 * routine will do no argument checking.
 *
 * @param libCtx The library ctx to use.
 * @param idObj The object containing the ID to build into issuer and
 * serial number.
 * @param base64 An object built to encode binary data to Base64.
 * @param issuerSerial The address where the function will deposit the
 * pointer to the newly allocated buffer.
 * @param issuerSerialLen The address where the function will deposit
 * the length of the encoding.
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV VoltBuildIssuerSerialAlloc VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   VtIdentityObject idObj,
   VtAlgorithmObject base64,
   unsigned char **issuerSerial,
   unsigned int *issuerSerialLen
));

int VoltP7EnvWriteInit (
   VtPkcs7Object pkcs7Obj,
   VtPolicyCtx policyCtx,
   VtStorageCtx storageCtx,
   VtTransportCtx transportCtx,
   VtRandomObject random
   )
{
  int status;
  unsigned int index, indexC, indexD, idCount, maxIndex, keyLen;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7WriteEnvCtx *envCtx = (VoltPkcs7WriteEnvCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  unsigned char *keyData = (unsigned char *)0;
  VtAlgorithmObject base64 = (VtAlgorithmObject)0;
  VtIdentityObject currentId, compareId;
  VtBase64Info base64Info;
  VtItem keyItem;
  VtItem *getKeyData;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

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

    /* This implementation does not work without recipients or a
     * symmetric encryptor. The recipients might be represented as an
     * IdentityList or as a list of RecipientData.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_INVALID_P7_OBJ;
    if ( (envCtx->recipList == (VtIdentityList)0) &&
         (envCtx->recipients == (VoltRecipientData *)0) )
      break;
    VOLT_SET_FNCT_LINE (fnctLine)
    if (envCtx->symEncryptor == (VtAlgorithmObject)0)
      break;

    /* Build a Base64 object. We'll need it later for each recipient,
     * so rather than build again and again, build one now and pass it
     * around.
     */
    base64Info.base64BlockSize = 76;
    base64Info.newLineCharacter = VT_BASE64_NO_NEW_LINE;
    base64Info.errorCheck = VT_BASE64_NO_ERROR_CHECK;
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtCreateAlgorithmObject (
      (VtLibCtx)libCtx, VtAlgorithmImplBase64, (Pointer)&base64Info,
      &base64);
    if (status != 0)
      break;

    /* If there's no key object yet, build it. If there is one, get the
     * key data.
     */
    if (envCtx->symKey == (VtKeyObject)0)
    {
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_MEMORY;
      keyLen = (envCtx->symKeyBits + 7) / 8;
      keyData = (unsigned char *)Z2Malloc (keyLen, VOLT_MEMORY_SENSITIVE);
      if (keyData == (unsigned char *)0)
        break;

      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtGenerateRandomBytes (random, keyData, keyLen);
      if (status != 0)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtCreateKeyObject (
        (VtLibCtx)libCtx, VtKeyImplDefault, (Pointer)0, &(envCtx->symKey));
      if (status != 0)
        break;

      keyItem.data = keyData;
      keyItem.len = keyLen;
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtSetKeyParam (
        envCtx->symKey, envCtx->SymKeyParam, (Pointer)&keyItem);
      if (status != 0)
        break;

      getKeyData = &keyItem;
    }
    else
    {
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtGetKeyParam (
        envCtx->symKey, envCtx->SymKeyParam, (Pointer *)&getKeyData);
      if (status != 0)
        break;
    }

    /* If we don't have the RecipientData array built, build it. If it
     * is built, just compute the totalRecipInfoLen and we're done.
     */
    if (envCtx->recipients != (VoltRecipientData *)0)
    {
      envCtx->totalRecipInfoLen = 0;
      for (index = 0; index < envCtx->recipientsCount; ++index)
        envCtx->totalRecipInfoLen += envCtx->recipients[index].recipInfoLen;

      break;
    }

    /* How many recipients are there?
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtGetIdentityListCount (envCtx->recipList, &idCount, &maxIndex);
    if (status != 0)
      break;

    /* Build the array of recipientDatas. Use index as a temp variable.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    index = idCount * sizeof (VoltRecipientData);
    envCtx->recipients = (VoltRecipientData *)Z2Malloc (index, 0);
    if (envCtx->recipients == (VoltRecipientData *)0)
      break;
    Z2Memset (envCtx->recipients, 0, index);
    envCtx->recipientsCount = idCount;

    /* Cycle through the identities, creating RecipientData for each.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    indexD = 0;
    for (index = 0; index <= maxIndex; ++index)
    {
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtGetIdentityListIdentity (
        envCtx->recipList, index, &currentId);
      if (status != 0)
      {
        /* If status is VT_ERROR_NO_ID_AT_INDEX, don't quit, just move
         * on to the next ID in the list.
         */
        if (status != VT_ERROR_NO_ID_AT_INDEX)
          break;
        status = 0;
        continue;
      }

      /* Make sure the identity is encoded. Calling this routine will
       * build the encoded ID internally, which is all we need. Use
       * keyLen as a temp variable. We're expecting the
       * BUFFER_TOO_SMALL error.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtEncodeIdentity (
        currentId, VT_ENCODE_IBCS_2_V_DISTRICT, policyCtx,
        storageCtx, transportCtx, (unsigned char *)0, 0, &keyLen);
      if (status == 0)
        status = VT_ERROR_GENERAL;
      if (status != VT_ERROR_BUFFER_TOO_SMALL)
        break;

      /* If this is a repeat identity, don't bother with it. Set it to
       * be inactive. Compare with all previously encoded ID's.
       * Use keyLen as a temp variable.
       */
      keyLen = 0;
      for (indexC = 0; indexC < index; ++indexC)
      {
        status = VtGetIdentityListIdentity (
          envCtx->recipList, indexC, &compareId);
        if (status != 0)
          continue;

        VoltIsSameIdentity (currentId, compareId, &keyLen);
        if (keyLen != 0)
          break;
      }

      /* If keyLen is not 0, there was a matching ID, ignore this
       * identity.
       */
      if (keyLen != 0)
      {
        VtSetEntryStatusInIdentityList (
          envCtx->recipList, index, VT_RECIPIENT_LIST_ENTRY_INACTIVE);
        continue;
      }

      /* Build the RecipientData struct for this identity.
       */
      envCtx->recipients[indexD].idRef = currentId;
      VOLT_SET_FNCT_LINE (fnctLine)
      status =  VoltBuildRecipientData (
        (VoltObject *)obj, random, base64, VtDerCoderBFType1IBE,
        getKeyData->data, getKeyData->len, &(envCtx->recipients[indexD]));
      if (status != 0)
        break;

      envCtx->totalRecipInfoLen += envCtx->recipients[indexD].recipInfoLen;

      indexD++;
    }
    if (status != 0)
      break;

  } while (0);

  VtDestroyAlgorithmObject (&base64);

  if (keyData != (unsigned char *)0)
    Z2Free (keyData);

  if (status == 0)
    obj->state = VOLT_P7_STATE_ENV_WRITE_INIT;

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, pkcs7Obj, status, 0, errorType,
    (char *)0, "VoltP7EnvWriteInit", fnctLine, (char *)0)

  return (status);
}

int VoltP7EnvWriteUpdate (
   VtPkcs7Object pkcs7Obj,
   VtRandomObject random,
   unsigned char *inputData,
   unsigned int inputDataLen,
   unsigned char *message,
   unsigned int bufferSize,
   unsigned int *messageLen
   )
{
  int status;
  unsigned int index, tempLen, recipOutLen, offset;
#if VT_64_BIT_LENGTH == 64
  VtUInt64 encryptedDataLen, outputLen, encContentInfoLen;
  VtUInt64 seqLen, expLen, totalLen;
#else
  unsigned int encryptedDataLen, outputLen, encContentInfoLen;
  unsigned int seqLen, expLen, totalLen;
#endif
  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 };
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  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.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_INPUT_LENGTH;
#if VT_64_BIT_LENGTH == 64
      if ((VtUInt64)inputDataLen > obj->dataLen64)
#else
      if (inputDataLen > obj->dataLen)
#endif
        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).
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      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, and it
       * will not work with 64-bit lengths, 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)

⌨️ 快捷键说明

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