void ltc_init(void) { int cipherID; unsigned char key[ENCRYPTION_KEY_LENGTH]; #if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; #endif TRACE_DEBUG("LTC: Initializing ...\n\r"); // Register cipher register_cipher(&CIPHER_DESC); cipherID = find_cipher(CIPHER_NAME); // Load key ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); #if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) // Load IV ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); #endif // Start decryption mode #if defined(ENCRYPTION_ECB) ecb_start(cipherID, key, ENCRYPTION_KEY_LENGTH, 0, &sECB); #elif defined(ENCRYPTION_CBC) cbc_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, &sCBC); #elif defined(ENCRYPTION_CTR) ctr_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, CTR_COUNTER_BIG_ENDIAN, &sCTR); #endif TRACE_DEBUG("LTC: Initialization done.\n\r"); }
static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) { int rc, cipher_idx, hash_idx; symmetric_CBC cbc; if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR; if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR; rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc); if(rc != CRYPT_OK) return SQLITE_ERROR; cbc_done(&cbc); return SQLITE_OK; }
void CAESModule::decrypt(Tools::CSecureMemory &rPlainText, Tools::CSecureMemory const &rCypherText) const { FASSERT(((rCypherText.getSize()-gIVSize) % gBlockSize) == 0); FASSERT(mKey.getSize() == gKeySize); Tools::CSecureMemory const IV(&rCypherText[0], gIVSize); int ErrorCode; int const Cipher = find_cipher("rijndael"); FASSERT(Cipher != -1); symmetric_CBC CBCMode; ErrorCode = cbc_start(Cipher, &IV[0], &mKey[0], static_cast<unsigned long>(mKey.getSize()), 0, &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Cannot setup AES cipher: ") + std::string(error_to_string(ErrorCode))); } Tools::CSecureMemory PaddedPlainText; PaddedPlainText.allocate(rCypherText.getSize() - gIVSize); ErrorCode = cbc_decrypt(&rCypherText[gIVSize], &PaddedPlainText[0], static_cast<unsigned long>(PaddedPlainText.getSize()), &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error during decryption: ") + std::string(error_to_string(ErrorCode))); } ErrorCode = cbc_done(&CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error when closing decryption stream: ") + std::string(error_to_string(ErrorCode))); } try { Tools::getUnpaddedMemory(rPlainText, PaddedPlainText); } catch(Debug::ExAssert &rError) { UNUSED_ARGUMENT(rError); throw ExKeyError(std::string("{CAESModule} Memory structure of decrypted data is invalid. Cannot delete padding bytes.")); } return; }
void CAESModule::encrypt(Tools::CSecureMemory &rCypherText, Tools::CSecureMemory const &rPlainText) const { FASSERT(mKey.getSize() == gKeySize); Tools::CSecureMemory IV; getRandomIV(IV); Tools::CSecureMemory PaddedPlainText; getPadding(PaddedPlainText, rPlainText); int ErrorCode; rCypherText.allocate(PaddedPlainText.getSize()+IV.getSize()); std::memcpy(&rCypherText[0], &IV[0], IV.getSize()); int const Cipher = find_cipher("rijndael"); FASSERT(Cipher != -1); symmetric_CBC CBCMode; ErrorCode = cbc_start(Cipher, &IV[0], &mKey[0], static_cast<unsigned long>(mKey.getSize()), 0, &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Cannot setup AES cipher: ") + std::string(error_to_string(ErrorCode))); } ErrorCode = cbc_encrypt(&PaddedPlainText[0], &rCypherText[IV.getSize()], static_cast<unsigned long>(PaddedPlainText.getSize()), &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error during encryption: ") + std::string(error_to_string(ErrorCode))); } ErrorCode = cbc_done(&CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error when closing encryption stream: ") + std::string(error_to_string(ErrorCode))); } return; }
void ltc_init_3DES_CBC(void) { int cipherID; unsigned char key[ENCRYPTION_KEY_LENGTH]; unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; TRACE_DEBUG("LTC: Initializing CBC...\n\r"); // Register cipher register_cipher(&des3_desc); cipherID = find_cipher("3des"); // Load key ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); // Load IV ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); // Start decryption mode cbc_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, &sCBC); TRACE_DEBUG("LTC: Initialization done.\n\r"); }
/*++ EncryptCBC EncryptCFB EncryptCTR EncryptECB EncryptOFB Encrypts data in the specified cipher mode and algorithm. Arguments: cipher - Index of the desired cipher. rounds - Number of rounds. counterMode - The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN). iv - The initial vector, must be the length of one block. key - The secret key. keyLength - Length of the secret key, in bytes. data - Plain text (data to encrypt). dataLength - Length of plain text, in bytes. dest - Buffer to receive cipher text (encrypted data). Return Value: A LibTomCrypt status code; CRYPT_OK will be returned if successful. --*/ static int EncryptCBC( 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_CBC state; status = cbc_start(cipher, iv, key, keyLength, rounds, &state); if (status == CRYPT_OK) { status = cbc_encrypt(data, dest, dataLength, &state); cbc_done(&state); } return status; }
/* Generate the actual encryption/integrity keys, using the results of the * key exchange, as specified in section 5.2 of the IETF secsh-transport * draft. This occurs after the DH key-exchange. * * ses.newkeys is the new set of keys which are generated, these are only * taken into use after both sides have sent a newkeys message */ static void gen_new_keys() { unsigned char IV[MAX_IV_LEN]; unsigned char key[MAX_KEY_LEN]; hash_state hs; unsigned int keysize; TRACE(("enter gen_new_keys")); /* the dh_K and hash are the start of all hashes, we make use of that */ sha1_init(&hs); sha1_process_mp(&hs, ses.dh_K); mp_clear(ses.dh_K); m_free(ses.dh_K); sha1_process(&hs, ses.hash, SHA1_HASH_SIZE); m_burn(ses.hash, SHA1_HASH_SIZE); /* client->server IV */ hashkeys(IV, SHA1_HASH_SIZE, &hs, 'A'); /* client->server encryption key */ keysize = ses.newkeys->recv_algo_crypt->keysize; hashkeys(key, keysize, &hs, 'C'); if (cbc_start( find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name), IV, key, keysize, 0, &ses.newkeys->recv_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); } /* server->client IV */ hashkeys(IV, SHA1_HASH_SIZE, &hs, 'B'); /* server->client encryption key */ keysize = ses.newkeys->trans_algo_crypt->keysize; hashkeys(key, keysize, &hs, 'D'); if (cbc_start( find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name), IV, key, keysize, 0, &ses.newkeys->trans_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); } /* MAC key client->server */ keysize = ses.newkeys->recv_algo_mac->keysize; hashkeys(ses.newkeys->recvmackey, keysize, &hs, 'E'); /* MAC key server->client */ keysize = ses.newkeys->trans_algo_mac->keysize; hashkeys(ses.newkeys->transmackey, keysize, &hs, 'F'); #ifndef DISABLE_ZLIB gen_new_zstreams(); #endif /* Switch over to the new keys */ m_burn(ses.keys, sizeof(struct key_context)); m_free(ses.keys); ses.keys = ses.newkeys; ses.newkeys = NULL; TRACE(("leave gen_new_keys")); }
C4Err CBC_Init(Cipher_Algorithm algorithm, const void *key, const void *iv, CBC_ContextRef * ctxOut) { int err = kC4Err_NoErr; CBC_Context* cbcCTX = NULL; int keylen = 0; int cipher = -1; int status = CRYPT_OK; ValidateParam(ctxOut); 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); } cbcCTX = XMALLOC(sizeof (CBC_Context)); CKNULL(cbcCTX); cbcCTX->magic = kCBC_ContextMagic; cbcCTX->algor = algorithm; status = cbc_start(cipher, iv, key, keylen, 0, &cbcCTX->state); CKSTAT; *ctxOut = cbcCTX; done: if(status != CRYPT_OK) { if(cbcCTX) { memset(cbcCTX, sizeof (CBC_Context), 0); XFREE(cbcCTX); } err = sCrypt2C4Err(status); } return err; }
// ========================================================================= // Decryption function // Note: PlaintextLength must be set to the size of the PlaintextData buffer on // entry; on exit, this will be set to the size of the buffer used. NTSTATUS ImpCypherDecryptSectorData( IN GUID* CypherGUID, IN LARGE_INTEGER SectorID, // Indexed from zero IN int SectorSize, // In bytes IN int KeyLength, // In bits IN FREEOTFEBYTE* Key, IN char* KeyASCII, // ASCII representation of "Key" IN int IVLength, // In bits IN FREEOTFEBYTE* IV, IN int CyphertextLength, // In bytes IN FREEOTFEBYTE* CyphertextData, OUT FREEOTFEBYTE* PlaintextData ) { NTSTATUS status = STATUS_SUCCESS; // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE]; int cipher; symmetric_CBC *cbc; int errnum; DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDecryptData\n"))); if (!( (IsEqualGUID(&CIPHER_GUID_CAST5, CypherGUID)) )) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n"))); status = STATUS_INVALID_PARAMETER; } // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL if ( (IVLength == 0) || (IV == NULL) ) { FREEOTFE_MEMZERO(<cNullIV, sizeof(ltcNullIV)); IV = (char*)<cNullIV; } cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC)); FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC)); if NT_SUCCESS(status) { status = InitLTCCypher(&cipher); } if NT_SUCCESS(status) { // Start a CBC session if ((errnum = cbc_start( cipher, IV, Key, (KeyLength/8), 0, cbc )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum)); } else { if ((errnum = cbc_decrypt( CyphertextData, PlaintextData, CyphertextLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt/decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } cbc_done(cbc); } } SecZeroMemory(cbc, sizeof(symmetric_CBC)); FREEOTFE_FREE(cbc); DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDecryptData\n"))); return status; }
// ========================================================================= // Encrypt/Decrypt function // Note: PlaintextLength must be set to the size of the PlaintextData buffer on // entry; on exit, this will be set to the size of the buffer used. NTSTATUS ImpCypherCryptData( IN GUID* CypherGUID, IN LARGE_INTEGER SectorID, IN int SectorSize, // In bytes IN int KeyLength, // In bits IN FREEOTFEBYTE* Key, IN char* KeyASCII, // ASCII representation of "Key" IN int IVLength, // In bits IN FREEOTFEBYTE* IV, IN BOOLEAN encryptNotDecrypt, // TRUE = encrypt; FALSE = decrypt IN int InLength, // In bytes IN FREEOTFEBYTE* InData, OUT FREEOTFEBYTE* OutData ) { NTSTATUS status = STATUS_SUCCESS; // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE]; int cipher; symmetric_CBC *cbc; symmetric_LRW *lrw; symmetric_xts *xts; int errnum; CYPHER_MODE mode; int keySizeUnderlying; LARGE_INTEGER blockID64; INTEGER_128 blockID128; DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDecryptData\n"))); status = DetermineCypherDetails( CypherGUID, &keySizeUnderlying, &mode ); // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL if ( (IVLength == 0) || (IV == NULL) ) { FREEOTFE_MEMZERO(<cNullIV, sizeof(ltcNullIV)); IV = (char*)<cNullIV; } // Sanity check on key supplied if NT_SUCCESS(status) { switch (mode) { case CYPHER_MODE_CBC: { if (KeyLength != keySizeUnderlying) { status = STATUS_INVALID_PARAMETER; } break; } case CYPHER_MODE_XTS: { if (KeyLength != (2 * keySizeUnderlying)) { status = STATUS_INVALID_PARAMETER; } break; } case CYPHER_MODE_LRW: { if (KeyLength != (keySizeUnderlying + (twofish_desc.block_length * 8))) { status = STATUS_INVALID_PARAMETER; } break; } } } if NT_SUCCESS(status) { status = InitLTCCypher(&cipher); } if NT_SUCCESS(status) { switch (mode) { case CYPHER_MODE_CBC: { cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC)); FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC)); // Start a CBC session if ((errnum = cbc_start( cipher, IV, Key, (keySizeUnderlying/8), 0, cbc )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = cbc_encrypt( InData, OutData, InLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = cbc_decrypt( InData, OutData, InLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } cbc_done(cbc); } SecZeroMemory(cbc, sizeof(symmetric_CBC)); FREEOTFE_FREE(cbc); break; } case CYPHER_MODE_LRW: { lrw = FREEOTFE_MEMALLOC(sizeof(symmetric_LRW)); FREEOTFE_MEMZERO(lrw, sizeof(symmetric_LRW)); // Generate index in correct format // LRW uses: // *) The block index (i.e. the number of 128 bit blocks) // *) The first block has block index 1 - not 0! // *) Bigendian format // Note: LTC increments this itself as it processes each block SectorIDToBlockIdx_64Bit(SectorID, SectorSize, &blockID64); LARGE_INTEGER__To__INTEGER_128_BigEndian( blockID64, blockID128 ); IV = blockID128; // Start a LRW session if ((errnum = lrw_start( cipher, IV, Key, (keySizeUnderlying/8), // 128 bits tweak key begins after the // cypher key (Key + (keySizeUnderlying/8)), 0, lrw )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start LRW session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = lrw_encrypt( InData, OutData, InLength, lrw )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = lrw_decrypt( InData, OutData, InLength, lrw )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } lrw_done(lrw); } SecZeroMemory(lrw, sizeof(symmetric_LRW)); FREEOTFE_FREE(lrw); break; } case CYPHER_MODE_XTS: { xts = FREEOTFE_MEMALLOC(sizeof(symmetric_xts)); FREEOTFE_MEMZERO(xts, sizeof(symmetric_xts)); // Generate index in correct format // XTS uses: // *) The sector index (i.e. the number of N-bit sectors) // *) The first sector is sector 0 // *) Littleendian format LARGE_INTEGER__To__INTEGER_128_LittleEndian( SectorID, blockID128 ); // Start an XTS session if ((errnum = xts_start( cipher, Key, &(Key[keySizeUnderlying/8]), (keySizeUnderlying/8), 0, xts )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start XTS session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = xts_encrypt( InData, InLength, OutData, blockID128, xts )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = xts_decrypt( InData, InLength, OutData, blockID128, xts )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } xts_done(xts); } SecZeroMemory(xts, sizeof(symmetric_xts)); FREEOTFE_FREE(xts); break; } } } DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDecryptData\n"))); return status; }
int modes_test(void) { unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; int cipher_idx; #ifdef LTC_CBC_MODE symmetric_CBC cbc; #endif #ifdef LTC_CFB_MODE symmetric_CFB cfb; #endif #ifdef LTC_OFB_MODE symmetric_OFB ofb; #endif unsigned long l; /* make a random pt, key and iv */ yarrow_read(pt, 64, &yarrow_prng); yarrow_read(key, 16, &yarrow_prng); yarrow_read(iv, 16, &yarrow_prng); /* get idx of AES handy */ cipher_idx = find_cipher("aes"); if (cipher_idx == -1) { fprintf(stderr, "test requires AES"); return 1; } #ifdef LTC_F8_MODE DO(f8_test_mode()); #endif #ifdef LTC_LRW_MODE DO(lrw_test()); #endif #ifdef LTC_CBC_MODE /* test CBC mode */ /* encode the block */ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); l = sizeof(iv2); DO(cbc_getiv(iv2, &l, &cbc)); if (l != 16 || memcmp(iv2, iv, 16)) { fprintf(stderr, "cbc_getiv failed"); return 1; } DO(cbc_encrypt(pt, ct, 64, &cbc)); /* decode the block */ DO(cbc_setiv(iv2, l, &cbc)); zeromem(tmp, sizeof(tmp)); DO(cbc_decrypt(ct, tmp, 64, &cbc)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "CBC failed"); return 1; } #endif #ifdef LTC_CFB_MODE /* test CFB mode */ /* encode the block */ DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); l = sizeof(iv2); DO(cfb_getiv(iv2, &l, &cfb)); /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ if (l != 16) { fprintf(stderr, "cfb_getiv failed"); return 1; } DO(cfb_encrypt(pt, ct, 64, &cfb)); /* decode the block */ DO(cfb_setiv(iv, l, &cfb)); zeromem(tmp, sizeof(tmp)); DO(cfb_decrypt(ct, tmp, 64, &cfb)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "CFB failed"); return 1; } #endif #ifdef LTC_OFB_MODE /* test OFB mode */ /* encode the block */ DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); l = sizeof(iv2); DO(ofb_getiv(iv2, &l, &ofb)); if (l != 16 || memcmp(iv2, iv, 16)) { fprintf(stderr, "ofb_getiv failed"); return 1; } DO(ofb_encrypt(pt, ct, 64, &ofb)); /* decode the block */ DO(ofb_setiv(iv2, l, &ofb)); zeromem(tmp, sizeof(tmp)); DO(ofb_decrypt(ct, tmp, 64, &ofb)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "OFB failed"); return 1; } #endif #ifdef LTC_CTR_MODE DO(ctr_test()); #endif return 0; }
TEE_Result tee_cipher_init3(void *ctx, uint32_t algo, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len) { TEE_Result res; int ltc_res, ltc_cipherindex; uint8_t *real_key, key_array[24]; size_t real_key_len; struct symmetric_CTS *cts; res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); if (res != TEE_SUCCESS) return TEE_ERROR_NOT_SUPPORTED; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: ltc_res = ecb_start( ltc_cipherindex, key1, key1_len, 0, (symmetric_ECB *)ctx); break; case TEE_ALG_DES3_ECB_NOPAD: /* either des3 or des2, depending on the size of the key */ get_des2_key(key1, key1_len, key_array, &real_key, &real_key_len); ltc_res = ecb_start( ltc_cipherindex, real_key, real_key_len, 0, (symmetric_ECB *)ctx); break; case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: if (iv_len != (size_t)cipher_descriptor[ltc_cipherindex].block_length) return TEE_ERROR_BAD_PARAMETERS; ltc_res = cbc_start( ltc_cipherindex, iv, key1, key1_len, 0, (symmetric_CBC *)ctx); break; case TEE_ALG_DES3_CBC_NOPAD: /* either des3 or des2, depending on the size of the key */ get_des2_key(key1, key1_len, key_array, &real_key, &real_key_len); if (iv_len != (size_t)cipher_descriptor[ltc_cipherindex].block_length) return TEE_ERROR_BAD_PARAMETERS; ltc_res = cbc_start( ltc_cipherindex, iv, real_key, real_key_len, 0, (symmetric_CBC *)ctx); break; case TEE_ALG_AES_CTR: if (iv_len != (size_t)cipher_descriptor[ltc_cipherindex].block_length) return TEE_ERROR_BAD_PARAMETERS; ltc_res = ctr_start( ltc_cipherindex, iv, key1, key1_len, 0, CTR_COUNTER_BIG_ENDIAN, (symmetric_CTR *)ctx); break; case TEE_ALG_AES_CTS: cts = (struct symmetric_CTS *)ctx; res = tee_cipher_init3( (void *)(&(cts->ecb)), TEE_ALG_AES_ECB_NOPAD, mode, key1, key1_len, key2, key2_len, iv, iv_len); if (res != TEE_SUCCESS) return res; res = tee_cipher_init3( (void *)(&(cts->cbc)), TEE_ALG_AES_CBC_NOPAD, mode, key1, key1_len, key2, key2_len, iv, iv_len); if (res != TEE_SUCCESS) return res; ltc_res = CRYPT_OK; break; case TEE_ALG_AES_XTS: if (key1_len != key2_len) return TEE_ERROR_BAD_PARAMETERS; ltc_res = xts_start( ltc_cipherindex, key1, key2, key1_len, 0, (symmetric_xts *)ctx); break; default: return TEE_ERROR_NOT_SUPPORTED; } if (ltc_res == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; }
int modes_test(void) { unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; int x, cipher_idx; symmetric_CBC cbc; symmetric_CFB cfb; symmetric_OFB ofb; symmetric_CTR ctr; unsigned long l; /* make a random pt, key and iv */ yarrow_read(pt, 64, &test_yarrow); yarrow_read(key, 16, &test_yarrow); yarrow_read(iv, 16, &test_yarrow); /* get idx of AES handy */ cipher_idx = find_cipher("aes"); if (cipher_idx == -1) { printf("test requires AES"); return 1; } /* test CBC mode */ /* encode the block */ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); l = sizeof(iv2); DO(cbc_getiv(iv2, &l, &cbc)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("cbc_getiv failed"); return 1; } for (x = 0; x < 4; x++) { DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc)); } /* decode the block */ DO(cbc_setiv(iv2, l, &cbc)); zeromem(tmp, sizeof(tmp)); for (x = 0; x < 4; x++) { DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc)); } if (memcmp(tmp, pt, 64) != 0) { printf("CBC failed"); return 1; } /* test CFB mode */ /* encode the block */ DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); l = sizeof(iv2); DO(cfb_getiv(iv2, &l, &cfb)); /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ if (l != 16) { printf("cfb_getiv failed"); return 1; } DO(cfb_encrypt(pt, ct, 64, &cfb)); /* decode the block */ DO(cfb_setiv(iv, l, &cfb)); zeromem(tmp, sizeof(tmp)); DO(cfb_decrypt(ct, tmp, 64, &cfb)); if (memcmp(tmp, pt, 64) != 0) { printf("CFB failed"); return 1; } /* test OFB mode */ /* encode the block */ DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); l = sizeof(iv2); DO(ofb_getiv(iv2, &l, &ofb)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("ofb_getiv failed"); return 1; } DO(ofb_encrypt(pt, ct, 64, &ofb)); /* decode the block */ DO(ofb_setiv(iv2, l, &ofb)); zeromem(tmp, sizeof(tmp)); DO(ofb_decrypt(ct, tmp, 64, &ofb)); if (memcmp(tmp, pt, 64) != 0) { printf("OFB failed"); return 1; } /* test CTR mode */ /* encode the block */ DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr)); l = sizeof(iv2); DO(ctr_getiv(iv2, &l, &ctr)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("ctr_getiv failed"); return 1; } DO(ctr_encrypt(pt, ct, 64, &ctr)); /* decode the block */ DO(ctr_setiv(iv2, l, &ctr)); zeromem(tmp, sizeof(tmp)); DO(ctr_decrypt(ct, tmp, 64, &ctr)); if (memcmp(tmp, pt, 64) != 0) { printf("CTR failed"); return 1; } return 0; }
/* * Perform an encrypt/decrypt operation to/from files using AES+CBC+PKCS7 pad. * Set encrypt to 1 to encrypt, 0 to decrypt. * * Input: in/out files, key, iv, and mode * Output: CRYPT_OK if no error * Side Effects: bytes slurped from infile, pushed to outfile, fds updated. */ int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv, int encrypt) { union paddable inbuf, outbuf; int cipher, ret; symmetric_CBC cbc; size_t nb; /* Register your cipher! */ cipher = register_cipher(&aes_desc); if(cipher == -1) return CRYPT_INVALID_CIPHER; /* Start a CBC session with cipher/key/val params */ ret = cbc_start(cipher, iv, key, KEY_LENGTH, 0, &cbc); if( ret != CRYPT_OK ) return -1; do { /* Get bytes from the source */ nb = fread(inbuf.unpad, 1, sizeof(inbuf.unpad), infd); if(!nb) return encrypt ? CRYPT_OK : CRYPT_ERROR; /* Barf if we got a read error */ if(ferror(infd)) return CRYPT_ERROR; if(encrypt) { /* We're encrypting, so pad first (if at EOF) and then crypt */ if(feof(infd)) nb = pkcs7_pad(&inbuf, nb, aes_desc.block_length, 1); ret = cbc_encrypt(inbuf.pad, outbuf.pad, nb, &cbc); if(ret != CRYPT_OK) return ret; } else { /* We're decrypting, so decrypt and then unpad if at EOF */ ret = cbc_decrypt(inbuf.unpad, outbuf.unpad, nb, &cbc); if( ret != CRYPT_OK ) return ret; if( feof(infd) ) nb = pkcs7_pad(&outbuf, nb, aes_desc.block_length, 0); if(nb == 0) /* The file didn't decrypt correctly */ return CRYPT_ERROR; } /* Push bytes to outfile */ if(fwrite(outbuf.unpad, 1, nb, outfd) != nb) return CRYPT_ERROR; } while(!feof(infd)); /* Close up */ cbc_done(&cbc); return CRYPT_OK; }