static int DH_check_pub_key_rfc(const DH *dh, BN_CTX *ctx, int *ret) { BIGNUM *bn = NULL; int ok = 0; const BIGNUM *pub_key, *p, *q, *g; check((dh && ret), "Invalid arguments"); BN_CTX_start(ctx); DH_get0_key(dh, &pub_key, NULL); DH_get0_pqg(dh, &p, &q, &g); /* Verify that y lies within the interval [2,p-1]. */ if (!DH_check_pub_key(dh, pub_key, ret)) goto err; /* If the DH is conform to RFC 2631 it should have a non-NULL q. * Others (like the DHs generated from OpenSSL) might have a problem with * this check. */ if (q) { /* Compute y^q mod p. If the result == 1, the key is valid. */ bn = BN_CTX_get(ctx); if (!bn || !BN_mod_exp(bn, pub_key, q, p, ctx)) goto err; if (!BN_is_one(bn)) *ret |= DH_CHECK_PUBKEY_INVALID; } ok = 1; err: BN_CTX_end(ctx); return ok; }
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); }
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) { BN_CTX *ctx=NULL; 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(); 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_EXP_CONSTTIME); } if (!mont) goto err; } if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) { DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY); goto err; } if (!dh->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); err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return(ret); }
int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) { BN_CTX *ctx = NULL; BIGNUM *shared_key; int ret = -1; int check_result; if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); shared_key = BN_CTX_get(ctx); if (shared_key == NULL) { goto err; } if (dh->priv_key == NULL) { OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE); goto err; } if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, dh->p, ctx)) { goto err; } if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) { OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); goto err; } if (!BN_mod_exp_mont_consttime(shared_key, peers_key, dh->priv_key, dh->p, ctx, dh->method_mont_p)) { OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); goto err; } ret = BN_bn2bin(shared_key, out); err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ret; }