1 /** 2 * Cipher Modes 3 * 4 * Copyright: 5 * (C) 2013 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.modes.cipher_mode; 12 13 public import botan.algo_base.transform; 14 import botan.constants; 15 16 /** 17 * Interface for cipher modes 18 */ 19 abstract class CipherMode : KeyedTransform, Transformation 20 { 21 public: 22 /** 23 * Returns true iff this mode provides authentication as well as 24 * confidentiality. 25 */ 26 abstract bool authenticated() const { return false; } 27 } 28 29 static if (BOTAN_TEST): 30 31 import botan.test; 32 import botan.codec.hex; 33 import botan.libstate.lookup; 34 import botan.filters.filters; 35 import core.atomic; 36 import memutils.hashmap; 37 38 private shared size_t total_tests; 39 SecureVector!ubyte runMode()(string algo, CipherDir dir, 40 auto const ref SecureVector!ubyte pt, 41 auto const ref SecureVector!ubyte nonce, 42 auto const ref SecureVector!ubyte key) 43 { 44 /* 45 Unique!CipherMode cipher = getCipher(algo, dir); 46 47 cipher.setKey(key); 48 cipher.start(nonce); 49 50 SecureVector!ubyte ct = pt; 51 cipher.finish(ct); 52 */ 53 54 Pipe pipe = Pipe(getCipher(algo, SymmetricKey(key.clone), InitializationVector(nonce.clone), dir)); 55 56 pipe.processMsg(pt.ptr, pt.length); 57 58 return pipe.readAll(); 59 } 60 61 size_t modeTest(string algo, string pt, string ct, string key_hex, string nonce_hex) 62 { 63 auto nonce = hexDecodeLocked(nonce_hex); 64 auto key = hexDecodeLocked(key_hex); 65 66 size_t fails = 0; 67 68 const string ct2 = hexEncode(runMode(algo, ENCRYPTION, hexDecodeLocked(pt), nonce, key)); 69 atomicOp!"+="(total_tests, 1); 70 if (ct != ct2) 71 { 72 logError(algo ~ " got ct " ~ ct2 ~ " expected " ~ ct); 73 ++fails; 74 } 75 76 const string pt2 = hexEncode(runMode(algo, DECRYPTION, hexDecodeLocked(ct), nonce, key)); 77 atomicOp!"+="(total_tests, 1); 78 if (pt != pt2) 79 { 80 logError(algo ~ " got pt " ~ pt2 ~ " expected " ~ pt); 81 ++fails; 82 } 83 84 return fails; 85 } 86 87 static if (BOTAN_HAS_TESTS && !SKIP_CIPHER_MODE_TEST) unittest { 88 logDebug("Testing cipher_mode.d ..."); 89 auto test = delegate(string input) 90 { 91 File vec = File(input, "r"); 92 93 return runTestsBb(vec, "Mode", "Out", true, 94 (ref HashMap!(string, string) m) { 95 return modeTest(m["Mode"], m["In"], m["Out"], m["Key"], m["Nonce"]); 96 }); 97 }; 98 99 size_t fails = runTestsInDir("test_data/modes", test); 100 101 testReport("cipher_mode", total_tests, fails); 102 }