summaryrefslogtreecommitdiffstats
path: root/libtomcrypt/pk/dsa/dsa_verify_key.c
blob: cba33c5884a7ad1bc8d295a63a7f46ff8df13bdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
 *
 * LibTomCrypt is a library that provides various cryptographic
 * algorithms in a highly modular and flexible manner.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
 */
#include "tomcrypt.h"

/**
   @file dsa_verify_key.c
   DSA implementation, verify a key, Tom St Denis
*/

#ifdef LTC_MDSA

/**
   Verify a DSA key for validity
   @param key   The key to verify
   @param stat  [out]  Result of test, 1==valid, 0==invalid
   @return CRYPT_OK if successful
*/
int dsa_verify_key(dsa_key * key, int *stat)
{
	mp_int tmp, tmp2;
	int res, err;

	LTC_ARGCHK(key != NULL);
	LTC_ARGCHK(stat != NULL);

	/* default to an invalid key */
	*stat = 0;

	/* first make sure key->q and key->p are prime */
	if ((err = mp_prime_is_prime(&key->q, 8, &res)) != CRYPT_OK) {
		return err;
	}
	if (res == 0) {
		return CRYPT_OK;
	}

	if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) {
		return err;
	}
	if (res == 0) {
		return CRYPT_OK;
	}

	/* now make sure that g is not -1, 0 or 1 and <p */
	if (mp_cmp_d(&key->g, 0) == LTC_MP_EQ
	    || mp_cmp_d(&key->g, 1) == LTC_MP_EQ) {
		return CRYPT_OK;
	}
	if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) {
		return err;
	}
	if ((err = mp_sub_d(&key->p, 1, &tmp)) != CRYPT_OK) {
		goto error;
	}
	if (mp_cmp(&tmp, &key->g) == LTC_MP_EQ
	    || mp_cmp(&key->g, &key->p) != LTC_MP_LT) {
		err = CRYPT_OK;
		goto error;
	}

	/* 1 < y < p-1 */
	if (!
	    (mp_cmp_d(&key->y, 1) == LTC_MP_GT
	     && mp_cmp(&key->y, &tmp) == LTC_MP_LT)) {
		err = CRYPT_OK;
		goto error;
	}

	/* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
	if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != CRYPT_OK) {
		goto error;
	}
	if (mp_iszero(&tmp2) != LTC_MP_YES) {
		err = CRYPT_OK;
		goto error;
	}

	if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != CRYPT_OK) {
		goto error;
	}
	if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
		err = CRYPT_OK;
		goto error;
	}

	/* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
	if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != CRYPT_OK) {
		goto error;
	}
	if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
		err = CRYPT_OK;
		goto error;
	}

	/* at this point we are out of tests ;-( */
	err = CRYPT_OK;
	*stat = 1;
error:
	mp_clear_multi(&tmp, &tmp2, NULL);
	return err;
}
#endif

/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */
/* $Revision: 1.8 $ */
/* $Date: 2007/05/12 14:32:35 $ */