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

📄 certcset.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
			deleteDN( &certInfoPtr->subjectName );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a CRMF request there could also be a validity period 
	   specified */
	if( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		{
		const time_t currentTime = getApproxTime();

		/* We don't allow start times backdated by more than a year, or end 
		   times before the start time.  Since these are trivial things, we
		   don't abort if there's a problem but just quietly fix the value */
		if( certRequestInfoPtr->startTime > 0 && \
			certRequestInfoPtr->startTime > currentTime - ( 86400 * 365 ) )
			certInfoPtr->startTime = certRequestInfoPtr->startTime;
		if( certRequestInfoPtr->endTime > 0 && \
			certRequestInfoPtr->endTime > certInfoPtr->startTime )
			certInfoPtr->endTime = certRequestInfoPtr->endTime;
		}

	return( CRYPT_OK );
	}

/* Copy what we need to identify the cert to be revoked and any revocation 
   information into a certificate object */

static int copyRevReqInfo( CERT_INFO *certInfoPtr,
						   CERT_INFO *revRequestInfoPtr )
	{
	int status;

	status = copyRevocationInfo( certInfoPtr, revRequestInfoPtr );
	if( cryptStatusError( status ) || \
		revRequestInfoPtr->attributes == NULL )
		return( status );
	return( copyRevocationAttributes( &certInfoPtr->attributes,
									  revRequestInfoPtr->attributes,
									  &certInfoPtr->errorLocus, 
									  &certInfoPtr->errorType ) );
	}

/* Copy user certificate info into a certificate object */

static int copyUserCertInfo( CERT_INFO *certInfoPtr,
							 CERT_INFO *userCertInfoPtr,
							 const CRYPT_HANDLE iCryptHandle )
	{
	STREAM stream;
	BYTE certHash[ CRYPT_MAX_HASHSIZE ];
	int certHashLength = CRYPT_MAX_HASHSIZE, status;

	assert( userCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			userCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
	assert( userCertInfoPtr->certificate != NULL );

	/* If it's a CRL, copy the revocation information across */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
		return( copyRevocationInfo( certInfoPtr, userCertInfoPtr ) );

	/* If it's a CRMF cert request, copy the public key and DN.  We copy the 
	   full DN rather than just the encoded form in case the user wants to 
	   query the request details after creating it */
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		{
		status = copyDN( &certInfoPtr->subjectName,
						 userCertInfoPtr->subjectName );
		if( cryptStatusError( status ) )
			return( status );
		if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
			certInfoPtr->publicKeyInfo != NULL )
			/* If a key has already been added as 
			   CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, there's nothing further
			   to do.  Checking for this (rather than returning an error)
			   allows the DN information from an existing cert to be copied
			   into a request for a new key */
			return( CRYPT_OK );
		status = copyPublicKeyInfo( certInfoPtr, iCryptHandle, NULL );
		if( cryptStatusError( status ) )
			deleteDN( &certInfoPtr->subjectName );
		return( status );
		}

	/* If it's a CRMF revocation request, copy across the issuer and serial 
	   number */
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
		{
		/* If the info is already present we can't add it again */
		if( certInfoPtr->issuerName != NULL )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
			return( CRYPT_ERROR_INITED );
			}

		/* Copy across the issuer name and allocate any further storage that 
		   we need.  We don't care about any internal structure of the issuer 
		   DN so we just copy the pre-encoded form, we could in theory copy 
		   the full DN but it isn't really the issuer (creator) of the object 
		   so it's better if it appears to have no issuer DN than a 
		   misleading one */
		status = copyIssuerDnData( certInfoPtr, userCertInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		status = setSerialNumber( certInfoPtr, userCertInfoPtr->serialNumber,
								  userCertInfoPtr->serialNumberLength );
		if( cryptStatusOK( status ) && \
			certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION && \
			( certInfoPtr->subjectDNdata = \
					  clAlloc( "copyUserCertInfo",
							   userCertInfoPtr->subjectDNsize ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		if( cryptStatusError( status ) )
			{
			clFree( "copyUserCertInfo", certInfoPtr->issuerDNdata );
			certInfoPtr->issuerDNptr = certInfoPtr->issuerDNdata = NULL;
			certInfoPtr->issuerDNsize = 0;
			if( certInfoPtr->serialNumber != NULL && \
				certInfoPtr->serialNumber != certInfoPtr->serialNumberBuffer )
				clFree( "copyUserCertInfo", certInfoPtr->serialNumber );
			certInfoPtr->serialNumber = NULL;
			return( status );
			}

		/* If it's a CRMF revocation request, copy the subject DN for use in 
		   CMP */
		if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
			{
			memcpy( certInfoPtr->subjectDNdata, userCertInfoPtr->subjectDNptr,
					userCertInfoPtr->subjectDNsize );
			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->responderUrl == NULL )
		{
		const CRYPT_ATTRIBUTE_TYPE aiaAttribute = \
					( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
					CRYPT_CERTINFO_AUTHORITYINFO_RTCS : \
					CRYPT_CERTINFO_AUTHORITYINFO_OCSP;
		SELECTION_STATE savedState;
		int urlSize;

		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( ( certInfoPtr->responderUrl = \
						clAlloc( "copyUserCertInfo", urlSize ) ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			else
				getCertComponent( userCertInfoPtr,
								  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
								  certInfoPtr->responderUrl,
								  &certInfoPtr->responderUrlSize );
			}
		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->serialNumber, \
									   userCertInfoPtr->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->revocations,
										 &certInfoPtr->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->validityInfo,
								   &certInfoPtr->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->validityInfo,
							rtcsRequestInfoPtr->validityInfo,
							&certInfoPtr->errorLocus, &certInfoPtr->errorType );
	if( cryptStatusOK( status ) )
		status = copyRequestAttributes( &certInfoPtr->attributes,
							rtcsRequestInfoPtr->attributes,
							&certInfoPtr->errorLocus, &certInfoPtr->errorType );
	return( status );
	}

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

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

	/* Set the response type based on the format specifier in the request */
	certInfoPtr->responseType = OCSPRESPONSE_TYPE_OCSP;

	return( CRYPT_OK );
	}

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

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;
		return( CRYPT_OK );
		}

	/* If there's no PKI user DN with the potential to conflict with the one 
	   in the request present, we're done */
	if( pkiUserInfoPtr->subjectName == NULL )
		return( CRYPT_OK );

	/* There's both a request DN and PKI user DN present.  If the request 
	   contains only a CN, combine it with the PKI user DN and update the 
	   request */
	status = getDNComponentValue( certInfoPtr->subjectName,
								  CRYPT_CERTINFO_COMMONNAME, commonName,
								  &commonNameLength, CRYPT_MAX_TEXTSIZE );
	if( cryptStatusOK( status ) )
		{
		void *tempDN = NULL;
		BOOLEAN isCommonNameDN;

		/* Check whether the request DN contains only a CN.  There's no easy 
		   way to do this directly, the only way we can do it is by creating 
		   a temporary DN consisting of only the CN and comparing it to the 
		   request DN.  We use sizeofDN() rather than compareDN() since it's 
		   much faster than a full DN comparison, this is safe because we 
		   know that both contain at least the same CN so any size mismatch 
		   indicates a DN value mismatch */
		status = insertDNComponent( &tempDN, CRYPT_CERTINFO_COMMONNAME,
									commonName, commonNameLength,
									&certInfoPtr->errorType );

⌨️ 快捷键说明

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