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_sign_hash.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_sign_hash.c
13
DSA implementation, sign a hash, Tom St Denis
14
*/
15
16
#ifdef LTC_MDSA
17
18
/**
19
Sign a hash with DSA
20
@param in The hash to sign
21
@param inlen The length of the hash to sign
22
@param r The "r" integer of the signature (caller must initialize with mp_init() first)
23
@param s The "s" integer of the signature (caller must initialize with mp_init() first)
24
@param prng An active PRNG state
25
@param wprng The index of the PRNG desired
26
@param key A private DSA key
27
@return CRYPT_OK if successful
28
*/
29
int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
30
void *r, void *s,
31
prng_state *prng, int wprng, dsa_key *key)
32
{
33
void *k, *kinv, *tmp;
34
unsigned char *buf;
35
int err, qbits;
36
37
LTC_ARGCHK(in != NULL);
38
LTC_ARGCHK(r != NULL);
39
LTC_ARGCHK(s != NULL);
40
LTC_ARGCHK(key != NULL);
41
42
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
43
return err;
44
}
45
if (key->type != PK_PRIVATE) {
46
return CRYPT_PK_NOT_PRIVATE;
47
}
48
49
/* check group order size */
50
if (key->qord >= LTC_MDSA_MAX_GROUP) {
51
return CRYPT_INVALID_ARG;
52
}
53
54
buf = XMALLOC(LTC_MDSA_MAX_GROUP);
55
if (buf == NULL) {
56
return CRYPT_MEM;
57
}
58
59
/* Init our temps */
60
if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; }
61
62
qbits = mp_count_bits(key->q);
63
retry:
64
65
do {
66
/* gen random k */
67
if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; }
68
69
/* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */
70
if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; }
71
72
/* test gcd */
73
if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; }
74
} while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);
75
76
/* now find 1/k mod q */
77
if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; }
78
79
/* now find r = g^k mod p mod q */
80
if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; }
81
if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; }
82
83
if (mp_iszero(r) == LTC_MP_YES) { goto retry; }
84
85
/* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/
86
inlen = MIN(inlen, (unsigned long)(key->qord));
87
88
/* now find s = (in + xr)/k mod q */
89
if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; }
90
if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; }
91
if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; }
92
if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; }
93
94
if (mp_iszero(s) == LTC_MP_YES) { goto retry; }
95
96
err = CRYPT_OK;
97
error:
98
mp_clear_multi(k, kinv, tmp, NULL);
99
ERRBUF:
100
#ifdef LTC_CLEAN_STACK
101
zeromem(buf, LTC_MDSA_MAX_GROUP);
102
#endif
103
XFREE(buf);
104
return err;
105
}
106
107
/**
108
Sign a hash with DSA
109
@param in The hash to sign
110
@param inlen The length of the hash to sign
111
@param out [out] Where to store the signature
112
@param outlen [in/out] The max size and resulting size of the signature
113
@param prng An active PRNG state
114
@param wprng The index of the PRNG desired
115
@param key A private DSA key
116
@return CRYPT_OK if successful
117
*/
118
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
119
unsigned char *out, unsigned long *outlen,
120
prng_state *prng, int wprng, dsa_key *key)
121
{
122
void *r, *s;
123
int err;
124
125
LTC_ARGCHK(in != NULL);
126
LTC_ARGCHK(out != NULL);
127
LTC_ARGCHK(outlen != NULL);
128
LTC_ARGCHK(key != NULL);
129
130
if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) {
131
return CRYPT_MEM;
132
}
133
134
if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) {
135
goto error;
136
}
137
138
err = der_encode_sequence_multi(out, outlen,
139
LTC_ASN1_INTEGER, 1UL, r,
140
LTC_ASN1_INTEGER, 1UL, s,
141
LTC_ASN1_EOL, 0UL, NULL);
142
143
error:
144
mp_clear_multi(r, s, NULL);
145
return err;
146
}
147
148
#endif
149
150