aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checks/validate.dat240
-rw-r--r--include/kdf.h34
-rw-r--r--include/ssl3_mac.h34
-rw-r--r--src/def_alg.cpp2
-rw-r--r--src/get_enc.cpp10
-rw-r--r--src/ssl3_mac.cpp88
-rw-r--r--src/ssl3_prf.cpp71
-rw-r--r--src/tls_prf.cpp63
8 files changed, 537 insertions, 5 deletions
diff --git a/checks/validate.dat b/checks/validate.dat
index 6f5b9d006..ba76359f8 100644
--- a/checks/validate.dat
+++ b/checks/validate.dat
@@ -31887,6 +31887,29 @@ C65D515D8FDF3465396DBEA4C44F6F069C597FF9AAA32227:\
39F2933F156616549749CCAEBF682322:\
0398D70C12CE6F7ED28828647FB18A56
+# SSL3-MAC vectors were posted by Thomas Pornin to sci.crypt
+[SSL3-MAC(MD5)]
+00:A856430AF077AE2C328D9FFE4E56813A:0123456789ABCDEF0123456789ABCDEF
+
+01:96279D16E7812EDDA2EC64DAC996348F:0123456789ABCDEF0123456789ABCDEF
+
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF:475006C7DC7A3F371352D948B4BE950E:\
+0123456789ABCDEF0123456789ABCDEF
+
+[SSL3-MAC(SHA-1)]
+00:DD2BA1F4A721F22C8A9BA7350B5CD6838B225827:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
+01:CD6289A1FEC0BB104C271BE488343BA92328B073:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF:98E523EADE38B3BF4EBF51D7EE814316C9EB3159:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
# From draft-ietf-tls-seedhas-00.txt
[HMAC(HAS-160)]
4869205468657265:\
@@ -32326,6 +32349,223 @@ EF4AAB69:37
02AEB40A3D4B66FBA540F9D4B20006F2046E0F3A029DEAB201FC692B79EB27CEF7E16069046A:\
DBB986:38
+[SSL3-PRF]
+6E60:D626B75AB8BD4F5B9458BDDA8589FD39:17FEBCA565786528F84A:16
+
+66BEEC6EDE7FCDF50B76EBCD5C0FE0A472F2EA8B1E2BE2971E49CA:\
+EB:5C461D77ACDB631ABAE2E7AFED5E9ABBBAA99B:1
+
+1171D78F812512DEFBA258574E41F2832BB9B359EB0CA79E7669:\
+2C8B:73D677854D88F62417774A2A5645CCAE9C1AEF8E9D1B48:2
+
+6162DEC990B2132C30C153F2B200:1B9430:2666F0B22E8E48DB1640:3
+
+D3C0DD69C18F17D35C5296FE45F0:C7C19FCD:320C9EEC122C19AFB8E90F72:4
+
+EE6A733EC671DA7477AE18916895A133CC92E23DBACEE2634846CAEF0B08:\
+C264D9D0C9:B7F9722B37389C11:5
+
+97D7F3D2AFB3198862F6FAC8B17CCEFB26:C1CB767626AC:\
+D3583CD13AC119CAFBD44CAEA5AB:6
+
+E87A9BBC656884A13295B8D4DD4645905846C249D2470ACD2BE5:\
+3DC5B6402F451C:542D044668EDC104A9266C2EC79EC37F72A0C6B7301EFDF267CF39:7
+
+7463F0B9F822E17311E47680DC5B505811E9:FE4B1DA4EDA36820:02AB98439528C994:8
+
+EE8999703E5D9C628AA404235F3C94C3A890B1:EF317D3E81DAEF0F89:161DEB5AB705BD15:9
+
+AE531918E679D2D7B32C61BA31415484E9725B2905095819:18D5272345C1695BE38C:\
+A162AC0F0AB41CB80735D1EDAEA3C562CF261C0067:10
+
+8FE402D6ED0BD018A532FC063E7D81D97CDEA7:D61088CA1CE8944B17CD3E:\
+BF7F091B6E0DDB90897B6BF80A4F:11
+
+4279DB52505E7B505BBC26CE0FBF2F4353086C1363:4A84A8E829528393FF890129:\
+8710A8A12B2D18A27A50E5F32C37448A:12
+
+B80B58DAB89B1C4D1335C48E479220E253B8EACFD64319544A:1450E50B7D86B76015930BA420:\
+E9158BA5F6E25D013A37B9D65406E989CB77D05D97B2B04F9C7F26DF987A:13
+
+965F1BC656F01C1C7F977419A5F99FB54FA34548C332EA79B5B0EE:\
+CEE11A3A9A406FE9DA77FE6FB007:\
+3F6FF94F05596ACBAF5AE7CBD97E3FF3233992D988361E:14
+
+657B5F618710AF88BF4F0328E7071D022D02EA5E:8EA957C330D55CC208326CEA06D25A:\
+BD0A575481E823931F68BE84E31DE56B2D95F3ECE4F614CBFD31CE:15
+
+33CE7917528009F2A1011CFCD494B80D4BBFD901:2FB1FDD16FCE41C9C563226A564D1647:\
+81851CC61D3E910E04D5EC38A465:16
+
+40ED568CFC6C0A17866C67B7660C96BF9DA54C:321118AA031C5C9EFF145542B4426C3C71:\
+A3502B96214854E5AF5720E8970D3F240AAB2E21319A88E901:17
+
+12695F5B19541C8B0092418A72A7ED8482F35FCC4A82D4E1C5AE:\
+22BC94F745F6E247054DDA2C772E5D2D3EC4:\
+2CE5F4676C06D0CB61E91F7D751F0F:18
+
+F36E535A1C2C6F6771:6004BBD20BB68E2F1FFC65977807EE25A3FBFE:\
+290BE26068D887AA6E86500E85C606:19
+
+7C7EE43D46AE85D23F0D5264DBD410:0E1FE69316D67CF65D62196C25CC4F517664BD43:\
+FC4A7F986331A012CBDAD765288C2CEC08AAD045:20
+
+C580B05EC577F45434C13640AAB31B:937E22F90D1493317B0B068A44859036905540AF67:\
+6C9F5929EA435A86E117BD586B34F7E4F97794573C0B4C90:21
+
+E275AEB758A949CBB11256E74412E1DA3743899F9007DD5D80A7:\
+69C2640797F38E87F1C870891164F0B31F1A3A02627A:\
+585B267A9E08EF4DBF48F6:22
+
+DCF06E7AC257DA73CC6FC0A086B4:30CCF63491F642A55E45136E42FDD0355DB272502EA1B0:\
+16F0355230F105EB316F558512EC3B51871741:23
+
+C4C38EC6A1EA975D0ECA535B0CC4D6D0:\
+3B50F91EDFDD96CBA8B6329616D4F5964CD8C961CB1D9332:\
+E84EE4D9DC701DE04E250768F2DFB9B6A2:24
+
+7B557AC16D60B74ECAA87641887E6467BAC107:\
+CA148D27F3DC362B0F43C68312058C1CD9B92ECAC2CFDD601F:\
+D7B9EB91BCDE1F6C144A0799:25
+
+B23EFA7FAA11D0E597F00867992CB3B9DA93D607FAC0:\
+510297144BA4E0FB5C94749576F756AA36F51289CA463419DC06:\
+DA5E3A17C6DDE81CC69A5AC11904D2E9E969D9F2D1731E842C:26
+
+1A5063B374A5F7769AD59432CFFA6B:\
+3437D8B56E573E724B72DD08A5D144E86E646BD24EA0795BA2C3BD:\
+FE0314911D4C07803C48A9EA86:27
+
+870515C65F0AF7AAB10C365AF8AC535E1AA8997D139645A21F71FD23ABBB:\
+1895554BD0A1DE7F48FA8776D314EAE2B9E8D7E3CF2A418D17659DC1:\
+AA33C0BFF91FC9F1C97BFD00D5F5AC2953C6D1EC43E5838887A2F984C5A53F:28
+
+1BAE220F6AFEB0A2F51D44721A7A9B9C:\
+13720151D256DEBAAA668359A876A9A9788D540F509E90372952A91757:\
+11555530CBAECFF82C76147416A50831532A40BD29F15F1E0EA49129:29
+
+BC55F2BAC14370BB5832575A233F1FCE32322E5B4CE1955153CAF3C84493DF:\
+972B190F7EC73DA7C5B8B38E9B6DCEE452AB0BC2220F37BEA3FAC596B2F6:\
+00E8D1BAA9142A646C5DBCC680FB:30
+
+834CD382FBF84FF54CC8D3BCB778ACD7DDE8FE32ABA212ABB1:\
+6151C82D7384ED41264424827766B6A7279593C86DCBAC9A4D711009E30EC3:\
+EE768F1AAF889EFB5B20F7536FECA037BF:31
+
+E0BDEBC1D1EEDB393368D489:\
+F3D8ED6D46280C3694F33D2D4A210248D657277DD78ACD3B34063D085657A58E:\
+5D2B46C7BB5258ABC13514995E518FD4D77BECB738D77909:32
+
+[TLS-PRF]
+6C81AF87ABD86BE83C37CE981F6BFE11BD53A8:A8:\
+A6D455CB1B2929E43D63CCE55CE89D66F252549729C19C1511:1
+
+6BB61D34AF2BCCF45A850850BCDE35E55A92BA:5E75:\
+510194C9C9F90D98452FB914F636D5E5297C:2
+
+3CC54F5F3EF82C93CE60EB62DC9DF005280DD1:706F52:\
+7FC24D382379A9CD54D53458947CB28E298A1DCC5EB2556F71ACAC1B:3
+
+BD3462DC587DFA992AE48BD7643B62A9971928:841D7339:\
+9F6FAFED1F241A1E40ADEAF2AD80:4
+
+1235A061FA3867B8E51511D1E672CE141E2FA6:D856787D41:\
+1026B9224FC59706BEADAE58EBD161FD2EAC:5
+
+63A22C3C7C5651103648F5CFC9764A7BDE821F:F13096FEED6E:\
+512FBF47D9DA2915:6
+
+AA15082F10F25EC4F96DFFE9DC3D80BBA6361B:B637FCADE57896:\
+519B87DB85FBE92FB4070F3BEF6E3D97DF69B66061EB83B4A334E8EEDC0F8E:7
+
+775B727CE679B8696171C7BE60FC2E3F4DE516:3431016193616501:\
+453C2549058B063C83E8B85E5CEF3570DF51B7D79B486F4F33:8
+
+AB299AD69DC581F13D86562AE2BE8B08015FF8:A624CC363499B1EA64:5569FC:9
+
+AE4947624D877916E5B01EDDAB8E4CDC817630:5B908EB5B2A7F115CF57:\
+7FDE51EFB4044017C95E3608F8FB6F:10
+
+4F13EB6FBE1FA2FCD7B5B21C9F20980D1986A4:EE73EEE90E35AF2BC3575D:\
+514DBCE520AB34:11
+
+41BC094049008CBAE99CAC0BA901D0B2DD15DF:BD859DAE2729A348774146B5:\
+CB6C0544FF8CF74C71E910F2220D54C509DC442CB3:12
+
+95751B37945DD9DE515B45927A229AAB40F7D0:FE310AF0913149D53718AC53E5:\
+75318F49A11F42A24AF48267411FDD0831:13
+
+FC250F36E5C1365C3EAD122E63F90612DBBDA7:C0107D144E53227EDE5E677A35BE:\
+8A4B5AEA3AC0B2FF777D77B5EFB6E7D8AF:14
+
+F6A8A67ACA60F25080100F3F5C928038936E57:A1FCD686295E3DE32C438A8FFD63CE:\
+F8B663768421BA77861F1EBEBF4C8341DC01ED1F7D4B054B7C:15
+
+77BF131D53997B1FB2ACE2137E26992B36BF3E:60D0A09FCFDE24AB73F62A7C9F594766:\
+859D1EE9A694865ECC1830C361D24485AC1026:16
+
+39CF412177DD47B8E97A4D92D104138CD4E41C:F7D49D2C112F3EE64411F50B264AE15BB4:\
+9CD35F26E8A89C25410B3394A957B781BBD0D190DA:17
+
+5C40AF252D0A4F445E638D954993BCB0673281:\
+FDA100D44E2F839C21199A56ACAF57454C21:\
+2DFB810DC9ED5B291754144937E6052666D476D1F5F94C:18
+
+2A8B07B082F2A4C95611B20685A4410E90B8D2:\
+A5CCE186AFDB9C0EB664C719DD1A69C1BA6059:\
+320ADFA586F7EBF346646DE9:19
+
+BCBD1EFDA490B9D541BA9DF50FE9A451DD0313:\
+2291E19459725562F106F63FE2F81E73BA23F04A:\
+255230A341E671BC31B1:20
+
+B361B123993602D0BA62567BF9B81992DB108EAE:\
+A71CB3E9C58E83414D69775CF7127E9C95AF10B7E2:\
+20878A3A703785DE37846086C097619E9823F7FCD2B7B3A9466FA6:21
+
+8E7CC0EED8BFF691B370C08FE0DB32D06700B088:\
+25DA6B3027CBBCA4352EFB85D3FCB9060285BC39ECB8:\
+02F3B9155F5CFF08B9F47A2FDC701BA3F08BCDDF21292911D06FC0A5A99B:22
+
+041CC7ED27C01A701A0F15269DA6CA6D806B10C3:\
+E3B7F0D721C05663166B43A75F2997F9F029886FC069D0:\
+8E5F4FADE80AF92D495AF5A50C8E:23
+
+A7421C0D96D2455E57408C2BF02E86DCEE71B060:\
+46948B1DD4C7977AA7241ABD74A88E7838E575DD34AA9B75:\
+BD2623716653B538C885FA2ED4B0A2:24
+
+56DAD2D1AF95F938E073D10A1A779F80BB0F76FE:\
+53B1169FA52AABC427D1C41501B612DF6D726F55DAD9D246E9:\
+D1DA1DEF7BD5C327894B7A992AA7A694664470F642:25
+
+4F2E4F77820A686894B90A0AFD0ABA772D0CC6B0:\
+30ED285AE596143BE7998901C2F35530D81CA4DD14E03D17DF2C:\
+062577E22854BAF0E68A51A27644FFB0:26
+
+86173BD0F3C5E7052482B53BD8604E197112F3D8:\
+BB3BD1CBFA7889441E930C4B5E8EC7AB00D9612E9D762D42427AD9:\
+12B4E5F24ADC8A:27
+
+2B9CE8B0AB3041D6A1803BDD342E6537E40BE305:\
+88F8AFCB8109C7B359B18CCED73A1B09404CC9EABB23695BF353ED9E:\
+517D3D00850F48912B713E653CB4F38703B6A6:28
+
+819CB722AA4475D8301A8E24DCD9D82DF2B081F4:\
+83FD6F33AD11819019E086F0683E26D59D57C9E5AF26C81738E44D47A3:\
+56872A31A10E8C:29
+
+80F1F9B0D05F41C448E5306E41833918B9E688ED:\
+0C00B5F50565FDD5345C63773D5FCC8B3C8E412DFFF23B95490EFB4E53FA:\
+6175CDE230DF6691F4E8A36B265C53CAD736AD6F34F895D5C6633D66B5:30
+
+0AE876A7BB96C24CEFA6ED53CEE7B0A41B8FF7B3:\
+881B99C3E43B1A42F096CF556D3143D5C5DBC4E984D26C5F3075BCB08B73DA::31
+
+2212169D33FADC6FF94A3E5E0020587953CF1964:\
+1E1C646C2BFBDC62FA4C81F1D0781F5F269D3F45E5C33CAC8A2640226C8C5D16:\
+FCD5C9637A21E43F3CFF6ECF65B6E2F97933779F101AD6:32
+
# From RFC 2631
[X9.42-PRF(KeyWrap.TripleDES)]
diff --git a/include/kdf.h b/include/kdf.h
index 57f1dc047..ad7a11dbe 100644
--- a/include/kdf.h
+++ b/include/kdf.h
@@ -16,11 +16,11 @@ namespace Botan {
class BOTAN_DLL KDF1 : public KDF
{
public:
- KDF1(const std::string&);
- private:
SecureVector<byte> derive(u32bit, const byte[], u32bit,
const byte[], u32bit) const;
+ KDF1(const std::string&);
+ private:
const std::string hash_name;
};
@@ -30,11 +30,11 @@ class BOTAN_DLL KDF1 : public KDF
class BOTAN_DLL KDF2 : public KDF
{
public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
KDF2(const std::string&);
private:
- SecureVector<byte> derive(u32bit, const byte[], u32bit,
- const byte[], u32bit) const;
const std::string hash_name;
};
@@ -44,12 +44,36 @@ class BOTAN_DLL KDF2 : public KDF
class BOTAN_DLL X942_PRF : public KDF
{
public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
X942_PRF(const std::string&);
private:
+ std::string key_wrap_oid;
+ };
+
+/*************************************************
+* SSL3 PRF *
+*************************************************/
+class BOTAN_DLL SSL3_PRF : public KDF
+ {
+ public:
SecureVector<byte> derive(u32bit, const byte[], u32bit,
const byte[], u32bit) const;
+ };
- std::string key_wrap_oid;
+/*************************************************
+* TLS PRF *
+*************************************************/
+class BOTAN_DLL TLS_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+ private:
+ SecureVector<byte> P_hash(const std::string&, u32bit,
+ const byte[], u32bit,
+ const byte[], u32bit) const;
};
}
diff --git a/include/ssl3_mac.h b/include/ssl3_mac.h
new file mode 100644
index 000000000..8ab08c97d
--- /dev/null
+++ b/include/ssl3_mac.h
@@ -0,0 +1,34 @@
+/*************************************************
+* SSL3-MAC Header File *
+* (C) 1999-2004 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_SSL3_MAC_H__
+#define BOTAN_SSL3_MAC_H__
+
+#include <botan/base.h>
+
+namespace Botan {
+
+/*************************************************
+* SSL3-MAC *
+*************************************************/
+class SSL3_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+ SSL3_MAC(const std::string&);
+ ~SSL3_MAC() { delete hash; }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key(const byte[], u32bit);
+ HashFunction* hash;
+ SecureVector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/src/def_alg.cpp b/src/def_alg.cpp
index 29e99d6a0..bba904b11 100644
--- a/src/def_alg.cpp
+++ b/src/def_alg.cpp
@@ -57,6 +57,7 @@
#include <botan/cbc_mac.h>
#include <botan/cmac.h>
#include <botan/hmac.h>
+#include <botan/ssl3_mac.h>
#include <botan/x919_mac.h>
#include <botan/mode_pad.h>
@@ -233,6 +234,7 @@ Default_Engine::find_mac(const std::string& algo_spec) const
HANDLE_TYPE_ONE_STRING("CBC-MAC", CBC_MAC);
HANDLE_TYPE_ONE_STRING("CMAC", CMAC);
HANDLE_TYPE_ONE_STRING("HMAC", HMAC);
+ HANDLE_TYPE_ONE_STRING("SSL3-MAC", SSL3_MAC);
HANDLE_TYPE_NO_ARGS("X9.19-MAC", ANSI_X919_MAC);
return 0;
diff --git a/src/get_enc.cpp b/src/get_enc.cpp
index 29a166b2c..31c1e06aa 100644
--- a/src/get_enc.cpp
+++ b/src/get_enc.cpp
@@ -106,6 +106,16 @@ KDF* get_kdf(const std::string& algo_spec)
if(name.size() == 2)
return new X942_PRF(name[1]);
}
+ if(kdf_name == "TLS-PRF")
+ {
+ if(name.size() == 1)
+ return new TLS_PRF;
+ }
+ else if(kdf_name == "SSL3-PRF")
+ {
+ if(name.size() == 1)
+ return new SSL3_PRF;
+ }
else
throw Algorithm_Not_Found(algo_spec);
diff --git a/src/ssl3_mac.cpp b/src/ssl3_mac.cpp
new file mode 100644
index 000000000..ceb04bf44
--- /dev/null
+++ b/src/ssl3_mac.cpp
@@ -0,0 +1,88 @@
+/*************************************************
+* SSL3-MAC Source File *
+* (C) 1999-2004 Jack Lloyd *
+*************************************************/
+
+#include <botan/ssl3_mac.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+/*************************************************
+* Update a SSL3-MAC Calculation *
+*************************************************/
+void SSL3_MAC::add_data(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*************************************************
+* Finalize a SSL3-MAC Calculation *
+*************************************************/
+void SSL3_MAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, OUTPUT_LENGTH);
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*************************************************
+* SSL3-MAC Key Schedule *
+*************************************************/
+void SSL3_MAC::key(const byte key[], u32bit length)
+ {
+ hash->clear();
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ i_key.copy(key, length);
+ o_key.copy(key, length);
+ hash->update(i_key);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void SSL3_MAC::clear() throw()
+ {
+ hash->clear();
+ i_key.clear();
+ o_key.clear();
+ }
+
+/*************************************************
+* Return the name of this type *
+*************************************************/
+std::string SSL3_MAC::name() const
+ {
+ return "SSL3-MAC(" + hash->name() + ")";
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+MessageAuthenticationCode* SSL3_MAC::clone() const
+ {
+ return new SSL3_MAC(hash->name());
+ }
+
+/*************************************************
+* SSL3-MAC Constructor *
+*************************************************/
+SSL3_MAC::SSL3_MAC(const std::string& hash_name) :
+ MessageAuthenticationCode(output_length_of(hash_name),
+ output_length_of(hash_name)),
+ hash(get_hash(hash_name))
+ {
+ if(hash->name() != "MD5" && hash->name() != "SHA-160")
+ throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
+
+ const u32bit INNER_HASH_LENGTH = (hash->name() == "MD5") ? 64 : 60;
+
+ i_key.create(INNER_HASH_LENGTH);
+ o_key.create(INNER_HASH_LENGTH);
+ }
+
+}
diff --git a/src/ssl3_prf.cpp b/src/ssl3_prf.cpp
new file mode 100644
index 000000000..a86ed8ff7
--- /dev/null
+++ b/src/ssl3_prf.cpp
@@ -0,0 +1,71 @@
+/*************************************************
+* SSL3 PRF Source File *
+* (C) 2004-2006 Jack Lloyd *
+*************************************************/
+
+#include <botan/kdf.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Return the next inner hash *
+*************************************************/
+OctetString next_hash(u32bit where, u32bit want,
+ HashFunction* md5, HashFunction* sha1,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len)
+ {
+ if(want > md5->OUTPUT_LENGTH)
+ throw Internal_Error("SSL3_PRF:next_hash: want is too big");
+
+ const byte ASCII_A_CHAR = 0x41;
+
+ for(u32bit j = 0; j != where + 1; j++)
+ sha1->update(ASCII_A_CHAR + where);
+ sha1->update(secret, secret_len);
+ sha1->update(seed, seed_len);
+ SecureVector<byte> sha1_hash = sha1->final();
+
+ md5->update(secret, secret_len);
+ md5->update(sha1_hash);
+ SecureVector<byte> md5_hash = md5->final();
+
+ return OctetString(md5_hash, want);
+ }
+
+}
+
+/*************************************************
+* SSL3 PRF *
+*************************************************/
+SecureVector<byte> SSL3_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ if(key_len > 416)
+ throw Internal_Error("SSL3_PRF: Requested key length is too large");
+
+ std::auto_ptr<HashFunction> md5(get_hash("MD5"));
+ std::auto_ptr<HashFunction> sha1(get_hash("SHA-1"));
+
+ OctetString output;
+
+ int counter = 0;
+ while(key_len)
+ {
+ const u32bit produce = std::min(key_len, md5->OUTPUT_LENGTH);
+
+ output = output + next_hash(counter++, produce, md5.get(), sha1.get(),
+ secret, secret_len, seed, seed_len);
+
+ key_len -= produce;
+ }
+
+ return output.bits_of();
+ }
+
+}
diff --git a/src/tls_prf.cpp b/src/tls_prf.cpp
new file mode 100644
index 000000000..2222e3baa
--- /dev/null
+++ b/src/tls_prf.cpp
@@ -0,0 +1,63 @@
+/*************************************************
+* TLS PRF Source File *
+* (C) 2004-2006 Jack Lloyd *
+*************************************************/
+
+#include <botan/kdf.h>
+#include <botan/lookup.h>
+#include <botan/xor_buf.h>
+#include <botan/hmac.h>
+
+namespace Botan {
+
+/*************************************************
+* TLS PRF *
+*************************************************/
+SecureVector<byte> TLS_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ u32bit S1_len = (secret_len + 1) / 2,
+ S2_len = (secret_len + 1) / 2;
+ const byte* S1 = secret;
+ const byte* S2 = secret + (secret_len - S2_len);
+
+ SecureVector<byte> key1, key2;
+ key1 = P_hash("MD5", key_len, S1, S1_len, seed, seed_len);
+ key2 = P_hash("SHA-1", key_len, S2, S2_len, seed, seed_len);
+
+ xor_buf(key1.begin(), key2.begin(), key2.size());
+
+ return key1;
+ }
+
+/*************************************************
+* TLS PRF P_hash function *
+*************************************************/
+SecureVector<byte> TLS_PRF::P_hash(const std::string& hash, u32bit len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ SecureVector<byte> out;
+
+ HMAC hmac(hash);
+ hmac.set_key(secret, secret_len);
+
+ SecureVector<byte> A(seed, seed_len);
+ while(len)
+ {
+ const u32bit this_block_len = std::min(hmac.OUTPUT_LENGTH, len);
+
+ A = hmac.process(A);
+
+ hmac.update(A);
+ hmac.update(seed, seed_len);
+ SecureVector<byte> block = hmac.final();
+
+ out.append(block, this_block_len);
+ len -= this_block_len;
+ }
+ return out;
+ }
+
+}