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

📄 comp_set.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
			certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
			certInfoPtr->subjectDNsize = userCertInfoPtr->subjectDNsize;
			}

		return( CRYPT_OK );
		}

	/* It's an RTCS or OCSP request, remember the responder URL if there's
	   one present (we can't leave it to be read out of the cert because
	   authorityInfoAccess isn't a valid attribute for RTCS/OCSP requests)
	   and copy the cert information to the validity/revocation list */
	assert( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
			certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );

	/* If there's no responder URL set, check whether the user cert contains
	   a responder URL in the RTCS/OCSP authorityInfoAccess GeneralName */
	if( ( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST && \
		  certInfoPtr->cCertVal->responderUrl == NULL ) || \
		( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST && \
		  certInfoPtr->cCertRev->responderUrl == NULL ) )
		{
		const CRYPT_ATTRIBUTE_TYPE aiaAttribute = \
					( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
					CRYPT_CERTINFO_AUTHORITYINFO_RTCS : \
					CRYPT_CERTINFO_AUTHORITYINFO_OCSP;
		SELECTION_STATE savedState;
		void *responderUrl;
		int urlSize = 0;

		saveSelectionState( savedState, userCertInfoPtr );
		status = selectGeneralName( userCertInfoPtr, aiaAttribute,
									MAY_BE_ABSENT );
		if( cryptStatusOK( status ) )
			status = selectGeneralName( userCertInfoPtr,
										CRYPT_ATTRIBUTE_NONE,
										MUST_BE_PRESENT );
		if( cryptStatusOK( status ) )
			status = getCertComponent( userCertInfoPtr,
								CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
								NULL, &urlSize );
		if( cryptStatusOK( status ) )
			{
			/* There's a responder URL present, copy it to the request */
			if( ( responderUrl = \
						clAlloc( "copyUserCertInfo", urlSize ) ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			else
				{
				status = getCertComponent( userCertInfoPtr,
									CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
									responderUrl, &urlSize );
				}
			if( cryptStatusOK( status ) )
				{
				if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST )
					{
					certInfoPtr->cCertVal->responderUrl = responderUrl;
					certInfoPtr->cCertVal->responderUrlSize = urlSize;
					}
				else
					{
					certInfoPtr->cCertRev->responderUrl = responderUrl;
					certInfoPtr->cCertRev->responderUrlSize = urlSize;
					}
				}
			}
		else
			/* If there's no responder URL present it's not a (fatal)
			   error */
			status = CRYPT_OK;
		restoreSelectionState( savedState, userCertInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* If we're using OCSP, make sure that the CA cert hash (needed for the
	   weird cert ID) is present.  We add the necessary information as a
	   pre-encoded blob since we can't do much with the ID fields */
	if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
		{
		BYTE idBuffer[ 256 ], *idBufPtr = idBuffer;
		const int idLength = ( int ) sizeofObject( \
				sizeofAlgoID( CRYPT_ALGO_SHA ) + \
				sizeofObject( 20 ) + sizeofObject( 20 ) + \
				sizeofInteger( userCertInfoPtr->cCertCert->serialNumber, \
							   userCertInfoPtr->cCertCert->serialNumberLength ) );

		/* Make sure there's a CA cert hash present */
		if( !certInfoPtr->certHashSet )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}

		/* Generate the OCSPv1 cert ID */
		if( idLength > 256 && \
		    ( idBufPtr = clDynAlloc( "copyUserCertInfo", \
									 idLength ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		sMemOpen( &stream, idBufPtr, idLength );
		status = writeOCSPv1ID( &stream, userCertInfoPtr,
								certInfoPtr->certHash );
		sMemDisconnect( &stream );
		if( cryptStatusOK( status ) )
			status = addRevocationEntry( &certInfoPtr->cCertRev->revocations,
										 &certInfoPtr->cCertRev->currentRevocation,
										 CRYPT_KEYID_NONE, idBufPtr,
										 idLength, FALSE );
		if( idBufPtr != idBuffer )
			clFree( "copyUserCertInfo", idBufPtr );

		/* Add the cert information again as an ESSCertID extension to work
		   around the problems inherent in OCSPv1 IDs.  This isn't currently
		   used because non-cryptlib v1 responders won't understand it and
		   cryptlib uses RTCS that doesn't have the OCSP problems */

		if( status == CRYPT_ERROR_DUPLICATE )
			/* If this cert is already present in the list, set the extended
			   error code for it */
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( status );
		}

	/* It's an RTCS request, add the cert hash.  We read the cert hash
	   indirectly since it's computed on demand and may not have been
	   evaluated yet */
	status = getCertComponent( userCertInfoPtr,
							   CRYPT_CERTINFO_FINGERPRINT_SHA, certHash,
							   &certHashLength );
	if( cryptStatusOK( status ) )
		status = addValidityEntry( &certInfoPtr->cCertVal->validityInfo,
								   &certInfoPtr->cCertVal->currentValidity, 
								   certHash, certHashLength );
	if( status == CRYPT_ERROR_DUPLICATE )
		/* If this cert is already present in the list, set the extended
		   error code for it */
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
	return( status );
	}

/* Get the hash of the public key (for an OCSPv1 request), possibly
   overwriting a previous hash if there are multiple entries in the
   request */

static int copyCaCertInfo( CERT_INFO *certInfoPtr,
						   CERT_INFO *caCertInfoPtr )
	{
	HASHFUNCTION hashFunction;
	STREAM stream;
	int length, status;

	assert( caCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			caCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
	assert( caCertInfoPtr->publicKeyInfo != NULL );

	getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );

	/* Dig down into the encoded key data to find the weird bits of key that
	   OCSP requires us to hash.  We store the result as the cert hash,
	   which is safe because it isn't used for an OCSP request so it can't
	   be accessed externally */
	sMemConnect( &stream, caCertInfoPtr->publicKeyInfo,
				 caCertInfoPtr->publicKeyInfoSize );
	readSequence( &stream, NULL );	/* Wrapper */
	readUniversal( &stream );		/* AlgoID */
	status = readBitStringHole( &stream, &length, DEFAULT_TAG );
	if( cryptStatusError( status ) )/* BIT STRING wrapper */
		{
		/* There's a problem with the format of the key */
		assert( NOTREACHED );
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_VALUE );
		return( CRYPT_ERROR_INVALID );
		}
	hashFunction( NULL, certInfoPtr->certHash, sMemBufPtr( &stream ),
				  length, HASH_ALL );
	certInfoPtr->certHashSet = TRUE;
	sMemDisconnect( &stream );

	return( CRYPT_OK );
	}

/* Copy revocation information from an RTCS or OCSP request to a response */

static int copyRtcsReqInfo( CERT_INFO *certInfoPtr,
							CERT_INFO *rtcsRequestInfoPtr )
	{
	int status;

	/* Copy the cert validity information and extensions */
	status = copyValidityEntries( &certInfoPtr->cCertVal->validityInfo,
								  rtcsRequestInfoPtr->cCertVal->validityInfo );
	if( cryptStatusOK( status ) )
		status = copyOCSPRequestAttributes( &certInfoPtr->attributes,
											rtcsRequestInfoPtr->attributes );
	return( status );
	}

static int copyOcspReqInfo( CERT_INFO *certInfoPtr,
							CERT_INFO *ocspRequestInfoPtr )
	{
	int status;

	/* Copy the revocation information and extensions */
	status = copyRevocationEntries( &certInfoPtr->cCertRev->revocations,
									ocspRequestInfoPtr->cCertRev->revocations );
	if( cryptStatusOK( status ) )
		status = copyOCSPRequestAttributes( &certInfoPtr->attributes,
											ocspRequestInfoPtr->attributes );
	if( cryptStatusError( status ) )
		return( status );

	return( CRYPT_OK );
	}

/* Set or modify data in a cert request based on the PKI user info */

static int copyPkiUserAttributes( CERT_INFO *certInfoPtr,
								  ATTRIBUTE_LIST *pkiUserAttributes )
	{
	ATTRIBUTE_LIST *attributeListPtr;
	int status;

	/* There's one rather ugly special-case situation that we have to handle
	   which is when the user has submitted a PnP PKI request for a generic 
	   signing cert but their PKI user info indicates that they're intended
	   to be a CA user.  The processing flow for this is as follows:

		CMP: readRequestBody()

			Read request into state=high cert request object;
			Add PKI user info to request;

		ca_issue: caIssuerCert() 

			Add request to newly-created cert object;
			Sign cert;
	   
	   When augmenting the request with the PKI user info, the incoming 
	   request will contain a keyUsage of digitalSignature while the PKI 
	   user info will contain a keyUsage of keyCertSign and/or crlSign.  We 
	   can't fix this up at the CMP level because the request is in the high 
	   state and no changes to the attributes can be made (the PKI user info 
	   is a special case that can added to an object in the high state but 
	   which modifies attributes in it as if it were still in the low state).
	   
	   To avoid the attribute conflict, if we find this situation in the 
	   request/pkiUser combination we delete the keyUsage in the request to 
	   allow it to be replaced by the pkiUser attributes.  Hardcoding in 
	   this special case isn't very elegant, but it's the only way to make 
	   the PnP PKI issue work without requiring that the user explicitly 
	   specify that they want to be a CA, which makes it rather non-PnP */
	attributeListPtr = findAttributeField( certInfoPtr->attributes,
										   CRYPT_CERTINFO_KEYUSAGE,
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && \
		attributeListPtr->intValue == CRYPT_KEYUSAGE_DIGITALSIGNATURE )
		{
		const ATTRIBUTE_LIST *pkiAttributeListPtr = \
				findAttributeField( pkiUserAttributes, CRYPT_CERTINFO_KEYUSAGE,
									CRYPT_ATTRIBUTE_NONE );
		if( pkiAttributeListPtr != NULL && \
			( pkiAttributeListPtr->intValue & ( CRYPT_KEYUSAGE_KEYCERTSIGN | \
												CRYPT_KEYUSAGE_CRLSIGN ) ) )
			{
			/* The cert contains a digitalSignature keyUsage and the PKI user
			   info contains a CA usage, delete the digitalSignature usage to
			   make way for the CA usage */
			deleteAttribute( &certInfoPtr->attributes,
							 &certInfoPtr->attributeCursor, attributeListPtr,
							 certInfoPtr->currentSelection.dnPtr );
			}
		}

	/* Copy the attributes from the PKI user info into the cert */
	status = copyAttributes( &certInfoPtr->attributes, pkiUserAttributes, 
							 &certInfoPtr->errorLocus, 
							 &certInfoPtr->errorType );
	if( cryptStatusError( status ) )
		return( status );

	/* The PKI user info contains an sKID that's used to uniquely identify
	   the user, this applies to the user info itself rather than the cert
	   that'll be issued from it.  Since this will have been copied over 
	   alongside the other attributes, we need to explicitly delete it 
	   before we continue */
	attributeListPtr = findAttributeField( certInfoPtr->attributes, 
										   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		deleteAttribute( &certInfoPtr->attributes,
						 &certInfoPtr->attributeCursor, attributeListPtr,
						 certInfoPtr->currentSelection.dnPtr );
		}

	return( CRYPT_OK );
	}

static int copyPkiUserInfo( CERT_INFO *certInfoPtr,
							CERT_INFO *pkiUserInfoPtr )
	{
	char commonName[ CRYPT_MAX_TEXTSIZE ];
	int commonNameLength, status;

	assert( pkiUserInfoPtr->type == CRYPT_CERTTYPE_PKIUSER );
	assert( pkiUserInfoPtr->certificate != NULL );

	/* If there's no DN present in the request, try and fill it in from the
	   CA-supplied PKI user info */
	if( certInfoPtr->subjectName == NULL )
		{
		/* If neither the request nor the PKI user info has a DN present, we
		   can't continue */
		if( pkiUserInfoPtr->subjectName == NULL )
			return( CRYPT_ERROR_NOTINITED );

		assert( pkiUserInfoPtr->subjectDNptr != NULL );

		/* There's no DN present in the request, it's been supplied by the
		   CA in the PKI user info, copy over the DN and its encoded form
		   from the user info */
		status = copyDN( &certInfoPtr->subjectName,
						 pkiUserInfoPtr->subjectName );
		if( cryptStatusError( status ) )
			return( status );
		if( ( certInfoPtr->subjectDNdata = \
					clAlloc( "copyPkiUserInfo",
							 pkiUserInfoPtr->subjectDNsize ) ) == NULL )
			{
			deleteDN( &certInfoPtr->subjectName );
			return( CRYPT_ERROR_MEMORY );
			}
		memcpy( certInfoPtr->subjectDNdata, pkiUserInfoPtr->subjectDNptr,
				pkiUserInfoPtr->subjectDNsize );
		certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
		certInfoPtr->subjectDNsize = pkiUserInfoPtr->subjectDNsize;

		/* Copy any additional attributes across */
		return( copyPkiUserAttributes( certInfoPtr, 
									   pkiUserInfoPtr->attributes ) );
		}

	/* If there's no PKI user DN with the potential to conflict with the one
	   in the request present, copy any additional attributes across and 

⌨️ 快捷键说明

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