Example #1
0
static int writeCertID( INOUT STREAM *stream,
                        IN_HANDLE const CRYPT_CONTEXT iCryptCert )
{
    MESSAGE_DATA msgData;
    BYTE certHash[ CRYPT_MAX_HASHSIZE + 8 ];
    int essCertIDSize, payloadSize, status;

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

    REQUIRES( isHandleRangeValid( iCryptCert ) );

    /* Find out how big the payload will be */
    setMessageData( &msgData, certHash, CRYPT_MAX_HASHSIZE );
    status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
                              &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 );
    if( cryptStatusError( status ) )
        return( status );
    essCertIDSize = ( int ) sizeofObject( msgData.length );
    payloadSize = objSize( objSize( objSize( essCertIDSize ) ) );

    /* Write the signing certificate ID information */
    writeSequence( stream, sizeofOID( OID_ESS_CERTID ) + \
                   ( int ) sizeofObject( payloadSize ) );
    writeOID( stream, OID_ESS_CERTID );
    writeSet( stream, payloadSize );
    writeSequence( stream, objSize( objSize( essCertIDSize ) ) );
    writeSequence( stream, objSize( essCertIDSize ) );
    writeSequence( stream, essCertIDSize );
    return( writeOctetString( stream, certHash, msgData.length,
                              DEFAULT_TAG ) );
}
Example #2
0
static int readAVABitstring( INOUT STREAM *stream, 
							 OUT_LENGTH_SHORT_Z int *length, 
							 OUT_TAG_ENCODED_Z int *stringTag )
	{
	long streamPos;
	int bitStringLength, innerTag, innerLength = DUMMY_INIT, status;

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

	/* Bitstrings are used for uniqueIdentifiers, however these usually 
	   encapsulate something else:

		BIT STRING {
			IA5String 'xxxxx'
			}

	   so we try and dig one level deeper to find the encapsulated string if 
	   there is one.  This gets a bit complicated because we have to 
	   speculatively try and decode the inner content and if that fails 
	   assume that it's raw bitstring data.  First we read the bitstring 
	   wrapper and remember where the bitstring data starts */
	status = readBitStringHole( stream, &bitStringLength, 2, DEFAULT_TAG );
	if( cryptStatusError( status ) )
		return( status );
	streamPos = stell( stream );

	/* Then we try and read any inner content */
	status = innerTag = peekTag( stream );
	if( !cryptStatusError( status ) )
		status = readGenericHole( stream, &innerLength, 1, innerTag );
	if( !cryptStatusError( status ) && \
		bitStringLength == sizeofObject( innerLength ) )
		{
		/* There was inner content present, treat it as the actual type and 
		   value of the bitstring.  This assumes that the inner content is
		   a string data type, which always seems to be the case (in any 
		   event it's not certain what we should be returning to the user if
		   we find, for example, a SEQUENCE with further encapsulated 
		   content at this point) */
		*stringTag = innerTag;
		*length = innerLength;

		return( CRYPT_OK );
		}

	/* We couldn't identify any (obvious) inner content, it must be raw
	   bitstring data.  Unfortunately we have no idea what format this is
	   in, it could in fact really be raw binary data but never actually 
	   seems to be this, it's usually ASCII text so we mark it as such and 
	   let the string-read routines sort it out */
	sClearError( stream );
	sseek( stream, streamPos );
	*stringTag = BER_STRING_IA5;
	*length = bitStringLength;

	return( CRYPT_OK );
	}
Example #3
0
CHECK_RETVAL \
int sizeofDN( INOUT_OPT DN_PTR *dnComponentList )
	{
	int length, status;

	assert( dnComponentList == NULL || \
			isWritePtr( dnComponentList, sizeof( DN_COMPONENT ) ) );

	/* Null DNs produce a zero-length SEQUENCE */
	if( dnComponentList == NULL )
		return( sizeofObject( 0 ) );

	status = preEncodeDN( dnComponentList, &length );
	if( cryptStatusError( status ) )
		return( status );
	return( sizeofObject( length ) );
	}
Example #4
0
CHECK_RETVAL_LENGTH \
int sizeofMessageDigest( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
                         IN_LENGTH_HASH const int hashSize )
{
    const int hashParam = isParameterisedHashAlgo( hashAlgo ) ? hashSize : 0;
    int algoInfoSize, hashInfoSize;

    REQUIRES( isHashAlgo( hashAlgo ) );
    REQUIRES( hashSize >= 16 && hashSize <= CRYPT_MAX_HASHSIZE );

    algoInfoSize = sizeofAlgoIDex( hashAlgo, hashParam, 0 );
    hashInfoSize = sizeofObject( hashSize );
    ENSURES( algoInfoSize > 8 && algoInfoSize < MAX_INTLENGTH_SHORT );
    ENSURES( hashInfoSize > hashSize && hashInfoSize < MAX_INTLENGTH_SHORT );

    return( sizeofObject( algoInfoSize + hashInfoSize ) );
}
Example #5
0
static int writeKeyDerivationInfo( INOUT STREAM *stream,
								   IN_HANDLE const CRYPT_CONTEXT iCryptContext )
	{
	MESSAGE_DATA msgData;
	BYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];
	int saltLength, keySetupIterations, prfAlgo = DUMMY_INIT;
	int derivationInfoSize, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	
	REQUIRES( isHandleRangeValid( iCryptContext ) );

	/* Get the key derivation information */
	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
							  &keySetupIterations,
							  CRYPT_CTXINFO_KEYING_ITERATIONS );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
								  &prfAlgo, CRYPT_CTXINFO_KEYING_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	setMessageData( &msgData, salt, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_KEYING_SALT );
	if( cryptStatusError( status ) )
		return( status );
	saltLength = msgData.length;
	derivationInfoSize = ( int ) sizeofObject( saltLength ) + \
						 sizeofShortInteger( keySetupIterations );
	if( prfAlgo != CRYPT_ALGO_HMAC_SHA1 )
		derivationInfoSize += sizeofAlgoID( prfAlgo );

	/* Write the PBKDF2 information */
	writeConstructed( stream, sizeofOID( OID_PBKDF2 ) +
					  ( int ) sizeofObject( derivationInfoSize ), CTAG_KK_DA );
	writeOID( stream, OID_PBKDF2 );
	writeSequence( stream, derivationInfoSize );
	writeOctetString( stream, salt, saltLength, DEFAULT_TAG );
	status = writeShortInteger( stream, keySetupIterations, DEFAULT_TAG );
	if( prfAlgo != CRYPT_ALGO_HMAC_SHA1 )
		status = writeAlgoID( stream, prfAlgo );
	zeroise( salt, CRYPT_MAX_HASHSIZE );
	return( status );
	}
Example #6
0
CHECK_RETVAL \
static int sizeofCertID( IN_HANDLE const CRYPT_CONTEXT iCryptCert )
{
    const int essCertIDSize = objSize( objSize( objSize( objSize( 20 ) ) ) );
    /* Infinitely-nested SHA-1 hash */

    REQUIRES( isHandleRangeValid( iCryptCert ) );

    return( objSize( sizeofOID( OID_ESS_CERTID ) + \
                     sizeofObject( essCertIDSize ) ) );
}
Example #7
0
static int calculatePubkeyStorage( const PKCS15_INFO *pkcs15infoPtr,
								   INOUT_PTR void **newPubKeyDataPtr, 
								   OUT_LENGTH_SHORT_Z int *newPubKeyDataSize, 
								   IN_LENGTH_SHORT const int pubKeySize,
								   IN_LENGTH_SHORT const int pubKeyAttributeSize,
								   IN_LENGTH_SHORT const int extraDataSize )
	{
	void *newPubKeyData;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isWritePtr( newPubKeyDataPtr, sizeof( void * ) ) );
	assert( isWritePtr( newPubKeyDataSize, sizeof( int ) ) ); 

	REQUIRES( pubKeySize > 0 && pubKeySize < MAX_INTLENGTH_SHORT );
	REQUIRES( pubKeyAttributeSize > 0 && \
			  pubKeyAttributeSize < MAX_INTLENGTH_SHORT );
	REQUIRES( extraDataSize >= 0 && extraDataSize < MAX_INTLENGTH_SHORT );

	/* Calculate the new private-key data size */
	*newPubKeyDataSize = sizeofObject( \
							pubKeyAttributeSize + \
							sizeofObject( \
								sizeofObject( \
									sizeofObject( pubKeySize ) + \
									extraDataSize ) ) );
	ENSURES( *newPubKeyDataSize > 0 && \
			 *newPubKeyDataSize < MAX_BUFFER_SIZE );

	/* If the new data will fit into the existing storage, we're done */
	if( *newPubKeyDataSize <= pkcs15infoPtr->pubKeyDataSize )
		return( CRYPT_OK );

	/* Allocate storage for the new data */
	newPubKeyData = clAlloc( "calculatePubkeyStorage", *newPubKeyDataSize );
	if( newPubKeyData == NULL )
		return( CRYPT_ERROR_MEMORY );
	*newPubKeyDataPtr = newPubKeyData;

	return( CRYPT_OK );
	}
Example #8
0
static int getAttributeEncodingInfo( const ATTRIBUTE_LIST *attributeListPtr,
									 OUT_OPT_PTR \
										ATTRIBUTE_INFO **attributeInfoPtrPtr,
									 OUT_INT_Z int *attributeDataSize )
	{
	const ATTRIBUTE_INFO *attributeInfoPtr;
	BOOLEAN isConstructed = FALSE;

	assert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isWritePtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );
	assert( isWritePtr( attributeDataSize, sizeof( int ) ) );

	/* Clear return value */
	*attributeInfoPtrPtr = NULL;

	/* If it's a constructed attribute then the encoding information for
	   the outermost wrapper will be recorded in the encoding FIFO, 
	   otherwise it's present directly */
	if( attributeListPtr->fifoEnd > 0 )
		{
		attributeInfoPtr = \
			attributeListPtr->encodingFifo[ attributeListPtr->fifoEnd - 1 ];
		isConstructed = TRUE;
		}
	else
		attributeInfoPtr = attributeListPtr->attributeInfoPtr;
	ENSURES( attributeInfoPtr != NULL );

	/* Determine the size of the attribute payload */
	if( isConstructed && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )
		{
		*attributeDataSize = ( int ) sizeofObject( \
				attributeListPtr->sizeFifo[ attributeListPtr->fifoEnd - 1 ] );
		}
	else
		*attributeDataSize = attributeListPtr->encodedSize;
	*attributeInfoPtrPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr;

	return( CRYPT_OK );
	}
static int calculateCertStorage( const PKCS15_INFO *pkcs15infoPtr,
								 OUT_PTR void **newCertDataPtr, 
								 OUT_LENGTH_SHORT_Z int *newCertDataSize,
								 IN_LENGTH_SHORT const int certAttributeSize,
								 IN_LENGTH_SHORT const int certSize )
	{
	void *newCertData;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isWritePtr( newCertDataPtr, sizeof( void * ) ) );
	assert( isWritePtr( newCertDataSize, sizeof( int ) ) ); 

	REQUIRES( certAttributeSize > 0 && \
			  certAttributeSize < MAX_INTLENGTH_SHORT );
	REQUIRES( certSize > 0 && certSize < MAX_INTLENGTH_SHORT );

	/* Calculate the new certificate data size */
#ifdef USE_PKCS15V12_FORM
	*newCertDataSize = sizeofObject( certAttributeSize + \
									 sizeofObject( \
									   sizeofObject( \
										 sizeofObject( certSize ) ) ) );
#else
	*newCertDataSize = sizeofObject( certAttributeSize + \
									 sizeofObject( \
									   sizeofObject( certSize ) ) );
#endif /* USE_PKCS15V12_FORM */
	ENSURES( *newCertDataSize > 0 && *newCertDataSize < MAX_INTLENGTH );

	/* If the new data will fit into the existing storage, we're done */
	if( *newCertDataSize <= pkcs15infoPtr->certDataSize )
		return( CRYPT_OK );

	/* Allocate storage for the new data */
	newCertData = clAlloc( "calculateCertStorage", *newCertDataSize );
	if( newCertData == NULL )
		return( CRYPT_ERROR_MEMORY );
	*newCertDataPtr = newCertData;

	return( CRYPT_OK );
	}
Example #10
0
int sizeofEntry() {
    if(sizeofObject()) return(sizeofObject()+3*sizeof(double)+2*sizeof(BOOL));	// compressedEntry is: Object, rmin, rmax, distance, splitted, recomp
    return 0;
}
Example #11
0
static int preEncodeDN( INOUT DN_COMPONENT *dnComponentPtr, 
						OUT_LENGTH_SHORT_Z int *length )
	{
	int size = 0, iterationCount;

	assert( isWritePtr( dnComponentPtr, sizeof( DN_COMPONENT ) ) );
	assert( isWritePtr( length, sizeof( int ) ) );

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

	assert( isReadPtr( dnComponentPtr, sizeof( DN_COMPONENT ) ) );

#if 0	/* 18/7/08 Should never happen */
	/* If we're being fed an entry in the middle of a DN, move back to the
	   start */
	for( iterationCount = 0;
		 dnComponentPtr->prev != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 dnComponentPtr = dnComponentPtr->prev, iterationCount++ );
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
#endif /* 0 */
	ENSURES( dnComponentPtr->prev == NULL );

	/* Walk down the DN pre-encoding each AVA */
	for( iterationCount = 0;
		 dnComponentPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED; 
		 dnComponentPtr = dnComponentPtr->next, iterationCount++ )
		{
		DN_COMPONENT *rdnStartPtr = dnComponentPtr;
		int innerIterationCount;

		/* Calculate the size of every AVA in this RDN */
		for( innerIterationCount = 0;
			 dnComponentPtr != NULL && \
				innerIterationCount < FAILSAFE_ITERATIONS_MED;
			 dnComponentPtr = dnComponentPtr->next, innerIterationCount++ )
			{
			const DN_COMPONENT_INFO *dnComponentInfo = dnComponentPtr->typeInfo;
			int dnStringLength, status;

			status = getAsn1StringInfo( dnComponentPtr->value, 
										dnComponentPtr->valueLength,
										&dnComponentPtr->valueStringType, 
										&dnComponentPtr->asn1EncodedStringType,
										&dnStringLength );
			if( cryptStatusError( status ) )
				return( status );
			dnComponentPtr->encodedAVAdataSize = ( int ) \
										sizeofOID( dnComponentInfo->oid ) + \
										sizeofObject( dnStringLength );
			dnComponentPtr->encodedRDNdataSize = 0;
			rdnStartPtr->encodedRDNdataSize += ( int ) \
						sizeofObject( dnComponentPtr->encodedAVAdataSize );
			if( !( dnComponentPtr->flags & DN_FLAG_CONTINUED ) )
				break;
			}
		ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_MED );

		/* Calculate the overall size of the RDN */
		size += ( int ) sizeofObject( rdnStartPtr->encodedRDNdataSize );

		/* If the inner loop terminated because it reached the end of the DN 
		   then we need to explicitly exit the outer loop as well before it
		   tries to follow the 'next' link in the dnComponentPtr */
		if( dnComponentPtr == NULL )
			break;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
	*length = size;

	return( CRYPT_OK );
	}
Example #12
0
int writeMessageDigest( INOUT STREAM *stream,
                        IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
                        IN_BUFFER( hashSize ) const void *hash,
                        IN_LENGTH_HASH const int hashSize )
{
    const int hashParam = isParameterisedHashAlgo( hashAlgo ) ? hashSize : 0;
    int status;

    assert( isWritePtr( stream, sizeof( STREAM ) ) );
    assert( isReadPtr( hash, hashSize ) );

    REQUIRES_S( isHashAlgo( hashAlgo ) );
    REQUIRES_S( hashSize >= 16 && hashSize <= CRYPT_MAX_HASHSIZE );

    writeSequence( stream, sizeofAlgoIDex( hashAlgo, hashParam, 0 ) + \
                   ( int ) sizeofObject( hashSize ) );
    status = writeAlgoIDex( stream, hashAlgo, hashParam, 0 );
    if( cryptStatusOK( status ) )
        status = writeOctetString( stream, hash, hashSize, DEFAULT_TAG );
    return( status );
}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int readMessageDigest( INOUT STREAM *stream,
                       OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,
                       OUT_BUFFER( hashMaxLen, *hashSize ) void *hash,
                       IN_LENGTH_HASH const int hashMaxLen,
                       OUT_LENGTH_SHORT_Z int *hashSize )
{
    int hashAlgoSize, status;
Example #13
0
static int writeNonCMSheader( INOUT STREAM *stream, 
							  IN_BUFFER( oidLength ) const BYTE *oid, 
							  IN_RANGE( 1, MAX_OID_SIZE ) const int oidLength, 
							  IN_LENGTH_SHORT const int length, 
							  IN_LENGTH_SHORT const int attrDataLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( oid, oidLength ) );

	REQUIRES( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );
	REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );
	REQUIRES( attrDataLength > 0 && attrDataLength < MAX_INTLENGTH_SHORT );

	writeSequence( stream, ( int ) \
				   ( sizeofOID( oid ) + \
				     sizeofObject( sizeofObject( length ) ) + \
					 sizeofObject( attrDataLength ) ) );
	swrite( stream, oid, oidLength );
	writeConstructed( stream, ( int ) sizeofObject( length ), 0 );
	return( writeSequence( stream, length ) );
	}

/* Write the MAC data at the end of the keyset */

CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
static int sizeofMacData( const PKCS12_INFO *pkcs12info ) 
	{
	assert( isReadPtr( pkcs12info, sizeof( PKCS12_INFO ) ) );

	return( sizeofObject( \
				sizeofAlgoID( CRYPT_ALGO_SHA1 ) + \
Example #14
0
static int writePkiHeader( INOUT STREAM *stream,
                           INOUT SESSION_INFO *sessionInfoPtr,
                           INOUT CMP_PROTOCOL_INFO *protocolInfo )
{
    CRYPT_HANDLE senderNameObject = DUMMY_INIT, recipNameObject = DUMMY_INIT;
    STREAM nullStream;
    MESSAGE_DATA msgData;
#ifdef USE_FULL_HEADERS
    const BOOLEAN sendFullHeader = TRUE;
#else
    BOOLEAN sendFullHeader = FALSE;
#endif /* USE_FULL_HEADERS */
    BOOLEAN sendClibID = FALSE, sendCertID = FALSE, sendMacInfo = FALSE;
    BOOLEAN sendUserID = FALSE;
    int senderNameLength, recipNameLength, attributeLength = 0;
    int protInfoLength = DUMMY_INIT, totalLength, hashAlgo, status;

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

    /* Determine which of the many unnecessary and inexplicable bits of the
       CMP header we actually have to send:

    	sendCertID: Sent on the first message where it's required (which
    		isn't necessarily the first message in an exchange, for example
    		it's not used in an ir/ip), either to identify the CA's cert in
    		a CTL sent in a PKIBoot response or to identify the signing
    		certificate when we're using signature-based message
    		authentication.

    	sendClibID: Sent on the first message to tell the other side that
    		this is a cryptlib client/server.

    	sendFullHeader: Sent if the other side isn't running cryptlib, unless
    		we're doing PKIBoot, for which we couldn't send full headers even
    		if we wanted to

    	sendMacInfo: Sent if we're using MAC integrity protection and the
    		the other side isn't running cryptlib, or if this is the first
    		message.

    	sendUserID: Sent on the first message or if we're sending full
    		headers, provided that it's actually available to send */
    if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CERTIDSENT ) && \
            ( ( isServer( sessionInfoPtr ) && \
                protocolInfo->operation == CTAG_PB_GENM ) || \
              !protocolInfo->useMACsend ) )
        sendCertID = TRUE;
    if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CLIBIDSENT ) )
        sendClibID = TRUE;
#ifndef USE_FULL_HEADERS
    if( !protocolInfo->isCryptlib && \
            protocolInfo->operation != CTAG_PB_GENM )
        sendFullHeader = TRUE;
#endif /* !USE_FULL_HEADERS */
    if( protocolInfo->useMACsend && \
            !( protocolInfo->isCryptlib && \
               ( sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT ) ) )
        sendMacInfo = TRUE;
    if( ( sendFullHeader || \
            !( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) ) && \
            ( protocolInfo->userIDsize > 0 ) )
        sendUserID = TRUE;

    REQUIRES( !sendFullHeader || !protocolInfo->headerRead || \
              ( protocolInfo->userIDsize > 0 && \
                protocolInfo->userIDsize < MAX_INTLENGTH_SHORT ) );
    REQUIRES( protocolInfo->transIDsize > 0 && \
              protocolInfo->transIDsize < MAX_INTLENGTH_SHORT );

    /* Get any other state information that we may need */
    status = krnlSendMessage( sessionInfoPtr->ownerHandle,
                              IMESSAGE_GETATTRIBUTE, &hashAlgo,
                              CRYPT_OPTION_ENCR_HASH );
    ENSURES( cryptStatusOK( status ) );
    protocolInfo->hashAlgo = hashAlgo;	/* int vs.enum */

    /* Determine how big the sender and recipient information will be.  We
       shouldn't need to send a recipient name for an ir because it won't
       usually be known yet, but various implementations can't handle a
       zero-length GeneralName so we supply it if it's available even though
       it's redundant */
    if( sendFullHeader )
    {
        status = initDNInfo( sessionInfoPtr, &senderNameObject,
                             &recipNameObject, &senderNameLength,
                             &recipNameLength,
                             ( protocolInfo->operation == CTAG_PB_IR ) ? \
                             TRUE : FALSE,
                             protocolInfo->cryptOnlyKey );
        if( cryptStatusError( status ) )
            return( status );
    }
    else
    {
        /* We're not using sender or recipient information since it doesn't
           serve any useful purpose, just set the fields to an empty
           SEQUENCE */
        senderNameLength = recipNameLength = sizeofObject( 0 );
    }

    /* Determine how big the remaining header data will be */
    sMemNullOpen( &nullStream );
    if( protocolInfo->useMACsend )
    {
        status = writeMacInfo( &nullStream, protocolInfo, sendMacInfo );
    }
    else
    {
        status = writeContextAlgoID( &nullStream, protocolInfo->authContext,
                                     protocolInfo->hashAlgo );
    }
    if( cryptStatusOK( status ) )
        protInfoLength = stell( &nullStream );
    sMemClose( &nullStream );
    if( cryptStatusError( status ) )
        return( status );
    if( sendClibID )
    {
        attributeLength += sizeofObject( \
                                         sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
                                         sizeofObject( 0 ) );
    }
    if( sendCertID )
    {
        const int certIDsize = sizeofCertID( protocolInfo->authContext );

        ENSURES( certIDsize > 0 && certIDsize < MAX_INTLENGTH_SHORT );

        attributeLength += certIDsize;
    }
    totalLength = sizeofShortInteger( CMP_VERSION ) + \
                  objSize( senderNameLength ) + objSize( recipNameLength ) + \
                  objSize( protInfoLength ) + \
                  objSize( sizeofObject( protocolInfo->transIDsize ) );
    if( sendUserID )
        totalLength += objSize( sizeofObject( protocolInfo->userIDsize ) );
    if( sendFullHeader )
    {
        if( protocolInfo->senderNonceSize > 0 )
            totalLength += objSize( \
                                    sizeofObject( protocolInfo->senderNonceSize ) );
        if( protocolInfo->recipNonceSize > 0 )
            totalLength += objSize( \
                                    sizeofObject( protocolInfo->recipNonceSize ) );
    }
    if( attributeLength > 0 )
        totalLength += objSize( objSize( attributeLength ) );

    /* Perform an early check for data-size problems before we go through
       all of the following code */
    if( sizeofObject( totalLength ) <= 0 || \
            sizeofObject( totalLength ) > sMemDataLeft( stream ) )
        return( CRYPT_ERROR_OVERFLOW );

    /* Write the PKI header wrapper, version information, and sender and
       recipient names if there's name information present */
    writeSequence( stream, totalLength );
    writeShortInteger( stream, CMP_VERSION, DEFAULT_TAG );
    if( sendFullHeader )
    {
        writeConstructed( stream, senderNameLength, 4 );
        if( senderNameObject != CRYPT_ERROR )
        {
            status = exportAttributeToStream( stream, senderNameObject,
                                              CRYPT_IATTRIBUTE_SUBJECT );
            if( cryptStatusError( status ) )
                return( status );
        }
        else
            writeSequence( stream, 0 );
        writeConstructed( stream, recipNameLength, 4 );
        if( recipNameObject != CRYPT_ERROR )
        {
            status = exportAttributeToStream( stream, recipNameObject,
                                              CRYPT_IATTRIBUTE_SUBJECT );
        }
        else
            status = writeSequence( stream, 0 );
    }
    else
    {
        /* This is one of the portions of CMP where an optional field is
           marked as mandatory, to balance out the mandatory fields that are
           marked as optional.  To work around this we write the names as
           zero-length DNs */
        writeConstructed( stream, senderNameLength, 4 );
        writeSequence( stream, 0 );
        writeConstructed( stream, recipNameLength, 4 );
        status = writeSequence( stream, 0 );
    }
    if( cryptStatusError( status ) )
        return( status );

    /* Write the protection information, assorted nonces and IDs, and extra
       information that the other side may be able to make use of */
    writeConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );
    if( protocolInfo->useMACsend )
    {
        status = writeMacInfo( stream, protocolInfo, sendMacInfo );
        sessionInfoPtr->protocolFlags |= CMP_PFLAG_MACINFOSENT;
    }
    else
    {
        status = writeContextAlgoID( stream, protocolInfo->authContext,
                                     protocolInfo->hashAlgo );
    }
    if( cryptStatusError( status ) )
        return( status );
    if( sendUserID )
    {
        /* We're using full headers or we're the client sending our first
           message, identify the sender key */
        writeConstructed( stream, objSize( protocolInfo->userIDsize ),
                          CTAG_PH_SENDERKID );
        writeOctetString( stream, protocolInfo->userID,
                          protocolInfo->userIDsize, DEFAULT_TAG );
        DEBUG_PRINT(( "%s: Writing userID.\n",
                      protocolInfo->isServer ? "SVR" : "CLI" ));
        DEBUG_DUMP_HEX( protocolInfo->isServer ? "SVR" : "CLI",
                        protocolInfo->userID, protocolInfo->userIDsize );
        sessionInfoPtr->protocolFlags |= CMP_PFLAG_USERIDSENT;
    }
    writeConstructed( stream, objSize( protocolInfo->transIDsize ),
                      CTAG_PH_TRANSACTIONID );
    status = writeOctetString( stream, protocolInfo->transID,
                               protocolInfo->transIDsize, DEFAULT_TAG );
    if( cryptStatusError( status ) )
        return( status );
    if( sendFullHeader )
    {
        if( protocolInfo->senderNonceSize > 0 )
        {
            /* We're using nonces, generate a new sender nonce (the initial
               nonce will have been set when the protocol state was
               initialised) */
            setMessageData( &msgData, protocolInfo->senderNonce,
                            protocolInfo->senderNonceSize );
            krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
                             &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
            writeConstructed( stream,
                              objSize( protocolInfo->senderNonceSize ),
                              CTAG_PH_SENDERNONCE );
            status = writeOctetString( stream, protocolInfo->senderNonce,
                                       protocolInfo->senderNonceSize,
                                       DEFAULT_TAG );
        }
        if( protocolInfo->recipNonceSize > 0 )
        {
            writeConstructed( stream,
                              objSize( protocolInfo->recipNonceSize ),
                              CTAG_PH_RECIPNONCE );
            status = writeOctetString( stream, protocolInfo->recipNonce,
                                       protocolInfo->recipNonceSize,
                                       DEFAULT_TAG );
        }
    }
    if( cryptStatusError( status ) )
        return( status );
    if( attributeLength > 0 )
    {
        ENSURES( sendClibID || sendCertID );

        /* We haven't sent any messages yet, let the other side know that
           we're running cryptlib and identify our signing certificate as
           required */
        writeConstructed( stream, objSize( attributeLength ),
                          CTAG_PH_GENERALINFO );
        writeSequence( stream, attributeLength );
        if( sendClibID )
        {
            sessionInfoPtr->protocolFlags |= CMP_PFLAG_CLIBIDSENT;
            writeSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
                           sizeofObject( 0 ) );
            writeOID( stream, OID_CRYPTLIB_PRESENCECHECK );
            status = writeSet( stream, 0 );
        }
        if( sendCertID )
        {
            sessionInfoPtr->protocolFlags |= CMP_PFLAG_CERTIDSENT;
            status = writeCertID( stream, protocolInfo->authContext );
        }
    }
    return( status );
}
Example #15
0
static int initDNInfo( INOUT SESSION_INFO *sessionInfoPtr,
                       OUT_HANDLE_OPT CRYPT_HANDLE *senderNameObject,
                       OUT_HANDLE_OPT CRYPT_HANDLE *recipNameObject,
                       OUT_LENGTH_SHORT_Z int *senderNameLength,
                       OUT_LENGTH_SHORT_Z int *recipNameLength,
                       const BOOLEAN isInitialClientMessage,
                       const BOOLEAN isClientCryptOnlyKey )
{
    MESSAGE_DATA msgData;
    int status;

    assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
    assert( isWritePtr( senderNameObject, sizeof( CRYPT_HANDLE ) ) );
    assert( isWritePtr( recipNameObject, sizeof( CRYPT_HANDLE ) ) );
    assert( isWritePtr( senderNameLength, sizeof( int ) ) );
    assert( isWritePtr( recipNameLength, sizeof( int ) ) );

    /* Clear return values */
    *senderNameObject = *recipNameObject = CRYPT_ERROR;
    *senderNameLength = *recipNameLength = 0;

    /* Get the objects that we'll be using for our source of DN
       information */
    if( isServer( sessionInfoPtr ) )
    {
        *senderNameObject = sessionInfoPtr->privateKey;
        *recipNameObject = sessionInfoPtr->iCertResponse;
    }
    else
    {
        *senderNameObject = isClientCryptOnlyKey ? \
                            sessionInfoPtr->iAuthOutContext : \
                            sessionInfoPtr->iCertRequest;
        *recipNameObject = sessionInfoPtr->iAuthInContext;
    }

    /* Get the sender DN information */
    setMessageData( &msgData, NULL, 0 );
    status = krnlSendMessage( *senderNameObject, IMESSAGE_GETATTRIBUTE_S,
                              &msgData, CRYPT_IATTRIBUTE_SUBJECT );
    if( status == CRYPT_ERROR_NOTFOUND && isInitialClientMessage )
    {
        /* If there's no subject DN present and it's the first message in a
           client's ir exchange, this isn't an error because the subject
           usually won't know their DN yet.  That's the theory anyway,
           some X.500-obsessive servers will reject a message with no
           sender name but there isn't really anything that we can do about
           this, particularly since we can't tell in advance what beaviour
           the server will exhibit */
        if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
        {
            *senderNameObject = CRYPT_ERROR;
            msgData.length = ( int ) sizeofObject( 0 );
            status = CRYPT_OK;
        }
        else
        {
            /* Try again with the response from the server, which contains
               our newly-allocated DN */
            *senderNameObject = sessionInfoPtr->iCertResponse;
            status = krnlSendMessage( *senderNameObject,
                                      IMESSAGE_GETATTRIBUTE_S, &msgData,
                                      CRYPT_IATTRIBUTE_SUBJECT );
        }
    }
    if( cryptStatusError( status ) )
        return( status );
    *senderNameLength = msgData.length;

    /* Get the recipient DN information */
    setMessageData( &msgData, NULL, 0 );
    if( *recipNameObject != CRYPT_ERROR )
    {
        status = krnlSendMessage( *recipNameObject, IMESSAGE_GETATTRIBUTE_S,
                                  &msgData, CRYPT_IATTRIBUTE_SUBJECT );
    }
    else
    {
        /* If we're sending an error response there may not be any recipient
           name information present yet if the error occurred before the
           recipient information could be established, and if this is a MAC-
           authenticated PKIBoot we don't have the CA's certificate yet so
           we don't know its DN.  To work around this we send a zero-length
           DN (this is one of those places where an optional field is
           specified as being mandatory, to lend balance to the places where
           mandatory fields are specified as optional) */
        msgData.length = ( int ) sizeofObject( 0 );
    }
    if( cryptStatusError( status ) )
        return( status );
    *recipNameLength = msgData.length;

    return( CRYPT_OK );
}
Example #16
0
int
MTobject::CompressedLength() const
{
//	return dimension*sizeof(double);
	return sizeofObject();
}