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

📄 smwrite.c

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

/* Call this function when obj->dataLen is set, but that info has not
 * been passed down to the P7 and B64 objects.
 * <p>Once we know the total length of data that will be passed to the
 * SecureMail object, we can figure out how many bytes will be passed
 * to the P7 signer object. We can then figure out how big the
 * SignedData will be, which will be passed to the P7 enveloper. The
 * result of that will be passed to the Base64 encoder.
 * <p>This function will set the fields inside the writeCtx that hold
 * the lengths of these elements.
 *
 * @param obj The SecureMail object set with the info.
 * @param writeCtx The context with the objects and fields to set.
 * @param random The random object, calls to P7 functions will have
 * this as an arg.
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV SetTotalLengths VOLT_PROTO_LIST ((
   VoltSecureMailObject *obj,
   VoltSecureMailWriteCtx *writeCtx,
   VtRandomObject random
));

/* Append the given data to the given VtItem.
 * <p>This function will allocate the data to hold the old info and the
 * new info, copy the old info into the new buffer, then copy the new
 * info after the old info. It will then place any trailingCharacters.
 * <p>The trailingCharacters might be NULL (nothing to append), or
 * maybe they are new line characters, or maybe they are
 * NULL-terminating characters.
 * <p>This function assumes theItem points to a vaild VtItem.
 * <p>The data field of theItem can be NULL. In other words, the call
 * to Append can place the first block of data into theItem.
 * <p>If dataToAppend or trailingCharacters is NULL, then the
 * affiliated length arg (dataToAppendLen and trailingCharactersLen)
 * must be 0.
 * <p>This function does not check the args, it is the responsibility
 * of the caller not to make mistakes.
 */
static int VOLT_CALLING_CONV AppendToVtItem VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   unsigned char *dataToAppend,
   unsigned int dataToAppendLen,
   unsigned char *trailingCharacters,
   unsigned int trailingCharactersLen,
   VtItem *theItem
));

/* This creates an ASCII string (NULL-terminated) version of theNum in
 * decimal.
 * <p>For example, the number 0x0000006B is converted to a string of
 * length 4: 0x31, 0x30, 0x37, 0x00. That is the string "107".
 */
int VOLT_CALLING_CONV ConvertNumToAsciiAlloc VOLT_PROTO_LIST ((
   VoltLibCtx *libCtx,
   unsigned int theNum,
   char **asciiNum,
   unsigned int *asciiNumLen
));

int VoltSecureMailWriteInit (
   VtSecureMailObject secureMailObj,
   VtPolicyCtx policyCtx,
   VtStorageCtx storageCtx,
   VtTransportCtx transportCtx,
   VtRandomObject random
   )
{
  int status;
  unsigned int index, elementLen, newLineLen;
  VoltSecureMailObject *obj = (VoltSecureMailObject *)secureMailObj;
  VoltSecureMailWriteCtx *writeCtx = (VoltSecureMailWriteCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VoltPolicyCtx *pCtx;
  VtItem *getItem = (VtItem *)0;
  char *contentType = VOLT_DEFAULT_CONTENT_TYPE;
  VtBase64Info b64Info;

  do
  {
    /* Create the Base64 object. We couldn't create it until we had the
     * new line issue settled.
     */
    if (obj->base64 != (VtAlgorithmObject)0)
      VtDestroyAlgorithmObject (&(obj->base64));

    b64Info.base64BlockSize = 64;
    b64Info.newLineCharacter = VT_BASE64_NEW_LINE_LF;
    if (writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].len == 2)
      b64Info.newLineCharacter = VT_BASE64_NEW_LINE_CR_LF;
    b64Info.errorCheck = VT_BASE64_NO_ERROR_CHECK;
    status = VtCreateAlgorithmObject (
      (VtLibCtx)libCtx, VtAlgorithmImplBase64, (Pointer)&b64Info,
      &(obj->base64));
    if (status != 0)
      break;

    /* Init the subordinate objects.
     */
    status = VtPkcs7WriteInit (
      obj->p7SignedData, policyCtx, storageCtx, transportCtx, random);
    if (status != 0)
      break;

    status = VtPkcs7WriteInit (
      obj->p7EnvelopedData, policyCtx, storageCtx, transportCtx, random);
    if (status != 0)
      break;

    status = VtEncodeInit (obj->base64);
    if (status != 0)
      break;

    /* If there's no content type, use the default.
     */
    if (obj->contentInfo.data == (unsigned char *)0)
    {
      status = VT_ERROR_MEMORY;
      obj->contentInfo.data = (unsigned char *)Z2Malloc (
        VOLT_DEFAULT_CONTENT_TYPE_LEN + 1, 0);
      if (obj->contentInfo.data == (unsigned char *)0)
        break;
      Z2Memcpy (
        obj->contentInfo.data, contentType, VOLT_DEFAULT_CONTENT_TYPE_LEN);
      obj->contentInfo.data[VOLT_DEFAULT_CONTENT_TYPE_LEN] = 0;
      obj->contentInfo.len = VOLT_DEFAULT_CONTENT_TYPE_LEN;
    }

    /* Get elements out of the policy ctx. If there is no policy ctx,
     * we're done.
     */
    if (policyCtx == (VtPolicyCtx)0)
      break;

    pCtx = (VoltPolicyCtx *)policyCtx;

    /* Get any header.
     */
    status = pCtx->PolicyGetInfoAlloc (
      policyCtx, VOLT_POLICY_GET_SECURE_MAIL_HEADER,
      (Pointer)(writeCtx->recipListRef), (Pointer *)&getItem);
    if (status != 0)
      break;

    if (getItem != (VtItem *)0)
    {
      if ( (getItem->data != (unsigned char *)0) && (getItem->len != 0) )
      {
        status = VoltCopyItemDataAlloc (
          obj->voltObject.libraryCtx, 0, 0, getItem,
          &(writeCtx->itemArray[VOLT_WRITE_SM_ITEM_HEADER]));
        if (status != 0)
          break;
      }

      /* Free the getItem data so we can use the variable again.
       */
      pCtx->PolicyGetInfoFree (policyCtx, (Pointer)getItem);
      getItem = (VtItem *)0;
    }

    /* Get any footer.
     */
    // For now, leave this out. The current client does not work the
    // way we want it to, so we'll put this in when we decide how to do
    // everything just the way we want.
//    status = pCtx->PolicyGetInfoAlloc (
//      policyCtx, VOLT_POLICY_GET_CONTENT_FOOTER, (Pointer)0,
//      (Pointer *)&getItem);
//    if (status != 0)
//      break;

    newLineLen = writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].len;
    if (getItem != (VtItem *)0)
    {
      /* Copy the footer with a new line at the front.
       */
      if ( (getItem->data != (unsigned char *)0) && (getItem->len != 0) )
      {
        status = VT_ERROR_MEMORY;
        writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].data =
          (unsigned char *)Z2Malloc (
          getItem->len + newLineLen, VOLT_MEMORY_SENSITIVE);
        if (writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].data ==
          (unsigned char *)0)
          break;
        Z2Memcpy (
          writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].data,
          writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].data, newLineLen);
        Z2Memcpy (
          writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].data +
          newLineLen, getItem->data, getItem->len);
        writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].len =
          getItem->len + newLineLen;
        status = 0;
      }
    }

    /* Sum up the preliminary and trailing lengths.
     */
    for (index = VOLT_WRITE_SM_HEAD_INDEX_START;
         index <= VOLT_WRITE_SM_HEAD_INDEX_END; ++index)
    {
      /* Add in the length of the actual data to write out.
       * If there is data to write out, add a newLine.
       */
      elementLen = writeCtx->itemArray[index].len;
      if (elementLen != 0)
        elementLen += newLineLen;
      writeCtx->prelimLen += elementLen;
    }

    for (index = VOLT_WRITE_SM_FOOT_INDEX_START;
         index <= VOLT_WRITE_SM_FOOT_INDEX_END; ++index)
    {
      /* Add in the length of the actual data to write out.
       * If there is data to write out, add a newLine.
       */
      elementLen = writeCtx->itemArray[index].len;
      if (elementLen != 0)
        elementLen += newLineLen;
      writeCtx->trailLen += elementLen;
    }

    obj->state = VOLT_SECURE_MAIL_STATE_WRITE_INIT;

  } while (0);

  if (getItem != (VtItem *)0)
    pCtx->PolicyGetInfoFree (policyCtx, (Pointer)getItem);

  return (status);
}

int VoltSecureMailWriteUpdate (
   VtSecureMailObject secureMailObj,
   VtRandomObject random,
   unsigned char *inputData,
   unsigned int inputDataLen,
   unsigned char *message,
   unsigned int bufferSize,
   unsigned int *messageLen
   )
{
  int status;
  unsigned int index, offset, elementLen, newLineLen, preliminaryLen;
  unsigned int contentReportLen, signedDataLen, envelopedDataLen, b64Len;
  unsigned char *newLine;
  unsigned char *sBuffer = (unsigned char *)0;
  unsigned char *eBuffer = (unsigned char *)0;
  VoltSecureMailObject *obj = (VoltSecureMailObject *)secureMailObj;
  VoltSecureMailWriteCtx *writeCtx = (VoltSecureMailWriteCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VtItem *preP7 = &(writeCtx->itemArray[VOLT_WRITE_SM_PRE_PKCS7]);

  do
  {
    /* How big is the output going to be?
     */
    if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_INIT)
    {
      /* If the state is INIT, we have not set the lengths of the P7
       * objects yet.
       */
      status = SetTotalLengths (obj, writeCtx, random);
      if (status != 0)
        break;
    }

    /* If the state is INIT_LEN, we've set the lengths of the P7
     * objects, but we still haven't written out any preliminary info.
     * We also need to send to the Sign object the content report.
     * If the state is not INIT_LEN, it must be UPDATE, we can call
     * UPDATE only after Init or another Update call.
     */
    status = VT_ERROR_INVALID_CALL_ORDER;
    preliminaryLen = 0;
    contentReportLen = 0;
    if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_INIT_LEN)
    {
      preliminaryLen = writeCtx->prelimLen;
      contentReportLen =
        writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_REPORT].len;
    }
    else if (obj->state != VOLT_SECURE_MAIL_STATE_WRITE_UPDATE)
    {
      break;
    }

    /* Make sure the inputLen is valid.
     */
    status = VT_ERROR_INVALID_INPUT_LENGTH;
    if ((obj->inputLen + inputDataLen) > obj->dataLen)
      break;

    /* How long will the SignedData be?
     * The variable contentReportLen contains the length of
     * contentReport, unless we've already written it out, in which
     * case, that variable is set to 0.
     */
    status = VtPkcs7WriteUpdate (
      obj->p7SignedData, random,
      (unsigned char *)0, inputDataLen + contentReportLen,
      (unsigned char *)0, 0, &signedDataLen);
    if (status == 0)
      status = VT_ERROR_GENERAL;
    if (status != VT_ERROR_BUFFER_TOO_SMALL)
      break;

    /* How long will the envelopedData be?
     */
    status = VtPkcs7WriteUpdate (
      obj->p7EnvelopedData, random, (unsigned char *)0, signedDataLen,
      (unsigned char *)0, 0, &envelopedDataLen);
    if (status == 0)
      status = VT_ERROR_GENERAL;
    if (status != VT_ERROR_BUFFER_TOO_SMALL)
      break;

    /* How long will the Base64 be?
     */
    status = obj->GetEncodeDecodeSize (
      obj->base64, (VtRandomObject)0, VOLT_CALLER_ENCODE_UPDATE,
      (unsigned char *)0, envelopedDataLen + preP7->len, &b64Len);

    status = VT_ERROR_BUFFER_TOO_SMALL;
    *messageLen = preliminaryLen + b64Len;
    if (bufferSize < *messageLen)
      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;

    /* Start writing out the message.
     */
    offset = 0;

    if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_INIT_LEN)
    {
      /* If the state is INIT_LEN, we have not written out the
       * preliminaries yet.
       */
      newLine = writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].data;
      newLineLen = writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].len;
      for (index = VOLT_WRITE_SM_HEAD_INDEX_START;
           index <= VOLT_WRITE_SM_HEAD_INDEX_END; ++index)
      {
        /* Add in the length of the actual data to write out.
         * If there is data to write out, add a newLine.
         */
        elementLen = writeCtx->itemArray[index].len;
        if (elementLen == 0)
          continue;

        Z2Memcpy (
          message + offset, writeCtx->itemArray[index].data, elementLen);
        offset += elementLen;
        Z2Memcpy (message + offset, newLine, newLineLen);
        offset += newLineLen;
      }

      /* Now that we've written out the preliminaries, the state can be
       * regular UPDATE.
       */
      obj->state = VOLT_SECURE_MAIL_STATE_WRITE_UPDATE;
    }

    /* Allocate a buffer to hold the signed data.
     */
    status = VT_ERROR_MEMORY;
    sBuffer = (unsigned char *)Z2Malloc (signedDataLen, 0);
    if (sBuffer == (unsigned char *)0)
      break;

    /* Write out the SignedData.
     * Use index as a temp variable.
     */
    index = 0;
    if (contentReportLen != 0)
    {
      /* If we haven't written out the content report, do it now. Get
       * the number of bytes written in index.
       */
      status = VtPkcs7WriteUpdate (
        obj->p7SignedData, random,
        writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_REPORT].data,
        contentReportLen, sBuffer, signedDataLen, &index);
      if (status != 0)
        break;
    }

    /* If we wrote out something based on contentReport, index is how
     * many bytes written. If we did not write out something based on
     * contentReport, index is 0.
     */
    status = VtPkcs7WriteUpdate (
      obj->p7SignedData, random, inputData, inputDataLen,
      sBuffer + index, signedDataLen - index, &signedDataLen);
    if (status != 0)
      break;
    signedDataLen += index;

    /* Allocate a buffer to hold the enveloped data.
     */
    status = VT_ERROR_MEMORY;
    eBuffer = (unsigned char *)Z2Malloc (envelopedDataLen, 0);
    if (eBuffer == (unsigned char *)0)
      break;

    /* Envelope the signed data.
     */
    status = VtPkcs7WriteUpdate (
      obj->p7EnvelopedData, random, sBuffer, signedDataLen,
      eBuffer, envelopedDataLen, &envelopedDataLen);
    if (status != 0)
      break;

    /* If there's any preP7 data, encode it. Then Base64 encode the
     * enveloped data.
     */
    if (preP7->len != 0)
    {
      status = VtEncodeUpdate (
        obj->base64, (VtRandomObject)0, preP7->data, preP7->len,
        message + offset, bufferSize - offset, &b64Len);
      if (status != 0)
        break;

      offset += b64Len;
      preP7->len = 0;
    }
    status = VtEncodeUpdate (
      obj->base64, (VtRandomObject)0, eBuffer, envelopedDataLen,
      message + offset, bufferSize - offset, &b64Len);
    if (status != 0)
      break;

⌨️ 快捷键说明

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