?? smwrite.c
字號(hào):
/* Copyright 2003-2006, 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"
#include "errorctx.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,
UInt32 theNumLo,
UInt32 theNumHi,
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;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
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;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplBase64, (Pointer)&b64Info,
&(obj->base64));
if (status != 0)
break;
/* Init the subordinate objects.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VtPkcs7WriteInit (
obj->p7SignedData, policyCtx, storageCtx, transportCtx, random);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtPkcs7WriteInit (
obj->p7EnvelopedData, policyCtx, storageCtx, transportCtx, random);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtEncodeInit (obj->base64);
if (status != 0)
break;
/* If there's no content type, use the default.
*/
if (obj->contentInfo.data == (unsigned char *)0)
{
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
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.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
index = VOLT_POLICY_GET_SECURE_MAIL_HEADER;
status = pCtx->PolicyGetInfoAlloc (
policyCtx, VOLT_POLICY_GET_SECURE_MAIL_HEADER,
(Pointer)&index, (Pointer *)&getItem);
if (status != 0)
break;
if (getItem != (VtItem *)0)
{
if ( (getItem->data != (unsigned char *)0) && (getItem->len != 0) )
{
VOLT_SET_FNCT_LINE (fnctLine)
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) )
{
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
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);
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, secureMailObj, status, 0, errorType,
(char *)0, "VoltSecureMailWriteInit", fnctLine, (char *)0)
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;
#if VT_64_BIT_LENGTH == 64
VtUInt64 msgLen;
#else
unsigned int msgLen;
#endif
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]);
VoltEncodeDecodeSizeInfo encodeDecodeSizeInfo;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
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.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
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.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
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.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
#if VT_64_BIT_LENGTH == 64
if ((obj->inputLen64 + (VtUInt64)inputDataLen) > obj->dataLen64)
#else
if ((obj->inputLen + inputDataLen) > obj->dataLen)
#endif
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.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
signedDataLen = inputDataLen + contentReportLen;
if (signedDataLen < inputDataLen)
break;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtPkcs7WriteUpdate (
obj->p7SignedData, random, (unsigned char *)0, signedDataLen,
(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?
*/
VOLT_SET_FNCT_LINE (fnctLine)
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?
*/
encodeDecodeSizeInfo.dataToProcess = (unsigned char *)0;
#if VT_64_BIT_LENGTH == 64
encodeDecodeSizeInfo.dataToProcessLen =
(VtUInt64)envelopedDataLen + (VtUInt64)(preP7->len);
#else
encodeDecodeSizeInfo.dataToProcessLen = envelopedDataLen + preP7->len;
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (encodeDecodeSizeInfo.dataToProcessLen < envelopedDataLen)
break;
#endif
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = obj->GetEncodeDecodeSize (
obj->base64, (VtRandomObject)0, VOLT_CALLER_ENCODE_UPDATE,
&encodeDecodeSizeInfo);
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
msgLen = encodeDecodeSizeInfo.processedDataLen;
#if VT_64_BIT_LENGTH == 64
msgLen += (VtUInt64)preliminaryLen;
if (msgLen > (VtUInt64)0xffffffff)
break;
*messageLen = (unsigned int)msgLen;
#else
msgLen += preliminaryLen;
if (msgLen < preliminaryLen)
break;
*messageLen = msgLen;
#endif
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_BUFFER_TOO_SMALL;
if (bufferSize < *messageLen)
break;
/* If the caller passed NULL input with non-zero inputLen, they
* just wanted the length, don't process.
*/
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -