aboutsummaryrefslogtreecommitdiffstats
path: root/checks
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-11-17 21:31:54 +0000
committerlloyd <[email protected]>2013-11-17 21:31:54 +0000
commite072b28e66a06a1a82678a2b5d8b946bf63f6289 (patch)
treea3e1e30aad9cf60f23a75d12f5fcbad4d56bb03d /checks
parenta9e79b8a9da0abffce15d9bb891f7604d1856744 (diff)
Add HKDF
Diffstat (limited to 'checks')
-rw-r--r--checks/hkdf.cpp84
-rw-r--r--checks/hkdf.vec51
-rw-r--r--checks/validate.cpp3
-rw-r--r--checks/validate.h2
4 files changed, 140 insertions, 0 deletions
diff --git a/checks/hkdf.cpp b/checks/hkdf.cpp
new file mode 100644
index 000000000..95960f62b
--- /dev/null
+++ b/checks/hkdf.cpp
@@ -0,0 +1,84 @@
+#include "validate.h"
+
+#include <botan/libstate.h>
+#include <botan/hkdf.h>
+#include <botan/hex.h>
+#include <iostream>
+#include <fstream>
+
+using namespace Botan;
+
+namespace {
+
+secure_vector<byte> hkdf(const std::string& algo,
+ const secure_vector<byte>& ikm,
+ const secure_vector<byte>& salt,
+ const secure_vector<byte>& info,
+ size_t L)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ const MessageAuthenticationCode* mac_proto = af.prototype_mac("HMAC(" + algo + ")");
+
+ if(!mac_proto)
+ throw std::invalid_argument("Bad HKDF hash " + algo);
+
+ HKDF hkdf(mac_proto->clone(), mac_proto->clone());
+
+ hkdf.start_extract(&salt[0], salt.size());
+ hkdf.extract(&ikm[0], ikm.size());
+ hkdf.finish_extract();
+
+ secure_vector<byte> key(L);
+ hkdf.expand(&key[0], key.size(), &info[0], info.size());
+ return key;
+ }
+
+void hkdf_test(const std::string& algo,
+ const std::string& ikm,
+ const std::string& salt,
+ const std::string& info,
+ const std::string& okm,
+ size_t L)
+ {
+ const std::string got = hex_encode(
+ hkdf(algo,
+ hex_decode_locked(ikm),
+ hex_decode_locked(salt),
+ hex_decode_locked(info),
+ L)
+ );
+
+ if(got != okm)
+ std::cout << "HKDF got " << got << " expected " << okm << std::endl;
+ }
+
+}
+
+void test_hkdf()
+ {
+ // From RFC 5869
+ std::ifstream vec("checks/hkdf.vec");
+
+ std::map<std::string, std::string> vars;
+
+ while(vec.good())
+ {
+ std::string line;
+ std::getline(vec, line);
+
+ if(line == "")
+ continue;
+
+ const std::string key = line.substr(0, line.find_first_of(' '));
+ const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos);
+
+ vars[key] = val;
+
+ if(key == "OKM")
+ {
+ hkdf_test(vars["Hash"], vars["IKM"], vars["salt"], vars["info"],
+ vars["OKM"], to_u32bit(vars["L"]));
+ vars.clear();
+ }
+ }
+ }
diff --git a/checks/hkdf.vec b/checks/hkdf.vec
new file mode 100644
index 000000000..57a90cf8d
--- /dev/null
+++ b/checks/hkdf.vec
@@ -0,0 +1,51 @@
+
+Hash = SHA-256
+IKM = 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+salt = 000102030405060708090A0B0C
+info = F0F1F2F3F4F5F6F7F8F9
+L = 42
+PRK = 077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844AD7C2B3E5
+OKM = 3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56ECC4C5BF34007208D5B887185865
+
+Hash = SHA-256
+IKM = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+salt = 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF
+info = B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+L = 82
+
+PRK = 06A6B88C5853361A06104C9CEB35B45CEF760014904671014A193F40C15FC244
+OKM = B11E398DC80327A1C8E7F78C596A49344F012EDA2D4EFAD8A050CC4C19AFA97C59045A99CAC7827271CB41C65E590E09DA3275600C2F09B8367793A9ACA3DB71CC30C58179EC3E87C14C01D5C1F3434F1D87
+
+Hash = SHA-256
+IKM = 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+L = 42
+PRK = 19EF24A32C717B167F33A91D6F648BDF96596776AFDB6377AC434C1C293CCB04
+OKM = 8DA4E775A563C18F715F802A063C5A31B8A11F5C5EE1879EC3454E5F3C738D2D9D201395FAA4B61A96C8
+
+Hash = SHA-1
+IKM = 0B0B0B0B0B0B0B0B0B0B0B
+salt = 000102030405060708090A0B0C
+info = F0F1F2F3F4F5F6F7F8F9
+L = 42
+PRK = 9B6C18C432A7BF8F0E71C8EB88F4B30BAA2BA243
+OKM = 085A01EA1B10F36933068B56EFA5AD81A4F14B822F5B091568A9CDD4F155FDA2C22E422478D305F3F896
+
+Hash = SHA-1
+IKM = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+salt = 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF
+info = B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+L = 82
+PRK = 8ADAE09A2A307059478D309B26C4115A224CFAF6
+OKM = 0BD770A74D1160F7C9F12CD5912A06EBFF6ADCAE899D92191FE4305673BA2FFE8FA3F1A4E5AD79F3F334B3B202B2173C486EA37CE3D397ED034C7F9DFEB15C5E927336D0441F4C4300E2CFF0D0900B52D3B4
+
+Hash = SHA-1
+IKM = 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+L = 42
+PRK = DA8C8A73C7FA77288EC6F5E7C297786AA0D32D01
+OKM = 0AC1AF7002B3D761D1E55298DA9D0506B9AE52057220A306E07B6B87E8DF21D0EA00033DE03984D34918
+
+Hash = SHA-1
+IKM = 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+L = 42
+PRK = 2ADCCADA18779E7C2077AD2EB19D3F3E731385DD
+OKM = 2C91117204D745F3500D636A62F64F0AB3BAE548AA53D423B0D1F27EBBA6F5E5673A081D70CCE7ACFC48
diff --git a/checks/validate.cpp b/checks/validate.cpp
index 19032e332..8ac35393c 100644
--- a/checks/validate.cpp
+++ b/checks/validate.cpp
@@ -417,7 +417,10 @@ u32bit do_validation_tests(const std::string& filename,
}
if(should_pass)
+ {
test_ocb();
+ test_hkdf();
+ }
return errors;
}
diff --git a/checks/validate.h b/checks/validate.h
index 539154d53..3499bf8c0 100644
--- a/checks/validate.h
+++ b/checks/validate.h
@@ -32,4 +32,6 @@ size_t do_tls_tests(RandomNumberGenerator& rng);
void test_ocb();
+void test_hkdf();
+
#endif