📄 readsign.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 "certobj.h"
#include "vcert.h"
#include "certvfyctx.h"
#include "vfylist.h"
#include "distobj.h"
#include "vtime.h"
#include "digest.h"
#include "errorctx.h"
/* Decode each of the attributes in the authAttributes field of the
* given signerInfo. This function will build an array of
* Asn1P9Attribute pointers, as many pointers as are authenticate
* attributes. It will then create (Asn1P9Attribute_new) the objects
* and decode (d2i_Asn1P9Attribute) each of the attributes. It will
* return the array and the count.
* <p>The caller must destroy each of the objects (Asn1P9Attribute_free)
* and free the memory that is the array.
*
* @param libCtx The libCtx to use.
* @param signerInfo The specific signerInfo from which the
* authenticated attributes are to be extracted.
* @param attributes The address where this function will deposit the
* created array.
* @param attributeCount The address where this function will deposit
* the number of Asn1P9Attribute objects it created.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV DecodeAuthAttributesAlloc VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
Asn1SignerInfo *signerInfo,
Asn1P9Attribute ***attributes,
unsigned int *attributeCount
));
/* This function finds the attribute in the array that matches the
* given flag, then compares the value in the attribute object with the
* given baseValue. If there is no attribute to match or if the value
* does not compare equally to the baseValue, the routine sets
* verifyResult to FALSE.
* <p>This function also expects that the attribute has only one value
* (a P9 attribute is actually a SET OF values) and that the value is
* an "atomic" ASN.1 type (an OID or OCTET STRING, for example).
* <p>The flag indicates what to look for. Currently, the following are
* supported.
* <pre>
* <code>
* VOLT_P9_ATTRIBUTE_CONTENT_TYPE
* VOLT_P9_ATTRIBUTE_DIGEST
* </code>
* </pre>
* <p>This function will set the verifyResult to 0 if it does not
* verify, but will not set it to nonzero if it does. That is, the
* caller must initialize the value to 1. This is so that a series of
* calls to this function can be cumulative, so that it is possible to
* call this function more than once to verify several attributes. If
* one fails and the next succeeds, the success will not overwrite the
* failure.
*
* @param libCtx The libCtx to use.
* @param flag What attribute to search for.
* @param attributes The array to search.
* @param attributeCount The number of attributes in the array.
* @param baseValue The value to match.
* @param baseValueLen The length, in bytes, of the baseValue.
* @param vfyFailList The VerifyFailureList to use if the verification
* fails.
* @param verifyResult The address where the function will place the
* verification result (0 for FALSE, does not verify; and nonzero for
* TRUE, verifies)
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV VerifyAuthAttribute VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
unsigned int flag,
Asn1P9Attribute **attributes,
unsigned int attributeCount,
unsigned char *baseValue,
unsigned int baseValueLen,
VtVerifyFailureList vfyFailList,
unsigned int *verifyResult
));
#define VOLT_P9_ATTRIBUTE_CONTENT_TYPE 3
#define VOLT_P9_ATTRIBUTE_DIGEST 4
/* This function looks through the array of attributes until finding
* the one with the given OID. If it can't find an attribute with that
* OID, it returns the INVALID_ENCODING_ERROR.
* <p>The function sets the unsigned int at the address index to the
* index in the array of the attribute with the matching OID.
* <p>This function does no arg checking, it assumes a valid array and
* valid OID to check.
*
* @param libCtx The libCtx to use.
* @param oid The OID to match.
* @param oidLen The length, in bytes, of the OID.
* @param attributes The array to search.
* @param attributeCount The number of attributes in the array.
* @param index The address where the routine will deposit the index
* into the array of the attribute with the matching OID.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV FindAuthAttribute VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
unsigned char *oid,
unsigned int oidLen,
Asn1P9Attribute **attributes,
unsigned int attributeCount,
unsigned int *index
));
/* Build a cert object from the encoding, then add it to the list of
* msgCerts in the readCtx. This function will grow the array of
* msgCerts, if necessary.
*/
static int VOLT_CALLING_CONV AddCertToList VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltPkcs7ReadSignCtx *readCtx,
unsigned char *certDer,
unsigned int certDerLen
));
/* Build a SignerInfo object from the encoding, then add it to the
* list of signerInfos in the readCtx. This function will grow the
* array of signerInfos, if necessary.
*/
static int VOLT_CALLING_CONV AddSignerInfoToList VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltPkcs7ReadSignCtx *readCtx,
unsigned char *encoding,
unsigned int encodingLen
));
int VoltP7ReadSignedInit (
VtPkcs7Object pkcs7Obj
)
{
int status;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* The state must be VOLT_P7_STATE_SIGN_READ_SET, if not, we're
* not allowed to call ReadInit.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_CALL_ORDER;
if (obj->state != VOLT_P7_STATE_SIGN_READ_SET)
break;
/* Set the state to INIT.
*/
obj->state = VOLT_P7_STATE_SIGN_READ_INIT;
status = 0;
} while (0);
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, pkcs7Obj, status, 0, VT_ERROR_TYPE_PRIMARY,
(char *)0, "VoltP7ReadSignedInit", fnctLine, (char *)0)
return (status);
}
int VoltP7ReadSignedUpdate (
VtPkcs7Object pkcs7Obj,
unsigned char *message,
unsigned int messageLen,
unsigned int *bytesRead,
unsigned char *outputData,
unsigned int bufferSize,
unsigned int *outputDataLen
)
{
int status;
unsigned int messageRead, length;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
VoltPkcs7ReadSignCtx *readCtx = (VoltPkcs7ReadSignCtx *)(obj->localCtx);
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltDerElement *derElement = &(readCtx->currentElement);
unsigned char p7Oid[VoltP7SignDataOidBytesLen] = { VoltP7SignDataOidBytes };
VtSetAlgIdInfo algIdInfo;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
*bytesRead = 0;
*outputDataLen = 0;
switch (obj->state)
{
default:
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_CALL_ORDER;
break;
case VOLT_P7_STATE_SIGN_READ_COMPLETE:
/* If we're done, don't read anything.
*/
status = 0;
break;
case VOLT_P7_STATE_SIGN_READ_INIT:
/* The first thing to do is read the ContentInfo SEQUENCE.
* "Cheat" a little bit and set the explicitTag to the outer
* SEQUENCE, then we can capture the SEQUENCE and the OID at the
* same time.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, VOLT_SEQUENCE_TAG, VOLT_OID_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* Is this the SignedData OID?
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_ENCODING;
if (derElement->valueLen != VoltP7SignDataOidBytesLen)
break;
if (Z2Memcmp (
p7Oid, derElement->element + 2, VoltP7SignDataOidBytesLen) != 0)
break;
obj->state = VOLT_P7_STATE_SIGN_READ_SD_OID;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_SD_OID:
/* We now have the SignedData. It starts with the EXPLICIT.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0xA0, VOLT_SEQUENCE_TAG, 0,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
obj->state = VOLT_P7_STATE_SIGN_READ_EXP_1;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_EXP_1:
/* Now it's the version.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, VOLT_INTEGER_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* Is this the expected version?
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_UNSUPPORTED;
if (derElement->valueLen != 1)
break;
if (derElement->element[2] != 1)
break;
obj->state = VOLT_P7_STATE_SIGN_READ_VERSION;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_VERSION:
/* Next up is the SET OF digest algorithm ID's. This
* implementation can operate with only one digest algorithm.
* "Cheat" a little bit, pass the SET OF tag as the explicitTag,
* and the SEQUENCE as the tag. We'll get the SET OF as the
* explicit and the contents of the first (presumably only)
* digest algID in the element buffer.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, VOLT_SET_TAG, VOLT_SEQUENCE_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* Make sure there's only one digest alg. If more than one, error.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_UNSUPPORTED;
if (derElement->explicitLen != derElement->elementLen)
break;
/* Build a digest object from this
*/
algIdInfo.derCoders = readCtx->DerCoders;
algIdInfo.derCoderCount = readCtx->derCoderCount;
algIdInfo.berEncoding = derElement->element;
algIdInfo.maxEncodingLen = derElement->elementLen;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplAlgId, (Pointer)&algIdInfo,
&(readCtx->digestObj));
if (status != 0)
break;
obj->state = VOLT_P7_STATE_SIGN_READ_DIGEST;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_DIGEST:
/* Now read the contentInfo, the data to verify. Start with the
* SEQUENCE and OID. Do this by "cheating", setting the
* explicitTag to the SEQUENCE, thereby capturing both the
* SEQUENCE tag and the first element, the OID.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, VOLT_SEQUENCE_TAG, VOLT_OID_TAG, 1,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* Is this the Data OID?
* First, set the buffer containing the OID to hold the Data OID.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_UNSUPPORTED;
p7Oid[VoltP7SignDataOidBytesLen - 1] = VOLT_P7_OID_BYTE_DATA;
if (derElement->valueLen != VoltP7SignDataOidBytesLen)
break;
if (Z2Memcmp (
p7Oid, derElement->element + 2, VoltP7SignDataOidBytesLen) != 0)
break;
/* Copy this OID into the readCtx.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_MEMORY;
readCtx->contentOid = (unsigned char *)Z2Realloc (
readCtx->contentOid, VoltP7SignDataOidBytesLen);
if (readCtx->contentOid == (unsigned char *)0)
break;
Z2Memcpy (readCtx->contentOid, p7Oid, VoltP7SignDataOidBytesLen);
readCtx->contentOidLen = VoltP7SignDataOidBytesLen;
obj->state = VOLT_P7_STATE_SIGN_READ_DATA_OID;
/* Move on to the next element.
*/
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_SIGN_READ_DATA_OID:
/* We expect to see an EXPLICIT then OCTET STRING.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0xA0, VOLT_OCTET_STRING_TAG, 0,
derElement, &messageRead);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -