#include #include #include extern const char *__progname; #include "algs.h" typedef struct encstate ENCSTATE; struct encstate { void *algstate; char *buf; int ptr; int fill; } ; #define VFINDFN_ROSTR(lc,uc)\ void *lc##alg_vfind_rostr(ROSTR name) { int i; uc##ALG *a; \ for (i=0;(a=alglist_##lc[i]);i++) if (str_equalcC(name,a->name))\ return(a); return(0); } #define VFINDFN_C(lc,uc)\ void *lc##alg_vfind_c(const char *name) { int i; uc##ALG *a; \ for (i=0;(a=alglist_##lc[i]);i++) if (!strcmp(name,a->name)) \ return(a); return(0); } #define ENUMFN(lc,uc)\ void *lc##alg_enum(int i) { return(alglist_##lc[i]); } #define NAMEFN(lc,uc)\ const char *lc##alg_name(void *a) { return(((uc##ALG *)a)->name); } VFINDFN_C(enc,ENC) VFINDFN_ROSTR(enc,ENC) ENUMFN(enc,ENC) NAMEFN(enc,ENC) void *encalg_init(ENCALG *alg, const void *key, const void *iv, char rw) { void *algstate; ENCSTATE *s; switch (rw) { case 'r': algstate = (*alg->init_dec)(key,iv); break; case 'w': algstate = (*alg->init_enc)(key,iv); break; default: abort(); break; } if (! algstate) return(0); s = malloc(sizeof(ENCSTATE)); if (! s) return(0); s->algstate = algstate; s->buf = malloc(alg->blksize); s->ptr = 0; s->fill = 0; return(s); } void encalg_r(ENCALG *a, void *state, void (*rd)(void *, void *, int), void *cookie, void *buf, int nb) { ENCSTATE *s; int n; s = state; while (nb > 0) { n = s->fill - s->ptr; if (n < 1) { (*rd)(cookie,s->buf,a->blksize); (*a->process)(s->algstate,s->buf,a->blksize); s->fill = a->blksize; s->ptr = 0; n = a->blksize; } if (n >= nb) { bcopy(s->buf+s->ptr,buf,nb); s->ptr += nb; return; } bcopy(s->buf+s->ptr,buf,n); buf = ((char *)buf) + n; nb -= n; s->fill = 0; s->ptr = 0; } } void encalg_w(ENCALG *a, void *state, void (*wr)(void *, const void *, int), void *cookie, const void *buf, int nb) { ENCSTATE *s; int n; const char *bp; s = state; bp = buf; if (s->ptr) { if (s->ptr+nb < a->blksize) { bcopy(bp,s->buf+s->ptr,nb); s->ptr += nb; return; } n = a->blksize - s->ptr; bcopy(bp,s->buf+s->ptr,n); bp += n; nb -= n; (*a->process)(s->algstate,s->buf,a->blksize); (*wr)(cookie,s->buf,a->blksize); s->ptr = 0; } while (nb >= a->blksize) { bcopy(bp,s->buf,a->blksize); (*a->process)(s->algstate,s->buf,a->blksize); (*wr)(cookie,s->buf,a->blksize); bp += a->blksize; nb -= a->blksize; } if (nb > 0) { bcopy(bp,s->buf,nb); s->ptr = nb; } } VFINDFN_C(comp,COMP) VFINDFN_ROSTR(comp,COMP) ENUMFN(comp,COMP) NAMEFN(comp,COMP) void *compalg_init(COMPALG *alg, char rw) { switch (rw) { case 'r': return((*alg->init_decomp)()); break; case 'w': return((*alg->init_comp)()); break; } abort(); } VFINDFN_C(mac,MAC) VFINDFN_ROSTR(mac,MAC) ENUMFN(mac,MAC) NAMEFN(mac,MAC) void *macalg_init(MACALG *alg, const void *key) { return((*alg->init)(key)); } VFINDFN_C(kex,KEX) VFINDFN_ROSTR(kex,KEX) ENUMFN(kex,KEX) NAMEFN(kex,KEX) VFINDFN_C(hk,HK) VFINDFN_ROSTR(hk,HK) ENUMFN(hk,HK) NAMEFN(hk,HK) VFINDFN_C(ua,UA) VFINDFN_ROSTR(ua,UA) ENUMFN(ua,UA) NAMEFN(ua,UA) void alglist_free(ALGLIST *l) { ALGLIST *a; while (l) { a = l; l = l->link; free(a); } }