comparison libtomcrypt/src/pk/dsa/dsa_verify_key.c @ 1471:6dba84798cd5

Update to libtomcrypt 1.18.1, merged with Dropbear changes
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 21:44:05 +0800
parents f849a5ca2efc
children
comparison
equal deleted inserted replaced
1470:8bba51a55704 1471:6dba84798cd5
3 * LibTomCrypt is a library that provides various cryptographic 3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner. 4 * algorithms in a highly modular and flexible manner.
5 * 5 *
6 * The library is free for all purposes without any express 6 * The library is free for all purposes without any express
7 * guarantee it works. 7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtom.org
10 */ 8 */
11 #include "tomcrypt.h" 9 #include "tomcrypt.h"
12 10
13 /** 11 /**
14 @file dsa_verify_key.c 12 @file dsa_verify_key.c
16 */ 14 */
17 15
18 #ifdef LTC_MDSA 16 #ifdef LTC_MDSA
19 17
20 /** 18 /**
21 Verify a DSA key for validity 19 Validate a DSA key
22 @param key The key to verify 20
21 Yeah, this function should've been called dsa_validate_key()
22 in the first place and for compat-reasons we keep it
23 as it was (for now).
24
25 @param key The key to validate
23 @param stat [out] Result of test, 1==valid, 0==invalid 26 @param stat [out] Result of test, 1==valid, 0==invalid
24 @return CRYPT_OK if successful 27 @return CRYPT_OK if successful
25 */ 28 */
26 int dsa_verify_key(dsa_key *key, int *stat) 29 int dsa_verify_key(dsa_key *key, int *stat)
27 { 30 {
28 void *tmp, *tmp2; 31 int err;
29 int res, err; 32
33 err = dsa_int_validate_primes(key, stat);
34 if (err != CRYPT_OK || *stat == 0) return err;
35
36 err = dsa_int_validate_pqg(key, stat);
37 if (err != CRYPT_OK || *stat == 0) return err;
38
39 return dsa_int_validate_xy(key, stat);
40 }
41
42 /**
43 Non-complex part (no primality testing) of the validation
44 of DSA params (p, q, g)
45
46 @param key The key to validate
47 @param stat [out] Result of test, 1==valid, 0==invalid
48 @return CRYPT_OK if successful
49 */
50 int dsa_int_validate_pqg(dsa_key *key, int *stat)
51 {
52 void *tmp1, *tmp2;
53 int err;
30 54
31 LTC_ARGCHK(key != NULL); 55 LTC_ARGCHK(key != NULL);
32 LTC_ARGCHK(stat != NULL); 56 LTC_ARGCHK(stat != NULL);
33
34 /* default to an invalid key */
35 *stat = 0; 57 *stat = 0;
36 58
37 /* first make sure key->q and key->p are prime */ 59 /* check q-order */
38 if ((err = mp_prime_is_prime(key->q, 8, &res)) != CRYPT_OK) { 60 if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
39 return err; 61 (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
40 } 62 (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
41 if (res == 0) {
42 return CRYPT_OK; 63 return CRYPT_OK;
43 } 64 }
44 65
45 if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { 66 /* FIPS 186-4 chapter 4.1: 1 < g < p */
46 return err; 67 if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
47 }
48 if (res == 0) {
49 return CRYPT_OK; 68 return CRYPT_OK;
50 } 69 }
51 70
52 /* now make sure that g is not -1, 0 or 1 and <p */ 71 if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) { return err; }
53 if (mp_cmp_d(key->g, 0) == LTC_MP_EQ || mp_cmp_d(key->g, 1) == LTC_MP_EQ) {
54 return CRYPT_OK;
55 }
56 if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) { return err; }
57 if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { goto error; }
58 if (mp_cmp(tmp, key->g) == LTC_MP_EQ || mp_cmp(key->g, key->p) != LTC_MP_LT) {
59 err = CRYPT_OK;
60 goto error;
61 }
62 72
63 /* 1 < y < p-1 */ 73 /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
64 if (!(mp_cmp_d(key->y, 1) == LTC_MP_GT && mp_cmp(key->y, tmp) == LTC_MP_LT)) { 74 if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; }
65 err = CRYPT_OK; 75 if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; }
66 goto error;
67 }
68
69 /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
70 if ((err = mp_div(tmp, key->q, tmp, tmp2)) != CRYPT_OK) { goto error; }
71 if (mp_iszero(tmp2) != LTC_MP_YES) { 76 if (mp_iszero(tmp2) != LTC_MP_YES) {
72 err = CRYPT_OK; 77 err = CRYPT_OK;
73 goto error; 78 goto error;
74 } 79 }
75 80
76 if ((err = mp_exptmod(key->g, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } 81 /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
77 if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { 82 * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1
83 */
84 if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; }
85 if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) {
78 err = CRYPT_OK; 86 err = CRYPT_OK;
79 goto error; 87 goto error;
80 } 88 }
81 89
82 /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */ 90 err = CRYPT_OK;
83 if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } 91 *stat = 1;
84 if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { 92 error:
93 mp_clear_multi(tmp2, tmp1, NULL);
94 return err;
95 }
96
97 /**
98 Primality testing of DSA params p and q
99
100 @param key The key to validate
101 @param stat [out] Result of test, 1==valid, 0==invalid
102 @return CRYPT_OK if successful
103 */
104 int dsa_int_validate_primes(dsa_key *key, int *stat)
105 {
106 int err, res;
107
108 *stat = 0;
109 LTC_ARGCHK(key != NULL);
110 LTC_ARGCHK(stat != NULL);
111
112 /* key->q prime? */
113 if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
114 return err;
115 }
116 if (res == LTC_MP_NO) {
117 return CRYPT_OK;
118 }
119
120 /* key->p prime? */
121 if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
122 return err;
123 }
124 if (res == LTC_MP_NO) {
125 return CRYPT_OK;
126 }
127
128 *stat = 1;
129 return CRYPT_OK;
130 }
131
132 /**
133 Validation of a DSA key (x and y values)
134
135 @param key The key to validate
136 @param stat [out] Result of test, 1==valid, 0==invalid
137 @return CRYPT_OK if successful
138 */
139 int dsa_int_validate_xy(dsa_key *key, int *stat)
140 {
141 void *tmp;
142 int err;
143
144 *stat = 0;
145 LTC_ARGCHK(key != NULL);
146 LTC_ARGCHK(stat != NULL);
147
148 /* 1 < y < p-1 */
149 if ((err = mp_init(&tmp)) != CRYPT_OK) {
150 return err;
151 }
152 if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) {
153 goto error;
154 }
155 if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) {
85 err = CRYPT_OK; 156 err = CRYPT_OK;
86 goto error; 157 goto error;
87 } 158 }
88 159
89 /* at this point we are out of tests ;-( */ 160 if (key->type == PK_PRIVATE) {
161 /* FIPS 186-4 chapter 4.1: 0 < x < q */
162 if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) {
163 err = CRYPT_OK;
164 goto error;
165 }
166 /* FIPS 186-4 chapter 4.1: y = g^x mod p */
167 if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) {
168 goto error;
169 }
170 if (mp_cmp(tmp, key->y) != LTC_MP_EQ) {
171 err = CRYPT_OK;
172 goto error;
173 }
174 }
175 else {
176 /* with just a public key we cannot test y = g^x mod p therefore we
177 * only test that y^q mod p = 1, which makes sure y is in g^x mod p
178 */
179 if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) {
180 goto error;
181 }
182 if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) {
183 err = CRYPT_OK;
184 goto error;
185 }
186 }
187
90 err = CRYPT_OK; 188 err = CRYPT_OK;
91 *stat = 1; 189 *stat = 1;
92 error: 190 error:
93 mp_clear_multi(tmp, tmp2, NULL); 191 mp_clear(tmp);
94 return err; 192 return err;
95 } 193 }
194
96 #endif 195 #endif
97 196
98 /* $Source$ */ 197 /* ref: $Format:%D$ */
99 /* $Revision$ */ 198 /* git commit: $Format:%H$ */
100 /* $Date$ */ 199 /* commit time: $Format:%ai$ */