📄 writesign.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"
#include "vcert.h"
#include "digest.h"
#include "vtime.h"
#include "surrender.h"
/* Set up the OpenSSL ASN.1 templates.
*/
ASN1_SEQUENCE (Asn1P9Attribute) =
{
ASN1_SIMPLE (Asn1P9Attribute, attrType, Asn1ObjectId),
ASN1_SET_OF (Asn1P9Attribute, attrValues, Asn1Encoded)
} ASN1_SEQUENCE_END (Asn1P9Attribute);
IMPLEMENT_ASN1_FUNCTIONS (Asn1P9Attribute)
ASN1_SEQUENCE (Asn1IssuerSerial) =
{
ASN1_SIMPLE (Asn1IssuerSerial, issuerName, Asn1Encoded),
ASN1_SIMPLE (Asn1IssuerSerial, serialNumber, ASN1_INTEGER)
} ASN1_SEQUENCE_END (Asn1IssuerSerial);
IMPLEMENT_ASN1_FUNCTIONS (Asn1IssuerSerial)
ASN1_SEQUENCE (Asn1SignerInfo) =
{
ASN1_SIMPLE (Asn1SignerInfo, version, ASN1_INTEGER),
ASN1_SIMPLE (Asn1SignerInfo, issuerSerial, Asn1IssuerSerial),
ASN1_SIMPLE (Asn1SignerInfo, digestAlg, Asn1Encoded),
ASN1_OPT (Asn1SignerInfo, authAttributes, Asn1Encoded),
ASN1_SIMPLE (Asn1SignerInfo, signatureAlg, Asn1Encoded),
ASN1_SIMPLE (Asn1SignerInfo, signature, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT (Asn1SignerInfo, unauthAttributes, Asn1P9Attribute, 1),
} ASN1_SEQUENCE_END (Asn1SignerInfo);
IMPLEMENT_ASN1_FUNCTIONS (Asn1SignerInfo)
/* Create an Asn1SignerInfo object, then set it with the information
* found in the signerInfo struct.
* <p>The caller passes in a VoltP7SignerInfo struct containing key and
* cert defining the signer. The struct also contains the field where
* the function will place the created Asn1 object.
* <p>The struct also contains a filed for the length of the
* signerInfo. This is the length of the encoded SignerInfo. This length
* will be an upper bound, the actual length may be shorter.
*
* @param p7Obj The object containing the signCtx and other info.
* @param surrCtx If not NULL a surrender ctx to pass on to subordinate
* objects.
* @param random A random object, if needed.
* @param signerInfo The struct containing the key and cert, also the
* place where the created Asn1 object and length will be deposited.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV BuildSignerInfoCreate VOLT_PROTO_LIST ((
VoltPkcs7Object *p7Obj,
VoltSurrenderCtx *surrCtx,
VtRandomObject random,
unsigned char *digestBuf,
unsigned int digestLen,
VoltP7SignerInfo *signerInfo
));
/* Build the AuthenticatedAttributes for a SignedData message.
* <p>Actually, this builds only the following three attributes:
* pkcs-9-at-contentType, pkcs-9-at-messageDigest, and
* pkcs-9-at-signingTime.
* <p>If using AuthenticatedAttributes in a P7 SignedData message, the
* contentType and messageDigest are required.
* <p>The input flag contentType must be one of the following.
* <code>
* <pre>
* VT_PKCS7_DATA
* VT_PKCS7_SIGNED_DATA
* VT_PKCS7_ENVELOPED_DATA
* VT_PKCS7_SIGN_ENV_DATA
* VT_PKCS7_DIGESTED_DATA
* VT_PKCS7_ENCRYPTED_DATA
* </pre>
* </code>
* <p>This routine will create the DER encoding of the Attributes:
* <code>
* <pre>
* Attributes ::= SET OF {
* Attribute }
*
* Attribute ::= SEQUENCE {
* type OID,
* values SET OF ANY }
* </pre>
* </code>
* <p>For SignedData, the Attributes are Implicit, so the function will
* make sure the appropriate tag is used.
* <p>This routine will fill the provided buffer. If no buffer is given
* or if the buffer is too small, the function will return
* VT_ERROR_BUFFER_TOO_SMALL and set the authAttrsLen to the needed
* size.
*
* @param p7Obj The object containing info needed, such as signCtx and
* libCtx.
* @param contentType A flag indicating what contentType is being
* signed (Data, SignedData, EnvelopedData, etc.).
* @param contentDigest The digest of the content, this is what will be
* the value of the messageDigest attribute.
* @param contentDigestLen The length, in bytes, of the contentDigest.
* @param theTime The time to use for signingTime.
* @param authAttrs The buffer the function will fill with the
* attributes.
* @param bufferSize The size, in bytes of the output buffer.
* @param authAttrsLen The address where this function will deposit the
* length, in bytes, of the encoding of the attributes.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV BuildAuthAttributes VOLT_PROTO_LIST ((
VoltPkcs7Object *p7Obj,
unsigned int contentType,
unsigned char *contentDigest,
unsigned int contentDigestLen,
VtTime *theTime,
unsigned char *authAttrs,
unsigned int bufferSize,
unsigned int *authAttrsLen
));
/* Fix the signature so that the signatureLen is the same as
* sigBufSize. Do this by prepending 00 bytes in the appropriate
* places.
* <p>This particular function operates on DSA signatures only. In the
* future, we'll have to be able to fix any signature. This function
* also expects r and s to be 20 bytes. In other words, the signature
* was created using DSA with a subprime of 160 bits.
* <p>This function expects the signature to be in the buffer and that the
* buffer is sigBufSize bytes big. It will go to the address given by
* signatureLen to find the actual signatureLen, and it will set that
* value to the new signatureLen.
*
* @param libCtx
* @param signature
* @param sigBufSize
* @param signatureLen
* @return none
*/
static void VOLT_CALLING_CONV FixDsaSignature VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
unsigned char *signature,
unsigned int sigBufSize,
unsigned int *signatureLen
));
int VoltP7SignWriteInit (
VtPkcs7Object pkcs7Obj,
VtPolicyCtx policyCtx,
VtStorageCtx storageCtx,
VtTransportCtx transportCtx,
VtRandomObject random
)
{
int status;
unsigned int index;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltPkcs7WriteSignCtx *signCtx = (VoltPkcs7WriteSignCtx *)(obj->localCtx);
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltP7SignerInfo *currentSignerInfo;
VtCertObject nextCert = (VtCertObject)0;
VtItem *getCertData = (VtItem *)0;
VtKeyObject *obtainKey;
VtCertObject *obtainCert;
VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
do
{
if ( ((obj->voltObject.objectType & VOLT_OBJECT_TYPE_SURRENDER) != 0) &&
(obj->voltObject.surrenderCtx != (Pointer)0) )
surrCtx = (VoltSurrenderCtx *)(obj->voltObject.surrenderCtx);
/* The state must be VOLT_P7_STATE_SIGN_WRITE_SET, if not, we're
* not allowed to call WriteInit.
*/
status = VT_ERROR_INVALID_CALL_ORDER;
if (obj->state != VOLT_P7_STATE_SIGN_WRITE_SET)
break;
/* This implementation does not work without signers.
*/
status = VT_ERROR_INVALID_P7_OBJ;
if (signCtx->signerInfosCount == 0)
break;
/* Get the signing time.
*/
VtGetTime ((VtLibCtx)libCtx, &(signCtx->signingTime));
/* For each of the signers, get the private key and cert. This
* implementation of P7 requires a cert for each signer.
*/
status = 0;
for (index = 0; index < signCtx->signerInfosCount; ++index)
{
currentSignerInfo = &(signCtx->signerInfos[index]);
if ( (currentSignerInfo->priKeyRef == (VtKeyObject)0) &&
(currentSignerInfo->priKey != (VtKeyObject)0) )
currentSignerInfo->priKeyRef = currentSignerInfo->priKey;
/* Check to see if we already have a key and cert.
*/
obtainKey = (VtKeyObject *)0;
obtainCert = (VtCertObject *)0;
if (currentSignerInfo->priKeyRef == (VtKeyObject)0)
obtainKey = &(currentSignerInfo->priKey);
if (currentSignerInfo->cert.data == (unsigned char *)0)
obtainCert = &nextCert;
/* If there's no DSA private key and/or cert, get them. If we
* already have them, no need. We don't need the IBE private key.
*/
if ( (obtainKey != (VtKeyObject *)0) ||
(obtainCert != (VtCertObject *)0) )
{
status = VoltP7GetKeysAndCert (
surrCtx, currentSignerInfo->signerId, random, policyCtx, storageCtx,
transportCtx, obtainCert, (VtKeyObject *)0, obtainKey);
if (status != 0)
break;
}
/* Get the cert data.
*/
if (obtainCert != (VtCertObject *)0)
{
status = VtGetCertParam (
nextCert, VtCertParamX509DerData, (Pointer *)&getCertData);
if (status != 0)
break;
/* Copy the cert data.
*/
status = VT_ERROR_MEMORY;
if (currentSignerInfo->cert.data != (unsigned char *)0)
Z2Free (currentSignerInfo->cert.data);
currentSignerInfo->cert.data = Z2Malloc (getCertData->len, 0);
if (currentSignerInfo->cert.data == (unsigned char *)0)
break;
Z2Memcpy (
currentSignerInfo->cert.data, getCertData->data, getCertData->len);
currentSignerInfo->cert.len = getCertData->len;
status = 0;
}
if (obtainKey != (VtKeyObject *)0)
currentSignerInfo->priKeyRef = currentSignerInfo->priKey;
/* We only needed this object to get the data. Destroy it so
* the next iteration will have a NULL.
*/
VtDestroyCertObject (&nextCert);
/* Now that we have the key and cert, build the Asn1SignerInfo
* object.
*/
status = BuildSignerInfoCreate (
obj, surrCtx, random, signCtx->digest, signCtx->digestSize,
currentSignerInfo);
if (status != 0)
break;
signCtx->totalSignerInfoLen += currentSignerInfo->signerInfoLen;
signCtx->totalCertLen += currentSignerInfo->cert.len;
}
/* Count up the extra certs.
*/
for (index = 0; index < signCtx->extraCertsCount; ++index)
signCtx->totalCertLen += signCtx->extraCerts[index].len;
} while (0);
if (status == 0)
obj->state = VOLT_P7_STATE_SIGN_WRITE_INIT;
VtDestroyCertObject (&nextCert);
return (status);
}
int VoltP7SignWriteUpdate (
VtPkcs7Object pkcs7Obj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
)
{
int status;
unsigned int contentLen, contentInfoLen, signedDataLen, explicitLen;
unsigned int totalLen, outputLen, offset;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltPkcs7WriteSignCtx *signCtx = (VoltPkcs7WriteSignCtx *)(obj->localCtx);
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
unsigned char signedDataOid[VoltP7SignDataOidBytesLen] =
{ VoltP7SignDataOidBytes };
unsigned char dataOid[VoltP7DataOidBytesLen] = { VoltP7DataOidBytes };
do
{
/* The state must be INIT or UPDATE.
*/
if (obj->state == VOLT_P7_STATE_SIGN_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 <SignedData OID> contentType
* A0 len EXPLICIT content
* 30 len SignedData
* 02 01 01 version
* 31 len digestAlgorithms
* <digest algID>
* 30 len contentInfo
* 06 len <Data OID> contentType
* A0 len EXPLICIT content
* 04 len Data
*/
/* Work up from the bottom. Start with the 04 len, how many bytes
* make up the length octets? Then add in the length of the data
* itself.
* Later on, we'll need to subtract the number of bytes not
* passed in during this call. We're counting the total bytes
* that will be passed in (obj->dataLen) in order to get the
* lengths in the encoding correct. However, we may not have all
* the data now, inputDataLen might be smaller.
*/
outputLen = VoltDetermineDerLengthLen (obj->dataLen);
outputLen += (1 + obj->dataLen);
/* Now add in the length of the A0 len. Then add in the number of
* bytes that make up the OID for the Data itself.
*/
contentLen = outputLen;
outputLen += VoltDetermineDerLengthLen (contentLen);
outputLen += VoltP7DataOidBytesLen + 3;
/* Now determine the length of the 30 len of the contentInfo of
* the SignedData (this is the content that is being signed, so
* it is the Data construct).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -