From 261a665b1be34f07d5012eed5f6090fd85dd8479 Mon Sep 17 00:00:00 2001 From: lloyd Date: Thu, 14 Mar 2013 18:02:26 +0000 Subject: Add OCB mode, currently encrypt only, and an AEAD interface --- checks/bench.cpp | 1 + checks/ocb.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++ checks/validate.cpp | 2 + checks/validate.h | 2 + 4 files changed, 153 insertions(+) create mode 100644 checks/ocb.cpp (limited to 'checks') diff --git a/checks/bench.cpp b/checks/bench.cpp index 5faba00db..4e6f15fb6 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -76,6 +76,7 @@ const std::string algos[] = { "AES-128/CBC/CTS", "AES-128/CTR-BE", "AES-128/EAX", + "AES-128/OCB", "AES-128/OFB", "AES-128/XTS", "AES-128/CFB(128)", diff --git a/checks/ocb.cpp b/checks/ocb.cpp new file mode 100644 index 000000000..b45b6d2b8 --- /dev/null +++ b/checks/ocb.cpp @@ -0,0 +1,148 @@ + +#include "validate.h" + +#include +#include +#include +#include +#include +#include +//#include + +using namespace Botan; + +// something like this should be in the library +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) + { + //std::unique_ptr ocb = get_aead("AES-128/OCB", ENCRYPTION); + + OCB_Encryption* ocb = new OCB_Encryption(new AES_128); + + ocb->set_key(key); + ocb->set_nonce(&nonce[0], nonce.size()); + ocb->set_associated_data(ad, ad_len); + + Pipe pipe(ocb); + pipe.process_msg(pt, pt_len); + return unlock(pipe.read_all()); + } + +std::vector ocb_decrypt(const SymmetricKey& key, + const std::vector& nonce, + const byte pt[], size_t pt_len, + const byte ad[], size_t ad_len) + { + throw std::runtime_error("Not implemented"); + +#if 0 + OCB_Decryption* ocb = new OCB_Decryption(new AES_128); + + ocb->set_key(key); + ocb->set_nonce(&nonce[0], nonce.size()); + ocb->set_associated_data(ad, ad_len); + + Pipe pipe(ocb); + pipe.process_msg(pt, pt_len); + return pipe.read_all_unlocked(); +#endif + } + +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()); + } + + +void test_ocb_long() + { + SymmetricKey key("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; + + const std::vector C1 = ocb_encrypt(key, N, S, S); + const std::vector C2 = ocb_encrypt(key, N, S, empty); + const std::vector C3 = ocb_encrypt(key, N, empty, S); + + //std::cout << "C_" << i << " = " << hex_encode(C1) << " " << hex_encode(C2) << " " << hex_encode(C3) << "\n"; + + C += C1; + C += C2; + C += C3; + + SHA_256 sha256; + sha256.update(C); + //std::cout << "SHA-256(C_" << i << ") = " << hex_encode(sha256.final()) << "\n"; + } + + // SHA-256 hash of C would be useful + + SHA_256 sha256; + sha256.update(C); + const std::string C_hash = hex_encode(sha256.final()); + const std::string expected_C_hash = "C4E5158067F49356042296B13B050DE00A120EA846073E5E0DACFD0C9F43CC65"; + + if(C_hash != expected_C_hash) + { + std::cout << "OCB-128 long test, C hashes differ\n"; + std::cout << C_hash << " !=\n" << expected_C_hash << "\n"; + } + + //std::cout << "SHA-256(C) = " << C_hash << "\n"; + + N[11] = 0; + const std::vector cipher = ocb_encrypt(key, N, empty, C); + + const std::string expected = "B2B41CBF9B05037DA7F16C24A35C1C94"; + + const std::string cipher_hex = hex_encode(cipher); + + if(cipher_hex != expected) + std::cout << "OCB AES-128 long test mistmatch " << cipher_hex << " != " << expected << "\n"; + else + std::cout << "OCB AES-128 long test OK\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); + + 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"; + else + std::cout << "OCB/AES-128 encrypt OK\n"; + +#if 0 + std::vector dec = ocb_decrypt(key, nonce, ctext, ad); + + std::cout << hex_encode(dec) << "\n"; +#endif + + test_ocb_long(); + } + + diff --git a/checks/validate.cpp b/checks/validate.cpp index 48bc6bd87..55af920cd 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -416,6 +416,8 @@ u32bit do_validation_tests(const std::string& filename, errors++; } + test_ocb(); + return errors; } diff --git a/checks/validate.h b/checks/validate.h index b88837d4b..539154d53 100644 --- a/checks/validate.h +++ b/checks/validate.h @@ -30,4 +30,6 @@ void do_x509_tests(RandomNumberGenerator&); size_t do_tls_tests(RandomNumberGenerator& rng); +void test_ocb(); + #endif -- cgit v1.2.3