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

📄 certwr.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	}

/* Write an OCSP request:

	OCSPRequest ::= SEQUENCE {				-- Write, v1
		reqName		[1]	EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
		reqList			SEQUENCE OF SEQUENCE {
						SEQUENCE {			-- certID
			hashAlgo	AlgorithmIdentifier,
			iNameHash	OCTET STRING,
			iKeyHash	OCTET STRING,
			serialNo	INTEGER
			} }
		}

	OCSPRequest ::= SEQUENCE {				-- Write, v2
		version		[0]	EXPLICIT INTEGER (1),
		reqName		[1]	EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
		reqList			SEQUENCE OF SEQUENCE {
			certID	[2]	EXPLICIT OCTET STRING	-- Cert hash
			}
		} */

static int writeOcspRequestInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
								 const CERT_INFO *issuerCertInfoPtr,
								 const CRYPT_CONTEXT iIssuerCryptContext )
	{
	REVOCATION_INFO *revocationInfo;
	int length, extensionSize, revocationInfoLength = 0, status;

	/* Make sure that we've actually got some requests present to write */
	if( subjectCertInfoPtr->revocations == NULL )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_ABSENT );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Perform any necessary pre-encoding steps.  We should really update the
	   nonce when we write the data for real, but to do that we'd have to re-
	   calculate the extension information (via preEncodeCertifiate()) for
	   null-stream and real writes just because the one extension changes, so
	   we calculate it when we do the dummy write instead.  This is safe
	   because the write process always performs a real write immediately
	   after the null-stream write */
	if( sIsNullStream( stream ) )
		{
		ATTRIBUTE_LIST *attributeListPtr;
		RESOURCE_DATA msgData;

		/* To ensure freshness we always use a new nonce when we write an
		   OCSP request.  We don't check for problems (which, in any case,
		   could only occur if there's an out-of-memory error) because
		   there's not much we can meaningfully do if the add fails */
		attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
											   CRYPT_CERTINFO_OCSP_NONCE,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			setMessageData( &msgData, attributeListPtr->value, 16 );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  IMESSAGE_GETATTRIBUTE_S, &msgData,
									  CRYPT_IATTRIBUTE_RANDOM_NONCE );
			attributeListPtr->valueLength = 16;
			}
		else
			{
			BYTE nonce[ CRYPT_MAX_HASHSIZE ];

			setMessageData( &msgData, nonce, 16 );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  IMESSAGE_GETATTRIBUTE_S, &msgData,
									  CRYPT_IATTRIBUTE_RANDOM_NONCE );
			if( cryptStatusOK( status ) )
				status = addAttributeField( &subjectCertInfoPtr->attributes,
											CRYPT_CERTINFO_OCSP_NONCE,
											CRYPT_ATTRIBUTE_NONE, nonce, 16,
											ATTR_FLAG_NONE, NULL, NULL );
			attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
												   CRYPT_CERTINFO_OCSP_NONCE,
												   CRYPT_ATTRIBUTE_NONE );
			}
		if( cryptStatusError( status ) )
			return( status );
		if( attributeListPtr != NULL )
			{
			BYTE *noncePtr = attributeListPtr->value;

			/* Because of OCSP's inexplicable use of integers to encode the
			   nonce octet string, we have to tweak the first byte to ensure
			   that the integer encoding works as a standard OCTET STRING */
			noncePtr[ 0 ] &= 0x7F;
			if( !noncePtr[ 0 ] )
				noncePtr[ 0 ]++;
			}

		/* Perform the pre-encoding checks */
		status = preEncodeCertificate( subjectCertInfoPtr, NULL,
									   CRYPT_CERTTYPE_OCSP_REQUEST );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Determine how big the encoded OCSP request will be */
	for( revocationInfo = subjectCertInfoPtr->revocations;
		 revocationInfo != NULL; revocationInfo = revocationInfo->next )
		revocationInfoLength += sizeofOcspRequestEntry( revocationInfo );
	extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
	length = ( ( subjectCertInfoPtr->version == 2 ) ? \
				 sizeofObject( sizeofShortInteger( CTAG_OR_VERSION ) ) : 0 ) + \
			 ( ( issuerCertInfoPtr != NULL ) ? \
				 sizeofObject( sizeofObject( issuerCertInfoPtr->subjectDNsize ) ) : 0 ) + \
			 sizeofObject( revocationInfoLength ) + \
			 ( extensionSize ? \
			   sizeofObject( sizeofObject( extensionSize ) ) : 0 );

	/* Write the outer SEQUENCE wrapper */
	writeSequence( stream, length );

	/* If we're using v2 identifiers, mark this as a v2 request */
	if( subjectCertInfoPtr->version == 2 )
		{
		writeConstructed( stream, sizeofShortInteger( 1 ), CTAG_OR_VERSION );
		writeShortInteger( stream, 1, DEFAULT_TAG );
		}

	/* If we're signing the request, write the issuer DN as a GeneralName */
	if( issuerCertInfoPtr != NULL )
		{
		writeConstructed( stream,
						  sizeofObject( issuerCertInfoPtr->subjectDNsize ), 1 );
		writeConstructed( stream, issuerCertInfoPtr->subjectDNsize, 4 );
		swrite( stream, issuerCertInfoPtr->subjectDNptr,
				issuerCertInfoPtr->subjectDNsize );
		}

	/* Write the SEQUENCE OF revocation information wrapper and the
	   revocation information */
	status = writeSequence( stream, revocationInfoLength );
	for( revocationInfo = subjectCertInfoPtr->revocations;
		 cryptStatusOK( status ) && revocationInfo != NULL;
		 revocationInfo = revocationInfo->next )
		status = writeOcspRequestEntry( stream, revocationInfo );
	if( cryptStatusError( status ) || extensionSize <= 0 )
		return( status );

	/* Write the attributes */
	return( writeAttributes( stream, subjectCertInfoPtr->attributes,
							 CRYPT_CERTTYPE_OCSP_REQUEST, extensionSize ) );
	}

/* Write an OCSP response:

	OCSPResponse ::= SEQUENCE {
		version		[0]	EXPLICIT INTEGER (1),
		respID		[1]	EXPLICIT Name,
		producedAt		GeneralizedTime,
		responses		SEQUENCE OF Response
		exts		[1]	EXPLICIT Extensions OPTIONAL,
		}

	RTCSResponse ::= SEQUENCE {
		responses		SEQUENCE OF Response,
		exts			Extensions OPTIONAL
		} */

static int writeOcspResponseInfo( STREAM *stream,
								  CERT_INFO *subjectCertInfoPtr,
								  const CERT_INFO *issuerCertInfoPtr,
								  const CRYPT_CONTEXT iIssuerCryptContext )
	{
	REVOCATION_INFO *revocationInfo;
	int length = 0, extensionSize, revocationInfoLength = 0, status;

	/* Make sure that we've actually got some responses present to write */
	if( subjectCertInfoPtr->revocations == NULL )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_ABSENT );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Perform any necessary pre-encoding steps */
	if( sIsNullStream( stream ) )
		{
		status = preEncodeCertificate( subjectCertInfoPtr, NULL,
									   CRYPT_CERTTYPE_OCSP_RESPONSE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Determine how big the encoded OCSP response will be */
	for( revocationInfo = subjectCertInfoPtr->revocations;
		 revocationInfo != NULL; revocationInfo = revocationInfo->next )
		revocationInfoLength += sizeofOcspResponseEntry( revocationInfo );
	extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
	length = ( int ) \
			 sizeofObject( sizeofShortInteger( CTAG_OP_VERSION ) ) + \
			 sizeofObject( issuerCertInfoPtr->subjectDNsize ) + \
			 sizeofGeneralizedTime() + \
			 sizeofObject( revocationInfoLength ) + \
			 ( extensionSize ? \
				sizeofObject( sizeofObject( extensionSize ) ) : 0 );

	/* Write the outer SEQUENCE wrapper, and, if it's an OCSP response, mark
	   it as a v1 response and write the issuer DN and producedAt time */
	writeSequence( stream, length );
	writeConstructed( stream, sizeofShortInteger( 1 ), CTAG_OP_VERSION );
	writeShortInteger( stream, 1, DEFAULT_TAG );
	writeConstructed( stream, issuerCertInfoPtr->subjectDNsize, 1 );
	swrite( stream, issuerCertInfoPtr->subjectDNptr,
			issuerCertInfoPtr->subjectDNsize );
	writeGeneralizedTime( stream, subjectCertInfoPtr->startTime,
						  DEFAULT_TAG );

	/* Write the SEQUENCE OF revocation information wrapper and the
	   revocation information */
	status = writeSequence( stream, revocationInfoLength );
	for( revocationInfo = subjectCertInfoPtr->revocations;
		 cryptStatusOK( status ) && revocationInfo != NULL;
		 revocationInfo = revocationInfo->next )
		status = writeOcspResponseEntry( stream, revocationInfo,
										 subjectCertInfoPtr->startTime );
	if( cryptStatusError( status ) || extensionSize <= 0 )
		return( status );

	/* Write the attributes */
	return( writeAttributes( stream, subjectCertInfoPtr->attributes,
							 CRYPT_CERTTYPE_OCSP_RESPONSE, extensionSize ) );
	}

/* Write PKI user info */

int writePkiUserInfo( STREAM *stream, CERT_INFO *userInfoPtr,
					  const CERT_INFO *issuerCertInfoPtr,
					  const CRYPT_CONTEXT iIssuerCryptContext )
	{
	BYTE userInfo[ 128 ], algoID[ 128 ];
	int extensionSize, userInfoSize, algoIDsize, status;

	UNUSED( issuerCertInfoPtr );

	if( sIsNullStream( stream ) )
		{
		RESOURCE_DATA msgData;
		BYTE keyID[ 16 ];
		int keyIDlength;

		/* Generate the key identifier.  Once it's in user-encoded form the
		   full identifier can't quite fit so we adjust the size to the
		   maximum amount we can encode.  This is necessary because it's
		   also used to locate the user info in a key store, if we used the
		   un-adjusted form for the key ID we couldn't locate the stored
		   user info using the adjusted form */
		setMessageData( &msgData, keyID, 16 );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusError( status ) )
			return( status );
		keyIDlength = adjustPKIUserValue( keyID, 3 );
		addAttributeField( &userInfoPtr->attributes,
						   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,
						   CRYPT_ATTRIBUTE_NONE, keyID, keyIDlength,
						   ATTR_FLAG_NONE, NULL, NULL );
		status = checkAttributes( ATTRIBUTE_CERTIFICATE,
								  userInfoPtr->attributes,
								  &userInfoPtr->errorLocus,
								  &userInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );

		/* We can't generate the user info yet since we're doing the pre-
		   encoding pass and writing to a null stream so we leave it for the
		   actual encoding pass and only provide a size estimate for now */
		userInfoSize = PKIUSER_ENCR_AUTHENTICATOR_SIZE;

		/* Since we can't use the fixed CA key yet, we set the algo ID size
		   to the size of the info for the fixed 3DES key */
		algoIDsize = 22;
		}
	else
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;
		RESOURCE_DATA msgData;
		STREAM userInfoStream;

		/* Create an RC4 context and use it to generate the user passwords.
		   These aren't encryption keys but just authenticators used for
		   MACing so we don't go to the usual extremes to protect them */
		setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RC4 );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		sMemOpen( &userInfoStream, userInfo, 128 );
		writeSequence( &userInfoStream,
					   2 * sizeofObject( PKIUSER_AUTHENTICATOR_SIZE ) );
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_GENKEY,
								  NULL, FALSE );
		if( cryptStatusOK( status ) )
			{
			krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_ENCRYPT,
							 userInfoPtr->pkiIssuePW,
							 PKIUSER_AUTHENTICATOR_SIZE );
			writeOctetString( &userInfoStream, userInfoPtr->pkiIssuePW,
							  PKIUSER_AUTHENTICATOR_SIZE, DEFAULT_TAG );
			status = krnlSendMessage( createInfo.cryptHandle,
									  IMESSAGE_CTX_ENCRYPT,
									  userInfoPtr->pkiRevPW,
									  PKIUSER_AUTHENTICATOR_SIZE );
			writeOctetString( &userInfoStream, userInfoPtr->pkiRevPW,
							  PKIUSER_AUTHENTICATOR_SIZE, DEFAULT_TAG );
			userInfoSize = stell( &userInfoStream );
			}
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		sMemDisconnect( &userInfoStream );
		if( cryptStatusError( status ) )
			return( status );

		/* Encrypt the user info.  Since user objects aren't fully
		   implemented yet, we use a fixed key as the CA key for now.  When
		   user objects are fully implemented, we'd need to lock the CA key
		   around the following operations */
		setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_3DES );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		setMessageData( &msgData, "interop interop interop ", 24 );
		status = krnlSendMessage( createInfo.cryptHandle,
								  IMESSAGE_SETATTRIBUTE_S, &msgData,
								  CRYPT_CTXINFO_KEY );
		if( cryptStatusOK( status ) )
			{
			int i;

			/* Add PKCS #5 padding to the end of the user info and encrypt
			   it */
			assert( userInfoSize + 2 == PKIUSER_ENCR_AUTHENTICATOR_SIZE );
			for( i = 0; i < 2; i++ )
				userInfo[ userInfoSize++ ] = 2;
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_CTX_GENIV );
			status = krnlSendMessage( createInfo.cryptHandle,
									  IMESSAGE_CTX_ENCRYPT, userInfo,
									  userInfoSize );
			if( cryptStatusOK( status ) )
				{
				STREAM algoIDstream;

				sMemOpen( &algoIDstream, algoID, 128 );
				status = writeContextAlgoID( &algoIDstream,
									createInfo.cryptHandle, CRYPT_ALGO_NONE,
									ALGOID_FLAG_NONE );
				algoIDsize = stell( &algoIDstream );
				sMemDisconnect( &algoIDstream );
				}
			}
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the user DN, encrypted user info, and any supplementary
	   information */
	extensionSize = sizeofAttributes( userInfoPtr->attributes );
	writeDN( stream, userInfoPtr->subjectName, DEFAULT_TAG );
	swrite( stream, algoID, algoIDsize );
	writeOctetString( stream, userInfo, userInfoSize, DEFAULT_TAG );
	return( writeAttributes( stream, userInfoPtr->attributes,
							 CRYPT_CERTTYPE_PKIUSER, extensionSize ) );
	}

/****************************************************************************
*																			*
*						Read Function Access Information					*
*																			*
****************************************************************************/

const CERTWRITE_INFO certWriteTable[] = {
	{ CRYPT_CERTTYPE_CERTIFICATE, writeCertInfo },
	{ CRYPT_CERTTYPE_CERTCHAIN, writeCertInfo },
	{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, writeAttributeCertInfo },
	{ CRYPT_CERTTYPE_CERTREQUEST, writeCertRequestInfo },
	{ CRYPT_CERTTYPE_REQUEST_CERT, writeCrmfRequestInfo },
	{ CRYPT_CERTTYPE_REQUEST_REVOCATION, writeRevRequestInfo },
	{ CRYPT_CERTTYPE_CRL, writeCRLInfo },
	{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, writeCmsAttributes },
	{ CRYPT_CERTTYPE_RTCS_REQUEST, writeRtcsRequestInfo },
	{ CRYPT_CERTTYPE_RTCS_RESPONSE, writeRtcsResponseInfo },
	{ CRYPT_CERTTYPE_OCSP_REQUEST, writeOcspRequestInfo },
	{ CRYPT_CERTTYPE_OCSP_RESPONSE, writeOcspResponseInfo },
	{ CRYPT_CERTTYPE_PKIUSER, writePkiUserInfo },
	{ CRYPT_CERTTYPE_NONE, NULL }
	};

⌨️ 快捷键说明

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