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 ) ); }
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 ); }
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 ) ); }
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 ) ); }
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 ); }
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 ) ) ); }
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 ); }
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 ); }
int sizeofEntry() { if(sizeofObject()) return(sizeofObject()+3*sizeof(double)+2*sizeof(BOOL)); // compressedEntry is: Object, rmin, rmax, distance, splitted, recomp return 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 ); }
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;
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 ) + \
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 ); }
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 ); }
int MTobject::CompressedLength() const { // return dimension*sizeof(double); return sizeofObject(); }