Example #1
0
static int readProtAlgoInfo( INOUT STREAM *stream, 
							 OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,
							 OUT_INT_SHORT_Z int *keySize )
	{
	const OID_INFO *oidInfoPtr;
	const PKCS12_ALGO_MAP *algoMapInfoPtr;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
	assert( isWritePtr( keySize, sizeof( int ) ) );

	/* Clear return values */
	*cryptAlgo = CRYPT_ALGO_NONE;
	*keySize = 0;

	/* Read the wrapper and the protection algorithm OID and extract the
	   protection information parameters for it */
	readSequence( stream, NULL );
	status = readOIDEx( stream, encryptionOIDinfo, 
						FAILSAFE_ARRAYSIZE( encryptionOIDinfo, OID_INFO ), 
						&oidInfoPtr );
	if( cryptStatusError( status ) )
		return( status );
	algoMapInfoPtr = oidInfoPtr->extraInfo;
	*cryptAlgo = algoMapInfoPtr->cryptAlgo;
	*keySize = algoMapInfoPtr->keySize;

	return( CRYPT_OK );
	}
Example #2
0
int hwGetCapabilities( const CAPABILITY_INFO **capabilityInfo,
					   int *noCapabilities )
	{
	assert( isReadPtr( capabilityInfo, sizeof( CAPABILITY_INFO * ) ) );
	assert( isWritePtr( noCapabilities, sizeof( int ) ) );

	*capabilityInfo = capabilities;
	*noCapabilities = FAILSAFE_ARRAYSIZE( capabilities, CAPABILITY_INFO );

	return( CRYPT_OK );
	}
Example #3
0
static int loadECCparams( INOUT CONTEXT_INFO *contextInfoPtr )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	const ECC_DOMAIN_PARAMS *eccParams = NULL;
	int curveSize, i, bnStatus = BN_STATUS;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	/* Find the parameter info for this curve */
	for( i = 0; domainParamTbl[ i ].paramType != CRYPT_ECCCURVE_NONE && \
				i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ); 
		 i++ )
		{
		if( domainParamTbl[ i ].paramType == pkcInfo->curveType )
			{
			eccParams = &domainParamTbl[ i ];
			break;
			}
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ) );
	ENSURES( eccParams != NULL );

	/* For the named curve the key size is defined by exective fiat based
	   on the curve type rather than being taken from the public-key value 
	   (which in this case is the magnitude of the point Q on the curve), so 
	   we set it explicitly based on the curve type */
	pkcInfo->keySizeBits = eccParams->curveSizeBits;
	curveSize = bitsToBytes( eccParams->curveSizeBits );

	/* Load the parameters into the context bignums */
	CKPTR( BN_bin2bn( eccParams->p, curveSize, &pkcInfo->eccParam_p ) );
	CKPTR( BN_bin2bn( eccParams->a, curveSize, &pkcInfo->eccParam_a ) );
	CKPTR( BN_bin2bn( eccParams->b, curveSize, &pkcInfo->eccParam_b ) );
	CKPTR( BN_bin2bn( eccParams->gx, curveSize, &pkcInfo->eccParam_gx ) );
	CKPTR( BN_bin2bn( eccParams->gy, curveSize, &pkcInfo->eccParam_gy ) );
	CKPTR( BN_bin2bn( eccParams->n, curveSize, &pkcInfo->eccParam_n ) );
	CKPTR( BN_bin2bn( eccParams->h, curveSize, &pkcInfo->eccParam_h ) );

	return( getBnStatus( bnStatus ) );
	}
Example #4
0
int getKeyTypeTag( IN_HANDLE_OPT const CRYPT_CONTEXT cryptContext,
				   IN_ALGO_OPT const CRYPT_ALGO_TYPE cryptAlgo,
				   OUT int *tag )
	{
	static const MAP_TABLE tagMapTbl[] = {
		{ CRYPT_ALGO_RSA, 100 },
		{ CRYPT_ALGO_DH, CTAG_PK_DH },
		{ CRYPT_ALGO_ELGAMAL, CTAG_PK_DH },
		{ CRYPT_ALGO_DSA, CTAG_PK_DSA },
		{ CRYPT_ALGO_ECDSA, CTAG_PK_ECC },
		{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
		};
	int keyCryptAlgo, value, status;

	REQUIRES( ( isHandleRangeValid( cryptContext ) && \
				cryptAlgo == CRYPT_ALGO_NONE ) || \
			  ( cryptContext == CRYPT_UNUSED && \
				isPkcAlgo( cryptAlgo ) ) );

	/* Clear return value */
	*tag = 0;

	/* If the caller hasn't already supplied the algorithm details, get them
	   from the context */
	if( cryptAlgo != CRYPT_ALGO_NONE )
		keyCryptAlgo = cryptAlgo;
	else
		{
		status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
								  &keyCryptAlgo, CRYPT_CTXINFO_ALGO );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Map the algorithm to the corresponding tag.  We have to be a bit 
	   careful with the tags because the out-of-band special-case value 
	   DEFAULT_TAG looks like an error value, so we supply a dummy value
	   of '100' for this tag and map it back to DEFAULT_TAG when we return
	   it to the caller */
	status = mapValue( keyCryptAlgo, &value, tagMapTbl, 
					   FAILSAFE_ARRAYSIZE( tagMapTbl, MAP_TABLE ) );
	ENSURES( cryptStatusOK( status ) );
	*tag = ( value == 100 ) ? DEFAULT_TAG : value;

	return( CRYPT_OK );
	}
Example #5
0
int setDeviceHardware( INOUT DEVICE_INFO *deviceInfo )
	{
	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );

	deviceInfo->initFunction = initFunction;
	deviceInfo->shutdownFunction = shutdownFunction;
	deviceInfo->controlFunction = controlFunction;
	deviceInfo->getItemFunction = getItemFunction;
	deviceInfo->setItemFunction = setItemFunction;
	deviceInfo->deleteItemFunction = deleteItemFunction;
	deviceInfo->getFirstItemFunction = getFirstItemFunction;
	deviceInfo->getNextItemFunction = getNextItemFunction;
	deviceInfo->getRandomFunction = getRandomFunction;
	deviceInfo->capabilityInfoList = capabilityInfoList;
	deviceInfo->mechanismFunctions = mechanismFunctions;
	deviceInfo->mechanismFunctionCount = \
		FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );

	return( CRYPT_OK );
	}
Example #6
0
		{ CRYPT_IATTRIBUTE_KEY_SPKI, KEYFORMAT_CERT },
		{ CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL, KEYFORMAT_CERT },
		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
		};
	int value, status;

	assert( isWritePtr( keyformat, sizeof( KEYFORMAT_TYPE ) ) );

	REQUIRES( isAttribute( attribute ) || \
			  isInternalAttribute( attribute ) );

	/* Clear return value */
	*keyformat = KEYFORMAT_NONE;

	status = mapValue( attribute, &value, attributeMapTbl, 
					   FAILSAFE_ARRAYSIZE( attributeMapTbl, MAP_TABLE ) );
	ENSURES( cryptStatusOK( status ) );
	*keyformat = value;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Key Parameter Handling Functions					*
*																			*
****************************************************************************/

/* Initialise crypto parameters such as the IV and encryption mode, shared 
   by most capabilities.  This is never called directly, but is accessed
   through function pointers in the capability lists */
static int processAdditionalScepRequest( INOUT SESSION_INFO *sessionInfoPtr,
										 const HTTP_URI_INFO *httpReqInfo )
	{
	HTTP_URI_INFO rewrittenHttpReqInfo;
	MESSAGE_DATA msgData;
	int operationType, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( isReadPtr( httpReqInfo, sizeof( HTTP_URI_INFO ) ) );

	/* If the client has fed us an HTTP GET request, find out what they  
	   want.  SCEP's handling of HTTP requests is a bit different from the 
	   "attribute '=' value" lookup that's normally used for HTTP data 
	   retrieval.  Instead, it uses the format 
	   "'operation =' value '&' extraData", with the search key buried in 
	   the 'extraData' value.  In addition the content of the 'extraData' 
	   value isn't defined outside of "any string which is understood by the 
	   CA".  However since 'value' defines what we want, we can determine 
	   what to return based on this and ignore the 'extraData' portion.

	   In order to fix up the query information into a format that works 
	   with standard HTTP queries, we rewrite the query data from the 
	   "'operation =' value '&' extraData" form into "attribute '=' value" 
	   before we process the query */
	memset( &rewrittenHttpReqInfo, 0, sizeof( HTTP_URI_INFO ) );
	memcpy( rewrittenHttpReqInfo.attribute, httpReqInfo->value, 
			httpReqInfo->valueLen );
	rewrittenHttpReqInfo.attributeLen = httpReqInfo->valueLen;
	if( httpReqInfo->extraDataLen > 0 )
		{
		memcpy( rewrittenHttpReqInfo.value, httpReqInfo->extraData, 
				httpReqInfo->extraDataLen );
		rewrittenHttpReqInfo.valueLen = httpReqInfo->extraDataLen;
		}
	status = processCertQuery( sessionInfoPtr, &rewrittenHttpReqInfo,
							   certstoreReadInfo, 
							   FAILSAFE_ARRAYSIZE( certstoreReadInfo, \
												   CERTSTORE_READ_INFO ),
							   &operationType, NULL, 0, NULL );
	if( cryptStatusError( status ) )
		{
		sendCertErrorResponse( sessionInfoPtr, status );
		return( status );
		}
	ENSURES( operationType == SCEP_OPERATION_GETCACAPS || \
			 operationType == SCEP_OPERATION_GETCACERT || \
			 operationType == SCEP_OPERATION_GETCACERTCHAIN );

	/* If it's a CA capabilities query, return the information as raw text
	   over HTTP */
	if( operationType == SCEP_OPERATION_GETCACAPS )
		{
		STREAM stream;

		sMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 );
		status = swrite( &stream, "POSTPKIOperation\n", 17 );
		if( algoAvailable( CRYPT_ALGO_SHA1 ) )
			status = swrite( &stream, "SHA-1\n", 6 );
		if( algoAvailable( CRYPT_ALGO_SHA2 ) )
			status = swrite( &stream, "SHA-256\n", 8 );
		if( algoAvailable( CRYPT_ALGO_SHAng ) )
			status = swrite( &stream, "SHAng\n", 6 );
		if( algoAvailable( CRYPT_ALGO_3DES ) )
			status = swrite( &stream, "DES3\n", 5 );
		if( algoAvailable( CRYPT_ALGO_AES ) )
			status = swrite( &stream, "AES\n", 4 );
		if( cryptStatusOK( status ) )
			sessionInfoPtr->receiveBufEnd = stell( &stream );
		sMemDisconnect( &stream );
		ENSURES( cryptStatusOK( status ) );
		return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE,
								  SCEP_CONTENT_TYPE_LEN ) );
		}

	/* Export the CA certificate and send it to the client */
	setMessageData( &msgData, sessionInfoPtr->receiveBuffer,
					sessionInfoPtr->receiveBufSize );
	status = krnlSendMessage( sessionInfoPtr->privateKey,
							  IMESSAGE_CRT_EXPORT, &msgData,
							  ( operationType == SCEP_OPERATION_GETCACERT ) ? \
								CRYPT_CERTFORMAT_CERTIFICATE : \
								CRYPT_CERTFORMAT_CERTCHAIN );
	if( cryptStatusError( status ) )
		{
		retExt( status,
				( status, SESSION_ERRINFO, 
				  "Couldn't export CA certificate%s for '%s' request", 
				  ( operationType == SCEP_OPERATION_GETCACERT ) ? \
					"" : " chain",
				  ( operationType == SCEP_OPERATION_GETCACERT ) ? \
					"GetCACert" : "GetCACertChain" ) );
		}
	sessionInfoPtr->receiveBufEnd = msgData.length;
	if( operationType == SCEP_OPERATION_GETCACERT )
		{
		return( writePkiDatagram( sessionInfoPtr, 
								  SCEP_CONTENT_TYPE_GETCACERT,
								  SCEP_CONTENT_TYPE_GETCACERT_LEN ) );
		}
	return( writePkiDatagram( sessionInfoPtr, 
							  SCEP_CONTENT_TYPE_GETCACERTCHAIN,
							  SCEP_CONTENT_TYPE_GETCACERTCHAIN_LEN ) );
	}
Example #8
0
int initKeymgmtACL( INOUT KERNEL_DATA *krnlDataPtr )
	{
	int i;

	assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );

	/* If we're running a fuzzing build, skip the lengthy self-checks */
#ifdef CONFIG_FUZZ
	krnlData = krnlDataPtr;
	return( CRYPT_OK );
#endif /* CONFIG_FUZZ */

	/* Perform a consistency check on the key management ACLs */
	for( i = 0; keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE && \
				i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ); 
		 i++ )
		{
		const KEYMGMT_ACL *keyMgmtACL = &keyManagementACL[ i ];
		int j;

		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
			( keyMgmtACL->keysetR_subTypeB & ( SUBTYPE_CLASS_A | \
											   SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->keysetR_subTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
			keyMgmtACL->keysetR_subTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
			( keyMgmtACL->keysetW_subTypeB & ( SUBTYPE_CLASS_A | \
											   SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->keysetW_subTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
			keyMgmtACL->keysetW_subTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
			( keyMgmtACL->keysetD_subTypeB & ( SUBTYPE_CLASS_A | \
											   SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->keysetD_subTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
			keyMgmtACL->keysetD_subTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
			( keyMgmtACL->keysetFN_subTypeB & ( SUBTYPE_CLASS_A | \
											    SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->keysetFN_subTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
			keyMgmtACL->keysetFN_subTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
			( keyMgmtACL->keysetQ_subTypeB & ( SUBTYPE_CLASS_A | \
											   SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->keysetQ_subTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY ) ) != 0 || \
			keyMgmtACL->keysetQ_subTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( ( keyMgmtACL->objSubTypeA & ( SUBTYPE_CLASS_B | \
										  SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->objSubTypeA & \
				~( SUBTYPE_CLASS_A | ST_CERT_ANY | ST_CTX_PKC | \
									 ST_CTX_CONV ) ) != 0 || \
			keyMgmtACL->objSubTypeB != ST_NONE || \
			keyMgmtACL->objSubTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		ENSURES( keyMgmtACL->allowedKeyIDs != NULL );
		for( j = 0; keyMgmtACL->allowedKeyIDs[ j ] != CRYPT_KEYID_NONE && \
					j < FAILSAFE_ITERATIONS_SMALL; j++ )
			{
			ENSURES( keyMgmtACL->allowedKeyIDs[ j ] > CRYPT_KEYID_NONE && \
					 keyMgmtACL->allowedKeyIDs[ j ] < CRYPT_KEYID_LAST );
			}
		ENSURES( j < FAILSAFE_ITERATIONS_SMALL );

		ENSURES( keyMgmtACL->allowedFlags >= KEYMGMT_FLAG_NONE && \
				 keyMgmtACL->allowedFlags < KEYMGMT_FLAG_MAX );

		if( keyMgmtACL->specificKeysetSubTypeA != ST_NONE || \
			( keyMgmtACL->specificKeysetSubTypeB & ( SUBTYPE_CLASS_A | \
													 SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->specificKeysetSubTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI ) ) != 0 || \
			keyMgmtACL->specificKeysetSubTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}

		if( ( keyMgmtACL->specificObjSubTypeA & ( SUBTYPE_CLASS_B | \
												  SUBTYPE_CLASS_C ) ) || \
			( keyMgmtACL->specificObjSubTypeA & \
				~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) != 0 || \
			keyMgmtACL->specificObjSubTypeB != ST_NONE || \
			keyMgmtACL->specificObjSubTypeC != ST_NONE )
			{
			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
			retIntError();
			}
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ) );

	/* Perform a consistency check on the supplementary ID ACLs */
	for( i = 0; idTypeACL[ i ].idType != CRYPT_KEYID_NONE && \
				i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ); 
		 i++ )
		{
		const IDTYPE_ACL *idACL = &idTypeACL[ i ];

		ENSURES( idACL->idType > CRYPT_KEYID_NONE && \
				 idACL->idType < CRYPT_KEYID_LAST );

		if( ( idACL->keysetSubTypeB & \
				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 )
			{
			DEBUG_DIAG(( "Key management supplementary ACLs inconsistent" ));
			retIntError();
			}
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ) );

	/* Set up the reference to the kernel data block */
	krnlData = krnlDataPtr;

	return( CRYPT_OK );
	}
Example #9
0
static int processAdditionalScepRequest( INOUT SESSION_INFO *sessionInfoPtr,
										 const HTTP_URI_INFO *httpReqInfo )
	{
	HTTP_URI_INFO rewrittenHttpReqInfo;
	MESSAGE_DATA msgData;
	int operationType, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( isReadPtr( httpReqInfo, sizeof( HTTP_URI_INFO ) ) );

	/* If the client has fed us an HTTP GET request, find out what they  
	   want.  SCEP's handling of HTTP requests is a bit different from the 
	   "attribute '=' value" lookup that's normally used for HTTP data 
	   retrieval.  Instead, it uses the format 
	   "'operation =' value '&' extraData", with the search key buried in 
	   the 'extraData' value.  In addition the content of the 'extraData' 
	   value isn't defined outside of "any string which is understood by the 
	   CA".  However since 'value' defines what we want, we can determine 
	   what to return based on this and ignore the 'extraData' portion.

	   In order to fix up the query information into a format that works 
	   with standard HTTP queries, we rewrite the query data from the 
	   "'operation =' value '&' extraData" form into "attribute '=' value" 
	   before we process the query */
	memset( &rewrittenHttpReqInfo, 0, sizeof( HTTP_URI_INFO ) );
	memcpy( rewrittenHttpReqInfo.attribute, httpReqInfo->value, 
			httpReqInfo->valueLen );
	rewrittenHttpReqInfo.attributeLen = httpReqInfo->valueLen;
	if( httpReqInfo->extraDataLen > 0 )
		{
		memcpy( rewrittenHttpReqInfo.value, httpReqInfo->extraData, 
				httpReqInfo->extraDataLen );
		rewrittenHttpReqInfo.valueLen = httpReqInfo->extraDataLen;
		}
	status = processCertQuery( sessionInfoPtr, &rewrittenHttpReqInfo,
							   certstoreReadInfo, 
							   FAILSAFE_ARRAYSIZE( certstoreReadInfo, \
												   CERTSTORE_READ_INFO ),
							   &operationType, NULL, 0, NULL );
	if( cryptStatusError( status ) )
		{
		sendCertErrorResponse( sessionInfoPtr, status );
		return( status );
		}
	ENSURES( operationType == SCEP_OPERATION_GETCACAPS || \
			 operationType == SCEP_OPERATION_GETCACERT || \
			 operationType == SCEP_OPERATION_GETCACERTCHAIN );

	/* If it's a CA capabilities query, return the information as raw text
	   over HTTP */
	if( operationType == SCEP_OPERATION_GETCACAPS )
		{
		STREAM stream;

		sMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 );
		swrite( &stream, "POSTPKIOperation\n", 17 );
#if 0	/* 14/6/14 Too risky to implement given its current state in the 
				   spec, see the discussion on the JSCEP mailing list for
				   details */
		status = swrite( &stream, "Renewal\n", 8 );
#endif /* 0 */
		if( algoAvailable( CRYPT_ALGO_SHA1 ) )
			status = swrite( &stream, "SHA-1\n", 6 );
		if( algoAvailable( CRYPT_ALGO_SHA2 ) )
			status = swrite( &stream, "SHA-256\n", 8 );
		if( algoAvailable( CRYPT_ALGO_SHAng ) )
			status = swrite( &stream, "SHAng\n", 6 );
		if( algoAvailable( CRYPT_ALGO_3DES ) )
			status = swrite( &stream, "DES3\n", 5 );
		if( algoAvailable( CRYPT_ALGO_AES ) )
			status = swrite( &stream, "AES\n", 4 );
		if( cryptStatusOK( status ) )
			sessionInfoPtr->receiveBufEnd = stell( &stream );
		sMemDisconnect( &stream );
		ENSURES( cryptStatusOK( status ) );
		return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, 
								  SCEP_CONTENT_TYPE_LEN ) );
		}
Example #10
0
CHECK_RETVAL_BOOL \
BOOLEAN isGeneralNameSelectionComponent( IN_ATTRIBUTE \
											const CRYPT_ATTRIBUTE_TYPE certInfoType )
	{
	static const CRYPT_ATTRIBUTE_TYPE certGeneralNameTbl[] = {
		CRYPT_CERTINFO_AUTHORITYINFO_RTCS, 
		CRYPT_CERTINFO_AUTHORITYINFO_OCSP,
		CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS, 
		CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE,
		CRYPT_CERTINFO_AUTHORITYINFO_CRLS,
		CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY,
		CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING,
		CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY,
		CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY,
		CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST,
		CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT,
		CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR,
		CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY,
		CRYPT_CERTINFO_SUBJECTALTNAME,
		CRYPT_CERTINFO_ISSUERALTNAME,
		CRYPT_CERTINFO_ISSUINGDIST_FULLNAME,
		CRYPT_CERTINFO_CERTIFICATEISSUER,
		CRYPT_CERTINFO_PERMITTEDSUBTREES,
		CRYPT_CERTINFO_EXCLUDEDSUBTREES,
		CRYPT_CERTINFO_CRLDIST_FULLNAME,
		CRYPT_CERTINFO_CRLDIST_CRLISSUER,
		CRYPT_CERTINFO_AUTHORITY_CERTISSUER,
		CRYPT_CERTINFO_FRESHESTCRL_FULLNAME,
		CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER,
		CRYPT_CERTINFO_DELTAINFO_LOCATION,
		CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER,
		CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER,
		CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME,
		CRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE 
		};
	static const CRYPT_ATTRIBUTE_TYPE cmsGeneralNameTbl[] = {
		CRYPT_CERTINFO_CMS_RECEIPT_TO,
		CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF,
		CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO,
		CRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE 
		};
	const CRYPT_ATTRIBUTE_TYPE *generalNameTbl;
	int generalNameTblSize, i;

	REQUIRES_B( isAttribute( certInfoType ) || \
				isInternalAttribute( certInfoType ) );

	/* Determine which type of attribute we're dealing with */
	if( certInfoType >= CRYPT_CERTINFO_FIRST_EXTENSION && \
		certInfoType <= CRYPT_CERTINFO_LAST_EXTENSION )
		{
		generalNameTbl = certGeneralNameTbl;
		generalNameTblSize = FAILSAFE_ARRAYSIZE( certGeneralNameTbl, \
												 CRYPT_ATTRIBUTE_TYPE );
		}
	else
		{
		if( certInfoType >= CRYPT_CERTINFO_FIRST_CMS && \
			certInfoType <= CRYPT_CERTINFO_LAST_CMS )
			{
			generalNameTbl = cmsGeneralNameTbl;
			generalNameTblSize = FAILSAFE_ARRAYSIZE( cmsGeneralNameTbl, \
													 CRYPT_ATTRIBUTE_TYPE );
			}
		else
			{
			/* It's neither a certificate nor a CMS attribute extension, it
			   can't be a GeneralName */
			return( FALSE );
			}
		}

	/* Check for membership in the GeneralName set.  In theory we could 
	   divide this further via binary search but we're really reaching the 
	   law of diminishing returns here */
	for( i = 0; i < generalNameTblSize && \
				generalNameTbl[ i ] != CRYPT_ATTRIBUTE_NONE; i++ )
		{
		if( generalNameTbl[ i ] == certInfoType )
			return( TRUE );
		}
	ENSURES_B( i < generalNameTblSize );

	return( FALSE );
	}
Example #11
0
BOOLEAN checkAttributesConsistent( INOUT SESSION_INFO *sessionInfoPtr,
								   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )
	{
	static const MAP_TABLE excludedAttrTbl[] = {
		{ CRYPT_SESSINFO_REQUEST, 
			CHECK_ATTR_REQUEST | CHECK_ATTR_PRIVKEY | CHECK_ATTR_PRIVKEYSET },
		{ CRYPT_SESSINFO_PRIVATEKEY,
			CHECK_ATTR_PRIVKEY | CHECK_ATTR_PRIVKEYSET },
		{ CRYPT_SESSINFO_CACERTIFICATE, 
			CHECK_ATTR_CACERT | CHECK_ATTR_FINGERPRINT },
		{ CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1, 
			CHECK_ATTR_FINGERPRINT | CHECK_ATTR_CACERT },
		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 } 
		};
	int flags = 0, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	
	REQUIRES_B( attribute == CRYPT_SESSINFO_REQUEST || \
				attribute == CRYPT_SESSINFO_PRIVATEKEY || \
				attribute == CRYPT_SESSINFO_CACERTIFICATE || \
				attribute == CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );

	/* Find the excluded-attribute information for this attribute */
	status = mapValue( attribute, &flags, excludedAttrTbl,
					   FAILSAFE_ARRAYSIZE( excludedAttrTbl, MAP_TABLE ) );
	ENSURES( cryptStatusOK( status  ) );

	/* Make sure that none of the excluded attributes are present */
	if( ( flags & CHECK_ATTR_REQUEST ) && \
		sessionInfoPtr->iCertRequest != CRYPT_ERROR )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( FALSE );
		}
	if( ( flags & CHECK_ATTR_PRIVKEYSET ) && \
		sessionInfoPtr->privKeyset != CRYPT_ERROR )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( FALSE );
		}
	if( ( flags & CHECK_ATTR_CACERT ) && \
		sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CACERTIFICATE,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( FALSE );
		}
	if( ( flags & CHECK_ATTR_FINGERPRINT ) && \
		findSessionInfo( sessionInfoPtr->attributeList,
						 CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 ) != NULL )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( FALSE );
		}
	
	return( TRUE );
	}
Example #12
0
			option.  (GCM with ECC is a variant of this, this is even more 
			of a fashion statement and really only makes sense with ECC).
	DH suites unless PREFER_RSA_TO_DH is defined, since these provide
			PFS, are secure against factoring attacks, and in many cases
			are the same as RSA when employed in anon-DH-equivalent mode.
	RSA suites with strong ciphers.
	Misc RSA suites with also-ran ciphers.
	Canary used to detect broken older version of MSIE */

typedef struct {
	const CIPHERSUITE_INFO *cipherSuites;
	const int cipherSuiteCount;
	} CIPHERSUITES_LIST;

static const CIPHERSUITES_LIST cipherSuitesList[] = {
	{ cipherSuitePSK, FAILSAFE_ARRAYSIZE( cipherSuitePSK, CIPHERSUITE_INFO ) },
#if defined( PREFER_ECC ) && defined( USE_ECDH ) && defined( USE_ECDSA )
  #ifdef USE_GCM
	{ cipherSuiteGCM, FAILSAFE_ARRAYSIZE( cipherSuiteGCM, CIPHERSUITE_INFO ) },
  #endif /* USE_GCM */
	{ cipherSuiteECC, FAILSAFE_ARRAYSIZE( cipherSuiteECC, CIPHERSUITE_INFO ) },
#endif /* PREFER_ECC && USE_ECDH && USE_ECDSA */
#ifdef PREFER_RSA_TO_DH
	{ cipherSuiteRSA, FAILSAFE_ARRAYSIZE( cipherSuiteRSA, CIPHERSUITE_INFO ) },
	{ cipherSuiteDH, FAILSAFE_ARRAYSIZE( cipherSuiteDH, CIPHERSUITE_INFO ) },
#else
	{ cipherSuiteDH, FAILSAFE_ARRAYSIZE( cipherSuiteDH, CIPHERSUITE_INFO ) },
	{ cipherSuiteRSA, FAILSAFE_ARRAYSIZE( cipherSuiteRSA, CIPHERSUITE_INFO ) },
#endif /* PREFER_RSA_TO_DH */
#if !defined( PREFER_ECC ) && defined( USE_ECDH ) && defined( USE_ECDSA )
  #ifdef USE_GCM
Example #13
0
static int processCertWrapper( INOUT STREAM *stream, 
							   OUT_LENGTH_SHORT_Z int *objectOffset, 
							   OUT_DATALENGTH_Z int *objectLength, 
							   IN_DATALENGTH_Z const int objectStartPos )
	{
	static const CMS_CONTENT_INFO FAR_BSS oidInfoSignedData = { 1, 3 };
	static const OID_INFO FAR_BSS signedDataOIDinfo[] = {
		{ OID_CMS_SIGNEDDATA, CRYPT_OK, &oidInfoSignedData },
		{ NULL, 0 }, { NULL, 0 }
		};
	static const OID_INFO FAR_BSS dataOIDinfo[] = {
		{ OID_CMS_DATA, CRYPT_OK, NULL },
		{ NULL, 0 }, { NULL, 0 }
		};
	long length;
	int setLength, localLength, offset DUMMY_INIT, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( objectOffset, sizeof( int ) ) );
	assert( isWritePtr( objectLength, sizeof( int ) ) );

	REQUIRES( objectStartPos >= 0 && objectStartPos < MAX_BUFFER_SIZE );

	/* Clear return values */
	*objectOffset = *objectLength = 0;

	/* Read the SignedData wrapper */
	sseek( stream, objectStartPos );
	status = readCMSheader( stream, signedDataOIDinfo, 
							FAILSAFE_ARRAYSIZE( signedDataOIDinfo, OID_INFO ), 
							&length, READCMS_FLAG_NONE );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the SET OF DigestAlgorithmIdentifier, empty for a pure 
	   certificate chain, nonempty for signed data or buggy certificate 
	   chains */
	status = readSet( stream, &setLength );
	if( cryptStatusOK( status ) && setLength > 0 )
		status = sSkip( stream, setLength, MAX_INTLENGTH_SHORT );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the ContentInfo information */
	status = readCMSheader( stream, dataOIDinfo, 
							FAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ), 
							&length, READCMS_FLAG_INNERHEADER );
	if( cryptStatusError( status ) )
		return( status );

	/* If we've been fed signed data (i.e. the ContentInfo has the content 
	   field present), skip the content to get to the certificate chain */
	if( length > 0 )
		{
		status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		{
		/* If we have an indefinite length then there could be up to three 
		   EOCs present (one for each of the SEQUENCE, [0], and OCTET 
		   STRING), which we have to skip.  In theory there could be content
		   present as well but at that point we're going to be replicating
		   large chunks of the de-enveloping code so we only try and process
		   zero-length content, created by some buggy browser's cert-export
		   code (possibly Firefox)  */
		if( length == CRYPT_UNUSED )
			{
			int i;

			for( i = 0; i < 3; i++ )
				{
				status = checkEOC( stream );
				if( cryptStatusError( status ) )
					return( status );
				if( !status )
					break;
				}
			}
		}

	/* We've reached the inner content encapsulation, find out how long the 
	   content (i.e. the chain of certificates) is */
	status = getStreamObjectLength( stream, &localLength );
	if( cryptStatusOK( status ) )
		{
		offset = stell( stream );
		status = readConstructedI( stream, NULL, 0 );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Adjust for the [0] { ... } wrapper that contains the list of 
	   certificate, returning a pointer to the collection of certificates
	   without any encapsulation */
	localLength -= stell( stream ) - offset;
	if( localLength < MIN_CERTSIZE || localLength >= MAX_INTLENGTH )
		return( CRYPT_ERROR_BADDATA );
	*objectOffset = stell( stream );
	*objectLength = localLength;
	
	return( CRYPT_OK );
	}
Example #14
0
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( objectOffset, sizeof( int ) ) );
	assert( isWritePtr( objectLength, sizeof( int ) ) );
	assert( isWritePtr( objectType, sizeof( CRYPT_CERTTYPE_TYPE ) ) );

	REQUIRES( formatHint >= CRYPT_CERTTYPE_NONE && \
			  formatHint < CRYPT_CERTTYPE_LAST );

	/* Clear return values */
	*objectOffset = *objectLength = 0;
	*objectType = CRYPT_CERTTYPE_NONE;

	/* Figure out how much data we need to have for a minimum-length 
	   object */
	status = mapValue( formatHint, &minLength, minLengthMapTable,
					   FAILSAFE_ARRAYSIZE( minLengthMapTable, MAP_TABLE ) );
	ENSURES( cryptStatusOK( status ) );

	/* If it's an SSL certificate chain then there's no recognisable 
	   tagging, however the caller will have told us what it is */
	if( formatHint == CRYPT_ICERTTYPE_SSL_CERTCHAIN )
		{
		*objectLength = sMemDataLeft( stream );
		*objectType = CRYPT_ICERTTYPE_SSL_CERTCHAIN;
		return( CRYPT_OK );
		}

	/* Check whether we need to process the object wrapper using context-
	   specific tagging rather than the usual SEQUENCE */
	status = tag = peekTag( stream );
	if( cryptStatusError( status ) )
Example #15
0
static CAPABILITY_INFO *getCapability( const DEVICE_INFO *deviceInfo,
									   const PKCS11_MECHANISM_INFO *mechanismInfoPtr,
									   const int maxMechanisms )
	{
	VARIABLE_CAPABILITY_INFO *capabilityInfo;
	CK_MECHANISM_INFO pMechanism;
	CK_RV status;
	const CRYPT_ALGO_TYPE cryptAlgo = mechanismInfoPtr->cryptAlgo;
	const BOOLEAN isPKC = isPkcAlgo( cryptAlgo ) ? TRUE : FALSE;
	const CK_FLAGS keyGenFlag = isPKC ? CKF_GENERATE_KEY_PAIR : CKF_GENERATE;
	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
	int hardwareOnly, i, iterationCount;

	assert( isReadPtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
	assert( isReadPtr( mechanismInfoPtr, \
					   maxMechanisms * sizeof( PKCS11_MECHANISM_INFO ) ) );

	/* Set up canary values for the mechanism information in case the driver
	   blindly reports success for every mechanism that we ask for */
	memset( &pMechanism, 0, sizeof( CK_MECHANISM_INFO ) );
	pMechanism.ulMinKeySize = 0xA5A5;
	pMechanism.ulMaxKeySize = 0x5A5A;

	/* Get the information for this mechanism.  Since many PKCS #11 drivers
	   implement some of their capabilities using God knows what sort of 
	   software implementation, we provide the option to skip emulated 
	   mechanisms if required */
	status = C_GetMechanismInfo( pkcs11Info->slotID, 
								 mechanismInfoPtr->mechanism,
								 &pMechanism );
	if( status != CKR_OK )
		return( NULL );
	if( pMechanism.ulMinKeySize == 0xA5A5 && \
		pMechanism.ulMaxKeySize == 0x5A5A )
		{
		/* The driver reported that this mechanism is available but didn't
		   update the mechanism information, it's lying */
		DEBUG_DIAG(( "Driver reports that mechanism %X is available even "
					 "though it isn't", mechanismInfoPtr->mechanism ));
		assert( DEBUG_WARN );
		return( NULL );
		}
	status = krnlSendMessage( deviceInfo->ownerHandle, IMESSAGE_GETATTRIBUTE, 
							  &hardwareOnly, 
							  CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY );
	if( cryptStatusOK( status ) && hardwareOnly && \
		!( pMechanism.flags & CKF_HW ) )
		{
		DEBUG_DIAG(( "Skipping mechanism %X, which is only available in "
					 "software emulation", mechanismInfoPtr->mechanism ));
		return( NULL );
		}
	if( mechanismInfoPtr->requiredFlags != CKF_NONE )
		{
		/* Make sure that the driver flags indicate support for the specific 
		   functionality that we require */
		if( ( mechanismInfoPtr->requiredFlags & \
			  pMechanism.flags ) != mechanismInfoPtr->requiredFlags )
			{
			DEBUG_DIAG(( "Driver reports that mechanism %X only has "
						 "capabilities %lX when we require %lX", 
						 mechanismInfoPtr->mechanism, 
						 mechanismInfoPtr->requiredFlags & pMechanism.flags,
						 mechanismInfoPtr->requiredFlags ));
//////////////////////////////////
// Kludge to allow it to be used
//////////////////////////////////
//			assert( DEBUG_WARN );
//			return( NULL );
			}
		}

	/* Copy across the template for this capability */
	if( ( capabilityInfo = clAlloc( "getCapability", \
									sizeof( CAPABILITY_INFO ) ) ) == NULL )
		return( NULL );
	for( i = 0; capabilityTemplates[ i ].cryptAlgo != cryptAlgo && \
				capabilityTemplates[ i ].cryptAlgo != CRYPT_ERROR && \
				i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ); 
		 i++ );
	ENSURES_N( i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ) );
	ENSURES_N( capabilityTemplates[ i ].cryptAlgo != CRYPT_ERROR );
	memcpy( capabilityInfo, &capabilityTemplates[ i ],
			sizeof( CAPABILITY_INFO ) );

	/* Set up the keysize information if there's anything useful available */
	if( keysizeValid( cryptAlgo ) )
		{
		int minKeySize = ( int ) pMechanism.ulMinKeySize;
		int maxKeySize = ( int ) pMechanism.ulMaxKeySize;

		/* Adjust the key size to bytes and make sure that all values are 
		   consistent.  Some implementations report silly bounds (e.g. 1-bit 
		   RSA, "You naughty minKey" or alternatively 4Gbit RSA) so we 
		   adjust them to a sane value if necessary.  We also limit the 
		   maximum key size to match the cryptlib native maximum key size, 
		   both for consistency and because cryptlib performs buffer 
		   allocation based on the maximum native buffer size */
		if( pMechanism.ulMinKeySize < 0 || \
			pMechanism.ulMinKeySize >= 10000L )
			{
			DEBUG_DIAG(( "Driver reports invalid minimum key size %lu for "
						 "%s algorithm", pMechanism.ulMinKeySize,
						 capabilityInfo->algoName ));
			assert( DEBUG_WARN );
			minKeySize = 0;
			}
		if( pMechanism.ulMaxKeySize < 0 || \
			pMechanism.ulMaxKeySize >= 100000L )
			{
			DEBUG_DIAG(( "Driver reports invalid maximum key size %lu for "
						 "%s algorithm", pMechanism.ulMaxKeySize,
						 capabilityInfo->algoName ));
			assert( DEBUG_WARN );
			maxKeySize = 0;
			}
		if( !keysizeInBytes( cryptAlgo ) )
			{
			minKeySize = bitsToBytes( minKeySize );
			maxKeySize = bitsToBytes( maxKeySize );
			}
		if( minKeySize > capabilityInfo->minKeySize )
			capabilityInfo->minKeySize = minKeySize;
		if( capabilityInfo->keySize < capabilityInfo->minKeySize )
			capabilityInfo->keySize = capabilityInfo->minKeySize;
		capabilityInfo->maxKeySize = min( maxKeySize, 
										  capabilityInfo->maxKeySize );
		if( capabilityInfo->maxKeySize < capabilityInfo->minKeySize )
			{
			/* Serious braindamage in the driver, we'll just have to make
			   a sensible guess */
			DEBUG_DIAG(( "Driver reports maximum key size %d < minimum key "
						 "size %d for %s algorithm", 
						 capabilityInfo->maxKeySize, 
						 capabilityInfo->minKeySize, 
						 capabilityInfo->algoName ));
			assert( DEBUG_WARN );
			if( isPKC )
				{
				capabilityInfo->maxKeySize = \
					max( capabilityInfo->minKeySize, bitsToBytes( 2048 ) );
				}
			else
				capabilityInfo->maxKeySize = 16;
			}
		if( capabilityInfo->keySize > capabilityInfo->maxKeySize )
			capabilityInfo->keySize = capabilityInfo->maxKeySize;
		capabilityInfo->endFunction = genericEndFunction;
		}

	/* Set up the device-specific handlers */
	capabilityInfo->selfTestFunction = selfTestFunction;
	capabilityInfo->getInfoFunction = getDefaultInfo;
	if( !isPKC )
		capabilityInfo->initParamsFunction = initGenericParams;
	capabilityInfo->endFunction = mechanismInfoPtr->endFunction;
	capabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;
	if( pMechanism.flags & keyGenFlag )
		capabilityInfo->generateKeyFunction = \
									mechanismInfoPtr->generateKeyFunction;
	if( pMechanism.flags & CKF_SIGN )
		{
		/* cryptlib treats hashing as an encrypt/decrypt operation while 
		   PKCS #11 treats it as a sign/verify operation, so we have to
		   juggle the function pointers based on the underlying algorithm
		   type */
		if( isPKC )
			capabilityInfo->signFunction = mechanismInfoPtr->signFunction;
		else
			capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
		}
	if( pMechanism.flags & CKF_VERIFY )
		{
		/* See comment above */
		if( isPKC )
			capabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;
		else
			capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
		}
	if( pMechanism.flags & CKF_ENCRYPT )
		{
		/* Not all devices implement all modes, so we have to be careful to 
		   set up the pointer for the exact mode that's supported */
		switch( mechanismInfoPtr->cryptMode )
			{
			case CRYPT_MODE_CBC:
				capabilityInfo->encryptCBCFunction = mechanismInfoPtr->encryptFunction;
				break;

			case CRYPT_MODE_CFB:
				capabilityInfo->encryptCFBFunction = mechanismInfoPtr->encryptFunction;
				break;

			case CRYPT_MODE_GCM:
				capabilityInfo->encryptGCMFunction = mechanismInfoPtr->encryptFunction;
				break;

			default:	/* ECB or a PKC */
				capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
				break;
			}
		}
	if( pMechanism.flags & CKF_DECRYPT )
		{
		/* Not all devices implement all modes, so we have to be careful to 
		   set up the pointer for the exact mode that's supported */
		switch( mechanismInfoPtr->cryptMode )
			{
			case CRYPT_MODE_CBC:
				capabilityInfo->decryptCBCFunction = mechanismInfoPtr->decryptFunction;
				break;

			case CRYPT_MODE_CFB:
				capabilityInfo->decryptCFBFunction = mechanismInfoPtr->decryptFunction;
				break;

			case CRYPT_MODE_GCM:
				capabilityInfo->decryptGCMFunction = mechanismInfoPtr->decryptFunction;
				break;

			default:	/* ECB or a PKC */
				capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
				break;
			}
		}
	if( cryptAlgo == CRYPT_ALGO_DH && pMechanism.flags & CKF_DERIVE )
		{
		/* DH is a special-case that doesn't really have an encrypt function 
		   and where "decryption" is actually a derivation */
		capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
		capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
		}

	/* Keygen capabilities are generally present as separate mechanisms,
	   sometimes CKF_GENERATE/CKF_GENERATE_KEY_PAIR is set for the main 
	   mechanism and sometimes it's set for the separate one so if it isn't 
	   present in the main one we check the alternative one */
	if( !( pMechanism.flags & keyGenFlag ) && \
		( mechanismInfoPtr->keygenMechanism != CKM_NONE ) )
		{
		status = C_GetMechanismInfo( pkcs11Info->slotID, 
									 mechanismInfoPtr->keygenMechanism,
									 &pMechanism );
		if( status == CKR_OK && ( pMechanism.flags & keyGenFlag ) && \
			( !hardwareOnly || ( pMechanism.flags & CKF_HW ) ) )
			{
			/* Some tinkertoy tokens don't implement key generation in 
			   hardware but instead do it on the host PC (!!!) and load the
			   key into the token afterwards, so we have to perform another 
			   check here to make sure that they're doing things right */
			capabilityInfo->generateKeyFunction = \
									mechanismInfoPtr->generateKeyFunction;
			}
		}

	/* Record mechanism-specific parameters if required */
	if( isConvAlgo( cryptAlgo ) || isMacAlgo( cryptAlgo ) )
		{
		capabilityInfo->paramKeyType = mechanismInfoPtr->keyType;
		capabilityInfo->paramKeyGen = mechanismInfoPtr->keygenMechanism;
		capabilityInfo->paramDefaultMech = mechanismInfoPtr->defaultMechanism;
		}

	/* Some drivers report bizarre combinations of capabilities like (for 
	   RSA) sign, verify, and decrypt but not encrypt, which will fail later 
	   sanity checks.  If we run into one of these we force the capabilities 
	   to be consistent by disabling any for which only partial capabilities
	   are supported */
	if( isPkcAlgo( cryptAlgo ) )
		{
		if( capabilityInfo->decryptFunction != NULL && \
			capabilityInfo->encryptFunction == NULL )
			{
			DEBUG_DIAG(( "Driver reports decryption but not encryption "
						 "capability for %s algorithm, disabling "
						 "encryption", capabilityInfo->algoName ));
			capabilityInfo->decryptFunction = NULL;
			}
		if( capabilityInfo->signFunction != NULL && \
			capabilityInfo->sigCheckFunction == NULL )
			{
			DEBUG_DIAG(( "Driver reports signature-generation but not "
						 "signature-verification capability for %s "
						 "algorithm, disabling signing", 
						 capabilityInfo->algoName ));
//////////////////////////////////
// Kludge to allow it to be used
//////////////////////////////////
if( cryptAlgo == CRYPT_ALGO_ECDSA )
capabilityInfo->sigCheckFunction = capabilityInfo->signFunction;
else
			capabilityInfo->signFunction = NULL;
			}

		/* If we've now disabled all capabilities, we can't use this 
		   algorithm */
		if( capabilityInfo->decryptFunction == NULL && \
			capabilityInfo->signFunction == NULL )
			{
			DEBUG_DIAG(( "Use of algorithm %s disabled since no consistent "
						 "set of capabilities is available", 
						 capabilityInfo->algoName ));
			clFree( "getCapability", capabilityInfo );
			assert( DEBUG_WARN );
			return( NULL );
			}
		}

	/* If it's not a conventional encryption algo, we're done */
	if( !isConvAlgo( cryptAlgo ) )
		return( ( CAPABILITY_INFO * ) capabilityInfo );

	/* PKCS #11 handles encryption modes by defining a separate mechanism for
	   each one.  In order to enumerate all the modes available for a 
	   particular algorithm we check for each mechanism in turn and set up 
	   the appropriate function pointers if it's available */
	for( mechanismInfoPtr++, iterationCount = 0; 
		 mechanismInfoPtr->cryptAlgo == cryptAlgo && \
			iterationCount < maxMechanisms; 
		 mechanismInfoPtr++, iterationCount++ )
		{
		/* There's a different form of the existing mechanism available,
		   check whether the driver implements it */
		status = C_GetMechanismInfo( pkcs11Info->slotID, 
									 mechanismInfoPtr->mechanism,
									 &pMechanism );
		if( status != CKR_OK )
			continue;

		/* Set up the pointer for the appropriate encryption mode */
		switch( mechanismInfoPtr->cryptMode )
			{
			case CRYPT_MODE_CBC:
				if( pMechanism.flags & CKF_ENCRYPT )
					capabilityInfo->encryptCBCFunction = \
										mechanismInfoPtr->encryptFunction;
				if( pMechanism.flags & CKF_DECRYPT )
					capabilityInfo->decryptCBCFunction = \
										mechanismInfoPtr->decryptFunction;
				break;
			case CRYPT_MODE_CFB:
				if( pMechanism.flags & CKF_ENCRYPT )
					capabilityInfo->encryptCFBFunction = \
										mechanismInfoPtr->encryptFunction;
				if( pMechanism.flags & CKF_DECRYPT )
					capabilityInfo->decryptCFBFunction = \
										mechanismInfoPtr->decryptFunction;
				break;
			case CRYPT_MODE_GCM:
				if( pMechanism.flags & CKF_ENCRYPT )
					capabilityInfo->encryptGCMFunction = \
										mechanismInfoPtr->encryptFunction;
				if( pMechanism.flags & CKF_DECRYPT )
					capabilityInfo->decryptGCMFunction = \
										mechanismInfoPtr->decryptFunction;
				break;

			default:
				retIntError_Null();
			}
		}
	ENSURES_N( iterationCount < maxMechanisms );

	return( ( CAPABILITY_INFO * ) capabilityInfo );
	}
Example #16
0
	{ CTAG_PB_KUR, CRYPT_REQUESTTYPE_KEYUPDATE },
	{ CTAG_PB_RR, CRYPT_REQUESTTYPE_REVOCATION },
	{ CTAG_PB_GENM, CRYPT_REQUESTTYPE_PKIBOOT },
	{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
	};

CHECK_RETVAL_RANGE( CRYPT_REQUESTYPE_NONE, CRYPT_REQUESTYPE_LAST ) \
static int reqToClibReq( IN_ENUM_OPT( CTAG_PB ) const CMP_MESSAGE_TYPE reqType )
	{
	int value, status;

	REQUIRES( reqType >= CTAG_PB_IR && reqType < CTAG_PB_LAST );
			  /* CTAG_PB_IR == 0 so this is the same as _NONE */

	status = mapValue( reqType, &value, reqClibReqMapTbl, 
					   FAILSAFE_ARRAYSIZE( reqClibReqMapTbl, MAP_TABLE ) );
	return( cryptStatusError( status ) ? status : value );
	}

/* Set up user authentication information (either a MAC context or a public 
   key) based on a request submitted by the client.  This is done whenever 
   the client starts a new transaction with a new user ID or certificate 
   ID */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int initServerAuthentMAC( INOUT SESSION_INFO *sessionInfoPtr, 
						  INOUT CMP_PROTOCOL_INFO *protocolInfo )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	MESSAGE_DATA msgData;
int initCertMgmtACL( INOUT KERNEL_DATA *krnlDataPtr )
	{
	int i;

	assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );

	/* Perform a consistency check on the cert management ACLs */
	for( i = 0; certMgmtACLTbl[ i ].action != MECHANISM_NONE && \
				i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ); i++ )
		{
		const CERTMGMT_ACL *certMgmtACL = &certMgmtACLTbl[ i ];

		/* Actions and permissions are consistent */
		ENSURES( certMgmtACL->action > CRYPT_CERTACTION_NONE && \
				 certMgmtACL->action < CRYPT_CERTACTION_LAST );
		ENSURES( certMgmtACL->access == ACTION_PERM_NONE || \
				 certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL || \
				 certMgmtACL->access == ACTION_PERM_ALL );

		/* If it's a no-access ACL, all mechanisms should be blocked */
		if( certMgmtACL->access == ACTION_PERM_NONE )
			{
			ENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_NONE );
			continue;
			}

		/* If it's an internal-only ACL, it always needs a request
		   parameter */
		if( certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL )
			{
			if( paramInfo( certMgmtACL, 1 ).valueType != PARAM_VALUE_OBJECT || \
				( paramInfo( certMgmtACL, 1 ).subTypeA & \
					~( ST_CERT_CERTREQ | ST_CERT_REQ_CERT | \
					   ST_CERT_REQ_REV | ST_CERT_CERT ) ) || \
				paramInfo( certMgmtACL, 1 ).subTypeB != ST_NONE )
				{
				DEBUG_DIAG(( "Certificate management ACLs inconsistent" ));
				retIntError();
				}
			}

		/* If it requires a CA key parameter, it must be a private-key
		   context with the key loaded and an attached CA certificate */
		if( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )
			{
			ENSURES( paramInfo( certMgmtACL, 0 ).subTypeA == ST_CTX_PKC && \
					 paramInfo( certMgmtACL, 0 ).subTypeB == ST_NONE && \
					 paramInfo( certMgmtACL, 0 ).flags == ACL_FLAG_HIGH_STATE );
			if( ( secParamInfo( certMgmtACL, 0 ).subTypeA & \
					~( ST_CERT_CERT | ST_CERT_CERTCHAIN ) ) || \
				secParamInfo( certMgmtACL, 0 ).subTypeB != ST_NONE || \
				secParamInfo( certMgmtACL, 0 ).flags != ACL_FLAG_HIGH_STATE )
				{
				DEBUG_DIAG(( "Certificate management ACLs inconsistent" ));
				retIntError();
				}
			continue;
			}
		ENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_UNUSED );
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ) );

	/* Set up the reference to the kernel data block */
	krnlData = krnlDataPtr;

	return( CRYPT_OK );
	}
Example #18
0
	{ CRYPT_REQUESTTYPE_KEYUPDATE, CTAG_PB_KUR },
	{ CRYPT_REQUESTTYPE_REVOCATION, CTAG_PB_RR },
	{ CRYPT_REQUESTTYPE_PKIBOOT, CTAG_PB_GENM },
	{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
	};

CHECK_RETVAL_RANGE( 0, CTAG_PB_LAST ) \
static int clibReqToReq( IN_ENUM( CRYPT_REQUESTTYPE ) const int reqType )
	{
	int value, status;

	REQUIRES( reqType > CRYPT_REQUESTTYPE_NONE && \
			  reqType < CRYPT_REQUESTTYPE_LAST );

	status = mapValue( reqType, &value, clibReqReqMapTbl, 
					   FAILSAFE_ARRAYSIZE( clibReqReqMapTbl, MAP_TABLE ) );
	return( cryptStatusError( status ) ? status : value );
	}

/* Set up information needed to perform a client-side transaction */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int initClientInfo( INOUT SESSION_INFO *sessionInfoPtr,
						   INOUT CMP_PROTOCOL_INFO *protocolInfo )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
	const ATTRIBUTE_LIST *userNamePtr = \
				findSessionInfo( sessionInfoPtr->attributeList,
								 CRYPT_SESSINFO_USERNAME );
	const ATTRIBUTE_LIST *passwordPtr = \
				findSessionInfo( sessionInfoPtr->attributeList,