fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / crypto / signature / dsa.c
1 /* dsa.c  -  DSA signature algorithm
2  *      Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/crypto/mpi.h>
23 #include <asm/errno.h>
24 #include "local.h"
25
26 /*
27  * perform DSA algorithm signature verification
28  */
29 int DSA_verify(const MPI datahash, const MPI sig[], const MPI pkey[])
30 {
31         MPI p, q, g, y, r, s;
32         MPI w = NULL, u1 = NULL, u2 = NULL, v = NULL;
33         MPI base[3];
34         MPI exp[3];
35         int rc;
36
37         if (!datahash ||
38             !sig[0] || !sig[1] ||
39             !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3])
40                 return -EINVAL;
41
42         p = pkey[0];    /* prime */
43         q = pkey[1];    /* group order */
44         g = pkey[2];    /* group generator */
45         y = pkey[3];    /* g^x mod p */
46         r = sig[0];
47         s = sig[1];
48
49         if (!(mpi_cmp_ui(r, 0) > 0 && mpi_cmp(r, q) < 0)) {
50                 printk("DSA_verify assertion failed [0 < r < q]\n");
51                 return -EKEYREJECTED;
52         }
53
54         if (!(mpi_cmp_ui(s, 0) > 0 && mpi_cmp(s, q) < 0)) {
55                 printk("DSA_verify assertion failed [0 < s < q]\n");
56                 return -EKEYREJECTED;
57         }
58
59         rc = -ENOMEM;
60         w  = mpi_alloc(mpi_get_nlimbs(q)); if (!w ) goto cleanup;
61         u1 = mpi_alloc(mpi_get_nlimbs(q)); if (!u1) goto cleanup;
62         u2 = mpi_alloc(mpi_get_nlimbs(q)); if (!u2) goto cleanup;
63         v  = mpi_alloc(mpi_get_nlimbs(p)); if (!v ) goto cleanup;
64
65         /* w = s^(-1) mod q */
66         if (mpi_invm(w, s, q) < 0)
67                 goto cleanup;
68
69         /* u1 = (datahash * w) mod q */
70         if (mpi_mulm(u1, datahash, w, q) < 0)
71                 goto cleanup;
72
73         /* u2 = r * w mod q  */
74         if (mpi_mulm(u2, r, w, q) < 0)
75                 goto cleanup;
76
77         /* v =  g^u1 * y^u2 mod p mod q */
78         base[0] = g;    exp[0] = u1;
79         base[1] = y;    exp[1] = u2;
80         base[2] = NULL; exp[2] = NULL;
81
82         if (mpi_mulpowm(v, base, exp, p) < 0)
83                 goto cleanup;
84
85         if (mpi_fdiv_r(v, v, q) < 0)
86                 goto cleanup;
87
88         rc = (mpi_cmp(v, r) == 0) ? 0 : -EKEYREJECTED;
89
90 cleanup:
91         mpi_free(w);
92         mpi_free(u1);
93         mpi_free(u2);
94         mpi_free(v);
95         return rc;
96 }