void tee_cipher_final(void *ctx, uint32_t algo) { switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: ecb_done((symmetric_ECB *)ctx); break; case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: cbc_done((symmetric_CBC *)ctx); break; case TEE_ALG_AES_CTR: ctr_done((symmetric_CTR *)ctx); break; case TEE_ALG_AES_XTS: xts_done((symmetric_xts *)ctx); break; case TEE_ALG_AES_CTS: cbc_done(&(((struct symmetric_CTS *)ctx)->cbc)); ecb_done(&(((struct symmetric_CTS *)ctx)->ecb)); break; default: /* TEE_ERROR_NOT_SUPPORTED; */ break; } }
void CBC_Free(CBC_ContextRef ctx) { if(sCBC_ContextIsValid(ctx)) { cbc_done(&ctx->state); ZERO(ctx, sizeof(CBC_Context)); XFREE(ctx); } }
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 ltc_cleanup(void) { TRACE_DEBUG("LTC: Cleaning up ...\n\r"); #if defined(ENCRYPTION_ECB) ecb_done(&sECB); #elif defined(ENCRYPTION_CBC) cbc_done(&sCBC); #elif defined(ENCRYPTION_CTR) ctr_done(&sCTR); #endif TRACE_DEBUG("LTC: Cleanup done.\n\r"); }
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; }
/*++ 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; }
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; }
// ========================================================================= // 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; }
void ltc_cleanup_CBC(void) { TRACE_DEBUG("LTC: Cleaning up CBC...\n\r"); cbc_done(&sCBC); TRACE_DEBUG("LTC: Cleanup done.\n\r"); }
/* * 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; }