VLT_U16 CipherGetBlockSize( void ) { if( ST_UNKNOWN != cipherState ) { return( theCipher.cipherGetBlockSize() ); } return( ECPHBLKNOTSUPPORTED ); }
VLT_STS CipherInit( VLT_U8 opMode, const KEY_BLOB* pKey, VLT_PU8 pParams ) { VLT_U8 keyMode ; VLT_STS status = VLT_FAIL; /** * Make sure we have a valid params pointer */ if( NULL == pParams ) { return( ECPHIIVLDPRM ); } else { /** * Cache the parameters. */ params = *((CIPHER_PARAMS*)pParams); if( ( params.algoID != VLT_ALG_CIP_DES ) && ( params.algoID != VLT_ALG_CIP_TDES_2K_EDE ) && ( params.algoID != VLT_ALG_CIP_TDES_3K_EDE ) && ( params.algoID != VLT_ALG_CIP_TDES_3K_EEE ) && ( params.algoID != VLT_ALG_CIP_AES ) && ( params.algoID != VLT_ALG_KTS_TDES_3K_EEE ) && ( params.algoID != VLT_ALG_KTS_TDES_3K_EDE ) && ( params.algoID != VLT_ALG_KTS_AES ) ) { /** * Clear the cipherState to signify the * fact that something has gone pear * shaped and we shouldn't deligate * any further calls to the concrete * cipher methods. */ cipherState = ST_UNKNOWN; /** * Return the appropriate error and * exit gracefully. */ return( ECPHIINVLDALGO ); } } /** * Set all the function pointers * to the actual concrete cipher * methods based on the algo Id. */ switch(params.algoID) { #if( VLT_ENABLE_CIPHER_DES == VLT_ENABLE ) case VLT_ALG_CIP_DES: theCipher.cipherInit = DesInit; theCipher.cipherDoFinal = DesDoFinal; theCipher.cipherGetBlockSize = DesGetBlockSize; theCipher.cipherUpdate = DesUpdate; theCipher.cipherClose = DesClose; break; #endif /* ( VLT_ENABLE_CIPHER_DES == VLT_ENABLE )*/ #if( VLT_ENABLE_CIPHER_TDES == VLT_ENABLE ) case VLT_ALG_CIP_TDES_2K_EDE: case VLT_ALG_CIP_TDES_3K_EDE: case VLT_ALG_CIP_TDES_3K_EEE: case VLT_ALG_KTS_TDES_3K_EEE: case VLT_ALG_KTS_TDES_3K_EDE: theCipher.cipherInit = TDesInit; theCipher.cipherDoFinal = TDesDoFinal; theCipher.cipherGetBlockSize = TDesGetBlockSize; theCipher.cipherUpdate = TDesUpdate; theCipher.cipherClose = TDesClose; break; #endif /* ( VLT_ENABLE_CIPHER_TDES == VLT_ENABLE ) */ #if( VLT_ENABLE_CIPHER_AES == VLT_ENABLE ) case VLT_ALG_CIP_AES: case VLT_ALG_KTS_AES: theCipher.cipherInit = AesInit; theCipher.cipherDoFinal = AesDoFinal; theCipher.cipherGetBlockSize = AesGetBlockSize; theCipher.cipherUpdate = AesUpdate; theCipher.cipherClose = AesClose; break; #endif/*( VLT_ENABLE_CIPHER_AES == VLT_ENABLE )*/ default: return( ECPHINOTSUPPORTED ); } /** * Check and setup the Keying mode. */ switch(params.algoID) { case VLT_ALG_CIP_TDES_2K_EDE: keyMode = TDES_EDE; break; case VLT_ALG_CIP_TDES_3K_EDE: case VLT_ALG_KTS_TDES_3K_EDE: keyMode = TDES_EDE; break; case VLT_ALG_CIP_TDES_3K_EEE: case VLT_ALG_KTS_TDES_3K_EEE: keyMode = TDES_EEE; break; case VLT_ALG_CIP_DES: /** * Do nothing for des the * key mode is not relevant. */ break; case VLT_ALG_CIP_AES: case VLT_ALG_KTS_AES: /** * Do nothing for aes the * key mode is not relevant. */ break; default: return( ECPHINOTSUPPORTED ); } /** * Check the chaining mode. */ switch( params.chainMode ) { case BLOCK_MODE_ECB: case BLOCK_MODE_CBC: break; case BLOCK_MODE_CFB: case BLOCK_MODE_OFB: default: return(ECPHICHNMODE); } /** * Initialise the chaining block to zeros */ /* * No need to check the return type as pointer has been validated */ (void)host_memset( chainBlock, 0x00, theCipher.cipherGetBlockSize() ); /** * Check the padding scheme. */ switch( params.paddingScheme ) { case PADDING_ISO9797_METHOD2: case PADDING_NONE: case PADDING_PKCS5: case PADDING_PKCS7: break; default: return(ECPHIPADUNKNOWN); } /** * Cache the operationalMode, we'll need it * when we are doing the padding. */ operationalMode = opMode; /** * Delegate the call to the initialisation method * of the appropriate cipher. */ status = theCipher.cipherInit( opMode, pKey, &keyMode ); /** * Prepare to accept the first block * of data. */ if( VLT_OK == status ) { cipherState = ST_INITIALISED; } return( status ); }
VLT_STS CipherUpdate( VLT_PU8 pDataIn, VLT_U32 DataInLen, VLT_U32 dataInCapacity, VLT_PU8 pDataOut, VLT_PU32 pDataOutLen, VLT_U32 dataOutCapacity ) { VLT_STS status = VLT_FAIL; VLT_U16 blockSize = 0; VLT_U32 byteCount = 0; VLT_U32 workingLen = 0; if ( ( ST_UNKNOWN == cipherState ) || ( ST_FINALISED == cipherState ) ) { return( ECPHUPDNOTSUPPORTED ); } /** * Cache the block size, we'll use it * frequently. */ blockSize = theCipher.cipherGetBlockSize( ); /** * Ensure we haven't been passed * null pointers by the caller. */ if( ( NULL == pDataIn ) || ( NULL == pDataOutLen ) || ( NULL == pDataOut ) ) { return( ECPHUPDNULLPARAM ); } /** * For the CipherUpdate the capacity of * the buffer passed to us by the caller * should be equal or larger than that * of the data buffer length. */ if( ( DataInLen > dataInCapacity ) || ( DataInLen > dataOutCapacity ) ) { return( ECPHUPDINVLDCPCT ); } /** * Update only deals with data lengths * multiple of the block size, if the * client has passed us anything else * other than that then we should exit * gracefully-ish! */ if( 0 != ( DataInLen % blockSize ) ) { return( ECPHUPDINVLDLEN ); } /** * Chunk things up in multiples of the * block size. */ while( 0 != ( DataInLen - byteCount ) ) { /* * Perform a copy of the input data into a temp buffer * this is needed to ensure the input data is not trashed * if CBC mode is selected. */ /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( &workingBlock[0], &pDataIn[byteCount], blockSize ); /** * Do the chaining */ if( VLT_ENCRYPT_MODE == operationalMode ) { if( BLOCK_MODE_CBC == params.chainMode ) { if( ST_INITIALISED == cipherState ) { /* * Make a copy of the IV of the first round. */ /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( chainBlock, &(params.pIV[0]), blockSize ); cipherState = ST_UPDATED; } /* * No need to check the return type as pointer has been validated */ (void)host_memxor( &workingBlock[0], chainBlock, blockSize ); } } else { if( BLOCK_MODE_CBC == params.chainMode ) { /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( tempBlock, &pDataIn[byteCount], blockSize ); } } /** * Set the working length */ workingLen = blockSize; /** * Do the Encrypt/Decrypt */ if( VLT_OK == ( status = theCipher.cipherUpdate( //&pData[byteCount], &workingBlock[0], /* workingBlock is used to ensure the pDataIn is preserved */ &workingLen, &pDataOut[byteCount], &workingLen) ) ) { /** * It should be impossible for the block * cipher to return a length not equal to * the blockSize, nevertheless if it does * exit with an appropriate error code and * set the chaining block back to the IV * for the next call. */ if( workingLen != blockSize ) { return( ECPHUPDINVLDBLOCK ); } } else { return( status ); } /** * Do the chaining */ if( VLT_ENCRYPT_MODE == operationalMode ) { if( BLOCK_MODE_CBC == params.chainMode ) { /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( chainBlock, &pDataOut[byteCount], blockSize ); } } else { if( BLOCK_MODE_CBC == params.chainMode ) { if( ST_INITIALISED == cipherState ) { /* * No need to check the return type as pointer has been validated */ (void)host_memxor( &pDataOut[byteCount], &(params.pIV[0]), blockSize ); cipherState = ST_UPDATED; } else { /* * No need to check the return type as pointer has been validated */ (void)host_memxor( &pDataOut[byteCount], chainBlock, blockSize ); } /* * No need to check the return type as pointer has been validated */ (void)host_memcpy( chainBlock, tempBlock, blockSize ); } } /** * Update the byte count to * move to the next block of data. */ byteCount += workingLen; } *pDataOutLen = byteCount; return( VLT_OK ); }
VLT_STS CipherDoFinal( VLT_PU8 pDataIn, VLT_U32 DataInLen, VLT_U32 dataInCapacity, VLT_PU8 pDataOut, VLT_PU32 pDataOutLen, VLT_U32 dataOutCapacity ) { VLT_STS status = VLT_FAIL; if ( ( ST_UNKNOWN == cipherState ) || ( ST_FINALISED == cipherState ) ) { return( ECPHDFNOTSUPPORTED ); } /** * Ensure we haven't been passed * null pointers by the caller. */ if( ( NULL == pDataIn )|| ( NULL == pDataOutLen ) || ( NULL == pDataOut ) ) { return( ECPHUPDNULLPARAM ); } /** * Apply the padding if we have been called to * encrypt data. */ if( ( VLT_ENCRYPT_MODE == operationalMode ) && ( PADDING_NONE != params.paddingScheme ) ) { status = PaddingAdd( params.paddingScheme, theCipher.cipherGetBlockSize(), pDataIn, &DataInLen, dataInCapacity ); } else { status = VLT_OK; } /** * Process the data, encrypt/decrypt */ if( VLT_OK == status ) { status = CipherUpdate( pDataIn, DataInLen, dataInCapacity, pDataOut, pDataOutLen, dataOutCapacity); } if( VLT_OK == status ) { if( VLT_DECRYPT_MODE == operationalMode ) { status = PaddingRemove( params.paddingScheme, theCipher.cipherGetBlockSize(), pDataOut, pDataOutLen ); } } /** * Set the appropriate cipher state; */ cipherState = ST_FINALISED; return( status ); }