Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008-2010 Tobias Brunner
! 3: * Copyright (C) 2008 Martin Willi
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include <openssl/opensslconf.h>
! 18:
! 19: #ifndef OPENSSL_NO_DH
! 20:
! 21: #include <openssl/bn.h>
! 22: #include <openssl/dh.h>
! 23:
! 24: #include "openssl_diffie_hellman.h"
! 25: #include "openssl_util.h"
! 26:
! 27: #include <utils/debug.h>
! 28:
! 29: /* these were added with 1.1.0 when DH was made opaque */
! 30: #if OPENSSL_VERSION_NUMBER < 0x10100000L
! 31: OPENSSL_KEY_FALLBACK(DH, key, pub_key, priv_key)
! 32: OPENSSL_KEY_FALLBACK(DH, pqg, p, q, g)
! 33: #define DH_set_length(dh, len) ({ (dh)->length = len; 1; })
! 34: #endif
! 35:
! 36: typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
! 37:
! 38: /**
! 39: * Private data of an openssl_diffie_hellman_t object.
! 40: */
! 41: struct private_openssl_diffie_hellman_t {
! 42: /**
! 43: * Public openssl_diffie_hellman_t interface.
! 44: */
! 45: openssl_diffie_hellman_t public;
! 46:
! 47: /**
! 48: * Diffie Hellman group number.
! 49: */
! 50: diffie_hellman_group_t group;
! 51:
! 52: /**
! 53: * Diffie Hellman object
! 54: */
! 55: DH *dh;
! 56:
! 57: /**
! 58: * Other public value
! 59: */
! 60: BIGNUM *pub_key;
! 61:
! 62: /**
! 63: * Shared secret
! 64: */
! 65: chunk_t shared_secret;
! 66:
! 67: /**
! 68: * True if shared secret is computed
! 69: */
! 70: bool computed;
! 71: };
! 72:
! 73: METHOD(diffie_hellman_t, get_my_public_value, bool,
! 74: private_openssl_diffie_hellman_t *this, chunk_t *value)
! 75: {
! 76: const BIGNUM *pubkey;
! 77:
! 78: *value = chunk_alloc(DH_size(this->dh));
! 79: memset(value->ptr, 0, value->len);
! 80: DH_get0_key(this->dh, &pubkey, NULL);
! 81: BN_bn2bin(pubkey, value->ptr + value->len - BN_num_bytes(pubkey));
! 82: return TRUE;
! 83: }
! 84:
! 85: METHOD(diffie_hellman_t, get_shared_secret, bool,
! 86: private_openssl_diffie_hellman_t *this, chunk_t *secret)
! 87: {
! 88: if (!this->computed)
! 89: {
! 90: return FALSE;
! 91: }
! 92: /* shared secret should requires a len according the DH group */
! 93: *secret = chunk_alloc(DH_size(this->dh));
! 94: memset(secret->ptr, 0, secret->len);
! 95: memcpy(secret->ptr + secret->len - this->shared_secret.len,
! 96: this->shared_secret.ptr, this->shared_secret.len);
! 97: return TRUE;
! 98: }
! 99:
! 100:
! 101: METHOD(diffie_hellman_t, set_other_public_value, bool,
! 102: private_openssl_diffie_hellman_t *this, chunk_t value)
! 103: {
! 104: int len;
! 105:
! 106: if (!diffie_hellman_verify_value(this->group, value))
! 107: {
! 108: return FALSE;
! 109: }
! 110:
! 111: BN_bin2bn(value.ptr, value.len, this->pub_key);
! 112: chunk_clear(&this->shared_secret);
! 113: this->shared_secret.ptr = malloc(DH_size(this->dh));
! 114: memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
! 115: len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
! 116: if (len < 0)
! 117: {
! 118: DBG1(DBG_LIB, "DH shared secret computation failed");
! 119: return FALSE;
! 120: }
! 121: this->shared_secret.len = len;
! 122: this->computed = TRUE;
! 123: return TRUE;
! 124: }
! 125:
! 126: METHOD(diffie_hellman_t, set_private_value, bool,
! 127: private_openssl_diffie_hellman_t *this, chunk_t value)
! 128: {
! 129: BIGNUM *privkey;
! 130:
! 131: privkey = BN_bin2bn(value.ptr, value.len, NULL);
! 132: if (privkey)
! 133: {
! 134: if (!DH_set0_key(this->dh, NULL, privkey))
! 135: {
! 136: return FALSE;
! 137: }
! 138: chunk_clear(&this->shared_secret);
! 139: this->computed = FALSE;
! 140: return DH_generate_key(this->dh);
! 141: }
! 142: return FALSE;
! 143: }
! 144:
! 145: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
! 146: private_openssl_diffie_hellman_t *this)
! 147: {
! 148: return this->group;
! 149: }
! 150:
! 151: /**
! 152: * Lookup the modulus in modulo table
! 153: */
! 154: static status_t set_modulus(private_openssl_diffie_hellman_t *this)
! 155: {
! 156: BIGNUM *p, *g;
! 157:
! 158: diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
! 159: if (!params)
! 160: {
! 161: return NOT_FOUND;
! 162: }
! 163: p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL);
! 164: g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL);
! 165: if (!DH_set0_pqg(this->dh, p, NULL, g))
! 166: {
! 167: return FAILED;
! 168: }
! 169: if (params->exp_len != params->prime.len)
! 170: {
! 171: #ifdef OPENSSL_IS_BORINGSSL
! 172: this->dh->priv_length = params->exp_len * 8;
! 173: #else
! 174: if (!DH_set_length(this->dh, params->exp_len * 8))
! 175: {
! 176: return FAILED;
! 177: }
! 178: #endif
! 179: }
! 180: return SUCCESS;
! 181: }
! 182:
! 183: METHOD(diffie_hellman_t, destroy, void,
! 184: private_openssl_diffie_hellman_t *this)
! 185: {
! 186: BN_clear_free(this->pub_key);
! 187: DH_free(this->dh);
! 188: chunk_clear(&this->shared_secret);
! 189: free(this);
! 190: }
! 191:
! 192: /*
! 193: * Described in header.
! 194: */
! 195: openssl_diffie_hellman_t *openssl_diffie_hellman_create(
! 196: diffie_hellman_group_t group, ...)
! 197: {
! 198: private_openssl_diffie_hellman_t *this;
! 199: const BIGNUM *privkey;
! 200:
! 201: INIT(this,
! 202: .public = {
! 203: .dh = {
! 204: .get_shared_secret = _get_shared_secret,
! 205: .set_other_public_value = _set_other_public_value,
! 206: .get_my_public_value = _get_my_public_value,
! 207: .set_private_value = _set_private_value,
! 208: .get_dh_group = _get_dh_group,
! 209: .destroy = _destroy,
! 210: },
! 211: },
! 212: );
! 213:
! 214: this->dh = DH_new();
! 215: if (!this->dh)
! 216: {
! 217: free(this);
! 218: return NULL;
! 219: }
! 220:
! 221: this->group = group;
! 222: this->computed = FALSE;
! 223: this->pub_key = BN_new();
! 224: this->shared_secret = chunk_empty;
! 225:
! 226: if (group == MODP_CUSTOM)
! 227: {
! 228: chunk_t g, p;
! 229:
! 230: VA_ARGS_GET(group, g, p);
! 231: if (!DH_set0_pqg(this->dh, BN_bin2bn(p.ptr, p.len, NULL), NULL,
! 232: BN_bin2bn(g.ptr, g.len, NULL)))
! 233: {
! 234: destroy(this);
! 235: return NULL;
! 236: }
! 237: }
! 238: else
! 239: {
! 240: /* find a modulus according to group */
! 241: if (set_modulus(this) != SUCCESS)
! 242: {
! 243: destroy(this);
! 244: return NULL;
! 245: }
! 246: }
! 247:
! 248: /* generate my public and private values */
! 249: if (!DH_generate_key(this->dh))
! 250: {
! 251: destroy(this);
! 252: return NULL;
! 253: }
! 254: DH_get0_key(this->dh, NULL, &privkey);
! 255: DBG2(DBG_LIB, "size of DH secret exponent: %d bits", BN_num_bits(privkey));
! 256: return &this->public;
! 257: }
! 258:
! 259: #endif /* OPENSSL_NO_DH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>