-#include "rmd160.h"
-#include "rsa.h"
-#include "sha.h"
-
-/*----- Digital signature algorithm ---------------------------------------*/
-
-static int dsasign(key *k, const void *m, size_t msz, dstr *d)
-{
- dsa_priv dp;
- key_packstruct ks[DSA_PRIVFETCHSZ];
- key_packdef *kp;
- size_t sz;
- octet *p;
- int e;
-
- kp = key_fetchinit(dsa_privfetch, ks, &dp);
- if ((e = key_fetch(kp, k)) != 0) {
- key_fetchdone(kp);
- return (e);
- }
- sz = mp_octets(dp.dp.q);
- DENSURE(d, sz * 2);
- p = d->buf + d->len;
- rand_get(RAND_GLOBAL, p, sz);
- dsa_sign(&dp.dp, dp.x, m, msz, p, sz, p, sz, p + sz, sz);
- d->len += sz * 2;
- key_fetchdone(kp);
- return (0);
-}
-
-static int dsaverify(key *k, const void *m, size_t msz,
- const void *s, size_t ssz)
-{
- dsa_pub dp;
- key_packstruct ks[DSA_PUBFETCHSZ];
- key_packdef *kp;
- size_t sz;
- int e;
-
- kp = key_fetchinit(dsa_pubfetch, ks, &dp);
- if ((e = key_fetch(kp, k)) != 0) {
- key_fetchdone(kp);
- return (e);
- }
- sz = ssz / 2;
- e = dsa_verify(&dp.dp, dp.y, m, msz, s, sz, s + sz, sz);
- key_fetchdone(kp);
- return (e);
-}
-
-/*----- RSA signing -------------------------------------------------------*/
-
-static int rsasign(key *k, const void *m, size_t msz, dstr *d)
-{
- rsa_priv rp;
- key_packstruct ks[RSA_PRIVFETCHSZ];
- key_packdef *kp;
- octet *p;
- size_t sz;
- mp *x;
- int e;
-
- kp = key_fetchinit(rsa_privfetch, ks, &rp);
- if ((e = key_fetch(kp, k)) != 0) {
- key_fetchdone(kp);
- return (e);
- }
- sz = mp_octets(rp.n);
- if (sz < msz + 11)
- die(EXIT_FAILURE, "key too small (help!)");
- DENSURE(d, sz);
- p = d->buf + d->len;
- memcpy(p + sz - msz, m, msz);
- p[0] = 0;
- p[1] = 1;
- memset(p + 2, 0xff, sz - msz - 3);
- p[sz - msz - 1] = 0;
- memcpy(p + sz - msz, m, msz);
- x = mp_loadb(MP_NEW, p, sz);
- x = rsa_decrypt(&rp, x, x, &rand_global);
- mp_storeb(x, p, sz);
- d->len += sz;
- mp_drop(x);
- key_fetchdone(kp);
- return (0);
-}
-
-static int rsaverify(key *k, const void *m, size_t msz,
- const void *s, size_t ssz)
-{
- rsa_pub rp;
- key_packstruct ks[RSA_PUBFETCHSZ];
- key_packdef *kp;
- octet *p;
- size_t sz;
- mp *x;
- mpmont mm;
- int ok = 0;
- int e;
- int i;
-
- kp = key_fetchinit(rsa_pubfetch, ks, &rp);
- if ((e = key_fetch(kp, k)) != 0) {
- key_fetchdone(kp);
- return (e);
- }
- x = mp_loadb(MP_NEW, s, ssz);
- mpmont_create(&mm, rp.n);
- x = mpmont_exp(&mm, x, x, rp.e);
- mpmont_destroy(&mm);
- sz = mp_octets(rp.n);
- p = xmalloc(sz);
- mp_storeb(x, p, sz);
- mp_drop(x);
- key_fetchdone(kp);
- if (msz + 11 >= sz || p[0] != 0 || p[1] != 1 || p[sz - msz - 1] != 0)
- goto done;
- for (i = 2; i < sz - msz - 1; i++) {
- if (p[i] != 0xff)
- goto done;
- }
- if (memcmp(m, p + sz - msz, msz) != 0)
- goto done;
- ok = 1;
-done:
- free(p);
- return (ok);
-}
-
-/*----- Algorithm choice --------------------------------------------------*/
-
-typedef struct sig {
- const char *name;
- const char *type;
- int (*sign)(key */*k*/, const void */*m*/, size_t /*msz*/, dstr */*d*/);
- int (*verify)(key */*k*/, const void */*m*/, size_t /*msz*/,
- const void */*s*/, size_t /*ssz*/);
-} sig;
-
-static const gchash *hashtab[] = { &rmd160, &sha, &md5, 0 };
-static sig sigtab[] = {
- { "dsa", "dsig-dsa", dsasign, dsaverify },
- { "rsa", "dsig-rsa", rsasign, rsaverify },
- { 0, 0, 0 }
-};
-
-/* --- @gethash@ --- *
- *
- * Arguments: @const char *name@ = pointer to name string
- *
- * Returns: Pointer to appropriate hash class.
- *
- * Use: Chooses a hash function by name.
- */
-
-static const gchash *gethash(const char *name)
-{
- const gchash **g, *gg = 0;
- size_t sz = strlen(name);
- for (g = hashtab; *g; g++) {
- if (strncmp(name, (*g)->name, sz) == 0) {
- if ((*g)->name[sz] == 0) {
- gg = *g;
- break;
- } else if (gg)
- return (0);
- else
- gg = *g;
- }
- }
- return (gg);
-}
-
-/* --- @getsig@ --- *
- *
- * Arguments: @const char *name@ = pointer to name string
- *
- * Returns: Pointer to appropriate signature type.
- *
- * Use: Chooses a signature algorithm by name.
- */
-
-static sig *getsig(const char *name)
-{
- sig *s, *ss = 0;
- size_t sz = strlen(name);
- for (s = sigtab; s->name; s++) {
- if (strncmp(name, s->name, sz) == 0) {
- if (s->name[sz] == 0) {
- ss = s;
- break;
- } else if (ss)
- return (0);
- else
- ss = s;
- }
- }
- return (ss);
-}