Example #1
0
static int readAVA( INOUT STREAM *stream, 
					OUT_INT_Z int *type, 
					OUT_LENGTH_SHORT_Z int *length, 
					OUT_TAG_ENCODED_Z int *stringTag )
	{
	const DN_COMPONENT_INFO *dnComponentInfo;
	BYTE oid[ MAX_OID_SIZE + 8 ];
	int oidLength, tag, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( type, sizeof( int ) ) );
	assert( isWritePtr( length, sizeof( int ) ) );
	assert( isWritePtr( stringTag, sizeof( int ) ) );

	/* Clear return values */
	*type = 0;
	*length = 0;
	*stringTag = 0;

	/* Read the start of the AVA and determine the type from the 
	   AttributeType field.  If we find something that we don't recognise we 
	   indicate it as a non-component type that can be read or written but 
	   not directly accessed by the user (although it can still be accessed 
	   using the cursor functions) */
	readSequence( stream, NULL );
	status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, 
							 BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	dnComponentInfo = findDNInfoByOID( oid, oidLength );
	if( dnComponentInfo == NULL )
		{
		/* If we don't recognise the component type at all, skip it */
		status = readUniversal( stream );
		return( cryptStatusError( status ) ? status : OK_SPECIAL );
		}
	*type = dnComponentInfo->type;

	/* We've reached the data value, make sure that it's in order.  When we
	   read the wrapper around the string type with readGenericHole() we have 
	   to allow a minimum length of zero instead of one because of broken 
	   AVAs with zero-length strings */
	tag = peekTag( stream );
	if( cryptStatusError( tag ) )
		return( tag );
	if( tag == BER_BITSTRING )
		return( readAVABitstring( stream, length, stringTag ) );
	*stringTag = tag;
	return( readGenericHole( stream, length, 0, tag ) );
	}
Example #2
0
	long integer;
	int oidLength, innerLength, value, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( offset, sizeof( int ) ) );

	/* Clear return values */
	*objectType = CRYPT_CERTTYPE_NONE;
	*offset = 0;

	/* Read the contentType OID, determine the content type based on it,
	   and read the content encapsulation and header.  It can be either
	   a PKCS #7 certificate chain, a Netscape certificate sequence, or an 
	   X.509 userCertificate (which is just an oddball certificate 
	   wrapper) */
	status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, 
							 BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	if( oidLength != sizeofOID( OID_CMS_SIGNEDDATA ) || \
		memcmp( oid, OID_CMS_SIGNEDDATA, oidLength ) )
		return( CRYPT_ERROR_BADDATA );
	readConstructedI( stream, NULL, 0 );
	status = readSequenceI( stream, NULL );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the version number (1 = PKCS #7 v1.5, 2 = PKCS #7 v1.6, 3 = 
	   S/MIME with attribute certificate(s)) and SET OF 
	   DigestAlgorithmIdentifier (this is empty for a pure certificate chain, 
	   nonempty for signed data) */
	status = readShortInteger( stream, &integer );
Example #3
0
static int readRsaPrivateKeyOld( INOUT STREAM *stream, 
								 INOUT CONTEXT_INFO *contextInfoPtr )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
	const int startPos = stell( stream );
	int length, endPos, iterationCount, status;

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

	REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
			  contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );

	/* Skip the PKCS #8 wrapper.  When we read the OCTET STRING 
	   encapsulation we use MIN_PKCSIZE_THRESHOLD rather than MIN_PKCSIZE
	   so that a too-short key will get to readBignumChecked(), which
	   returns an appropriate error code */
	readSequence( stream, &length );	/* Outer wrapper */
	readShortInteger( stream, NULL );	/* Version */
	status = readAlgoID( stream, &cryptAlgo, ALGOID_CLASS_PKC );
	if( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_RSA )
		return( CRYPT_ERROR_BADDATA );
	status = readOctetStringHole( stream, NULL, 
								  ( 2 * MIN_PKCSIZE_THRESHOLD ) + \
									( 5 * ( MIN_PKCSIZE_THRESHOLD / 2 ) ), 
								  DEFAULT_TAG );
	if( cryptStatusError( status ) )	/* OCTET STRING encapsulation */
		return( status );

	/* Read the header */
	readSequence( stream, NULL );
	status = readShortInteger( stream, NULL );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the RSA key components, skipping n and e if we've already got 
	   them via the associated public key/certificate */
	if( BN_is_zero( &rsaKey->rsaParam_n ) )
		{
		status = readBignumChecked( stream, &rsaKey->rsaParam_n,
									RSAPARAM_MIN_N, RSAPARAM_MAX_N, 
									NULL );
		if( cryptStatusOK( status ) )
			status = readBignum( stream, &rsaKey->rsaParam_e,
								 RSAPARAM_MIN_E, RSAPARAM_MAX_E,
								 &rsaKey->rsaParam_n );
		}
	else
		{
		readUniversal( stream );
		status = readUniversal( stream );
		}
	if( cryptStatusOK( status ) )
		{
		/* d isn't used so we skip it */
		status = readUniversal( stream );
		}
	if( cryptStatusOK( status ) )
		status = readBignum( stream, &rsaKey->rsaParam_p,
							 RSAPARAM_MIN_P, RSAPARAM_MAX_P,
							 &rsaKey->rsaParam_n );
	if( cryptStatusOK( status ) )
		status = readBignum( stream, &rsaKey->rsaParam_q,
							 RSAPARAM_MIN_Q, RSAPARAM_MAX_Q,
							 &rsaKey->rsaParam_n );
	if( cryptStatusOK( status ) )
		status = readBignum( stream, &rsaKey->rsaParam_exponent1,
							 RSAPARAM_MIN_EXP1, RSAPARAM_MAX_EXP1,
							 &rsaKey->rsaParam_n );
	if( cryptStatusOK( status ) )
		status = readBignum( stream, &rsaKey->rsaParam_exponent2,
							 RSAPARAM_MIN_EXP2, RSAPARAM_MAX_EXP2,
							 &rsaKey->rsaParam_n );
	if( cryptStatusOK( status ) )
		status = readBignum( stream, &rsaKey->rsaParam_u,
							 RSAPARAM_MIN_U, RSAPARAM_MAX_U,
							 &rsaKey->rsaParam_n );
	if( cryptStatusError( status ) )
		return( status );

	/* Check whether there are any attributes present */
	if( stell( stream ) >= startPos + length )
		return( CRYPT_OK );

	/* Read the attribute wrapper */
	status = readConstructed( stream, &length, 0 );
	if( cryptStatusError( status ) )
		return( status );
	endPos = stell( stream ) + length;

	/* Read the collection of attributes.  Unlike any other key-storage 
	   format, PKCS #8 stores the key usage information as an X.509 
	   attribute alongside the encrypted private key data so we have to
	   process whatever attributes may be present in order to find the
	   keyUsage (if there is any) in order to set the object action 
	   permissions */
	for( iterationCount = 0;
		 stell( stream ) < endPos && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 iterationCount++ )
		{
		BYTE oid[ MAX_OID_SIZE + 8 ];
		int oidLength, actionFlags, value;

		/* Read the attribute.  Since there's only one attribute type that 
		   we can use, we hardcode the read in here rather than performing a 
		   general-purpose attribute read */
		readSequence( stream, NULL );
		status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, 
								 BER_OBJECT_IDENTIFIER );
		if( cryptStatusError( status ) )
			return( status );

		/* If it's not a key-usage attribute, we can't do much with it */
		if( oidLength != sizeofOID( OID_X509_KEYUSAGE ) || \
			memcmp( oid, OID_X509_KEYUSAGE, oidLength ) )
			{
			status = readUniversal( stream );
			if( cryptStatusError( status ) )
				return( status );
			continue;
			}

		/* Read the keyUsage attribute and convert it into cryptlib action 
		   permissions */
		readSet( stream, NULL );
		status = readBitString( stream, &value );
		if( cryptStatusError( status ) )
			return( status );
		actionFlags = ACTION_PERM_NONE;
		if( value & ( KEYUSAGE_SIGN | KEYUSAGE_CA ) )
			{
			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
										   ACTION_PERM_ALL ) | \
						   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
										   ACTION_PERM_ALL );
			}
		if( value & KEYUSAGE_CRYPT )
			{
			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
										   ACTION_PERM_ALL ) | \
						   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
										   ACTION_PERM_ALL );
			}
#if 0	/* 11/6/13 Windows sets these flags to what are effectively
				   gibberish values (dataEncipherment for a signing key,
				   digitalSignature for an encryption key) so in order
				   to be able to use the key we have to ignore the keyUsage 
				   settings, in the same way that every other application 
				   seems to */
		if( actionFlags == ACTION_PERM_NONE )
			return( CRYPT_ERROR_NOTAVAIL );
		status = krnlSendMessage( contextInfoPtr->objectHandle, 
								  IMESSAGE_SETATTRIBUTE, &actionFlags, 
								  CRYPT_IATTRIBUTE_ACTIONPERMS );
		if( cryptStatusError( status ) )
			return( status );
#else
		assert( actionFlags != ACTION_PERM_NONE );	/* Warn in debug mode */
#endif /* 0 */
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( CRYPT_OK );
	}
Example #4
0
static int readGeneralInfoAttribute( INOUT STREAM *stream, 
									 INOUT CMP_PROTOCOL_INFO *protocolInfo )
	{
	BYTE oid[ MAX_OID_SIZE + 8 ];
	int length, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );

	/* Read the attribute.  Since there are only two attribute types that we 
	   use, we hardcode the read in here rather than performing a general-
	   purpose attribute read */
	readSequence( stream, NULL );
	status = readEncodedOID( stream, oid, MAX_OID_SIZE, &length, 
							 BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );

	/* Process the cryptlib presence-check value */
	if( length == sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) && \
		!memcmp( oid, OID_CRYPTLIB_PRESENCECHECK, length ) )
		{
		/* The other side is running cryptlib, we can make some common-sense 
		   assumptions about its behaviour */
		protocolInfo->isCryptlib = TRUE;
		return( readUniversal( stream ) );			/* Attribute */
		}

	/* Check for the ESSCertID, which fixes CMP's broken certificate 
	   identification mechanism */
	if( length == sizeofOID( OID_ESS_CERTID ) && \
		!memcmp( oid, OID_ESS_CERTID, length ) )
		{
		BYTE certID[ CRYPT_MAX_HASHSIZE + 8 ];
		int certIDsize, endPos;

		/* Extract the certificate hash from the ESSCertID */
		readSet( stream, NULL );					/* Attribute */
		readSequence( stream, NULL );				/* SigningCerts */
		readSequence( stream, NULL );				/* Certs */
		status = readSequence( stream, &length );	/* ESSCertID */
		if( cryptStatusError( status ) )
			return( status );
		endPos = stell( stream ) + length;
		status = readOctetString( stream, certID, &certIDsize, 
								  KEYID_SIZE, KEYID_SIZE );
		if( cryptStatusError( status ) )
			return( status );
		if( protocolInfo->certIDsize != KEYID_SIZE || \
			memcmp( certID, protocolInfo->certID, KEYID_SIZE ) )
			{
			/* The certificate used for authentication purposes has changed,
			   remember the new certID */
			memcpy( protocolInfo->certID, certID, KEYID_SIZE );
			protocolInfo->certIDsize = KEYID_SIZE;
			protocolInfo->certIDchanged = TRUE;
			}
		if( stell( stream ) < endPos )
			{
			/* Skip the issuerSerial if there's one present.  We can't 
			   really do much with it in this form without rewriting it into 
			   the standard issuerAndSerialNumber, but in any case we don't 
			   need it because we've already got the certificate ID */
			status = readUniversal( stream );
			}
		return( status );
		}

	/* It's something that we don't recognise, skip it */
	return( readUniversal( stream ) );
	}