📄 pkcs15_wr.c
字号:
CRYPT_UNUSED );
sSkip( stream, exportedKeySize );
}
/* Clean up */
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Add a certificate to a PKCS #15 collection, updating affected public and
private key attributes as required */
static int addCert( PKCS15_INFO *pkcs15infoPtr,
const CRYPT_CERTIFICATE cryptCert,
const void *pubKeyAttributes,
const int pubKeyAttributeSize,
const void *privKeyAttributes,
const int privKeyAttributeSize,
const CERTADD_TYPE certAddType )
{
RESOURCE_DATA msgData;
STREAM stream;
BYTE keyBuffer[ MAX_PRIVATE_KEYSIZE ];
BYTE certAttributes[ KEYATTR_BUFFER_SIZE ];
void *newPrivKeyData = pkcs15infoPtr->privKeyData;
#ifdef RETAIN_PUBKEY
void *newPubKeyData = pkcs15infoPtr->pubKeyData;
#endif /* RETAIN_PUBKEY */
void *newCertData = pkcs15infoPtr->certData;
const int keyTypeTag = getKeyTypeTag( cryptCert );
int newPrivKeyDataSize, newPrivKeyOffset, privKeyInfoSize;
#ifdef RETAIN_PUBKEY
int newPubKeyDataSize, newPubKeyOffset, pubKeyInfoSize;
#endif /* RETAIN_PUBKEY */
int newCertDataSize, newCertOffset, certAttributeSize;
int status;
/* If we've been passed a standalone cert, it has to be implicitly
trusted in order to be added */
if( certAddType == CERTADD_STANDALONE_CERT )
{
int value;
status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_TRUSTED_IMPLICIT );
if( cryptStatusError( status ) || !value )
return( CRYPT_ARGERROR_NUM1 );
/* Set the personality type to cert-only */
pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
}
/* Write the cert attributes */
status = writeCertAttributes( certAttributes, &certAttributeSize,
pkcs15infoPtr, cryptCert );
if( cryptStatusError( status ) )
return( status );
/* Find out how big the PKCS #15 data will be and allocate room for it.
Since the cert will affect the key attributes, we need to rewrite the
key information once we've done the cert. If the rewritten key data
will fit into the existing space (for example if only a permission bit
or two has changed) we reuse the current storage, otherwise we
allocate new storage */
if( certAddType == CERTADD_UPDATE_EXISTING )
{
#ifdef RETAIN_PUBKEY
pubKeyInfoSize = pkcs15infoPtr->pubKeyDataSize - \
pkcs15infoPtr->pubKeyOffset;
newPubKeyDataSize = pubKeyAttributeSize + \
( int ) sizeofObject( \
sizeofObject( \
sizeofObject( pubKeyInfoSize ) ) );
if( sizeofObject( newPubKeyDataSize ) > \
pkcs15infoPtr->pubKeyDataSize )
{
newPubKeyData = \
clAlloc( "addCert", \
( int ) sizeofObject( newPubKeyDataSize ) );
if( newPubKeyData == NULL )
return( CRYPT_ERROR_MEMORY );
}
#else
if( pkcs15infoPtr->pubKeyData != NULL )
{
zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
clFree( "addCert", pkcs15infoPtr->pubKeyData );
pkcs15infoPtr->pubKeyData = NULL;
pkcs15infoPtr->pubKeyDataSize = 0;
}
#endif /* RETAIN_PUBKEY */
privKeyInfoSize = pkcs15infoPtr->privKeyDataSize - \
pkcs15infoPtr->privKeyOffset;
newPrivKeyDataSize = privKeyAttributeSize + \
( int ) sizeofObject( \
sizeofObject( privKeyInfoSize ) );
if( sizeofObject( newPrivKeyDataSize ) > \
pkcs15infoPtr->privKeyDataSize )
{
newPrivKeyData = \
clAlloc( "addCert", \
( int ) sizeofObject( newPrivKeyDataSize ) );
if( ( newPrivKeyData == NULL ) )
{
#ifdef RETAIN_PUBKEY
clFree( "addCert", newPubKeyData );
#endif /* RETAIN_PUBKEY */
return( CRYPT_ERROR_MEMORY );
}
}
}
setMessageData( &msgData, keyBuffer, MAX_PRIVATE_KEYSIZE );
status = krnlSendMessage( cryptCert, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTIFICATE );
if( cryptStatusOK( status ) )
{
newCertDataSize = ( int ) sizeofObject( \
certAttributeSize + \
sizeofObject( \
sizeofObject( msgData.length ) ) );
if( newCertDataSize > pkcs15infoPtr->certDataSize )
{
newCertData = clAlloc( "addCert", newCertDataSize );
if( newCertData == NULL )
status = CRYPT_ERROR_MEMORY;
}
}
if( cryptStatusOK( status ) )
{
sMemOpen( &stream, newCertData, newCertDataSize );
writeSequence( &stream, certAttributeSize + \
( int ) sizeofObject( sizeofObject( msgData.length ) ) );
swrite( &stream, certAttributes, certAttributeSize );
writeConstructed( &stream, ( int ) sizeofObject( msgData.length ),
CTAG_OB_TYPEATTR );
writeSequence( &stream, msgData.length );
newCertOffset = stell( &stream );
swrite( &stream, keyBuffer, msgData.length );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
}
if( cryptStatusError( status ) )
{
/* Undo what we've done so far without changing the existing PKCS #15
data */
#ifdef RETAIN_PUBKEY
if( newPubKeyData != pkcs15infoPtr->pubKeyData )
clFree( "addCert", newPubKeyData );
#endif /* RETAIN_PUBKEY */
if( newPrivKeyData != pkcs15infoPtr->privKeyData )
clFree( "addCert", newPrivKeyData );
if( newCertData != pkcs15infoPtr->certData && newCertData != NULL )
clFree( "addCert", newCertData );
return( status );
}
/* Replace the old cert (if there is one) with the new cert. If it's an
add of a standalone cert, we're done */
if( newCertData != pkcs15infoPtr->certData )
{
if( pkcs15infoPtr->certData != NULL )
{
zeroise( pkcs15infoPtr->certData, pkcs15infoPtr->certDataSize );
clFree( "addCert", pkcs15infoPtr->certData );
}
pkcs15infoPtr->certData = newCertData;
}
pkcs15infoPtr->certDataSize = newCertDataSize;
pkcs15infoPtr->certOffset = newCertOffset;
if( certAddType != CERTADD_UPDATE_EXISTING )
return( CRYPT_OK );
#ifdef RETAIN_PUBKEY
assert( pubKeyInfoSize < MAX_PRIVATE_KEYSIZE );
#endif /* RETAIN_PUBKEY */
assert( privKeyInfoSize < MAX_PRIVATE_KEYSIZE );
/* The corresponding key is already present, we need to update the key
info since adding the certificate may have changed the attributes.
First we write the new attributes and append the existing key info.
Since we may be doing an in-place update, we copy the data out to a
temporary buffer while we make the changes */
#ifdef RETAIN_PUBKEY
memcpy( keyBuffer, ( BYTE * ) pkcs15infoPtr->pubKeyData +
pkcs15infoPtr->pubKeyOffset,
pubKeyInfoSize );
sMemOpen( &stream, newPubKeyData,
( int ) sizeofObject( newPubKeyDataSize ) );
writeConstructed( &stream, newPubKeyDataSize, keyTypeTag );
swrite( &stream, pubKeyAttributes, pubKeyAttributeSize );
writeConstructed( &stream,
( int ) sizeofObject( sizeofObject( pubKeyInfoSize ) ),
CTAG_OB_TYPEATTR );
writeSequence( &stream, ( int ) sizeofObject( pubKeyInfoSize ) );
writeConstructed( &stream, pubKeyInfoSize, CTAG_OV_DIRECT );
newPubKeyOffset = stell( &stream );
swrite( &stream, keyBuffer, pubKeyInfoSize );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
#endif /* RETAIN_PUBKEY */
memcpy( keyBuffer, ( BYTE * ) pkcs15infoPtr->privKeyData +
pkcs15infoPtr->privKeyOffset,
privKeyInfoSize );
sMemOpen( &stream, newPrivKeyData,
( int ) sizeofObject( newPrivKeyDataSize ) );
writeConstructed( &stream, newPrivKeyDataSize, keyTypeTag );
swrite( &stream, privKeyAttributes, privKeyAttributeSize );
writeConstructed( &stream, ( int ) sizeofObject( privKeyInfoSize ),
CTAG_OB_TYPEATTR );
writeSequence( &stream, privKeyInfoSize );
newPrivKeyOffset = stell( &stream );
swrite( &stream, keyBuffer, privKeyInfoSize );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
zeroise( keyBuffer, MAX_PRIVATE_KEYSIZE );
/* Replace the old data with the newly-written data */
#ifdef RETAIN_PUBKEY
if( newPubKeyData != pkcs15infoPtr->pubKeyData )
{
zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
clFree( "addCert", pkcs15infoPtr->pubKeyData );
pkcs15infoPtr->pubKeyData = newPubKeyData;
}
#endif /* RETAIN_PUBKEY */
if( newPrivKeyData != pkcs15infoPtr->privKeyData )
{
zeroise( pkcs15infoPtr->privKeyData, pkcs15infoPtr->privKeyDataSize );
clFree( "addCert", pkcs15infoPtr->privKeyData );
pkcs15infoPtr->privKeyData = newPrivKeyData;
}
#ifdef RETAIN_PUBKEY
pkcs15infoPtr->pubKeyDataSize = ( int ) sizeofObject( newPubKeyDataSize );
pkcs15infoPtr->pubKeyOffset = newPubKeyOffset;
#endif /* RETAIN_PUBKEY */
pkcs15infoPtr->privKeyDataSize = ( int ) sizeofObject( newPrivKeyDataSize );
pkcs15infoPtr->privKeyOffset = newPrivKeyOffset;
return( CRYPT_OK );
}
/* Add a complete cert chain to a PKCS #15 collection */
static int addCertChain( PKCS15_INFO *pkcs15info,
const CRYPT_CERTIFICATE iCryptCert )
{
BOOLEAN seenNonDuplicate = FALSE;
int status;
/* See if there are certs in the chain beyond the first one, which we've
already added. Getting a data not found error is OK since it just
means that there are no more certs present */
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORNEXT,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );
/* Walk up the chain checking each cert to see whether we need to add
it */
do
{
PKCS15_INFO *pkcs15infoPtr;
BYTE iAndSID [ CRYPT_MAX_HASHSIZE ];
int i;
/* Check whether this cert is present */
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,
iAndSID );
if( cryptStatusError( status ) )
continue;
if( findEntry( pkcs15info, CRYPT_IKEYID_ISSUERID, iAndSID,
KEYID_SIZE, KEYMGMT_FLAG_NONE ) != NULL )
continue;
/* We've found a cert that isn't present yet, try and add it */
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
break;
if( i == MAX_PKCS15_OBJECTS )
return( CRYPT_ERROR_OVERFLOW );
pkcs15infoPtr = &pkcs15info[ i ];
pkcs15infoPtr->index = i;
pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
status = addCert( pkcs15infoPtr, iCryptCert, NULL, 0, NULL, 0,
CERTADD_NORMAL );
/* A cert being added may already be present, however we can't fail
immediately because there may be further certs in the chain, so we
keep track of whether we've successfully added at least one cert
and clear data duplicate errors */
if( status == CRYPT_OK )
seenNonDuplicate = TRUE;
else
if( status == CRYPT_ERROR_DUPLICATE )
status = CRYPT_OK;
}
while( cryptStatusOK( status ) && \
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORNEXT,
CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
if( cryptStatusOK( status ) && !seenNonDuplicate )
/* We reached the end of the chain without finding anything we could
add, return a data duplicate error */
status = CRYPT_ERROR_DUPLICATE;
return( status );
}
/* Add a public key to a PKCS #15 collection */
static int addPublicKey( PKCS15_INFO *pkcs15info,
const CRYPT_HANDLE cryptHandle,
const void *pubKeyAttributes,
const int pubKeyAttributeSize,
const CRYPT_ALGO_TYPE pkcCryptAlgo,
const int modulusSize )
{
RESOURCE_DATA msgData;
STREAM stream;
const int keyTypeTag = getKeyTypeTag( cryptHandle );
int pubKeyDataSize, extraDataSize = 0, status;
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEY_SPKI );
pubKeyDataSize = msgData.length;
if( pkcCryptAlgo == CRYPT_ALGO_RSA )
/* RSA keys have an extra element for PKCS #11 compatibility */
extraDataSize = sizeofShortInteger( modulusSize );
if( cryptStatusOK( status ) )
{
pkcs15info->pubKeyDataSize = ( int ) sizeofObject( \
pubKeyAttributeSize + \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -