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

📄 imp_exp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* If we've hit a [1] it's an attribute certificate, if we've hit a
	   GeneralizedTime it's an OCSP response, if we've hit a SET it's PKI
	   user info, and if we've hit a [0] or [1] primitive tag (implicitly 
	   tagged INTEGER) or [3]...[9] it's a CRMF revocation request */
	tag = peekTag( &stream );
	if( cryptStatusError( tag ) )
		return( tag );
	if( tag == MAKE_CTAG( 1 ) || tag == BER_TIME_GENERALIZED || \
		tag == BER_SET )
		{
		sMemDisconnect( &stream );
		*objectType = \
			( tag == MAKE_CTAG( 1 ) ) ? CRYPT_CERTTYPE_ATTRIBUTE_CERT : \
			( tag == BER_TIME_GENERALIZED ) ? \
				CRYPT_CERTTYPE_OCSP_RESPONSE : CRYPT_CERTTYPE_PKIUSER;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}
	if( tag == MAKE_CTAG_PRIMITIVE( 0 ) || \
		tag == MAKE_CTAG_PRIMITIVE( 1 ) || \
		( tag >= MAKE_CTAG( 3 ) && tag <= MAKE_CTAG( 9 ) ) )
		{
		sMemDisconnect( &stream );
		*objectType = CRYPT_CERTTYPE_REQUEST_REVOCATION;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* Read the next SEQUENCE.  If it's followed by an OID it's the 
	   AlgorithmIdentifier in a certificate or CRL.  If it's followed by a 
	   SET it's the Name in a certificate request or attribute certificate.  
	   If it's followed by a tag in the range [0]...[9] it's a horror from 
	   CRMF */
	status = readSequence( &stream, &length );
	if( cryptStatusOK( status ) && length <= 0 )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	tag = peekTag( &stream );
	if( cryptStatusError( tag ) )
		return( tag );
	if( tag == BER_OBJECT_IDENTIFIER )
		{
		/* Skip the AlgorithmIdentifier data and the following Name.  For a
		   certificate we now have a SEQUENCE (from the Validity), for a CRL 
		   a UTCTime or GeneralizedTime */
		sSkip( &stream, length );
		readUniversal( &stream );
		tag = readTag( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( tag ) )
			return( tag );
		if( tag == BER_SEQUENCE )
			{
			*objectType = CRYPT_CERTTYPE_CERTIFICATE;
			return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
			}
		if( tag == BER_TIME_UTC || tag == BER_TIME_GENERALIZED )
			{
			*objectType = CRYPT_CERTTYPE_CRL;
			return( CRYPT_OK );
			}
		return( CRYPT_ERROR_BADDATA );
		}
	if( isLongData )
		{
		/* Beyond this point we shouldn't be seeing long-length objects */
		return( CRYPT_ERROR_OVERFLOW );
		}
	if( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 9 ) )
		{
		/* Certificate requests and revocation requests have the same 
		   format, however revocation requests should have the certificate 
		   serial number present while certificate requests shouldn't (at 
		   least in any normal implementation) so we use this to 
		   distinguish the two.  If this ever fails in the future we can 
		   also look for things like [6] (the public key) as a clue that 
		   it's a certificate request */
		sMemDisconnect( &stream );
		*objectType = ( tag == MAKE_CTAG( 1 ) ) ? \
				CRYPT_CERTTYPE_REQUEST_REVOCATION : CRYPT_CERTTYPE_REQUEST_CERT;
		return( CRYPT_OK );
		}
	if( tag == BER_SET )
		{
		sSkip( &stream, length );
		readSequence( &stream, NULL );
		tag = readTag( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( tag ) )
			return( tag );
		if( tag == BER_OBJECT_IDENTIFIER )
			{
			*objectType = CRYPT_CERTTYPE_ATTRIBUTE_CERT;
			return( CRYPT_OK );
			}
		if( tag == BER_SEQUENCE )
			{
			*objectType = CRYPT_CERTTYPE_CERTREQUEST;
			return( CRYPT_OK );
			}
		return( CRYPT_ERROR_BADDATA );
		}

	/* Read the next SEQUENCE.  If it's followed by a yet another SEQUENCE 
	   or a tag from [0] ... [3] it's an OCSP request, if it's followed by
	   an OCTET STRING it's a cryptlib OCSP response */
	readSequence( &stream, NULL );
	tag = readTag( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( tag ) )
		return( tag );
	if( tag == BER_SEQUENCE || \
		( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 3 ) ) )
		{
		*objectType = CRYPT_CERTTYPE_OCSP_REQUEST;
		return( CRYPT_OK );
		}
	if( tag == BER_OCTETSTRING )
		{
		*objectType = CRYPT_CERTTYPE_OCSP_RESPONSE;
		return( CRYPT_OK );
		}

	/* It's nothing identifiable */
	return( CRYPT_ERROR_BADDATA );
	}

/* Decode a base64/PEM/SMIME-encoded certificate into a temporary buffer */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
static int decodeCertificate( IN_BUFFER( certObjectLength ) const void *certObject, 
							  IN_LENGTH const int certObjectLength,
							  OUT_PTR void **newObject, 
							  OUT_LENGTH_Z int *newObjectLength,
							  IN_ENUM( CRYPT_CERTFORMAT ) \
								const CRYPT_CERTFORMAT_TYPE format )
	{
	void *decodedObjectPtr;
	int decodedLength, status;

	assert( isReadPtr( certObject, certObjectLength ) );
	assert( isWritePtr( newObject, sizeof( void * ) ) );
	assert( isWritePtr( newObjectLength, sizeof( int ) ) );

	REQUIRES( certObjectLength > 0 && certObjectLength < MAX_INTLENGTH );
	REQUIRES( format > CRYPT_CERTFORMAT_NONE && \
			  format < CRYPT_CERTFORMAT_LAST );

	/* Clear return values */
	*newObject = NULL;
	*newObjectLength = 0;

	/* Decode the base64/PEM/SMIME-encoded certificate into a temporary 
	   buffer */
	status = base64decodeLen( certObject, certObjectLength, 
							  &decodedLength );
	if( cryptStatusError( status ) )
		return( status );
	if( decodedLength < 64 || decodedLength >= MAX_INTLENGTH_SHORT )
		return( CRYPT_ERROR_UNDERFLOW );
	if( ( decodedObjectPtr = clAlloc( "checkTextEncoding", \
									  decodedLength + 8 ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	status = base64decode( decodedObjectPtr, decodedLength, &decodedLength,
						   certObject, certObjectLength, format );
	if( cryptStatusOK( status ) && \
		( decodedLength < 64 || decodedLength >= MAX_INTLENGTH_SHORT ) )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		clFree( "checkTextEncoding", decodedObjectPtr );
		return( status );
		}
	*newObject = decodedObjectPtr;
	*newObjectLength = decodedLength;

	return( CRYPT_OK );
	}

/* Detect the encoded form of certificate data, either raw binary, raw
   binary with a MIME header, or some form of text encoding.  Autodetection 
   in the presence of EBCDIC gets a bit more complicated because the text
   content can potentially be either EBCDIC or ASCII so we have to add an
   extra layer of checking for EBCDIC */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
static int checkTextEncoding( IN_BUFFER( certObjectLength ) const void *certObject, 
							  IN_LENGTH const int certObjectLength,
							  OUT_PTR void **newObject, 
							  OUT_LENGTH int *newObjectLength )
	{
	CRYPT_CERTFORMAT_TYPE format;
#ifdef EBCDIC_CHARS
	void *asciiObject = NULL;
#endif /* EBCDIC_CHARS */
	int offset, status;

	assert( isReadPtr( certObject, certObjectLength ) );
	assert( isWritePtr( newObject, sizeof( void * ) ) );
	assert( isWritePtr( newObjectLength, sizeof( int ) ) );

	REQUIRES( certObjectLength > 0 && certObjectLength < MAX_INTLENGTH );

	/* Initialise the return values to the default settings, the identity
	   transformation */
	*newObject = ( void * ) certObject;
	*newObjectLength = certObjectLength;

	/* Check for a header that identifies some form of encoded object */
	status = base64checkHeader( certObject, certObjectLength, &format, &offset );
#ifdef EBCDIC_CHARS
	if( cryptStatusError( status ) )
		{
		int status;

		/* If we get a decoding error (i.e. it's not either an unencoded 
		   object or some form of ASCII encoded object) try again assuming
		   that the source is EBCDIC */
		if( ( asciiObject = clAlloc( "checkTextEncoding",
									 certObjectLength + 8 ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		status = ebcdicToAscii( asciiObject, certObject, certObjectLength );
		if( cryptStatusError( status ) )
			return( status );
		certObject = asciiObject;
		status = base64checkHeader( certObject, certObjectLength, &format, 
									&offset );
		if( cryptStatusOK( status ) && \
			( format != CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && \
			  format != CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) )
			{
			clFree( "checkTextEncoding", asciiObject );
			asciiObject = NULL;
			}
		}
#endif /* EBCDIC_CHARS */
	if( cryptStatusError( status ) )
		return( status );

	/* Make sure that the length after (potentially) skipping the header is 
	   still valid, since this will now be different from the length that 
	   was validated by the kernel */
	if( certObjectLength - offset < 64 || \
		certObjectLength - offset > MAX_INTLENGTH )
		{
#ifdef EBCDIC_CHARS
		if( asciiObject != NULL )
			clFree( "checkTextEncoding", asciiObject );
#endif /* EBCDIC_CHARS */
		return( CRYPT_ERROR_UNDERFLOW );
		}

	if( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE || \
		format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE )
		{
		status = decodeCertificate( ( const char * ) certObject + offset, 
									certObjectLength - offset, newObject,
									newObjectLength, format );
#ifdef EBCDIC_CHARS
		if( asciiObject != NULL )
			clFree( "checkTextEncoding", asciiObject );
#endif /* EBCDIC_CHARS */
		if( cryptStatusError( status ) )
			return( status );

		/* Let the caller know that they have to free the temporary decoding
		   buffer before they exit */
		return( OK_SPECIAL );
		}

	/* If it's binary-encoded MIME data we don't need to decode it but still 
	   need to skip the MIME header */
	if( format == CRYPT_CERTFORMAT_CERTIFICATE || \
		format == CRYPT_CERTFORMAT_CERTCHAIN )
		{
		assert( offset > 0 );

		*newObject = ( BYTE * ) certObject + offset;
		*newObjectLength -= offset;
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Import/Export Functions						*
*																			*
****************************************************************************/

/* Import a certificate object.  If the import type is set to create a data-
   only certificate, its publicKeyInfo pointer is set to the start of the 
   encoded public key to allow it to be decoded later.  Returns the length 
   of the certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int importCert( IN_BUFFER( certObjectLength ) const void *certObject, 
				IN_LENGTH const int certObjectLength,
				OUT_HANDLE_OPT CRYPT_CERTIFICATE *certificate,
				IN_HANDLE const CRYPT_USER iCryptOwner,
				IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
				IN_BUFFER_OPT( keyIDlength ) const void *keyID, 
				IN_LENGTH_KEYID_Z const int keyIDlength,
				IN_ENUM_OPT( CRYPT_CERTTYPE ) \
					const CRYPT_CERTTYPE_TYPE formatHint )
	{
	CERT_INFO *certInfoPtr;
	CRYPT_CERTTYPE_TYPE type;
	STREAM stream;
	READCERT_FUNCTION readCertFunction;
	BOOLEAN isDecodedObject = FALSE;
	void *certObjectPtr = ( void * ) certObject, *certBuffer;
	int objectLength = certObjectLength, length, offset = 0;
	int complianceLevel, initStatus = CRYPT_OK, status;

	assert( isReadPtr( certObject, certObjectLength ) );
	assert( isWritePtr( certificate, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( ( keyIDtype == CRYPT_KEYID_NONE && \
			  keyID == NULL && keyIDlength == 0 ) || \
			( keyIDtype != CRYPT_KEYID_NONE && \
			  isReadPtr( keyID, keyIDlength ) ) );

	REQUIRES( certObjectLength > 0 && certObjectLength < MAX_INTLENGTH );
	REQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
			  isHandleRangeValid( iCryptOwner ) );
	REQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \
				keyID == NULL && keyIDlength == 0 ) || \
			  ( ( keyIDtype > CRYPT_KEYID_NONE && \
				  keyIDtype < CRYPT_KEYID_LAST ) && \
				keyID != NULL && \
				keyIDlength >= MIN_NAME_LENGTH && \
				keyIDlength < MAX_ATTRIBUTE_SIZE ) );
	REQUIRES( formatHint >= CRYPT_CERTTYPE_NONE && \
			  formatHint < CRYPT_CERTTYPE_LAST );

	/* Clear return value */
	*certificate = CRYPT_ERROR;

	/* Determine how much checking we need to perform */
	status = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE, 

⌨️ 快捷键说明

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