/* Implements the default Dh_method provided by OpenSSL, enabling the generation of a DH public key based on key parameters, and generating a shared key based on the DH public key (one party) and the DH private key (the other) for key exchange */#include <stdio.h># Include "Cryptlib.h" #include <openssl/bn.h> #include <openssl/rand.h>//implement pseudo-random number generation, support user-defined random number generation # include <openssl/dh.h>static int Generate_key (DH *dh); static int Compute_key (unsigned char *key, const bignum *pub_key, DH * DH); static int dh_bn_mod_exp (const DH *DH, Bignum *r, const bignum *a, const bignum *p, const BI Gnum *m, Bn_ctx *ctx, Bn_mont_ctx *m_ctx); R=a^p% mstatic int dh_init (DH *dh), static int dh_finish (DH *dh), int dh_generate_key (DH *dh)//Generate Public private key {#ifdef OPENSSL _fips if (Fips_mode () &&! ( Dh->meth->flags & Dh_flag_fips_method) &&! (Dh->flags & Dh_flag_non_fips_allow)) {Dherr (Dh_f_dh_generate_key, Dh_r_non_fips_method); return 0; } #endif return Dh->meth->generate_key (DH); Generates a public private key, stored in the Public private key attribute of the DH struct}//the function int dh_compute_key (unsigned ch) based on the other public key and the own DH key to generate the shared keyAr *key, const bignum *pub_key, DH *dh) {#ifdef openssl_fips if (Fips_mode () &&! ( Dh->meth->flags & Dh_flag_fips_method) &&! (Dh->flags & Dh_flag_non_fips_allow)) {Dherr (Dh_f_dh_compute_key, Dh_r_non_fips_method); return 0; } #endif return Dh->meth->compute_key (Key, Pub_key, DH); The results are saved in key}int dh_compute_key_padded (unsigned char *key, const bignum *pub_key, DH *dh) {int RV, pad; RV = Dh->meth->compute_key (key, Pub_key, DH); if (RV <= 0) return RV; Pad = bn_num_bytes (dh->p)-RV; Returns the number of bytes of dh->p if (Pad > 0) {memmove (key + pad, key, RV); memset (key, 0, pad); } return RV + pad;} Static Dh_method Dh_ossl = {"OpenSSL DH METHOD", Generate_key, Compute_key, Dh_bn_mod_exp, Dh_init, Dh_ Finish, 0, NULL, null};const dh_method *dh_openssl (void) {return &dh_ossl;} The static int Generate_key (DH *dh)//is called by Dh_generate_key, where the specific implementation of {int OK = 0; int generate_new_key = 0; unsigned l; Bn_ctx *ctx; New context structure Bn_mont_ctx *mont = NULL; Bignum *pub_key = null, *priv_key = NULL; CTX = Bn_ctx_new (); if (CTX = = NULL) goto err; if (Dh->priv_key = = NULL) {Priv_key = Bn_new (); Gets the private key if (Priv_key = = NULL) goto err; Generate_new_key = 1; } Else Priv_key = dh->priv_key; if (Dh->pub_key = = NULL) {Pub_key = Bn_new (); Gets the public key, temporarily if (Pub_key = = NULL) goto err; } Else Pub_key = dh->pub_key; if (Dh->flags & dh_flag_cache_mont_p) {MONT = bn_mont_ctx_set_locked (&dh->method_mont_p, CRYPTO_LOCK_DH, Dh->p, CTX); if (!mont) goto err; if (Generate_new_key) {if (dh->q) {do {if (!bn_rand_range (Priv_key, dh->q)) ensure priv_key<dh->q goto err; } while(Bn_is_zero (priv_key) | | Bn_is_one (Priv_key)); } else {/* secret exponent length */L = dh->length? Dh->length:bn_num_bits (Dh->p)-1; if (!bn_rand (Priv_key, l, 0, 0)) goto err; }} {Bignum LOCAL_PRK; Bignum *PRK; if ((Dh->flags & dh_flag_no_exp_consttime) = = 0) {bn_init (&LOCAL_PRK); PRK = &local_prk; Bn_with_flags (PRK, Priv_key, bn_flg_consttime); } else PRK = Priv_key; Really generate public key if (!dh->meth->bn_mod_exp (DH, Pub_key, Dh->g, PRK, Dh->p, CTX, Mont)) Goto err; } Dh->pub_key = Pub_key; The public private key is assigned to the DH structure dh->priv_key = Priv_key; OK = 1; Err:if (ok! = 1) dherr (Dh_f_generate_key, err_r_bn_lib); if (Pub_key! = null) && (Dh->pub_key = = null)) Bn_free (Pub_key); if (Priv_key! = null) && (Dh->priv_key = = null)) Bn_free (prIv_key); Bn_ctx_free (CTX); return (OK);} Called by Dh_compute_key, here the concrete implementation of the static int compute_key (unsigned char *key, const bignum *pub_key, DH *dh) {Bn_ctx *ctx = NU LL; Bn_mont_ctx *mont = NULL; Bignum *tmp; int ret =-1; int Check_result; if (Bn_num_bits (dh->p) > Openssl_dh_max_modulus_bits) {dherr (Dh_f_compute_key, Dh_r_modulus_too_large); Goto err; } CTX = Bn_ctx_new (); New context Structure if (CTX = = NULL) goto err; Bn_ctx_start (CTX); TMP = Bn_ctx_get (CTX); if (Dh->priv_key = = NULL) {dherr (Dh_f_compute_key, Dh_r_no_private_value); Goto err; } if (Dh->flags & dh_flag_cache_mont_p) {MONT = bn_mont_ctx_set_locked (&dh->method_mont_p, CRYPTO_LOCK_DH, Dh->p, CTX); if ((Dh->flags & dh_flag_no_exp_consttime) = = 0) {/* XXX */bn_set_flags (Dh->priv_key, BN _flg_consttime); } if (!mont) gotoErr } if (! Dh_check_pub_key (DH, Pub_key, &check_result) | | Check_result) {//Check public key rationality Dherr (Dh_f_compute_key, Dh_r_invalid_pubkey); Goto err; } if (!dh->//tep=pub_key ^ Dh->priv_key% dh->p,tmp is key meth->bn_mod_exp (DH, tmp, Pub_key, Dh->priv_key, Dh->p, CTX, Mont)) {Dherr (Dh_f_compute_key, err_r_bn_lib); Goto err; } ret = Bn_bn2bin (TMP, key); Convert to byte storage: big-endian, deposit key in Err:if (CTX! = NULL) {bn_ctx_end (CTX); Bn_ctx_free (CTX); } return (ret);} static int dh_bn_mod_exp (const DH *DH, Bignum *r, const bignum *a, const bignum *p, Const Bignum *m, Bn_ctx *ctx, Bn_mont_ctx *m_ctx) {/* * If A is only one word long and constant time is F Alse, use the faster * exponenentiation function. */if (a->top = = 1 && ((Dh->flags & dh_flag_no_exp_consttime)! = 0)) {Bn_ulong a = a->d[0] ; Return BN_MOD_EXP_mont_word (R, A, p, M, CTX, M_ctx); } else return Bn_mod_exp_mont (R, a, p, M, CTX, m_ctx);} static int dh_init (DH *dh)//initialization function {dh->flags |= dh_flag_cache_mont_p; return (1);} static int dh_finish (DH *dh)//End Function {if (dh->method_mont_p) Bn_mont_ctx_free (dh->method_mont_p); return (1);}
OpenSSL open source program DH algorithm parsing dh_key.c