📄 writeenv.c
字号:
)
{
int status;
unsigned int index, encryptedDataLen, encContentInfoLen;
unsigned int seqLen, expLen, totalLen, tempLen, outputLen, offset;
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 };
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.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (inputDataLen > obj->dataLen)
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).
*/
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, 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)
break;
*/
/* Currently, this code supports only block ciphers in CBC mode
* with P5 padding. So this is how to compute outputLen.
*/
encryptedDataLen = obj->dataLen / envCtx->blockSize;
if (envCtx->blockSize != 1)
encryptedDataLen++;
encryptedDataLen *= envCtx->blockSize;
/* Add in the total length of encrypted data so all other lengths
* will be computed correctly. Then later on, subtract the amount
* of encryptedData we will not output.
*/
outputLen = VoltDetermineDerLengthLen (encryptedDataLen);
outputLen += (1 + encryptedDataLen);
/* Add in the symmetric encryption algID and the Data OID.
* Don't add amounts twice.
*/
encContentInfoLen =
outputLen + envCtx->symEncryptorAlgId.len + VoltP7DataOidBytesLen + 2;
outputLen = VoltDetermineDerLengthLen (encContentInfoLen);
outputLen += encContentInfoLen + 1;
/* What is the SET OF for RecipientInfos going to be? Add in the
* varsion.
*/
outputLen += VoltDetermineDerLengthLen (envCtx->totalRecipInfoLen);
outputLen += envCtx->totalRecipInfoLen + 4;
/* Now add in the SEQUENCE that is the EnvelopedData.
*/
seqLen = outputLen;
outputLen += VoltDetermineDerLengthLen (outputLen);
outputLen++;
/* Next is the EXPLICIT.
*/
expLen = outputLen;
outputLen += VoltDetermineDerLengthLen (outputLen);
outputLen++;
/* Add in the EnvelopedData OID.
*/
outputLen += VoltP7EnvDataOidBytesLen + 2;
/* Now comes the overall SEQUENCE.
*/
totalLen = outputLen;
outputLen += VoltDetermineDerLengthLen (outputLen);
outputLen++;
/* If the actual inputLen is not the same as what the total input
* len is going to be, subtract off the encryptedDataLen, then add
* the actual inputLen.
*/
if (inputDataLen != obj->dataLen)
{
outputLen -= encryptedDataLen;
/* For the moment, this does not work with NULL input, so compute
* it explicitly.
*/
/* status = VtEncryptUpdate (
envCtx->symEncryptor, random, (unsigned char *)0, inputDataLen,
(unsigned char *)0, 0, &tempLen);
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
*/
index = inputDataLen / envCtx->blockSize;
tempLen = index * envCtx->blockSize;
outputLen += tempLen;
}
/* Is the buffer big enough?
*/
status = VT_ERROR_BUFFER_TOO_SMALL;
*messageLen = outputLen;
if (bufferSize < outputLen)
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, write out the prefix.
* First, the 30 len of the overall contentInfo.
*/
offset = VoltWriteDerTagAndLen (message, 0x30, totalLen);
/* Write out the EnvelopedData OID.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x06, VoltP7EnvDataOidBytesLen);
Z2Memcpy (message + offset, envDataOid, VoltP7EnvDataOidBytesLen);
offset += VoltP7EnvDataOidBytesLen;
/* EXPLICIT.
*/
offset += VoltWriteDerTagAndLen (message + offset, 0xA0, expLen);
/* SEQUENCE.
*/
offset += VoltWriteDerTagAndLen (message + offset, 0x30, seqLen);
/* version (we support only version 0).
*/
message[offset] = 0x02;
offset++;
message[offset] = 0x01;
offset++;
message[offset] = 0x00;
offset++;
/* SET OF.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x31, envCtx->totalRecipInfoLen);
/* Write out each of the RecipientInfos.
*/
for (index = 0; index < envCtx->recipientsCount; ++index)
{
if (envCtx->recipients[index].idRef == (VtIdentityObject)0)
continue;
status = VT_ERROR_INVALID_INPUT;
temp = message + offset;
outputLen = i2d_Asn1RecipientInfo (
envCtx->recipients[index].recipInfo, &temp);
if (outputLen != envCtx->recipients[index].recipInfoLen)
break;
offset += outputLen;
status = 0;
}
/* Next is the EncryptedContentInfo.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x30, encContentInfoLen);
/* The OID of the data being encrypted: Data.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x06, VoltP7DataOidBytesLen);
Z2Memcpy (message + offset, dataOid, VoltP7DataOidBytesLen);
offset += VoltP7DataOidBytesLen;
/* The symmetric algorithm ID.
*/
Z2Memcpy (
message + offset, envCtx->symEncryptorAlgId.data,
envCtx->symEncryptorAlgId.len);
offset += envCtx->symEncryptorAlgId.len;
/* EncryptedContent, IMPLICIT.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x80, encryptedDataLen);
}
else if (obj->state == VOLT_P7_STATE_ENV_WRITE_UPDATE)
{
/* If Update, make sure the amount of input does not exceed the
* dataLen.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if ((inputDataLen + obj->inputLen) > obj->dataLen)
break;
/* Is the output buffer big enough?
*/
*messageLen = 0;
status = 0;
if (inputDataLen == 0)
break;
tempLen = inputDataLen + envCtx->unprocessedDataLen;
/* If this is the last of the input data, we'll call
* EncryptFinal, if not, we'll call EncryptUpdate.
*/
if ((inputDataLen + obj->inputLen) < obj->dataLen)
{
/* For the moment, this does not work with NULL input, so
* compute the required output size explicitly.
*/
/* status = VtEncryptUpdate (
envCtx->symEncryptor, random, (unsigned char *)0, inputDataLen,
(unsigned char *)0, 0, &tempLen);
*/
index = tempLen / envCtx->blockSize;
tempLen = index * envCtx->blockSize;
status = VT_ERROR_BUFFER_TOO_SMALL;
}
else
{
/* For the moment, this does not work with NULL input, so
* compute the required output size explicitly.
*/
/* status = VtEncryptFinal (
envCtx->symEncryptor, random, inputData, inputDataLen,
(unsigned char *)0, 0, &tempLen);
*/
index = tempLen / envCtx->blockSize;
if (envCtx->blockSize != 1)
index++;
tempLen = index * envCtx->blockSize;
status = VT_ERROR_BUFFER_TOO_SMALL;
}
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
*messageLen = tempLen;
if (bufferSize < tempLen)
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;
offset = 0;
}
else
{
status = VT_ERROR_INVALID_CALL_ORDER;
break;
}
/* Encrypt the bytes given.
*/
if ((inputDataLen + obj->inputLen) < obj->dataLen)
{
/* For the moment we need to compute unprocessedDataLen. When we
* fix the NULL input issue, we can get rid of this.
*/
tempLen = inputDataLen + envCtx->unprocessedDataLen;
index = tempLen / envCtx->blockSize;
envCtx->unprocessedDataLen = tempLen - (index * envCtx->blockSize);
status = VtEncryptUpdate (
envCtx->symEncryptor, random, inputData, inputDataLen,
message + offset, bufferSize - offset, &tempLen);
}
else
{
envCtx->unprocessedDataLen = 0;
status = VtEncryptFinal (
envCtx->symEncryptor, random, inputData, inputDataLen,
message + offset, bufferSize - offset, &tempLen);
}
if (status != 0)
break;
obj->inputLen += inputDataLen;
obj->state = VOLT_P7_STATE_ENV_WRITE_UPDATE;
} while (0);
return (status);
}
int VoltP7EnvWriteFinal (
VtPkcs7Object pkcs7Obj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
)
{
int status;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
*messageLen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -