Return to wolfssl_diffie_hellman.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / wolfssl |
1.1 misho 1: /* 2: * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc. 3: * 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: 10: * 11: * The above copyright notice and this permission notice shall be included in 12: * all copies or substantial portions of the Software. 13: * 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 20: * THE SOFTWARE. 21: */ 22: 23: #include "wolfssl_common.h" 24: 25: #ifndef NO_DH 26: 27: #include <wolfssl/wolfcrypt/dh.h> 28: 29: #include "wolfssl_diffie_hellman.h" 30: #include "wolfssl_util.h" 31: 32: #include <utils/debug.h> 33: 34: typedef struct private_wolfssl_diffie_hellman_t private_wolfssl_diffie_hellman_t; 35: 36: /** 37: * Private data of an wolfssl_diffie_hellman_t object. 38: */ 39: struct private_wolfssl_diffie_hellman_t { 40: 41: /** 42: * Public wolfssl_diffie_hellman_t interface. 43: */ 44: wolfssl_diffie_hellman_t public; 45: 46: /** 47: * Diffie Hellman group number. 48: */ 49: diffie_hellman_group_t group; 50: 51: /** 52: * Diffie Hellman object 53: */ 54: DhKey dh; 55: 56: /** 57: * Length of public values 58: */ 59: int len; 60: 61: /** 62: * Private key 63: */ 64: chunk_t priv; 65: 66: /** 67: * Public key 68: */ 69: chunk_t pub; 70: 71: /** 72: * Shared secret 73: */ 74: chunk_t shared_secret; 75: }; 76: 77: METHOD(diffie_hellman_t, get_my_public_value, bool, 78: private_wolfssl_diffie_hellman_t *this, chunk_t *value) 79: { 80: *value = chunk_copy_pad(chunk_alloc(this->len), this->pub, 0x00); 81: return TRUE; 82: } 83: 84: METHOD(diffie_hellman_t, get_shared_secret, bool, 85: private_wolfssl_diffie_hellman_t *this, chunk_t *secret) 86: { 87: if (!this->shared_secret.len) 88: { 89: return FALSE; 90: } 91: *secret = chunk_copy_pad(chunk_alloc(this->len), this->shared_secret, 0x00); 92: return TRUE; 93: } 94: 95: METHOD(diffie_hellman_t, set_other_public_value, bool, 96: private_wolfssl_diffie_hellman_t *this, chunk_t value) 97: { 98: word32 len; 99: 100: if (!diffie_hellman_verify_value(this->group, value)) 101: { 102: return FALSE; 103: } 104: 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) 109: { 110: DBG1(DBG_LIB, "DH shared secret computation failed"); 111: chunk_free(&this->shared_secret); 112: return FALSE; 113: } 114: this->shared_secret.len = len; 115: return TRUE; 116: } 117: 118: METHOD(diffie_hellman_t, set_private_value, bool, 119: private_wolfssl_diffie_hellman_t *this, chunk_t value) 120: { 121: bool success = FALSE; 122: chunk_t g; 123: word32 len; 124: 125: chunk_clear(&this->priv); 126: this->priv = chunk_clone(value); 127: 128: /* calculate public value - g^priv mod p */ 129: if (wolfssl_mp2chunk(&this->dh.g, &g)) 130: { 131: len = this->pub.len; 132: if (wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr, 133: this->priv.len, g.ptr, g.len) == 0) 134: { 135: this->pub.len = len; 136: success = TRUE; 137: } 138: } 139: 140: free(g.ptr); 141: return success; 142: } 143: 144: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, 145: private_wolfssl_diffie_hellman_t *this) 146: { 147: return this->group; 148: } 149: 150: METHOD(diffie_hellman_t, destroy, void, 151: private_wolfssl_diffie_hellman_t *this) 152: { 153: wc_FreeDhKey(&this->dh); 154: chunk_clear(&this->pub); 155: chunk_clear(&this->priv); 156: chunk_clear(&this->shared_secret); 157: free(this); 158: } 159: 160: /** 161: * Maximum private key length when generating key 162: */ 163: static int wolfssl_priv_key_size(int len) 164: { 165: if (len <= 128) 166: { 167: return 21; 168: } 169: if (len <= 256) 170: { 171: return 29; 172: } 173: if (len <= 384) 174: { 175: return 34; 176: } 177: if (len <= 512) 178: { 179: return 39; 180: } 181: if (len <= 640) 182: { 183: return 42; 184: } 185: if (len <= 768) 186: { 187: return 46; 188: } 189: if (len <= 896) 190: { 191: return 49; 192: } 193: if (len <= 1024) 194: { 195: return 52; 196: } 197: return len / 20; 198: } 199: 200: /** 201: * Generic internal constructor 202: */ 203: static wolfssl_diffie_hellman_t *create_generic(diffie_hellman_group_t group, 204: chunk_t g, chunk_t p) 205: { 206: private_wolfssl_diffie_hellman_t *this; 207: word32 privLen, pubLen; 208: WC_RNG rng; 209: 210: INIT(this, 211: .public = { 212: .dh = { 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, 218: .destroy = _destroy, 219: }, 220: }, 221: .group = group, 222: .len = p.len, 223: ); 224: 225: if (wc_InitDhKey(&this->dh) != 0) 226: { 227: free(this); 228: return NULL; 229: } 230: 231: if (wc_DhSetKey(&this->dh, p.ptr, p.len, g.ptr, g.len) != 0) 232: { 233: destroy(this); 234: return NULL; 235: } 236: 237: if (wc_InitRng(&rng) != 0) 238: { 239: destroy(this); 240: return NULL; 241: } 242: 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) 250: { 251: wc_FreeRng(&rng); 252: destroy(this); 253: return NULL; 254: } 255: this->pub.len = pubLen; 256: this->priv.len = privLen; 257: wc_FreeRng(&rng); 258: 259: return &this->public; 260: } 261: 262: /* 263: * Described in header 264: */ 265: wolfssl_diffie_hellman_t *wolfssl_diffie_hellman_create( 266: diffie_hellman_group_t group, ...) 267: { 268: diffie_hellman_params_t *params; 269: chunk_t g, p; 270: 271: if (group == MODP_CUSTOM) 272: { 273: VA_ARGS_GET(group, g, p); 274: return create_generic(group, g, p); 275: } 276: params = diffie_hellman_get_params(group); 277: if (!params) 278: { 279: return NULL; 280: } 281: /* wolfSSL doesn't support optimized exponent sizes according to RFC 3526 */ 282: return create_generic(group, params->generator, params->prime); 283: } 284: 285: #endif /* NO_DH */