📄 pkcs15_adpb.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 Public-key Add Interface *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "pkcs15.h"
#include "asn1.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/pkcs15.h"
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
#ifdef USE_PKCS15
/* Define the following to use the post-PKCS #15 draft encapsulation for
certificates. Note that this will break backwards compatibility for
cryptlib versions before 3.3.0 (which dates from late 2006) because
earlier versions (likewise for backwards compatibility) still read and
wrote the original form */
/* #define POST_DRAFT_ENCAPSULATION */
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Calculate the size of and if necessary allocate storage for public-key
and certificate data */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int calculatePubkeyStorage( const PKCS15_INFO *pkcs15infoPtr,
OUT_PTR void **newPubKeyDataPtr,
OUT_LENGTH_SHORT_Z int *newPubKeyDataSize,
IN_LENGTH_SHORT const int pubKeySize,
IN_LENGTH_SHORT const int pubKeyAttributeSize,
IN_LENGTH_SHORT const int extraDataSize )
{
void *newPubKeyData;
assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isWritePtr( newPubKeyDataPtr, sizeof( void * ) ) );
assert( isWritePtr( newPubKeyDataSize, sizeof( int ) ) );
REQUIRES( pubKeySize > 0 && pubKeySize < MAX_INTLENGTH_SHORT );
REQUIRES( pubKeyAttributeSize > 0 && \
pubKeyAttributeSize < MAX_INTLENGTH_SHORT );
REQUIRES( extraDataSize >= 0 && extraDataSize < MAX_INTLENGTH_SHORT );
/* Calculate the new private-key data size */
*newPubKeyDataSize = sizeofObject( \
pubKeyAttributeSize + \
sizeofObject( \
sizeofObject( \
sizeofObject( pubKeySize ) + \
extraDataSize ) ) );
/* If the new data will fit into the existing storage, we're done */
if( *newPubKeyDataSize <= pkcs15infoPtr->pubKeyDataSize )
return( CRYPT_OK );
/* Allocate storage for the new data */
newPubKeyData = clAlloc( "calculatePubkeyStorage", *newPubKeyDataSize );
if( newPubKeyData == NULL )
return( CRYPT_ERROR_MEMORY );
*newPubKeyDataPtr = newPubKeyData;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int calculateCertStorage( const PKCS15_INFO *pkcs15infoPtr,
OUT_PTR void **newCertDataPtr,
OUT_LENGTH_SHORT_Z int *newCertDataSize,
IN_LENGTH_SHORT const int certAttributeSize,
IN_LENGTH_SHORT const int certSize )
{
void *newCertData;
assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isWritePtr( newCertDataPtr, sizeof( void * ) ) );
assert( isWritePtr( newCertDataSize, sizeof( int ) ) );
REQUIRES( certAttributeSize > 0 && \
certAttributeSize < MAX_INTLENGTH_SHORT );
REQUIRES( certSize > 0 && certSize < MAX_INTLENGTH_SHORT );
/* Calculate the new certificate data size */
*newCertDataSize = sizeofObject( certAttributeSize + \
sizeofObject( \
sizeofObject( certSize ) ) );
/* If the new data will fit into the existing storage, we're done */
if( *newCertDataSize <= pkcs15infoPtr->certDataSize )
return( CRYPT_OK );
/* Allocate storage for the new data */
newCertData = clAlloc( "calculateCertStorage", *newCertDataSize );
if( newCertData == NULL )
return( CRYPT_ERROR_MEMORY );
*newCertDataPtr = newCertData;
return( CRYPT_OK );
}
/* Delete the public-key entry for a personality, used when we're replacing
the pubkey with a certificate */
STDC_NONNULL_ARG( ( 1 ) ) \
static void deletePubKey( INOUT PKCS15_INFO *pkcs15infoPtr )
{
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
clFree( "deletePubKey", pkcs15infoPtr->pubKeyData );
pkcs15infoPtr->pubKeyData = NULL;
pkcs15infoPtr->pubKeyDataSize = 0;
}
/* Replace existing public-key or certificate data with updated
information */
STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void replacePubkeyData( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_BUFFER( newPubKeyDataSize ) \
const void *newPubKeyData,
IN_LENGTH_SHORT_MIN( 16 ) \
const int newPubKeyDataSize,
IN_LENGTH_SHORT const int newPubKeyOffset )
{
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( newPubKeyData, newPubKeyDataSize ) );
REQUIRES_V( newPubKeyDataSize >= 16 && \
newPubKeyDataSize < MAX_INTLENGTH_SHORT );
REQUIRES_V( newPubKeyOffset > 0 && \
newPubKeyOffset < newPubKeyDataSize && \
newPubKeyOffset < MAX_INTLENGTH_SHORT );
/* If we've allocated new storage for the data rather than directly
replacing the existing entry, free the existing entry and replace it
with the new one */
if( newPubKeyData != pkcs15infoPtr->pubKeyData )
{
if( pkcs15infoPtr->pubKeyData != NULL )
{
zeroise( pkcs15infoPtr->pubKeyData,
pkcs15infoPtr->pubKeyDataSize );
clFree( "replacePubkeyData", pkcs15infoPtr->pubKeyData );
}
pkcs15infoPtr->pubKeyData = ( void * ) newPubKeyData;
}
/* Update the size information */
pkcs15infoPtr->pubKeyDataSize = newPubKeyDataSize;
pkcs15infoPtr->pubKeyOffset = newPubKeyOffset;
}
STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void replaceCertData( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_BUFFER( newCertDataSize ) \
const void *newCertData,
IN_LENGTH_SHORT_MIN( 16 ) \
const int newCertDataSize,
IN_LENGTH_SHORT const int newCertOffset )
{
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( newCertData, newCertDataSize ) );
REQUIRES_V( newCertDataSize >= 16 && \
newCertDataSize < MAX_INTLENGTH_SHORT );
REQUIRES_V( newCertOffset > 0 && \
newCertOffset < newCertDataSize && \
newCertOffset < MAX_INTLENGTH_SHORT );
/* If we've allocated new storage for the data rather than directly
replacing the existing entry, free the existing entry and replace it
with the new one */
if( newCertData != pkcs15infoPtr->certData )
{
if( pkcs15infoPtr->certData != NULL )
{
zeroise( pkcs15infoPtr->certData, pkcs15infoPtr->certDataSize );
clFree( "replaceCertData", pkcs15infoPtr->certData );
}
pkcs15infoPtr->certData = ( void * ) newCertData;
}
/* Update the size information */
pkcs15infoPtr->certDataSize = newCertDataSize;
pkcs15infoPtr->certOffset = newCertOffset;
}
/****************************************************************************
* *
* Add a Certificate *
* *
****************************************************************************/
/* Add a certificate to a PKCS #15 collection, updating affected public and
private key attributes as required */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
int pkcs15AddCert( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
IN_BUFFER_OPT( privKeyAttributeSize ) \
const void *privKeyAttributes,
IN_LENGTH_SHORT_Z const int privKeyAttributeSize,
IN_ENUM( CERTADD ) const CERTADD_TYPE certAddType,
INOUT ERROR_INFO *errorInfo )
{
MESSAGE_DATA msgData;
STREAM stream;
BYTE certAttributes[ KEYATTR_BUFFER_SIZE + 8 ];
void *newCertData = pkcs15infoPtr->certData;
void *newPrivKeyData = pkcs15infoPtr->privKeyData;
int newCertDataSize = DUMMY_INIT, certInfoSize = DUMMY_INIT;
int newPrivKeyDataSize = DUMMY_INIT, privKeyInfoSize = DUMMY_INIT;
int newCertOffset = DUMMY_INIT, certAttributeSize;
int subType = PKCS15_SUBTYPE_NORMAL, keyTypeTag, status;
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( ( certAddType == CERTADD_UPDATE_EXISTING && \
isReadPtr( privKeyAttributes, privKeyAttributeSize ) ) || \
( ( certAddType == CERTADD_NORMAL || \
certAddType == CERTADD_STANDALONE_CERT ) && \
privKeyAttributes == NULL && privKeyAttributeSize == 0 ) );
REQUIRES( isHandleRangeValid( iCryptCert ) );
REQUIRES( ( certAddType == CERTADD_UPDATE_EXISTING && \
privKeyAttributes != NULL && \
privKeyAttributeSize > 0 && \
privKeyAttributeSize < MAX_INTLENGTH_SHORT ) || \
( ( certAddType == CERTADD_NORMAL || \
certAddType == CERTADD_STANDALONE_CERT ) && \
privKeyAttributes == NULL && privKeyAttributeSize == 0 ) );
REQUIRES( certAddType > CERTADD_NONE && certAddType < CERTADD_LAST );
REQUIRES( errorInfo != NULL );
/* Get the tag for encoding the key data */
status = getKeyTypeTag( iCryptCert, CRYPT_ALGO_NONE, &keyTypeTag );
if( cryptStatusError( status ) )
return( status );
/* If we've been passed a standalone certificate it has to be
implicitly trusted in order to be added */
if( certAddType == CERTADD_STANDALONE_CERT )
{
int value;
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_TRUSTED_IMPLICIT );
if( cryptStatusError( status ) || !value )
{
retExtArg( CRYPT_ARGERROR_NUM1,
( CRYPT_ARGERROR_NUM1, errorInfo,
"Only a trusted certificate can be added as a "
"standalone certificate" ) );
}
/* Set the personality type to certificate-only */
subType = PKCS15_SUBTYPE_CERT;
}
/* Write the certificate attributes */
status = writeCertAttributes( certAttributes, KEYATTR_BUFFER_SIZE,
&certAttributeSize, pkcs15infoPtr,
iCryptCert );
if( cryptStatusError( status ) )
{
retExt( status,
( status, errorInfo,
"Couldn't write certificate attributes" ) );
}
/* Find out how big the PKCS #15 data will be and allocate room for it.
Since adding the certificate will affect the key attributes we need
to rewrite the key information once we've added the certificate */
if( certAddType == CERTADD_UPDATE_EXISTING )
{
/* Since we're re-using pre-encoded private key data the extra
information is already present in encoded form so we set the
extraDataSize parameter to zero */
privKeyInfoSize = pkcs15infoPtr->privKeyDataSize - \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -