summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbeck <>2017-05-06 20:42:57 +0000
committerbeck <>2017-05-06 20:42:57 +0000
commit270fd63e5d8c3683472108ff30860e5f0eb33ef1 (patch)
treed7342fea9121d617dc8b0a17a471ebab354fa0ed /src/lib
parent4b07231945fb22f051b25555dae5b5f56398eee0 (diff)
downloadopenbsd-270fd63e5d8c3683472108ff30860e5f0eb33ef1.tar.gz
openbsd-270fd63e5d8c3683472108ff30860e5f0eb33ef1.tar.bz2
openbsd-270fd63e5d8c3683472108ff30860e5f0eb33ef1.zip
Bring in HKDF, from BoringSSL, with regress tests modified to be
in C. Ride previous minor bump ok tom@ inoguchi@ jsing@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/Makefile7
-rw-r--r--src/lib/libcrypto/hkdf/hkdf.c116
-rw-r--r--src/lib/libcrypto/hkdf/hkdf.h64
3 files changed, 186 insertions, 1 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index 13f4ab0de5..6454d6b109 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.16 2017/04/30 04:44:58 jsing Exp $ 1# $OpenBSD: Makefile,v 1.17 2017/05/06 20:42:57 beck Exp $
2 2
3LIB= crypto 3LIB= crypto
4 4
@@ -169,6 +169,9 @@ SRCS+= gost89imit_pmeth.c gost_asn1.c gost_err.c gostr341001.c
169SRCS+= gostr341001_ameth.c gostr341001_key.c gostr341001_params.c 169SRCS+= gostr341001_ameth.c gostr341001_key.c gostr341001_params.c
170SRCS+= gostr341001_pmeth.c gostr341194.c streebog.c 170SRCS+= gostr341001_pmeth.c gostr341194.c streebog.c
171 171
172# hkdf/
173SRCS+= hkdf.c
174
172# hmac/ 175# hmac/
173SRCS+= hmac.c hm_ameth.c hm_pmeth.c 176SRCS+= hmac.c hm_ameth.c hm_pmeth.c
174 177
@@ -287,6 +290,7 @@ SRCS+= pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c
287 ${LCRYPTO_SRC}/err \ 290 ${LCRYPTO_SRC}/err \
288 ${LCRYPTO_SRC}/evp \ 291 ${LCRYPTO_SRC}/evp \
289 ${LCRYPTO_SRC}/gost \ 292 ${LCRYPTO_SRC}/gost \
293 ${LCRYPTO_SRC}/hkdf \
290 ${LCRYPTO_SRC}/hmac \ 294 ${LCRYPTO_SRC}/hmac \
291 ${LCRYPTO_SRC}/idea \ 295 ${LCRYPTO_SRC}/idea \
292 ${LCRYPTO_SRC}/lhash \ 296 ${LCRYPTO_SRC}/lhash \
@@ -344,6 +348,7 @@ HDRS=\
344 ${LCRYPTO_SRC}/err/err.h \ 348 ${LCRYPTO_SRC}/err/err.h \
345 ${LCRYPTO_SRC}/evp/evp.h \ 349 ${LCRYPTO_SRC}/evp/evp.h \
346 ${LCRYPTO_SRC}/gost/gost.h \ 350 ${LCRYPTO_SRC}/gost/gost.h \
351 ${LCRYPTO_SRC}/hkdf/hkdf.h \
347 ${LCRYPTO_SRC}/hmac/hmac.h \ 352 ${LCRYPTO_SRC}/hmac/hmac.h \
348 ${LCRYPTO_SRC}/idea/idea.h \ 353 ${LCRYPTO_SRC}/idea/idea.h \
349 ${LCRYPTO_SRC}/lhash/lhash.h \ 354 ${LCRYPTO_SRC}/lhash/lhash.h \
diff --git a/src/lib/libcrypto/hkdf/hkdf.c b/src/lib/libcrypto/hkdf/hkdf.c
new file mode 100644
index 0000000000..9fe587de13
--- /dev/null
+++ b/src/lib/libcrypto/hkdf/hkdf.c
@@ -0,0 +1,116 @@
1/* Copyright (c) 2014, Google Inc.
2 *
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.
6 *
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.
14 */
15
16#include <openssl/hkdf.h>
17
18#include <assert.h>
19#include <string.h>
20
21#include <openssl/err.h>
22#include <openssl/hmac.h>
23
24/* https://tools.ietf.org/html/rfc5869#section-2 */
25int
26HKDF(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)
29{
30 uint8_t prk[EVP_MAX_MD_SIZE];
31 size_t prk_len;
32
33 if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
34 salt_len))
35 return 0;
36 if (!HKDF_expand(out_key, out_len, digest, prk, prk_len, info,
37 info_len))
38 return 0;
39
40 return 1;
41}
42
43/* https://tools.ietf.org/html/rfc5869#section-2.2 */
44int
45HKDF_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)
48{
49 unsigned int len;
50
51 /*
52 * If salt is not given, HashLength zeros are used. However, HMAC does that
53 * internally already so we can ignore it.
54 */
55 if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) ==
56 NULL) {
57 CRYPTOerror(ERR_R_CRYPTO_LIB);
58 return 0;
59 }
60 *out_len = len;
61 return 1;
62}
63
64/* https://tools.ietf.org/html/rfc5869#section-2.3 */
65int
66HKDF_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)
69{
70 const size_t digest_len = EVP_MD_size(digest);
71 uint8_t previous[EVP_MAX_MD_SIZE];
72 size_t n, done = 0;
73 unsigned int i;
74 int ret = 0;
75 HMAC_CTX hmac;
76
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);
81 return 0;
82 }
83
84 HMAC_CTX_init(&hmac);
85 if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL))
86 goto out;
87
88 for (i = 0; i < n; i++) {
89 uint8_t ctr = i + 1;
90 size_t todo;
91
92 if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) ||
93 !HMAC_Update(&hmac, previous, digest_len)))
94 goto out;
95
96 if (!HMAC_Update(&hmac, info, info_len) ||
97 !HMAC_Update(&hmac, &ctr, 1) ||
98 !HMAC_Final(&hmac, previous, NULL))
99 goto out;
100
101 todo = digest_len;
102 if (done + todo > out_len)
103 todo = out_len - done;
104
105 memcpy(out_key + done, previous, todo);
106 done += todo;
107 }
108
109 ret = 1;
110
111 out:
112 HMAC_CTX_cleanup(&hmac);
113 if (ret != 1)
114 CRYPTOerror(ERR_R_CRYPTO_LIB);
115 return ret;
116}
diff --git a/src/lib/libcrypto/hkdf/hkdf.h b/src/lib/libcrypto/hkdf/hkdf.h
new file mode 100644
index 0000000000..fb0fac37af
--- /dev/null
+++ b/src/lib/libcrypto/hkdf/hkdf.h
@@ -0,0 +1,64 @@
1/* Copyright (c) 2014, Google Inc.
2 *
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.
6 *
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. */
14
15#ifndef OPENSSL_HEADER_HKDF_H
16#define OPENSSL_HEADER_HKDF_H
17
18#include <openssl/evp.h>
19
20#if defined(__cplusplus)
21extern "C" {
22#endif
23
24/*
25 * HKDF computes HKDF (as specified by RFC 5869) of initial keying
26 * material |secret| with |salt| and |info| using |digest|, and
27 * outputs |out_len| bytes to |out_key|. It returns one on success and
28 * zero on error.
29 *
30 * HKDF is an Extract-and-Expand algorithm. It does not do any key
31 * stretching, and as such, is not suited to be used alone to generate
32 * a key from a password.
33 */
34
35int HKDF(uint8_t *out_key, size_t out_len, const struct env_md_st *digest,
36 const uint8_t *secret, size_t secret_len, const uint8_t *salt,
37 size_t salt_len, const uint8_t *info, size_t info_len);
38
39/*
40 * HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from
41 * initial keying material |secret| and salt |salt| using |digest|,
42 * and outputs |out_len| bytes to |out_key|. The maximum output size
43 * is |EVP_MAX_MD_SIZE|. It returns one on success and zero on error.
44 */
45int HKDF_extract(uint8_t *out_key, size_t *out_len,
46 const struct env_md_st *digest, const uint8_t *secret,
47 size_t secret_len, const uint8_t *salt, size_t salt_len);
48
49/*
50 * HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of
51 * length |out_len| from the PRK |prk| and info |info| using |digest|,
52 * and outputs the result to |out_key|. It returns one on success and
53 * zero on error.
54 */
55int HKDF_expand(uint8_t *out_key, size_t out_len,
56 const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
57 const uint8_t *info, size_t info_len);
58
59
60#if defined(__cplusplus)
61} /* extern C */
62#endif
63
64#endif /* OPENSSL_HEADER_HKDF_H */