#include "validate.h" #include #include #include #include #include //#include using namespace Botan; // something like this should be in the library namespace { std::vector ocb_decrypt(const SymmetricKey& key, const std::vector& nonce, const byte ct[], size_t ct_len, const byte ad[], size_t ad_len) { OCB_Decryption ocb(new AES_128); ocb.set_key(key); ocb.set_associated_data(ad, ad_len); ocb.start(&nonce[0], nonce.size()); secure_vector buf(ct, ct+ct_len); ocb.finish(buf, 0); return unlock(buf); } std::vector ocb_encrypt(const SymmetricKey& key, const std::vector& nonce, const byte pt[], size_t pt_len, const byte ad[], size_t ad_len) { OCB_Encryption ocb(new AES_128); ocb.set_key(key); ocb.set_associated_data(ad, ad_len); ocb.start(&nonce[0], nonce.size()); secure_vector buf(pt, pt+pt_len); ocb.finish(buf, 0); try { std::vector pt2 = ocb_decrypt(key, nonce, &buf[0], buf.size(), ad, ad_len); if(pt_len != pt2.size() || !same_mem(pt, &pt2[0], pt_len)) std::cout << "OCB failed to decrypt correctly\n"; } catch(std::exception& e) { std::cout << "OCB round trip error - " << e.what() << "\n"; } return unlock(buf); } template std::vector ocb_encrypt(const SymmetricKey& key, const std::vector& nonce, const std::vector& pt, const std::vector& ad) { return ocb_encrypt(key, nonce, &pt[0], pt.size(), &ad[0], ad.size()); } template std::vector ocb_decrypt(const SymmetricKey& key, const std::vector& nonce, const std::vector& pt, const std::vector& ad) { return ocb_decrypt(key, nonce, &pt[0], pt.size(), &ad[0], ad.size()); } std::vector ocb_encrypt(OCB_Encryption& ocb, const std::vector& nonce, const std::vector& pt, const std::vector& ad) { ocb.set_associated_data(&ad[0], ad.size()); ocb.start(&nonce[0], nonce.size()); secure_vector buf(pt.begin(), pt.end()); ocb.finish(buf, 0); return unlock(buf); } void test_ocb_long(size_t taglen, const std::string &expected) { OCB_Encryption ocb(new AES_128, taglen/8); ocb.set_key(SymmetricKey("00000000000000000000000000000000")); const std::vector empty; std::vector N(12); std::vector C; for(size_t i = 0; i != 128; ++i) { const std::vector S(i); N[11] = i; C += ocb_encrypt(ocb, N, S, S); C += ocb_encrypt(ocb, N, S, empty); C += ocb_encrypt(ocb, N, empty, S); } N[11] = 0; const std::vector cipher = ocb_encrypt(ocb, N, empty, C); const std::string cipher_hex = hex_encode(cipher); if(cipher_hex != expected) std::cout << "OCB AES-128 long test mistmatch " << cipher_hex << " != " << expected << "\n"; } } void test_ocb() { SymmetricKey key("000102030405060708090A0B0C0D0E0F"); std::vector nonce = hex_decode("000102030405060708090A0B"); std::vector pt = hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627"); std::vector ad = hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627"); const std::string expected = "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635659C623211DEEA0DE30D2C381879F4C8"; std::vector ctext = ocb_encrypt(key, nonce, pt, ad); const std::string ctext_hex = hex_encode(ctext); if(ctext_hex != expected) std::cout << "OCB/AES-128 encrypt test failure\n" << ctext_hex << " !=\n" << expected << "\n"; try { std::vector dec = ocb_decrypt(key, nonce, ctext, ad); if(dec != pt) std::cout << "OCB fails to decrypt\n"; } catch(std::exception& e) { std::cout << "Correct OCB message rejected - " << e.what() << "\n"; } test_ocb_long(128, "B2B41CBF9B05037DA7F16C24A35C1C94"); test_ocb_long(96, "1A4F0654277709A5BDA0D380"); test_ocb_long(64, "B7ECE9D381FE437F"); }