#include #include #include #include #include "pp.h" #include "b64.h" #include "algs.h" #include "pkt-util.h" #define ENCPREF_LEN 15 static const unsigned char encpref[ENCPREF_LEN] = { 0x30, /* universal, constructed, sequence */ 0x21, /* length (33) */ 0x30, /* universal, constructed, sequence */ 0x09, /* length (9) */ 0x06, /* universal, object ID */ 0x05, /* length (5) */ 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* 1.3.14.3.2.26 = id-SHA1 */ 0x05, /* universal, null */ 0x00, /* length (0) */ 0x04, /* universal, octet string */ 0x14, /* length (20) */ }; static HASHALG *hk_ssh_rsa_prehash(void) { extern HASHALG hashalg_sha1; return(&hashalg_sha1); } static int hk_ssh_rsa_checksig(const void *pkdata, int pklen, const void *hash, const void *sig, int siglen) { __label__ parsefail; MP_INT n; MP_INT e; MP_INT s; MP_INT m; MP_INT h; MP_INT tmp1; STR sstr; int nlen; int rv; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&n); mpz_clear(&e); mpz_clear(&s); mpz_clear(&m); mpz_clear(&h); mpz_clear(&tmp1); } if (pklen < 11+4+4) return(0); if (bcmp(pkdata,"\0\0\0\7ssh-rsa",11)) return(0); if (siglen < 11+4) return(0); if (bcmp(sig,"\0\0\0\7ssh-rsa",11)) return(0); mpz_init(&n); mpz_init(&e); mpz_init(&s); mpz_init(&m); mpz_init(&h); mpz_init(&tmp1); parse_data(pkdata,pklen,fail, PP_SKIP(11), PP_MPINT(&e), PP_MPINT(&n), PP_ENDSHERE ); nlen = (mpz_sizeinbase(&n,2) + 7) >> 3; if (nlen < ENCPREF_LEN+20+10+1) return(0); parse_data(sig,siglen,fail, PP_SKIP(11), PP_STRING(&sstr), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } data_to_mpint(&s,sstr.data,sstr.len); if (mpz_cmp(&s,&n) >= 0) fail(0,0); mpz_powm(&m,&s,&e,&n); mpz_set_ui(&h,1); mpz_mul_2exp(&h,&h,((nlen-(ENCPREF_LEN+20+3))*8)+1); mpz_sub_ui(&h,&h,1); mpz_mul_2exp(&h,&h,(ENCPREF_LEN+20+1)*8); data_to_mpint(&tmp1,&encpref[0],ENCPREF_LEN); mpz_mul_2exp(&tmp1,&tmp1,20*8); mpz_add(&h,&h,&tmp1); data_to_mpint(&tmp1,hash,20); mpz_add(&h,&h,&tmp1); rv = (mpz_cmp(&m,&h) == 0); if (! rv) { printf("hk_ssh_rsa_checksig failed:\n"); printf("H(m) ="); { int i; for (i=0;i<20;i++) printf(" %02x",((const unsigned char *)hash)[i]); } printf("\n"); printf("n = "); mpz_out_str(stdout,16,&n); printf("\n"); printf("e = "); mpz_out_str(stdout,16,&e); printf("\n"); printf("s = "); mpz_out_str(stdout,16,&s); printf("\n"); printf("m = "); mpz_out_str(stdout,16,&m); printf("\n"); printf("h = "); mpz_out_str(stdout,16,&h); printf("\n"); } clears(); return(rv); } static int hk_ssh_rsa_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-rsa",11)) { free(b); return(0); } *blobp = b; *lenp = l; return(1); } static int hk_ssh_rsa_read_priv(FILE *f, const void *pubdata, int publen, void **blobp, int *lenp) { __label__ parsefail; void *b; int l; MP_INT n; MP_INT e; MP_INT d; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&n); mpz_clear(&e); mpz_clear(&d); } if ((publen < 11) || bcmp(pubdata,"\0\0\0\7ssh-rsa",11)) return(0); mpz_init(&n); mpz_init(&e); mpz_init(&d); parse_data(pubdata,publen,fail, PP_SKIP(11), PP_MPINT(&e), PP_MPINT(&n), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } if (! b64_read_blob(f,&b,&l)) return(0); data_to_mpint(&d,b,l); if (mpz_cmp(&d,&n) >= 0) { free(b); fail(0,0); } *blobp = b; *lenp = l; clears(); return(1); } static int hk_ssh_rsa_sign(STR *into, const void *pubdata, int publen, const void *privdata, int privlen, const void *hash) { __label__ parsefail; MP_INT n; MP_INT e; MP_INT d; MP_INT s; MP_INT m; MP_INT h; MP_INT tmp1; int nlen; unsigned char *res; unsigned char *rp; int rlen; static void fail(const void *dp __attribute__((__unused__)), const char *fmt __attribute__((__unused__)), ...) { goto parsefail; } static void clears(void) { mpz_clear(&n); mpz_clear(&e); mpz_clear(&d); mpz_clear(&s); mpz_clear(&m); mpz_clear(&h); mpz_clear(&tmp1); } if (publen < 11+4+4) return(0); if (bcmp(pubdata,"\0\0\0\7ssh-rsa",11)) return(0); mpz_init(&n); mpz_init(&e); mpz_init(&d); mpz_init(&s); mpz_init(&m); mpz_init(&h); mpz_init(&tmp1); parse_data(pubdata,publen,fail, PP_SKIP(11), PP_MPINT(&e), PP_MPINT(&n), PP_ENDSHERE ); if (0) { parsefail:; clears(); return(0); } nlen = (mpz_sizeinbase(&n,2) + 7) >> 3; if (nlen < ENCPREF_LEN+20+10+1) fail(0,0); data_to_mpint(&d,privdata,privlen); if (mpz_cmp(&d,&n) >= 0) fail(0,0); mpz_set_ui(&h,1); mpz_mul_2exp(&h,&h,((nlen-(ENCPREF_LEN+20+3))*8)+1); mpz_sub_ui(&h,&h,1); mpz_mul_2exp(&h,&h,(ENCPREF_LEN+20+1)*8); data_to_mpint(&tmp1,&encpref[0],ENCPREF_LEN); mpz_mul_2exp(&tmp1,&tmp1,20*8); mpz_add(&h,&h,&tmp1); data_to_mpint(&tmp1,hash,20); mpz_add(&h,&h,&tmp1); mpz_powm(&m,&h,&d,&n); rlen = 11 + mpint_bytes(&m); res = malloc(rlen); rp = put_string(res,"ssh-rsa",-1); rp = put_mpint(rp,&m); if (rp != res+rlen) abort(); into->data = res; into->len = rlen; clears(); return(1); } HKALG hkalg_ssh_rsa = { "ssh-rsa", 0, 1, &hk_ssh_rsa_prehash, &hk_ssh_rsa_checksig, &hk_ssh_rsa_read_pub, &hk_ssh_rsa_read_priv, &hk_ssh_rsa_sign };