📄 pkcs15_adpb.c
字号:
pkcs15infoPtr->privKeyOffset;
status = calculatePrivkeyStorage( pkcs15infoPtr, &newPrivKeyData,
&newPrivKeyDataSize,
privKeyInfoSize,
privKeyAttributeSize, 0 );
if( cryptStatusError( status ) )
return( status );
}
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTIFICATE );
if( cryptStatusOK( status ) )
{
certInfoSize = msgData.length;
status = calculateCertStorage( pkcs15infoPtr, &newCertData,
&newCertDataSize, certAttributeSize,
certInfoSize );
}
if( cryptStatusError( status ) )
{
if( newPrivKeyData != pkcs15infoPtr->privKeyData )
clFree( "addCert", newPrivKeyData );
return( status );
}
/* Write the PKCS #15 certificate data */
sMemOpen( &stream, newCertData, newCertDataSize );
writeSequence( &stream, certAttributeSize + \
sizeofObject( sizeofObject( certInfoSize ) ) );
swrite( &stream, certAttributes, certAttributeSize );
writeConstructed( &stream, sizeofObject( certInfoSize ),
CTAG_OB_TYPEATTR );
status = writeSequence( &stream, certInfoSize );
if( cryptStatusOK( status ) )
{
newCertOffset = stell( &stream );
status = exportCertToStream( &stream, iCryptCert,
CRYPT_CERTFORMAT_CERTIFICATE );
}
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
/* Undo what we've done so far without changing the existing PKCS #15
data */
assert( DEBUG_WARN );
if( newPrivKeyData != pkcs15infoPtr->privKeyData )
clFree( "addCert", newPrivKeyData );
if( newCertData != pkcs15infoPtr->certData && newCertData != NULL )
clFree( "addCert", newCertData );
retExt( status,
( status, errorInfo,
"Couldn't write PKCS #15 certificate data" ) );
}
ENSURES( !cryptStatusError( checkObjectEncoding( newCertData, \
newCertDataSize ) ) );
#ifdef POST_DRAFT_ENCAPSULATION
/* Certificates require an awkward CTAG_OV_DIRECT (= [0] IMPLICIT) tag,
this is simple to handle when we're encoding the data ourselves (as
we do for public and private keys) but a serious pain if we're simply
exporting pre-encoded data like a certificate. In order to handle
this we modify the exported encoded data, which is easier than
passing the tag requirement down through the kernel call to the
certificate export code */
( ( BYTE * ) newCertData )[ newCertOffset ] = MAKE_CTAG( CTAG_OV_DIRECT );
#endif /* POST_DRAFT_ENCAPSULATION */
/* Replace the old certificate (if there is one) with the new one. If
it's a certificate associated with a private key we also have to
update the private-key attributes, which can be affected by
certificate information */
pkcs15infoPtr->type = subType;
replaceCertData( pkcs15infoPtr, newCertData, newCertDataSize,
newCertOffset );
if( certAddType == CERTADD_UPDATE_EXISTING )
{
updatePrivKeyAttributes( pkcs15infoPtr,
newPrivKeyData, newPrivKeyDataSize,
privKeyAttributes, privKeyAttributeSize,
privKeyInfoSize, keyTypeTag );
}
/* The public-key data is redundant now that we've performed the update,
delete it */
if( pkcs15infoPtr->pubKeyData != NULL )
deletePubKey( pkcs15infoPtr );
return( CRYPT_OK );
}
/* Add a complete certificate chain to a PKCS #15 collection */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int pkcs15AddCertChain( INOUT PKCS15_INFO *pkcs15info,
IN_LENGTH_SHORT const int noPkcs15objects,
IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
INOUT ERROR_INFO *errorInfo )
{
BOOLEAN seenNonDuplicate = FALSE;
int iterationCount = 0, status;
assert( isWritePtr( pkcs15info, \
sizeof( PKCS15_INFO ) * noPkcs15objects ) );
REQUIRES( noPkcs15objects >= 1 && \
noPkcs15objects < MAX_INTLENGTH_SHORT );
REQUIRES( isHandleRangeValid( iCryptCert ) );
REQUIRES( errorInfo != NULL );
/* See if there are certificates 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 certificates present */
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
if( cryptStatusOK( status ) )
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 certificate to see whether we need to
add it */
do
{
PKCS15_INFO *pkcs15infoPtr;
BYTE iAndSID[ CRYPT_MAX_HASHSIZE + 8 ];
int iAndSIDlength, index;
/* Check whether this certificate is present */
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,
iAndSID, KEYID_SIZE, &iAndSIDlength );
if( cryptStatusError( status ) )
continue;
if( findEntry( pkcs15info, noPkcs15objects, CRYPT_IKEYID_ISSUERID,
iAndSID, iAndSIDlength, KEYMGMT_FLAG_NONE ) != NULL )
continue;
/* We've found a certificate that isn't present yet, try and add
it */
pkcs15infoPtr = findFreeEntry( pkcs15info, noPkcs15objects, &index );
if( pkcs15infoPtr == NULL )
return( CRYPT_ERROR_OVERFLOW );
status = pkcs15AddCert( pkcs15infoPtr, iCryptCert, NULL, 0,
CERTADD_NORMAL, errorInfo );
if( cryptStatusOK( status ) )
pkcs15infoPtr->index = index;
/* A certificate being added may already be present, however we
can't fail immediately because there may be further certificates
in the chain that can be added so we keep track of whether we've
successfully added at least one certificate and clear data
duplicate errors */
if( cryptStatusOK( status ) )
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 && \
iterationCount++ < FAILSAFE_ITERATIONS_MED );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
if( cryptStatusOK( status ) && !seenNonDuplicate )
{
/* We reached the end of the chain without finding anything that we
could add, return a data duplicate error */
retExt( CRYPT_ERROR_DUPLICATE,
( CRYPT_ERROR_DUPLICATE, errorInfo,
"Couldn't find any new certificates to add" ) );
}
return( status );
}
/****************************************************************************
* *
* Add a Public Key *
* *
****************************************************************************/
/* Add a public key to a PKCS #15 collection */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 7 ) ) \
int pkcs15AddPublicKey( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_HANDLE const CRYPT_HANDLE iCryptContext,
IN_BUFFER( pubKeyAttributeSize ) \
const void *pubKeyAttributes,
IN_LENGTH_SHORT const int pubKeyAttributeSize,
IN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo,
IN_LENGTH_PKC const int modulusSize,
INOUT ERROR_INFO *errorInfo )
{
MESSAGE_DATA msgData;
STREAM stream;
void *newPubKeyData = pkcs15infoPtr->pubKeyData;
int newPubKeyDataSize, newPubKeyOffset = DUMMY_INIT, pubKeySize;
int extraDataSize = 0, keyTypeTag, status;
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( pubKeyAttributes, pubKeyAttributeSize ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( pubKeyAttributeSize > 0 && \
pubKeyAttributeSize < MAX_INTLENGTH_SHORT );
REQUIRES( pkcCryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
pkcCryptAlgo <= CRYPT_ALGO_LAST_PKC );
REQUIRES( modulusSize >= MIN_PKCSIZE && \
modulusSize <= CRYPT_MAX_PKCSIZE );
REQUIRES( errorInfo != NULL );
/* Get the tag for encoding the key data */
status = getKeyTypeTag( CRYPT_UNUSED, pkcCryptAlgo, &keyTypeTag );
if( cryptStatusError( status ) )
return( status );
/* Find out how big the PKCS #15 data will be and allocate room for it */
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusError( status ) )
return( status );
pubKeySize = msgData.length;
if( pkcCryptAlgo == CRYPT_ALGO_RSA )
{
/* RSA keys have an extra element for PKCS #11 compatibility */
extraDataSize = sizeofShortInteger( modulusSize );
}
status = calculatePubkeyStorage( pkcs15infoPtr, &newPubKeyData,
&newPubKeyDataSize, pubKeySize,
pubKeyAttributeSize, extraDataSize );
if( cryptStatusError( status ) )
return( status );
/* Write the public key data */
sMemOpen( &stream, newPubKeyData, newPubKeyDataSize );
writeConstructed( &stream, pubKeyAttributeSize + \
sizeofObject( \
sizeofObject( \
sizeofObject( pubKeySize ) + \
extraDataSize ) ),
keyTypeTag );
swrite( &stream, pubKeyAttributes, pubKeyAttributeSize );
writeConstructed( &stream, sizeofObject( \
sizeofObject( pubKeySize ) + \
extraDataSize ),
CTAG_OB_TYPEATTR );
writeSequence( &stream, sizeofObject( pubKeySize ) + extraDataSize );
status = writeConstructed( &stream, pubKeySize, CTAG_OV_DIRECT );
if( cryptStatusOK( status ) )
{
newPubKeyOffset = stell( &stream );
status = exportAttributeToStream( &stream, iCryptContext,
CRYPT_IATTRIBUTE_KEY_SPKI );
}
if( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )
{
/* When using the SPKI option for storing key components the RSA
components require a [1] tag since the basic (non-SPKI) option is
also a SEQUENCE, so if it's an RSA key we modify the tag. This is
easier than passing the tag requirement down through the kernel
call to the context. In addition RSA keys have an extra element
for PKCS #11 compatibility */
( ( BYTE * ) newPubKeyData )[ newPubKeyOffset ] = MAKE_CTAG( 1 );
status = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );
}
assert( stell( &stream ) == newPubKeyDataSize );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
assert( DEBUG_WARN );
if( newPubKeyData != pkcs15infoPtr->pubKeyData )
clFree( "addPublicKey", newPubKeyData );
retExt( status,
( status, errorInfo,
"Couldn't write PKCS #15 public-key data" ) );
}
ENSURES( !cryptStatusError( checkObjectEncoding( newPubKeyData, \
newPubKeyDataSize ) ) );
/* Replace the old data with the newly-written data */
replacePubkeyData( pkcs15infoPtr, newPubKeyData, newPubKeyDataSize,
newPubKeyOffset );
return( CRYPT_OK );
}
#endif /* USE_PKCS15 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -