📄 writesign.c
字号:
*/
contentInfoLen = outputLen;
outputLen += VoltDetermineDerLengthLen (contentInfoLen);
outputLen++;
/* Add in the length of the SET OF digest algID's. We're assuming
* here that lengths will never be longer than 127 bytes. This
* implementation works with only one digest algorithm, so the
* SET OF is actually a SET OF one algID.
* Then add in the version (3 bytes).
*/
outputLen += signCtx->digestAlgId.len + 5;
/* Figure out the 30 len of the SignedData content. This includes
* the certs and signerInfo's. Use offset as a temp variable.
*/
signedDataLen = VoltDetermineDerLengthLen (signCtx->totalCertLen);
signedDataLen += VoltDetermineDerLengthLen (signCtx->totalSignerInfoLen);
signedDataLen +=
outputLen + signCtx->totalCertLen + signCtx->totalSignerInfoLen + 2;
offset = VoltDetermineDerLengthLen (signedDataLen);
outputLen += offset + 1;
/* Figure out the A0 len of the EXPLICIT. Use offset as a temp
* variable.
*/
explicitLen = signedDataLen + offset + 1;
offset = VoltDetermineDerLengthLen (explicitLen);
outputLen += offset + 1;
/* Add in the SignedData OID.
*/
outputLen += VoltP7SignDataOidBytesLen + 2;
/* What is the 30 len of the total contentInfo?
*/
totalLen = explicitLen + offset + VoltP7SignDataOidBytesLen + 3;
outputLen += VoltDetermineDerLengthLen (totalLen);
outputLen++;
/* outputLen counts the total input length. However, this call to
* Update may not have all the data.
*/
outputLen -= (obj->dataLen - inputDataLen);
/* 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. Place the prefix.
* First, the 30 len of the overall contentInfo.
*/
offset = VoltWriteDerTagAndLen (message, 0x30, totalLen);
/* Write out the SignedData OID.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x06, VoltP7SignDataOidBytesLen);
Z2Memcpy (message + offset, signedDataOid, VoltP7SignDataOidBytesLen);
offset += VoltP7SignDataOidBytesLen;
/* Write out the EXPLICIT and the SignedData's SEQUENCE.
*/
offset += VoltWriteDerTagAndLen (message + offset, 0xA0, explicitLen);
offset += VoltWriteDerTagAndLen (message + offset, 0x30, signedDataLen);
/* Now it's the version.
*/
message[offset] = 0x02;
offset++;
message[offset] = 0x01;
offset++;
message[offset] = 0x01;
offset++;
/* Write out the SET of digestAlgorithms.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x31, signCtx->digestAlgId.len);
Z2Memcpy (
message + offset, signCtx->digestAlgId.data, signCtx->digestAlgId.len);
offset += signCtx->digestAlgId.len;
/* Next is contentInfo of the signed data.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x30, contentInfoLen);
/* Place the Data OID.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x06, VoltP7DataOidBytesLen);
Z2Memcpy (message + offset, dataOid, VoltP7DataOidBytesLen);
offset += VoltP7DataOidBytesLen;
/* Now comes the data itself. First, the EXPLICIT.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0xA0, contentLen);
/* Now the OCTET STRING.
*/
offset += VoltWriteDerTagAndLen (
message + offset, 0x04, obj->dataLen);
/* We'll start digesting data now.
*/
status = VtDigestInit (signCtx->digester);
if (status != 0)
break;
}
else if (obj->state == VOLT_P7_STATE_SIGN_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?
*/
status = VT_ERROR_BUFFER_TOO_SMALL;
*messageLen = inputDataLen;
if (bufferSize < inputDataLen)
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;
}
/* Digest the input data.
*/
status = VtDigestUpdate (signCtx->digester, inputData, inputDataLen);
if (status != 0)
break;
/* Write out the input.
*/
Z2Memcpy (message + offset, inputData, inputDataLen);
obj->inputLen += inputDataLen;
obj->state = VOLT_P7_STATE_SIGN_WRITE_UPDATE;
} while (0);
return (status);
}
int VoltP7SignWriteFinal (
VtPkcs7Object pkcs7Obj,
VtRandomObject random,
unsigned char *inputData,
unsigned int inputDataLen,
unsigned char *message,
unsigned int bufferSize,
unsigned int *messageLen
)
{
int status;
unsigned int index, bufSize;
unsigned int signatureLen, lastMessageLen, digestLen, totalLen;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltPkcs7WriteSignCtx *signCtx = (VoltPkcs7WriteSignCtx *)(obj->localCtx);
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltDigestClassCtx *digestCtx = (VoltDigestClassCtx *)
(((VoltAlgorithmObject *)(signCtx->digester))->classCtx);
unsigned char *buffer, *temp;
unsigned char *digest = (unsigned char *)0;
Asn1SignerInfo *nextSignerInfo;
do
{
/* If no dataLen is set, the inputDataLen is that value.
*/
if (obj->dataLen == 0)
obj->dataLen = inputDataLen;
/* The state must be INIT or UPDATE.
*/
status = VT_ERROR_INVALID_CALL_ORDER;
if ( (obj->state != VOLT_P7_STATE_SIGN_WRITE_INIT) &&
(obj->state != VOLT_P7_STATE_SIGN_WRITE_UPDATE) )
break;
/* Make sure the total len of input equals the "predicted" len.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if ((inputDataLen + obj->inputLen) != obj->dataLen)
break;
/* How much space is needed for the last chunk of data?
* If there's no input data, the outputLen might be 0, which is
* fine. So if the return is 0, reset status to BUFFER_TOO_SMALL
* just to make it easier to break out on a different error.
*/
status = VoltP7SignWriteUpdate (
pkcs7Obj, random, (unsigned char *)0, inputDataLen,
(unsigned char *)0, 0, &lastMessageLen);
if (status == 0)
status = VT_ERROR_BUFFER_TOO_SMALL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
/* We now know how long each of the components will be, determine
* the total length.
* last of the message
* A0 len
* <certs>
* --no CRL's for this implementation--
* 31 len
* <SignerInfo's>
*/
totalLen = VoltDetermineDerLengthLen (signCtx->totalCertLen);
totalLen += 1 + signCtx->totalCertLen;
totalLen += VoltDetermineDerLengthLen (signCtx->totalSignerInfoLen);
totalLen += 1 + signCtx->totalSignerInfoLen;
totalLen += lastMessageLen;
status = VT_ERROR_BUFFER_TOO_SMALL;
*messageLen = totalLen;
if (bufferSize < totalLen)
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, place data into the output.
*/
totalLen = 0;
status = VoltP7SignWriteUpdate (
pkcs7Obj, random, inputData, inputDataLen,
message, bufferSize, &lastMessageLen);
if (status != 0)
break;
bufferSize -= lastMessageLen;
totalLen += lastMessageLen;
/* Call DigestFinal to get the digest of the data.
*/
status = VtDigestFinal (
signCtx->digester, (unsigned char *)0, 0,
signCtx->digest, signCtx->digestSize, &digestLen);
if (status != 0)
break;
/* Place the certs. IMPLICIT SET OF.
*/
totalLen += VoltWriteDerTagAndLen (
message + totalLen, 0xA0, signCtx->totalCertLen);
for (index = 0; index < signCtx->signerInfosCount; ++index)
{
Z2Memcpy (
message + totalLen, signCtx->signerInfos[index].cert.data,
signCtx->signerInfos[index].cert.len);
totalLen += signCtx->signerInfos[index].cert.len;
}
for (index = 0; index < signCtx->extraCertsCount; ++index)
{
Z2Memcpy (
message + totalLen, signCtx->extraCerts[index].data,
signCtx->extraCerts[index].len);
totalLen += signCtx->extraCerts[index].len;
}
/* Next is SingerInfos, that's a SET OF.
*/
totalLen += VoltWriteDerTagAndLen (
message + totalLen, 0x31, signCtx->totalSignerInfoLen);
/* We need a buffer to hold the digest of auth attrs.
*/
status = VT_ERROR_MEMORY;
digest = (unsigned char *)Z2Malloc (signCtx->digestSize, 0);
if (digest == (unsigned char *)0)
break;
/* For each of the signer's, place the correct digest into the
* authAttributes, then create the signature of the authAttributes.
*/
for (index = 0; index < signCtx->signerInfosCount; ++index)
{
nextSignerInfo = signCtx->signerInfos[index].asn1SignerInfo;
/* We set the Asn1Encoded inside the asn1SignerInfo object with a
* placeholder. We'll fill the buffer inside the object with the
* actual data now.
*/
buffer = nextSignerInfo->authAttributes->base.data;
bufSize = (unsigned int)(nextSignerInfo->authAttributes->base.length);
status = BuildAuthAttributes (
obj, VT_PKCS7_DATA, signCtx->digest, signCtx->digestSize,
&(signCtx->signingTime), buffer, bufSize, &bufSize);
if (status != 0)
break;
/* Digest the auth attrs for the signature.
*/
status = VtDigestInit (signCtx->digester);
if (status != 0)
break;
/* P7 says to sign the auth attrs as SET OF. However, we built
* the authAttrs as IMPLICIT. So for the digesting, change the A0
* to 31. Then when the digesting is done, change it back.
*/
buffer[0] = 0x31;
status = VtDigestFinal (
signCtx->digester, buffer, bufSize,
digest, signCtx->digestSize, &digestLen);
if (status != 0)
break;
buffer[0] = 0xA0;
/* Create a signature for that data.
*/
status = VtSign (
signCtx->signerInfos[index].signObj,
signCtx->signerInfos[index].priKeyRef,
random, digestCtx->algorithm, digest, digestLen,
signCtx->signerInfos[index].signature,
signCtx->signerInfos[index].sigBufSize, &signatureLen);
if (status != 0)
break;
/* If the signature is smaller than the sigBufSize, fix it
* (prepend 00 bytes in appropriate places) to make it work.
*/
if (signatureLen != signCtx->signerInfos[index].sigBufSize)
FixDsaSignature (
libCtx, signCtx->signerInfos[index].signature,
signCtx->signerInfos[index].sigBufSize, &signatureLen);
/* Place the signature into the SignerInfo.
*/
status = VT_ERROR_MEMORY;
if (ASN1_OCTET_STRING_set (
nextSignerInfo->signature,
signCtx->signerInfos[index].signature, (int)signatureLen) != 1)
break;
/* Encode the SignerInfo into the message buffer.
*/
status = VT_ERROR_INVALID_INPUT;
temp = message + totalLen;
signCtx->signerInfos[index].signerInfoLen = i2d_Asn1SignerInfo (
signCtx->signerInfos[index].asn1SignerInfo, &temp);
if (temp == (unsigned char *)0)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -