1 #include <errno.h>
2 
3 #include "crypto_kdf_blake2b.h"
4 #include "crypto_generichash_blake2b.h"
5 #include "private/common.h"
6 
7 size_t
8 crypto_kdf_blake2b_bytes_min(void)
9 {
10     return crypto_kdf_blake2b_BYTES_MIN;
11 }
12 
13 size_t
14 crypto_kdf_blake2b_bytes_max(void)
15 {
16     return crypto_kdf_blake2b_BYTES_MAX;
17 }
18 
19 size_t
20 crypto_kdf_blake2b_contextbytes(void)
21 {
22     return crypto_kdf_blake2b_CONTEXTBYTES;
23 }
24 
25 size_t
26 crypto_kdf_blake2b_keybytes(void)
27 {
28     return crypto_kdf_blake2b_KEYBYTES;
29 }
30 
31 int crypto_kdf_blake2b_derive_from_key(unsigned char *subkey, size_t subkey_len,
32                                        uint64_t subkey_id,
33                                        const char ctx[crypto_kdf_blake2b_CONTEXTBYTES],
34                                        const unsigned char key[crypto_kdf_blake2b_KEYBYTES])
35 {
36     unsigned char ctx_padded[crypto_generichash_blake2b_PERSONALBYTES];
37     unsigned char salt[crypto_generichash_blake2b_SALTBYTES];
38 
39     memcpy(ctx_padded, ctx, crypto_kdf_blake2b_CONTEXTBYTES);
40     memset(ctx_padded + crypto_kdf_blake2b_CONTEXTBYTES, 0, sizeof ctx_padded - crypto_kdf_blake2b_CONTEXTBYTES);
41     STORE64_LE(salt, subkey_id);
42     memset(salt + 8, 0, (sizeof salt) - 8);
43     if (subkey_len < crypto_kdf_blake2b_BYTES_MIN ||
44         subkey_len > crypto_kdf_blake2b_BYTES_MAX) {
45         errno = EINVAL;
46         return -1;
47     }
48     return crypto_generichash_blake2b_salt_personal(subkey, subkey_len,
49                                                     NULL, 0,
50                                                     key, crypto_kdf_blake2b_KEYBYTES,
51                                                     salt, ctx_padded);
52 }
53