📄 writeenv.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "p7obj.h"
#include "idobj.h"
#include "algobj.h"
#include "derhelp.h"
#include "oidlist.h"
#include "errorctx.h"
/* Set up the OpenSSL ASN.1 templates.
*/
ASN1_SEQUENCE (Asn1EncryptedInfo) =
{
ASN1_SIMPLE (Asn1EncryptedInfo, contentType, Asn1ObjectId),
ASN1_SIMPLE (Asn1EncryptedInfo, algId, Asn1Encoded),
ASN1_IMP (Asn1EncryptedInfo, encryptedContent, Asn1EncryptedContent, 0)
} ASN1_SEQUENCE_END (Asn1EncryptedInfo);
IMPLEMENT_ASN1_FUNCTIONS (Asn1EncryptedInfo)
ASN1_SEQUENCE (Asn1EnvelopedData) =
{
ASN1_SIMPLE (Asn1EnvelopedData, version, ASN1_INTEGER),
ASN1_SET_OF (Asn1EnvelopedData, recipInfo, Asn1RecipientInfo),
ASN1_SIMPLE (Asn1EnvelopedData, encryptedInfo, Asn1EncryptedInfo)
} ASN1_SEQUENCE_END (Asn1EnvelopedData);
IMPLEMENT_ASN1_FUNCTIONS (Asn1EnvelopedData)
ASN1_SEQUENCE (Asn1EnvelopedContent) =
{
ASN1_SIMPLE (Asn1EnvelopedContent, contentType, Asn1ObjectId),
ASN1_EXP (Asn1EnvelopedContent, envelopedData, Asn1EnvelopedData, 0)
} ASN1_SEQUENCE_END (Asn1EnvelopedContent);
IMPLEMENT_ASN1_FUNCTIONS (Asn1EnvelopedContent)
/* The identity object should contain an encoded ID. Build the
* identity-based IssuerAndSerialNumber out of it.
*
* IssuerAndSerialNumber ::= SEQUENCE {
* issuer Name,
* serialNumber CertificateSerialNumber }
*
* CertificateSerialNumber ::= INTEGER
*
* The serialNumber is always 1 (02 01 01).
* <p>The Name will contain one Attribute (OID: id-at-name), which is the
* PrintableString of the Base64 encoded identity string.
*
* Name ::= CHOICE {
* RDNSequence }
*
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::=
* SET OF AttributeTypeAndValue
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY DEFINED BY AttributeType
*
* The IssuerAndSerialNumber in this context will then be fixed at
*
* 30 len SEQ: IssuerAndSerialNumber
* 30 len SEQ OF RDN
* 31 len SET OF Attribute
* 30 len SEQ: Attribute
* 06 03 OID
* 55 04 29
* 13 len value (ANY, PrintableString)
* <Base64 of encoded ID>
* 02 01 INTEGER: serialNumber
* 01
*
* This function will allocate the space necessary to hold the encoding
* and return the new buffer and its length. It is the responsibility
* of the caller to free that memory.
* <p>This function assumes that the identity has been encoded and that
* it exists in the encoding field of the VoltIdentityObject. The
* routine will do no argument checking.
*
* @param libCtx The library ctx to use.
* @param idObj The object containing the ID to build into issuer and
* serial number.
* @param base64 An object built to encode binary data to Base64.
* @param issuerSerial The address where the function will deposit the
* pointer to the newly allocated buffer.
* @param issuerSerialLen The address where the function will deposit
* the length of the encoding.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV VoltBuildIssuerSerialAlloc VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VtIdentityObject idObj,
VtAlgorithmObject base64,
unsigned char **issuerSerial,
unsigned int *issuerSerialLen
));
int VoltP7EnvWriteInit (
VtPkcs7Object pkcs7Obj,
VtPolicyCtx policyCtx,
VtStorageCtx storageCtx,
VtTransportCtx transportCtx,
VtRandomObject random
)
{
int status;
unsigned int index, indexC, indexD, idCount, maxIndex, keyLen;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltPkcs7WriteEnvCtx *envCtx = (VoltPkcs7WriteEnvCtx *)(obj->localCtx);
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
unsigned char *keyData = (unsigned char *)0;
VtAlgorithmObject base64 = (VtAlgorithmObject)0;
VtIdentityObject currentId, compareId;
VtBase64Info base64Info;
VtItem keyItem;
VtItem *getKeyData;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* The state must be VOLT_P7_STATE_ENV_WRITE_SET, if not, we're
* not allowed to call WriteInit.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_CALL_ORDER;
if (obj->state != VOLT_P7_STATE_ENV_WRITE_SET)
break;
/* This implementation does not work without recipients or a
* symmetric encryptor. The recipients might be represented as an
* IdentityList or as a list of RecipientData.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_P7_OBJ;
if ( (envCtx->recipList == (VtIdentityList)0) &&
(envCtx->recipients == (VoltRecipientData *)0) )
break;
VOLT_SET_FNCT_LINE (fnctLine)
if (envCtx->symEncryptor == (VtAlgorithmObject)0)
break;
/* Build a Base64 object. We'll need it later for each recipient,
* so rather than build again and again, build one now and pass it
* around.
*/
base64Info.base64BlockSize = 76;
base64Info.newLineCharacter = VT_BASE64_NO_NEW_LINE;
base64Info.errorCheck = VT_BASE64_NO_ERROR_CHECK;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplBase64, (Pointer)&base64Info,
&base64);
if (status != 0)
break;
/* If there's no key object yet, build it. If there is one, get the
* key data.
*/
if (envCtx->symKey == (VtKeyObject)0)
{
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_MEMORY;
keyLen = (envCtx->symKeyBits + 7) / 8;
keyData = (unsigned char *)Z2Malloc (keyLen, VOLT_MEMORY_SENSITIVE);
if (keyData == (unsigned char *)0)
break;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGenerateRandomBytes (random, keyData, keyLen);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtCreateKeyObject (
(VtLibCtx)libCtx, VtKeyImplDefault, (Pointer)0, &(envCtx->symKey));
if (status != 0)
break;
keyItem.data = keyData;
keyItem.len = keyLen;
VOLT_SET_FNCT_LINE (fnctLine)
status = VtSetKeyParam (
envCtx->symKey, envCtx->SymKeyParam, (Pointer)&keyItem);
if (status != 0)
break;
getKeyData = &keyItem;
}
else
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGetKeyParam (
envCtx->symKey, envCtx->SymKeyParam, (Pointer *)&getKeyData);
if (status != 0)
break;
}
/* If we don't have the RecipientData array built, build it. If it
* is built, just compute the totalRecipInfoLen and we're done.
*/
if (envCtx->recipients != (VoltRecipientData *)0)
{
envCtx->totalRecipInfoLen = 0;
for (index = 0; index < envCtx->recipientsCount; ++index)
envCtx->totalRecipInfoLen += envCtx->recipients[index].recipInfoLen;
break;
}
/* How many recipients are there?
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGetIdentityListCount (envCtx->recipList, &idCount, &maxIndex);
if (status != 0)
break;
/* Build the array of recipientDatas. Use index as a temp variable.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_MEMORY;
index = idCount * sizeof (VoltRecipientData);
envCtx->recipients = (VoltRecipientData *)Z2Malloc (index, 0);
if (envCtx->recipients == (VoltRecipientData *)0)
break;
Z2Memset (envCtx->recipients, 0, index);
envCtx->recipientsCount = idCount;
/* Cycle through the identities, creating RecipientData for each.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
indexD = 0;
for (index = 0; index <= maxIndex; ++index)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGetIdentityListIdentity (
envCtx->recipList, index, ¤tId);
if (status != 0)
{
/* If status is VT_ERROR_NO_ID_AT_INDEX, don't quit, just move
* on to the next ID in the list.
*/
if (status != VT_ERROR_NO_ID_AT_INDEX)
break;
status = 0;
continue;
}
/* Make sure the identity is encoded. Calling this routine will
* build the encoded ID internally, which is all we need. Use
* keyLen as a temp variable. We're expecting the
* BUFFER_TOO_SMALL error.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VtEncodeIdentity (
currentId, VT_ENCODE_IBCS_2_V_DISTRICT, policyCtx,
storageCtx, transportCtx, (unsigned char *)0, 0, &keyLen);
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
/* If this is a repeat identity, don't bother with it. Set it to
* be inactive. Compare with all previously encoded ID's.
* Use keyLen as a temp variable.
*/
keyLen = 0;
for (indexC = 0; indexC < index; ++indexC)
{
status = VtGetIdentityListIdentity (
envCtx->recipList, indexC, &compareId);
if (status != 0)
continue;
VoltIsSameIdentity (currentId, compareId, &keyLen);
if (keyLen != 0)
break;
}
/* If keyLen is not 0, there was a matching ID, ignore this
* identity.
*/
if (keyLen != 0)
{
VtSetEntryStatusInIdentityList (
envCtx->recipList, index, VT_RECIPIENT_LIST_ENTRY_INACTIVE);
continue;
}
/* Build the RecipientData struct for this identity.
*/
envCtx->recipients[indexD].idRef = currentId;
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltBuildRecipientData (
(VoltObject *)obj, random, base64, VtDerCoderBFType1IBE,
getKeyData->data, getKeyData->len, &(envCtx->recipients[indexD]));
if (status != 0)
break;
envCtx->totalRecipInfoLen += envCtx->recipients[indexD].recipInfoLen;
indexD++;
}
if (status != 0)
break;
} while (0);
VtDestroyAlgorithmObject (&base64);
if (keyData != (unsigned char *)0)
Z2Free (keyData);
if (status == 0)
obj->state = VOLT_P7_STATE_ENV_WRITE_INIT;
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, pkcs7Obj, status, 0, errorType,
(char *)0, "VoltP7EnvWriteInit", fnctLine, (char *)0)
return (status);
}
int VoltP7EnvWriteUpdate (
VtPkcs7Object pkcs7Obj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
)
{
int status;
unsigned int index, tempLen, recipOutLen, offset;
#if VT_64_BIT_LENGTH == 64
VtUInt64 encryptedDataLen, outputLen, encContentInfoLen;
VtUInt64 seqLen, expLen, totalLen;
#else
unsigned int encryptedDataLen, outputLen, encContentInfoLen;
unsigned int seqLen, expLen, totalLen;
#endif
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 };
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
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.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
#if VT_64_BIT_LENGTH == 64
if ((VtUInt64)inputDataLen > obj->dataLen64)
#else
if (inputDataLen > obj->dataLen)
#endif
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).
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
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, and it
* will not work with 64-bit lengths, 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -