std::string tls_policy_string(const std::string& policy_str) { std::unique_ptr<Botan::TLS::Policy> policy; if(policy_str == "default") { policy.reset(new Botan::TLS::Policy); } else if(policy_str == "suiteb_128") { policy.reset(new Botan::TLS::NSA_Suite_B_128); } else if(policy_str == "suiteb_192") { policy.reset(new Botan::TLS::NSA_Suite_B_192); } else if(policy_str == "bsi") { policy.reset(new Botan::TLS::BSI_TR_02102_2); } else if(policy_str == "strict") { policy.reset(new Botan::TLS::Strict_Policy); } else if(policy_str == "datagram") { policy.reset(new Botan::TLS::Datagram_Policy); } else { throw Test_Error("Unknown TLS policy type '" + policy_str + "'"); } return policy->to_string(); }
std::string read_tls_policy(const std::string& policy_str) { const std::string fspath = Test::data_file("tls-policy/" + policy_str + ".txt"); std::ifstream is(fspath.c_str()); if(!is.good()) { throw Test_Error("Missing policy file " + fspath); } Botan::TLS::Text_Policy policy(is); return policy.to_string(); }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { const std::vector<uint8_t> key = get_req_bin(vars, "Key"); const std::vector<uint8_t> expected = get_req_bin(vars, "Out"); const std::vector<uint8_t> nonce = get_opt_bin(vars, "Nonce"); const size_t seek = get_opt_sz(vars, "Seek", 0); std::vector<uint8_t> input = get_opt_bin(vars, "In"); if(input.empty()) input.resize(expected.size()); Test::Result result(algo); const std::vector<std::string> providers = provider_filter(Botan::StreamCipher::providers(algo)); if(providers.empty()) { result.note_missing("block cipher " + algo); return result; } for(auto&& provider_ask : providers) { std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider_ask)); if(!cipher) { result.test_failure("Stream " + algo + " supported by " + provider_ask + " but not found"); continue; } const std::string provider(cipher->provider()); result.test_is_nonempty("provider", provider); result.test_eq(provider, cipher->name(), algo); cipher->set_key(key); if(nonce.size()) { if(!cipher->valid_iv_length(nonce.size())) throw Test_Error("Invalid nonce for " + algo); cipher->set_iv(nonce.data(), nonce.size()); } else { /* * If no nonce was set then implicitly the cipher is using a * null/empty nonce. Call set_iv with such a nonce to make sure * set_iv accepts it. */ if(!cipher->valid_iv_length(0)) throw Test_Error("Stream cipher " + algo + " requires nonce but none provided"); cipher->set_iv(nullptr, 0); } if (seek != 0) cipher->seek(seek); // Test that clone works and does not affect parent object std::unique_ptr<Botan::StreamCipher> clone(cipher->clone()); result.confirm("Clone has different pointer", cipher.get() != clone.get()); result.test_eq("Clone has same name", cipher->name(), clone->name()); clone->set_key(Test::rng().random_vec(cipher->maximum_keylength())); std::vector<uint8_t> buf = input; cipher->encrypt(buf); cipher->clear(); result.test_eq(provider, "encrypt", buf, expected); } return result; }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { Test::Result result("OCB wide block long test"); const std::vector<uint8_t> expected = vars.get_req_bin("Output"); std::unique_ptr<Botan::BlockCipher> cipher; size_t bs = 0; if(algo == "SHACAL2") { #if defined(BOTAN_HAS_SHACAL2) cipher = Botan::BlockCipher::create_or_throw("SHACAL2"); bs = 32; #else return {result}; #endif } else { if(algo == "Toy128") bs = 16; else if(algo == "Toy192") bs = 24; else if(algo == "Toy256") bs = 32; else if(algo == "Toy512") bs = 64; else throw Test_Error("Unknown cipher for OCB wide block long test"); cipher.reset(new OCB_Wide_Test_Block_Cipher(bs)); } Botan::OCB_Encryption enc(cipher.release(), std::min<size_t>(bs, 32)); /* Y, string of length min(B, 256) bits Y is defined as follows. K = (0xA0 || 0xA1 || 0xA2 || ...)[1..B] C = <empty string> for i = 0 to 127 do S = (0x50 || 0x51 || 0x52 || ...)[1..8i] N = num2str(3i+1,16) C = C || OCB-ENCRYPT(K,N,S,S) N = num2str(3i+2,16) C = C || OCB-ENCRYPT(K,N,<empty string>,S) N = num2str(3i+3,16) C = C || OCB-ENCRYPT(K,N,S,<empty string>) end for N = num2str(385,16) Y = OCB-ENCRYPT(K,N,C,<empty string>) */ std::vector<uint8_t> key(bs); for(size_t i = 0; i != bs; ++i) key[i] = 0xA0 + i; enc.set_key(key); const std::vector<uint8_t> empty; std::vector<uint8_t> N(2); std::vector<uint8_t> C; for(size_t i = 0; i != 128; ++i) { std::vector<uint8_t> S(i); for(size_t j = 0; j != S.size(); ++j) S[j] = 0x50 + j; Botan::store_be(static_cast<uint16_t>(3 * i + 1), &N[0]); ocb_encrypt(result, C, enc, N, S, S); Botan::store_be(static_cast<uint16_t>(3 * i + 2), &N[0]); ocb_encrypt(result, C, enc, N, S, empty); Botan::store_be(static_cast<uint16_t>(3 * i + 3), &N[0]); ocb_encrypt(result, C, enc, N, empty, S); } Botan::store_be(static_cast<uint16_t>(385), &N[0]); std::vector<uint8_t> final_result; ocb_encrypt(result, final_result, enc, N, empty, C); result.test_eq("correct value", final_result, expected); return result; }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { const std::vector<uint8_t> key = get_req_bin(vars, "Key"); const std::vector<uint8_t> expected = get_req_bin(vars, "Out"); const std::vector<uint8_t> nonce = get_opt_bin(vars, "Nonce"); const size_t seek = get_opt_sz(vars, "Seek", 0); std::vector<uint8_t> input = get_opt_bin(vars, "In"); if(input.empty()) { input.resize(expected.size()); } Test::Result result(algo); const std::vector<std::string> providers = provider_filter(Botan::StreamCipher::providers(algo)); if(providers.empty()) { result.note_missing("block cipher " + algo); return result; } for(auto const& provider_ask : providers) { std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider_ask)); if(!cipher) { result.test_failure("Stream " + algo + " supported by " + provider_ask + " but not found"); continue; } const std::string provider(cipher->provider()); result.test_is_nonempty("provider", provider); result.test_eq(provider, cipher->name(), algo); try { std::vector<uint8_t> buf(128); cipher->cipher1(buf.data(), buf.size()); result.test_failure("Was able to encrypt without a key being set"); } catch(Botan::Invalid_State&) { result.test_success("Trying to encrypt with no key set fails"); } try { cipher->seek(0); result.test_failure("Was able to seek without a key being set"); } catch(Botan::Invalid_State&) { result.test_success("Trying to seek with no key set fails"); } catch(Botan::Not_Implemented&) { result.test_success("Trying to seek failed because not implemented"); } cipher->set_key(key); /* Test invalid nonce sizes. this assumes no implemented cipher supports a nonce of 65000 */ const size_t large_nonce_size = 65000; result.confirm("Stream cipher does not support very large nonce", cipher->valid_iv_length(large_nonce_size) == false); result.test_throws("Throws if invalid nonce size given", [&]() { cipher->set_iv(nullptr, large_nonce_size); }); if(nonce.size()) { if(!cipher->valid_iv_length(nonce.size())) { throw Test_Error("Invalid nonce for " + algo); } cipher->set_iv(nonce.data(), nonce.size()); } else { /* * If no nonce was set then implicitly the cipher is using a * null/empty nonce. Call set_iv with such a nonce to make sure * set_iv accepts it. */ if(!cipher->valid_iv_length(0)) { throw Test_Error("Stream cipher " + algo + " requires nonce but none provided"); } cipher->set_iv(nullptr, 0); } if(seek != 0) { cipher->seek(seek); } // Test that clone works and does not affect parent object std::unique_ptr<Botan::StreamCipher> clone(cipher->clone()); result.confirm("Clone has different pointer", cipher.get() != clone.get()); result.test_eq("Clone has same name", cipher->name(), clone->name()); clone->set_key(Test::rng().random_vec(cipher->maximum_keylength())); { std::vector<uint8_t> buf = input; cipher->encrypt(buf); result.test_eq(provider, "encrypt", buf, expected); } cipher->clear(); try { std::vector<uint8_t> buf(128); cipher->cipher1(buf.data(), buf.size()); result.test_failure("Was able to encrypt without a key being set (after clear)"); } catch(Botan::Invalid_State&) { result.test_success("Trying to encrypt with no key set (after clear) fails"); } } return result; }