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"
25 #ifdef HAVE_CURVE25519
27 #include "wolfssl_x_diffie_hellman.h"
29 #include <utils/debug.h>
31 #include <wolfssl/wolfcrypt/curve25519.h>
32 #include <wolfssl/wolfcrypt/fe_operations.h>
34 typedef struct private_diffie_hellman_t private_diffie_hellman_t
;
39 struct private_diffie_hellman_t
{
43 diffie_hellman_t
public;
46 * Diffie Hellman group number.
48 diffie_hellman_group_t group
;
51 * Private (public) key
58 chunk_t shared_secret
;
61 * True if shared secret is computed
67 * Compute the shared secret
69 static bool compute_shared_key(private_diffie_hellman_t
*this,
70 curve25519_key
*pub
, chunk_t
*shared_secret
)
73 word32 len
= CURVE25519_KEYSIZE
;
75 *shared_secret
= chunk_alloc(len
);
76 ret
= wc_curve25519_shared_secret_ex(&this->key
, pub
, shared_secret
->ptr
,
77 &len
, EC25519_LITTLE_ENDIAN
);
81 METHOD(diffie_hellman_t
, set_other_public_value
, bool,
82 private_diffie_hellman_t
*this, chunk_t value
)
87 if (!diffie_hellman_verify_value(this->group
, value
))
92 ret
= wc_curve25519_init(&pub
);
95 DBG1(DBG_LIB
, "%N public key initialization failed",
96 diffie_hellman_group_names
, this->group
);
100 ret
= wc_curve25519_import_public_ex(value
.ptr
, value
.len
, &pub
,
101 EC25519_LITTLE_ENDIAN
);
104 DBG1(DBG_LIB
, "%N public value is malformed",
105 diffie_hellman_group_names
, this->group
);
109 chunk_clear(&this->shared_secret
);
111 if (!compute_shared_key(this, &pub
, &this->shared_secret
))
113 DBG1(DBG_LIB
, "%N shared secret computation failed",
114 diffie_hellman_group_names
, this->group
);
115 wc_curve25519_free(&pub
);
118 this->computed
= TRUE
;
119 wc_curve25519_free(&pub
);
123 METHOD(diffie_hellman_t
, get_my_public_value
, bool,
124 private_diffie_hellman_t
*this, chunk_t
*value
)
126 word32 len
= CURVE25519_KEYSIZE
;
128 *value
= chunk_alloc(len
);
129 if (wc_curve25519_export_public_ex(&this->key
, value
->ptr
, &len
,
130 EC25519_LITTLE_ENDIAN
) != 0)
138 METHOD(diffie_hellman_t
, set_private_value
, bool,
139 private_diffie_hellman_t
*this, chunk_t value
)
142 unsigned char basepoint
[CURVE25519_KEYSIZE
] = {9};
146 ret
= wc_curve25519_init(&pub
);
147 /* Create base point for calculating public key */
150 ret
= wc_curve25519_import_public_ex(basepoint
, CURVE25519_KEYSIZE
,
151 &pub
, EC25519_LITTLE_ENDIAN
);
155 ret
= wc_curve25519_import_private_ex(value
.ptr
, value
.len
, &this->key
,
156 EC25519_LITTLE_ENDIAN
);
160 len
= CURVE25519_KEYSIZE
;
161 ret
= wc_curve25519_shared_secret_ex(&this->key
, &pub
,
162 this->key
.p
.point
, &len
, EC25519_LITTLE_ENDIAN
);
172 METHOD(diffie_hellman_t
, get_shared_secret
, bool,
173 private_diffie_hellman_t
*this, chunk_t
*secret
)
179 *secret
= chunk_clone(this->shared_secret
);
183 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
184 private_diffie_hellman_t
*this)
189 METHOD(diffie_hellman_t
, destroy
, void,
190 private_diffie_hellman_t
*this)
192 wc_curve25519_free(&this->key
);
193 chunk_clear(&this->shared_secret
);
198 * Described in header
200 diffie_hellman_t
*wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group
)
202 private_diffie_hellman_t
*this;
216 .get_shared_secret
= _get_shared_secret
,
217 .set_other_public_value
= _set_other_public_value
,
218 .get_my_public_value
= _get_my_public_value
,
219 .set_private_value
= _set_private_value
,
220 .get_dh_group
= _get_dh_group
,
226 if (wc_curve25519_init(&this->key
) != 0)
228 DBG1(DBG_LIB
, "Initializing key failed");
233 if (wc_InitRng(&rng
) != 0)
235 DBG1(DBG_LIB
, "Initializing a random number generator failed");
239 ret
= wc_curve25519_make_key(&rng
, CURVE25519_KEYSIZE
, &this->key
);
243 DBG1(DBG_LIB
, "Making a key failed");
247 return &this->public;
250 #endif /* HAVE_CURVE25519 */