Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tomcrypt/src/pk/dsa/dsa_verify_key.c
4396 views
1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2
*
3
* LibTomCrypt is a library that provides various cryptographic
4
* algorithms in a highly modular and flexible manner.
5
*
6
* The library is free for all purposes without any express
7
* guarantee it works.
8
*/
9
#include "tomcrypt.h"
10
11
/**
12
@file dsa_verify_key.c
13
DSA implementation, verify a key, Tom St Denis
14
*/
15
16
#ifdef LTC_MDSA
17
18
/**
19
Validate a DSA key
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
26
@param stat [out] Result of test, 1==valid, 0==invalid
27
@return CRYPT_OK if successful
28
*/
29
int dsa_verify_key(dsa_key *key, int *stat)
30
{
31
int 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;
54
55
LTC_ARGCHK(key != NULL);
56
LTC_ARGCHK(stat != NULL);
57
*stat = 0;
58
59
/* check q-order */
60
if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
61
(unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
62
(mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
63
return CRYPT_OK;
64
}
65
66
/* FIPS 186-4 chapter 4.1: 1 < g < p */
67
if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
68
return CRYPT_OK;
69
}
70
71
if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) { return err; }
72
73
/* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
74
if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; }
75
if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; }
76
if (mp_iszero(tmp2) != LTC_MP_YES) {
77
err = CRYPT_OK;
78
goto error;
79
}
80
81
/* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
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) {
86
err = CRYPT_OK;
87
goto error;
88
}
89
90
err = CRYPT_OK;
91
*stat = 1;
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) {
156
err = CRYPT_OK;
157
goto error;
158
}
159
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
188
err = CRYPT_OK;
189
*stat = 1;
190
error:
191
mp_clear(tmp);
192
return err;
193
}
194
195
#endif
196
197