📄 dn.c
字号:
/****************************************************************************
* *
* Certificate DN Routines *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "cert.h"
#include "asn1.h"
#else
#include "cert/cert.h"
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
/* DN component info flags. Some implementations may place more than one
AVA into a RDN, in which case we set a flag to indicate that the RDN
continues in the next DN component structure. If the RDN/DN was set by
specifying the entire DN at once using a free-format text DN string, it's
not a good idea to allow random changes to it so we mark the components
as locked. If we're reading data from an external source the DN can
contain all sorts of strange stuff so we set a flag to tell the DN
component-handling code not to perform any validity checking on the
components as they're added */
#define DN_FLAG_NONE 0x00 /* No DN flag */
#define DN_FLAG_CONTINUED 0x01 /* RDN continues with another AVA */
#define DN_FLAG_LOCKED 0x02 /* RDN can't be modified */
#define DN_FLAG_PREENCODED 0x04 /* RDN has had pre-encoding done */
#define DN_FLAG_NOCHECK 0x08 /* Don't check validity of components */
#define DN_FLAG_MAX 0x0F /* Maximum possible flag value */
/* The structure to hold a DN component */
typedef struct DC {
/* DN component type and type information */
int type; /* cryptlib component type, either a
CRYPT_ATTRIBUTE_TYPE or an integer ID */
const void *typeInfo; /* Type info for this component */
int flags;
/* DN component data */
BUFFER_FIXED( valueLength ) \
void *value; /* DN component value */
int valueLength; /* DN component value length */
int valueStringType; /* DN component native string type */
/* Encoding information: The native string type (used for conversion to
ASN.1 string type when encoding), the encoded string type, the
overall size of the RDN data (without the tag and length) if this is
the first or only component of an RDN, and the size of the AVA data */
int encodingStringType, encodedStringType;
int encodedRDNdataSize, encodedAVAdataSize;
/* The next and previous list element in the linked list of DN
components */
struct DC *next, *prev;
/* Variable-length storage for the DN data */
DECLARE_VARSTRUCT_VARS;
} DN_COMPONENT;
/****************************************************************************
* *
* DN Information Tables *
* *
****************************************************************************/
/* A macro to make make declaring DN OIDs simpler */
#define MKDNOID( value ) MKOID( "\x06\x03" value )
/* Type information for DN components. If the OID doesn't correspond to a
valid cryptlib component (i.e. it's one of the 1,001 other odd things that
can be crammed into a DN) we can't directly identify it with a type but
instead return a simple integer value in the info table. This works
because the certificate component values don't start until x000 */
typedef struct {
const CRYPT_ATTRIBUTE_TYPE type;/* cryptlib type */
const BYTE *oid; /* OID for this type */
const char *name, *altName; /* Name for this type */
const int maxLength; /* Maximum allowed length for this type */
const BOOLEAN ia5OK; /* Whether IA5 is allowed for this comp.*/
const BOOLEAN wcsOK; /* Whether widechar is allowed for comp.*/
} DN_COMPONENT_INFO;
static const DN_COMPONENT_INFO FAR_BSS certInfoOIDs[] = {
/* Useful components */
{ CRYPT_CERTINFO_COMMONNAME, MKDNOID( "\x55\x04\x03" ),
"cn", "oid.2.5.4.3", CRYPT_MAX_TEXTSIZE, FALSE, TRUE },
{ CRYPT_CERTINFO_COUNTRYNAME, MKDNOID( "\x55\x04\x06" ),
"c", "oid.2.5.4.6", 2, FALSE, FALSE },
{ CRYPT_CERTINFO_LOCALITYNAME, MKDNOID( "\x55\x04\x07" ),
"l", "oid.2.5.4.7", 128, FALSE, TRUE },
{ CRYPT_CERTINFO_STATEORPROVINCENAME, MKDNOID( "\x55\x04\x08" ),
"sp", "oid.2.5.4.8", 128, FALSE, TRUE },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, MKDNOID( "\x55\x04\x0A" ),
"o", "oid.2.5.4.10", CRYPT_MAX_TEXTSIZE, FALSE, TRUE },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, MKDNOID( "\x55\x04\x0B" ),
"ou", "oid.2.5.4.11", CRYPT_MAX_TEXTSIZE, FALSE, TRUE },
/* Non-useful components */
{ 1, MKDNOID( "\x55\x04\x01" ), /* aliasObjectName (2 5 4 1) */
"oid.2.5.4.1", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 2, MKDNOID( "\x55\x04\x02" ), /* knowledgeInformation (2 5 4 2) */
"oid.2.5.4.2", NULL, MAX_ATTRIBUTE_SIZE /*32768*/, FALSE, FALSE },
{ 3, MKDNOID( "\x55\x04\x04" ), /* surname (2 5 4 4) */
"s", "oid.2.5.4.4", CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 4, MKDNOID( "\x55\x04\x05" ), /* serialNumber (2 5 4 5) */
"sn", "oid.2.5.4.5", CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 5, MKDNOID( "\x55\x04\x09" ), /* streetAddress (2 5 4 9) */
"st", "oid.2.5.4.9", 128, FALSE, FALSE },
{ 6, MKDNOID( "\x55\x04\x0C" ), /* title (2 5 4 12) */
"t", "oid.2.5.4.12", CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 7, MKDNOID( "\x55\x04\x0D" ), /* description (2 5 4 13) */
"d", "oid.2.5.4.13", 1024, FALSE, FALSE },
{ 8, MKDNOID( "\x55\x04\x0E" ), /* searchGuide (2 5 4 14) */
"oid.2.5.4.14", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 9, MKDNOID( "\x55\x04\x0F" ), /* businessCategory (2 5 4 15) */
"bc", "oid.2.5.4.15", 128, FALSE, FALSE },
{ 10, MKDNOID( "\x55\x04\x10" ), /* postalAddress (2 5 4 16) */
"oid.2.5.4.16", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 11, MKDNOID( "\x55\x04\x11" ), /* postalCode (2 5 4 17) */
"oid.2.5.4.17", NULL, 40, FALSE, FALSE },
{ 12, MKDNOID( "\x55\x04\x12" ), /* postOfficeBox (2 5 4 18) */
"oid.2.5.4.18", NULL, 40, FALSE, FALSE },
{ 13, MKDNOID( "\x55\x04\x13" ), /* physicalDeliveryOfficeName (2 5 4 19) */
"oid.2.5.4.19", NULL, 128, FALSE, FALSE },
{ 14, MKDNOID( "\x55\x04\x14" ), /* telephoneNumber (2 5 4 20) */
"oid.2.5.4.20", NULL, 32, FALSE, FALSE },
{ 15, MKDNOID( "\x55\x04\x15" ), /* telexNumber (2 5 4 21) */
"oid.2.5.4.21", NULL, 14, FALSE, FALSE },
{ 16, MKDNOID( "\x55\x04\x16" ), /* teletexTerminalIdentifier (2 5 4 22) */
"oid.2.5.4.22", NULL, 24, FALSE, FALSE },
{ 17, MKDNOID( "\x55\x04\x17" ), /* facsimileTelephoneNumber (2 5 4 23) */
"oid.2.5.4.23", NULL, 32, FALSE, FALSE },
{ 18, MKDNOID( "\x55\x04\x18" ), /* x121Address (2 5 4 24) */
"oid.2.5.4.24", NULL, 15, FALSE, FALSE },
{ 19, MKDNOID( "\x55\x04\x19" ), /* internationalISDNNumber (2 5 4 25) */
"isdn", "oid.2.5.4.25", 16, FALSE, FALSE },
{ 20, MKDNOID( "\x55\x04\x1A" ), /* registeredAddress (2 5 4 26) */
"oid.2.5.4.26", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 21, MKDNOID( "\x55\x04\x1B" ), /* destinationIndicator (2 5 4 27) */
"oid.2.5.4.27", NULL, 128, FALSE, FALSE },
{ 22, MKDNOID( "\x55\x04\x1C" ), /* preferredDeliveryMethod (2 5 4 28) */
"oid.2.5.4.28", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 23, MKDNOID( "\x55\x04\x1D" ), /* presentationAddress (2 5 4 29) */
"oid.2.5.4.29", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 24, MKDNOID( "\x55\x04\x1E" ), /* supportedApplicationContext (2 5 4 30) */
"oid.2.5.4.30", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 25, MKDNOID( "\x55\x04\x1F" ), /* member (2 5 4 31) */
"oid.2.5.4.31", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 26, MKDNOID( "\x55\x04\x20" ), /* owner (2 5 4 32) */
"oid.2.5.4.32", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 27, MKDNOID( "\x55\x04\x21" ), /* roleOccupant (2 5 4 33) */
"oid.2.5.4.33", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 28, MKDNOID( "\x55\x04\x22" ), /* seeAlso (2 5 4 34) */
"oid.2.5.4.34", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
/* 0x23-0x28 are certificates/CRLs and some weird encrypted directory components */
{ 29, MKDNOID( "\x55\x04\x29" ), /* name (2 5 4 41) */
"oid.2.5.4.41", NULL, MAX_ATTRIBUTE_SIZE /*32768*/, FALSE, FALSE },
{ 30, MKDNOID( "\x55\x04\x2A" ), /* givenName (2 5 4 42) */
"g", "oid.2.5.4.42", CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 31, MKDNOID( "\x55\x04\x2B" ), /* initials (2 5 4 43) */
"i", "oid.2.5.4.43", CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 32, MKDNOID( "\x55\x04\x2C" ), /* generationQualifier (2 5 4 44) */
"oid.2.5.4.44", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 33, MKDNOID( "\x55\x04\x2D" ), /* uniqueIdentifier (2 5 4 45) */
"oid.2.5.4.45", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 34, MKDNOID( "\x55\x04\x2E" ), /* dnQualifier (2 5 4 46) */
"oid.2.5.4.46", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
/* 0x2F-0x30 are directory components */
{ 35, MKDNOID( "\x55\x04\x31" ), /* distinguishedName (2 5 4 49) */
"oid.2.5.4.49", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 36, MKDNOID( "\x55\x04\x32" ), /* uniqueMember (2 5 4 50) */
"oid.2.5.4.50", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 37, MKDNOID( "\x55\x04\x33" ), /* houseIdentifier (2 5 4 51) */
"oid.2.5.4.51", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
/* 0x34-0x3A are more certificates and weird encrypted directory components */
{ 38, MKDNOID( "\x55\x04\x41" ), /* pseudonym (2 5 4 65) */
"oid.2.5.4.65", NULL, 128, FALSE, FALSE },
{ 39, MKDNOID( "\x55\x04\x42" ), /* communicationsService (2 5 4 66) */
"oid.2.5.4.66", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
{ 40, MKDNOID( "\x55\x04\x43" ), /* communicationsNetwork (2 5 4 67) */
"oid.2.5.4.67", NULL, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },
/* 0x44-0x49 are more PKI-related attributes */
{ 41, MKOID( "\x06\x0A\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" ), /* userid (0 9 2342 19200300 100 1 1) */
"uid", NULL, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },
{ 42, MKOID( "\x06\x0A\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x03" ), /* rfc822Mailbox (0 9 2342 19200300 100 1 3) */
"oid.0.9.2342.19200300.100.1.3", NULL, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },
{ 43, MKOID( "\x06\x0A\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" ), /* domainComponent (0 9 2342 19200300 100 1 25) */
"dc", "oid.0.9.2342.19200300.100.1.25", CRYPT_MAX_TEXTSIZE, TRUE, FALSE },
{ 44, MKOID( "\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" ), /* emailAddress (1 2 840 113549 1 9 1) */
"email", "oid.1.2.840.113549.1.9.1", CRYPT_MAX_TEXTSIZE, TRUE, FALSE },
{ 45, MKOID( "\x06\x07\x02\x82\x06\x01\x0A\x07\x14" ), /* nameDistinguisher (0 2 262 1 10 7 20) */
"oid.0.2.262.1.10.7.20", NULL, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },
{ CRYPT_ATTRIBUTE_NONE, NULL }, { CRYPT_ATTRIBUTE_NONE, NULL }
};
/* Check that a country code is valid */
#define xA ( 1 << 0 )
#define xB ( 1 << 1 )
#define xC ( 1 << 2 )
#define xD ( 1 << 3 )
#define xE ( 1 << 4 )
#define xF ( 1 << 5 )
#define xG ( 1 << 6 )
#define xH ( 1 << 7 )
#define xI ( 1 << 8 )
#define xJ ( 1 << 9 )
#define xK ( 1 << 10 )
#define xL ( 1 << 11 )
#define xM ( 1 << 12 )
#define xN ( 1 << 13 )
#define xO ( 1 << 14 )
#define xP ( 1 << 15 )
#define xQ ( 1 << 16 )
#define xR ( 1 << 17 )
#define xS ( 1 << 18 )
#define xT ( 1 << 19 )
#define xU ( 1 << 20 )
#define xV ( 1 << 21 )
#define xW ( 1 << 22 )
#define xX ( 1 << 23 )
#define xY ( 1 << 24 )
#define xZ ( 1 << 25 )
CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
static BOOLEAN checkCountryCode( IN_BUFFER( 2 ) const char *countryCode )
{
static const long countryCodes[] = { /* ISO 3166 code table */
/* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */
/*A*/ xD|xE|xF|xG| xI| xL|xM|xN|xO| xQ|xR|xS|xT|xU| xW| xZ,
/*B*/ xA|xB| xD|xE|xF|xG|xH|xI|xJ| xM|xN|xO| xR|xS|xT| xV|xW| xY|xZ,
/*C*/ xA| xC|xD| xF|xG|xH|xI| xK|xL|xM|xN|xO| xR| xU|xV| xX|xY|xZ,
/*D*/ xE| xJ|xK| xM| xO| xZ,
/*E*/ xC| xE| xG|xH| xR|xS|xT,
/*F*/ xI|xJ|xK| xM| xO| xR,
/*G*/ xA|xB| xD|xE|xF| xH|xI| xL|xM|xN| xP|xQ|xR|xS|xT|xU| xW| xY,
/*H*/ xK| xM|xN| xR| xT|xU,
/*I*/ xD|xE| xL| xN|xO| xQ|xR|xS|xT,
/*J*/ xM| xO|xP,
/*K*/ xE| xG|xH|xI| xM|xN| xP| xR| xW| xY|xZ,
/*L*/ xA|xB|xC| xI| xK| xR|xS|xT|xU|xV| xY,
/*M*/ xA| xC|xD| xG|xH| xK|xL|xM|xN|xO|xP|xQ|xR|xS|xT|xU|xV|xW|xX|xY|xZ,
/*N*/ xA| xC| xE|xF|xG| xI| xL| xO|xP| xR| xU| xZ,
/*O*/ xM,
/*P*/ xA| xE|xF|xG|xH| xK|xL|xM|xN| xR|xS|xT| xW| xY,
/*Q*/ xA,
/*R*/ xE| xO| xU| xW,
/*S*/ xA|xB|xC|xD|xE| xG|xH|xI|xJ|xK|xL|xM|xN|xO| xR| xT| xV| xY|xZ,
/*T*/ xC|xD| xF|xG|xH| xJ|xK|xL|xM|xN|xO| xR| xT| xV|xW| xZ,
/*U*/ xA| xG| xM| xS| xY|xZ,
/*V*/ xA| xC| xE| xG| xI| xN| xU,
/*W*/ xF| xS,
/*X*/ 0,
/*Y*/ xE| xT|xU,
/*Z*/ xA| xM| xW,
0, 0 /* Catch overflows */
};
const int cc0 = countryCode[ 0 ] - 'A';
const int cc1 = countryCode[ 1 ] - 'A';
assert( isReadPtr( countryCode, 2 ) );
/* Check that the country code is present in the table of valid ISO 3166
codes. Note the explicit declaration of the one-bit as '1L', this is
required because the shift amount can be greater than the word size on
16-bit systems */
if( cc0 < 0 || cc0 > 25 || cc1 < 0 || cc1 > 25 )
return( FALSE );
return( ( countryCodes[ cc0 ] & ( 1L << cc1 ) ) ? TRUE : FALSE );
}
/* Determine the sort priority for DN components */
CHECK_RETVAL_RANGE( MAX_ERROR, 10 ) \
static int dnSortOrder( const CRYPT_ATTRIBUTE_TYPE type )
{
typedef struct {
const CRYPT_ATTRIBUTE_TYPE type;
const int sortOrder;
} DN_SORT_ORDER;
static const DN_SORT_ORDER dnSortOrderTbl[] = {
{ CRYPT_CERTINFO_COUNTRYNAME, 0 },
{ CRYPT_CERTINFO_STATEORPROVINCENAME, 1 },
{ CRYPT_CERTINFO_LOCALITYNAME, 2 },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, 3 },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, 4 },
{ CRYPT_CERTINFO_COMMONNAME, 5 },
{ CRYPT_ATTRIBUTE_NONE, 0 }, { CRYPT_ATTRIBUTE_NONE, 0 }
};
int i;
REQUIRES( type >= CRYPT_CERTINFO_FIRST_DN && \
type <= CRYPT_CERTINFO_LAST_DN );
for( i = 0; dnSortOrderTbl[ i ].type != type && \
dnSortOrderTbl[ i ].type != CRYPT_ATTRIBUTE_NONE && \
i < FAILSAFE_ARRAYSIZE( dnSortOrderTbl, DN_SORT_ORDER );
i++ );
ENSURES( i < FAILSAFE_ARRAYSIZE( dnSortOrderTbl, DN_SORT_ORDER ) );
ENSURES( dnSortOrderTbl[ i ].type != CRYPT_ATTRIBUTE_NONE );
return( i );
}
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Find a DN component in a DN component list by type and by OID */
CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
static DN_COMPONENT *findDNComponent( const DN_COMPONENT *dnComponentList,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,
IN_BUFFER_OPT( valueLength ) const void *value,
IN_LENGTH_SHORT_Z const int valueLength )
{
const DN_COMPONENT *listPtr;
int iterationCount;
assert( isReadPtr( dnComponentList, sizeof( DN_COMPONENT ) ) );
assert( ( value == NULL && valueLength == 0 ) || \
isReadPtr( value, valueLength ) );
/* We may be doing the lookup purely by type */
REQUIRES_N( type >= CRYPT_CERTINFO_FIRST_DN && \
type <= CRYPT_CERTINFO_LAST_DN );
REQUIRES_N( ( value == NULL && valueLength == 0 ) || \
( value != NULL && \
valueLength > 0 && valueLength < MAX_INTLENGTH_SHORT ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -