Exemplo n.º 1
0
static int fuzzSpecial( const int fuzzType, const char *fuzzFileName )
	{
	CRYPT_CONTEXT cryptPrivKey;
	BYTE buffer[ 8192 ];
	const int minLength = ( fuzzType == 4000 ) ? 2 : 16;
	int length, status;

	/* If we're fuzzing bignum ops, load the private key that we'll need */
	if( fuzzType == 4000 )
		{
		if( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptPrivKey ) )
			return( CRYPT_ERROR_FAILED );
		}

	/* We're ready to go, start the forkserver and read the mutable data */
#ifndef __WINDOWS__
	__afl_manual_init();
#endif /* !__WINDOWS__ */
	length = readFileData( fuzzFileName, fuzzFileName, buffer, 8192, 
						   minLength, TRUE );
	if( length < minLength )
		return( CRYPT_ERROR_READ );

	/* Process the input file */
	if( fuzzType == 4000 )
		{
		BYTE tmpBuffer[ 8192 ];

#if 0	/* We don't do an early-out in order to check that the bignum code 
		   can actually reject all invalid input values */
		/* Any value that's larger than the modulus will be trivially 
		   rejected so there's no point in trying to process it */
		if( buffer[ 0 ] > 0x9C )
			{
			cryptDestroyContext( cryptPrivKey );
			return( CRYPT_OK );
			}
#endif /* 0 */

		memcpy( tmpBuffer, buffer, length );
		status = cryptDecrypt( cryptPrivKey, buffer, length );
		if( cryptStatusOK( status ) )
			status = cryptEncrypt( cryptPrivKey, buffer, length );
		if( cryptStatusOK( status ) )
			{
			/* Make sure that we got back what we started with */
			assert( !memcmp( buffer, tmpBuffer, length ) );
			}
		cryptDestroyContext( cryptPrivKey );
		}
Exemplo n.º 2
0
static int testKeysetWrite( const CRYPT_KEYSET_TYPE keysetType,
							const C_STR keysetName )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	CRYPT_CONTEXT pubKeyContext, privKeyContext;
	C_CHR filenameBuffer[ FILENAME_BUFFER_SIZE ];
	C_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ];
	int length, status;

	/* Import the certificate from a file - this is easier than creating one
	   from scratch.  We use one of the later certs in the test set, since
	   this contains an email address, which the earlier ones don't */
	status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 
									 EMAILADDR_CERT_NO );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't read certificate from file, status %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	/* Make sure that the certificate does actually contain an email 
	   address */
	status = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,
									  name, &length );
	if( cryptStatusError( status ) )
		{
		printf( "Certificate doesn't contain an email address and can't be "
				"used for testing,\n  line %d.\n", __LINE__ );
		return( FALSE );
		}

	/* Create the database keyset with a check to make sure this access
	   method exists so we can return an appropriate error message.  If the
	   database table already exists, this will return a duplicate data
	   error so we retry the open with no flags to open the existing database
	   keyset for write access */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,
							  keysetName, CRYPT_KEYOPT_CREATE );
	if( cryptStatusOK( status ) )
		printf( "Created new certificate database '%s'.\n", keysetName );
	if( status == CRYPT_ERROR_PARAM3 )
		{
		/* This type of keyset access isn't available, return a special error
		   code to indicate that the test wasn't performed, but that this
		   isn't a reason to abort processing */
		cryptDestroyCert( cryptCert );
		return( CRYPT_ERROR_NOTAVAIL );
		}
	if( status == CRYPT_ERROR_DUPLICATE )
		status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,
								  keysetName, 0 );
	if( cryptStatusError( status ) )
		{
		cryptDestroyCert( cryptCert );
		printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
				status, __LINE__ );
		if( status == CRYPT_ERROR_OPEN )
			return( CRYPT_ERROR_FAILED );
		return( FALSE );
		}

	/* Write the key to the database */
	puts( "Adding certificate." );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status == CRYPT_ERROR_DUPLICATE )
		{
		/* The key is already present, delete it and retry the write */
		status = cryptGetAttributeString( cryptCert,
								CRYPT_CERTINFO_COMMONNAME, name, &length );
		if( cryptStatusOK( status ) )
			{
#ifdef UNICODE_STRINGS
			length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
			name[ length ] = TEXT( '\0' );
			status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptDeleteKey()", status,
								  __LINE__ ) );
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		}
	if( cryptStatusError( status ) )
		{
		printExtError( cryptKeyset, "cryptAddPublicKey()", status, __LINE__ );

		/* LDAP writes can fail due to the chosen directory not supporting the
		   schema du jour, so we're a bit more careful about cleaning up since
		   we'll skip the error and continue processing */
		cryptDestroyCert( cryptCert );
		cryptKeysetClose( cryptKeyset );
		return( FALSE );
		}
	cryptDestroyCert( cryptCert );

	/* Add a second certificate with C=US so that we've got enough certs to 
	   properly exercise the query code.  This certificate is highly unusual 
	   in that it doesn't have a DN, so we have to move up the DN looking 
	   for higher-up values, in this case the OU */
	if( keysetType != CRYPT_KEYSET_LDAP )
		{
		status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 2 );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't read certificate from file, status %d, "
					"line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		if( status == CRYPT_ERROR_DUPLICATE )
			{
			status = cryptGetAttributeString( cryptCert,
							CRYPT_CERTINFO_COMMONNAME, name, &length );
			if( cryptStatusError( status ) )
				status = cryptGetAttributeString( cryptCert,
							CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, name, &length );
			if( cryptStatusOK( status ) )
				{
#ifdef UNICODE_STRINGS
				length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
				name[ length ] = TEXT( '\0' );
				status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
				}
			if( cryptStatusOK( status ) )
				status = cryptAddPublicKey( cryptKeyset, cryptCert );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptAddPublicKey()",
								  status, __LINE__ ) );
		cryptDestroyCert( cryptCert );
		}

	/* Add a third certificate with a DN that'll cause problems for some 
	   storage technologies */
	if( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )
		return( FALSE );
	status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
							  CRYPT_CERTTYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateCert() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}
	status = cryptSetAttribute( cryptCert,
					CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );
	if( cryptStatusError( status ) )
		return( attrErrorExit( cryptCert, "cryptSetAttribute()", status,
							   __LINE__ ) );
	if( !addCertFields( cryptCert, sqlCertData, __LINE__ ) )
		return( FALSE );
	status = cryptSignCert( cryptCert, privKeyContext );
	if( cryptStatusError( status ) )
		return( attrErrorExit( cryptCert, "cryptSignCert()", status,
							   __LINE__ ) );
	destroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( cryptStatusError( status ) )
		{
		/* The key is already present, delete it and retry the write */
		status = cryptGetAttributeString( cryptCert,
								CRYPT_CERTINFO_COMMONNAME, name, &length );
		if( cryptStatusOK( status ) )
			{
#ifdef UNICODE_STRINGS
			length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
			name[ length ] = TEXT( '\0' );
			status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptDeleteKey()", status,
								  __LINE__ ) );
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		}
	if( cryptStatusError( status ) )
		{
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()",
							  status, __LINE__ ) );
		}
	cryptDestroyCert( cryptCert );

	/* Now try the same thing with a CRL.  This code also tests the
	   duplicate-detection mechanism, if we don't get a duplicate error
	   there's a problem */
	puts( "Adding CRL." );
	status = importCertFromTemplate( &cryptCert, CRL_FILE_TEMPLATE, 1 );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't read CRL from file, status %d, line %d.\n", 
				status, __LINE__ );
		return( TRUE );
		}
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status,
							  __LINE__ ) );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status != CRYPT_ERROR_DUPLICATE )
		{
		printf( "Addition of duplicate item to keyset failed to produce "
			    "CRYPT_ERROR_DUPLICATE, status %d, line %d.\n", status,
				__LINE__ );
		return( FALSE );
		}
	cryptDestroyCert( cryptCert );

	/* Finally, try it with a certificate chain */
	puts( "Adding certificate chain." );
	filenameParamFromTemplate( filenameBuffer, CERTCHAIN_FILE_TEMPLATE, 
							   CERT_CHAIN_NO );
	status = importCertFile( &cryptCert, filenameBuffer );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't read certificate chain from file, status %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status,
							  __LINE__ ) );
	cryptDestroyCert( cryptCert );

	/* In addition to the other certs we also add the generic user 
	   certificate, which is used later in other tests.  Since it may have 
	   been added earlier we try and delete it first (we can't use the 
	   existing version since the issuerAndSerialNumber won't match the one 
	   in the private-key keyset) */
	status = getPublicKey( &cryptCert, USER_PRIVKEY_FILE,
						   USER_PRIVKEY_LABEL );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't read user certificate from file, status %d, line "
				"%d.\n", status, __LINE__ );
		return( FALSE );
		}
	status = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_COMMONNAME,
									  name, &length );
	if( cryptStatusError( status ) )
		return( FALSE );
#ifdef UNICODE_STRINGS
	length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
	name[ length ] = TEXT( '\0' );
	do
		status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
	while( cryptStatusOK( status ) );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status == CRYPT_ERROR_NOTFOUND )
		{
		/* This can occur if a database keyset is defined but hasn't been
		   initialised yet so the necessary tables don't exist, it can be
		   opened but an attempt to add a key will return a not found error
		   since it's the table itself rather than any item within it that
		   isn't being found */
		status = CRYPT_OK;
		}
	if( cryptStatusError( status ) )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status,
							  __LINE__ ) );
	cryptDestroyCert( cryptCert );

	/* Finally, if ECC is enabled we also add ECC certificates that are used
	   later in other tests */
	if( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) )
		{
#ifdef UNICODE_STRINGS
		wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
#endif /* UNICODE_STRINGS */
		void *fileNamePtr = filenameBuffer;

		/* Add the P256 certificate */
		filenameFromTemplate( filenameBuffer, 
							  SERVER_ECPRIVKEY_FILE_TEMPLATE, 256 );
#ifdef UNICODE_STRINGS
		mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
		fileNamePtr = wcBuffer;
#endif /* UNICODE_STRINGS */
		status = getPublicKey( &cryptCert, fileNamePtr,
							   USER_PRIVKEY_LABEL );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't read user certificate from file, status %d, "
					"line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
			return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status,
								  __LINE__ ) );
		cryptDestroyCert( cryptCert );

		/* Add the P384 certificate */
		filenameFromTemplate( filenameBuffer, 
							  SERVER_ECPRIVKEY_FILE_TEMPLATE, 384 );
#ifdef UNICODE_STRINGS
		mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
		fileNamePtr = wcBuffer;
#endif /* UNICODE_STRINGS */
		status = getPublicKey( &cryptCert, fileNamePtr,
							   USER_PRIVKEY_LABEL );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't read user certificate from file, status %d, "
					"line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
			return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status,
								  __LINE__ ) );
		cryptDestroyCert( cryptCert );
		}

	/* Make sure the deletion code works properly.  This is an artifact of
	   the way RDBMS' work, the delete query can execute successfully but
	   not delete anything so we make sure the glue code correctly
	   translates this into a CRYPT_DATA_NOTFOUND */
	status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
							 TEXT( "Mr.Not Appearing in this Keyset" ) );
	if( status != CRYPT_ERROR_NOTFOUND )
		{
		puts( "Attempt to delete a nonexistant key reports success, the "
			  "database backend glue\ncode needs to be fixed to handle this "
			  "correctly." );
		return( FALSE );
		}

	/* Close the keyset */
	status = cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
				status, __LINE__ );
		}

	return( TRUE );
	}
Exemplo n.º 3
0
static int fuzzSession( const CRYPT_SESSION_TYPE sessionType,
						const char *fuzzFileName )
	{
	CRYPT_SESSION cryptSession;
	CRYPT_CONTEXT cryptPrivKey = CRYPT_UNUSED;
	BYTE buffer[ 4096 ];
	const BOOLEAN isServer = \
			( sessionType == CRYPT_SESSION_SSH_SERVER || \
			  sessionType == CRYPT_SESSION_SSL_SERVER || \
			  sessionType == CRYPT_SESSION_OCSP_SERVER || \
			  sessionType == CRYPT_SESSION_RTCS_SERVER || \
			  sessionType == CRYPT_SESSION_TSP_SERVER || \
			  sessionType == CRYPT_SESSION_CMP_SERVER || \
			  sessionType == CRYPT_SESSION_SCEP_SERVER ) ? \
			TRUE : FALSE;
	int length, status;

	/* Create the session */
	status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
	if( cryptStatusError( status ) )
		return( status );

	/* Set up the various attributes needed to establish a minimal session */
	if( !isServer )
		{
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_SERVER_NAME,
										  "localhost", 9 );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( isServer )
		{
		if( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptPrivKey ) )
			return( CRYPT_ERROR_FAILED );
		}
	if( sessionType == CRYPT_SESSION_SSH || \
		sessionType == CRYPT_SESSION_CMP )
		{
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_USERNAME,
										  SSH_USER_NAME,
										  paramStrlen( SSH_USER_NAME ) );
		if( cryptStatusOK( status ) )
			{
			status = cryptSetAttributeString( cryptSession,
											  CRYPT_SESSINFO_PASSWORD,
											  SSH_PASSWORD,
											  paramStrlen( SSH_PASSWORD ) );
			}
		if( cryptStatusError( status ) )
			return( status );
		}
	if( sessionType == CRYPT_SESSION_CMP )
		{
		status = cryptSetAttribute( cryptSession,
									CRYPT_SESSINFO_CMP_REQUESTTYPE,
									CRYPT_REQUESTTYPE_INITIALISATION );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Perform any final session initialisation */
	cryptFuzzInit( cryptSession, cryptPrivKey );

	/* We're ready to go, start the forkserver and read the mutable data */
#ifndef __WINDOWS__
	__afl_manual_init();
#endif /* !__WINDOWS__ */
	length = readFileData( fuzzFileName, fuzzFileName, buffer, 4096, 32, 
						   TRUE );
	if( length < 32 )
		return( CRYPT_ERROR_READ );

	/* Perform the fuzzing */
	( void ) cryptSetFuzzData( cryptSession, buffer, length );
	cryptDestroySession( cryptSession );
	if( cryptPrivKey != CRYPT_UNUSED )
		cryptDestroyContext( cryptPrivKey );

	return( CRYPT_OK );
	}