• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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