📄 writeenv.c
字号:
/* Copyright 2003-2005, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "p7obj.h"
#include "idobj.h"
#include "derhelp.h"
#include "oidlist.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
));
/* Build the RecipientData struct. The caller passes the RecipientData,
* which should contain an idRef and nothing else. This function builds
* the rest of the info.
* <p>The function does no argument checking, it is the responsibility
* of the caller not to make mistakes.
*
* @param p7Obj Contains things the function needs, such as libCtx and
* localCtx.
* @param random A source of random bytes, if necessary.
* @param base64 An object built to encode binary data to Base64.
* @param symKeyData The key data to encrypt with the recipient's
* public key.
* @param symKeyDataLen The length, in bytes, of the key data.
* @param recipientData The struct containing the identity and the
* empty fields to fill.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV VoltBuildRecipientData VOLT_PROTO_LIST ((
VoltPkcs7Object *p7Obj,
VtRandomObject random,
VtAlgorithmObject base64,
unsigned char *symKeyData,
unsigned int symKeyDataLen,
VoltRecipientData *recipientData
));
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;
do
{
/* The state must be VOLT_P7_STATE_ENV_WRITE_SET, if not, we're
* not allowed to call WriteInit.
*/
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.
*/
status = VT_ERROR_INVALID_P7_OBJ;
if ( (envCtx->recipList == (VtIdentityList)0) ||
(envCtx->symEncryptor == (VtAlgorithmObject)0) )
break;
/* Make sure the recipientData array is not yet built.
*/
if (envCtx->recipients != (VoltRecipientData *)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;
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)
{
status = VT_ERROR_MEMORY;
keyLen = (envCtx->symKeyBits + 7) / 8;
keyData = (unsigned char *)Z2Malloc (keyLen, VOLT_MEMORY_SENSITIVE);
if (keyData == (unsigned char *)0)
break;
status = VtGenerateRandomBytes (random, keyData, keyLen);
if (status != 0)
break;
status = VtCreateKeyObject (
(VtLibCtx)libCtx, VtKeyImplDefault, (Pointer)0, &(envCtx->symKey));
if (status != 0)
break;
keyItem.data = keyData;
keyItem.len = keyLen;
status = VtSetKeyParam (
envCtx->symKey, envCtx->SymKeyParam, (Pointer)&keyItem);
if (status != 0)
break;
getKeyData = &keyItem;
}
else
{
status = VtGetKeyParam (
envCtx->symKey, envCtx->SymKeyParam, (Pointer *)&getKeyData);
if (status != 0)
break;
}
/* How many recipients are there?
*/
status = VtGetIdentityListCount (envCtx->recipList, &idCount, &maxIndex);
if (status != 0)
break;
/* Build the array of recipientDatas. Use index as a temp variable.
*/
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.
*/
indexD = 0;
for (index = 0; index <= maxIndex; ++index)
{
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.
*/
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;
status = VoltBuildRecipientData (
obj, random, base64, getKeyData->data, getKeyData->len,
&(envCtx->recipients[indexD]));
if (status != 0)
break;
envCtx->totalRecipInfoLen += envCtx->recipients[indexD].recipInfoLen;
indexD++;
}
if (status != 0)
break;
obj->state = VOLT_P7_STATE_ENV_WRITE_INIT;
} while (0);
VtDestroyAlgorithmObject (&base64);
if (keyData != (unsigned char *)0)
Z2Free (keyData);
return (status);
}
int VoltP7EnvWriteUpdate (
VtPkcs7Object pkcs7Obj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -