dbxpk15.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,715 行 · 第 1/5 页
C
1,715 行
{
zeroise( pkcs15info->certData, pkcs15info->certDataSize );
free( pkcs15info->certData );
}
if( pkcs15info->dataData != NULL )
{
zeroise( pkcs15info->dataData, pkcs15info->dataDataSize );
free( pkcs15info->dataData );
}
zeroise( pkcs15info, sizeof( PKCS15_INFO ) );
}
void pkcs15Free( PKCS15_INFO *pkcs15info )
{
int i;
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
pkcs15freeEntry( &pkcs15info[ i ] );
}
/* Get the hash of various certificate name fields */
static int getCertID( const CRYPT_HANDLE iCryptHandle,
CRYPT_ATTRIBUTE_TYPE nameType, BYTE *nameID )
{
RESOURCE_DATA msgData;
BYTE idBuffer[ 1024 ], *idBufPtr = idBuffer;
int status;
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, nameType );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
if( msgData.length > 1024 && \
( idBufPtr = malloc( msgData.length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
msgData.data = idBufPtr;
status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, nameType );
if( cryptStatusOK( status ) )
{
HASHFUNCTION hashFunction;
int hashSize;
/* Get the hash algorithm information and hash the name to get a name
ID */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
hashFunction( NULL, nameID, idBufPtr, msgData.length, HASH_ALL );
}
if( idBufPtr != idBuffer )
free( idBufPtr );
return( status );
}
/* Get the PKCS #15 validity information from a certificate */
static int getValidityInfo( PKCS15_INFO *pkcs15info,
const CRYPT_HANDLE cryptHandle )
{
RESOURCE_DATA msgData;
time_t validFrom, validTo;
int status;
/* Remember the validity information for later. Note that we always
update the validity (even if it's already set) since we may be
replacing an older cert with a newer one */
setResourceData( &msgData, &validFrom, sizeof( time_t ) );
status = krnlSendMessage( cryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDFROM );
setResourceData( &msgData, &validTo, sizeof( time_t ) );
if( cryptStatusOK( status ) )
status = krnlSendMessage( cryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDTO );
if( cryptStatusError( status ) )
return( status );
if( pkcs15info->validTo > validTo )
/* There's an existing, newer cert already present, make sure we
don't try and add the new one */
return( CRYPT_ERROR_DUPLICATE );
pkcs15info->validFrom = validFrom;
pkcs15info->validTo = validTo;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Read/Write PKCS #15 Attributes *
* *
****************************************************************************/
/* When writing attributes it's useful to have a fixed-size buffer rather
than having to mess around with all sorts of variable-length structures,
the following value defines the maximum size of the data we can write
(that is, the I/O stream is opened with this size and generates a
CRYPT_ERROR_OVERFLOW if we go beyond this). The maximum-length buffer
contents are two CRYPT_MAX_TEXTSIZE strings and a few odd bits and pieces
so this is plenty */
#define KEYATTR_BUFFER_SIZE 256
/* Translate the PKCS #15 usage flags into cryptlib permitted actions. The
PKCS #11 use of the 'derive' flag to mean 'allow key agreement' is a bit
of a kludge, we map it to allowing keyagreement export and import and if
there are further constraints they'll be handled by the attached cert.
The PKCS #15 nonRepudiation flag doesn't have any definition, so we can't
do anything with it */
static int getPermittedActions( const int usageFlags )
{
int actionFlags = 0;
if( usageFlags & PKCS15_USAGE_ENCRYPT )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
ACTION_PERM_NONE_EXTERNAL );
if( usageFlags & PKCS15_USAGE_DECRYPT )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
ACTION_PERM_NONE_EXTERNAL );
if( usageFlags & PKCS15_USAGE_SIGN )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN,
ACTION_PERM_NONE_EXTERNAL );
if( usageFlags & PKCS15_USAGE_VERIFY )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK,
ACTION_PERM_NONE_EXTERNAL );
if( usageFlags & PKCS15_USAGE_DERIVE )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
ACTION_PERM_NONE_EXTERNAL );
return( !actionFlags ? CRYPT_ERROR_PERMISSION : actionFlags );
}
/* Read a sequence of PKCS #15 key identifiers */
static int readKeyIdentifiers( STREAM *stream, PKCS15_INFO *pkcs15info,
const int length )
{
const int endPos = ( int ) stell( stream ) + length;
int status = CRYPT_OK;
while( !cryptStatusError( status ) && stell( stream ) < endPos )
{
HASHFUNCTION hashFunction;
void *iAndSPtr;
long value;
int hashSize, payloadLength, iAndSLength;
/* Read each identifier type and copy the useful ones into the PKCS
#15 info */
readSequence( stream, &payloadLength );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
break;
switch( value )
{
case PKCS15_KEYID_ISSUERANDSERIALNUMBER:
/* Hash the full issuerAndSerialNumber to get an iAndSID */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
iAndSPtr = sMemBufPtr( stream );
readSequence( stream, &iAndSLength );
status = sSkip( stream, iAndSLength );
if( cryptStatusError( status ) )
break;
hashFunction( NULL, ( BYTE * ) pkcs15info->iAndSID, iAndSPtr,
( int ) sizeofObject( iAndSLength ), HASH_ALL );
pkcs15info->iAndSIDlength = hashSize;
break;
case PKCS15_KEYID_SUBJECTKEYIDENTIFIER:
status = readOctetString( stream, pkcs15info->keyID,
&pkcs15info->keyIDlength, CRYPT_MAX_HASHSIZE );
break;
case PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH:
/* If we've already got the iAndSID by hashing the
issuerAndSerialNumber, use that version instead */
if( pkcs15info->iAndSIDlength )
{
readUniversal( stream );
continue;
}
status = readOctetString( stream, pkcs15info->iAndSID,
&pkcs15info->iAndSIDlength, KEYID_SIZE );
break;
case PKCS15_KEYID_ISSUERNAMEHASH:
status = readOctetString( stream, pkcs15info->issuerNameID,
&pkcs15info->issuerNameIDlength, KEYID_SIZE );
break;
case PKCS15_KEYID_SUBJECTNAMEHASH:
status = readOctetString( stream, pkcs15info->subjectNameID,
&pkcs15info->subjectNameIDlength, KEYID_SIZE );
break;
case PKCS15_KEYID_PGP2:
status = readOctetString( stream, pkcs15info->pgp2KeyID,
&pkcs15info->pgp2KeyIDlength, PGP_KEYID_SIZE );
break;
case PKCS15_KEYID_OPENPGP:
status = readOctetString( stream, pkcs15info->openPGPKeyID,
&pkcs15info->openPGPKeyIDlength, PGP_KEYID_SIZE );
break;
default:
status = readUniversal( stream );
}
}
return( status );
}
/* Read an object's attributes */
static int readObjectAttributes( STREAM *stream, PKCS15_INFO *pkcs15info,
const PKCS15_OBJECT_TYPE type )
{
int length, endPos, status;
/* Clear the return value */
memset( pkcs15info, 0, sizeof( PKCS15_INFO ) );
/* Skip the outer header (this has already been checked when we read in
the object data */
readTag( stream );
readShortLength( stream );
/* Process the PKCS15CommonObjectAttributes */
status = readSequence( stream, &length );
if( cryptStatusOK( status ) && length > 0 )
{
endPos = ( int ) stell( stream ) + length;
/* Read the label if it's present and skip anything else */
if( peekTag( stream ) == BER_STRING_UTF8 )
status = readOctetStringTag( stream,
( BYTE * ) pkcs15info->label, &pkcs15info->labelLength,
CRYPT_MAX_TEXTSIZE, BER_STRING_UTF8 );
if( cryptStatusOK( status ) && stell( stream ) < endPos )
status = sseek( stream, endPos );
}
if( cryptStatusError( status ) )
return( status );
/* Process the PKCS15CommonXXXAttributes */
readSequence( stream, &length );
endPos = ( int ) stell( stream ) + length;
if( type == PKCS15_OBJECT_DATA )
{
/* It's a data object, make sure it's one of ours */
status = readOID( stream, OID_CRYPTLIB_CONTENTTYPE );
if( cryptStatusOK( status ) && stell( stream ) < endPos )
status = sseek( stream, endPos );
}
else
{
/* It's a key or cert object, read the ID and assorted flags */
status = readOctetString( stream, pkcs15info->iD,
&pkcs15info->iDlength, CRYPT_MAX_HASHSIZE );
if( cryptStatusError( status ) )
return( status );
if( type == PKCS15_OBJECT_PUBKEY || type == PKCS15_OBJECT_PRIVKEY )
{
int usageFlags;
/* Usage flags */
readBitString( stream, &usageFlags );
if( peekTag( stream ) == BER_BOOLEAN ) /* Native flag */
status = readUniversal( stream );
if( stell( stream ) < endPos && /* Access flags */
peekTag( stream ) == BER_BITSTRING )
status = readUniversal( stream );
if( type == PKCS15_OBJECT_PUBKEY )
pkcs15info->pubKeyUsage = usageFlags;
else
pkcs15info->privKeyUsage = usageFlags;
}
else
if( type == PKCS15_OBJECT_CERT )
{
if( peekTag( stream ) == BER_BOOLEAN ) /* Authority flag */
status = readUniversal( stream );
if( stell( stream ) < endPos && /* Identifier */
peekTag( stream ) == BER_SEQUENCE )
status = readUniversal( stream );
if( stell( stream ) < endPos && /* Thumbprint */
peekTag( stream ) == MAKE_CTAG( CTAG_CA_DUMMY ) )
status = readUniversal( stream );
if( stell( stream ) < endPos &&
peekTag( stream ) == MAKE_CTAG( CTAG_CA_TRUSTED_USAGE ) )
{ /* Trusted usage */
readConstructed( stream, NULL, CTAG_CA_TRUSTED_USAGE );
status = readBitString( stream, &pkcs15info->trustedUsage );
}
if( stell( stream ) < endPos && \
peekTag( stream ) == MAKE_CTAG( CTAG_CA_IDENTIFIERS ) )
{ /* Identifiers */
readConstructed( stream, &length, CTAG_CA_IDENTIFIERS );
status = readKeyIdentifiers( stream, pkcs15info, length );
}
if( stell( stream ) < endPos && peekTag( stream ) == \
MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) )
status = readBooleanTag( stream,
&pkcs15info->implicitTrust,
MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) );
}
if( cryptStatusOK( status ) && stell( stream ) < endPos )
status = sseek( stream, endPos );
}
if( cryptStatusError( status ) )
return( status );
/* For now we use the iD as the keyID, this may be overridden later if
there's a real keyID present */
memcpy( pkcs15info->keyID, pkcs15info->iD, pkcs15info->iDlength );
pkcs15info->keyIDlength = pkcs15info->iDlength;
/* Skip the public/private key attributes if present */
if( peekTag( stream ) == MAKE_CTAG( CTAG_OB_SUBCLASSATTR ) )
status = readUniversal( stream );
if( cryptStatusError( status ) )
return( status );
/* Process the type attributes, which just consists of remembering where
the payload starts */
readConstructed( stream, NULL, CTAG_OB_TYPEATTR );
status = readSequence( stream, &length );
endPos = ( int ) stell( stream ) + length;
if( cryptStatusOK( status ) )
{
int value;
switch( type )
{
case PKCS15_OBJECT_PUBKEY:
readConstructed( stream, NULL, CTAG_OV_DIRECT );
pkcs15info->pubKeyOffset = ( int ) stell( stream );
break;
case PKCS15_OBJECT_PRIVKEY:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?