📄 chk_use.c
字号:
/****************************************************************************
* *
* Certificate Usage Checking Routines *
* Copyright Peter Gutmann 1997-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "cert.h"
#include "certattr.h"
#else
#include "cert/cert.h"
#include "cert/certattr.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* ExtKeyUsage to Key Usage Routines *
* *
****************************************************************************/
/* The following keyUsage settings are used based on extendedKeyUsage and
Netscape key usage extensions. In the following 'Y' = required, 'w' =
written but apparently not required, S = for signature keys only, E = for
encryption keys only, KA = for key agreement keys only.
dig non key dat key cer crl enc dec
sig rep enc enc agt sig sig onl onl
PKIX: -----------------------------------
serverAuth S E KA [1]
clientAuth S
codeSign Y
email Y Y E
ipsecEndSys S E KA
ipsecTunnel S E KA
ipsecUser S E KA
timeStamping Y Y
ocsp Y
directoryService ?
MS: -----------------------------------
individualCodeSign Y
commercialCodeSign Y
ctlSign Y
tsa Y
sgc E
encryptedFS E
NS: -----------------------------------
sgc E
NS extensions: -----------------------------------
sslClient Y
sslServer S E [1]
sMime S E
objectSign Y
sslCA Y w
sMimeCA Y w
objectSignCA Y w
-----------------------------------
dig non key dat key cer crl enc dec
sig rep enc enc agt sig sig onl onl
[1] These keys need to potentially perform both decryption for RSA key
transport and signing for (authenticating) DH key agreement */
/* Masks for various key usage types */
#define USAGE_SIGN_MASK ( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION | \
CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN )
#define USAGE_CRYPT_MASK ( CRYPT_KEYUSAGE_KEYENCIPHERMENT | \
CRYPT_KEYUSAGE_DATAENCIPHERMENT )
#define USAGE_KEYAGREEMENT_MASK ( CRYPT_KEYUSAGE_KEYAGREEMENT | \
CRYPT_KEYUSAGE_ENCIPHERONLY | \
CRYPT_KEYUSAGE_DECIPHERONLY )
/* Mask for key usage types that we don't check for consistency against
extended key usages. The two CA usages don't occur in extended key usage,
and no-one can agree on what non-repudiation is supposed to mean */
#define USAGE_MASK_NONRELEVANT ( CRYPT_KEYUSAGE_NONREPUDIATION | \
CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN )
/* Flags to denote the algorithm type */
#define ALGO_TYPE_NONE 0
#define ALGO_TYPE_SIGN 1
#define ALGO_TYPE_CRYPT 2
#define ALGO_TYPE_KEYAGREEMENT 4
#define ALGO_TYPE_FLAG_NONE 0 /* Defines for range checking */
#define ALGO_TYPE_FLAG_MAX 0x07
/* Table mapping extended key usage values to key usage flags */
typedef struct {
const CRYPT_ATTRIBUTE_TYPE usageType;
const int keyUsageFlags;
} EXT_USAGE_INFO;
static const EXT_USAGE_INFO FAR_BSS extendedUsageInfo[] = {
{ CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,/* individualCodeSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,/* commercialCodeSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,/* certTrustListSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING, /* timeStampSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO, /* serverGatedCrypto */
CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM, /* encrypedFileSystem */
CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_CERTINFO_EXTKEY_SERVERAUTH, /* serverAuth */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_CLIENTAUTH, /* clientAuth */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_CODESIGNING, /* codeSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION, /* emailProtection */
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_NONREPUDIATION },
{ CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM, /* ipsecEndSystem */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL, /* ipsecTunnel */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_IPSECUSER, /* ipsecUser */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_TIMESTAMPING, /* timeStamping */
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_NONREPUDIATION },
{ CRYPT_CERTINFO_EXTKEY_OCSPSIGNING, /* ocspSigning */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE, /* directoryService */
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO, /* serverGatedCrypto */
CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_ATTRIBUTE_NONE, 0 }
};
/* Table mapping Netscape certificate-type flags to extended key usage
flags */
typedef struct {
const int certType;
const int keyUsageFlags;
} CERT_TYPE_INFO;
static const CERT_TYPE_INFO FAR_BSS certTypeInfo[] = {
{ CRYPT_NS_CERTTYPE_SSLCLIENT,
CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_NS_CERTTYPE_SSLSERVER,
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_NS_CERTTYPE_SMIME,
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_NS_CERTTYPE_OBJECTSIGNING,
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_NONREPUDIATION },
{ CRYPT_NS_CERTTYPE_RESERVED, 0 },
{ CRYPT_NS_CERTTYPE_SSLCA,
CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },
{ CRYPT_NS_CERTTYPE_SMIMECA,
CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },
{ CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA,
CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },
{ 0, 0 }
};
/* Build up key usage flags consistent with the extended key usage purpose.
We don't have to perform any special-case handling for
anyExtendedKeyUsage (added in RFC 3280, section 4.2.1.13) since it's a
no-op extension whose presence is the equivalent of adding "|| TRUE" to
an expression */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int getExtendedKeyUsageFlags( const ATTRIBUTE_LIST *attributes,
IN_FLAGS( ALGO_TYPE ) const int algorithmType,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus )
{
int keyUsage = 0, i;
assert( isReadPtr( attributes, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
REQUIRES( algorithmType > ALGO_TYPE_FLAG_NONE && \
algorithmType < ALGO_TYPE_FLAG_MAX );
/* Most certificates don't contain an extendedKeyUsage extension so
rather than iterating through a long list of non-present attribute
fields we perform an early-out check to see whether there's actually
anything to do */
if( !checkAttributePresent( attributes, CRYPT_CERTINFO_EXTKEYUSAGE ) )
return( 0 );
/* There's an extendedKeyUsage extension present, build up the key usage
flags for it */
for( i = 0; extendedUsageInfo[ i ].usageType != CRYPT_ATTRIBUTE_NONE && \
i < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO );
i++ )
{
const ATTRIBUTE_LIST *attributeListPtr = \
findAttributeField( attributes, extendedUsageInfo[ i ].usageType,
CRYPT_ATTRIBUTE_NONE );
int extendedUsage = 0;
/* If this usage isn't present, continue */
if( attributeListPtr == NULL )
continue;
/* If the usage is consistent with the algorithm type, add it */
if( algorithmType & ALGO_TYPE_SIGN )
extendedUsage |= extendedUsageInfo[ i ].keyUsageFlags & USAGE_SIGN_MASK;
if( algorithmType & ALGO_TYPE_CRYPT )
extendedUsage |= extendedUsageInfo[ i ].keyUsageFlags & USAGE_CRYPT_MASK;
if( algorithmType & ALGO_TYPE_KEYAGREEMENT )
extendedUsage |= extendedUsageInfo[ i ].keyUsageFlags & USAGE_KEYAGREEMENT_MASK;
/* If there's no key usage consistent with the extended usage and the
extended usage isn't some special-case usage, return an error */
if( extendedUsage == 0 && extendedUsageInfo[ i ].keyUsageFlags != 0 )
{
*errorLocus = extendedUsageInfo[ i ].usageType;
return( CRYPT_ERROR_INVALID );
}
keyUsage |= extendedUsage;
}
ENSURES( i < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO ) );
return( keyUsage );
}
/* Build up key usage flags consistent with the Netscape certificate-type
purpose */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int getNetscapeCertTypeFlags( const ATTRIBUTE_LIST *attributes,
IN_FLAGS( ALGO_TYPE ) const int algorithmType,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus )
{
const ATTRIBUTE_LIST *attributeListPtr = \
findAttributeField( attributes, CRYPT_CERTINFO_NS_CERTTYPE,
CRYPT_ATTRIBUTE_NONE );
int nsCertType, keyUsage = 0, i;
assert( isReadPtr( attributes, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
REQUIRES( algorithmType > ALGO_TYPE_FLAG_NONE && \
algorithmType < ALGO_TYPE_FLAG_MAX );
/* If there isn't a Netscape certificate-type extension present, exit */
if( attributeListPtr == NULL )
return( 0 );
nsCertType = ( int ) attributeListPtr->intValue;
/* The Netscape certificate-type value is a bitfield containing the
different certificate types. For each certificate-type flag that's
set we set the corresponding keyUsage flags */
for( i = 0; certTypeInfo[ i ].certType && \
i < FAILSAFE_ARRAYSIZE( certTypeInfo, CERT_TYPE_INFO ); i++ )
{
int nsUsage = 0;
/* If this isn't the currently-selected certificate-type, continue */
if( !( nsCertType & certTypeInfo[ i ].certType ) )
continue;
/* If the usage is consistent with the algorithm type, add it */
if( algorithmType & ALGO_TYPE_SIGN )
nsUsage |= certTypeInfo[ i ].keyUsageFlags & USAGE_SIGN_MASK;
if( algorithmType & ALGO_TYPE_CRYPT )
nsUsage |= certTypeInfo[ i ].keyUsageFlags & USAGE_CRYPT_MASK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -