static int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext, CRYPT_DEVICE *iCryptDevice, HARDWARE_INFO **hwInfoPtrPtr ) { CRYPT_DEVICE iLocalDevice; DEVICE_INFO *deviceInfo; int status; assert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) ); assert( isWritePtr( hwInfoPtrPtr, sizeof( HARDWARE_INFO * ) ) ); REQUIRES( isHandleRangeValid( iCryptContext ) ); /* Clear return values */ *iCryptDevice = CRYPT_ERROR; *hwInfoPtrPtr = NULL; /* Get the the device associated with this context */ status = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT, &iLocalDevice, OBJECT_TYPE_DEVICE ); if( cryptStatusError( status ) ) return( status ); /* Get the hardware information from the device information */ status = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE, ( void ** ) &deviceInfo, CRYPT_ERROR_SIGNALLED ); if( cryptStatusError( status ) ) return( status ); *iCryptDevice = iLocalDevice; *hwInfoPtrPtr = deviceInfo->deviceHardware; return( CRYPT_OK ); }
static int cloneActionContext( OUT_HANDLE_OPT CRYPT_CONTEXT *iClonedContext, IN_HANDLE const CRYPT_CONTEXT cryptContext, IN_ALGO const CRYPT_ALGO_TYPE algorithm ) { MESSAGE_CREATEOBJECT_INFO createInfo; int status; assert( isWritePtr( iClonedContext, sizeof( CRYPT_CONTEXT ) ) ); REQUIRES( isHandleRangeValid( cryptContext ) ); REQUIRES( algorithm > CRYPT_ALGO_NONE && algorithm < CRYPT_ALGO_LAST ); setMessageCreateObjectInfo( &createInfo, algorithm ); status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, &createInfo, OBJECT_TYPE_CONTEXT ); if( cryptStatusError( status ) ) return( status ); status = krnlSendMessage( cryptContext, IMESSAGE_CLONE, NULL, createInfo.cryptHandle ); if( cryptStatusError( status ) ) { krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT ); return( status ); } *iClonedContext = createInfo.cryptHandle; return( CRYPT_OK ); }
CHECK_RETVAL_BOOL \ static BOOLEAN checkPrivateKey( IN_HANDLE const CRYPT_CONTEXT iCryptContext, const BOOLEAN isCertKey ) { int value, status; REQUIRES( isHandleRangeValid( iCryptContext ) ); /* If the private key requires an associated certificate, make sure that it's present and of the correct form */ if( isCertKey ) { status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_IMMUTABLE ); if( cryptStatusError( status ) || !value ) return( FALSE ); status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_CERTTYPE ); if( cryptStatusError( status ) || \ ( value != CRYPT_CERTTYPE_CERTIFICATE && \ value != CRYPT_CERTTYPE_CERTCHAIN ) ) return( FALSE ); return( TRUE ); } /* The private key can't have an associated certificate, make sure there's none present */ status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_CERTTYPE ); return( cryptStatusOK( status ) ? FALSE : TRUE ); }
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 getDynData( OUT DYNBUF *dynBuf, IN_HANDLE const CRYPT_HANDLE cryptHandle, IN_MESSAGE const MESSAGE_TYPE message, IN_INT const int messageParam ) { MESSAGE_DATA msgData; void *dataPtr = NULL; int status; assert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) ); REQUIRES( isHandleRangeValid( cryptHandle ) ); REQUIRES( ( message == IMESSAGE_GETATTRIBUTE_S && \ ( isAttribute( messageParam ) || \ isInternalAttribute( messageParam ) ) ) || \ ( message == IMESSAGE_CRT_EXPORT && \ messageParam == CRYPT_CERTFORMAT_CERTIFICATE ) ); /* Clear return values. Note that we don't use the usual memset() to clear the value since the structure contains the storage for the fixed-size portion of the buffer appended to it, and using memset() to clear that is just unnecessary overhead */ dynBuf->data = dynBuf->dataBuffer; dynBuf->length = 0; /* Get the data from the object */ setMessageData( &msgData, NULL, 0 ); status = krnlSendMessage( cryptHandle, message, &msgData, messageParam ); if( cryptStatusError( status ) ) return( status ); if( msgData.length > DYNBUF_SIZE ) { /* The data is larger than the built-in buffer size, dynamically allocate a larger buffer */ if( ( dataPtr = clDynAlloc( "dynCreate", msgData.length ) ) == NULL ) return( CRYPT_ERROR_MEMORY ); msgData.data = dataPtr; status = krnlSendMessage( cryptHandle, message, &msgData, messageParam ); if( cryptStatusError( status ) ) { clFree( "dynCreate", dataPtr ); return( status ); } dynBuf->data = dataPtr; } else { /* The data will fit into the built-in buffer, read it directly into the buffer */ msgData.data = dynBuf->data; status = krnlSendMessage( cryptHandle, message, &msgData, messageParam ); if( cryptStatusError( status ) ) return( status ); } dynBuf->length = msgData.length; return( CRYPT_OK ); }
static int getNextItemFunction( DEVICE_INFO *deviceInfo, CRYPT_CERTIFICATE *iCertificate, int *stateInfo, const int options ) { HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware; MESSAGE_KEYMGMT_INFO getnextcertInfo; assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) ); assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) ); assert( isWritePtr( stateInfo, sizeof( int ) ) ); REQUIRES( isHandleRangeValid( *stateInfo ) || \ *stateInfo == CRYPT_ERROR ); UNUSED_ARG( hardwareInfo ); /* Clear return value */ *iCertificate = CRYPT_ERROR; /* If the previous certificate was the last one, there's nothing left to fetch */ if( *stateInfo == CRYPT_ERROR ) return( CRYPT_ERROR_NOTFOUND ); /* Get the next certificate */ setMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0, stateInfo, sizeof( int ), options ); return( krnlSendMessage( hardwareInfo->iCryptKeyset, IMESSAGE_KEY_GETNEXTCERT, &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY ) ); }
int setConvInfo( const CRYPT_CONTEXT iCryptContext, const int keySize ) { assert( isHandleRangeValid( iCryptContext ) ); REQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE ); return( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &keySize, CRYPT_IATTRIBUTE_KEYSIZE ) ); }
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 ) ) ); }
int dynCreate( OUT DYNBUF *dynBuf, IN_HANDLE const CRYPT_HANDLE cryptHandle, IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType ) { assert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) ); REQUIRES( isHandleRangeValid( cryptHandle ) ); REQUIRES( isAttribute( attributeType ) || \ isInternalAttribute( attributeType ) ); return( getDynData( dynBuf, cryptHandle, IMESSAGE_GETATTRIBUTE_S, attributeType ) ); }
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 ); }
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 ); }
static int setItemFunction( DEVICE_INFO *deviceInfo, const CRYPT_HANDLE iCryptHandle ) { HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware; MESSAGE_KEYMGMT_INFO setkeyInfo; assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) ); REQUIRES( isHandleRangeValid( iCryptHandle ) ); /* Redirect the add down to the PKCS #15 storage object */ if( hardwareInfo->iCryptKeyset == CRYPT_ERROR ) return( CRYPT_ERROR_NOTINITED ); setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, NULL, 0, KEYMGMT_FLAG_NONE ); setkeyInfo.cryptHandle = iCryptHandle; return( krnlSendMessage( hardwareInfo->iCryptKeyset, IMESSAGE_KEY_SETKEY, &setkeyInfo, KEYMGMT_ITEM_PUBLICKEY ) ); }
static int setItemFunction( INOUT DEVICE_INFO *deviceInfo, IN_HANDLE const CRYPT_HANDLE iCryptHandle ) { CRYPT_CERTIFICATE iCryptCert; PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11; int value, cryptStatus; assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) ); REQUIRES( isHandleRangeValid( iCryptHandle ) ); /* If the certificate isn't signed then we can't store it in this state */ cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_IMMUTABLE ); if( cryptStatusError( cryptStatus ) || !value ) return( CRYPT_ERROR_NOTINITED ); /* Lock the certificate for our exclusive use (in case it's a certificate chain we also select the first certificate in the chain), update the device with the certificate, and unlock it to allow others access */ cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert, OBJECT_TYPE_CERTIFICATE ); if( cryptStatusOK( cryptStatus ) ) cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED ); if( cryptStatusError( cryptStatus ) ) return( cryptStatus ); cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_CURSORFIRST, CRYPT_CERTINFO_CURRENT_CERTIFICATE ); if( cryptStatusOK( cryptStatus ) ) cryptStatus = updateCertChain( pkcs11Info, iCryptCert ); ( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED ); return( cryptStatus ); }
static int pgpReadDecryptMPI( INOUT STREAM *stream, IN_HANDLE const CRYPT_CONTEXT iCryptContext, IN_LENGTH_PKC const int minLength, IN_LENGTH_PKC const int maxLength ) { void *mpiDataPtr = DUMMY_INIT_PTR; const long mpiDataStartPos = stell( stream ) + UINT16_SIZE; int mpiLength, dummy, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); REQUIRES( isHandleRangeValid( iCryptContext ) ); REQUIRES( minLength >= bitsToBytes( 155 ) && \ minLength <= maxLength && \ maxLength <= CRYPT_MAX_PKCSIZE ); /* Get the MPI length and decrypt the payload data. We have to be careful how we handle this because readInteger16Ubits() returns the canonicalised form of the values (with leading zeroes truncated) so the returned length value doesn't necessarily represent the amount of data that we need to decrypt: startPos dataStart stell() | | | v v <-- length -->v +---+-----------+---------------+ | | |///////////////| Stream +---+-----------+---------------+ */ status = readInteger16Ubits( stream, NULL, &dummy, minLength, maxLength ); if( cryptStatusError( status ) ) return( status ); mpiLength = stell( stream ) - mpiDataStartPos; status = sMemGetDataBlockAbs( stream, mpiDataStartPos, &mpiDataPtr, mpiLength ); if( cryptStatusOK( status ) ) status = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT, mpiDataPtr, mpiLength ); return( status ); }
static int getHardwareReference( const CRYPT_CONTEXT iCryptContext, int *keyHandle ) { MESSAGE_DATA msgData; BYTE storageID[ KEYID_SIZE + 8 ]; int status; assert( isWritePtr( keyHandle, sizeof( int ) ) ); REQUIRES( isHandleRangeValid( iCryptContext ) ); setMessageData( &msgData, storageID, KEYID_SIZE ); status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID ); if( cryptStatusOK( status ) ) status = hwLookupItem( storageID, KEYID_SIZE, keyHandle ); if( cryptStatusError( status ) ) { /* In theory this is an internal error but in practice we shouldn't treat this as too fatal, what it really means is that the crypto hardware (which we don't control and therefore can't do too much about) is out of sync with the PKCS #15 storage object. This can happen for example during the development process when the hardware is reinitialised but the storage object isn't, or from any one of a number of other circumstances beyond our control. To deal with this we return a standard notfound error but also output a diagnostic message for developers to let them know that they need to check hardware/storage object synchronisation */ DEBUG_PRINT(( "Object held in PKCS #15 object store doesn't " "correspond to anything known to the crypto " "hardware HAL" )); return( CRYPT_ERROR_NOTFOUND ); } return( CRYPT_OK ); }
static int openStorageObject( CRYPT_KEYSET *iCryptKeyset, const CRYPT_KEYOPT_TYPE options, const CRYPT_DEVICE iCryptDevice ) { MESSAGE_CREATEOBJECT_INFO createInfo; char storageFilePath[ MAX_PATH_LENGTH + 8 ]; int storageFilePathLen, status; assert( isWritePtr( iCryptKeyset, sizeof( CRYPT_KEYSET ) ) ); REQUIRES( options == CRYPT_KEYOPT_NONE || \ options == CRYPT_KEYOPT_CREATE ); REQUIRES( isHandleRangeValid( iCryptDevice ) ); /* Clear return value */ *iCryptKeyset = CRYPT_ERROR; /* Try and open/create the PKCS #15 storage object */ status = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH, &storageFilePathLen, "CLKEYS", 6, BUILDPATH_GETPATH ); if( cryptStatusError( status ) ) return( status ); setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE ); if( options != CRYPT_KEYOPT_NONE ) createInfo.arg2 = options; createInfo.strArg1 = storageFilePath; createInfo.strArgLen1 = storageFilePathLen; status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, &createInfo, OBJECT_TYPE_KEYSET ); if( cryptStatusError( status ) ) return( status ); /* Now that we've got the storage object we have to perform a somewhat awkward double-linked-list update of the keyset to give it the handle of the owning device since we need to create any contexts for keys fetched from the storage object via the hardware device rather than the default system device. In theory we could also do this via a new get-owning-object message but we still need to signal to the keyset that it's a storage object rather than a standard keyset so this action serves a second purpose anyway and we may as well use it to explicitly set the owning-device handle at the same time. Note that we don't set the storage object as a dependent object of the device because it's not necessarily constant across device sessions. In particular if we initialise or zeroise the device then the storage object will be reset, but there's no way to switch dependent objects without destroying and recreating the parent. In addition it's not certain whether the storage-object keyset should really be a dependent object or not, in theory it's nice because it allows keyset-specific messages/accesses to be sent to the device and automatically routed to the keyset (standard accesses will still go to the device, so for example a getItem() will be handled as a device-get rather than a keyset-get) but such unmediated access to the underlying keyset probably isn't a good idea anyway */ status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &iCryptDevice, CRYPT_IATTRIBUTE_HWSTORAGE ); if( cryptStatusError( status ) ) { krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT ); return( status ); } *iCryptKeyset = createInfo.cryptHandle; return( CRYPT_OK ); }
BYTE *bufPtr = ( encryptedKey == NULL ) ? NULL : buffer; const int bufSize = ( encryptedKey == NULL ) ? 0 : CRYPT_MAX_KEYSIZE + 16; int keySize, ivSize, status; assert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \ isWritePtr( encryptedKey, encryptedKeyMaxLength ) ); assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) ); REQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \ ( encryptedKey != NULL && \ encryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \ encryptedKeyMaxLength < MAX_INTLENGTH ) ); REQUIRES( ( keyexType == KEYEX_PGP && \ iSessionKeyContext == CRYPT_UNUSED ) || \ ( keyexType != KEYEX_PGP && \ isHandleRangeValid( iSessionKeyContext ) ) ); REQUIRES( isHandleRangeValid( iExportContext ) ); REQUIRES( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST ); /* Clear return value */ *encryptedKeyLength = 0; /* Make sure that the requested key exchange format is available */ if( writeKeyexFunction == NULL ) return( CRYPT_ERROR_NOTAVAIL ); #ifdef USE_PGP /* PGP doesn't actually wrap up a key but derives the session key directly from the password. Because of this there isn't any key wrapping to be done so we just write the key derivation parameters and exit */
static int updateCertChain( INOUT PKCS11_INFO *pkcs11Info, IN_HANDLE const CRYPT_CERTIFICATE iCryptCert ) { static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; static const CK_CERTIFICATE_TYPE certType = CKC_X_509; CK_ATTRIBUTE certTemplate[] = { { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) }, { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) }, { CKA_ISSUER, NULL_PTR, 0 }, { CKA_SERIAL_NUMBER, NULL_PTR, 0 }, }; BOOLEAN isLeafCert = TRUE, seenNonDuplicate = FALSE; int value, iterationCount, cryptStatus; assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) ); REQUIRES( isHandleRangeValid( iCryptCert ) ); /* If we've been passed a standalone certificate, check whether it's implicitly trusted, which allows it to be added without requiring the presence of a corresponding public/private key in the device */ cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_CERTTYPE ); if( cryptStatusError( cryptStatus ) ) { return( ( cryptStatus == CRYPT_ARGERROR_OBJECT ) ? \ CRYPT_ARGERROR_NUM1 : cryptStatus ); } if( value == CRYPT_CERTTYPE_CERTIFICATE ) { cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value, CRYPT_CERTINFO_TRUSTED_IMPLICIT ); if( cryptStatusError( cryptStatus ) ) return( CRYPT_ARGERROR_NUM1 ); /* If the certificate is implicitly trusted we indicate that it's (effectively) a non-leaf certificate so that it can be added even if there's no corresponding key already in the device */ if( value ) isLeafCert = FALSE; } /* Add each certificate in the chain to the device */ for( iterationCount = 0; iterationCount < FAILSAFE_ITERATIONS_MED; iterationCount++ ) { CK_OBJECT_HANDLE hObject; DYNBUF iAndSDB; /* If the certificate is already present, don't do anything */ cryptStatus = dynCreate( &iAndSDB, iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER ); if( cryptStatusError( cryptStatus ) ) return( cryptStatus ); cryptStatus = addIAndSToTemplate( &certTemplate[ 2 ], dynData( iAndSDB ), dynLength( iAndSDB ) ); if( cryptStatusError( cryptStatus ) ) { /* In theory we could simply skip any certificates for which we can't decode the iAndS, but in practice it's probably better to fail and warn the user than to continue with only some certificates added */ dynDestroy( &iAndSDB ); return( cryptStatus ); } cryptStatus = findObject( pkcs11Info, &hObject, certTemplate, 4 ); dynDestroy( &iAndSDB ); if( cryptStatusError( cryptStatus ) ) { /* The certificate isn't already present, write it */ cryptStatus = updateCertificate( pkcs11Info, iCryptCert, isLeafCert ); if( cryptStatusError( cryptStatus ) ) return( cryptStatus ); isLeafCert = FALSE; seenNonDuplicate = TRUE; } /* Try and move to the next certificate */ cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_CURSORNEXT, CRYPT_CERTINFO_CURRENT_CERTIFICATE ); if( cryptStatusError( cryptStatus ) ) break; } ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED ); return( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE ); }
static int updateCertificate( INOUT PKCS11_INFO *pkcs11Info, IN_HANDLE const CRYPT_HANDLE iCryptHandle, const BOOLEAN isLeafCert ) { static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; static const CK_CERTIFICATE_TYPE certType = CKC_X_509; static const CK_BBOOL bTrue = TRUE; CK_DATE startDate, endDate; CK_ATTRIBUTE certTemplate[] = { { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) }, { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) }, { CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }, { CKA_ID, NULL_PTR, 0 }, { CKA_SUBJECT, NULL_PTR, 0 }, { CKA_ISSUER, NULL_PTR, 0 }, { CKA_SERIAL_NUMBER, NULL_PTR, 0 }, { CKA_VALUE, NULL_PTR, 0 }, /* Optional fields, filled in if required and the driver supports this */ { CKA_NONE, NULL_PTR, 0 }, /* 8 */ { CKA_NONE, NULL_PTR, 0 }, /* 9 */ { CKA_NONE, NULL_PTR, 0 }, /* 10 */ { CKA_NONE, NULL_PTR, 0 }, /* 11 */ }; CK_OBJECT_HANDLE hObject; CK_RV status; MESSAGE_DATA msgData; DYNBUF subjectDB, iAndSDB, certDB; BYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ]; BOOLEAN hasURL = FALSE; time_t theTime; char label[ CRYPT_MAX_TEXTSIZE + 8 ], uri[ MAX_URL_SIZE + 8 ]; int templateCount = 8, cryptStatus; assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) ); REQUIRES( isHandleRangeValid( iCryptHandle ) ); /* Get the keyID from the certificate */ setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE ); cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_KEYID ); if( cryptStatusError( cryptStatus ) ) return( CRYPT_ARGERROR_NUM1 ); certTemplate[ 3 ].pValue = msgData.data; certTemplate[ 3 ].ulValueLen = msgData.length; /* If it's a leaf certificate, use the keyID to locate the corresponding public or private key object. This is used as a check to ensure that the certificate corresponds to a key in the device. In theory this would allow us to read the label from the key so that we can reuse it for the certificate, but there doesn't seem to be any good reason for this and it could lead to problems with multiple certificates with the same labels so we don't do it */ if( isLeafCert ) { static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY; static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) }, { CKA_ID, NULL_PTR, 0 } }; keyTemplate[ 1 ].pValue = certTemplate[ 3 ].pValue; keyTemplate[ 1 ].ulValueLen = certTemplate[ 3 ].ulValueLen; cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 ); if( cryptStatusError( cryptStatus ) ) { /* Couldn't find a private key with this ID, try for a public key */ keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubkeyClass; cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 ); } if( cryptStatusError( cryptStatus ) ) return( CRYPT_ARGERROR_NUM1 ); } /* Get the validFrom and validTo dates. These aren't currently used for anything, but could be used in the future to handle superceded certificates in the same way that it's done for PKCS #15 keysets */ setMessageData( &msgData, &theTime, sizeof( time_t ) ); cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_CERTINFO_VALIDFROM ); if( cryptStatusOK( cryptStatus ) ) { convertDate( &startDate, theTime ); setMessageData( &msgData, &theTime, sizeof( time_t ) ); cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_CERTINFO_VALIDTO ); } if( cryptStatusError( cryptStatus ) ) return( cryptStatus ); convertDate( &endDate, theTime ); /* Get the subjectName and issuerAndSerialNumber from the certificate */ cryptStatus = dynCreate( &subjectDB, iCryptHandle, CRYPT_IATTRIBUTE_SUBJECT ); if( cryptStatusError( cryptStatus ) ) return( cryptStatus ); cryptStatus = dynCreate( &iAndSDB, iCryptHandle, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER ); if( cryptStatusError( cryptStatus ) ) { dynDestroy( &subjectDB ); return( cryptStatus ); } certTemplate[ 4 ].pValue = dynData( subjectDB ); certTemplate[ 4 ].ulValueLen = dynLength( subjectDB ); cryptStatus = addIAndSToTemplate( &certTemplate[ 5 ], dynData( iAndSDB ), dynLength( iAndSDB ) ); if( cryptStatusError( cryptStatus ) ) { dynDestroy( &subjectDB ); dynDestroy( &iAndSDB ); return( cryptStatus ); } /* Get the certificate data */ cryptStatus = dynCreateCert( &certDB, iCryptHandle, CRYPT_CERTFORMAT_CERTIFICATE ); if( cryptStatusError( cryptStatus ) ) { dynDestroy( &subjectDB ); dynDestroy( &iAndSDB ); return( cryptStatus ); } certTemplate[ 7 ].pValue = dynData( certDB ); certTemplate[ 7 ].ulValueLen = dynLength( certDB ); /* Get the certificate holder name (label) from the certificate if available */ setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE ); cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_HOLDERNAME ); if( cryptStatusOK( cryptStatus ) ) { /* We've found a holder name, use it as the certificate object label */ addTemplateValue( certTemplate[ templateCount ], CKA_LABEL, msgData.data, msgData.length ); templateCount++; } /* Add the certificate dates. These have to be located between the label and the URI so that we can selectively back out the attributes that don't work for this driver, see the comments further down for more details */ addTemplateValue( certTemplate[ templateCount ], CKA_START_DATE, ( CK_VOID_PTR ) &startDate, sizeof( CK_DATE ) ); templateCount++; addTemplateValue( certTemplate[ templateCount ], CKA_END_DATE, ( CK_VOID_PTR ) &endDate, sizeof( CK_DATE ) ); templateCount++; /* Get the URI from the certificate if available */ setMessageData( &msgData, uri, MAX_URL_SIZE ); cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_HOLDERURI ); if( cryptStatusOK( cryptStatus ) ) { /* We've found a holder URI, use it as the certificate object URL */ addTemplateValue( certTemplate[ templateCount ], CKA_URL, msgData.data, msgData.length ); templateCount++; hasURL = TRUE; } /* Reset the status value, which may contain error values due to not finding various object attributes above */ cryptStatus = CRYPT_OK; /* We've finally got everything available, try and update the device with the certificate data. In theory we should also set CKA_PRIVATE = FALSE but the Dallas iButton driver doesn't allow this so we have to rely on drivers doing the right thing with the default setting */ status = C_CreateObject( pkcs11Info->hSession, ( CK_ATTRIBUTE_PTR ) certTemplate, templateCount, &hObject ); if( hasURL && ( status == CKR_TEMPLATE_INCONSISTENT || \ status == CKR_ATTRIBUTE_TYPE_INVALID ) ) { /* Support for the PKCS #11 v2.20 attribute CKA_URL is pretty hit- and-miss, some drivers from ca.2000 support it but others from ca.2007 still don't so if we get a CKR_ATTRIBUTE_TYPE_INVALID return code we try again without the CKA_URL */ templateCount--; status = C_CreateObject( pkcs11Info->hSession, ( CK_ATTRIBUTE_PTR ) certTemplate, templateCount, &hObject ); } if( status == CKR_TEMPLATE_INCONSISTENT || \ status == CKR_ATTRIBUTE_TYPE_INVALID ) { /* Even support for dates is hit-and-miss so if we're still getting CKR_ATTRIBUTE_TYPE_INVALID we try again without the CKA_START_DATE/CKA_END_DATE */ templateCount -= 2; status = C_CreateObject( pkcs11Info->hSession, ( CK_ATTRIBUTE_PTR ) certTemplate, templateCount, &hObject ); } if( status != CKR_OK ) cryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED ); /* Clean up */ dynDestroy( &subjectDB ); dynDestroy( &iAndSDB ); dynDestroy( &certDB ); return( cryptStatus ); }
int status; assert( isReadPtr( inData, inDataLength ) ); assert( isWritePtr( outData, outDataMaxLength ) ); assert( isWritePtr( outDataLength, sizeof( int ) ) ); REQUIRES( inDataLength > 16 && inDataLength < MAX_INTLENGTH ); REQUIRES( outDataMaxLength > 16 && \ outDataMaxLength >= inDataLength + 512 && \ outDataMaxLength < MAX_INTLENGTH ); REQUIRES( formatType == CRYPT_FORMAT_CRYPTLIB || \ formatType == CRYPT_FORMAT_CMS ); REQUIRES( contentType >= CRYPT_CONTENT_NONE && \ contentType < CRYPT_CONTENT_LAST ); REQUIRES( ( iPublicKey == CRYPT_UNUSED ) || \ isHandleRangeValid( iPublicKey ) ); /* Clear return values. Note that we can't clear the output buffer at this point since this function is frequently used for in-place processing, so we clear it after we've pushed the input data */ *outDataLength = 0; /* Create an envelope to wrap the data, add the encryption key if necessary, and pop the wrapped result */ setMessageCreateObjectInfo( &createInfo, formatType ); status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, &createInfo, OBJECT_TYPE_ENVELOPE ); if( cryptStatusError( status ) ) { memset( outData, 0, min( 16, outDataMaxLength ) );
static int checkAddInfo( const PKCS15_INFO *pkcs15infoPtr, IN_HANDLE const CRYPT_HANDLE iCryptHandle, const BOOLEAN isCertChain, const BOOLEAN privkeyPresent, const BOOLEAN certPresent, const BOOLEAN pkcs15keyPresent, const BOOLEAN pkcs15certPresent, OUT BOOLEAN *isCertUpdate, INOUT ERROR_INFO *errorInfo ) { MESSAGE_DATA msgData; BOOLEAN unneededCert, unneededKey; int status; assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) ); assert( isWritePtr( isCertUpdate, sizeof( BOOLEAN ) ) ); REQUIRES( isHandleRangeValid( iCryptHandle ) ); REQUIRES( errorInfo != NULL ); /* Clear return value */ *isCertUpdate = FALSE; /* Check what we can update (if anything) */ unneededKey = privkeyPresent & pkcs15keyPresent; unneededCert = certPresent & pkcs15certPresent; if( ( ( unneededCert && !privkeyPresent ) || \ ( unneededKey && unneededCert ) ) && \ pkcs15infoPtr->validTo > MIN_TIME_VALUE ) { time_t validTo; /* The certificate would be a duplicate, see if it's more recent than the existing one. We only perform this check if there's a validTo time stored for the certificate since without this restriction any certificate without a stored time could be overwritten */ setMessageData( &msgData, &validTo, sizeof( time_t ) ); status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_CERTINFO_VALIDTO ); if( cryptStatusOK( status ) && validTo > pkcs15infoPtr->validTo ) { time_t validFrom; /* It's a newer certificate, don't treat it as a duplicate. This check is effectively impossible to perform automatically since there are an infinite number of variations that have to be taken into account, for example a certificate for the same key issued by a different CA, same CA but it's changed the bits it sets in the keyUsage (digitalSignature vs. nonRepudiation), slightly different issuer DN (Thawte certificates with a date encoded in the DN), and so on and so on. Because this really requires manual processing by a human we don't even try and sort it all out but just allow a certificate for a given key (checked by the ID match) to be replaced by a newer certificate for the same key. This is restrictive enough to prevent most obviously-wrong replacements while being permissive enough to allow most probably-OK replacements */ unneededCert = FALSE; *isCertUpdate = TRUE; /* There's one special-case situation in which odd things can happen when updating certificates and that's when adding a future-dated certificate, which would result in the certificate being replaced with one that can't be used yet. There's no clean way to handle this because in order to know what to do we'd have to be able to guess the intent of the user, however for anything but signature certificates it's likely that the hit-and-miss certificate checking performed by most software won't even notice a future-dated certificate, and for signature certificates the semantics of signing data now using a certificate that isn't valid yet are somewhat uncertain. Since in most cases no-one will even notice the problem, we throw an exception in the debug build but don't do anything in release builds. This is probably less annoying to users than having the code reject an otherwise-valid future-dated certificate. If anyone ever complains about this then we can ask the users at that time what sort of behaviour they're prefer */ setMessageData( &msgData, &validFrom, sizeof( time_t ) ); status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_CERTINFO_VALIDFROM ); if( cryptStatusOK( status ) && \ validFrom > getApproxTime() + 86400L ) { assert( !"Attempt to replace certificate with future-dated certificate" ); } } } /* Make sure that we can update at least one of the objects in the PKCS #15 personality */ if( ( unneededKey && !certPresent ) || /* Key only, duplicate */ ( unneededCert && !privkeyPresent ) || /* Certificate only, duplicate */ ( unneededKey && unneededCert ) ) /* Key+certificate, duplicate */ { /* If it's anything other than a certificate chain, we can't add anything */ if( !isCertChain ) { retExt( CRYPT_ERROR_DUPLICATE, ( CRYPT_ERROR_DUPLICATE, errorInfo, "No new data to add" ) ); } /* Tell the caller that it's an opportunistic certificate-chain update */ return( OK_SPECIAL ); } return( CRYPT_OK ); }
int checkServerCertValid( const CRYPT_CERTIFICATE iServerKey, INOUT ERROR_INFO *errorInfo ) { CRYPT_CERTIFICATE iServerCert; CRYPT_ERRTYPE_TYPE errorType DUMMY_INIT; CRYPT_ATTRIBUTE_TYPE errorLocus DUMMY_INIT; static const int complianceLevelStandard = CRYPT_COMPLIANCELEVEL_STANDARD; int complianceLevel, status; assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) ); REQUIRES( isHandleRangeValid( iServerKey ) ); status = krnlSendMessage( iServerKey, IMESSAGE_GETATTRIBUTE, &complianceLevel, CRYPT_OPTION_CERT_COMPLIANCELEVEL ); if( cryptStatusError( status ) ) { /* We can't do much more if we can't even get the initial compliance level */ return( CRYPT_ERROR_INVALID ); } /* Check whether the certificate is valid at a standard level of compliance, which catches expired certificates and other obvious problems */ krnlSendMessage( iServerKey, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &complianceLevelStandard, CRYPT_OPTION_CERT_COMPLIANCELEVEL ); status = krnlSendMessage( iServerKey, IMESSAGE_CHECK, NULL, MESSAGE_CHECK_CERT ); krnlSendMessage( iServerKey, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &complianceLevel, CRYPT_OPTION_CERT_COMPLIANCELEVEL ); if( cryptStatusOK( status ) ) return( CRYPT_OK ); /* The certificate associated with the key isn't valid, get the certificate (since otherwise we'd be querying the key rather than the certificate) and fetch the extended error information */ status = krnlSendMessage( iServerKey, IMESSAGE_GETDEPENDENT, &iServerCert, OBJECT_TYPE_CERTIFICATE ); if( cryptStatusOK( status ) ) { int value; status = krnlSendMessage( iServerCert, IMESSAGE_GETATTRIBUTE, &value, CRYPT_ATTRIBUTE_ERRORLOCUS ); if( cryptStatusOK( status ) ) { errorLocus = value; /* int to enum */ status = krnlSendMessage( iServerCert, IMESSAGE_GETATTRIBUTE, &value, CRYPT_ATTRIBUTE_ERRORTYPE ); } if( cryptStatusOK( status ) ) errorType = value; /* int to enum */ } if( cryptStatusError( status ) ) { /* If we can't get extended error information then there's not much more that we can do */ retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, errorInfo, "Server certificate is invalid" ) ); } /* Try and get more information on common errors and report them to the caller */ if( errorType == CRYPT_ERRTYPE_CONSTRAINT ) { switch( errorLocus ) { case CRYPT_CERTINFO_VALIDFROM: retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, errorInfo, "Server certificate is not valid yet" ) ); case CRYPT_CERTINFO_VALIDTO: retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, errorInfo, "Server certificate has expired" ) ); case CRYPT_CERTINFO_KEYUSAGE: retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, errorInfo, "Server certificate's keyUsage doesn't allow it " "to be used" ) ); } } retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, errorInfo, "Server certificate is invalid, error type %d, error " "locus %d", errorType, errorLocus ) ); }
CHECK_RETVAL \ int loadDHcontext( IN_HANDLE const CRYPT_CONTEXT iDHContext, IN_LENGTH_SHORT_OPT const int requestedKeySize ) { MESSAGE_DATA msgData; const void *keyData; const int actualKeySize = \ ( requestedKeySize < 128 + 8 ) ? bitsToBytes( 1024 ) : \ ( requestedKeySize < 192 + 8 ) ? bitsToBytes( 1536 ) : \ ( requestedKeySize < 256 + 8 ) ? bitsToBytes( 2048 ) : \ ( requestedKeySize < 384 + 8 ) ? bitsToBytes( 3072 ) : \ 0; int keyDataLength, keyDataChecksum; REQUIRES( isHandleRangeValid( iDHContext ) ); REQUIRES( requestedKeySize >= MIN_PKCSIZE && \ requestedKeySize <= CRYPT_MAX_PKCSIZE ); /* Load the built-in DH key value that corresponds best to the client's requested key size. We allow for a bit of slop to avoid having something like a 1025-bit requested key size lead to the use of a 1536-bit key value. In theory we should probably generate a new DH key each time: status = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &requestedKeySize, CRYPT_CTXINFO_KEYSIZE ); if( cryptStatusOK( status ) ) status = krnlSendMessage( iDHContext, IMESSAGE_CTX_GENKEY, NULL, FALSE ); however because the handshake is set up so that the client (rather than the server) chooses the key size we can't actually perform the generation until we're in the middle of the handshake. This means that the server will grind to a halt during each handshake as it generates a new key of whatever size takes the client's fancy (it also leads to a nice potential DoS attack on the server). To avoid this problem we use fixed keys of various common sizes. As late as 2014 Java still can't handle DH keys over 1024 bits (it only allows keys ranging from 512-1024 bits): java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive) so if you need to talk to a system built in Java you need to hardcode the key size below to 1024 bits, the largest size that Java will allow */ switch( actualKeySize ) { case bitsToBytes( 1024 ): keyData = dh1024SSL; keyDataLength = sizeof( dh1024SSL ); keyDataChecksum = dh1024checksum; break; case bitsToBytes( 1536 ): keyData = dh1536SSL; keyDataLength = sizeof( dh1536SSL ); keyDataChecksum = dh1536checksum; break; case bitsToBytes( 2048 ): keyData = dh2048SSL; keyDataLength = sizeof( dh2048SSL ); keyDataChecksum = dh2048checksum; break; case bitsToBytes( 3072 ): default: /* Hier ist der mast zu ende */ keyData = dh3072SSL; keyDataLength = sizeof( dh3072SSL ); keyDataChecksum = dh3072checksum; break; } /* Make sure that the key data hasn't been corrupted */ if( keyDataChecksum != checksumData( keyData, keyDataLength ) ) { DEBUG_DIAG(( "Fixed DH value for %d-bit key has been corrupted", bytesToBits( actualKeySize ) )); retIntError(); } /* Load the fixed DH key into the context */ setMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength ); return( krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_KEY_SSL ) ); }