C4Err ECB_Decrypt(Cipher_Algorithm algorithm, const void * key, const void * in, size_t bytesIn, void * out ) { int err = kC4Err_NoErr; int status = CRYPT_OK; symmetric_ECB ECB; int keylen = 0; int cipher = -1; switch(algorithm) { case kCipher_Algorithm_AES128: keylen = 128 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_AES192: keylen = 192 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_AES256: keylen = 256 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_2FISH256: keylen = 256 >> 3; cipher = find_cipher("twofish"); break; default: RETERR(kC4Err_BadCipherNumber); } status = ecb_start(cipher, key, keylen, 0, &ECB ); CKSTAT; status = ecb_decrypt(in, out, bytesIn, &ECB); CKSTAT; done: ecb_done(&ECB); if(status != CRYPT_OK) err = sCrypt2C4Err(status); return err; }
static int DecryptECB( int cipher, int rounds, int counterMode, unsigned char *iv, unsigned char *key, unsigned long keyLength, unsigned char *data, unsigned long dataLength, unsigned char *dest ) { int status; symmetric_ECB state; status = ecb_start(cipher, key, keyLength, rounds, &state); if (status == CRYPT_OK) { status = ecb_decrypt(data, dest, dataLength, &state); ecb_done(&state); } return status; }
static int RunCipherKAT( katvector *kat) { int err = CRYPT_OK; char* name = NULL; uint8_t *out = NULL; size_t alloc_len = MAX(kat->EBClen, kat->CBClen); symmetric_ECB ECB; symmetric_CBC CBC; out = malloc(alloc_len); ZERO(out, alloc_len); // err = cipher_is_valid(kat->algor); CKERR; name = cipher_name(kat->algor); printf("\t%-7s %d ", name, kat->keysize); printf("%6s", "ECB"); DO( ecb_start(kat->algor, kat->key, kat->keysize>>3, 0, &ECB)); DO( ecb_encrypt(kat->PT, out, kat->PTlen, &ECB)) /* check against know-answer */ DO( compareResults( kat->EBC, out, kat->EBClen , kResultFormat_Byte, "Symmetric Encrypt")); DO(ecb_decrypt(out, out, kat->PTlen, &ECB)); /* check against orginal plain-text */ DO(compareResults( kat->PT, out, kat->PTlen , kResultFormat_Byte, "Symmetric Decrypt")); printf("%6s", "CBC"); DO(cbc_start(kat->algor, kat->IV, kat->key, kat->keysize>>3, 0, &CBC)); DO(cbc_encrypt(kat->PT, out, kat->PTlen, &CBC)); /* check against know-answer */ DO(compareResults( kat->CBC, out, kat->CBClen , kResultFormat_Byte, "Symmetric Encrypt")); // reset CBC befire decrypt*/ cbc_done(&CBC); DO(cbc_start(kat->algor, kat->IV, kat->key, kat->keysize>>3, 0, &CBC)); DO(cbc_decrypt(out, out, kat->PTlen, &CBC)); /* check against orginal plain-text */ DO( compareResults( kat->PT, out, kat->PTlen , kResultFormat_Byte, "Symmetric Decrypt")); done: ecb_done(&ECB); cbc_done(&CBC); free(out); printf("\n"); return err; }
/*! * \brief Main application function. \n * -> Initialize clock \n * -> Initialize USART for print functions \n * -> Initialize AES to generate Key schedule for AES-128 \n * -> Based on the AES mode enabled in conf_example.h file, \n * execute encryption and decryption of a message and \n * compare them against input data to check its functionality. \n * -> The decrypted message can be viewed on the COM port terminal \n */ int main(void) { /* * Initialize the System clock * Note: Clock should be configured in conf_clock.h */ system_init(); /* Configure EDBG SERCOM UART to print messages */ configure_usart(); /* Generate key schedule for AES-128 from the Cipher Key */ aes_init(key_vectors); /* Print status messages */ printf("AES key generated successfully!..\r\n"); /* Print Input message for user */ printf("\n The message to be encrypted is:\r\n"); printf("\n %s \r\n",pText); /* * Perform ECB, CFB, OFB, CTR and CBC Encryption and Decryption * based on the mode enabled in conf_example.h. User can choose * the mode that he wants to evaluate. By default, all modes are * enabled. * The decrypted message is printed to EDBG virtual COM port. * If the decrypted message is same as the input plain text, * it ensures the working of each mode. */ #if (AES_ECB == true) //Perform ECB Encryption ecb_encrypt( pText, cText, sizeof(pText) ); for (volatile int i = 0; i < 1000; i++); //Perform ECB Decryption ecb_decrypt( cText, pText1, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-ECB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_CFB == true) //Perform CFB Encryption cfb_encrypt(pText, cText, init_vector, CFB_MODE_128, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform CFB Decryption cfb_decrypt(cText, pText1, init_vector, CFB_MODE_128, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-CFB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_OFB == true) //Perform OFB Encryption ofb_encrypt(pText, cText, init_vector, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform OFB Decryption ofb_encrypt(cText, pText1, init_vector, sizeof(cText)); //Print decrytped message printf("\n Decrypted message using AES-OFB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_CTR == true) /* Initialize Counter block with initialization vector, * nonce and counter value */ ctr_blk_t counter_vector = { .i_vector = AES_CTR_IVECTOR, .nonce = AES_CTR_NONCE, .counter = AES_CTR_COUNTER }; //Perform CTR Encryption ctr_encrypt_decrypt(pText, cText, &counter_vector, sizeof(pText)); //Send Counter block value to decryptor for (volatile int i = 0; i < 1000; i++); counter_vector.i_vector = AES_CTR_IVECTOR; counter_vector.nonce = AES_CTR_NONCE; counter_vector.counter = AES_CTR_COUNTER; //Perform CTR Decryption ctr_encrypt_decrypt(cText, pText1, &counter_vector, sizeof(pText1)); //Print decrypted message printf("\n Decrypted message using AES-CTR mode : \r\n"); printf("\n %s \r\n",pText1); #endif /*! \warning CBC mode is done at the last as it process input plain text * during encryption and so the plain text value is not retained. * For testing purpose, to preserve the input plan text for testing with * other modes, this mode is added at the last. */ #if (AES_CBC == true) //Perform CBC Encryption cbc_encrypt(pText, cText, init_vector, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform CBC Decryption cbc_decrypt(cText, pText1, init_vector, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-CBC mode : \r\n"); printf("\n %s \r\n",pText1); #endif /* Forever loop */ while(1); }
int ltc_decrypt(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) { #if defined(ENCRYPTION_ECB) if (ecb_decrypt(cipherText, plainText, length, &sECB) != CRYPT_OK) { #elif defined(ENCRYPTION_CBC) if (cbc_decrypt(cipherText, plainText, length, &sCBC) != CRYPT_OK) { #elif defined(ENCRYPTION_CTR) if (ctr_decrypt(cipherText, plainText, length, &sCTR) != CRYPT_OK) { #endif return 0; } else { return 1; } } #endif //------------------------------------------------------------------------------ /// Decrypts a block of data in CBC mode /// \param Data to decrypt /// \param Buffer to store decrypted data /// \param Length of data /// \return 1 if successful, 0 otherwise. //------------------------------------------------------------------------------ #ifndef ONLY_ONE_ENCRYPTION int ltc_decrypt_CBC(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) { if (cbc_decrypt(cipherText, plainText, length, &sCBC) != CRYPT_OK) { return 0; } else { return 1; } } //------------------------------------------------------------------------------ /// Decrypts a block of data in CTR mode /// \param Data to decrypt /// \param Buffer to store decrypted data /// \param Length of data /// \return 1 if successful, 0 otherwise. //------------------------------------------------------------------------------ int ltc_decrypt_CTR(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) { if (ctr_decrypt(cipherText, plainText, length, &sCTR) != CRYPT_OK) { return 0; } else { return 1; } } //------------------------------------------------------------------------------ /// Decrypts a block of data in ECB mode /// \param Data to decrypt /// \param Buffer to store decrypted data /// \param Length of data /// \return 1 if successful, 0 otherwise. //------------------------------------------------------------------------------ int ltc_decrypt_ECB(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) { if (ecb_decrypt(cipherText, plainText, length, &sECB) != CRYPT_OK) { return 0; } else { return 1; } }
TEE_Result tee_cipher_update(void *ctx, uint32_t algo, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result res; int ltc_res = CRYPT_OK; size_t block_size; uint8_t tmp_block[64], tmp2_block[64]; int nb_blocks, len_last_block; struct symmetric_CTS *cts; /* * Check that the block contains the correct number of data, apart * for the last block in some XTS / CTR / XTS mode */ res = tee_cipher_get_block_size(algo, &block_size); if (res != TEE_SUCCESS) return res; if ((len % block_size) != 0) { if (!last_block) return TEE_ERROR_BAD_PARAMETERS; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: return TEE_ERROR_BAD_PARAMETERS; case TEE_ALG_AES_CTR: case TEE_ALG_AES_XTS: case TEE_ALG_AES_CTS: /* * These modes doesn't require padding for the last * block. * * This isn't entirely true, both XTS and CTS can only * encrypt minimum one block and also they need at least * one complete block in the last update to finish the * encryption. The algorithms are supposed to detect * that, we're only making sure that all data fed up to * that point consists of complete blocks. */ break; default: return TEE_ERROR_NOT_SUPPORTED; } } switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: if (mode == TEE_MODE_ENCRYPT) ltc_res = ecb_encrypt(data, dst, len, (symmetric_ECB *)ctx); else ltc_res = ecb_decrypt(data, dst, len, (symmetric_ECB *)ctx); break; case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: if (mode == TEE_MODE_ENCRYPT) ltc_res = cbc_encrypt(data, dst, len, (symmetric_CBC *)ctx); else ltc_res = cbc_decrypt(data, dst, len, (symmetric_CBC *)ctx); break; case TEE_ALG_AES_CTR: if (mode == TEE_MODE_ENCRYPT) ltc_res = ctr_encrypt(data, dst, len, (symmetric_CTR *)ctx); else ltc_res = ctr_decrypt(data, dst, len, (symmetric_CTR *)ctx); break; case TEE_ALG_AES_XTS: return TEE_ERROR_NOT_SUPPORTED; /* if (mode == TEE_MODE_ENCRYPT) { ltc_res = xts_encrypt(data, dst, len, (symmetric_xts *)ctx); } else { ltc_res = xts_decrypt(data, dst, len, (symmetric_xts *)ctx); } */ break; case TEE_ALG_AES_CTS: /* * From http://en.wikipedia.org/wiki/Ciphertext_stealing * CBC ciphertext stealing encryption using a standard * CBC interface: * 1. Pad the last partial plaintext block with 0. * 2. Encrypt the whole padded plaintext using the * standard CBC mode. * 3. Swap the last two ciphertext blocks. * 4. Truncate the ciphertext to the length of the * original plaintext. * * CBC ciphertext stealing decryption using a standard * CBC interface * 1. Dn = Decrypt (K, Cn-1). Decrypt the second to last * ciphertext block. * 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the * nearest multiple of the block size using the last * B-M bits of block cipher decryption of the * second-to-last ciphertext block. * 3. Swap the last two ciphertext blocks. * 4. Decrypt the (modified) ciphertext using the standard * CBC mode. * 5. Truncate the plaintext to the length of the original * ciphertext. */ cts = (struct symmetric_CTS *)ctx; if (!last_block) return tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, last_block, data, len, dst); /* Compute the last block length and check constraints */ if (block_size > 64) return TEE_ERROR_BAD_STATE; nb_blocks = ((len + block_size - 1) / block_size); if (nb_blocks < 2) return TEE_ERROR_BAD_STATE; len_last_block = len % block_size; if (len_last_block == 0) len_last_block = block_size; if (mode == TEE_MODE_ENCRYPT) { memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memset(tmp_block + len_last_block, 0, block_size - len_last_block); res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 1) * block_size, dst); if (res != TEE_SUCCESS) return res; memcpy(dst + (nb_blocks - 1) * block_size, dst + (nb_blocks - 2) * block_size, len_last_block); res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + (nb_blocks - 2) * block_size); if (res != TEE_SUCCESS) return res; } else { /* 1. Decrypt the second to last ciphertext block */ res = tee_cipher_update( &cts->ecb, TEE_ALG_AES_ECB_NOPAD, mode, 0, data + (nb_blocks - 2) * block_size, block_size, tmp2_block); if (res != TEE_SUCCESS) return res; /* 2. Cn = Cn || Tail (Dn, B-M) */ memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memcpy(tmp_block + len_last_block, tmp2_block + len_last_block, block_size - len_last_block); /* 3. Swap the last two ciphertext blocks */ /* done by passing the correct buffers in step 4. */ /* 4. Decrypt the (modified) ciphertext */ if (nb_blocks > 2) { res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 2) * block_size, dst); if (res != TEE_SUCCESS) return res; } res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + ((nb_blocks - 2) * block_size)); if (res != TEE_SUCCESS) return res; res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data + ((nb_blocks - 2) * block_size), block_size, tmp_block); if (res != TEE_SUCCESS) return res; /* 5. Truncate the plaintext */ memcpy(dst + (nb_blocks - 1) * block_size, tmp_block, len_last_block); break; } break; default: return TEE_ERROR_NOT_SUPPORTED; } if (ltc_res == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; }
static inline void ecb_wrapper(void* inbuf, void* outbuf, size_t size, uint32_t mode, uint8_t *ctr) { ecb_decrypt(inbuf, outbuf, size, mode); }