1 /* Copyright (c) 2014, Google Inc.
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include <openssl/hkdf.h>
21 #include <openssl/err.h>
22 #include <openssl/hmac.h>
24 /* https://tools.ietf.org/html/rfc5869#section-2 */
26 HKDF(uint8_t *out_key
, size_t out_len
, const EVP_MD
*digest
,
27 const uint8_t *secret
, size_t secret_len
, const uint8_t *salt
,
28 size_t salt_len
, const uint8_t *info
, size_t info_len
)
30 uint8_t prk
[EVP_MAX_MD_SIZE
];
33 if (!HKDF_extract(prk
, &prk_len
, digest
, secret
, secret_len
, salt
,
36 if (!HKDF_expand(out_key
, out_len
, digest
, prk
, prk_len
, info
,
43 /* https://tools.ietf.org/html/rfc5869#section-2.2 */
45 HKDF_extract(uint8_t *out_key
, size_t *out_len
,
46 const EVP_MD
*digest
, const uint8_t *secret
, size_t secret_len
,
47 const uint8_t *salt
, size_t salt_len
)
52 * If salt is not given, HashLength zeros are used. However, HMAC does that
53 * internally already so we can ignore it.
55 if (HMAC(digest
, salt
, salt_len
, secret
, secret_len
, out_key
, &len
) ==
57 CRYPTOerror(ERR_R_CRYPTO_LIB
);
64 /* https://tools.ietf.org/html/rfc5869#section-2.3 */
66 HKDF_expand(uint8_t *out_key
, size_t out_len
,
67 const EVP_MD
*digest
, const uint8_t *prk
, size_t prk_len
,
68 const uint8_t *info
, size_t info_len
)
70 const size_t digest_len
= EVP_MD_size(digest
);
71 uint8_t previous
[EVP_MAX_MD_SIZE
];
77 /* Expand key material to desired length. */
78 n
= (out_len
+ digest_len
- 1) / digest_len
;
79 if (out_len
+ digest_len
< out_len
|| n
> 255) {
80 CRYPTOerror(EVP_R_TOO_LARGE
);
85 if (!HMAC_Init_ex(&hmac
, prk
, prk_len
, digest
, NULL
))
88 for (i
= 0; i
< n
; i
++) {
92 if (i
!= 0 && (!HMAC_Init_ex(&hmac
, NULL
, 0, NULL
, NULL
) ||
93 !HMAC_Update(&hmac
, previous
, digest_len
)))
96 if (!HMAC_Update(&hmac
, info
, info_len
) ||
97 !HMAC_Update(&hmac
, &ctr
, 1) ||
98 !HMAC_Final(&hmac
, previous
, NULL
))
102 if (done
+ todo
> out_len
)
103 todo
= out_len
- done
;
105 memcpy(out_key
+ done
, previous
, todo
);
112 HMAC_CTX_cleanup(&hmac
);
114 CRYPTOerror(ERR_R_CRYPTO_LIB
);