184 lines
4.6 KiB
C
184 lines
4.6 KiB
C
/*
|
|
* Copyright (c) 2001, 2002 Virtual Unlimited B.V.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
/*!\file dsa.c
|
|
* \brief Digital Signature Algorithm, as specified by NIST FIPS 186.
|
|
*
|
|
* FIPS 186 specifies the DSA algorithm as having a large prime \f$p\f$,
|
|
* a cofactor \f$q\f$ and a generator \f$g\f$ of a subgroup of
|
|
* \f$\mathds{Z}^{*}_p\f$ with order \f$q\f$. The private and public key
|
|
* values are \f$x\f$ and \f$y\f$ respectively.
|
|
*
|
|
* \author Bob Deblier <bob.deblier@pandora.be>
|
|
* \ingroup DL_m DL_dsa_m
|
|
*
|
|
* - Signing equation:
|
|
* - r = (g^k mod p) mod q and
|
|
* - s = (inv(k) * (h(m) + x*r)) mod q
|
|
* - Verifying equation:
|
|
* - check 0 < r < q and 0 < s < q
|
|
* - w = inv(s) mod q
|
|
* - u1 = (h(m)*w) mod q
|
|
* - u2 = (r*w) mod q
|
|
* - v = ((g^u1 * y^u2) mod p) mod q
|
|
* - check v == r
|
|
*/
|
|
|
|
#include "system.h"
|
|
#include "dsa.h"
|
|
#include "dldp.h"
|
|
#include "mp.h"
|
|
#include "debug.h"
|
|
|
|
int dsasign(const mpbarrett* p, const mpbarrett* q, const mpnumber* g, randomGeneratorContext* rgc, const mpnumber* hm, const mpnumber* x, mpnumber* r, mpnumber* s)
|
|
{
|
|
register size_t psize = p->size;
|
|
register size_t qsize = q->size;
|
|
|
|
register mpw* ptemp;
|
|
register mpw* qtemp;
|
|
|
|
register mpw* pwksp;
|
|
register mpw* qwksp;
|
|
|
|
register int rc = -1;
|
|
|
|
ptemp = (mpw*) malloc((5*psize+2) * sizeof(*ptemp));
|
|
if (ptemp == (mpw*) 0)
|
|
return rc;
|
|
|
|
qtemp = (mpw*) malloc((14*qsize+11) * sizeof(*qtemp));
|
|
if (qtemp == (mpw*) 0)
|
|
{
|
|
free(ptemp);
|
|
return rc;
|
|
}
|
|
|
|
pwksp = ptemp+psize;
|
|
qwksp = qtemp+3*qsize;
|
|
|
|
/* allocate r */
|
|
mpnfree(r);
|
|
mpnsize(r, qsize);
|
|
|
|
/* get a random k, invertible modulo q; store k @ qtemp, inv(k) @ qtemp+qsize */
|
|
mpbrndinv_w(q, rgc, qtemp, qtemp+qsize, qwksp);
|
|
|
|
/* g^k mod p */
|
|
mpbpowmod_w(p, g->size, g->data, qsize, qtemp, ptemp, pwksp);
|
|
|
|
/* (g^k mod p) mod q - simple modulo */
|
|
mpmod(qtemp+2*qsize, psize, ptemp, qsize, q->modl, pwksp);
|
|
mpcopy(qsize, r->data, qtemp+psize+qsize);
|
|
|
|
/* allocate s */
|
|
mpnfree(s);
|
|
mpnsize(s, qsize);
|
|
|
|
/* x*r mod q */
|
|
mpbmulmod_w(q, x->size, x->data, r->size, r->data, qtemp, qwksp);
|
|
|
|
/* add h(m) mod q */
|
|
mpbaddmod_w(q, qsize, qtemp, hm->size, hm->data, qtemp+2*qsize, qwksp);
|
|
|
|
/* multiply inv(k) mod q */
|
|
mpbmulmod_w(q, qsize, qtemp+qsize, qsize, qtemp+2*qsize, s->data, qwksp);
|
|
|
|
rc = 0;
|
|
|
|
free(qtemp);
|
|
free(ptemp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int dsavrfy(const mpbarrett* p, const mpbarrett* q, const mpnumber* g, const mpnumber* hm, const mpnumber* y, const mpnumber* r, const mpnumber* s)
|
|
{
|
|
register size_t psize = p->size;
|
|
register size_t qsize = q->size;
|
|
|
|
register mpw* ptemp;
|
|
register mpw* qtemp;
|
|
|
|
register mpw* pwksp;
|
|
register mpw* qwksp;
|
|
|
|
register int rc = 0;
|
|
|
|
if (mpz(r->size, r->data))
|
|
return rc;
|
|
|
|
if (mpgex(r->size, r->data, qsize, q->modl))
|
|
return rc;
|
|
|
|
if (mpz(s->size, s->data))
|
|
return rc;
|
|
|
|
if (mpgex(s->size, s->data, qsize, q->modl))
|
|
return rc;
|
|
|
|
ptemp = (mpw*) malloc((6*psize+2) * sizeof(*ptemp));
|
|
if (ptemp == (mpw*) 0)
|
|
return rc;
|
|
|
|
qtemp = (mpw*) malloc((13*qsize+11) * sizeof(*qtemp));
|
|
if (qtemp == (mpw*) 0)
|
|
{
|
|
free(ptemp);
|
|
return rc;
|
|
}
|
|
|
|
pwksp = ptemp+2*psize;
|
|
qwksp = qtemp+2*qsize;
|
|
|
|
mpsetx(qsize, qtemp+qsize, s->size, s->data);
|
|
|
|
/* compute w = inv(s) mod q */
|
|
/*@-compdef@*/ /* FIX: mpsetx annotations, qtemp[qsize] is defined */
|
|
if (mpextgcd_w(qsize, qtemp+qsize, q->modl, qtemp, qwksp))
|
|
/*@=compdef@*/
|
|
{
|
|
|
|
/* compute u1 = h(m)*w mod q */
|
|
mpbmulmod_w(q, hm->size, hm->data, qsize, qtemp, qtemp+qsize, qwksp);
|
|
|
|
/* compute u2 = r*w mod q */
|
|
mpbmulmod_w(q, r->size, r->data, qsize, qtemp, qtemp, qwksp);
|
|
|
|
/* compute g^u1 mod p */
|
|
mpbpowmod_w(p, g->size, g->data, qsize, qtemp+qsize, ptemp, pwksp);
|
|
|
|
/* compute y^u2 mod p */
|
|
mpbpowmod_w(p, y->size, y->data, qsize, qtemp, ptemp+psize, pwksp);
|
|
|
|
/* multiply mod p */
|
|
mpbmulmod_w(p, psize, ptemp, psize, ptemp+psize, ptemp, pwksp);
|
|
|
|
/* modulo q */
|
|
mpmod(ptemp+psize, psize, ptemp, qsize, q->modl, pwksp);
|
|
|
|
rc = mpeqx(r->size, r->data, psize, ptemp+psize);
|
|
}
|
|
|
|
free(qtemp);
|
|
free(ptemp);
|
|
|
|
return rc;
|
|
}
|