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_generate_key(DH *); 22int DH_compute_key(unsigned char *, const BIGNUM *, DH *); 23DH *DHparams_dup(DH *); 24 25/* added in 1.1.0 when the DH struct was opaqued */ 26void DH_get0_pqg(const DH *, const BIGNUM **, const BIGNUM **, 27 const BIGNUM **); 28int DH_set0_pqg(DH *, BIGNUM *, BIGNUM *, BIGNUM *); 29void DH_get0_key(const DH *, const BIGNUM **, const BIGNUM **); 30int DH_set0_key(DH *, BIGNUM *, BIGNUM *); 31 32int Cryptography_DH_check(const DH *, int *); 33int DH_generate_parameters_ex(DH *, int, int, BN_GENCB *); 34DH *d2i_DHparams_bio(BIO *, DH **); 35int i2d_DHparams_bio(BIO *, DH *); 36DH *Cryptography_d2i_DHxparams_bio(BIO *bp, DH **x); 37int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x); 38""" 39 40CUSTOMIZATIONS = """ 41#if CRYPTOGRAPHY_IS_LIBRESSL 42#ifndef DH_CHECK_Q_NOT_PRIME 43#define DH_CHECK_Q_NOT_PRIME 0x10 44#endif 45 46#ifndef DH_CHECK_INVALID_Q_VALUE 47#define DH_CHECK_INVALID_Q_VALUE 0x20 48#endif 49 50#ifndef DH_CHECK_INVALID_J_VALUE 51#define DH_CHECK_INVALID_J_VALUE 0x40 52#endif 53 54/* DH_check implementation taken from OpenSSL 1.1.0pre6 */ 55 56/*- 57 * Check that p is a safe prime and 58 * if g is 2, 3 or 5, check that it is a suitable generator 59 * where 60 * for 2, p mod 24 == 11 61 * for 3, p mod 12 == 5 62 * for 5, p mod 10 == 3 or 7 63 * should hold. 64 */ 65 66int Cryptography_DH_check(const DH *dh, int *ret) 67{ 68 int ok = 0, r; 69 BN_CTX *ctx = NULL; 70 BN_ULONG l; 71 BIGNUM *t1 = NULL, *t2 = NULL; 72 73 *ret = 0; 74 ctx = BN_CTX_new(); 75 if (ctx == NULL) 76 goto err; 77 BN_CTX_start(ctx); 78 t1 = BN_CTX_get(ctx); 79 if (t1 == NULL) 80 goto err; 81 t2 = BN_CTX_get(ctx); 82 if (t2 == NULL) 83 goto err; 84 85 if (dh->q) { 86 if (BN_cmp(dh->g, BN_value_one()) <= 0) 87 *ret |= DH_NOT_SUITABLE_GENERATOR; 88 else if (BN_cmp(dh->g, dh->p) >= 0) 89 *ret |= DH_NOT_SUITABLE_GENERATOR; 90 else { 91 /* Check g^q == 1 mod p */ 92 if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) 93 goto err; 94 if (!BN_is_one(t1)) 95 *ret |= DH_NOT_SUITABLE_GENERATOR; 96 } 97 r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); 98 if (r < 0) 99 goto err; 100 if (!r) 101 *ret |= DH_CHECK_Q_NOT_PRIME; 102 /* Check p == 1 mod q i.e. q divides p - 1 */ 103 if (!BN_div(t1, t2, dh->p, dh->q, ctx)) 104 goto err; 105 if (!BN_is_one(t2)) 106 *ret |= DH_CHECK_INVALID_Q_VALUE; 107 if (dh->j && BN_cmp(dh->j, t1)) 108 *ret |= DH_CHECK_INVALID_J_VALUE; 109 110 } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { 111 l = BN_mod_word(dh->p, 24); 112 if (l == (BN_ULONG)-1) 113 goto err; 114 if (l != 11) 115 *ret |= DH_NOT_SUITABLE_GENERATOR; 116 } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { 117 l = BN_mod_word(dh->p, 10); 118 if (l == (BN_ULONG)-1) 119 goto err; 120 if ((l != 3) && (l != 7)) 121 *ret |= DH_NOT_SUITABLE_GENERATOR; 122 } else 123 *ret |= DH_UNABLE_TO_CHECK_GENERATOR; 124 125 r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); 126 if (r < 0) 127 goto err; 128 if (!r) 129 *ret |= DH_CHECK_P_NOT_PRIME; 130 else if (!dh->q) { 131 if (!BN_rshift1(t1, dh->p)) 132 goto err; 133 r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); 134 if (r < 0) 135 goto err; 136 if (!r) 137 *ret |= DH_CHECK_P_NOT_SAFE_PRIME; 138 } 139 ok = 1; 140 err: 141 if (ctx != NULL) { 142 BN_CTX_end(ctx); 143 BN_CTX_free(ctx); 144 } 145 return (ok); 146} 147#else 148int Cryptography_DH_check(const DH *dh, int *ret) { 149 return DH_check(dh, ret); 150} 151#endif 152 153/* These functions were added in OpenSSL 1.1.0f commit d0c50e80a8 */ 154/* Define our own to simplify support across all versions. */ 155#if defined(EVP_PKEY_DHX) && EVP_PKEY_DHX != -1 156DH *Cryptography_d2i_DHxparams_bio(BIO *bp, DH **x) { 157 return ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x); 158} 159int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x) { 160 return ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x); 161} 162#else 163DH *(*Cryptography_d2i_DHxparams_bio)(BIO *bp, DH **x) = NULL; 164int (*Cryptography_i2d_DHxparams_bio)(BIO *bp, DH *x) = NULL; 165#endif 166""" 167