#include #include #include #include #include #include "pp.h" #include "b64.h" #include "rnd.h" #include "algs.h" #include "pkt-util.h" static HASHALG *hk_ssh_dss_prehash(void) { extern HASHALG hashalg_sha1; return(&hashalg_sha1); } static int hk_ssh_dss_checksig(const void *pkdata, int pklen, const void *hash, const void *sig, int siglen) { __label__ parsefail; MP_INT p; MP_INT q; MP_INT g; MP_INT y; MP_INT r; MP_INT s; int rv; void *ds; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&p); mpz_clear(&q); mpz_clear(&g); mpz_clear(&y); mpz_clear(&r); mpz_clear(&s); } if (pklen < 11+4+4+4+4) return(0); if (bcmp(pkdata,"\0\0\0\7ssh-dss",11)) return(0); if (siglen != 11+4+40) return(0); if (bcmp(sig,"\0\0\0\7ssh-dss\0\0\0\50",15)) return(0); mpz_init(&p); mpz_init(&q); mpz_init(&g); mpz_init(&y); mpz_init(&r); mpz_init(&s); parse_data(pkdata,pklen,fail, PP_SKIP(11), PP_MPINT(&p), PP_MPINT(&q), PP_MPINT(&g), PP_MPINT(&y), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } data_to_mpint(&r,((const char *)sig)+15,20); data_to_mpint(&s,((const char *)sig)+15+20,20); ds = dsa_init(&p,&q,&g,&y); rv = dsa_verify(ds,hash,&r,&s); dsa_done(ds); if (! rv) { printf("hk_ssh_dss_checksig failed:\n"); printf("H(m) ="); { int i; for (i=0;i<20;i++) printf(" %02x",((const unsigned char *)hash)[i]); } printf("\n"); printf("p = "); mpz_out_str(stdout,16,&p); printf("\n"); printf("q = "); mpz_out_str(stdout,16,&q); printf("\n"); printf("g = "); mpz_out_str(stdout,16,&g); printf("\n"); printf("y = "); mpz_out_str(stdout,16,&y); printf("\n"); printf("r = "); mpz_out_str(stdout,16,&r); printf("\n"); printf("s = "); mpz_out_str(stdout,16,&s); printf("\n"); } clears(); return(rv); } static int hk_ssh_dss_read_pub(FILE *f, void **blobp, int *lenp) { void *b; int l; if (! b64_read_blob(f,&b,&l)) return(0); if ((l < 11) || bcmp(b,"\0\0\0\7ssh-dss",11)) { free(b); return(0); } *blobp = b; *lenp = l; return(1); } static int hk_ssh_dss_read_priv(FILE *f, const void *pubdata, int publen, void **blobp, int *lenp) { __label__ parsefail; MP_INT p; MP_INT q; MP_INT g; MP_INT y; MP_INT x; MP_INT tmp1; void *b; int l; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&p); mpz_clear(&q); mpz_clear(&g); mpz_clear(&y); mpz_clear(&x); mpz_clear(&tmp1); free(b); } if ((publen < 11) || bcmp(pubdata,"\0\0\0\7ssh-dss",11)) return(0); mpz_init(&p); mpz_init(&q); mpz_init(&g); mpz_init(&y); mpz_init(&x); mpz_init(&tmp1); b = 0; parse_data(pubdata,publen,fail, PP_SKIP(11), PP_MPINT(&p), PP_MPINT(&q), PP_MPINT(&g), PP_MPINT(&y), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } if (! b64_read_blob(f,&b,&l)) return(0); if (l != 20) fail(0,0); data_to_mpint(&x,b,l); if (mpz_cmp(&x,&q) >= 0) fail(0,0); mpz_powm(&tmp1,&g,&x,&p); if (mpz_cmp(&tmp1,&y) != 0) fail(0,0); *blobp = b; *lenp = l; b = 0; clears(); return(1); } static int hk_ssh_dss_sign(STR *into, const void *pubdata, int publen, const void *privdata, int privlen, const void *hash) { __label__ parsefail; MP_INT p; MP_INT q; MP_INT g; MP_INT y; MP_INT r; MP_INT s; void *dsa; unsigned char *res; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&p); mpz_clear(&q); mpz_clear(&g); mpz_clear(&y); mpz_clear(&r); mpz_clear(&s); } if (publen < 11+4+4) return(0); if (privlen != 20) return(0); if (bcmp(pubdata,"\0\0\0\7ssh-dss",11)) return(0); mpz_init(&p); mpz_init(&q); mpz_init(&g); mpz_init(&y); mpz_init(&r); mpz_init(&s); parse_data(pubdata,publen,fail, PP_SKIP(11), PP_MPINT(&p), PP_MPINT(&q), PP_MPINT(&g), PP_MPINT(&y), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } dsa = dsa_init(&p,&q,&g,&y); if (! dsa_sign(dsa,hash,privdata,&random_data,&r,&s)) fail(0,0); res = malloc(15+20+20); bcopy("\0\0\0\7ssh-dss\0\0\0\50",res,15); mpint_to_data(&r,res+15,20); mpint_to_data(&s,res+15+20,20); if (mpz_cmp_ui(&r,0) || mpz_cmp_ui(&s,0)) abort(); into->data = res; into->len = 15 + 20 + 20; clears(); if (! hk_ssh_dss_checksig(pubdata,publen,hash,res,15+20+20)) abort(); return(1); } HKALG hkalg_ssh_dss = { "ssh-dss", 0, 1, &hk_ssh_dss_prehash, &hk_ssh_dss_checksig, &hk_ssh_dss_read_pub, &hk_ssh_dss_read_priv, &hk_ssh_dss_sign };