1# This file is dual licensed under the terms of the Apache License, Version 2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 3# for complete details. 4 5from __future__ import absolute_import, division, print_function 6 7INCLUDES = """ 8#include <openssl/dh.h> 9""" 10 11TYPES = """ 12typedef ... DH; 13 14const long DH_NOT_SUITABLE_GENERATOR; 15""" 16 17FUNCTIONS = """ 18DH *DH_new(void); 19void DH_free(DH *); 20int DH_size(const DH *); 21int DH_check_pub_key(const DH *, const BIGNUM *, int *); 22int DH_generate_key(DH *); 23int DH_compute_key(unsigned char *, const BIGNUM *, DH *); 24int DH_set_ex_data(DH *, int, void *); 25void *DH_get_ex_data(DH *, int); 26DH *d2i_DHparams(DH **, const unsigned char **, long); 27int i2d_DHparams(const DH *, unsigned char **); 28int DHparams_print_fp(FILE *, const DH *); 29int DHparams_print(BIO *, const DH *); 30DH *DHparams_dup(DH *); 31 32/* added in 1.1.0 when the DH struct was opaqued */ 33void DH_get0_pqg(const DH *, const BIGNUM **, const BIGNUM **, 34 const BIGNUM **); 35int DH_set0_pqg(DH *, BIGNUM *, BIGNUM *, BIGNUM *); 36void DH_get0_key(const DH *, const BIGNUM **, const BIGNUM **); 37int DH_set0_key(DH *, BIGNUM *, BIGNUM *); 38 39int Cryptography_DH_check(const DH *, int *); 40int DH_generate_parameters_ex(DH *, int, int, BN_GENCB *); 41DH *d2i_DHparams_bio(BIO *, DH **); 42int i2d_DHparams_bio(BIO *, DH *); 43DH *Cryptography_d2i_DHxparams_bio(BIO *bp, DH **x); 44int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x); 45""" 46 47CUSTOMIZATIONS = """ 48/* These functions were added in OpenSSL 1.1.0 */ 49#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER 50void DH_get0_pqg(const DH *dh, 51 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) 52{ 53 if (p != NULL) 54 *p = dh->p; 55 if (q != NULL) 56 *q = dh->q; 57 if (g != NULL) 58 *g = dh->g; 59} 60 61int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) 62{ 63 /* If the fields p and g in d are NULL, the corresponding input 64 * parameters MUST be non-NULL. q may remain NULL. 65 */ 66 if ((dh->p == NULL && p == NULL) 67 || (dh->g == NULL && g == NULL)) 68 return 0; 69 70 if (p != NULL) { 71 BN_free(dh->p); 72 dh->p = p; 73 } 74 if (q != NULL) { 75 BN_free(dh->q); 76 dh->q = q; 77 } 78 if (g != NULL) { 79 BN_free(dh->g); 80 dh->g = g; 81 } 82 83 if (q != NULL) { 84 dh->length = BN_num_bits(q); 85 } 86 87 return 1; 88} 89 90void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) 91{ 92 if (pub_key != NULL) 93 *pub_key = dh->pub_key; 94 if (priv_key != NULL) 95 *priv_key = dh->priv_key; 96} 97 98int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) 99{ 100 /* If the field pub_key in dh is NULL, the corresponding input 101 * parameters MUST be non-NULL. The priv_key field may 102 * be left NULL. 103 */ 104 if (dh->pub_key == NULL && pub_key == NULL) 105 return 0; 106 107 if (pub_key != NULL) { 108 BN_free(dh->pub_key); 109 dh->pub_key = pub_key; 110 } 111 if (priv_key != NULL) { 112 BN_free(dh->priv_key); 113 dh->priv_key = priv_key; 114 } 115 116 return 1; 117} 118#endif 119 120#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 121#ifndef DH_CHECK_Q_NOT_PRIME 122#define DH_CHECK_Q_NOT_PRIME 0x10 123#endif 124 125#ifndef DH_CHECK_INVALID_Q_VALUE 126#define DH_CHECK_INVALID_Q_VALUE 0x20 127#endif 128 129#ifndef DH_CHECK_INVALID_J_VALUE 130#define DH_CHECK_INVALID_J_VALUE 0x40 131#endif 132 133/* DH_check implementation taken from OpenSSL 1.1.0pre6 */ 134 135/*- 136 * Check that p is a safe prime and 137 * if g is 2, 3 or 5, check that it is a suitable generator 138 * where 139 * for 2, p mod 24 == 11 140 * for 3, p mod 12 == 5 141 * for 5, p mod 10 == 3 or 7 142 * should hold. 143 */ 144 145int Cryptography_DH_check(const DH *dh, int *ret) 146{ 147 int ok = 0, r; 148 BN_CTX *ctx = NULL; 149 BN_ULONG l; 150 BIGNUM *t1 = NULL, *t2 = NULL; 151 152 *ret = 0; 153 ctx = BN_CTX_new(); 154 if (ctx == NULL) 155 goto err; 156 BN_CTX_start(ctx); 157 t1 = BN_CTX_get(ctx); 158 if (t1 == NULL) 159 goto err; 160 t2 = BN_CTX_get(ctx); 161 if (t2 == NULL) 162 goto err; 163 164 if (dh->q) { 165 if (BN_cmp(dh->g, BN_value_one()) <= 0) 166 *ret |= DH_NOT_SUITABLE_GENERATOR; 167 else if (BN_cmp(dh->g, dh->p) >= 0) 168 *ret |= DH_NOT_SUITABLE_GENERATOR; 169 else { 170 /* Check g^q == 1 mod p */ 171 if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) 172 goto err; 173 if (!BN_is_one(t1)) 174 *ret |= DH_NOT_SUITABLE_GENERATOR; 175 } 176 r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); 177 if (r < 0) 178 goto err; 179 if (!r) 180 *ret |= DH_CHECK_Q_NOT_PRIME; 181 /* Check p == 1 mod q i.e. q divides p - 1 */ 182 if (!BN_div(t1, t2, dh->p, dh->q, ctx)) 183 goto err; 184 if (!BN_is_one(t2)) 185 *ret |= DH_CHECK_INVALID_Q_VALUE; 186 if (dh->j && BN_cmp(dh->j, t1)) 187 *ret |= DH_CHECK_INVALID_J_VALUE; 188 189 } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { 190 l = BN_mod_word(dh->p, 24); 191 if (l == (BN_ULONG)-1) 192 goto err; 193 if (l != 11) 194 *ret |= DH_NOT_SUITABLE_GENERATOR; 195 } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { 196 l = BN_mod_word(dh->p, 10); 197 if (l == (BN_ULONG)-1) 198 goto err; 199 if ((l != 3) && (l != 7)) 200 *ret |= DH_NOT_SUITABLE_GENERATOR; 201 } else 202 *ret |= DH_UNABLE_TO_CHECK_GENERATOR; 203 204 r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); 205 if (r < 0) 206 goto err; 207 if (!r) 208 *ret |= DH_CHECK_P_NOT_PRIME; 209 else if (!dh->q) { 210 if (!BN_rshift1(t1, dh->p)) 211 goto err; 212 r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); 213 if (r < 0) 214 goto err; 215 if (!r) 216 *ret |= DH_CHECK_P_NOT_SAFE_PRIME; 217 } 218 ok = 1; 219 err: 220 if (ctx != NULL) { 221 BN_CTX_end(ctx); 222 BN_CTX_free(ctx); 223 } 224 return (ok); 225} 226#else 227int Cryptography_DH_check(const DH *dh, int *ret) { 228 return DH_check(dh, ret); 229} 230#endif 231 232/* These functions were added in OpenSSL 1.1.0f commit d0c50e80a8 */ 233/* Define our own to simplify support across all versions. */ 234#if defined(EVP_PKEY_DHX) && EVP_PKEY_DHX != -1 235DH *Cryptography_d2i_DHxparams_bio(BIO *bp, DH **x) { 236 return ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x); 237} 238int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x) { 239 return ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x); 240} 241#else 242DH *(*Cryptography_d2i_DHxparams_bio)(BIO *bp, DH **x) = NULL; 243int (*Cryptography_i2d_DHxparams_bio)(BIO *bp, DH *x) = NULL; 244#endif 245""" 246