1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <crypto/bytes.h>
11 #include <crypto/digest.h>
12 #include <crypto/secret.h>
13 #include <fbl/macros.h>
14 #include <fbl/unique_ptr.h>
15 #include <zircon/types.h>
16 
17 // |crypto::HKDF| is a key derivation function.  It can turn variable-length and/or weak input key
18 // material into cryptographically strong output key material.  However, this class does NOT do any
19 // key stretching.  It is the caller's responsibility to protect against brute forcing weak input
20 // key material, e.g. by requiring strong input key material or by rate-limiting the use of both
21 // |Init| and |Derive|.
22 namespace crypto {
23 
24 class HKDF final {
25 public:
26     enum Flags : uint16_t {
27         ALLOW_WEAK_KEY = 0x0001,
28     };
29 
30     HKDF();
31     ~HKDF();
32 
33     // Initializes the HKDF algorithms indicated by |digest| with the input key material in |ikm|
34     // and the given |salt|.  Callers must omit |flags| unless the security implications are clearly
35     // understood.
36     zx_status_t Init(digest::Algorithm digest, const Secret& ikm, const Bytes& salt,
37                      uint16_t flags = 0);
38 
39     // Fill |out| with |len| bytes of output key material.  The key material will depend on the
40     // |ikm| and |salt| given in |Init|, as well as the |label| provided here.  |out_key| will be
41     // the same if and only if all of those parameters are unchanged.
42     zx_status_t Derive(const char* label, size_t len, Bytes* out);
43     zx_status_t Derive(const char* label, size_t len, Secret* out);
44 
45 private:
46     DISALLOW_COPY_ASSIGN_AND_MOVE(HKDF);
47 
48     // Implementation of |Derive| above.
49     zx_status_t Derive(const char* label, uint8_t* out, size_t out_len);
50 
51     // Digest algorithm used by this HKDF.
52     digest::Algorithm digest_;
53     // The pseudo-random key used to derive other keys
54     Secret prk_;
55 };
56 
57 } // namespace crypto
58