2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #include "wolfssl_common.h"
27 #include <wolfssl/wolfcrypt/dh.h>
29 #include "wolfssl_diffie_hellman.h"
30 #include "wolfssl_util.h"
32 #include <utils/debug.h>
34 typedef struct private_wolfssl_diffie_hellman_t private_wolfssl_diffie_hellman_t
;
37 * Private data of an wolfssl_diffie_hellman_t object.
39 struct private_wolfssl_diffie_hellman_t
{
42 * Public wolfssl_diffie_hellman_t interface.
44 wolfssl_diffie_hellman_t
public;
47 * Diffie Hellman group number.
49 diffie_hellman_group_t group
;
52 * Diffie Hellman object
57 * Length of public values
74 chunk_t shared_secret
;
77 METHOD(diffie_hellman_t
, get_my_public_value
, bool,
78 private_wolfssl_diffie_hellman_t
*this, chunk_t
*value
)
80 *value
= chunk_copy_pad(chunk_alloc(this->len
), this->pub
, 0x00);
84 METHOD(diffie_hellman_t
, get_shared_secret
, bool,
85 private_wolfssl_diffie_hellman_t
*this, chunk_t
*secret
)
87 if (!this->shared_secret
.len
)
91 *secret
= chunk_copy_pad(chunk_alloc(this->len
), this->shared_secret
, 0x00);
95 METHOD(diffie_hellman_t
, set_other_public_value
, bool,
96 private_wolfssl_diffie_hellman_t
*this, chunk_t value
)
100 if (!diffie_hellman_verify_value(this->group
, value
))
105 chunk_clear(&this->shared_secret
);
106 this->shared_secret
= chunk_alloc(this->len
);
107 if (wc_DhAgree(&this->dh
, this->shared_secret
.ptr
, &len
, this->priv
.ptr
,
108 this->priv
.len
, value
.ptr
, value
.len
) != 0)
110 DBG1(DBG_LIB
, "DH shared secret computation failed");
111 chunk_free(&this->shared_secret
);
114 this->shared_secret
.len
= len
;
118 METHOD(diffie_hellman_t
, set_private_value
, bool,
119 private_wolfssl_diffie_hellman_t
*this, chunk_t value
)
121 bool success
= FALSE
;
125 chunk_clear(&this->priv
);
126 this->priv
= chunk_clone(value
);
128 /* calculate public value - g^priv mod p */
129 if (wolfssl_mp2chunk(&this->dh
.g
, &g
))
132 if (wc_DhAgree(&this->dh
, this->pub
.ptr
, &len
, this->priv
.ptr
,
133 this->priv
.len
, g
.ptr
, g
.len
) == 0)
144 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
145 private_wolfssl_diffie_hellman_t
*this)
150 METHOD(diffie_hellman_t
, destroy
, void,
151 private_wolfssl_diffie_hellman_t
*this)
153 wc_FreeDhKey(&this->dh
);
154 chunk_clear(&this->pub
);
155 chunk_clear(&this->priv
);
156 chunk_clear(&this->shared_secret
);
161 * Maximum private key length when generating key
163 static int wolfssl_priv_key_size(int len
)
201 * Generic internal constructor
203 static wolfssl_diffie_hellman_t
*create_generic(diffie_hellman_group_t group
,
204 chunk_t g
, chunk_t p
)
206 private_wolfssl_diffie_hellman_t
*this;
207 word32 privLen
, pubLen
;
213 .get_shared_secret
= _get_shared_secret
,
214 .set_other_public_value
= _set_other_public_value
,
215 .get_my_public_value
= _get_my_public_value
,
216 .set_private_value
= _set_private_value
,
217 .get_dh_group
= _get_dh_group
,
225 if (wc_InitDhKey(&this->dh
) != 0)
231 if (wc_DhSetKey(&this->dh
, p
.ptr
, p
.len
, g
.ptr
, g
.len
) != 0)
237 if (wc_InitRng(&rng
) != 0)
243 this->priv
= chunk_alloc(wolfssl_priv_key_size(this->len
));
244 this->pub
= chunk_alloc(this->len
);
245 privLen
= this->priv
.len
;
246 pubLen
= this->pub
.len
;
247 /* generate my public and private values */
248 if (wc_DhGenerateKeyPair(&this->dh
, &rng
, this->priv
.ptr
, &privLen
,
249 this->pub
.ptr
, &pubLen
) != 0)
255 this->pub
.len
= pubLen
;
256 this->priv
.len
= privLen
;
259 return &this->public;
263 * Described in header
265 wolfssl_diffie_hellman_t
*wolfssl_diffie_hellman_create(
266 diffie_hellman_group_t group
, ...)
268 diffie_hellman_params_t
*params
;
271 if (group
== MODP_CUSTOM
)
273 VA_ARGS_GET(group
, g
, p
);
274 return create_generic(group
, g
, p
);
276 params
= diffie_hellman_get_params(group
);
281 /* wolfSSL doesn't support optimized exponent sizes according to RFC 3526 */
282 return create_generic(group
, params
->generator
, params
->prime
);