X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/f790765dca6c9167e27f0db7198f9f3c61fadee8..8b810a45dec25017a6256e4ef134236444a00921:/dsa-sign.c diff --git a/dsa-sign.c b/dsa-sign.c new file mode 100644 index 00000000..8e5c9974 --- /dev/null +++ b/dsa-sign.c @@ -0,0 +1,213 @@ +/* -*-c-*- + * + * $Id: dsa-sign.c,v 1.1 1999/11/19 19:28:00 mdw Exp $ + * + * DSA signing operation + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: dsa-sign.c,v $ + * Revision 1.1 1999/11/19 19:28:00 mdw + * Implementation of the Digital Signature Algorithm. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "dsa.h" +#include "mp.h" +#include "mpmont.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dsa_mksig@ --- * + * + * Arguments: @const dsa_param *dp@ = pointer to DSA parameters + * @const mp *a@ = secret signing key + * @const mp *m@ = message to be signed + * @const mp *k@ = random data + * @mp **rr, **ss@ = where to put output parameters + * + * Returns: --- + * + * Use: Computes a DSA signature of a message. + */ + +void dsa_mksig(const dsa_param *dp, const mp *a, const mp *m, const mp *k, + mp **rr, mp **ss) +{ + mpmont pm, qm; + mp *k1, *r; + mp *rrr, *ar; + + /* --- Create the Montgomery contexts --- */ + + mpmont_create(&pm, dp->p); + mpmont_create(&qm, dp->q); + + /* --- Compute %$r = (g^k \bmod p) \bmod q$% --- */ + + r = mpmont_exp(&pm, dp->g, k); + mp_div(0, &r, r, dp->q); + *rr = r; + + /* --- Compute %$k^{-1} \bmod q$% --- */ + + mp_gcd(0, 0, &k1, dp->q, (mp *)k); + + /* --- Now for %$k^{-1}(m + ar)$% --- */ + + rrr = mpmont_mul(&qm, MP_NEW, r, qm.r2); + ar = mpmont_mul(&qm, MP_NEW, a, rrr); + ar = mp_add(ar, ar, m); + if (MP_CMP(ar, >=, dp->q)) + ar = mp_sub(ar, ar, dp->q); + rrr = mpmont_mul(&qm, rrr, ar, qm.r2); + ar = mpmont_mul(&qm, ar, rrr, k1); + *ss = ar; + + /* --- Tidy things up a little --- */ + + mp_drop(rrr); + mp_drop(k1); + mpmont_destroy(&pm); + mpmont_destroy(&qm); +} + +/* --- @dsa_sign@ --- * + * + * Arguments: @dsa_param *dp@ = pointer to DSA parameters + * @mp *a@ = pointer to secret signing key + * @const void *m@ = pointer to message + * @size_t msz@ = size of the message + * @const void *k@ = secret random data for securing signature + * @size_t ksz@ = size of secret data + * @void *r@ = pointer to output space for @r@ + * @size_t rsz@ = size of output space for @r@ + * @void *s@ = pointer to output space for @s@ + * @size_t ssz@ = size of output space for @s@ + * + * Returns: --- + * + * Use: Signs a message, storing the results in a big-endian binary + * form. + */ + +void dsa_sign(dsa_param *dp, mp *a, + const void *m, size_t msz, const void *k, size_t ksz, + void *r, size_t rsz, void *s, size_t ssz) +{ + mp *mm = mp_loadb(MP_NEW, m, msz); + mp *km = mp_loadb(MP_NEW, k, ksz); + mp *rm, *sm; + dsa_mksig(dp, a, mm, km, &rm, &sm); + mp_storeb(rm, r, rsz); + mp_storeb(sm, s, ssz); + mp_drop(mm); mp_drop(km); + mp_drop(rm); mp_drop(sm); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include + +#include "sha.h" + +static int verify(dstr *v) +{ + dsa_param dp; + mp *x; + sha_ctx c; + octet hash[SHA_HASHSZ]; + dsa_sig s; + int ok = 1; + + dp.q = *(mp **)v[0].buf; + dp.p = *(mp **)v[1].buf; + dp.g = *(mp **)v[2].buf; + x = *(mp **)v[3].buf; + + sha_init(&c); + sha_hash(&c, v[4].buf, v[4].len); + sha_done(&c, hash); + + dsa_sign(&dp, x, hash, sizeof(hash), v[5].buf, v[5].len, + s.r, sizeof(s.r), s.s, sizeof(s.s)); + + if (v[6].len != sizeof(s.r) || v[7].len != sizeof(s.s) || + memcmp(s.r, v[6].buf, sizeof(s.r)) != 0 || + memcmp(s.s, v[7].buf, sizeof(s.s)) != 0) { + fputs("\n*** signature failed", stderr); + fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16); + fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16); + fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16); + fputs("\nx = ", stderr); mp_writefile(x, stderr, 16); + fprintf(stderr, "\nmessage = `%s'", v[4].buf); + fputs("\nk = ", stderr); type_hex.dump(&v[5], stderr); + fputs("\nR = ", stderr); type_hex.dump(&v[6], stderr); + fputs("\nS = ", stderr); type_hex.dump(&v[7], stderr); + + { + mp *m = MP_NEW; + m = mp_loadb(m, hash, sizeof(hash)); + fputs("\nm = ", stderr); mp_writefile(m, stderr, 16); + m = mp_loadb(m, s.r, sizeof(s.r)); + fputs("\nr = ", stderr); mp_writefile(m, stderr, 16); + m = mp_loadb(m, s.s, sizeof(s.s)); + fputs("\ns = ", stderr); mp_writefile(m, stderr, 16); + mp_drop(m); + } + + fputc('\n', stderr); + ok = 0; + } + + mp_drop(dp.p); + mp_drop(dp.q); + mp_drop(dp.g); + mp_drop(x); + return (ok); +} + +static test_chunk tests[] = { + { "sign", verify, + { &type_mp, &type_mp, &type_mp, &type_mp, + &type_string, &type_hex, &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/tests/dsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/