1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file dsa_verify_key.c
7 DSA implementation, verify a key, Tom St Denis
8 */
9
10 #ifdef LTC_MDSA
11
12 /**
13 Validate a DSA key
14
15 Yeah, this function should've been called dsa_validate_key()
16 in the first place and for compat-reasons we keep it
17 as it was (for now).
18
19 @param key The key to validate
20 @param stat [out] Result of test, 1==valid, 0==invalid
21 @return CRYPT_OK if successful
22 */
dsa_verify_key(const dsa_key * key,int * stat)23 int dsa_verify_key(const dsa_key *key, int *stat)
24 {
25 int err;
26
27 err = dsa_int_validate_primes(key, stat);
28 if (err != CRYPT_OK || *stat == 0) return err;
29
30 err = dsa_int_validate_pqg(key, stat);
31 if (err != CRYPT_OK || *stat == 0) return err;
32
33 return dsa_int_validate_xy(key, stat);
34 }
35
36 /**
37 Non-complex part (no primality testing) of the validation
38 of DSA params (p, q, g)
39
40 @param key The key to validate
41 @param stat [out] Result of test, 1==valid, 0==invalid
42 @return CRYPT_OK if successful
43 */
dsa_int_validate_pqg(const dsa_key * key,int * stat)44 int dsa_int_validate_pqg(const dsa_key *key, int *stat)
45 {
46 void *tmp1, *tmp2;
47 int err;
48
49 LTC_ARGCHK(key != NULL);
50 LTC_ARGCHK(stat != NULL);
51 *stat = 0;
52
53 /* check q-order */
54 if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
55 (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
56 (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
57 return CRYPT_OK;
58 }
59
60 /* FIPS 186-4 chapter 4.1: 1 < g < p */
61 if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
62 return CRYPT_OK;
63 }
64
65 if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; }
66
67 /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
68 if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; }
69 if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; }
70 if (mp_iszero(tmp2) != LTC_MP_YES) {
71 err = CRYPT_OK;
72 goto error;
73 }
74
75 /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
76 * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1
77 */
78 if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; }
79 if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) {
80 err = CRYPT_OK;
81 goto error;
82 }
83
84 err = CRYPT_OK;
85 *stat = 1;
86 error:
87 mp_clear_multi(tmp2, tmp1, LTC_NULL);
88 return err;
89 }
90
91 /**
92 Primality testing of DSA params p and q
93
94 @param key The key to validate
95 @param stat [out] Result of test, 1==valid, 0==invalid
96 @return CRYPT_OK if successful
97 */
dsa_int_validate_primes(const dsa_key * key,int * stat)98 int dsa_int_validate_primes(const dsa_key *key, int *stat)
99 {
100 int err, res;
101
102 *stat = 0;
103 LTC_ARGCHK(key != NULL);
104 LTC_ARGCHK(stat != NULL);
105
106 /* key->q prime? */
107 if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
108 return err;
109 }
110 if (res == LTC_MP_NO) {
111 return CRYPT_OK;
112 }
113
114 /* key->p prime? */
115 if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
116 return err;
117 }
118 if (res == LTC_MP_NO) {
119 return CRYPT_OK;
120 }
121
122 *stat = 1;
123 return CRYPT_OK;
124 }
125
126 /**
127 Validation of a DSA key (x and y values)
128
129 @param key The key to validate
130 @param stat [out] Result of test, 1==valid, 0==invalid
131 @return CRYPT_OK if successful
132 */
dsa_int_validate_xy(const dsa_key * key,int * stat)133 int dsa_int_validate_xy(const dsa_key *key, int *stat)
134 {
135 void *tmp;
136 int err;
137
138 *stat = 0;
139 LTC_ARGCHK(key != NULL);
140 LTC_ARGCHK(stat != NULL);
141
142 /* 1 < y < p-1 */
143 if ((err = mp_init(&tmp)) != CRYPT_OK) {
144 return err;
145 }
146 if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) {
147 goto error;
148 }
149 if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) {
150 err = CRYPT_OK;
151 goto error;
152 }
153
154 if (key->type == PK_PRIVATE) {
155 /* FIPS 186-4 chapter 4.1: 0 < x < q */
156 if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) {
157 err = CRYPT_OK;
158 goto error;
159 }
160 /* FIPS 186-4 chapter 4.1: y = g^x mod p */
161 if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) {
162 goto error;
163 }
164 if (mp_cmp(tmp, key->y) != LTC_MP_EQ) {
165 err = CRYPT_OK;
166 goto error;
167 }
168 }
169 else {
170 /* with just a public key we cannot test y = g^x mod p therefore we
171 * only test that y^q mod p = 1, which makes sure y is in g^x mod p
172 */
173 if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) {
174 goto error;
175 }
176 if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) {
177 err = CRYPT_OK;
178 goto error;
179 }
180 }
181
182 err = CRYPT_OK;
183 *stat = 1;
184 error:
185 mp_clear(tmp);
186 return err;
187 }
188
189 #endif
190