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

📄 smread.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 "securemail.h"
#include "derhelp.h"
#include "errorctx.h"

/* Call DecodeUpdate, or DecodeFinal, place the result into
 * readCtx->unprocessedData. If the buffer is not big enough, expand it.
 * <p>The function will call Update or Final depending on the flag. If
 * non-zero, do Update, if 0, do Final.
 * <p>Upon return, the unprocessedData buffer contains the decoded
 * material and unprocessedDataLen is the length.
 *
 * @param obj
 * @param readCtx
 * @param flag If non-zero, Update, if 0, Final.
 * @param dataToDecode
 * @param dataToDecodeLen
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV DoDecodeUpdateOrFinal VOLT_PROTO_LIST ((
   VoltSecureMailObject *obj,
   VoltSecureMailReadCtx *readCtx,
   unsigned int flag,
   unsigned char *dataToDecode,
   unsigned int dataToDecodeLen
));

/* There's data in the unprocessedData buffer, pass it to the Envelope
 * object for a ReadUpdate.
 * <p>The function will call Update or Final depending on the flag. If
 * non-zero, do Update, if 0, do Final. If it calls FInal, it will call
 * it with no data.
 * <p>If the envelope object cannot read all the data because of
 * VT_ERROR_CHOOSE_RECIPIENT, return that error and make sure the
 * unprocessedData buffer contains any unread envelope data. That is,
 * Memmove the unread data to the beginning of the buffer and set
 * unprocessedDataLen. If this is the case, there will be no Envelope
 * output.
 * <p>This function will not return BUFFER_TOO_SMALL, because if
 * there's any output, this routine will use any allocated space it
 * already has or will allocate new space if needed.
 * <p>Any error other than CHOOSE will be passed back to the caller.
 * <p>If the return is 0, the function will have read all the input.
 * <p>If the envelope object produces output, this function will place
 * the output into the unprocessedData buffer. That is, upon successful
 * completion, look in the unprocessedData buffer (length:
 * unprocessedDataLen) for material that is to be passed to the
 * SignedData object.
 */
static int VOLT_CALLING_CONV DoEnvelopeRead VOLT_PROTO_LIST ((
   VoltSecureMailObject *obj,
   VoltSecureMailReadCtx *readCtx,
   unsigned int flag
));

/* Add the given data to the given byteArrayObj.
 * <p>Append data. If there is already data there, place this new data
 * on the end. This might require a realloc.
 *
 * @param obj
 * @param byteArrayObj Where the new data will be placed.
 * @param data The data to place.
 * @param dataLen The length, in bytes of the data to place.
 * @return an int, 0 if the function completed successfully or a
 * non-zero error code.
 */
static int VOLT_CALLING_CONV StoreUnprocessedData VOLT_PROTO_LIST ((
   VoltSecureMailObject *obj,
   VoltByteArrayObj *byteArrayObj,
   unsigned char *data,
   unsigned int dataLen
));

/* Data was copied into the byteArrayCtx. The completeFlag indicates
 * whether it was a complete content descriptor. The signRead is how
 * many bytes were read out of the unprocessedData buffer of the
 * readCtx.
 * <p>This function will move the unprocessedData buffer by signRead
 * bytes.
 * <p>If the completeFlag indicates complete, the routine will check
 * the contents to see if the descriptor copied is the last one. If it
 * is not the last one, the function will increment the
 * contentMaterialCount in the readCtx and set the contentMaterialState
 * to ELEMENT. If it is the last one, the function will set the
 * contentMaterialState to COMPLETE.
 * <p>If the completeFlag is not complete, the function will set the
 * contentMaterialState to PARTIAL.
 * <p>If complete, the routine will pass the content to the P7
 * SignedData object, but will not return the output to the
 * application's output buffer.
 */
static int VOLT_CALLING_CONV ProcessContentDescriptor VOLT_PROTO_LIST ((
   VoltSecureMailObject *obj,
   VoltSecureMailReadCtx *readCtx,
   VoltByteArrayObj *byteArrayObj,
   unsigned int completeFlag,
   unsigned int signRead
));

int VoltSecureMailReadInit (
   VtSecureMailObject secureMailObj
   )
{
  int status;
  VoltSecureMailObject *obj = (VoltSecureMailObject *)secureMailObj;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

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

    /* Init the subordinate objects.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtPkcs7ReadInit (obj->p7SignedData);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtPkcs7ReadInit (obj->p7EnvelopedData);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtDecodeInit (obj->base64);
    if (status != 0)
      break;

    obj->state = VOLT_SECURE_MAIL_STATE_READ_INIT;

  } while (0);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, secureMailObj, status, 0, errorType,
    (char *)0, "VoltSecureMailReadInit", fnctLine, (char *)0)

  return (status);
}

#define VOLT_ZDM_MESSAGE_TYPE \
    "<input type=\"hidden\" name=\"ZFRtype\" value=\"VoltageZFRDoc\">"
#define VOLT_ZDM_MESSAGE_TYPE_LEN  58
#define VOLT_ZDM_MESSAGE_START \
    "<input type=\"hidden\" name=\"ZFRdata\" value=\""
#define VOLT_ZDM_MESSAGE_START_LEN 43

int VoltSecureMailReadUpdate (
   VtSecureMailObject secureMailObj,
   unsigned char *message,
   unsigned int messageLen,
   unsigned int *bytesRead,
   unsigned char *outputData,
   unsigned int bufferSize,
   unsigned int *outputDataLen
   )
{
  int status;
  unsigned int index, completeFlag, amountRead, currentMessageLen;
  unsigned int inBlockLen, outBlockLen, leftovers, newLineLen;
  unsigned int theTag, lengthLen, valueLen, preSpaceLen, flag;
#if VT_64_BIT_LENGTH == 64
  VtUInt64 envelopeLen, inBlocks, outLen;
#else
  unsigned int envelopeLen, inBlocks, outLen;
#endif
  UInt32 lenLo, lenHi;
  VoltSecureMailObject *obj = (VoltSecureMailObject *)secureMailObj;
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VoltSecureMailReadCtx *readCtx = (VoltSecureMailReadCtx *)(obj->localCtx);
  unsigned char *currentMessage;
  unsigned char *beginMsg = VOLT_SECURE_MAIL_BEGIN_MESSAGE;
  unsigned char *beginBlk = VOLT_SECURE_MAIL_BEGIN_BLOCK;
  unsigned char *endBlk = VOLT_SECURE_MAIL_END_BLOCK;
  unsigned char *endMsg = VOLT_SECURE_MAIL_END_MESSAGE;
  unsigned char *zdmMessageType = VOLT_ZDM_MESSAGE_TYPE;
  unsigned char *zdmMessageStart = VOLT_ZDM_MESSAGE_START;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  *bytesRead = 0;
  *outputDataLen = 0;
  currentMessage = message;
  currentMessageLen = messageLen;

  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;

VoltSecureMailStateReadComplete:
    case VOLT_SECURE_MAIL_STATE_READ_ENV_FINAL:
    case VOLT_SECURE_MAIL_STATE_READ_SIGN_FINAL:
    case VOLT_SECURE_MAIL_STATE_READ_P7_FINAL:
    case VOLT_SECURE_MAIL_STATE_READ_COMPLETE:
      /* If we're done, don't read anything. Actually, if this is ZDM,
       * ignore any new data. Otherwise, the caller passed in too much
       * data.
       */
      status = 0;
      if (currentMessageLen == 0)
        break;

      if ((obj->formatType & VOLT_MESSAGE_FORMAT_ZDM) != 0)
      {
        *bytesRead += currentMessageLen;
        break;
      }

      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
      if (obj->formatType == VOLT_MESSAGE_FORMAT_SECURE_MAIL)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_SECURE_FILE_MSG;
      break;

    case VOLT_ZDM_STATE_READ_INIT:
      /* With ZDM, the first thing to do will be to read the
       * preliminary HTML info ... and ignore it.
       */
      obj->formatType = VOLT_MESSAGE_FORMAT_ZDM_MAIL;
      obj->state = VOLT_ZDM_STATE_READ_HEADER;

VoltZdmStateReadHeader:
    case VOLT_ZDM_STATE_READ_HEADER:
      /* Keep reading blocks of data until finding something we
       * recognize.
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltSMGetNextBlock (
        obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
        9, &amountRead, &completeFlag, &newLineLen);
      if (status != 0)
        break;

      *bytesRead += amountRead;
      if (completeFlag == 0)
        break;

      currentMessage = message + *bytesRead;
      currentMessageLen = messageLen - *bytesRead;

      /* We have the next block in the unprocessedData buffer, is this
       * the block that says this is a ZDM attachment?
       * If not, is it the start of the data?
       */
      if (readCtx->unprocessedData.len >= VOLT_ZDM_MESSAGE_TYPE_LEN)
      {
        if (Z2Memcmp (
          readCtx->unprocessedData.data, zdmMessageType,
          VOLT_ZDM_MESSAGE_TYPE_LEN) == 0)
          obj->formatType = VOLT_MESSAGE_FORMAT_ZDM_ATTACHMENT;
      }

      if (readCtx->unprocessedData.len >= VOLT_ZDM_MESSAGE_START_LEN)
      {
        if (Z2Memcmp (
          readCtx->unprocessedData.data, zdmMessageStart,
          VOLT_ZDM_MESSAGE_START_LEN) == 0)
        {
          /* We've found the start, what's after the start line, a new
           * line character or data. If new line, the beginning of the
           * actual data is on a new line. If data, there was no
           * carriage return inserted.
           */
          if ( (readCtx->unprocessedData.data[VOLT_ZDM_MESSAGE_START_LEN] == 0x0d) ||
               (readCtx->unprocessedData.data[VOLT_ZDM_MESSAGE_START_LEN] == 0x0a) )
          {
            readCtx->unprocessedData.len = 0;
          }
          else
          {
            /* If data, move the data to the beginning, we'll need to
             * read it.
             */
            Z2Memmove (
              readCtx->unprocessedData.data,
              readCtx->unprocessedData.data + VOLT_ZDM_MESSAGE_START_LEN,
              readCtx->unprocessedData.len - VOLT_ZDM_MESSAGE_START_LEN);
            readCtx->unprocessedData.len -= VOLT_ZDM_MESSAGE_START_LEN;
          }

          /* Now do we move on to reading SecureMail headers or actual
           * data.
           */
          if (obj->formatType == VOLT_MESSAGE_FORMAT_ZDM_MAIL)
          {
            /* This is MAIL, read SecureMail headers. Do we have the
             * first one in the buffer already?
             */
            obj->state = VOLT_SECURE_MAIL_STATE_READ_HEADER_1;
            if (readCtx->unprocessedData.len == 0)
              goto VoltSecureMailReadHeader1;
            goto VoltSecureMailReadHeader1A;
          }

          /* This is a ZDM attachment, there are no headers.
           * Do we have the first line of B64 in the buffer already?
           */
          if (readCtx->unprocessedData.len == 0)
            goto VoltSecureMailBase64;
          obj->state = VOLT_SECURE_MAIL_STATE_READ_B64_LEN;
          goto VoltSecureMailBase64A;
        }
      }

      /* The line is not something expected, keep reading.
       */
      readCtx->unprocessedData.len = 0;
      goto VoltZdmStateReadHeader;

    case VOLT_SECURE_MAIL_STATE_READ_INIT:
      /* The first thing to do will be to read the first header.
       */
      obj->state = VOLT_SECURE_MAIL_STATE_READ_HEADER_1;

VoltSecureMailReadHeader1:
    case VOLT_SECURE_MAIL_STATE_READ_HEADER_1:
      /* We're just starting to read the message. The first thing up
       * should be
       *   -----BEGIN VOLTAGE MESSAGE BLOCK V1-----
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltSMGetNextBlock (
        obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
        0, &amountRead, &completeFlag, &newLineLen);
      if (status != 0)
        break;

      *bytesRead += amountRead;
      if (completeFlag == 0)
        break;

      currentMessage = message + *bytesRead;
      currentMessageLen = messageLen - *bytesRead;

      /* We have the next block in the unprocessedData buffer, is this
       * the block we expect?
       * Remember, the VoltSMGetNextBlock function added a
       * NULL-terminating character.
       */
VoltSecureMailReadHeader1A:
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
      if (readCtx->unprocessedData.len !=
        VOLT_SECURE_MAIL_BEGIN_MESSAGE_LEN + newLineLen)
        break;
      if (Z2Memcmp (
        readCtx->unprocessedData.data, beginMsg,
        VOLT_SECURE_MAIL_BEGIN_MESSAGE_LEN) != 0)
        break;

      /* Set up the context for the next block.
       */
      status = 0;
      readCtx->unprocessedData.len = 0;
      obj->state = VOLT_SECURE_MAIL_STATE_READ_HEADER_2;
      obj->version = 1;
      
      /* If there's no more message to read, return.
       */
      if (currentMessageLen == 0)
        break;

VoltSecureMailReadHeader2:
    case VOLT_SECURE_MAIL_STATE_READ_HEADER_2:
      /* At this point we should read an "extra" header or
       *   -----BEGIN VOLTAGE SECURE BLOCK V1-----
       */  
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltSMGetNextBlock (
        obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
        9, &amountRead, &completeFlag, &newLineLen);
      if (status != 0)
        break;

      *bytesRead += amountRead;
      if (completeFlag == 0)
        break;

      currentMessage = message + *bytesRead;
      currentMessageLen = messageLen - *bytesRead;

      /* We have the next block in the unprocessedData buffer, is this
       * an "extra" block or the second header?
       * Note from the programmer: Notice the goto statement.
       * Normally I don't like them, but in this case it really works.
       */      
      if (readCtx->unprocessedData.len ==
        VOLT_SECURE_MAIL_BEGIN_BLOCK_LEN + newLineLen)
      {
        /* If this is the third header (no second header), skip to the
         * next part of the read.
         */
        if (Z2Memcmp (
          readCtx->unprocessedData.data, beginBlk,
          VOLT_SECURE_MAIL_BEGIN_BLOCK_LEN) == 0) 
        {
          /* Set up for reading the next part.
           */                     
          status = 0;
          readCtx->unprocessedData.len = 0;
          goto VoltSecureMailBase64 ;
        }
      }

      /* This is an "extra" header, just Copy it to the extraHeader
       * field in the context. Copy the NULL-terminating character as
       * well.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_MEMORY;
      readCtx->extraHeader.data = (unsigned char *)Z2Realloc (
        readCtx->extraHeader.data, readCtx->unprocessedData.len + readCtx->extraHeader.len);
      if (readCtx->extraHeader.data == (unsigned char *)0)

⌨️ 快捷键说明

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