3 * $Id: dsa-verify.c,v 1.6 2001/06/16 12:56:38 mdw Exp $
5 * DSA signature verification
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 /*----- Revision history --------------------------------------------------*
32 * $Log: dsa-verify.c,v $
33 * Revision 1.6 2001/06/16 12:56:38 mdw
34 * Fixes for interface change to @mpmont_expr@ and @mpmont_mexpr@.
36 * Revision 1.5 2000/10/08 12:13:17 mdw
37 * Use @MP_EQ@ instead of @MP_CMP@.
39 * Revision 1.4 2000/06/17 10:53:35 mdw
42 * Revision 1.3 1999/12/10 23:18:38 mdw
43 * Change interface for suggested destinations.
45 * Revision 1.2 1999/11/23 00:20:04 mdw
46 * Remove stray debugging code.
48 * Revision 1.1 1999/11/19 19:28:00 mdw
49 * Implementation of the Digital Signature Algorithm.
53 /*----- Header files ------------------------------------------------------*/
59 /*----- Main code ---------------------------------------------------------*/
61 /* --- @dsa_vrfy@ --- *
63 * Arguments: @const dsa_param *dp@ = pointer to DSA parameters
64 * @mp *y@ = public verification key
65 * @mp *m@ = message which was signed
66 * @mp *r, *s@ = the signature
68 * Returns: Zero if the signature is a forgery, nonzero if it's valid.
70 * Use: Verifies a DSA digital signature.
73 int dsa_vrfy(const dsa_param
*dp
, mp
*y
, mp
*m
, mp
*r
, mp
*s
)
80 /* --- Ensure that all of the signature bits are in range --- */
82 if ((r
->f
| s
->f
) & MP_NEG
)
84 if (MP_CMP(r
, >=, dp
->q
) || MP_CMP(s
, >=, dp
->q
))
87 /* --- Set up Montgomery contexts --- */
89 mpmont_create(&pm
, dp
->p
);
90 mpmont_create(&qm
, dp
->q
);
92 /* --- Compute %$w = s^{-1} \bmod q$% --- */
96 mp_gcd(0, 0, &z
, dp
->q
, s
);
97 w
= mpmont_mul(&qm
, MP_NEW
, z
, qm
.r2
);
101 /* --- Compute %$wr$% and %$wm$% --- */
103 f
[0].exp
= mpmont_mul(&qm
, MP_NEW
, w
, m
);
104 f
[1].exp
= mpmont_mul(&qm
, MP_NEW
, w
, r
);
108 /* --- Do the exponentiation and take residue mod @q@ --- */
112 w
= mpmont_mexp(&pm
, MP_NEW
, f
, 2);
113 mp_div(0, &w
, w
, dp
->q
);
116 /* --- Tidy up --- */
125 /* --- @dsa_verify@ --- *
127 * Arguments: @const dsa_param *dp@ = pointer to DSA parameters
128 * @mp *y@ = public verification key
129 * @const void *m@ = pointer to message block
130 * @size_t msz@ = size of message block
131 * @const void *r@ = pointer to @r@ signature half
132 * @size_t rsz@ = size of @r@
133 * @const void *s@ = pointer to @s@ signature half
134 * @size_t ssz@ = size of @s@
136 * Returns: Zero if the signature is a forgery, nonzero if it's valid.
138 * Use: Verifies a DSA digital signature.
141 int dsa_verify(const dsa_param
*dp
, mp
*y
,
142 const void *m
, size_t msz
,
143 const void *r
, size_t rsz
,
144 const void *s
, size_t ssz
)
146 mp
*mm
= mp_loadb(MP_NEW
, m
, msz
);
147 mp
*rm
= mp_loadb(MP_NEW
, r
, rsz
);
148 mp
*sm
= mp_loadb(MP_NEW
, s
, ssz
);
149 int ok
= dsa_vrfy(dp
, y
, mm
, rm
, sm
);
156 /*----- Test rig ----------------------------------------------------------*/
160 #include <mLib/testrig.h>
164 static int verify(int good
, dstr
*v
)
169 octet hash
[SHA_HASHSZ
];
173 dp
.q
= *(mp
**)v
[0].buf
;
174 dp
.p
= *(mp
**)v
[1].buf
;
175 dp
.g
= *(mp
**)v
[2].buf
;
176 y
= *(mp
**)v
[3].buf
;
179 sha_hash(&c
, v
[4].buf
, v
[4].len
);
182 rc
= dsa_verify(&dp
, y
, hash
, sizeof(hash
),
183 v
[5].buf
, v
[5].len
, v
[6].buf
, v
[6].len
);
187 fputs("\n*** verification failed", stderr
);
189 fputs("\n*** verification succeeded", stderr
);
190 fputs("\nq = ", stderr
); mp_writefile(dp
.q
, stderr
, 16);
191 fputs("\np = ", stderr
); mp_writefile(dp
.p
, stderr
, 16);
192 fputs("\ng = ", stderr
); mp_writefile(dp
.g
, stderr
, 16);
193 fputs("\ny = ", stderr
); mp_writefile(y
, stderr
, 16);
194 fprintf(stderr
, "\nmessage = `%s'", v
[4].buf
);
195 fputs("\nr = ", stderr
); type_hex
.dump(&v
[5], stderr
);
196 fputs("\ns = ", stderr
); type_hex
.dump(&v
[6], stderr
);
205 assert(mparena_count(MPARENA_GLOBAL
) == 0);
209 static int vgood(dstr
*v
) { return verify(1, v
); }
210 static int vbad(dstr
*v
) { return verify(0, v
); }
212 static test_chunk tests
[] = {
213 { "verify-good", vgood
,
214 { &type_mp
, &type_mp
, &type_mp
, &type_mp
,
215 &type_string
, &type_hex
, &type_hex
, 0 } },
216 { "verify-bad", vbad
,
217 { &type_mp
, &type_mp
, &type_mp
, &type_mp
,
218 &type_string
, &type_hex
, &type_hex
, 0 } },
222 int main(int argc
, char *argv
[])
225 test_run(argc
, argv
, tests
, SRCDIR
"/tests/dsa");
231 /*----- That's all, folks -------------------------------------------------*/