📄 smwrite.c
字号:
obj->inputLen += inputDataLen;
obj->state = VOLT_SECURE_MAIL_STATE_WRITE_UPDATE;
} while (0);
if (sBuffer != (unsigned char *)0)
Z2Free (sBuffer);
if (eBuffer != (unsigned char *)0)
Z2Free (eBuffer);
return (status);
}
int VoltSecureMailWriteFinal (
VtSecureMailObject secureMailObj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
)
{
int status;
unsigned int inputLen, updateLen, signedDataLen, envelopedDataLen, b64Len;
unsigned int index, offset, totalLen, elementLen, newLineLen;
unsigned char *input, *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);
unsigned int footerLen =
writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].len;
unsigned char *footer =
writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].data;
VtItem *preP7 = &(writeCtx->itemArray[VOLT_WRITE_SM_PRE_PKCS7]);
do
{
/* If a dataLen is not yet set, the inputLen from this call is that
* value.
*/
if (obj->dataLen == 0)
obj->dataLen = inputDataLen;
input = inputData;
inputLen = inputDataLen;
totalLen = 0;
/* Make sure the total len of input equals the "predicted" len.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if ((inputDataLen + obj->inputLen) != obj->dataLen)
break;
/* If the state is INIT, get the lengths.
*/
if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_INIT)
{
status = SetTotalLengths (obj, writeCtx, random);
if (status != 0)
break;
}
/* If the state is INIT_LEN, we're processing the data all at once.
*/
if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_INIT_LEN)
{
/* We know the total length of the output. Is the buffer big
* enough?
*/
status = VT_ERROR_BUFFER_TOO_SMALL;
totalLen =
writeCtx->prelimLen + writeCtx->base64Len + writeCtx->trailLen;
*messageLen = totalLen;
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;
/* The buffer is big enough, call Update to write out the
* preliminary data and what data we can process.
*/
status = VoltSecureMailWriteUpdate (
secureMailObj, random, inputData, inputDataLen,
message, bufferSize, &updateLen);
if (status != 0)
break;
message += updateLen;
bufferSize -= updateLen;
input = (unsigned char *)0;
inputLen = 0;
}
if (obj->state == VOLT_SECURE_MAIL_STATE_WRITE_UPDATE)
{
/* We've called Update, we'll need to call all the Finals.
*/
/* How much space is needed for the last chunk of input.
*/
status = VtPkcs7WriteFinal (
obj->p7SignedData, random, (unsigned char *)0, inputLen + footerLen,
(unsigned char *)0, 0, &signedDataLen);
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
status = VtPkcs7WriteFinal (
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_FINAL,
(unsigned char *)0, envelopedDataLen, &b64Len);
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
/* We know the total length of the output. Is the buffer big
* enough?
* If totalLen is already set, we've already made the check.
*/
if (totalLen == 0)
{
status = VT_ERROR_BUFFER_TOO_SMALL;
*messageLen = b64Len + writeCtx->trailLen;
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;
}
}
else
{
/* If we reach this point, the state was not INIT or UPDATE. We
* can call Final only after Init or Update.
*/
status = VT_ERROR_INVALID_CALL_ORDER;
break;
}
/* 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.
*/
updateLen = 0;
if (inputLen != 0)
{
status = VtPkcs7WriteUpdate (
obj->p7SignedData, random, input, inputLen,
sBuffer, signedDataLen, &updateLen);
if (status != 0)
break;
}
/* Add the contentFooter. If there's no footer, we still want to
* call Final.
*/
status = VtPkcs7WriteFinal (
obj->p7SignedData, random, footer, footerLen,
sBuffer + updateLen, signedDataLen - updateLen, &signedDataLen);
if (status != 0)
break;
signedDataLen += updateLen;
/* 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 = VtPkcs7WriteFinal (
obj->p7EnvelopedData, random, sBuffer, signedDataLen,
eBuffer, envelopedDataLen, &envelopedDataLen);
if (status != 0)
break;
/* Write out the Base64 into the app-supplied buffer.
*/
offset = 0;
if (preP7->len != 0)
{
status = VtEncodeFinal (
obj->base64, (VtRandomObject)0, preP7->data, preP7->len,
message, bufferSize, &b64Len);
if (status != 0)
break;
offset = b64Len;
preP7->len = 0;
}
status = VtEncodeFinal (
obj->base64, (VtRandomObject)0, eBuffer, envelopedDataLen,
message + offset, bufferSize - offset, &b64Len);
if (status != 0)
break;
offset += b64Len;
/* Write out any trailing info.
*/
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_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)
continue;
Z2Memcpy (
message + offset, writeCtx->itemArray[index].data, elementLen);
offset += elementLen;
Z2Memcpy (message + offset, newLine, newLineLen);
offset += newLineLen;
}
obj->inputLen += inputDataLen;
obj->state = VOLT_SECURE_MAIL_STATE_WRITE_FINAL;
} while (0);
if (sBuffer != (unsigned char *)0)
Z2Free (sBuffer);
if (eBuffer != (unsigned char *)0)
Z2Free (eBuffer);
return (status);
}
#define VOLT_CONTENT_TYPE_LABEL "content-type: "
#define VOLT_CONTENT_TYPE_LABEL_LEN 14
#define VOLT_CONTENT_LENGTH_LABEL "content-length: "
#define VOLT_CONTENT_LENGTH_LABEL_LEN 16
#define VOLT_FILE_NAME_LABEL "file-name="
#define VOLT_FILE_NAME_LABEL_LEN 10
#define VOLT_CONTENT_ZDR_UTC "ZDR-Utc: "
#define VOLT_CONTENT_ZDR_UTC_LEN 9
#define VOLT_CONTENT_ZDR_FROM "ZDR-From: "
#define VOLT_CONTENT_ZDR_FROM_LEN 10
#define VOLT_CONTENT_ZDR_TO "ZDR-To: "
#define VOLT_CONTENT_ZDR_TO_LEN 8
#define VOLT_CONTENT_ZDR_SUBJECT "ZDR-Subject: "
#define VOLT_CONTENT_ZDR_SUBJECT_LEN 13
#define VOLT_CONTENT_COMMA_SPACE ", "
#define VOLT_CONTENT_COMMA_SPACE_LEN 2
static int SetTotalLengths (
VoltSecureMailObject *obj,
VoltSecureMailWriteCtx *writeCtx,
VtRandomObject random
)
{
int status;
unsigned int asciiNumLen, reportLen, offset, index, count, maxIndex;
unsigned int newLineLen =
writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].len;
unsigned int footerLen =
writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_FOOTER].len;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VtIdentityObject getId;
char *contentTypeLabel = VOLT_CONTENT_TYPE_LABEL;
char *contentType = VOLT_SECURE_FILE_CONTENT;
char *contentLengthLabel = VOLT_CONTENT_LENGTH_LABEL;
char *zdrUtcLine = VOLT_CONTENT_ZDR_UTC;
char *zdrFromLine = VOLT_CONTENT_ZDR_FROM;
char *zdrToLine = VOLT_CONTENT_ZDR_TO;
char *zdrSubjectLine = VOLT_CONTENT_ZDR_SUBJECT;
char *asciiNum = (char *)0;
unsigned char *newLine =
writeCtx->itemArray[VOLT_WRITE_SM_ITEM_NEW_LINE].data;
VtItem *preP7 = &(writeCtx->itemArray[VOLT_WRITE_SM_PRE_PKCS7]);
VtItem *report = &(writeCtx->itemArray[VOLT_WRITE_SM_ITEM_CONTENT_REPORT]);
VtItem *getName;
VtItem tempItem;
VtTime theTime;
unsigned char utcTime[VOLT_UTC_LEN];
char *commaSpace = VOLT_CONTENT_COMMA_SPACE;
do
{
/* Build the content descriptor VtItem.
*/
reportLen = obj->contentInfo.len;
if ( (obj->formatType == VOLT_MESSAGE_FORMAT_SECURE_MAIL) ||
(obj->formatType == VOLT_MESSAGE_FORMAT_ZDM_MAIL) )
{
/* Build the content-type: and content-length: lines. First, get
* the length as ASCII characters.
*/
status = ConvertNumToAsciiAlloc (
libCtx, obj->dataLen + footerLen, &asciiNum, &asciiNumLen);
if (status != 0)
break;
/* Build the content descriptor buffer, content type label, then
* the content type, new line, content len label, then length,
* new line.
* If this is ZDM there's more to add.
* Finally, one last new line.
*/
status = AppendToVtItem (
libCtx, contentTypeLabel, VOLT_CONTENT_TYPE_LABEL_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
status = AppendToVtItem (
libCtx, obj->contentInfo.data, obj->contentInfo.len,
newLine, newLineLen, report);
if (status != 0)
break;
status = AppendToVtItem (
libCtx, contentLengthLabel, VOLT_CONTENT_LENGTH_LABEL_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
status = AppendToVtItem (
libCtx, asciiNum, asciiNumLen, newLine, newLineLen, report);
if (status != 0)
break;
if (obj->formatType == VOLT_MESSAGE_FORMAT_ZDM_MAIL)
{
status = AppendToVtItem (
libCtx, zdrUtcLine, VOLT_CONTENT_ZDR_UTC_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
VtGetTime ((VtLibCtx)libCtx, &theTime);
VoltConvertVtTimeToUTC (&theTime, utcTime);
status = AppendToVtItem (
libCtx, utcTime, VOLT_UTC_LEN, newLine, newLineLen, report);
if (status != 0)
break;
status = AppendToVtItem (
libCtx, zdrFromLine, VOLT_CONTENT_ZDR_FROM_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
/* Get the email address of the sender.
* If we can't get the email address out, don't quit, just
* print a blank line.
*/
tempItem.data = (unsigned char *)0;
tempItem.len = 0;
status = VtGetIdentityParam (
writeCtx->senderIdRef, VtIdentityParamCommonName,
(Pointer *)&getName);
if (status == 0)
tempItem = *getName;
status = AppendToVtItem (
libCtx, tempItem.data, tempItem.len, newLine, newLineLen, report);
if (status != 0)
break;
/* Print out the list of recipients.
*/
status = AppendToVtItem (
libCtx, zdrToLine, VOLT_CONTENT_ZDR_TO_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
status = VtGetIdentityListCount (
writeCtx->recipListRef, &count, &maxIndex);
if (status != 0)
break;
for (index = 0; index <= maxIndex; ++index)
{
status = VtGetIdentityListIdentity (
writeCtx->recipListRef, index, &getId);
if (status == VT_ERROR_NO_ID_AT_INDEX)
continue;
if (status != 0)
break;
tempItem.data = (unsigned char *)0;
tempItem.len = 0;
status = VtGetIdentityParam (
getId, VtIdentityParamCommonName, (Pointer *)&getName);
if (status == 0)
tempItem = *getName;
if (index != maxIndex)
{
/* If this is not the last email, we'll need a comma after
* the address.
*/
status = AppendToVtItem (
libCtx, tempItem.data, tempItem.len,
commaSpace, VOLT_CONTENT_COMMA_SPACE_LEN, report);
if (status != 0)
break;
}
else
{
/* If this is the last email, start a new line after the
* address.
*/
status = AppendToVtItem (
libCtx, tempItem.data, tempItem.len, newLine, newLineLen,
report);
if (status != 0)
break;
}
}
if (status != 0)
break;
/* Finally, the subject.
*/
status = AppendToVtItem (
libCtx, zdrSubjectLine, VOLT_CONTENT_ZDR_SUBJECT_LEN,
(unsigned char *)0, 0, report);
if (status != 0)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -