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 }