This commit was manufactured by cvs2svn to create branch 'vserver'.
[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 /*
28  * perform DSA algorithm signature verification
29  */
30 int DSA_verify(const MPI datahash, const MPI sig[], const MPI pkey[])
31 {
32         MPI p, q, g, y, r, s;
33         MPI w = NULL, u1 = NULL, u2 = NULL, v = NULL;
34         MPI base[3];
35         MPI exp[3];
36         int rc;
37
38         if (!datahash ||
39             !sig[0] || !sig[1] ||
40             !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3]
41             )
42                 return -EINVAL;
43
44         p = pkey[0];    /* prime */
45         q = pkey[1];    /* group order */
46         g = pkey[2];    /* group generator */
47         y = pkey[3];    /* g^x mod p */
48         r = sig[0];
49         s = sig[1];
50
51         if (!(mpi_cmp_ui(r, 0) > 0 && mpi_cmp(r, q) < 0)) {
52                 printk("DSA_verify assertion failed [0 < r < q]\n");
53                 return -EPERM;
54         }
55
56         if (!(mpi_cmp_ui(s, 0) > 0 && mpi_cmp(s, q) < 0)) {
57                 printk("DSA_verify assertion failed [0 < s < q]\n");
58                 return -EPERM;
59         }
60
61         rc = -ENOMEM;
62         w  = mpi_alloc(mpi_get_nlimbs(q)); if (!w ) goto cleanup;
63         u1 = mpi_alloc(mpi_get_nlimbs(q)); if (!u1) goto cleanup;
64         u2 = mpi_alloc(mpi_get_nlimbs(q)); if (!u2) goto cleanup;
65         v  = mpi_alloc(mpi_get_nlimbs(p)); if (!v ) goto cleanup;
66
67         /* w = s^(-1) mod q */
68         if (mpi_invm(w, s, q) < 0)
69                 goto cleanup;
70
71         /* u1 = (datahash * w) mod q */
72         if (mpi_mulm(u1, datahash, w, q) < 0)
73                 goto cleanup;
74
75         /* u2 = r * w mod q  */
76         if (mpi_mulm(u2, r, w, q) < 0)
77                 goto cleanup;
78
79         /* v =  g^u1 * y^u2 mod p mod q */
80         base[0] = g;    exp[0] = u1;
81         base[1] = y;    exp[1] = u2;
82         base[2] = NULL; exp[2] = NULL;
83
84         if (mpi_mulpowm(v, base, exp, p) < 0)
85                 goto cleanup;
86
87         if (mpi_fdiv_r(v, v, q) < 0)
88                 goto cleanup;
89
90         rc = mpi_cmp(v, r) == 0 ? 0 : -EPERM;
91
92  cleanup:
93         mpi_free(w);
94         mpi_free(u1);
95         mpi_free(u2);
96         mpi_free(v);
97         return rc;
98 } /* end DSA_verify() */