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

📄 cmp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		"The messageTime was not sufficiently close to the system time as "
			"defined by local policy",
		"No certificate could be found matching the provided criteria",
		"The data submitted has the wrong format",
		"The authority indicated in the request is different from the one "
			"creating the response token",
		"The requester's data is incorrect (used for notary services)",
		"Timestamp is missing but should be there (by policy)",
		"The proof-of-possession failed",
		"The certificate has already been revoked",
		"The certificate has already been confirmed",
		"Invalid integrity, password based instead of signature or vice "
			"versa",
		"Invalid recipient nonce, either missing or wrong value",
		"The TSA's time source is not available",
		"The requested TSA policy is not supported by the TSA",
		"The requested extension is not supported by the TSA",
		"The additional information requested could not be understood or is "
			"not available",
		"Invalid sender nonce, either missing or wrong size",
		"Invalid certificate template or missing mandatory information",
		"Signer of the message unknown or not trusted",
		"The transaction identifier is already in use",
		"The version of the message is not supported",
		"The sender was not authorized to make the preceding request or "
			"perform the preceding action",
		"The request cannot be handled due to system unavailability",
		"The request cannot be handled due to system failure",
		"Certificate cannot be issued because a duplicate certificate "
			"already exists",
		NULL
		};
	int bitIndex = 0, bitFlags = value;

	/* Find the first failure string corresponding to a bit set in the
	   failure info */
	if( !bitFlags )
		return( "Missing PKI failure code" );
	while( !( bitFlags & 1 ) )
		{
		bitIndex++;
		bitFlags >>= 1;
		}
	if( bitIndex >= sizeof( failureStrings ) / sizeof( char * ) )
		return( "Unknown PKI failure code" );

	return( ( char * ) failureStrings[ bitIndex ] );
	}

/* Read/write PKIStatus information:

	PKIStatusInfo ::= SEQUENCE {
		status			INTEGER,
		statusString	SEQUENCE OF UTF8String OPTIONAL,
		failInfo		BIT STRING OPTIONAL
		} */

static int readFreeText( STREAM *stream, char *string, const int maxLength )
	{
	int endPos, stringLength, status;

	/* Read the status string(s).  There can be more than one of these,
	   there's no indication of what the subsequent ones are used for (and
	   not much we can do with them in any case) so we skip them */
	readSequence( stream, &endPos );
	endPos += ( int ) stell( stream );
	status = readOctetStringTag( stream, string, &stringLength, maxLength,
								 BER_STRING_UTF8 );
	if( cryptStatusError( status ) )
		{
		*string = '\0';
		return( status );
		}
	string[ stringLength ] = '\0';
	return( ( stell( stream ) < endPos ) ? \
			sSkip( stream, endPos - stell( stream ) ) : CRYPT_OK );
	}

static int readPkiStatusInfo( STREAM *stream, int *errorCode,
							  char *errorMessage )
	{
	long value, endPos;
	int length, status;

	/* Clear the return values */
	*errorCode = 0;
	*errorMessage = '\0';

	/* Read the outer wrapper and status value */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	status = readShortInteger( stream, &value );
	if( cryptStatusError( status ) )
		return( status );
	*errorCode = ( int ) value;
	if( stell( stream ) < endPos && peekTag( stream ) == BER_SEQUENCE )
		{
		status = readFreeText( stream, errorMessage, MAX_ERRMSG_SIZE - 1 );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( stell( stream ) < endPos )
		{
		char textBitString[ 64 ];
		int value, textBitStringLen, errorMsgLen;
		int i, noBits, bitMask, bitNo = -1;

		/* Read the failure info and slot it into the error string */
		status = readBitString( stream, &value );
		if( cryptStatusError( status ) )
			return( status );
		i = value;
		for( noBits = 0; i && noBits < 32; noBits++ )
			i >>= 1;
		bitMask = 1 << ( noBits - 1 );
		for( i = 0; i < noBits; i++ )
			{
			if( value & bitMask )
				{
				bitNo = ( bitNo == -1 ) ? ( noBits - 1 ) - i : -2;
				textBitString[ i ] = '1';
				}
			else
				textBitString[ i ] = '0';
			bitMask >>= 1;
			}
		if( bitNo >= 0 )
			sprintf( textBitString + i, "'B (bit %d): ", bitNo );
		else
			strcpy( textBitString + i, "'B: " );
		textBitStringLen = strlen( textBitString );
		if( ( errorMsgLen = strlen( errorMessage ) ) != 0 )
			{
			memmove( errorMessage + textBitStringLen, errorMessage,
					 min( errorMsgLen + 1, MAX_ERRMSG_SIZE - textBitStringLen ) );
			errorMessage[ MAX_ERRMSG_SIZE - 1 ] = '\0';
			memcpy( errorMessage, textBitString, textBitStringLen );
			}
		else
			/* If there's a failure code present, turn it into an error
			   string */
			if( value )
				{
				memcpy( errorMessage, textBitString, textBitStringLen + 1 );
				strncat( errorMessage, getFailureString( value ),
						 MAX_ERRMSG_SIZE - textBitStringLen );
				}

		/* If we can return something more useful than the generic "failed"
		   error code, try and do so */
		if( value & CMPFAILINFO_BADALG )
			return( CRYPT_ERROR_NOTAVAIL );
		if( ( value & CMPFAILINFO_BADMESSAGECHECK ) || \
			( value & CMPFAILINFO_BADPOP ) || \
			( value & CMPFAILINFO_WRONGINTEGRITY ) )
			return( CRYPT_ERROR_WRONGKEY );
		if( ( value & CMPFAILINFO_BADREQUEST ) || \
			( value & CMPFAILINFO_NOTAUTHORIZED ) )
			return( CRYPT_ERROR_PERMISSION );
		if( value & CMPFAILINFO_BADDATAFORMAT )
			return( CRYPT_ERROR_BADDATA );
		if( ( value & CMPFAILINFO_UNACCEPTEDPOLICY ) || \
			( value & CMPFAILINFO_UNACCEPTEDEXTENSION ) || \
			( value & CMPFAILINFO_BADCERTTEMPLATE ) )
			return( CRYPT_ERROR_INVALID );
		if( ( value & CMPFAILINFO_TRANSACTIONIDINUSE ) || \
			( value & CMPFAILINFO_DUPLICATECERTREQ ) )
			return( CRYPT_ERROR_DUPLICATE );
		}

	/* A PKI status code is a bit difficult to turn into anything useful,
	   the best we can do is to report that that operation failed and let
	   the user get the exact details from the PKI status info */
	return( ( *errorCode == PKISTATUS_OK || \
			  *errorCode == PKISTATUS_OK_WITHINFO ) ? \
			CRYPT_OK : CRYPT_ERROR_FAILED );
	}

static int writePkiStatusInfo( STREAM *stream, const int status,
							   const long pkiFailureInfo )
	{
	const long localPKIFailureInfo = \
		( pkiFailureInfo != CMPFAILINFO_OK ) ? pkiFailureInfo : \
		( status == CRYPT_ERROR_NOTAVAIL ) ? CMPFAILINFO_BADALG : \
		( status == CRYPT_ERROR_SIGNATURE ) ? CMPFAILINFO_BADMESSAGECHECK :	\
		( status == CRYPT_ERROR_PERMISSION ) ? CMPFAILINFO_BADREQUEST :	\
		( status == CRYPT_ERROR_BADDATA ) ? CMPFAILINFO_BADDATAFORMAT :	\
		( status == CRYPT_ERROR_INVALID ) ? CMPFAILINFO_BADCERTTEMPLATE : \
		( status == CRYPT_ERROR_DUPLICATE ) ? CMPFAILINFO_DUPLICATECERTREQ : \
		0;
	const int length = \
			sizeofShortInteger( PKISTATUS_REJECTED ) + \
			( localPKIFailureInfo ? sizeofBitString( localPKIFailureInfo ) : 0 );

	/* If we've been passed a null stream, it's a size request only */
	if( stream == NULL )
		return( objSize( sizeofObject( length ) ) );

	/* Write the error status info.  If there's a specific failure info code
	   set by the caller we use that, otherwise we try and convert the
	   cryptlib status into an appropriate failure info value */
	writeSequence( stream, objSize( length ) );
	writeSequence( stream, length );
	writeShortInteger( stream, PKISTATUS_REJECTED, DEFAULT_TAG );
	if( localPKIFailureInfo )
		writeBitString( stream, localPKIFailureInfo, DEFAULT_TAG );
	return( CRYPT_OK );
	}

/* Write full cert ID info.  This is written as an attribute in the
   generalInfo field of the message header to allow unambiguous
   identification of the signing cert, which the standard CMP format can't
   do.  Although CMP uses a gratuitously incompatible definition of the
   standard attribute type (calling it InfoTypeAndValue), it's possible to
   shoehorn a standard attribute type in by taking the "ANY" in "ANY DEFINED
   BY x" to mean "SET OF AttributeValue" (for once the use of archaic ASN.1
   is a help, since it's so imprecise that we can shovel in anything and it's
   still valid):

	SigningCertificate ::=  SEQUENCE {
		certs			SEQUENCE OF ESSCertID	-- Size (1)
		} */

static int writeCertID( STREAM *stream, const CRYPT_CONTEXT iCryptCert )
	{
	RESOURCE_DATA msgData;
	int payloadSize, status;

	/* Find out how big the payload will be */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ESSCERTID );
	if( cryptStatusError( status ) )
		return( status );
	payloadSize = ( int ) \
		sizeofObject( sizeofObject( msgData.length ) );

	/* If we've been passed a null stream, it's a size request only */
	if( stream == NULL )
		return( ( int ) sizeofObject( sizeofOID( OID_ESS_CERTID ) + \
									  sizeofObject( payloadSize ) ) );

	/* Write the signing cert ID info */
	writeSequence( stream, sizeofOID( OID_ESS_CERTID ) + \
						   ( int ) sizeofObject( payloadSize ) );
	writeOID( stream, OID_ESS_CERTID );
	writeSet( stream, payloadSize );
	writeSequence( stream,
				   sizeofObject( msgData.length ) );
	writeSequence( stream, msgData.length );
	setResourceData( &msgData, sMemBufPtr( stream ),
					 sMemDataLeft( stream ) );
	status = krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ESSCERTID );
	if( cryptStatusOK( status ) )
		sSkip( stream, msgData.length );
	return( status );
	}

/* Read and process a cert encrypted with CMP's garbled reinvention of CMS
   content:

	EncryptedCert ::= SEQUENCE {
		dummy			[0]	... OPTIONAL,		-- Ignored
		cekAlg			[1]	AlgorithmIdentifier,-- CEK algorithm
		encCEK			[2]	BIT STRING,			-- Encrypted CEK
		dummy			[3]	... OPTIONAL,		-- Ignored
		dummy			[4] ... OPTIONAL,		-- Ignored
		encData			BIT STRING				-- Encrypted cert
		} */

static int processEncryptedCert( STREAM *stream,
								 const CRYPT_CONTEXT iImportContext )
	{
	CRYPT_CONTEXT iSessionKey;
	MECHANISM_WRAP_INFO mechanismInfo;
	QUERY_INFO queryInfo;
	BYTE *encKeyPtr;
	int encKeyLength, encCertLength, status;

	/* Read the CEK algorithm identifier and encrypted CEK.  All of the
	   values are optional although there's no indication of why or what
	   you're supposed to do if they're not present (OTOH for others there's
	   no indication of what you're supposed to do when they're present
	   either) so we treat an absent required value as an error and ignore
	   the others */
	readSequence( stream, NULL );
	if( peekTag( stream ) == MAKE_CTAG( CTAG_EV_DUMMY1 ) )
		readUniversal( stream );				/* Junk */
	status = readContextAlgoID( stream, &iSessionKey, &queryInfo,
								CTAG_EV_CEKALGO );
	if( cryptStatusError( status ) )			/* CEK algo */
		return( status );
	status = readBitStringHole( stream, &encKeyLength, CTAG_EV_ENCCEK );
	if( cryptStatusOK( status ) &&				/* Encrypted CEK */
		( encKeyLength < 56 || encKeyLength > CRYPT_MAX_PKCSIZE ) )
		status = CRYPT_ERROR_OVERFLOW;
	if( cryptStatusOK( status ) )
		{
		encKeyPtr = sMemBufPtr( stream );
		sSkip( stream, encKeyLength );
		if( peekTag( stream ) == MAKE_CTAG( CTAG_EV_DUMMY2 ) )
			readUniversal( stream );			/* Junk */
		if( peekTag( stream ) == MAKE_CTAG( CTAG_EV_DUMMY3 ) )
			readUniversal( stream );			/* Junk */
		status = readBitStringHole( stream, &encCertLength, DEFAULT_TAG );
		}
	if( cryptStatusOK( status ) &&				/* Encrypted cert */
		( encCertLength < 128 || encCertLength > 8192 ) )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusOK( status ) && \
		( queryInfo.cryptMode == CRYPT_MODE_ECB || \
		  queryInfo.cryptMode == CRYPT_MODE_CBC ) )
		{
		int blockSize;

		/* Make sure the data length is valid, checking at this point saves
		   a lot of unnecessary processing and allows us to return a more
		   meaningful error code */
		krnlSendMessage( iSessionKey, RESOURCE_IMESSAGE_GETATTRIBUTE,
						 &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
		if( queryInfo.size % blockSize )
			status = CRYPT_ERROR_BADDATA;
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKey, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Copy the encrypted key to the buffer and import it into the session
	   key context */
	setMechanismWrapInfo( &mechanismInfo, encKeyPtr, encKeyLength,
						  NULL, 0, iSessionKey, iImportContext,
						  CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_IMPORT, &mechanismInfo,
							  MECHANISM_PKCS1 );
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKey,

⌨️ 快捷键说明

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