Improve style
[openssl.git] / crypto / dh / dh_check.c
1 /*
2  * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/bn.h>
13 #include "dh_locl.h"
14
15 /*-
16  * Check that p and g are suitable enough
17  *
18  * p is odd
19  * 1 < g < p - 1
20  */
21
22 int DH_check_params(const DH *dh, int *ret)
23 {
24     int ok = 0;
25     BIGNUM *tmp = NULL;
26     BN_CTX *ctx = NULL;
27
28     *ret = 0;
29     ctx = BN_CTX_new();
30     if (ctx == NULL)
31         goto err;
32     BN_CTX_start(ctx);
33     tmp = BN_CTX_get(ctx);
34     if (tmp == NULL)
35         goto err;
36
37     if (!BN_is_odd(dh->p))
38         *ret |= DH_CHECK_P_NOT_PRIME;
39     if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g))
40         *ret |= DH_NOT_SUITABLE_GENERATOR;
41     if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
42         goto err;
43     if (BN_cmp(dh->g, tmp) >= 0)
44         *ret |= DH_NOT_SUITABLE_GENERATOR;
45
46     ok = 1;
47  err:
48     if (ctx != NULL) {
49         BN_CTX_end(ctx);
50         BN_CTX_free(ctx);
51     }
52     return (ok);
53 }
54
55 /*-
56  * Check that p is a safe prime and
57  * if g is 2, 3 or 5, check that it is a suitable generator
58  * where
59  * for 2, p mod 24 == 11
60  * for 3, p mod 12 == 5
61  * for 5, p mod 10 == 3 or 7
62  * should hold.
63  */
64
65 int DH_check(const DH *dh, int *ret)
66 {
67     int ok = 0, r;
68     BN_CTX *ctx = NULL;
69     BN_ULONG l;
70     BIGNUM *t1 = NULL, *t2 = NULL;
71
72     *ret = 0;
73     ctx = BN_CTX_new();
74     if (ctx == NULL)
75         goto err;
76     BN_CTX_start(ctx);
77     t1 = BN_CTX_get(ctx);
78     t2 = BN_CTX_get(ctx);
79     if (t2 == NULL)
80         goto err;
81
82     if (dh->q) {
83         if (BN_cmp(dh->g, BN_value_one()) <= 0)
84             *ret |= DH_NOT_SUITABLE_GENERATOR;
85         else if (BN_cmp(dh->g, dh->p) >= 0)
86             *ret |= DH_NOT_SUITABLE_GENERATOR;
87         else {
88             /* Check g^q == 1 mod p */
89             if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
90                 goto err;
91             if (!BN_is_one(t1))
92                 *ret |= DH_NOT_SUITABLE_GENERATOR;
93         }
94         r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
95         if (r < 0)
96             goto err;
97         if (!r)
98             *ret |= DH_CHECK_Q_NOT_PRIME;
99         /* Check p == 1 mod q  i.e. q divides p - 1 */
100         if (!BN_div(t1, t2, dh->p, dh->q, ctx))
101             goto err;
102         if (!BN_is_one(t2))
103             *ret |= DH_CHECK_INVALID_Q_VALUE;
104         if (dh->j && BN_cmp(dh->j, t1))
105             *ret |= DH_CHECK_INVALID_J_VALUE;
106
107     } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
108         l = BN_mod_word(dh->p, 24);
109         if (l == (BN_ULONG)-1)
110             goto err;
111         if (l != 11)
112             *ret |= DH_NOT_SUITABLE_GENERATOR;
113     } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
114         l = BN_mod_word(dh->p, 10);
115         if (l == (BN_ULONG)-1)
116             goto err;
117         if ((l != 3) && (l != 7))
118             *ret |= DH_NOT_SUITABLE_GENERATOR;
119     } else
120         *ret |= DH_UNABLE_TO_CHECK_GENERATOR;
121
122     r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
123     if (r < 0)
124         goto err;
125     if (!r)
126         *ret |= DH_CHECK_P_NOT_PRIME;
127     else if (!dh->q) {
128         if (!BN_rshift1(t1, dh->p))
129             goto err;
130         r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
131         if (r < 0)
132             goto err;
133         if (!r)
134             *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
135     }
136     ok = 1;
137  err:
138     if (ctx != NULL) {
139         BN_CTX_end(ctx);
140         BN_CTX_free(ctx);
141     }
142     return (ok);
143 }
144
145 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
146 {
147     int ok = 0;
148     BIGNUM *tmp = NULL;
149     BN_CTX *ctx = NULL;
150
151     *ret = 0;
152     ctx = BN_CTX_new();
153     if (ctx == NULL)
154         goto err;
155     BN_CTX_start(ctx);
156     tmp = BN_CTX_get(ctx);
157     if (tmp == NULL || !BN_set_word(tmp, 1))
158         goto err;
159     if (BN_cmp(pub_key, tmp) <= 0)
160         *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
161     if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
162         goto err;
163     if (BN_cmp(pub_key, tmp) >= 0)
164         *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
165
166     if (dh->q != NULL) {
167         /* Check pub_key^q == 1 mod p */
168         if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
169             goto err;
170         if (!BN_is_one(tmp))
171             *ret |= DH_CHECK_PUBKEY_INVALID;
172     }
173
174     ok = 1;
175  err:
176     if (ctx != NULL) {
177         BN_CTX_end(ctx);
178         BN_CTX_free(ctx);
179     }
180     return (ok);
181 }