sha/asm/keccak1600-armv4.pl: add NEON code path.
[openssl.git] / crypto / dh / dh_check.c
1 /*
2  * Copyright 1995-2016 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     if (t1 == NULL)
79         goto err;
80     t2 = BN_CTX_get(ctx);
81     if (t2 == NULL)
82         goto err;
83
84     if (dh->q) {
85         if (BN_cmp(dh->g, BN_value_one()) <= 0)
86             *ret |= DH_NOT_SUITABLE_GENERATOR;
87         else if (BN_cmp(dh->g, dh->p) >= 0)
88             *ret |= DH_NOT_SUITABLE_GENERATOR;
89         else {
90             /* Check g^q == 1 mod p */
91             if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
92                 goto err;
93             if (!BN_is_one(t1))
94                 *ret |= DH_NOT_SUITABLE_GENERATOR;
95         }
96         r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
97         if (r < 0)
98             goto err;
99         if (!r)
100             *ret |= DH_CHECK_Q_NOT_PRIME;
101         /* Check p == 1 mod q  i.e. q divides p - 1 */
102         if (!BN_div(t1, t2, dh->p, dh->q, ctx))
103             goto err;
104         if (!BN_is_one(t2))
105             *ret |= DH_CHECK_INVALID_Q_VALUE;
106         if (dh->j && BN_cmp(dh->j, t1))
107             *ret |= DH_CHECK_INVALID_J_VALUE;
108
109     } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
110         l = BN_mod_word(dh->p, 24);
111         if (l == (BN_ULONG)-1)
112             goto err;
113         if (l != 11)
114             *ret |= DH_NOT_SUITABLE_GENERATOR;
115     } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
116         l = BN_mod_word(dh->p, 10);
117         if (l == (BN_ULONG)-1)
118             goto err;
119         if ((l != 3) && (l != 7))
120             *ret |= DH_NOT_SUITABLE_GENERATOR;
121     } else
122         *ret |= DH_UNABLE_TO_CHECK_GENERATOR;
123
124     r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
125     if (r < 0)
126         goto err;
127     if (!r)
128         *ret |= DH_CHECK_P_NOT_PRIME;
129     else if (!dh->q) {
130         if (!BN_rshift1(t1, dh->p))
131             goto err;
132         r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
133         if (r < 0)
134             goto err;
135         if (!r)
136             *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
137     }
138     ok = 1;
139  err:
140     if (ctx != NULL) {
141         BN_CTX_end(ctx);
142         BN_CTX_free(ctx);
143     }
144     return (ok);
145 }
146
147 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
148 {
149     int ok = 0;
150     BIGNUM *tmp = NULL;
151     BN_CTX *ctx = NULL;
152
153     *ret = 0;
154     ctx = BN_CTX_new();
155     if (ctx == NULL)
156         goto err;
157     BN_CTX_start(ctx);
158     tmp = BN_CTX_get(ctx);
159     if (tmp == NULL || !BN_set_word(tmp, 1))
160         goto err;
161     if (BN_cmp(pub_key, tmp) <= 0)
162         *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
163     if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
164         goto err;
165     if (BN_cmp(pub_key, tmp) >= 0)
166         *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
167
168     if (dh->q != NULL) {
169         /* Check pub_key^q == 1 mod p */
170         if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
171             goto err;
172         if (!BN_is_one(tmp))
173             *ret |= DH_CHECK_PUBKEY_INVALID;
174     }
175
176     ok = 1;
177  err:
178     if (ctx != NULL) {
179         BN_CTX_end(ctx);
180         BN_CTX_free(ctx);
181     }
182     return (ok);
183 }