📄 readsign.c
字号:
/* How long is the cert list? This is IMPLICIT.
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, 0xA0, 0, derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
readCtx->currentLen = derElement->tlvLen;
obj->state = VOLT_P7_STATE_SIGN_READ_CERT_D;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
VoltP7StateSignReadCertData:
case VOLT_P7_STATE_SIGN_READ_CERT_D:
/* The next element is a cert.
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, VOLT_SEQUENCE_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* We kept the total length of all the certs, now that we've read
* one, subtract its length from the total. If that was the last
* cert, set the state to indicate we're done reading certs.
*/
readCtx->currentLen -= derElement->elementLen;
if (readCtx->currentLen == 0)
obj->state = VOLT_P7_STATE_SIGN_READ_CERTS;
/* Add this cert to the list of certs.
*/
status = AddCertToList (
libCtx, readCtx, derElement->element, derElement->elementLen);
if (status != 0)
break;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
/* There may be more certs, we checked readCtx->currentLen to
* see, if there are no more the state was set to
* VOLT_P7_STATE_SIGN_READ_CERTS. If the state is not that value,
* read another cert. If it is, move on to the CRL's.
* Note from the programmer: Notice the goto statement.
* Normally I don't like them, but in this case it really works.
*/
if (obj->state != VOLT_P7_STATE_SIGN_READ_CERTS)
goto VoltP7StateSignReadCertData;
case VOLT_P7_STATE_SIGN_READ_CERTS:
/* We're done with the certs. There might be some CRL's, but they
* are OPTIONAL. If they are there, the next byte will be A1. If
* not, skip the CRL collection code.
* Note from the programmer: Notice the goto statement.
* Normally I don't like them, but in this case it really works.
*/
if (message[0] != 0xA1)
{
obj->state = VOLT_P7_STATE_SIGN_READ_CRLS;
goto VoltP7StateSignReadCrls;
}
obj->state = VOLT_P7_STATE_SIGN_READ_CRL_L;
VoltP7StateSignReadCrlLen:
case VOLT_P7_STATE_SIGN_READ_CRL_L:
/* This implementation skips the CRL's. Get the length.
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, 0xA1, 0, derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
readCtx->currentLen = derElement->tlvLen;
obj->state = VOLT_P7_STATE_SIGN_READ_CRL_D;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_CRL_D:
/* Just skip CRL's. Skip all the CRL data, unless the amount in
* message is not enough. Then skip all the data in the message.
*/
length = messageLen;
if (messageLen >= readCtx->currentLen)
{
length = readCtx->currentLen;
obj->state = VOLT_P7_STATE_SIGN_READ_CRLS;
}
readCtx->currentLen -= length;
message += length;
messageLen -= length;
if (messageLen == 0)
break;
VoltP7StateSignReadCrls:
case VOLT_P7_STATE_SIGN_READ_CRLS:
/* We should have a SET OF SignerInfo. How long?
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, VOLT_SET_TAG, 0,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
readCtx->currentLen = derElement->tlvLen;
obj->state = VOLT_P7_STATE_SIGN_READ_SI;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
VoltP7StateSignReadSi:
case VOLT_P7_STATE_SIGN_READ_SI:
/* The next element is a SignerInfo
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, VOLT_SEQUENCE_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* We kept the total length of all the SignerInfo's, now that
* we've read one, subtract its length from the total. If that
* was the last SignerInfo, set the state to indicate we're done
* reading them.
*/
readCtx->currentLen -= derElement->elementLen;
if (readCtx->currentLen == 0)
obj->state = VOLT_P7_STATE_SIGN_READ_COMPLETE;
/* Add this cert to the list of SingerInfo's.
*/
status = AddSignerInfoToList (
libCtx, readCtx, derElement->element, derElement->elementLen);
if (status != 0)
break;
/* There may be more SignerInfo's, we checked readCtx->currentLen
* to see, if there are no more the state was set to
* VOLT_P7_STATE_SIGN_READ_COMPLETE. If the state is not that
* value, read another SignerInfo. If it is, we've read all there
* is to read, decode the authenticated attributes.
* Note from the programmer: Notice the goto statement.
* Normally I don't like them, but in this case it really works.
*/
if (obj->state == VOLT_P7_STATE_SIGN_READ_COMPLETE)
break;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
goto VoltP7StateSignReadSi;
}
return (status);
}
int VoltP7ReadSignedFinal (
VtPkcs7Object pkcs7Obj,
unsigned char *message,
unsigned int messageLen,
unsigned int *bytesRead,
unsigned char *outputData,
unsigned int bufferSize,
unsigned int *outputDataLen
)
{
int status;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
*bytesRead = 0;
*outputDataLen = 0;
do
{
/* If we're done, there's nothing to do.
*/
if ( (obj->state == VOLT_P7_STATE_SIGN_READ_COMPLETE) ||
(obj->state == VOLT_P7_STATE_SIGN_READ_FINAL) )
{
obj->state = VOLT_P7_STATE_SIGN_READ_FINAL;
status = 0;
break;
}
/* If we're not done, try to finish.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (messageLen == 0)
break;
status = VoltP7ReadSignedUpdate (
pkcs7Obj, message, messageLen, bytesRead,
outputData, bufferSize, outputDataLen);
if (status != 0)
break;
/* Are we finished now?
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (obj->state != VOLT_P7_STATE_SIGN_READ_COMPLETE)
break;
obj->state = VOLT_P7_STATE_SIGN_READ_FINAL;
status = 0;
} while (0);
return (status);
}
int VoltP7VerifySignerInfo (
VtPkcs7Object pkcs7Obj,
unsigned int index,
VtPolicyCtx policyCtx,
VtStorageCtx storageCtx,
VtTransportCtx transportCtx,
VtCertVerifyCtx certVerifyCtx,
Pointer verifyCtxInfo,
VtVerifyStack verifyStack,
unsigned int *verifyResult
)
{
int status;
unsigned int digestLen, newDigestLen, indexC;
unsigned int attrCount, contentOidLen, sigResult;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltPkcs7ReadSignCtx *readCtx;
VoltDigestClassCtx *digestCtx;
VtMpIntCtx mpCtx;
VtAlgorithmObject digestObj;
VtDistrictObject district = (VtDistrictObject)0;
Asn1SignerInfo *signerInfo;
unsigned char *digest;
unsigned char *contentOid;
VoltCertObject *signerCert;
VtCertObjectList *getCerts = (VtCertObjectList *)0;
VtCertObjectList trustedCerts;
VtCertObjectList untrustedCerts;
VtCertInfo certInfo;
VtSetAlgIdInfo algIdInfo;
VtKeyObject pubKey = (VtKeyObject)0;
VtAlgorithmObject verifier = (VtAlgorithmObject)0;
VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
unsigned char *newDigest = (unsigned char *)0;
Asn1P9Attribute **authAttrs;
VtSurrenderCallback surrenderCtx;
*verifyResult = 0;
do
{
/* We can do this only after all the data has been read.
*/
status = VT_ERROR_INVALID_P7_OBJ;
if (obj->contentType != VOLT_PKCS7_SIGNED_DATA_READ)
break;
readCtx = (VoltPkcs7ReadSignCtx *)(obj->localCtx);
digestCtx = (VoltDigestClassCtx *)
(((VoltAlgorithmObject *)(readCtx->digestObj))->classCtx);
/* Get the requested SignerInfo.
*/
status = VT_ERROR_INVALID_P7_OBJ;
if (readCtx->signerInfosCount <= index)
break;
signerInfo = readCtx->signerInfos[index].signerInfo;
/* We'll need a digest object and MpCtx.
*/
digestObj = readCtx->digestObj;
mpCtx = readCtx->mpCtx;
/* Get the buffer that holds the digest of the data and the one
* that holds the contentOid.
*/
digest = readCtx->digest;
digestLen = readCtx->digestLen;
contentOid = readCtx->contentOid;
contentOidLen = readCtx->contentOidLen;
/* Put together a VtCertList of the untrusted certs (msgCerts).
*/
untrustedCerts.certObjects = readCtx->msgCerts;
untrustedCerts.count = readCtx->msgCertsCount;
trustedCerts.certObjects = (VtCertObject *)0;
trustedCerts.count = 0;
/* Get the DerCoders array.
*/
certInfo.derCoders = readCtx->DerCoders;
certInfo.derCoderCount = readCtx->derCoderCount;
/* Get the cert associated with this signer.
*/
indexC = 0;
status = VoltFindCertByReference (
libCtx, VOLT_FIND_CERT_BY_ISSUER_SERIAL,
signerInfo->issuerSerial->issuerName->base.data,
(unsigned int)(signerInfo->issuerSerial->issuerName->base.length),
signerInfo->issuerSerial->serialNumber->data,
(unsigned int)(signerInfo->issuerSerial->serialNumber->length),
&indexC, &untrustedCerts, (VtCertObject *)&signerCert);
if (status != 0)
{
if (status != VT_ERROR_ENTRY_NOT_FOUND)
break;
/* Couldn't find the signer cert, id does not verify, but no
* error.
*/
status = 0;
break;
}
/* Build a key object from this cert.
*/
status = VtCreateKeyObject (
(VtLibCtx)libCtx, VtKeyImplMpCtx, (Pointer)mpCtx, &pubKey);
if (status != 0)
break;
certInfo.cert = signerCert->certificate.data;
certInfo.certLen = signerCert->certificate.len;
status = VtSetKeyParam (pubKey, VtKeyParamX509Cert, (Pointer)&certInfo);
if (status != 0)
break;
/* Build an object that verifies.
*/
algIdInfo.derCoders = certInfo.derCoders;
algIdInfo.derCoderCount = certInfo.derCoderCount;
algIdInfo.berEncoding = signerInfo->signatureAlg->base.data;
algIdInfo.maxEncodingLen =
(unsigned int)(signerInfo->signatureAlg->base.length);
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplAlgId, (Pointer)&algIdInfo,
&verifier);
if (status != 0)
break;
/* If there's a surrender ctx, get it to pass along to verifier.
*/
if ( ((obj->voltObject.objectType & VOLT_OBJECT_TYPE_SURRENDER) != 0) &&
(obj->voltObject.surrenderCtx != (Pointer)0) )
{
surrCtx = (VoltSurrenderCtx *)(obj->voltObject.surrenderCtx);
/* Set the verifying object with the surrender ctx, but don't copy
* the appData, just copy a reference, so we're still using the
* cert request object's appData.
*/
surrenderCtx.Surrender = surrCtx->Surrender;
surrenderCtx.appData = surrCtx->appData;
surrenderCtx.AppDataCopy = (VtSurrenderAppDataCopy)0;
surrenderCtx.AppDataFree = (VtSurrenderAppDataFree)0;
status = VtSetAlgorithmParam (
verifier, VtAlgorithmParamSurrenderCallback, (Pointer)&surrenderCtx);
if (status != 0)
break;
}
/* Digest. First, get a buffer.
*/
status = VT_ERROR_MEMORY;
newDigestLen = digestLen;
newDigest = (unsigned char *)Z2Malloc (newDigestLen, 0);
if (newDigest == (unsigned char *)0)
break;
status = VtDigestInit (digestObj);
if (status != 0)
break;
/* The authenticatedAttributes are IMPLICIT, but the standard
* specifies digesting the regular tag (0x31) instead.
*/
newDigest[0] = 0x31;
status = VtDigestUpdate (digestObj, newDigest, 1);
if (status != 0)
break;
/* Digest the rest, without the leading IMPLICIT (0xA0) tag.
*/
status = VtDigestFinal (
digestObj, signerInfo->authAttributes->base.data + 1,
(unsigned int)(signerInfo->authAttributes->base.length - 1),
newDigest, newDigestLen, &newDigestLen);
if (status != 0)
break;
authAttrs = readCtx->signerInfos[index].authAttrs;
attrCount = readCtx->signerInfos[index].authAttrsCount;
/* Verify that the authenticated attribute contentType matches
* the contentType of the message.
*/
status = VerifyAuthAttribute (
libCtx, VOLT_P9_ATTRIBUTE_CONTENT_TYPE, authAttrs, attrCount,
contentOid, contentOidLen);
if (status != 0)
break;
/* Verify that the authenticated attribute messageDigest matches
* the messageDigest of the regular message.
*/
status = VerifyAuthAttribute (
libCtx, VOLT_P9_ATTRIBUTE_DIGEST, authAttrs, attrCount,
digest, digestLen);
if (status != 0)
break;
/* Now that we have the algorithm and key objects, perform the
* verification.
*/
status = VtVerifySignature (
verifier, pubKey, (VtRandomObject)0, digestCtx->algorithm,
newDigest, newDigestLen, signerInfo->signature->data,
(unsigned int)(signerInfo->signature->length), &sigResult);
if (status != 0)
break;
/* If sigResult is not verified, we're done, no need to look
* further.
*/
if (sigResult == 0)
break;
/* Now verify the cert. In order to do that, get the trusted certs
* from the district object. Get the district object based on the
* district name in the signer cert.
*/
status = VoltDistrictObjectFromCert (
libCtx, (VtCertObject)signerCert, policyCtx, storageCtx, transportCtx,
&district);
/* If the above function failed, continue without the certs. But if
* there is a district object, get the trusted certs out of it.
*/
if (district != (VtDistrictObject)0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -