Return to wolfssl_x_diffie_hellman.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / wolfssl |
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 */