/* * (C) 2014,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include "tests.h" #if defined(BOTAN_HAS_AEAD_OCB) #if defined(BOTAN_HAS_AES) #include #include #include #include #include #include using namespace Botan; namespace { std::vector ocb_encrypt(OCB_Encryption& enc, OCB_Decryption& dec, const std::vector& nonce, const std::vector& pt, const std::vector& ad) { enc.set_associated_data(ad.data(), ad.size()); enc.start(nonce.data(), nonce.size()); secure_vector buf(pt.begin(), pt.end()); enc.finish(buf, 0); try { secure_vector ct = buf; dec.set_associated_data(ad.data(), ad.size()); dec.start(nonce.data(), nonce.size()); dec.finish(ct, 0); if(ct != pt) std::cout << "OCB failed to decrypt correctly" << std::endl; } catch(std::exception& e) { std::cout << "OCB round trip error - " << e.what() << std::endl; } return unlock(buf); } size_t test_ocb_long(size_t keylen, size_t taglen, const std::string &expected) { // Test from RFC 7253 Appendix A const std::string algo = "AES-" + std::to_string(keylen); std::unique_ptr aes(BlockCipher::create(algo)); if(!aes) throw Algorithm_Not_Found(algo); OCB_Encryption enc(aes->clone(), taglen / 8); OCB_Decryption dec(aes->clone(), taglen / 8); std::vector key(keylen/8); key[keylen/8-1] = taglen; enc.set_key(key); dec.set_key(key); const std::vector empty; std::vector N(12); std::vector C; for(size_t i = 0; i != 128; ++i) { const std::vector S(i); store_be(static_cast(3*i+1), &N[8]); C += ocb_encrypt(enc, dec, N, S, S); store_be(static_cast(3*i+2), &N[8]); C += ocb_encrypt(enc, dec, N, S, empty); store_be(static_cast(3*i+3), &N[8]); C += ocb_encrypt(enc, dec, N, empty, S); } store_be(static_cast(385), &N[8]); const std::vector cipher = ocb_encrypt(enc, dec, N, empty, C); const std::string cipher_hex = hex_encode(cipher); if(cipher_hex != expected) { std::cout << "OCB " << algo << " long test mistmatch " << cipher_hex << " != " << expected << std::endl; return 1; } return 0; } } size_t test_ocb() { size_t fails = 0; fails += test_ocb_long(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"); fails += test_ocb_long(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"); fails += test_ocb_long(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"); fails += test_ocb_long(128, 96, "77A3D8E73589158D25D01209"); fails += test_ocb_long(192, 96, "05D56EAD2752C86BE6932C5E"); fails += test_ocb_long(256, 96, "5458359AC23B0CBA9E6330DD"); fails += test_ocb_long(128, 64, "192C9B7BD90BA06A"); fails += test_ocb_long(192, 64, "0066BC6E0EF34E24"); fails += test_ocb_long(256, 64, "7D4EA5D445501CBE"); test_report("OCB long", 9, fails); return fails; } #else UNTESTED_WARNING(ocb); #endif // BOTAN_HAS_AES #else SKIP_TEST(ocb); #endif // BOTAN_HAS_AEAD_OCB