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

📄 cmp_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
			if( stell( stream ) < endPos )
				/* Skip the issuerSerial if there's one present.  We can't
				   really do much with it in this form without rewriting it
				   into the standard issuerAndSerialNumber form, but in any
				   case we don't need it because we've already got the cert
				   ID */
				status = readUniversal( stream );
			continue;
			}

		/* It's something that we don't recognise, skip it */
		status = readUniversal( stream );
		}
	if( iterationCount >= FAILSAFE_ITERATIONS_MED )
		retIntError();

	return( status );
	}
#endif /* USE_CMP */

/****************************************************************************
*																			*
*								Read Status Info							*
*																			*
****************************************************************************/

/* The following code is shared between CMP and TSP due to TSP's use of
   random elements cut & pasted from CMP without any real understanding of
   their function or semantics */

#if defined( USE_CMP ) || defined( USE_TSP )

/* Map a PKI failure info value to an error string */

static int getFailureString( const char **stringPtrPtr, int *stringLength,
							 const int value )
	{
	typedef struct {
		const char FAR_BSS *string;
		const int stringLength;
		} FAILURE_INFO;
	static const FAILURE_INFO FAR_BSS failureInfo[] = {
		{ "Unrecognized or unsupported Algorithm Identifier", 48 },
		{ "The integrity check failed (e.g. signature did not verify)", 58 },
		{ "This transaction is not permitted or supported", 46 },
		{ "The messageTime was not sufficiently close to the system time as "
		  "defined by local policy", 88 },
		{ "No certificate could be found matching the provided criteria", 60 },
		{ "The data submitted has the wrong format", 39 },
		{ "The authority indicated in the request is different from the one "
		  "creating the response token", 92 },
		{ "The requester's data is incorrect (used for notary services)", 60 },
		{ "Timestamp is missing but should be there (by policy)", 52 },
		{ "The proof-of-possession failed", 30 },
		{ "The certificate has already been revoked", 40 },
		{ "The certificate has already been confirmed", 42 },
		{ "Invalid integrity, password based instead of signature or vice "
		  "versa", 68 },
		{ "Invalid recipient nonce, either missing or wrong value", 54 },
		{ "The TSA's time source is not available", 38 },
		{ "The requested TSA policy is not supported by the TSA", 52 },
		{ "The requested extension is not supported by the TSA", 51 },
		{ "The additional information requested could not be understood or "
		  "is not available", 80 },
		{ "Invalid sender nonce, either missing or wrong size", 50 },
		{ "Invalid certificate template or missing mandatory information", 61 },
		{ "Signer of the message unknown or not trusted", 44 },
		{ "The transaction identifier is already in use", 44 },
		{ "The version of the message is not supported", 43 },
		{ "The sender was not authorized to make the preceding request or "
		  "perform the preceding action", 91 },
		{ "The request cannot be handled due to system unavailability", 58 },
		{ "The request cannot be handled due to system failure", 51 },
		{ "Certificate cannot be issued because a duplicate certificate "
		  "already exists", 75 },
		{ "Unknown PKI failure code", 24 }, { "Unknown PKI failure code", 25 }
		};
	int bitIndex = 0, bitFlags = value, iterationCount = 0;

	/* Clear return values */
	*stringPtrPtr = NULL;
	*stringLength = 0;

	/* Find the first failure string corresponding to a bit set in the
	   failure info */
	if( bitFlags <= 0 )
		{
		*stringPtrPtr = "Missing PKI failure code";
		*stringLength = 24;

		return( CRYPT_OK );
		}
	while( !( bitFlags & 1 ) && \
		   iterationCount++ < FAILSAFE_ARRAYSIZE( failureInfo, FAILURE_INFO ) )
		{
		bitIndex++;
		bitFlags >>= 1;
		}
	if( iterationCount >= FAILSAFE_ARRAYSIZE( failureInfo, FAILURE_INFO ) )
		retIntError();
	if( bitIndex >= 28 )
		{
		*stringPtrPtr = "Unknown PKI failure code";
		*stringLength = 24;

		return( CRYPT_OK );
		}
	*stringPtrPtr = failureInfo[ bitIndex ].string;
	*stringLength = failureInfo[ bitIndex ].stringLength;

	return( CRYPT_OK );
	}

/* Read PKIStatus information:

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

  Note that readPkiStatusInfo() is declared global, since it's used by the 
  TSP code due to TSP's use of random elements cut & pasted from CMP */

static int readFreeText( STREAM *stream, char *string, const int stringMaxLen,
						 int *stringLength )
	{
	int endPos, length, 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 += stell( stream );
	status = readCharacterString( stream, string, stringMaxLen, 
								  &length, BER_STRING_UTF8 );
	if( cryptStatusError( status ) )
		{
		strlcpy_s( string, stringMaxLen, "Invalid PKI free text" );
		return( status );
		}
	*stringLength = length;
	return( ( stell( stream ) < endPos ) ? \
			sSkip( stream, endPos - stell( stream ) ) : CRYPT_OK );
	}

int readPkiStatusInfo( STREAM *stream, ERROR_INFO *errorInfo )
	{
	char errorMessage[ MAX_ERRMSG_SIZE + 8 ], textBitString[ 128 + 8 ];
	long value, endPos;
	int errorMessageLength = 0, textBitStringLength;
	int bitString, noBits, bitMask, bitNo = -1, i, length, status;

	/* Clear the return values */
	memset( errorInfo, 0, sizeof( ERROR_INFO ) );

	/* Read the outer wrapper and status value */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	status = readShortInteger( stream, &value );
	if( cryptStatusError( status ) )
		{
		setErrorString( errorInfo, "Invalid PKI status value", 24 );
		return( status );
		}
	errorInfo->errorCode = ( int ) value;
	if( stell( stream ) < endPos && peekTag( stream ) == BER_SEQUENCE )
		{
		memcpy( errorMessage, "Server returned error: ", 23 );

		status = readFreeText( stream, errorMessage + 23,
							   MAX_ERRMSG_SIZE - 32, &errorMessageLength );
		if( cryptStatusError( status ) )
			return( status );
		errorMessageLength += 23;
		}
	if( stell( stream ) >= endPos )
		{
		/* If there was a problem but there's no extra error information
		   present, return a "This page deliberately left blank" error */
		if( errorMessageLength <= 0 && errorInfo->errorCode != PKISTATUS_OK )
			{
			setErrorString( errorInfo, 
							"Server returned nonspecific error information", 
							45 );
			}

		/* See comment at end for the translation of error codes */
		return( ( errorInfo->errorCode == PKISTATUS_OK || \
				  errorInfo->errorCode == PKISTATUS_OK_WITHINFO ) ? \
				CRYPT_OK : CRYPT_ERROR_FAILED );
		}

	/* Read the failure info and slot it into the error string */
	status = readBitString( stream, &bitString );
	if( cryptStatusError( status ) )
		{
		setErrorString( errorInfo, "Invalid PKI failure info", 24 );
		return( status );
		}
	memcpy( textBitString, "Server returned status value ", 29 );
	textBitStringLength = 29;
	i = bitString;
	for( noBits = 0; i > 0 && noBits < 32; noBits++ )
		i >>= 1;
	bitMask = 1 << ( noBits - 1 );
	for( i = 0; i < noBits; i++ )
		{
		if( bitString & bitMask )
			{
			/* If there's no bit set yet, set it.  If there's already a bit 
			   set, set it to a non-value that indicates that more than one 
			   bit is set */
			bitNo = ( bitNo == -1 ) ? ( noBits - 1 ) - i : -2;
			textBitString[ textBitStringLength++ ] = '1';
			}
		else
			textBitString[ textBitStringLength++ ] = '0';
		bitMask >>= 1;
		}
	if( bitNo >= 0 )
		{
		textBitStringLength = \
			sprintf_s( textBitString, 64,
					   "Server returned status bit %d: ", bitNo );
		}
	else
		{
		memcpy( textBitString + textBitStringLength, "'B: ", 4 );
		textBitStringLength += 4;
		}
	if( errorMessageLength > 0 )
		{
		/* There's error message text present, move it up to make room for 
		   the bit string text */
		if( errorMessageLength > MAX_ERRMSG_SIZE - textBitStringLength )
			errorMessageLength = MAX_ERRMSG_SIZE - textBitStringLength;
		memmove( errorMessage + textBitStringLength, 
				 errorMessage, errorMessageLength );
		memcpy( errorMessage, textBitString, textBitStringLength );
		errorMessageLength += textBitStringLength;
		}
	else
		{
		/* If there's a failure code present, turn it into an error string */
		if( bitString > 0 )
			{
			const char *failureString;
			int failureStringLength;

			memcpy( errorMessage, textBitString, textBitStringLength );
			status = getFailureString( &failureString, &failureStringLength, 
									   bitString );
			if( cryptStatusError( status ) || \
				textBitStringLength + failureStringLength >= MAX_ERRMSG_SIZE )
				{
				failureString = "[...]";
				failureStringLength = 5;
				}
			memcpy( errorMessage + textBitStringLength, failureString,
					failureStringLength );
			errorMessageLength = textBitStringLength + failureStringLength;
			}
		}
	if( errorMessageLength > 0 )
		setErrorString( errorInfo, errorMessage, errorMessageLength );

	/* If we can return something more useful than the generic "failed" 
	   error code, try and do so */
	if( bitString & CMPFAILINFO_BADALG )
		return( CRYPT_ERROR_NOTAVAIL );
	if( ( bitString & CMPFAILINFO_BADMESSAGECHECK ) || \
		( bitString & CMPFAILINFO_BADPOP ) || \
		( bitString & CMPFAILINFO_WRONGINTEGRITY ) )
		return( CRYPT_ERROR_WRONGKEY );
	if( ( bitString & CMPFAILINFO_BADREQUEST ) || \
		( bitString & CMPFAILINFO_SIGNERNOTTRUSTED ) || \
		( bitString & CMPFAILINFO_NOTAUTHORIZED ) )
		return( CRYPT_ERROR_PERMISSION );
	if( bitString & CMPFAILINFO_BADDATAFORMAT )
		return( CRYPT_ERROR_BADDATA );
	if( ( bitString & CMPFAILINFO_UNACCEPTEDPOLICY ) || \
		( bitString & CMPFAILINFO_UNACCEPTEDEXTENSION ) || \
		( bitString & CMPFAILINFO_BADCERTTEMPLATE ) )
		return( CRYPT_ERROR_INVALID );
	if( ( bitString & CMPFAILINFO_TRANSACTIONIDINUSE ) || \
		( bitString & 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 the operation failed and let
	   the user get the exact details from the PKI status info */
	return( ( errorInfo->errorCode == PKISTATUS_OK || \
			  errorInfo->errorCode == PKISTATUS_OK_WITHINFO ) ? \
			CRYPT_OK : CRYPT_ERROR_FAILED );
	}
#endif /* USE_CMP || USE_TSP */

#ifdef USE_CMP

/****************************************************************************
*																			*
*								PKI Body Functions							*
*																			*
****************************************************************************/

/* Read request body */

static int readRequestBody( STREAM *stream, SESSION_INFO *sessionInfoPtr,
							CMP_PROTOCOL_INFO *protocolInfo,
							const int messageType )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
	MESSAGE_DATA msgData;
	BYTE authCertID[ CRYPT_MAX_HASHSIZE + 8 ];
	int value, length, status;

	/* Import the CRMF request */
	status = readSequence( stream, &length );
	if( cryptStatusOK( status ) )
		status = importCertFromStream( stream,
								&sessionInfoPtr->iCertRequest,
								( messageType == CTAG_PB_P10CR ) ? \
									CRYPT_CERTTYPE_CERTREQUEST : \
								( messageType == CTAG_PB_RR ) ? \
									CRYPT_CERTTYPE_REQUEST_REVOCATION : \
									CRYPT_CERTTYPE_REQUEST_CERT,
								length );
	if( cryptStatusError( status ) )
		{
		protocolInfo->pkiFailInfo = CMPFAILINFO_BADCERTTEMPLATE;
		retExt( status, 
				( status, SESSION_ERRINFO, "Invalid CRMF request" ) );
		}

	/* If the request is from an encryption-only key, remember this so that
	   we can peform special-case processing later on */
	status = krnlSendMessage( sessionInfoPtr->iCertRequest,
							  IMESSAGE_GETATTRIBUTE, &value,
							  CRYPT_CERTINFO_SELFSIGNED );
	if( cryptStatusOK( status ) && !value )
		{
		/* If the request indicates that it's a signing key then it has to
		   be signed */
		status = krnlSendMessage( sessionInfoPtr->iCertRequest,
								  IMESSAGE_GETATTRIBUTE, &value,
								  CRYPT_CERTINFO_KEYUSAGE );
		if( cryptStatusOK( status ) && \

⌨️ 快捷键说明

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