uint32_t Cipher(uint8_t* out, const uint8_t* in, uint32_t len, uint8_t mode, const uint8_t* key, const uint8_t* IV, bool inverse) { Cipher_CTX ctx; CipherInit(&ctx, mode, key, IV); uint32_t ret = CipherUpdate(&ctx, out, in, len, inverse); ret += CipherFinal(&ctx, out, inverse); return ret; }
NTSTATUS Ext_Initialize(_Out_ PEVHD_EXT_CAPABILITIES pCaps) { NTSTATUS Status = STATUS_SUCCESS; TRACE_FUNCTION_IN(); pCaps->StateSize = 0; Status = CipherInit(); TRACE_FUNCTION_OUT_STATUS(Status); return Status; }
VLT_STS DoFinalSetup( VLT_PU8 pIV, VLT_U8 IvLen ) { VLT_U16 status = VLT_FAIL; /** * Check the IV ptr is not null */ if ( NULL == pIV ) { return ( SIGNER_DOFSUP_NULL_PARAM ); } switch (params.algoID) { case VLT_ALG_SIG_MAC_ISO9797_ALG1: /* No setup is required */ break; case VLT_ALG_SIG_MAC_ISO9797_ALG3: if (VLT_OK != ( status = CipherClose() ) ) { return ( status ); } /** * The final step for a MAC Algo 3 is a * switch to TDES! So re-init the Cipher. */ cipherParams.algoID = VLT_ALG_CIP_TDES_2K_EDE; cipherParams.pIV = pIV; if ( VLT_OK != (status = CipherInit( VLT_ENCRYPT_MODE, &theKey, (VLT_PU8)&cipherParams ) ) ) { return ( status ); } /** * Job done, the final block should now perform * a 3DES using the same both parts of the 2K * DES Key. * (k1 DES) -> (k2 DES-1) -> (k1 DES) = MAC */ break; case VLT_ALG_SIG_CMAC_AES: default: return( SIGNER_ALGO_ID_NOT_SUP ); } return ( VLT_OK ); }
// Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) { int c, retVal = ERR_SUCCESS; if (ea == 0) return ERR_CIPHER_INIT_FAILURE; for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c)) { switch (CipherInit (c, key, ks)) { case ERR_CIPHER_INIT_FAILURE: return ERR_CIPHER_INIT_FAILURE; case ERR_CIPHER_INIT_WEAK_KEY: retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error break; } key += CipherGetKeySize (c); ks += CipherGetKeyScheduleSize (c); } return retVal; }
VLT_STS SignerIso9797Init( VLT_U8 opMode, const KEY_BLOB* pKey, VLT_PU8 pParams ) { VLT_STS status = VLT_FAIL; /** * Make sure we have a valid params pointers */ if( ( NULL == pParams ) || ( NULL == pKey ) ) { return( INVALID_NULL_PARAMS ); } else if ( VLT_SIGN_MODE != opMode ) { return ( SIGNER_OPMODE_NOT_SUP ); } else { /** * Cache the parameters. */ params = *((SIGNER_PARAMS*)pParams); /** * Make sure we have a valid params pointers */ if ( NULL == params.pIV ) { return( INVALID_NULL_PARAMS ); } if( ( params.algoID != VLT_ALG_SIG_MAC_ISO9797_ALG1 ) && ( params.algoID != VLT_ALG_SIG_MAC_ISO9797_ALG3 ) ) { /** * Clear the singerState to signify the * fact that something has gone pear * shaped and we shouldn't deligate * any further calls to the concrete * methods. */ signerState = ST_UNKNOWN; /** * Return the appropriate error and * exit gracefully. */ return( SIGNER_ALGO_ID_NOT_SUP ); } } /** * Save a copy of the key! * Mac Algo 3 and AES CMAC * require key switching * in the final block! * This should only be done * on success but tweeking of * the key length is required * for Mac Alg3. */ theKey = *pKey; /** * Check and setup the required parameters for * the Chipher init method call. */ switch(params.algoID) { case VLT_ALG_SIG_MAC_ISO9797_ALG1: cipherParams.algoID = VLT_ALG_CIP_TDES_2K_EDE; cipherParams.chainMode = BLOCK_MODE_CBC; /** * The signer has to do padding itself * because of Cipher mode switching * in MAC algorithm 3, on the last block * if the Cipher does the padding, the * last block, can become the second last * block, due to padding method 2, PKCS5 etc. * The result is the last two blocks are * processed in the mode switch, and the * wrong answer is produced. */ cipherParams.paddingScheme = PADDING_NONE; break; case VLT_ALG_SIG_MAC_ISO9797_ALG3: cipherParams.algoID = VLT_ALG_CIP_DES; cipherParams.chainMode = BLOCK_MODE_CBC; cipherParams.paddingScheme = PADDING_NONE; theKey.keyType = VLT_KEY_DES; theKey.keySize = DES_KEY_SIZE; break; case VLT_ALG_SIG_CMAC_AES: default: return( SIGNER_ALGO_ID_NOT_SUP ); } /** * Check the padding scheme. */ switch( params.paddingScheme ) { case PADDING_ISO9797_METHOD2: case PADDING_NONE: case PADDING_PKCS5: case PADDING_PKCS7: break; default: return(SIGNER_PADDING_UNKNOWN); } /* * Check the IV length is supported. */ if( VLT_DES_IV_SIZE != params.ivSize ) { return (SIGNER_IV_LEN_NOT_SUP); } /** * Store the address of the IV into the Cipher params IV ptr. */ cipherParams.pIV = params.pIV; /** * Delegate the call to the initialisation method * to the cipher, and let the cipher use the appropriate algorithm. */ status = CipherInit( VLT_ENCRYPT_MODE, &theKey, (VLT_PU8)&cipherParams ); /** * Prepare to accept the first block * of data. */ if( VLT_OK == status ) { signerState = ST_INITIALISED; /** * Save a copy again! * Mac Algo 3 does a mixture * of DES and TDSES so the * keyLen has been modified * to DES_KEY_SIZE for the * first part, TDES_KEY_SIZE * is needed for the final * part! */ theKey = *pKey; /** * Setup the IV in the IV buffer if the * do final is called with a message * shorter or equal to the block size. * In this case the cipher will be re- * initalized with a new algorithm. */ /* * No need to check the return type as pointer has been validated */ (void)host_memcpy(&aIv[0], ¶ms.pIV[0], params.ivSize); /** * This is used to determine if do final * was called empty and update has not * been called (sign an empty message). */ blockCounter = 0; } return( status ); }
VLT_STS VltUnwrapKey( VLT_U8 u8KeyGroup, VLT_U8 u8KeyIndex, const VLT_FILE_PRIVILEGES *pKeyFilePrivileges, const VLT_KEY_OBJ_RAW* pKeyObj ) { #if( VLT_ENABLE_KEY_WRAPPING == VLT_ENABLE ) VLT_STS status = VLT_FAIL; VLT_U8 u8SecChnlState = VLT_USER_NOT_AUTHENTICATED; /* * Check the validity of the input parameters */ if( ( NULL == pKeyFilePrivileges ) || ( NULL == pKeyObj ) || ( NULL == pKeyObj->pu16ClearKeyObjectLen ) || ( NULL == pKeyObj->pu8KeyObject ) ) { return( EKWWKNULLPARAM ); } /* * Check that the key wrapping has been initialised */ if( ST_UNINIT == keyWrappingState ) { return ( EKWWKUNINIT ); } /* * Check if a Secure channel is enabled. If it is, don't allow the wrap */ if( VLT_OK == VltScpGetState( &u8SecChnlState ) ) { if( u8SecChnlState == VLT_USER_AUTHENTICATED ) { status = EKWWKSCPENBLD; } else { status = VLT_OK; } } else { /* * As Secure Channel hasn't been enabled the wrap call can proceed */ status = VLT_OK; } if( VLT_OK == status ) { /* * Initialise the Cipher */ status = CipherInit( VLT_ENCRYPT_MODE, &theKey, (VLT_PU8)&theWrapParams ); if( VLT_OK == status ) { /* * The cipher was initialised correctly so update the state */ keyWrappingState = ST_CIPHER_INIT; } } if( ( VLT_OK == status ) && ( WRAP_MODE != keyWrappingMode ) ) { /* * Call Initialize Algorithm on the VaultIC to set it up to unwrap the * wrapped key we are about to send down. Only do this if it hasn't * already been called */ VLT_ALGO_PARAMS algorithm; algorithm.u8AlgoID = theWrapParams.algoID; algorithm.data.SymCipher.u8Padding = theWrapParams.paddingScheme; algorithm.data.SymCipher.u8Mode = theWrapParams.chainMode; if (theWrapParams.pIV != NULL) { /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( &(algorithm.data.SymCipher.u8Iv[0]), theWrapParams.pIV, CipherGetBlockSize() ); algorithm.data.SymCipher.u8IvLength = (VLT_U8)CipherGetBlockSize(); } else algorithm.data.SymCipher.u8IvLength = 0; status = VltInitializeAlgorithm( u8CachedKTSKeyGroup, u8CachedKTSKeyIndex, VLT_UNWRAP_KEY_MODE, &algorithm ); if( VLT_OK == status ) { /* * Update the mode to wrap */ keyWrappingMode = WRAP_MODE; } } if( VLT_OK == status ) { VLT_U16 u16Remaining = VLT_PUTKEY_FIXED_DATA_LENGTH + *pKeyObj->pu16ClearKeyObjectLen; VLT_U16 u16KeyBytesRemaining = *(pKeyObj->pu16ClearKeyObjectLen); VLT_U16 u16MaxChunk = VltCommsGetMaxSendSize(); VLT_U16 u16Offset = 0; while( 0 != u16Remaining ) { VLT_SW Sw = VLT_STATUS_NONE; VLT_U16 u16Avail = 0; VLT_U16 u16PartialKeyLen = 0; VLT_U32 u32CipherDataLen = 0; VLT_U8 u8Final = 0; /* * Set index at the start of the data portion of the buffer */ idx = VLT_APDU_DATA_OFFSET; /* * Build the data in */ if( 0 == u16Offset ) { /* * Add the Key Priviliges */ Command.pu8Data[idx++] = pKeyFilePrivileges->u8Read; Command.pu8Data[idx++] = pKeyFilePrivileges->u8Write; Command.pu8Data[idx++] = pKeyFilePrivileges->u8Delete; Command.pu8Data[idx++] = pKeyFilePrivileges->u8Execute; /* * Add the Key Length */ Command.pu8Data[idx++] = (VLT_U8)( (*pKeyObj->pu16ClearKeyObjectLen >> 8 ) & 0xFF ); Command.pu8Data[idx++] = (VLT_U8)( (*pKeyObj->pu16ClearKeyObjectLen >> 0 ) & 0xFF ); } u16Avail = NumBufferBytesAvail( u16MaxChunk, idx ); if(u16KeyBytesRemaining > u16Avail) { /* * There is more key data remaining than can be transferred * in one transaction */ u16PartialKeyLen = ( u16Avail / CipherGetBlockSize() ) * CipherGetBlockSize(); } else { /* * The remaining data might all be able to be transferred in * one transaction */ if( u16Avail >= (u16KeyBytesRemaining + CipherGetBlockSize() ) ) { u16PartialKeyLen = u16KeyBytesRemaining; /* * Flag that this will be the final block to be encrypted */ u8Final = 1; } else { u16PartialKeyLen = u16KeyBytesRemaining - CipherGetBlockSize(); } } /* * Copy the number of bytes of the partial key into the buffer */ /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( &(Command.pu8Data[idx]), &( (pKeyObj->pu8KeyObject[u16Offset]) ), u16PartialKeyLen ); /* * Now encrypt the data in the buffer */ if( 1 == u8Final ) { status = CipherDoFinal( &(Command.pu8Data[idx]), u16PartialKeyLen, Command.u16Capacity - VLT_APDU_DATA_OFFSET, &(Command.pu8Data[idx]), &u32CipherDataLen, Command.u16Capacity - VLT_APDU_DATA_OFFSET ); } else { status = CipherUpdate( &(Command.pu8Data[idx]), u16PartialKeyLen, Command.u16Capacity - VLT_APDU_DATA_OFFSET, &(Command.pu8Data[idx]), &u32CipherDataLen, Command.u16Capacity - VLT_APDU_DATA_OFFSET ); } if( VLT_OK == status ) { /* * Update the index to reflect the data that has just been added */ idx += (VLT_U16)u32CipherDataLen; /* * Subtract the number of key bytes that have just been added to * the buffer from the number of key bytes remaining to be sent */ u16KeyBytesRemaining -= u16PartialKeyLen; /* * Decrement the remaining number of bytes to be sent. */ if( 0 == u16Offset ) { /* * The first time the File Privileges and the length are * included so include them plus the partial key length * which won't incude any padding bytes if some have been * added */ u16Remaining -= ( VLT_PUTKEY_FIXED_DATA_LENGTH - NUM_CRC_BYTES ) + u16PartialKeyLen; } else { /* * Subtract the partial key length that was added to * the buffer */ u16Remaining -= u16PartialKeyLen; } /* * Update the offset into the key */ u16Offset += u16PartialKeyLen; /* * We need two bytes free in the buffer for the wCRC field. */ if( ( NUM_CRC_BYTES == u16Remaining ) && ( NumBufferBytesAvail( u16MaxChunk, idx ) >= NUM_CRC_BYTES ) ) { Command.pu8Data[idx++] = (VLT_U8)( ( pKeyObj->u16Crc >> 8 ) & 0xFF ); Command.pu8Data[idx++] = (VLT_U8)( (pKeyObj->u16Crc >> 0 ) & 0xFF ); u16Remaining -= NUM_CRC_BYTES; }
void DecryptInit(Decrypt_CTX* ctx, uint8_t mode, const uint8_t* key, const uint8_t* IV) { CipherInit(ctx, mode, key, IV); }