1 | /* |
1 | /* |
2 | hkdf.C -- RFC 5869 HKDF implementation |
2 | hkdf.C -- RFC 5869 HKDF implementation |
3 | Copyright (C) 2013 Marc Lehmann <gvpe@schmorp.de> |
3 | Copyright (C) 2013,2016 Marc Lehmann <gvpe@schmorp.de> |
4 | |
4 | |
5 | This file is part of GVPE. |
5 | This file is part of GVPE. |
6 | |
6 | |
7 | GVPE is free software; you can redistribute it and/or modify it |
7 | GVPE is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by the |
8 | under the terms of the GNU General Public License as published by the |
… | |
… | |
31 | |
31 | |
32 | #include "config.h" |
32 | #include "config.h" |
33 | |
33 | |
34 | #include <cstring> |
34 | #include <cstring> |
35 | |
35 | |
|
|
36 | #include <openssl/opensslv.h> |
36 | #include <openssl/rand.h> |
37 | #include <openssl/rand.h> |
37 | #include <openssl/hmac.h> |
38 | #include <openssl/hmac.h> |
38 | |
39 | |
|
|
40 | #include "crypto.h" |
39 | #include "util.h" |
41 | #include "util.h" |
40 | #include "hkdf.h" |
42 | #include "hkdf.h" |
41 | |
43 | |
42 | hkdf::hkdf (const void *salt, int len, const EVP_MD *hash) |
44 | hkdf::hkdf (const void *salt, int len, const EVP_MD *xtr_hash) |
|
|
45 | : salt (salt), salt_len (len) |
43 | { |
46 | { |
44 | HMAC_CTX_init (&ctx); |
47 | ctx.init (salt, salt_len, xtr_hash); |
45 | |
|
|
46 | if (!salt) |
|
|
47 | { |
|
|
48 | memset (prk, 0, sizeof prk); |
|
|
49 | salt = prk; |
|
|
50 | len = EVP_MD_size (hash); |
|
|
51 | } |
|
|
52 | |
|
|
53 | require (HMAC_Init_ex (&ctx, salt, len, hash, 0)); |
|
|
54 | } |
|
|
55 | |
|
|
56 | hkdf::~hkdf () |
|
|
57 | { |
|
|
58 | HMAC_CTX_cleanup (&ctx); |
|
|
59 | } |
48 | } |
60 | |
49 | |
61 | void |
50 | void |
62 | hkdf::extract (const void *ikm, int len) |
51 | hkdf::extract (const void *ikm, int len) |
63 | { |
52 | { |
64 | require (HMAC_Update (&ctx, (u8 *)ikm, len)); |
53 | ctx.add (ikm, len); |
65 | } |
54 | } |
66 | |
55 | |
67 | void |
56 | void |
68 | hkdf::extract_done () |
57 | hkdf::extract_done (const EVP_MD *prf_hash) |
69 | { |
58 | { |
70 | require (HMAC_Final (&ctx, prk, 0)); |
59 | ctx.digest (prk); |
|
|
60 | ctx.init (salt, salt_len, prf_hash); |
71 | } |
61 | } |
72 | |
62 | |
73 | void |
63 | void |
74 | hkdf::expand (void *okm, int len, const void *info, int infolen) |
64 | hkdf::expand (void *okm, int len, const void *info, int infolen) |
75 | { |
65 | { |
76 | u8 tn[sizeof prk]; |
66 | u8 tn[sizeof prk]; |
77 | u8 iter = 0; |
67 | u8 iter = 0; |
78 | int md_size = HMAC_size (&ctx); |
68 | int md_size = ctx.size (); |
79 | |
69 | |
80 | while (len) |
70 | while (len) |
81 | { |
71 | { |
82 | require (HMAC_Init_ex (&ctx, prk, md_size, 0, 0)); |
72 | ctx.init (prk, md_size); |
83 | |
73 | |
84 | if (iter) |
74 | if (iter) |
85 | require (HMAC_Update (&ctx, tn, md_size)); |
75 | ctx.add (tn, md_size); |
86 | |
76 | |
87 | require (HMAC_Update (&ctx, (u8 *)info, infolen)); |
77 | ctx.add (info, infolen); |
88 | |
|
|
89 | |
78 | |
90 | ++iter; |
79 | ++iter; |
91 | require (iter); |
80 | require (iter); |
92 | |
81 | |
93 | require (HMAC_Update (&ctx, &iter, 1)); |
82 | ctx.add (&iter, 1); |
94 | |
83 | ctx.digest (tn); |
95 | require (HMAC_Final (&ctx, tn, 0)); |
|
|
96 | |
84 | |
97 | int ol = len > md_size ? md_size : len; |
85 | int ol = len > md_size ? md_size : len; |
98 | |
86 | |
99 | memcpy (okm, tn, ol); |
87 | memcpy (okm, tn, ol); |
100 | |
88 | |
… | |
… | |
117 | u8 s[256]; |
105 | u8 s[256]; |
118 | |
106 | |
119 | unhex (const char *hs) |
107 | unhex (const char *hs) |
120 | { |
108 | { |
121 | l = 0; |
109 | l = 0; |
122 | p = 0; |
110 | p = s; |
123 | |
111 | |
124 | if (!hs) |
112 | if (!hs) |
125 | return; |
113 | return; |
126 | |
|
|
127 | p = s; |
|
|
128 | |
114 | |
129 | while (*hs) |
115 | while (*hs) |
130 | { |
116 | { |
131 | int d1 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs; |
117 | int d1 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs; |
132 | int d2 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs; |
118 | int d2 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs; |