x4s_buf x4_dh_shared(const uint8 * g, size_t glen, const uint8 * p, size_t plen, const uint8 * x, size_t xlen, const uint8 * gx, size_t gxlen, const uint8 * gy, size_t gylen) { DH * dh; BIGNUM * bn; x4s_buf gxy = { 0 }; /* */ x4_assert(gx && gxlen && gy && gylen); /* */ dh = _dh_init(g,glen, p,plen, x,xlen); x4_assert(dh); dh->pub_key = BN_bin2bn(gx, gxlen, 0); x4_assert(dh->pub_key); bn = BN_bin2bn(gy, gylen, 0); x4_assert(bn); x4_buf_resize(&gxy, DH_size(dh)); DH_compute_key(gxy.data, bn, dh); DH_free(dh); return gxy; }
bool tr_dh_make_key (tr_dh_ctx_t raw_handle, size_t private_key_length, uint8_t * public_key, size_t * public_key_length) { DH * handle = raw_handle; int dh_size, my_public_key_length; const BIGNUM * hand_pub_key; assert (handle != NULL); assert (public_key != NULL); DH_set_length(handle, private_key_length * 8); if (!check_result (DH_generate_key (handle))) return false; DH_get0_key (handle, &hand_pub_key, NULL); my_public_key_length = BN_bn2bin (hand_pub_key, public_key); dh_size = DH_size (handle); tr_dh_align_key (public_key, my_public_key_length, dh_size); if (public_key_length != NULL) *public_key_length = dh_size; return true; }
void tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, const char *dh_file_inline ) { DH *dh; BIO *bio; ASSERT(NULL != ctx); if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_file_inline) { if (!(bio = BIO_new_mem_buf ((char *)dh_file_inline, -1))) msg (M_SSLDHERR, "Cannot open memory BIO for inline DH parameters"); } else { /* Get Diffie Hellman Parameters */ if (!(bio = BIO_new_file (dh_file, "r"))) msg (M_SSLDHERR, "Cannot open %s for DH parameters", dh_file); } dh = PEM_read_bio_DHparams (bio, NULL, NULL, NULL); BIO_free (bio); if (!dh) msg (M_SSLDHERR, "Cannot load DH parameters from %s", dh_file); if (!SSL_CTX_set_tmp_dh (ctx->ctx, dh)) msg (M_SSLDHERR, "SSL_CTX_set_tmp_dh"); msg (D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key", 8 * DH_size (dh)); DH_free (dh); }
static isc_result_t openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv, isc_buffer_t *secret) { DH *dhpub, *dhpriv; int ret; isc_region_t r; unsigned int len; REQUIRE(pub->keydata.dh != NULL); REQUIRE(priv->keydata.dh != NULL); dhpub = pub->keydata.dh; dhpriv = priv->keydata.dh; len = DH_size(dhpriv); isc_buffer_availableregion(secret, &r); if (r.length < len) return (ISC_R_NOSPACE); ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv); if (ret == 0) return (dst__openssl_toresult2("DH_compute_key", DST_R_COMPUTESECRETFAILURE)); isc_buffer_add(secret, len); return (ISC_R_SUCCESS); }
static int init_dh(SSL_CTX *ctx, const char *cert) { DH *dh; BIO *bio; assert(cert); bio = BIO_new_file(cert, "r"); if (!bio) { ERR_print_errors_fp(stderr); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dh) { ERR("{core} Note: no DH parameters found in %s\n", cert); return -1; } LOG("{core} Using DH parameters from %s\n", cert); SSL_CTX_set_tmp_dh(ctx, dh); LOG("{core} DH initialized with %d bit key\n", 8*DH_size(dh)); DH_free(dh); return 0; }
ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ BIGNUM *other_pub_key = NULL, *dh_p = NULL, *dh_g = NULL; DH *dh_priv = DH_new(); /* Check the arguments and get my private key (dh_priv), the peer's public key (other_pub_key), the parameters p & q */ { BIGNUM *dummy_pub_key = NULL, *priv_key = NULL; ERL_NIF_TERM head, tail; if (!get_bn_from_bin(env, argv[0], &other_pub_key) || !get_bn_from_bin(env, argv[1], &priv_key) || !enif_get_list_cell(env, argv[2], &head, &tail) || !get_bn_from_bin(env, head, &dh_p) || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_bin(env, head, &dh_g) || !enif_is_empty_list(env, tail) /* Note: DH_set0_key() does not allow setting only the * private key, although DH_compute_key() does not use the * public key. Work around this limitation by setting * the public key to a copy of the private key. */ || !(dummy_pub_key = BN_dup(priv_key)) || !DH_set0_key(dh_priv, dummy_pub_key, priv_key) || !DH_set0_pqg(dh_priv, dh_p, NULL, dh_g) ) { if (dh_p) BN_free(dh_p); if (dh_g) BN_free(dh_g); if (other_pub_key) BN_free(other_pub_key); if (dummy_pub_key) BN_free(dummy_pub_key); if (priv_key) BN_free(priv_key); return enif_make_badarg(env); } } { ErlNifBinary ret_bin; int size; enif_alloc_binary(DH_size(dh_priv), &ret_bin); size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv); BN_free(other_pub_key); DH_free(dh_priv); if (size<=0) { enif_release_binary(&ret_bin); return atom_error; } if (size != ret_bin.size) enif_realloc_binary(&ret_bin, size); return enif_make_binary(env, &ret_bin); } }
tr_dh_secret_t tr_dh_agree (tr_dh_ctx_t handle, const uint8_t * other_public_key, size_t other_public_key_length) { struct tr_dh_secret * ret; int dh_size, secret_key_length; BIGNUM * other_key; assert (handle != NULL); assert (other_public_key != NULL); if (!check_pointer (other_key = BN_bin2bn (other_public_key, other_public_key_length, NULL))) return NULL; dh_size = DH_size (handle); ret = tr_dh_secret_new (dh_size); secret_key_length = DH_compute_key (ret->key, other_key, handle); if (check_result_neq (secret_key_length, -1)) { tr_dh_secret_align (ret, secret_key_length); } else { tr_dh_secret_free (ret); ret = NULL; } BN_free (other_key); return ret; }
// Set the prime P and the generator, generate local public key DH_key_exchange::DH_key_exchange () { m_DH = DH_new (); m_DH->p = BN_bin2bn (m_dh_prime, sizeof(m_dh_prime), NULL); m_DH->g = BN_bin2bn (m_dh_generator, sizeof(m_dh_generator), NULL); assert (sizeof(m_dh_prime) == DH_size(m_DH)); DH_generate_key (m_DH); // TODO Check != 0 assert (m_DH->pub_key); // DH can generate key sizes that are smaller than the size of // P with exponentially decreasing probability, in which case // the msb's of m_dh_local_key need to be zeroed // appropriately. int key_size = get_local_key_size(); int len_dh = sizeof(m_dh_prime); // must equal DH_size(m_DH) if (key_size != len_dh) { assert(key_size > 0 && key_size < len_dh); int pad_zero_size = len_dh - key_size; std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0); BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size); } else BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key); // TODO Check return value }
struct sec performDH(char *pubkeyRec,DH *privkey){ struct sec s; int secret_size; /* Send the public key to the peer. * How this occurs will be specific to your situation (see main text below) */ /* Receive the public key from the peer. In this example we're just hard coding a value */ BIGNUM *pubkey = NULL; if(0 == (BN_dec2bn(&pubkey, pubkeyRec))) handleErrors(); /* Compute the shared secret */ unsigned char *secret; if(NULL == (secret = OPENSSL_malloc(sizeof(unsigned char) * (DH_size(privkey))))) handleErrors(); if(0 > (secret_size = DH_compute_key(secret, pubkey, privkey))) handleErrors(); /* Do something with the shared secret */ /* Note secret_size may be less than DH_size(privkey) */ printf("The shared secret is:\n"); strcpy(s.value,secret); s.length=secret_size; /* Clean up */ OPENSSL_free(secret); BN_free(pubkey); DH_free(privkey); return s; }
void openssl_dh_crypt() { BIO *b; DH *d1, *d2; int i, len1, len2; unsigned char skey1[COMM_LEN], skey2[COMM_LEN]; d1 = DH_new(); d2 = DH_new(); DH_generate_parameters_ex(d1, 64, DH_GENERATOR_2, NULL); DH_check(d1, &i); printf("\nDH key size: %d\n", DH_size(d1)); DH_generate_key(d1); d2->p = BN_dup(d1->p); d2->g = BN_dup(d1->g); DH_generate_key(d2); DH_check_pub_key(d1, d1->pub_key, &i); len1 = DH_compute_key(skey1, d2->pub_key, d1); len2 = DH_compute_key(skey2, d1->pub_key, d2); if ((len1 != len2) || (memcmp(skey1, skey2, len1) != 0)) { printf("DH_compute_key err!\n"); DH_free(d1); DH_free(d2); return; } b = BIO_new(BIO_s_file()); BIO_set_fp(b, stdout, BIO_NOCLOSE); DHparams_print(b, d1); BIO_free(b); DH_free(d1); DH_free(d2); }
bool DHWrapper::CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length) { if (_pDH == NULL) { FATAL("DHWrapper not initialized"); return false; } if (_sharedKeyLength != 0 || _pSharedKey != NULL) { FATAL("Shared key already computed"); return false; } _sharedKeyLength = DH_size(_pDH); if (_sharedKeyLength <= 0 || _sharedKeyLength > 1024) { FATAL("Unable to get shared key size in bytes"); return false; } _pSharedKey = new uint8_t[_sharedKeyLength]; memset(_pSharedKey, 0, _sharedKeyLength); _peerPublickey = BN_bin2bn(pPeerPublicKey, length, 0); if (_peerPublickey == NULL) { FATAL("Unable to get the peer public key"); return false; } if (DH_compute_key(_pSharedKey, _peerPublickey, _pDH) == -1) { FATAL("Unable to compute the shared key"); return false; } return true; }
const uint8_t* tr_cryptoComputeSecret( tr_crypto * crypto, const uint8_t * peerPublicKey ) { int len; uint8_t secret[KEY_LEN]; BIGNUM * bn = BN_bin2bn( peerPublicKey, KEY_LEN, NULL ); DH * dh; ensureKeyExists( crypto ); dh = crypto->dh; assert( DH_size( dh ) == KEY_LEN ); len = DH_compute_key( secret, bn, dh ); if( len == -1 ) logErrorFromSSL( ); else { int offset; assert( len <= KEY_LEN ); offset = KEY_LEN - len; memset( crypto->mySecret, 0, offset ); memcpy( crypto->mySecret + offset, secret, len ); crypto->mySecretIsSet = 1; } BN_free( bn ); return crypto->mySecret; }
int tr_compute_dh_key(unsigned char **pbuf, BIGNUM *pub_key, DH *priv_dh) { size_t buflen; unsigned char *buf = NULL;; int rc = 0; if ((!pbuf) || (!pub_key) || (!priv_dh)) { tr_debug("tr_compute_dh_key: Invalid parameters."); return(-1); } *pbuf = NULL; buflen = DH_size(priv_dh); buf = malloc(buflen); if (buf == NULL) { tr_crit("tr_compute_dh_key: out of memory"); return -1; } rc = DH_compute_key(buf, pub_key, priv_dh); if (0 <= rc) { *pbuf = buf; }else { free(buf); } return rc; }
std::string avjackif::async_client_hello(boost::asio::yield_context yield_context) { proto::client_hello client_hello; client_hello.set_client("avim"); client_hello.set_version(0001); unsigned char to[512]; auto dh = DH_new(); DH_generate_parameters_ex(dh,64,DH_GENERATOR_5,NULL); DH_generate_key(dh); // 把 g,p, pubkey 传过去 client_hello.set_random_g((const void*)to, BN_bn2bin(dh->g, to)); client_hello.set_random_p((const void*)to, BN_bn2bin(dh->p, to)); client_hello.set_random_pub_key((const void*)to, BN_bn2bin(dh->pub_key, to)); auto tobesend = av_router::encode(client_hello); boost::asio::async_write(*m_sock, boost::asio::buffer(tobesend), yield_context); // 解码 std::unique_ptr<proto::server_hello> server_hello( (proto::server_hello*)async_read_protobuf_message(*m_sock, yield_context)); m_remote_addr.reset(new proto::av_address( av_address_from_string(server_hello->server_av_address()))); auto server_pubkey = BN_bin2bn((const unsigned char *) server_hello->random_pub_key().data(), server_hello->random_pub_key().length(), NULL); m_shared_key.resize(DH_size(dh)); // 密钥就算出来啦! DH_compute_key(&m_shared_key[0], server_pubkey, dh); BN_free(server_pubkey); std::printf("key = 0x"); for (int i=0; i<DH_size(dh); ++i) { std::printf("%x%x", (m_shared_key[i] >> 4) & 0xf, m_shared_key[i] & 0xf); } std::printf("\n"); DH_free(dh); return server_hello->random_pub_key(); }
static krb5_error_code generate_dh_keyblock(krb5_context context, pk_client_params *client_params, krb5_enctype enctype, krb5_keyblock *reply_key) { unsigned char *dh_gen_key = NULL; krb5_keyblock key; krb5_error_code ret; size_t dh_gen_keylen, size; memset(&key, 0, sizeof(key)); if (!DH_generate_key(client_params->dh)) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Can't generate Diffie-Hellman keys"); goto out; } if (client_params->dh_public_key == NULL) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "dh_public_key"); goto out; } dh_gen_keylen = DH_size(client_params->dh); size = BN_num_bytes(client_params->dh->p); if (size < dh_gen_keylen) size = dh_gen_keylen; dh_gen_key = malloc(size); if (dh_gen_key == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } memset(dh_gen_key, 0, size - dh_gen_keylen); dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen), client_params->dh_public_key, client_params->dh); if (dh_gen_keylen == -1) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Can't compute Diffie-Hellman key"); goto out; } ret = _krb5_pk_octetstring2key(context, enctype, dh_gen_key, dh_gen_keylen, NULL, NULL, reply_key); out: if (dh_gen_key) free(dh_gen_key); if (key.keyvalue.data) krb5_free_keyblock_contents(context, &key); return ret; }
/* * Generate an empheral DH key. Because this can take a long * time to compute, we can use precomputed parameters of the * common key sizes. * * Since few sites will bother to precompute these parameter * files, we also provide a fallback to the parameters provided * by the OpenSSL project. * * These values can be static (once loaded or computed) since * the OpenSSL library can efficiently generate random keys from * the information provided. */ static DH * tmp_dh_cb(SSL *s, int is_export, int keylength) { DH *r = NULL; static DH *dh = NULL; static DH *dh512 = NULL; static DH *dh1024 = NULL; static DH *dh2048 = NULL; static DH *dh4096 = NULL; switch (keylength) { case 512: if (dh512 == NULL) dh512 = load_dh_file(keylength); if (dh512 == NULL) dh512 = load_dh_buffer(file_dh512, sizeof file_dh512); r = dh512; break; case 1024: if (dh1024 == NULL) dh1024 = load_dh_file(keylength); if (dh1024 == NULL) dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024); r = dh1024; break; case 2048: if (dh2048 == NULL) dh2048 = load_dh_file(keylength); if (dh2048 == NULL) dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048); r = dh2048; break; case 4096: if (dh4096 == NULL) dh4096 = load_dh_file(keylength); if (dh4096 == NULL) dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096); r = dh4096; break; default: if (dh == NULL) dh = load_dh_file(keylength); r = dh; } /* this may take a long time, but it may be necessary... */ if (r == NULL || 8 * DH_size(r) < keylength) r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL); return r; }
ssize_t tls_get_connection_info(struct tls *ctx, char *buf, size_t buflen) { SSL *conn = ctx->ssl_conn; const char *ocsp_pfx = "", *ocsp_info = ""; const char *proto = "-", *cipher = "-"; char dh[64]; int used_dh_bits = ctx->used_dh_bits, used_ecdh_nid = ctx->used_ecdh_nid; if (conn != NULL) { proto = SSL_get_version(conn); cipher = SSL_get_cipher(conn); #ifdef SSL_get_server_tmp_key if (ctx->flags & TLS_CLIENT) { EVP_PKEY *pk = NULL; int ok = SSL_get_server_tmp_key(conn, &pk); int pk_type = EVP_PKEY_id(pk); if (ok && pk) { if (pk_type == EVP_PKEY_DH) { DH *dh = EVP_PKEY_get0(pk); used_dh_bits = DH_size(dh) * 8; } else if (pk_type == EVP_PKEY_EC) { EC_KEY *ecdh = EVP_PKEY_get0(pk); const EC_GROUP *eg = EC_KEY_get0_group(ecdh); used_ecdh_nid = EC_GROUP_get_curve_name(eg); } EVP_PKEY_free(pk); } } #endif } if (used_dh_bits) { snprintf(dh, sizeof dh, "/DH=%d", used_dh_bits); } else if (used_ecdh_nid) { snprintf(dh, sizeof dh, "/ECDH=%s", OBJ_nid2sn(used_ecdh_nid)); } else { dh[0] = 0; } if (ctx->ocsp_result) { ocsp_info = ctx->ocsp_result; ocsp_pfx = "/OCSP="; } return snprintf(buf, buflen, "%s/%s%s%s%s", proto, cipher, dh, ocsp_pfx, ocsp_info); }
NOEXPORT int init_dh(SERVICE_OPTIONS *section) { DH *dh=NULL; s_log(LOG_DEBUG, "DH initialization"); #ifdef HAVE_OSSL_ENGINE_H if(!section->engine) /* cert is a file and not an identifier */ #endif dh=read_dh(section->cert); if(!dh) dh=get_dh2048(); if(!dh) { s_log(LOG_NOTICE, "DH initialization failed"); return 1; /* FAILED */ } SSL_CTX_set_tmp_dh(section->ctx, dh); s_log(LOG_DEBUG, "DH initialized with %d-bit key", 8*DH_size(dh)); DH_free(dh); return 0; /* OK */ }
int s2n_dh_compute_shared_secret_as_client(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *Yc_out, struct s2n_blob *shared_key) { struct s2n_dh_params client_params; uint8_t *client_pub_key; uint16_t client_pub_key_size; int shared_key_size; GUARD(s2n_dh_params_check(server_dh_params)); GUARD(s2n_dh_params_copy(server_dh_params, &client_params)); GUARD(s2n_dh_generate_ephemeral_key(&client_params)); GUARD(s2n_alloc(shared_key, DH_size(server_dh_params->dh))); const BIGNUM *client_pub_key_bn = s2n_get_Ys_dh_param(&client_params); client_pub_key_size = BN_num_bytes(client_pub_key_bn); GUARD(s2n_stuffer_write_uint16(Yc_out, client_pub_key_size)); client_pub_key = s2n_stuffer_raw_write(Yc_out, client_pub_key_size); if (client_pub_key == NULL) { GUARD(s2n_free(shared_key)); GUARD(s2n_dh_params_free(&client_params)); S2N_ERROR(S2N_ERR_DH_WRITING_PUBLIC_KEY); } if (BN_bn2bin(client_pub_key_bn, client_pub_key) != client_pub_key_size) { GUARD(s2n_free(shared_key)); GUARD(s2n_dh_params_free(&client_params)); S2N_ERROR(S2N_ERR_DH_COPYING_PUBLIC_KEY); } /* server_dh_params already validated */ const BIGNUM *server_pub_key_bn = s2n_get_Ys_dh_param(server_dh_params); shared_key_size = DH_compute_key(shared_key->data, server_pub_key_bn, client_params.dh); if (shared_key_size < 0) { GUARD(s2n_free(shared_key)); GUARD(s2n_dh_params_free(&client_params)); S2N_ERROR(S2N_ERR_DH_SHARED_SECRET); } shared_key->size = shared_key_size; GUARD(s2n_dh_params_free(&client_params)); return 0; }
static int init_dh(SSL_CTX * ctx, unsigned char *dhparam) { int rc = TRUE; BIO *bio = 0; DH *dh = 0; if (dhparam == NULL) return TRUE; if ((bio = BIO_new_file((char *) dhparam, "r")) == NULL) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"DH: could not read %s: %s", dhparam, strerror(errno)); rc = FALSE; } else { if ((dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"DH: could not load params from %s", dhparam); rc = FALSE; } else { if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) { LOG(SPOCP_DEBUG) traceLog(LOG_ERR, "Couldn't set Diffie-Hellman parameters"); rc = FALSE; } else LOG(SPOCP_DEBUG) traceLog(LOG_ERR, "Diffie-Hellman initialised from %s with %d-bit key", dhparam, 8 * DH_size(dh)); DH_free(dh); } BIO_free(bio); } return rc; }
bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) { // Check parameters if ((ppSymmetricKey == NULL) || (publicKey == NULL) || (privateKey == NULL)) { return false; } // Get keys DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); if (pub == NULL || pub->pub_key == NULL || priv == NULL) { ERROR_MSG("Failed to get OpenSSL DH keys"); return false; } // Derive the secret ByteString secret; secret.resize(DH_size(priv));; if (DH_compute_key(&secret[0], pub->pub_key, priv) <= 0) { ERROR_MSG("DH key derivation failed (0x%08X)", ERR_get_error()); return false; } *ppSymmetricKey = new SymmetricKey; if (*ppSymmetricKey == NULL) return false; if (!(*ppSymmetricKey)->setKeyBits(secret)) { delete *ppSymmetricKey; *ppSymmetricKey = NULL; return false; } return true; }
int Condor_Diffie_Hellman :: compute_shared_secret(const char * pk) { // the input pk is assumed to be an encoded string representing // the binary data for the remote party's public key -- y (or x) // the local DH knows about g and x, now, it will compute // (g^x)^y, or (g^y)^x BIGNUM * remote_pubKey = NULL; if (BN_hex2bn(&remote_pubKey, pk) == 0) { dprintf(D_ALWAYS, "Unable to obtain remote public key\n"); goto error; } if ((dh_ != NULL) && (remote_pubKey != NULL)) { secret_ = (unsigned char *) malloc(DH_size(dh_)); // Now compute keySize_ = DH_compute_key(secret_, remote_pubKey, dh_); BN_clear_free(remote_pubKey); if (keySize_ == -1) { dprintf(D_ALWAYS, "Unable to compute shared secret\n"); goto error; } } else { goto error; } return 1; error: if (remote_pubKey) { BN_clear_free(remote_pubKey); } if (secret_) { free(secret_); secret_ = NULL; } return 0; }
static void tls_info_callback(const SSL *ssl, int where, int rc) { struct tls *ctx = SSL_get_app_data(ssl); /* steal info about used DH key */ if (ssl->s3 && ssl->s3->tmp.dh && !ctx->used_dh_bits) { ctx->used_dh_bits = DH_size(ssl->s3->tmp.dh) * 8; } else if (ssl->s3 && ssl->s3->tmp.ecdh && !ctx->used_ecdh_nid) { ctx->used_ecdh_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ssl->s3->tmp.ecdh)); } /* detect renegotation on established connection */ if (where & SSL_CB_HANDSHAKE_START) { if (ctx->state & TLS_STATE_ESTABLISHED) ctx->state |= TLS_STATE_ABORT; } else if (where & SSL_CB_HANDSHAKE_DONE) { ctx->state |= TLS_STATE_ESTABLISHED; } }
static int init_dh(void) { #ifdef USE_DH FILE *fp; DH *dh; BIO *bio; fp=fopen(options.cert, "r"); if(!fp) { #ifdef USE_WIN32 /* Win32 doesn't seem to set errno in fopen() */ log(LOG_ERR, "Failed to open %s", options.cert); #else ioerror(options.cert); #endif return -1; /* FAILED */ } bio=BIO_new_fp(fp, BIO_CLOSE|BIO_FP_TEXT); if(!bio) { log(LOG_ERR, "BIO_new_fp failed"); return -1; /* FAILED */ } if((dh=PEM_read_bio_DHparams(bio, NULL, NULL #if SSLEAY_VERSION_NUMBER >= 0x00904000L , NULL #endif ))) { BIO_free(bio); log(LOG_DEBUG, "Using Diffie-Hellman parameters from %s", options.cert); } else { /* Failed to load DH parameters from file */ BIO_free(bio); log(LOG_NOTICE, "Could not load DH parameters from %s", options.cert); return -1; /* FAILED */ } SSL_CTX_set_tmp_dh(ctx, dh); log(LOG_INFO, "Diffie-Hellman initialized with %d bit key", 8*DH_size(dh)); DH_free(dh); #endif /* USE_DH */ return 0; /* OK */ }
BUF_MEM * dh_compute_key(EVP_PKEY *key, const BUF_MEM * in, BN_CTX *bn_ctx) { BUF_MEM * out = NULL; BIGNUM * bn = NULL; DH *dh = NULL; check(key && in, "Invalid arguments"); dh = EVP_PKEY_get1_DH(key); if (!dh) return NULL; /* decode public key */ bn = BN_bin2bn((unsigned char *) in->data, in->length, bn); if (!bn) goto err; out = BUF_MEM_create(DH_size(dh)); if (!out) goto err; out->length = DH_compute_key((unsigned char *) out->data, bn, dh); if ((int) out->length < 0) goto err; BN_clear_free(bn); DH_free(dh); return out; err: if (out) BUF_MEM_free(out); if (bn) BN_clear_free(bn); if (dh) DH_free(dh); return NULL; }
/* * Load precomputed DH parameters. * * To prevent "downgrade" attacks, we perform a number of checks * to verify that the DBA-generated DH parameters file contains * what we expect it to contain. */ static DH * load_dh_file(int keylength) { char homedir[MAXPGPATH]; char fnbuf[MAXPGPATH]; FILE *fp; DH *dh; int codes; if (!pqGetHomeDirectory(homedir, sizeof(homedir))) return NULL; /* attempt to open file. It's not an error if it doesn't exist. */ snprintf(fnbuf, sizeof(fnbuf), DHFILEPATTERN, homedir, keylength); if ((fp = fopen(fnbuf, "r")) == NULL) return NULL; /* flock(fileno(fp), LOCK_SH); */ dh = PEM_read_DHparams(fp, NULL, NULL, NULL); /* flock(fileno(fp), LOCK_UN); */ fclose(fp); /* is the prime the correct size? */ if (dh != NULL && 8 * DH_size(dh) < keylength) dh = NULL; /* make sure the DH parameters are usable */ if (dh != NULL) { if (DH_check(dh, &codes)) return NULL; if (codes & DH_CHECK_P_NOT_PRIME) return NULL; if ((codes & DH_NOT_SUITABLE_GENERATOR) && (codes & DH_CHECK_P_NOT_SAFE_PRIME)) return NULL; } return dh; }
/* * call-seq: * dh.compute_key(pub_bn) -> aString * * Returns a String containing a shared secret computed from the other party's public value. * See DH_compute_key() for further information. * * === Parameters * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by * DH#public_key as that contains the DH parameters only. */ static VALUE ossl_dh_compute_key(VALUE self, VALUE pub) { DH *dh; EVP_PKEY *pkey; BIGNUM *pub_key; VALUE str; int len; GetPKeyDH(self, pkey); dh = pkey->pkey.dh; pub_key = GetBNPtr(pub); len = DH_size(dh); str = rb_str_new(0, len); if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) { ossl_raise(eDHError, NULL); } rb_str_set_len(str, len); return str; }
/* * call-seq: * dh.compute_key(pub_bn) -> aString * * Returns a String containing a shared secret computed from the other party's public value. * See DH_compute_key() for further information. * * === Parameters * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by * DH#public_key as that contains the DH parameters only. */ static VALUE ossl_dh_compute_key(VALUE self, VALUE pub) { DH *dh; const BIGNUM *pub_key, *dh_p; VALUE str; int len; GetDH(self, dh); DH_get0_pqg(dh, &dh_p, NULL, NULL); if (!dh_p) ossl_raise(eDHError, "incomplete DH"); pub_key = GetBNPtr(pub); len = DH_size(dh); str = rb_str_new(0, len); if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) { ossl_raise(eDHError, NULL); } rb_str_set_len(str, len); return str; }
static void tls_info_callback(const SSL *ssl, int where, int rc) { struct tls *ctx = SSL_get_app_data(ssl); #ifdef USE_LIBSSL_INTERNALS if (!(ctx->state & TLS_HANDSHAKE_COMPLETE) && ssl->s3) { /* steal info about used DH key */ if (ssl->s3->tmp.dh && !ctx->used_dh_bits) { ctx->used_dh_bits = DH_size(ssl->s3->tmp.dh) * 8; } else if (ssl->s3->tmp.ecdh && !ctx->used_ecdh_nid) { ctx->used_ecdh_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ssl->s3->tmp.ecdh)); } } #endif /* detect renegotation on established connection */ if (where & SSL_CB_HANDSHAKE_START) { if (ctx->state & TLS_HANDSHAKE_COMPLETE) ctx->state |= TLS_DO_ABORT; } }
int s2n_pkcs3_to_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *pkcs3) { uint8_t *original_ptr = pkcs3->data; dh_params->dh = d2i_DHparams(NULL, (const unsigned char **)(void *)&pkcs3->data, pkcs3->size); GUARD(s2n_check_p_g_dh_params(dh_params)); if (pkcs3->data - original_ptr != pkcs3->size) { DH_free(dh_params->dh); S2N_ERROR(S2N_ERR_INVALID_PKCS3); } pkcs3->data = original_ptr; /* Require at least 2048 bits for the DH size */ if (DH_size(dh_params->dh) < S2N_MIN_DH_PRIME_SIZE_BYTES) { DH_free(dh_params->dh); S2N_ERROR(S2N_ERR_DH_TOO_SMALL); } /* Check the generator and prime */ GUARD(s2n_dh_params_check(dh_params)); return 0; }