📄 pkcs15_atwr.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 Attribute Write Routines *
* 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
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Get assorted ID information from a context or certificate */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int getKeyIDs( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_HANDLE const CRYPT_HANDLE iCryptContext )
{
MESSAGE_DATA msgData;
BYTE sKIDbuffer[ CRYPT_MAX_HASHSIZE + 8 ];
int status;
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
/* Get various pieces of information from the object. The information
may already have been set up earlier on so we only set it if this is
a newly-added key. We use a guard for the existence of both a label
and an ID since there may be a pre-set user ID (which isn't the same
as the key ID) present for implicitly created keys in user keysets */
if( pkcs15infoPtr->labelLength <= 0 )
{
setMessageData( &msgData, pkcs15infoPtr->label, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
if( cryptStatusError( status ) )
return( status );
pkcs15infoPtr->labelLength = msgData.length;
setMessageData( &msgData, pkcs15infoPtr->keyID, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
if( cryptStatusError( status ) )
return( status );
pkcs15infoPtr->keyIDlength = msgData.length;
}
if( pkcs15infoPtr->iDlength <= 0 && pkcs15infoPtr->keyIDlength > 0 )
{
memcpy( pkcs15infoPtr->iD, pkcs15infoPtr->keyID,
pkcs15infoPtr->keyIDlength );
pkcs15infoPtr->iDlength = pkcs15infoPtr->keyIDlength;
}
if( pkcs15infoPtr->pgp2KeyIDlength <= 0 )
{
setMessageData( &msgData, pkcs15infoPtr->pgp2KeyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_PGP2 );
if( cryptStatusOK( status ) )
{
/* Not present for all key types so an error isn't fatal */
pkcs15infoPtr->pgp2KeyIDlength = msgData.length;
}
}
if( pkcs15infoPtr->openPGPKeyIDlength <= 0 )
{
setMessageData( &msgData, pkcs15infoPtr->openPGPKeyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
if( cryptStatusError( status ) )
return( status );
pkcs15infoPtr->openPGPKeyIDlength = msgData.length;
}
/* The subjectKeyIdentifier, if present, may not be the same as the
keyID if the certificate that it's in has come from a CA that does
strange things with the sKID so we try and read this value and if
it's present override the implicit sKID (== keyID) value with the
actual sKID */
setMessageData( &msgData, sKIDbuffer, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusOK( status ) )
{
memcpy( pkcs15infoPtr->keyID, sKIDbuffer, msgData.length );
pkcs15infoPtr->keyIDlength = msgData.length;
}
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \
static int getCertIDs( INOUT PKCS15_INFO *pkcs15infoPtr,
IN_HANDLE const CRYPT_HANDLE iCryptCert,
OUT BOOLEAN *isCA,
OUT BOOLEAN *trustedImplicit,
OUT int *trustedUsage )
{
int status;
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isWritePtr( isCA, sizeof( BOOLEAN ) ) );
assert( isWritePtr( trustedImplicit, sizeof( BOOLEAN ) ) );
assert( isWritePtr( trustedUsage, sizeof( int ) ) );
REQUIRES( isHandleRangeValid( iCryptCert ) );
/* Clear return values */
*isCA = *trustedImplicit = FALSE;
*trustedUsage = CRYPT_UNUSED;
/* Get various pieces of status information from the certificate */
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, isCA,
CRYPT_CERTINFO_CA );
if( status == CRYPT_ERROR_NOTFOUND )
{
*isCA = FALSE;
status = CRYPT_OK;
}
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
trustedUsage, CRYPT_CERTINFO_TRUSTED_USAGE );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* If there's no trusted usage defined, don't store a trust
setting */
*trustedUsage = CRYPT_UNUSED;
status = CRYPT_OK;
}
}
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
&trustedImplicit, CRYPT_CERTINFO_TRUSTED_IMPLICIT );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* If it's not implicitly trusted, don't store a trust setting */
*trustedImplicit = FALSE;
status = CRYPT_OK;
}
}
if( cryptStatusOK( status ) )
status = getValidityInfo( pkcs15infoPtr, iCryptCert );
if( cryptStatusError( status ) )
return( status );
/* If we're adding a standalone certificate then the iD and keyID won't
have been set up yet so we need to set these up as well. Since the
certificate could be a data-only one we create the iD ourselves from
the encoded public key components rather than trying to read an
associated context's keyID attribute. For similar reasons we
specifically don't try and read the PGP ID information since for a
certificate chain it'll come from the context of the leaf certificate
rather than the current certificate (in any case they're not
necessary since none of the certificates in the chain will be PGP
keys) */
if( pkcs15infoPtr->iDlength <= 0 )
{
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_SPKI,
pkcs15infoPtr->iD, KEYID_SIZE,
&pkcs15infoPtr->iDlength );
if( cryptStatusError( status ) )
return( status );
}
if( pkcs15infoPtr->keyIDlength <= 0 )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, pkcs15infoPtr->keyID, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusOK( status ) )
pkcs15infoPtr->keyIDlength = msgData.length;
else
{
memcpy( pkcs15infoPtr->keyID, pkcs15infoPtr->iD,
pkcs15infoPtr->iDlength );
pkcs15infoPtr->keyIDlength = pkcs15infoPtr->iDlength;
}
}
/* Get the various other IDs for the certificate */
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,
pkcs15infoPtr->iAndSID, KEYID_SIZE,
&pkcs15infoPtr->iAndSIDlength );
if( cryptStatusOK( status ) )
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_SUBJECT,
pkcs15infoPtr->subjectNameID, KEYID_SIZE,
&pkcs15infoPtr->subjectNameIDlength );
if( cryptStatusOK( status ) )
status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUER,
pkcs15infoPtr->issuerNameID, KEYID_SIZE,
&pkcs15infoPtr->issuerNameIDlength );
return( status );
}
/* Get the PKCS #15 key usage flags for a context */
CHECK_RETVAL \
static int getKeyUsageFlags( IN_HANDLE const CRYPT_HANDLE iCryptContext,
IN_FLAGS( PKCS15_USAGE ) const int privKeyUsage )
{
int keyUsage = PKSC15_USAGE_FLAG_NONE, value, status;
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( privKeyUsage >= PKSC15_USAGE_FLAG_NONE && \
privKeyUsage < PKCS15_USAGE_FLAG_MAX );
/* Obtaining the usage flags gets a bit complicated because they're a
mixture of parts of X.509 and PKCS #11 flags (and the X.509 -> PKCS
#15 mapping isn't perfect, see for example key agreement) so we have
to build them up from bits and pieces pulled in from all over the
place */
if( cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_ENCRYPT ) ) )
keyUsage = PKCS15_USAGE_ENCRYPT;
if( cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_DECRYPT ) ) )
keyUsage |= PKCS15_USAGE_DECRYPT;
if( cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_SIGN ) ) )
keyUsage |= PKCS15_USAGE_SIGN;
if( cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_SIGCHECK ) ) )
keyUsage |= PKCS15_USAGE_VERIFY;
if( cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_KA_EXPORT ) ) || \
cryptStatusOK( krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
keyUsage |= PKCS15_USAGE_DERIVE; /* I don't think so Tim */
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_KEYUSAGE );
if( cryptStatusOK( status ) && \
( value & CRYPT_KEYUSAGE_NONREPUDIATION ) )
{
/* This may be a raw key or a certificate with no keyUsage present
so a failure to read the usage attribute isn't a problem */
keyUsage |= PKCS15_USAGE_NONREPUDIATION;
}
/* If the key ends up being unusable, tell the caller */
if( keyUsage <= PKSC15_USAGE_FLAG_NONE )
return( 0 );
/* If this is a public-key object which is updating a private-key one
then the only key usages that we'll have found are public-key ones.
To ensure that we don't disable use of the private-key object we copy
across private-key usages where corresponding public-key ones are
enabled. This is used, for example, when updating an unrestricted-
usage raw private key with a restricted-usage public key, e.g. from a
certificate */
if( cryptStatusError( krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_PRIVATE ) ) )
{
if( keyUsage & PKCS15_USAGE_ENCRYPT )
keyUsage |= privKeyUsage & PKCS15_USAGE_DECRYPT;
if( keyUsage & PKCS15_USAGE_VERIFY )
keyUsage |= privKeyUsage & PKCS15_USAGE_SIGN;
}
return( keyUsage );
}
/****************************************************************************
* *
* Write PKCS #15 Attributes *
* *
****************************************************************************/
/* Write PKCS #15 identifier values */
CHECK_RETVAL_RANGE( 0, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \
static int sizeofObjectIDs( const PKCS15_INFO *pkcs15infoPtr )
{
int identifierSize;
assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
identifierSize = ( int ) \
sizeofObject( \
sizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) + \
sizeofObject( pkcs15infoPtr->keyIDlength ) );
if( pkcs15infoPtr->iAndSIDlength > 0 )
identifierSize += ( int ) \
sizeofObject( \
sizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) + \
sizeofObject( pkcs15infoPtr->iAndSIDlength ) );
if( pkcs15infoPtr->issuerNameIDlength > 0 )
identifierSize += ( int ) \
sizeofObject( \
sizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) + \
sizeofObject( pkcs15infoPtr->issuerNameIDlength ) );
if( pkcs15infoPtr->subjectNameIDlength > 0 )
identifierSize += ( int ) \
sizeofObject( \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -