1 /** 2 * X9.42 PRF 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.kdf.prf_x942; 12 13 import botan.constants; 14 static if (BOTAN_HAS_TLS || BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 import botan.kdf.kdf; 17 import botan.asn1.der_enc; 18 import botan.asn1.oids; 19 import botan.hash.sha160; 20 import botan.utils.loadstor; 21 import std.algorithm; 22 import botan.utils.types; 23 24 /** 25 * PRF from ANSI X9.42 26 */ 27 class X942PRF : KDF 28 { 29 public: 30 /* 31 * X9.42 PRF 32 */ 33 override SecureVector!ubyte derive(size_t key_len, 34 const(ubyte)* secret, size_t secret_len, 35 const(ubyte)* salt, size_t salt_len) const 36 { 37 auto hash = scoped!SHA160(); 38 const OID kek_algo = OID(m_key_wrap_oid); 39 40 SecureVector!ubyte key; 41 uint counter = 1; 42 43 while (key.length != key_len && counter) 44 { 45 hash.update(secret, secret_len); 46 47 hash.update( 48 DEREncoder().startCons(ASN1Tag.SEQUENCE) 49 .startCons(ASN1Tag.SEQUENCE) 50 .encode(kek_algo) 51 .rawBytes(encodeX942Int(counter)) 52 .endCons() 53 54 .encodeIf (salt_len != 0, 55 DEREncoder() 56 .startExplicit(0) 57 .encode(salt, salt_len, ASN1Tag.OCTET_STRING) 58 .endExplicit() 59 ) 60 61 .startExplicit(2) 62 .rawBytes(encodeX942Int(cast(uint)(8 * key_len))) 63 .endExplicit() 64 65 .endCons().getContents() 66 ); 67 68 SecureVector!ubyte digest = hash.finished(); 69 const size_t needed = std.algorithm.min(digest.length, key_len - key.length); 70 key ~= digest.ptr[0 .. needed]; 71 72 ++counter; 73 } 74 75 return key; 76 } 77 78 79 override @property string name() const { return "X942_PRF(" ~ m_key_wrap_oid ~ ")"; } 80 override KDF clone() const { return new X942PRF(m_key_wrap_oid); } 81 /* 82 * X9.42 Constructor 83 */ 84 this(in string oid) 85 { 86 if (OIDS.haveOid(oid)) 87 m_key_wrap_oid = OIDS.lookup(oid).toString(); 88 else 89 m_key_wrap_oid = oid; 90 } 91 private: 92 string m_key_wrap_oid; 93 } 94 95 private: 96 97 /* 98 * Encode an integer as an OCTET STRING 99 */ 100 Vector!ubyte encodeX942Int(uint n) 101 { 102 ubyte[4] n_buf; 103 storeBigEndian(n, &n_buf); 104 return DEREncoder().encode(n_buf.ptr, 4, ASN1Tag.OCTET_STRING).getContentsUnlocked(); 105 }