Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2020 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
1.1 misho 5: * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the "Software"), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11: * copies of the Software, and to permit persons to whom the Software is
12: * furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included in
15: * all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23: * THE SOFTWARE.
24: */
25:
26: #include "wolfssl_common.h"
27:
1.1.1.2 ! misho 28: #if defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
1.1 misho 29:
30: #include "wolfssl_x_diffie_hellman.h"
31:
32: #include <utils/debug.h>
33:
1.1.1.2 ! misho 34: #ifdef HAVE_CURVE25519
1.1 misho 35: #include <wolfssl/wolfcrypt/curve25519.h>
1.1.1.2 ! misho 36: #endif
! 37: #ifdef HAVE_CURVE448
! 38: #include <wolfssl/wolfcrypt/curve448.h>
! 39: #endif
! 40:
1.1 misho 41: #include <wolfssl/wolfcrypt/fe_operations.h>
42:
43: typedef struct private_diffie_hellman_t private_diffie_hellman_t;
44:
45: /**
46: * Private data
47: */
48: struct private_diffie_hellman_t {
49: /**
50: * Public interface.
51: */
52: diffie_hellman_t public;
53:
54: /**
55: * Diffie Hellman group number.
56: */
57: diffie_hellman_group_t group;
58:
59: /**
60: * Private (public) key
61: */
1.1.1.2 ! misho 62: union {
! 63: #ifdef HAVE_CURVE25519
! 64: curve25519_key key25519;
! 65: #endif
! 66: #ifdef HAVE_CURVE448
! 67: curve448_key key448;
! 68: #endif
! 69: } key;
1.1 misho 70:
71: /**
72: * Shared secret
73: */
74: chunk_t shared_secret;
75: };
76:
1.1.1.2 ! misho 77: #ifdef HAVE_CURVE25519
1.1 misho 78:
1.1.1.2 ! misho 79: METHOD(diffie_hellman_t, set_other_public_value_25519, bool,
1.1 misho 80: private_diffie_hellman_t *this, chunk_t value)
81: {
1.1.1.2 ! misho 82: word32 len = CURVE25519_KEYSIZE;
1.1 misho 83: curve25519_key pub;
84: int ret;
85:
86: if (!diffie_hellman_verify_value(this->group, value))
87: {
88: return FALSE;
89: }
90:
91: ret = wc_curve25519_init(&pub);
92: if (ret != 0)
93: {
94: DBG1(DBG_LIB, "%N public key initialization failed",
95: diffie_hellman_group_names, this->group);
96: return FALSE;
97: }
98:
99: ret = wc_curve25519_import_public_ex(value.ptr, value.len, &pub,
100: EC25519_LITTLE_ENDIAN);
101: if (ret != 0)
102: {
103: DBG1(DBG_LIB, "%N public value is malformed",
104: diffie_hellman_group_names, this->group);
105: return FALSE;
106: }
107:
108: chunk_clear(&this->shared_secret);
1.1.1.2 ! misho 109: this->shared_secret = chunk_alloc(len);
! 110: if (wc_curve25519_shared_secret_ex(&this->key.key25519, &pub,
! 111: this->shared_secret.ptr, &len, EC25519_LITTLE_ENDIAN) != 0)
1.1 misho 112: {
113: DBG1(DBG_LIB, "%N shared secret computation failed",
114: diffie_hellman_group_names, this->group);
115: chunk_clear(&this->shared_secret);
116: wc_curve25519_free(&pub);
117: return FALSE;
118: }
119: wc_curve25519_free(&pub);
120: return TRUE;
121: }
122:
1.1.1.2 ! misho 123: METHOD(diffie_hellman_t, get_my_public_value_25519, bool,
1.1 misho 124: private_diffie_hellman_t *this, chunk_t *value)
125: {
126: word32 len = CURVE25519_KEYSIZE;
127:
128: *value = chunk_alloc(len);
1.1.1.2 ! misho 129: if (wc_curve25519_export_public_ex(&this->key.key25519, value->ptr, &len,
1.1 misho 130: EC25519_LITTLE_ENDIAN) != 0)
131: {
132: chunk_free(value);
133: return FALSE;
134: }
135: return TRUE;
136: }
137:
1.1.1.2 ! misho 138: METHOD(diffie_hellman_t, set_private_value_25519, bool,
1.1 misho 139: private_diffie_hellman_t *this, chunk_t value)
140: {
141: curve25519_key pub;
142: u_char basepoint[CURVE25519_KEYSIZE] = {9};
143: word32 len = CURVE25519_KEYSIZE;
144: int ret;
145:
146: ret = wc_curve25519_init(&pub);
147: /* create base point for calculating public key */
148: if (ret == 0)
149: {
150: ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE,
151: &pub, EC25519_LITTLE_ENDIAN);
152: }
153: if (ret == 0)
154: {
1.1.1.2 ! misho 155: ret = wc_curve25519_import_private_ex(value.ptr, value.len,
! 156: &this->key.key25519, EC25519_LITTLE_ENDIAN);
! 157: }
! 158: if (ret == 0)
! 159: {
! 160: ret = wc_curve25519_shared_secret_ex(&this->key.key25519, &pub,
! 161: this->key.key25519.p.point, &len,
! 162: EC25519_LITTLE_ENDIAN);
! 163: }
! 164: return ret == 0;
! 165: }
! 166:
! 167: #endif /* HAVE_CURVE25519 */
! 168:
! 169: #ifdef HAVE_CURVE448
! 170:
! 171: METHOD(diffie_hellman_t, set_other_public_value_448, bool,
! 172: private_diffie_hellman_t *this, chunk_t value)
! 173: {
! 174: word32 len = CURVE448_KEY_SIZE;
! 175: curve448_key pub;
! 176: int ret;
! 177:
! 178: if (!diffie_hellman_verify_value(this->group, value))
! 179: {
! 180: return FALSE;
! 181: }
! 182:
! 183: ret = wc_curve448_init(&pub);
! 184: if (ret != 0)
! 185: {
! 186: DBG1(DBG_LIB, "%N public key initialization failed",
! 187: diffie_hellman_group_names, this->group);
! 188: return FALSE;
! 189: }
! 190:
! 191: ret = wc_curve448_import_public_ex(value.ptr, value.len, &pub,
! 192: EC448_LITTLE_ENDIAN);
! 193: if (ret != 0)
! 194: {
! 195: DBG1(DBG_LIB, "%N public value is malformed",
! 196: diffie_hellman_group_names, this->group);
! 197: return FALSE;
! 198: }
! 199:
! 200: chunk_clear(&this->shared_secret);
! 201: this->shared_secret = chunk_alloc(len);
! 202: if (wc_curve448_shared_secret_ex(&this->key.key448, &pub,
! 203: this->shared_secret.ptr, &len, EC448_LITTLE_ENDIAN) != 0)
! 204: {
! 205: DBG1(DBG_LIB, "%N shared secret computation failed",
! 206: diffie_hellman_group_names, this->group);
! 207: chunk_clear(&this->shared_secret);
! 208: wc_curve448_free(&pub);
! 209: return FALSE;
! 210: }
! 211: wc_curve448_free(&pub);
! 212: return TRUE;
! 213: }
! 214:
! 215: METHOD(diffie_hellman_t, get_my_public_value_448, bool,
! 216: private_diffie_hellman_t *this, chunk_t *value)
! 217: {
! 218: word32 len = CURVE448_KEY_SIZE;
! 219:
! 220: *value = chunk_alloc(len);
! 221: if (wc_curve448_export_public_ex(&this->key.key448, value->ptr, &len,
! 222: EC448_LITTLE_ENDIAN) != 0)
! 223: {
! 224: chunk_free(value);
! 225: return FALSE;
! 226: }
! 227: return TRUE;
! 228: }
! 229:
! 230: METHOD(diffie_hellman_t, set_private_value_448, bool,
! 231: private_diffie_hellman_t *this, chunk_t value)
! 232: {
! 233: curve448_key pub;
! 234: u_char basepoint[CURVE448_KEY_SIZE] = {5};
! 235: word32 len = CURVE448_KEY_SIZE;
! 236: int ret;
! 237:
! 238: ret = wc_curve448_init(&pub);
! 239: /* create base point for calculating public key */
! 240: if (ret == 0)
! 241: {
! 242: ret = wc_curve448_import_public_ex(basepoint, CURVE448_KEY_SIZE,
! 243: &pub, EC448_LITTLE_ENDIAN);
! 244: }
! 245: if (ret == 0)
! 246: {
! 247: ret = wc_curve448_import_private_ex(value.ptr, value.len,
! 248: &this->key.key448, EC448_LITTLE_ENDIAN);
1.1 misho 249: }
250: if (ret == 0)
251: {
1.1.1.2 ! misho 252: ret = wc_curve448_shared_secret_ex(&this->key.key448, &pub,
! 253: this->key.key448.p, &len,
! 254: EC448_LITTLE_ENDIAN);
1.1 misho 255: }
256: return ret == 0;
257: }
258:
1.1.1.2 ! misho 259: #endif /* HAVE_CURVE448 */
! 260:
1.1 misho 261: METHOD(diffie_hellman_t, get_shared_secret, bool,
262: private_diffie_hellman_t *this, chunk_t *secret)
263: {
264: if (!this->shared_secret.len)
265: {
266: return FALSE;
267: }
268: *secret = chunk_clone(this->shared_secret);
269: return TRUE;
270: }
271:
272: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
273: private_diffie_hellman_t *this)
274: {
275: return this->group;
276: }
277:
278: METHOD(diffie_hellman_t, destroy, void,
279: private_diffie_hellman_t *this)
280: {
1.1.1.2 ! misho 281: if (this->group == CURVE_25519)
! 282: {
! 283: #ifdef HAVE_CURVE25519
! 284: wc_curve25519_free(&this->key.key25519);
! 285: #endif
! 286: }
! 287: else if (this->group == CURVE_448)
! 288: {
! 289: #ifdef HAVE_CURVE448
! 290: wc_curve448_free(&this->key.key448);
! 291: #endif
! 292: }
1.1 misho 293: chunk_clear(&this->shared_secret);
294: free(this);
295: }
296:
297: /*
298: * Described in header
299: */
300: diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
301: {
302: private_diffie_hellman_t *this;
303: WC_RNG rng;
1.1.1.2 ! misho 304: int ret = -1;
1.1 misho 305:
306: INIT(this,
307: .public = {
308: .get_shared_secret = _get_shared_secret,
309: .get_dh_group = _get_dh_group,
310: .destroy = _destroy,
311: },
312: .group = group,
313: );
314:
315: if (wc_InitRng(&rng) != 0)
316: {
317: DBG1(DBG_LIB, "initializing a random number generator failed");
318: destroy(this);
319: return NULL;
320: }
1.1.1.2 ! misho 321:
! 322: if (group == CURVE_25519)
! 323: {
! 324: #ifdef HAVE_CURVE25519
! 325: this->public.set_other_public_value = _set_other_public_value_25519;
! 326: this->public.get_my_public_value = _get_my_public_value_25519;
! 327: this->public.set_private_value = _set_private_value_25519;
! 328:
! 329: if (wc_curve25519_init(&this->key.key25519) != 0)
! 330: {
! 331: DBG1(DBG_LIB, "initializing key failed");
! 332: free(this);
! 333: return NULL;
! 334: }
! 335: ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE,
! 336: &this->key.key25519);
! 337: #endif
! 338: }
! 339: else if (group == CURVE_448)
! 340: {
! 341: #ifdef HAVE_CURVE448
! 342: this->public.set_other_public_value = _set_other_public_value_448;
! 343: this->public.get_my_public_value = _get_my_public_value_448;
! 344: this->public.set_private_value = _set_private_value_448;
! 345:
! 346: if (wc_curve448_init(&this->key.key448) != 0)
! 347: {
! 348: DBG1(DBG_LIB, "initializing key failed");
! 349: free(this);
! 350: return NULL;
! 351: }
! 352: ret = wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &this->key.key448);
! 353: #endif
! 354: }
1.1 misho 355: wc_FreeRng(&rng);
356: if (ret != 0)
357: {
358: DBG1(DBG_LIB, "making a key failed");
359: destroy(this);
360: return NULL;
361: }
362: return &this->public;
363: }
364:
1.1.1.2 ! misho 365: #endif /* HAVE_CURVE25519 || HAVE_CURVE448 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>