#include #include #include typedef struct state STATE; struct state { MP_INT p; MP_INT q; MP_INT g; MP_INT y; unsigned int yset : 1; } ; static void set_mpz_from_buf(MP_INT *v, const void *buf, int len) { int i; mpz_set_ui(v,0); for (i=0;i=0;i--) { ((unsigned char *)buf)[i] = mpz_get_ui(n) & 0xff; mpz_tdiv_q_2exp(n,n,8); } } void *dsa_init(const MP_INT *p, const MP_INT *q, const MP_INT *g, const MP_INT *y) { STATE *pqgy; if (mpz_sizeinbase(q,2) > 160) return(0); if (y && (mpz_cmp(y,p) >= 0)) return(0); pqgy = malloc(sizeof(STATE)); if (pqgy == 0) return(0); mpz_init_set(&pqgy->p,p); mpz_init_set(&pqgy->q,q); mpz_init_set(&pqgy->g,g); if (y) { mpz_init_set(&pqgy->y,y); pqgy->yset = 1; } else { mpz_init(&pqgy->y); pqgy->yset = 0; } return(pqgy); } void dsa_gen_priv(const void *handle, void (*randomness)(void *, int), void *x) { const STATE *pqgy; MP_INT v; unsigned char vbuf[22]; pqgy = handle; mpz_init(&v); do { (*randomness)(&vbuf[0],22); set_mpz_from_buf(&v,&vbuf[0],22); mpz_mod(&v,&v,&pqgy->q); } while (mpz_cmp_ui(&v,0) <= 0); set_buf_from_mpz(x,20,&v); } int dsa_priv_to_pub(const void *handle, const void *xbuf, MP_INT *y) { const STATE *pqgy; MP_INT x; pqgy = handle; mpz_init(&x); set_mpz_from_buf(&x,xbuf,20); if (mpz_cmp(&x,&pqgy->q) >= 0) { mpz_clear(&x); return(0); } mpz_powm(y,&pqgy->g,&x,&pqgy->p); return(1); } int dsa_set_pub(void *handle, const MP_INT *y) { STATE *pqgy; pqgy = handle; if (y && (mpz_cmp(y,&pqgy->p) >= 0)) return(0); if (y) { mpz_set(&pqgy->y,y); pqgy->yset = 1; } else { pqgy->yset = 0; } return(1); } int dsa_sign(const void *handle, const void *hbuf, const void *xbuf, void (*randomness)(void *, int), MP_INT *r, MP_INT *s) { const STATE *pqgy; MP_INT h; MP_INT x; unsigned char kbuf[22]; MP_INT k; MP_INT kinv; MP_INT tmp1; pqgy = handle; if (! pqgy->yset) return(0); mpz_init(&x); set_mpz_from_buf(&x,xbuf,20); if (mpz_cmp(&x,&pqgy->q) >= 0) { mpz_clear(&x); return(0); } mpz_init(&k); mpz_init(&kinv); mpz_init(&h); mpz_init(&tmp1); set_mpz_from_buf(&h,hbuf,20); while (1) { do { (*randomness)(&kbuf[0],22); set_mpz_from_buf(&k,&kbuf[0],22); mpz_mod(&k,&k,&pqgy->q); } while (mpz_cmp_ui(&k,0) <= 0); if (! mpz_invert(&kinv,&k,&pqgy->q)) { mpz_clear(&tmp1); mpz_clear(&h); mpz_clear(&kinv); mpz_clear(&k); mpz_clear(&x); return(0); } mpz_mod(&kinv,&kinv,&pqgy->q); mpz_powm(&tmp1,&pqgy->g,&k,&pqgy->p); mpz_mod(r,&tmp1,&pqgy->q); if (mpz_cmp_ui(r,0) == 0) continue; mpz_mul(&tmp1,&x,r); mpz_add(&tmp1,&tmp1,&h); mpz_mul(&tmp1,&tmp1,&kinv); mpz_mod(s,&tmp1,&pqgy->q); if (mpz_cmp_ui(s,0) == 0) continue; break; } mpz_clear(&tmp1); mpz_clear(&h); mpz_clear(&kinv); mpz_clear(&k); mpz_clear(&x); return(1); } int dsa_verify(const void *handle, const void *h, const MP_INT *r, const MP_INT *s) { const STATE *pqgy; MP_INT w; MP_INT u1; MP_INT u2; MP_INT v; MP_INT tmp1; int rv; pqgy = handle; mpz_init(&w); if (! mpz_invert(&w,s,&pqgy->q)) { mpz_clear(&w); return(0); } mpz_mod(&w,&w,&pqgy->q); mpz_init(&u1); mpz_init(&u2); mpz_init(&v); mpz_init(&tmp1); set_mpz_from_buf(&u1,h,20); mpz_mul(&u1,&u1,&w); mpz_mod(&u1,&u1,&pqgy->q); mpz_mul(&u2,r,&w); mpz_mod(&u2,&u2,&pqgy->q); mpz_powm(&tmp1,&pqgy->g,&u1,&pqgy->p); mpz_powm(&v,&pqgy->y,&u2,&pqgy->p); mpz_mul(&v,&v,&tmp1); mpz_mod(&v,&v,&pqgy->p); mpz_mod(&v,&v,&pqgy->q); rv = (mpz_cmp(&v,r) == 0); mpz_clear(&w); mpz_clear(&u1); mpz_clear(&u2); mpz_clear(&v); mpz_clear(&tmp1); return(rv); } void dsa_done(void *handle) { STATE *s; s = handle; mpz_clear(&s->p); mpz_clear(&s->q); mpz_clear(&s->g); mpz_clear(&s->y); free(s); }