#include "tests.h" #include #if defined(BOTAN_HAS_OCB) #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); } size_t 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"; return 1; } return 0; } } size_t test_ocb() { size_t fails = 0; fails += test_ocb_long(128, "B2B41CBF9B05037DA7F16C24A35C1C94"); fails += test_ocb_long(96, "1A4F0654277709A5BDA0D380"); fails += test_ocb_long(64, "B7ECE9D381FE437F"); test_report("OCB long", 3, fails); return fails; } #else size_t test_ocb() { std::cout << "OCB disabled in build\n"; return 0; } #endif