📄 certcget.c
字号:
if( cryptStatusOK( \
moveCursorToField( certInfoPtr,
certInfoPtr->currentSelection.generalName ) ) )
return( CRYPT_OK );
if( option == MUST_BE_PRESENT )
return( CRYPT_ERROR_NOTFOUND );
/* We're creating the GeneralName extension, deselect the current DN and
remember that we have to update the extension cursor when we've done
it */
certInfoPtr->currentSelection.dnPtr = NULL;
certInfoPtr->currentSelection.dnInExtension = FALSE;
certInfoPtr->currentSelection.updateCursor = TRUE;
assert( selectionInfoConsistent( certInfoPtr ) );
return( CRYPT_OK );
}
/* Handle selection of DNs */
int selectDN( CERT_INFO *certInfoPtr, const CRYPT_ATTRIBUTE_TYPE certInfoType,
const SELECTION_OPTION option )
{
CRYPT_ATTRIBUTE_TYPE generalName = \
certInfoPtr->currentSelection.generalName;
static const int value = CRYPT_UNUSED;
int status;
assert( ( option == MAY_BE_ABSENT && \
isDNSelectionComponent( certInfoType ) ) || \
( ( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT ) && \
certInfoType == CRYPT_ATTRIBUTE_NONE ) );
assert( selectionInfoConsistent( certInfoPtr ) );
if( option == MAY_BE_ABSENT )
{
/* Try and select a DN based on the supplied attribute ID */
switch( certInfoType )
{
case CRYPT_CERTINFO_SUBJECTNAME:
certInfoPtr->currentSelection.dnPtr = &certInfoPtr->subjectName;
break;
case CRYPT_CERTINFO_ISSUERNAME:
certInfoPtr->currentSelection.dnPtr = &certInfoPtr->issuerName;
/* If it's a self-signed cert and the issuer name isn't
explicitly present then it must be implicitly present as
the subject name */
if( certInfoPtr->issuerName == NULL && \
( certInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
certInfoPtr->currentSelection.dnPtr = &certInfoPtr->subjectName;
break;
default:
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* We've selected a built-in DN, remember that this isn't one in an
(optional) extension */
certInfoPtr->currentSelection.dnInExtension = FALSE;
assert( selectionInfoConsistent( certInfoPtr ) );
return( CRYPT_OK );
}
/* If there's a DN already selected, we're done */
if( certInfoPtr->currentSelection.dnPtr != NULL )
return( CRYPT_OK );
assert( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT );
/* To select a DN in a GeneralName, we first need to have a GeneralName
selected */
status = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE, option );
if( cryptStatusError( status ) )
return( status );
/* If we've now got a GeneralName selected, try and find a DN in it */
if( isGeneralNameSelected( certInfoPtr ) )
{
/* If there's a DN currently selected, we're done */
if( certInfoPtr->attributeCursor->fieldType == FIELDTYPE_DN )
{
certInfoPtr->currentSelection.dnPtr = \
&certInfoPtr->attributeCursor->value;
certInfoPtr->currentSelection.dnInExtension = TRUE;
assert( selectionInfoConsistent( certInfoPtr ) );
return( CRYPT_OK );
}
/* There's no DN selected, see if there's one present somewhere in
the extension */
if( cryptStatusOK( findDnInExtension( certInfoPtr, TRUE ) ) )
return( CRYPT_OK );
/* If there's no DN present and we're not about to create one,
exit */
if( option == MUST_BE_PRESENT )
return( CRYPT_ERROR_NOTFOUND );
/* Create the DN in the currently selected GeneralName */
generalName = certInfoPtr->attributeCursor->fieldID;
}
/* We're being asked to instantiate the DN, create the attribute field
that contains it */
status = addAttributeField( &certInfoPtr->attributes, generalName,
CRYPT_CERTINFO_DIRECTORYNAME, &value, CRYPT_UNUSED,
ATTR_FLAG_NONE, &certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
/* Find the field that we just created. This is a newly-created
attribute, so it's the only one present (i.e we don't have to worry
about finding one added at the end of the sequence of identical
attributes), and we also know that it must be present since we've
just created it */
return( selectGeneralName( certInfoPtr, generalName, MAY_BE_ABSENT ) );
}
/****************************************************************************
* *
* Get Cert Info *
* *
****************************************************************************/
/* Get a certificate component */
static int getCertAttributeComponentData( const ATTRIBUTE_LIST *attributeListPtr,
void *certInfo, int *certInfoLength )
{
const int maxLength = ( certInfoLength != NULL ) ? *certInfoLength : 0;
/* If the data type is an OID, we have to convert it to a human-readable
form before we return it */
if( attributeListPtr->fieldType == BER_OBJECT_IDENTIFIER )
{
char textOID[ CRYPT_MAX_TEXTSIZE * 2 ];
int length;
assert( certInfoLength != NULL );
length = oidToText( attributeListPtr->value, textOID );
*certInfoLength = length;
if( certInfo == NULL )
return( CRYPT_OK );
if( length > maxLength )
return( CRYPT_ERROR_OVERFLOW );
memcpy( certInfo, textOID, length );
return( CRYPT_OK );
}
/* If it's a basic data value, copy it over as an integer */
if( attributeListPtr->valueLength <= 0 )
{
*( ( int * ) certInfo ) = ( int ) attributeListPtr->intValue;
return( CRYPT_OK );
}
assert( certInfoLength != NULL );
/* It's a more complex data type, copy it across */
*certInfoLength = attributeListPtr->valueLength;
if( certInfo == NULL )
return( CRYPT_OK );
if( attributeListPtr->valueLength > maxLength )
return( CRYPT_ERROR_OVERFLOW );
memcpy( certInfo, attributeListPtr->value, attributeListPtr->valueLength );
return( CRYPT_OK );
}
static int getCertAttributeComponent( CERT_INFO *certInfoPtr,
const CRYPT_ATTRIBUTE_TYPE certInfoType,
void *certInfo, int *certInfoLength )
{
ATTRIBUTE_LIST *attributeListPtr;
assert( ( certInfo == NULL && *certInfoLength == 0 ) || \
( certInfoLength == NULL ) || \
( *certInfoLength > 1 && *certInfoLength <= 32768 ) );
/* Try and find this attribute in the attribute list */
if( isRevocationEntryComponent( certInfoType ) )
{
/* If it's an RTCS per-entry attribute, get the attribute from the
currently selected entry */
if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
{
if( certInfoPtr->currentValidity == NULL )
return( CRYPT_ERROR_NOTFOUND );
attributeListPtr = findAttributeFieldEx( \
certInfoPtr->currentValidity->attributes, certInfoType );
}
else
{
/* It's a CRL or OCSP per-entry attribute, get the attribute
from the currently selected entry */
if( certInfoPtr->currentRevocation == NULL )
return( CRYPT_ERROR_NOTFOUND );
attributeListPtr = findAttributeFieldEx( \
certInfoPtr->currentRevocation->attributes, certInfoType );
if( attributeListPtr == NULL && \
certInfoType == CRYPT_CERTINFO_CRLREASON )
/* Revocation reason codes are actually a single range of
values spread across two different extensions, so if we
don't find the value as a straight cRLReason we try
again for a cRLExtReason. If we've been specifically
asked for a cRLExtReason we don't go the other way
because the caller (presumably) specifically wants the
extended reason code */
attributeListPtr = findAttributeFieldEx( \
certInfoPtr->currentRevocation->attributes,
CRYPT_CERTINFO_CRLEXTREASON );
}
}
else
attributeListPtr = findAttributeFieldEx( certInfoPtr->attributes,
certInfoType );
if( attributeListPtr == NULL )
return( CRYPT_ERROR_NOTFOUND );
/* If this is a non-present field in a present attribute with a default
value for the field, return that */
if( isDefaultFieldValue( attributeListPtr ) )
{
*( ( int * ) certInfo ) = getDefaultFieldValue( certInfoType );
return( CRYPT_OK );
}
/* If this is a non-present field in a present attribute which denotes
an entire (constructed) attribute, return a boolean indicating its
presence */
if( isCompleteAttribute( attributeListPtr ) )
{
*( ( int * ) certInfo ) = TRUE;
return( CRYPT_OK );
}
return( getCertAttributeComponentData( attributeListPtr, certInfo,
certInfoLength ) );
}
/* Get the hash of a certificate */
static int getCertHash( CERT_INFO *certInfoPtr,
const CRYPT_ATTRIBUTE_TYPE certInfoType,
void *certInfo, int *certInfoLength )
{
const CRYPT_ALGO_TYPE cryptAlgo = \
( certInfoType == CRYPT_CERTINFO_FINGERPRINT_MD5 ) ? \
CRYPT_ALGO_MD5 : CRYPT_ALGO_SHA;
HASHFUNCTION hashFunction;
BYTE hash[ CRYPT_MAX_HASHSIZE ];
const int maxLength = *certInfoLength;
int hashSize;
/* Get the hash algorithm information */
getHashParameters( cryptAlgo, &hashFunction, &hashSize );
*certInfoLength = hashSize;
if( certInfo == NULL )
return( CRYPT_OK );
if( hashSize > maxLength )
return( CRYPT_ERROR_OVERFLOW );
assert( certInfoPtr->certificate != NULL );
/* Write the hash (fingerprint) to the output */
if( cryptAlgo == CRYPT_ALGO_SHA && certInfoPtr->certHashSet )
{
/* If we've got a cached hash present, return that instead of re-
hashing the cert */
memcpy( certInfo, certInfoPtr->certHash, KEYID_SIZE );
return( CRYPT_OK );
}
hashFunction( NULL, hash, certInfoPtr->certificate,
certInfoPtr->certificateSize, HASH_ALL );
memcpy( certInfo, hash, hashSize );
if( cryptAlgo == CRYPT_ALGO_SHA )
{
/* Remember the hash/fingerprint/oobCertID/certHash/thumbprint/
whatever for later, since this is reused frequently */
memcpy( certInfoPtr->certHash, hash, hashSize );
certInfoPtr->certHashSet = TRUE;
}
return( CRYPT_OK );
}
/* Get a single CRL entry */
static int getCrlEntry( CERT_INFO *certInfoPtr, void *certInfo,
int *certInfoLength )
{
STREAM stream;
const int maxLength = *certInfoLength;
int crlEntrySize, i, status;
assert( certInfoPtr->type == CRYPT_CERTTYPE_CRL );
if( certInfoPtr->currentRevocation == NULL )
return( CRYPT_ERROR_NOTFOUND );
/* Determine how big the encoded CRL entry will be. This is somewhat
ugly since we have to pick the necessary function out of the cert
write-function table, but the only other way to do it would be to
pseudo-sign the cert object in order to write the data, which
doesn't work for CRL entries where we could end up pseudo-singing it
multiple times */
for( i = 0; certWriteTable[ i ].type != CRYPT_CERTTYPE_CRL && \
certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
{
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
sMemOpen( &stream, NULL, 0 );
status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
NULL, CRYPT_UNUSED );
crlEntrySize = stell( &stream );
sMemClose( &stream );
if( cryptStatusError( status ) )
return( status );
/* Write the encoded single CRL entry */
*certInfoLength = crlEntrySize;
if( certInfo == NULL )
return( CRYPT_OK );
if( crlEntrySize > maxLength )
return( CRYPT_ERROR_OVERFLOW );
sMemOpen( &stream, certInfo, crlEntrySize );
status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
NULL, CRYPT_UNUSED );
sMemDisconnect( &stream );
return( status );
}
/* Get the issuerAndSerialNumber for a certificate */
static int getIAndS( CERT_INFO *certInfoPtr, void *certInfo,
int *certInfoLength )
{
STREAM stream;
void *serialNumber;
const int maxLength = *certInfoLength;
int serialNumberLength, status;
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
{
REVOCATION_INFO *crlInfoPtr = certInfoPtr->currentRevocation;
/* If it's a CRL, use the serial number of the currently selected
CRL entry */
assert( crlInfoPtr != NULL );
serialNumber = crlInfoPtr->dataPtr;
serialNumberLength = crlInfoPtr->dataLength;
}
else
{
serialNumber = certInfoPtr->serialNumber;
serialNumberLength = certInfoPtr->serialNumberLength;
}
assert( serialNumber != NULL );
*certInfoLength = ( int ) \
sizeofObject( certInfoPtr->issuerDNsize + \
sizeofInteger( serialNumber, serialNumberLength ) );
if( certInfo == NULL )
return( CRYPT_OK );
if( *certInfoLength > maxLength )
return( CRYPT_ERROR_OVERFLOW );
sMemOpen( &stream, certInfo, *certInfoLength );
writeSequence( &stream, certInfoPtr->issuerDNsize + \
sizeofInteger( serialNumber, serialNumberLength ) );
swrite( &stream, certInfoPtr->issuerDNptr, certInfoPtr->issuerDNsize );
status = writeInteger( &stream, serialNumber, serialNumberLength,
DEFAULT_TAG );
sMemDisconnect( &stream );
return( status );
}
/* Get the ESSCertID for a certificate */
static int getESSCertID( CERT_INFO *certInfoPtr, void *certInfo,
int *certInfoLength )
{
STREAM stream;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -