2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include "internal/cryptlib.h"
12 #include <openssl/bn.h>
16 * Check that p is a safe prime and
17 * if g is 2, 3 or 5, check that it is a suitable generator
19 * for 2, p mod 24 == 11
20 * for 3, p mod 12 == 5
21 * for 5, p mod 10 == 3 or 7
25 int DH_check(const DH
*dh
, int *ret
)
30 BIGNUM
*t1
= NULL
, *t2
= NULL
;
45 if (BN_cmp(dh
->g
, BN_value_one()) <= 0)
46 *ret
|= DH_NOT_SUITABLE_GENERATOR
;
47 else if (BN_cmp(dh
->g
, dh
->p
) >= 0)
48 *ret
|= DH_NOT_SUITABLE_GENERATOR
;
50 /* Check g^q == 1 mod p */
51 if (!BN_mod_exp(t1
, dh
->g
, dh
->q
, dh
->p
, ctx
))
54 *ret
|= DH_NOT_SUITABLE_GENERATOR
;
56 if (!BN_is_prime_ex(dh
->q
, BN_prime_checks
, ctx
, NULL
))
57 *ret
|= DH_CHECK_Q_NOT_PRIME
;
58 /* Check p == 1 mod q i.e. q divides p - 1 */
59 if (!BN_div(t1
, t2
, dh
->p
, dh
->q
, ctx
))
62 *ret
|= DH_CHECK_INVALID_Q_VALUE
;
63 if (dh
->j
&& BN_cmp(dh
->j
, t1
))
64 *ret
|= DH_CHECK_INVALID_J_VALUE
;
66 } else if (BN_is_word(dh
->g
, DH_GENERATOR_2
)) {
67 l
= BN_mod_word(dh
->p
, 24);
69 *ret
|= DH_NOT_SUITABLE_GENERATOR
;
70 } else if (BN_is_word(dh
->g
, DH_GENERATOR_5
)) {
71 l
= BN_mod_word(dh
->p
, 10);
72 if ((l
!= 3) && (l
!= 7))
73 *ret
|= DH_NOT_SUITABLE_GENERATOR
;
75 *ret
|= DH_UNABLE_TO_CHECK_GENERATOR
;
77 if (!BN_is_prime_ex(dh
->p
, BN_prime_checks
, ctx
, NULL
))
78 *ret
|= DH_CHECK_P_NOT_PRIME
;
80 if (!BN_rshift1(t1
, dh
->p
))
82 if (!BN_is_prime_ex(t1
, BN_prime_checks
, ctx
, NULL
))
83 *ret
|= DH_CHECK_P_NOT_SAFE_PRIME
;
94 int DH_check_pub_key(const DH
*dh
, const BIGNUM
*pub_key
, int *ret
)
105 tmp
= BN_CTX_get(ctx
);
106 if (tmp
== NULL
|| !BN_set_word(tmp
, 1))
108 if (BN_cmp(pub_key
, tmp
) <= 0)
109 *ret
|= DH_CHECK_PUBKEY_TOO_SMALL
;
110 if (BN_copy(tmp
, dh
->p
) == NULL
|| !BN_sub_word(tmp
, 1))
112 if (BN_cmp(pub_key
, tmp
) >= 0)
113 *ret
|= DH_CHECK_PUBKEY_TOO_LARGE
;
116 /* Check pub_key^q == 1 mod p */
117 if (!BN_mod_exp(tmp
, pub_key
, dh
->q
, dh
->p
, ctx
))
120 *ret
|= DH_CHECK_PUBKEY_INVALID
;