#include #include #include extern const char *__progname; #include "algs.h" typedef struct encstate ENCSTATE; struct encstate { void *algstate; char *buf; int buflen; 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->buflen = alg->blksize; if (s->buflen < 2048) s->buflen = (2048/alg->blksize) * alg->blksize; s->buf = malloc(s->buflen); s->ptr = 0; s->fill = 0; return(s); } int encalg_i(ENCALG *a, void *state, void (*w)(const void *, int), const void *buf, int nb, int want) { ENCSTATE *s; int n; const char *bp; int used; s = state; bp = buf; if (s->ptr) { if (s->ptr+nb < a->blksize) { bcopy(bp,s->buf+s->ptr,nb); s->ptr += nb; return(nb); } n = a->blksize - s->ptr; bcopy(bp,s->buf+s->ptr,n); bp += n; nb -= n; used = n; (*a->process)(s->algstate,s->buf,s->buf,a->blksize); (*w)(s->buf,a->blksize); want -= a->blksize; s->ptr = 0; } else { used = 0; } while ((want > 0) && (nb >= a->blksize)) { n = want + a->blksize - 1; if (n > s->buflen) n = s->buflen; if (n > nb) n = nb; n -= n % a->blksize; if (n < 1) abort(); (*a->process)(s->algstate,bp,s->buf,n); (*w)(s->buf,n); bp += n; nb -= n; used += n; want -= n; } if ((want > 0) && (nb > 0)) { bcopy(bp,s->buf,nb); s->ptr = nb; used += nb; } return(used); } void encalg_o(ENCALG *a, void *state, void (*w)(const void *, int), 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,s->buf,a->blksize); (*w)(s->buf,a->blksize); s->ptr = 0; } while (nb >= a->blksize) { n = s->buflen; if (n > nb) n = nb; n -= n % a->blksize; if (n < 1) abort(); (*a->process)(s->algstate,bp,s->buf,n); (*w)(s->buf,n); bp += n; nb -= n; } 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); } }