⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imp_exp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*						Certificate Import/Export Routines					*
*						Copyright Peter Gutmann 1997-2007					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "cert.h"
  #include "asn1.h"
  #include "asn1_ext.h"
#else
  #include "cert/cert.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */

/* Oddball OIDs that may be used to wrap certificates */

#define OID_X509_USERCERTIFICATE	"\x06\x03\x55\x04\x24"

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Determine the object type and how long the total object is.  If fed an 
   unknown object from the external source we can (with some difficulty) 
   determine its type at runtime (although it's hardly LL(1)) and import it 
   as appropriate.  If fed an object by a cryptlib-internal function, the
   exact type will always be known.
   
   If the data starts with a [0] it's CMS attributes.  If it starts with a 
   sequence followed by an OID it's a certificate chain/sequence or (rarely) 
   a certificate wrapped up in some weird packaging.  If it starts with a 
   sequence followed by an integer (version = 3), it's a PKCS #12 mess.  
   Otherwise, it follows the general pattern SEQUENCE { tbsSomething, 
   signature }, it's at this point that distinguishing the different types 
   gets tricky.

	Cert:			SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
							INTEGER,
							AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:	SEQUENCE { SEQUENCE {
							INTEGER OPTIONAL,
						[1]	Name,
							Name,
							AlgorithmID,
							INTEGER

	CRL:			SEQUENCE { SEQUENCE {
							INTEGER OPTIONAL,
							AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:	SEQUENCE { SEQUENCE {
							INTEGER,
							Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:	SEQUENCE { SEQUENCE {
							INTEGER,
							SEQUENCE {
								{ [0] ... [9] }	-- cert request should have 
												-- [6] SubjectPublicKeyInfo

	CRMF rev.req:	SEQUENCE { SEQUENCE {
							{ [0] ... [9] }		-- Should have [1] INTEGER 
												-- (serialNo),

	OCSP request:	SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
						[1]	EXPLICIT ... OPTIONAL,
							SEQUENCE { SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:		SEQUENCE { SEQUENCE {
						[0] EXPLICIT ... OPTIONAL,
							{ [1] | [2] } ...,
							GeneralizedTime

	OCSP resp (cl):	SEQUENCE { SEQUENCE 
							{ SEQUENCE { SEQUENCE {
								OCTET STRING

	PKI user:		SEQUENCE { SEQUENCE {		-- Name
							{ SET ... | empty }	-- RDN or zero-length DN

   The first step is to strip out the SEQUENCE { SEQUENCE, which is shared 
   by all objects.  In addition we can remove the [0] ... OPTIONAL and
   [1] ... OPTIONAL, which isn't useful in distinguishing anything.  Since 
   the standard OCSP response can also have [2] in place of the [1] and 
   leaving it in isn't notably useful we strip this as well.  Note that 
   attribute certificates can be left in one of two states depending on 
   whether the initial INTEGER is present or not and PKI user info is also 
   left in one of two states depending on whether there's a DN present.  
   Rather than parse down into the rest of the PKI user object (the next 
   element is an AlgorithmID that clashes with a certificate and CRL) we use 
   the presence of a zero-length sequence to identify a PKI user object with 
   an absent DN.  This leaves the following,

	Cert:					INTEGER,
							AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:			INTEGER OPTIONAL,
						[1]	Name,
							Name,					Name,
							AlgorithmID,			AlgorithmID,
							INTEGER					INTEGER

	CRL:					INTEGER OPTIONAL,
							AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:			INTEGER,
							Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			INTEGER,
							SEQUENCE {
								{ [0] ... [1] |	-- Implicitly tagged
								  [3] ... [9] }	-- [2] stripped

	CRMF rev.req:			{ [0] ... [1] |		-- Implicitly tagged
							  [3] ... [9] }		-- [2] stripped

	OCSP request:			SEQUENCE { SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:				GeneralizedTime

	OCSP resp (clib):		SEQUENCE { SEQUENCE {
								OCTET STRING

	PKI user:				SET ...				-- RDN

   Next we have the INTEGER, which also isn't notably useful.  Stripping this
   leaves:

	Cert:					AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	Attribute cert:		[1]	Name,
							Name,					Name,
							AlgorithmID,			AlgorithmID,
							INTEGER					INTEGER

	CRL:					AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Cert request:			Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [0] | [1] |	-- Primitive tag
								  [3] ... [9] }	-- [2] stripped

	CRMF rev.req:			{ [0] | [1] |		-- Primitive tag
							  [3] ... [9] }		-- [2] stripped

	OCSP request:			SEQUENCE { SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }
	
	OCSP resp:				GeneralizedTime

	OCSP resp (clib):		SEQUENCE { SEQUENCE {
								OCTET STRING

	PKI user:				SET ...				-- RDN

   We can now immediately identify the first attribute certificate variant 
   by the [1] ..., a CRMF revocation request by the not-stripped [0] or [1] 
   primitive tags (implicitly tagged INTEGER) or [3]...[9] ..., a standard 
   OCSP response by the GeneralizedTime, and the alternative PKI user 
   variant by the SET ..., leaving:

	Cert:					AlgorithmID,
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:					AlgorithmID,
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:			Name,
							AlgorithmID,
							INTEGER

	Cert request:			Name,
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [3] ... [9] }

	OCSP request:			SEQUENCE { SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }

	OCSP resp (clib):		SEQUENCE { SEQUENCE {
								OCTET STRING

   Expanding the complex types for certificate, attribute certificate, CRL, 
   and certificate request, we get:

	Cert:					SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:					SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:			SEQUENCE {			-- Name
								SET {
									...
								...
							SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							INTEGER

	Cert request:			SEQUENCE {			-- Name
								SET {
									...
								...
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:			SEQUENCE {
								{ [3] ... [9] }

	OCSP request:			SEQUENCE { SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }

	OCSP resp (clib):		SEQUENCE { SEQUENCE {
								OCTET STRING

   Stripping the first SEQUENCE { we get:

	Cert:						OBJECT IDENTIFIER,
								...
							Name,
							SEQUENCE {			-- Validity
								{ UTCTime | GeneralizedTime }

	CRL:						OBJECT IDENTIFIER,
								...
							Name,
							{ UTCTime | GeneralizedTime }

	Attribute cert:				SET {
									...
								...
							SEQUENCE {			-- AlgorithmID
								OBJECT IDENTIFIER,
								...
							INTEGER

	Cert request:				SET {
									...
								...
							SEQUENCE {			-- SubjectPublicKeyInfo
								AlgorithmID

	CRMF request:				{ [3] ... [9] }

	OCSP request:			SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }

	OCSP resp (clib):		SEQUENCE {
								OCTET STRING

   which allows us to distinguish certificates and CRLs (the two are 
   themselves distinguished by what follows the second Name) and certificate  
   requests and the second attribute certificate variant (the two are also 
   distinguished by what follows the Name).  What's left now are the tricky 
   ones, the other request and response types:

	CRMF request:				{ [3] ... [9] }

	OCSP request:			SEQUENCE {
								{ SEQUENCE | [0] | [1] | [2] | [3] }

	OCSP resp (clib):		SEQUENCE {
								OCTET STRING

   which can themselves be distinguished by the remaining data */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int decodeCertWrapper( INOUT STREAM *stream, 
							  OUT_LENGTH_SHORT_Z int *offset )
	{
	BYTE oid[ MAX_OID_SIZE + 8 ];
	BOOLEAN isCertChain = FALSE;
	int oidLength, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( offset, sizeof( int ) ) );

	/* Clear return value */
	*offset = 0;

	/* Read the contentType OID, determine the content type based on it,
	   and read the content encapsulation and header.  It can be either
	   a PKCS #7 certificate chain, a Netscape certificate sequence, or an 
	   X.509 userCertificate (which is just an oddball certificate 
	   wrapper) */
	status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, 
							 BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	if( !memcmp( oid, OID_CMS_SIGNEDDATA, oidLength ) )
		isCertChain = TRUE;
	else
		{
		if( !memcmp( oid, OID_X509_USERCERTIFICATE, oidLength ) )
			{
			/* Oddball wrapper type, set the payload offset to point to 
			   the certificate and indicate no wrapper present */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -