diff options
| author | forsyth <forsyth@vitanuova.com> | 2010-08-10 23:06:28 +0100 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2010-08-10 23:06:28 +0100 |
| commit | 7de2b42d50e3c05cc143e7b51284009b5e185581 (patch) | |
| tree | 42fffe0c9804551c120ef89c3f505059bbd31cfb | |
| parent | 99c84fef96ccd10bb6cabb823384c033090293e9 (diff) | |
20100810-2306
60 files changed, 2979 insertions, 157 deletions
@@ -1,3 +1,6 @@ +20100810 + initial introduction of crypt-*(2) and ipints(2) + replace keyring.m in module/runt.m by ipints.m and crypt.m; compensate in libinterp and libkeyring by using keyringif.m to generate Keyring's interface 20100802 various changes held back by accident, notably stackv in stack(1), better diagnostics by cat(1) 20100801 diff --git a/appl/cmd/randpass.b b/appl/cmd/randpass.b index 074b21ac..ddfa8e09 100644 --- a/appl/cmd/randpass.b +++ b/appl/cmd/randpass.b @@ -6,9 +6,9 @@ include "sys.m"; include "draw.m"; -include "keyring.m"; - kr : Keyring; - IPint: import kr; +include "ipints.m"; + ipints: IPints; + IPint: import ipints; Randpass: module { @@ -18,7 +18,7 @@ Randpass: module init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - kr = load Keyring Keyring->PATH; + ipints = load IPints IPints->PATH; if(args != nil) args = tl args; @@ -29,11 +29,7 @@ init(nil: ref Draw->Context, args: list of string) raise "fail:usage"; } } - - rbig := IPint.random(pwlen*8, pwlen*16); - rstr := rbig.iptob64(); - - sys->print("%s\n", rstr[0:pwlen]); + sys->print("%s\n", IPint.random(pwlen*8).iptob64()[0: pwlen]); } isnumeric(s: string): int diff --git a/dis/randpass.dis b/dis/randpass.dis Binary files differindex 333f6c04..7ebd35e6 100644 --- a/dis/randpass.dis +++ b/dis/randpass.dis diff --git a/emu/DragonFly/emu b/emu/DragonFly/emu index eb461164..e4fbc42a 100644 --- a/emu/DragonFly/emu +++ b/emu/DragonFly/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/DragonFly/emu-g b/emu/DragonFly/emu-g index 98a1ff89..0667fd62 100644 --- a/emu/DragonFly/emu-g +++ b/emu/DragonFly/emu-g @@ -33,6 +33,8 @@ mod math srv srv keyring + crypt + ipints loader port diff --git a/emu/FreeBSD/emu b/emu/FreeBSD/emu index eb461164..e4fbc42a 100644 --- a/emu/FreeBSD/emu +++ b/emu/FreeBSD/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype @@ -49,6 +49,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/Irix/emu b/emu/Irix/emu index 407b754b..a76441d3 100644 --- a/emu/Irix/emu +++ b/emu/Irix/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/Linux/emu b/emu/Linux/emu index be653b4b..e41ed6ad 100644 --- a/emu/Linux/emu +++ b/emu/Linux/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/Linux/emu-g b/emu/Linux/emu-g index 2ac1e46a..3d45c288 100644 --- a/emu/Linux/emu-g +++ b/emu/Linux/emu-g @@ -37,6 +37,8 @@ mod math srv srv keyring + crypt + ipints loader port diff --git a/emu/Linux/emu-wrt b/emu/Linux/emu-wrt index b53714bb..4f7f6fc6 100644 --- a/emu/Linux/emu-wrt +++ b/emu/Linux/emu-wrt @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader # freetype diff --git a/emu/MacOSX/emu b/emu/MacOSX/emu index 4ace5188..a1a9666f 100644 --- a/emu/MacOSX/emu +++ b/emu/MacOSX/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/MacOSX/emu-g b/emu/MacOSX/emu-g index fc0ff87a..d196f5ce 100644 --- a/emu/MacOSX/emu-g +++ b/emu/MacOSX/emu-g @@ -35,6 +35,8 @@ mod math srv srv keyring + crypt + ipints loader port diff --git a/emu/NetBSD/emu b/emu/NetBSD/emu index eb461164..e4fbc42a 100644 --- a/emu/NetBSD/emu +++ b/emu/NetBSD/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype @@ -49,6 +49,8 @@ mod math srv srv keyring + crypt + ipints loader freetype @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/OpenBSD/emu b/emu/OpenBSD/emu index 93dd36ea..4d9a7d0b 100644 --- a/emu/OpenBSD/emu +++ b/emu/OpenBSD/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/Plan9/emu b/emu/Plan9/emu index 2807c7c5..71390426 100644 --- a/emu/Plan9/emu +++ b/emu/Plan9/emu @@ -49,6 +49,8 @@ mod math # srv not used on Plan 9 keyring + crypt + ipints loader freetype diff --git a/emu/Plan9/emusig b/emu/Plan9/emusig index 1975a4cc..c08bda95 100644 --- a/emu/Plan9/emusig +++ b/emu/Plan9/emusig @@ -39,6 +39,8 @@ mod math # srv not used on Plan 9 keyring + crypt + ipints loader freetype @@ -47,6 +49,8 @@ port cache chan dev + devtab + dial dis discall @@ -74,6 +78,7 @@ init root /dev / /prog / + /prof / /net / /net.alt / /chan / diff --git a/emu/Solaris/emu b/emu/Solaris/emu index a887a102..55705a2b 100644 --- a/emu/Solaris/emu +++ b/emu/Solaris/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/emu/Unixware/emu b/emu/Unixware/emu index 9c92b0a8..92fc91bd 100644 --- a/emu/Unixware/emu +++ b/emu/Unixware/emu @@ -48,6 +48,8 @@ mod math srv srv keyring + crypt + ipints loader freetype diff --git a/include/interp.h b/include/interp.h index 15b7068c..abbe764b 100644 --- a/include/interp.h +++ b/include/interp.h @@ -389,6 +389,7 @@ extern void altgone(Prog*); extern Array* allocimgarray(Heap*, Heap*); extern Module* builtinmod(char*, void*, int); extern void cblock(Prog*); +extern void* checktype(void*, Type*, char*, int); extern void cmovw(void*, void*); extern Channel* cnewc(Type*, void (*)(void), int); extern int compile(Module*, int, Modlink*); @@ -410,12 +411,12 @@ extern void destroyimage(ulong); extern void destroylinks(Module*); extern void destroystack(REG*); extern void drawmodinit(void); +extern Type* dtype(void (*)(Heap*, int), int, uchar*, int); +extern Module* dupmod(Module*); extern int dynldable(int); extern void iqlock(ILock*); extern void iqunlock(ILock*); extern void loadermodinit(void); -extern Type* dtype(void (*)(Heap*, int), int, uchar*, int); -extern Module* dupmod(Module*); extern void error(char*); extern void errorf(char*, ...); extern void extend(void); diff --git a/include/version.h b/include/version.h index e9eae7b8..80208e8e 100644 --- a/include/version.h +++ b/include/version.h @@ -1 +1 @@ -#define VERSION "Fourth Edition (20100802)" +#define VERSION "Fourth Edition (20100810)" diff --git a/libinterp/crypt.c b/libinterp/crypt.c new file mode 100644 index 00000000..998e6d91 --- /dev/null +++ b/libinterp/crypt.c @@ -0,0 +1,1350 @@ +#include "lib9.h" +#include "kernel.h" +#include <isa.h> +#include "interp.h" +#include "runt.h" +#include "cryptmod.h" +#include <mp.h> +#include <libsec.h> +#include "pool.h" +#include "raise.h" +#include "ipint.h" + +#define MPX(x) checkIPint((void*)(x)) + +static Type* TDigestState; +static Type* TAESstate; +static Type* TDESstate; +static Type* TIDEAstate; +static Type* TBFstate; +static Type* TRC4state; + +static Type* TSKdsa; +static Type* TPKdsa; +static Type* TPKsigdsa; +static Type* TSKeg; +static Type* TPKeg; +static Type* TPKsigeg; +static Type* TSKrsa; +static Type* TPKrsa; +static Type* TPKsigrsa; + +static uchar DigestStatemap[] = Crypt_DigestState_map; +static uchar AESstatemap[] = Crypt_AESstate_map; +static uchar DESstatemap[] = Crypt_DESstate_map; +static uchar IDEAstatemap[] = Crypt_IDEAstate_map; +static uchar BFstatemap[] = Crypt_BFstate_map; +static uchar RC4statemap[] = Crypt_RC4state_map; + +static uchar DSAskmap[] = Crypt_SK_DSA_map; +static uchar DSApkmap[] = Crypt_PK_DSA_map; +static uchar DSAsigmap[] = Crypt_PKsig_DSA_map; +static uchar EGskmap[] = Crypt_SK_Elgamal_map; +static uchar EGpkmap[] = Crypt_PK_Elgamal_map; +static uchar EGsigmap[] = Crypt_PKsig_Elgamal_map; +static uchar RSAskmap[] = Crypt_SK_RSA_map; +static uchar RSApkmap[] = Crypt_PK_RSA_map; +static uchar RSAsigmap[] = Crypt_PKsig_RSA_map; + +static char exBadSK[] = "bad secret key"; +static char exBadPK[] = "bad public key"; +static char exBadBsize[] = "data not multiple of block size"; +static char exBadKey[] = "bad encryption key"; +static char exBadDigest[] = "bad digest value"; +static char exBadIvec[] = "bad ivec"; +static char exBadState[] = "bad encryption state"; + +/* + * these structures reveal the C state of Limbo adts in crypt.m + */ + +typedef struct XDigestState XDigestState; +typedef struct XAESstate XAESstate; +typedef struct XDESstate XDESstate; +typedef struct XIDEAstate XIDEAstate; +typedef struct XBFstate XBFstate; +typedef struct XRC4state XRC4state; + +/* digest state */ +struct XDigestState +{ + Crypt_DigestState x; + DigestState state; +}; + +/* AES state */ +struct XAESstate +{ + Crypt_AESstate x; + AESstate state; +}; + +/* DES state */ +struct XDESstate +{ + Crypt_DESstate x; + DESstate state; +}; + +/* IDEA state */ +struct XIDEAstate +{ + Crypt_IDEAstate x; + IDEAstate state; +}; + +/* BF state */ +struct XBFstate +{ + Crypt_BFstate x; + BFstate state; +}; + +/* RC4 state */ +struct XRC4state +{ + Crypt_RC4state x; + RC4state state; +}; + +static Crypt_PK* +newPK(Type *t, int pick) +{ + Heap *h; + Crypt_PK *sk; + + h = heap(t); + sk = H2D(Crypt_PK*, h); + sk->pick = pick; + return sk; +} + +static Crypt_SK* +newSK(Crypt_SK** ret, Type *t, int pick) +{ + Heap *h; + Crypt_SK *sk; + + h = heap(t); + sk = H2D(Crypt_SK*, h); + sk->pick = pick; + if(ret != nil) + *ret = sk; + switch(pick){ + case Crypt_PK_RSA: + sk->u.RSA.pk = newPK(TPKrsa, Crypt_PK_RSA); + break; + case Crypt_PK_Elgamal: + sk->u.Elgamal.pk = newPK(TPKeg, Crypt_PK_Elgamal); + break; + case Crypt_PK_DSA: + sk->u.DSA.pk = newPK(TPKdsa, Crypt_PK_DSA); + break; + default: + error(exType); + } + return sk; +} + +static Crypt_PKsig* +newPKsig(Type *t, int pick) +{ + Heap *h; + Crypt_PKsig *s; + + h = heap(t); + s = H2D(Crypt_PKsig*, h); + s->pick = pick; + return s; +} + +static IPints_IPint* +ipcopymp(mpint* b) +{ + if(b == nil) + return H; + return newIPint(mpcopy(b)); +} + +/* + * digests + */ +void +DigestState_copy(void *fp) +{ + F_DigestState_copy *f; + Heap *h; + XDigestState *ds, *ods; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + if(f->d != H){ + ods = checktype(f->d, TDigestState, "DigestState", 0); + h = heap(TDigestState); + ds = H2D(XDigestState*, h); + memmove(&ds->state, &ods->state, sizeof(ds->state)); + *f->ret = (Crypt_DigestState*)ds; + } +} + +static Crypt_DigestState* +crypt_digest_x(Array *buf, int n, Array *digest, int dlen, Crypt_DigestState *state, DigestState* (*fn)(uchar*, ulong, uchar*, DigestState*)) +{ + Heap *h; + XDigestState *ds; + uchar *cbuf, *cdigest; + + if(buf != H){ + if(n > buf->len) + n = buf->len; + cbuf = buf->data; + }else{ + if(n != 0) + error(exInval); + cbuf = nil; + } + + if(digest != H){ + if(digest->len < dlen) + error(exBadDigest); + cdigest = digest->data; + } else + cdigest = nil; + + if(state == H){ + h = heap(TDigestState); + ds = H2D(XDigestState*, h); + memset(&ds->state, 0, sizeof(ds->state)); + } else + ds = checktype(state, TDigestState, "DigestState", 1); + + (*fn)(cbuf, n, cdigest, &ds->state); + + return (Crypt_DigestState*)ds; +} + +void +Crypt_sha1(void *fp) +{ + F_Crypt_sha1 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, SHA1dlen, f->state, sha1); +} + +void +Crypt_sha224(void *fp) +{ + F_Crypt_sha224 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, SHA224dlen, f->state, sha224); +} + +void +Crypt_sha256(void *fp) +{ + F_Crypt_sha256 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, SHA256dlen, f->state, sha256); +} + +void +Crypt_sha384(void *fp) +{ + F_Crypt_sha384 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, SHA384dlen, f->state, sha384); +} + +void +Crypt_sha512(void *fp) +{ + F_Crypt_sha512 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, SHA512dlen, f->state, sha512); +} + +void +Crypt_md5(void *fp) +{ + F_Crypt_md5 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, MD5dlen, f->state, md5); +} + +void +Crypt_md4(void *fp) +{ + F_Crypt_md4 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + + *f->ret = crypt_digest_x(f->buf, f->n, f->digest, MD4dlen, f->state, md4); +} + +static Crypt_DigestState* +crypt_hmac_x(Array *data, int n, Array *key, Array *digest, int dlen, Crypt_DigestState *state, DigestState* (*fn)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*)) +{ + Heap *h; + XDigestState *ds; + uchar *cdata, *cdigest; + + if(data != H){ + if(n > data->len) + n = data->len; + cdata = data->data; + }else{ + if(n != 0) + error(exInval); + cdata = nil; + } + + if(key == H || key->len > 64) + error(exBadKey); + + if(digest != H){ + if(digest->len < dlen) + error(exBadDigest); + cdigest = digest->data; + } else + cdigest = nil; + + if(state == H){ + h = heap(TDigestState); + ds = H2D(XDigestState*, h); + memset(&ds->state, 0, sizeof(ds->state)); + } else + ds = checktype(state, TDigestState, "DigestState", 1); + + (*fn)(cdata, n, key->data, key->len, cdigest, &ds->state); + + return (Crypt_DigestState*)ds; +} + +void +Crypt_hmac_sha1(void *fp) +{ + F_Crypt_hmac_sha1 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + *f->ret = crypt_hmac_x(f->data, f->n, f->key, f->digest, SHA1dlen, f->state, hmac_sha1); +} + +void +Crypt_hmac_md5(void *fp) +{ + F_Crypt_hmac_md5 *f; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + *f->ret = crypt_hmac_x(f->data, f->n, f->key, f->digest, MD5dlen, f->state, hmac_md5); +} + +void +Crypt_dhparams(void *fp) +{ + F_Crypt_dhparams *f; + mpint *p, *alpha; + void *v; + + f = fp; + v = f->ret->t0; + f->ret->t0 = H; + destroy(v); + v = f->ret->t1; + f->ret->t1 = H; + destroy(v); + + p = mpnew(0); + alpha = mpnew(0); + release(); + if(f->nbits == 1024) + DSAprimes(alpha, p, nil); + else + gensafeprime(p, alpha, f->nbits, 0); + acquire(); + f->ret->t0 = newIPint(alpha); + f->ret->t1 = newIPint(p); +} + +void +cryptmodinit(void) +{ + ipintsmodinit(); /* TIPint */ + + TDigestState = dtype(freeheap, sizeof(XDigestState), DigestStatemap, sizeof(DigestStatemap)); + TAESstate = dtype(freeheap, sizeof(XAESstate), AESstatemap, sizeof(AESstatemap)); + TDESstate = dtype(freeheap, sizeof(XDESstate), DESstatemap, sizeof(DESstatemap)); + TIDEAstate = dtype(freeheap, sizeof(XIDEAstate), IDEAstatemap, sizeof(IDEAstatemap)); + TBFstate = dtype(freeheap, sizeof(XBFstate), BFstatemap, sizeof(BFstatemap)); + TRC4state = dtype(freeheap, sizeof(XRC4state), RC4statemap, sizeof(RC4statemap)); + + TSKdsa = dtype(freeheap, Crypt_SK_DSA_size, DSAskmap, sizeof(DSAskmap)); + TPKdsa = dtype(freeheap, Crypt_PK_DSA_size, DSApkmap, sizeof(DSApkmap)); + TPKsigdsa = dtype(freeheap, Crypt_PKsig_DSA_size, DSAsigmap, sizeof(DSAsigmap)); + TSKeg = dtype(freeheap, Crypt_SK_Elgamal_size, EGskmap, sizeof(EGskmap)); + TPKeg = dtype(freeheap, Crypt_PK_Elgamal_size, EGpkmap, sizeof(EGpkmap)); + TPKsigeg = dtype(freeheap, Crypt_PKsig_Elgamal_size, EGsigmap, sizeof(EGsigmap)); + TSKrsa = dtype(freeheap, Crypt_SK_RSA_size, RSAskmap, sizeof(RSAskmap)); + TPKrsa = dtype(freeheap, Crypt_PK_RSA_size, RSApkmap, sizeof(RSApkmap)); + TPKsigrsa = dtype(freeheap, Crypt_PKsig_RSA_size, RSAsigmap, sizeof(RSAsigmap)); + + builtinmod("$Crypt", Cryptmodtab, Cryptmodlen); +} + +void +Crypt_dessetup(void *fp) +{ + F_Crypt_dessetup *f; + Heap *h; + XDESstate *ds; + uchar *ivec; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->key == H) + error(exNilref); + if(f->key->len < 8) + error(exBadKey); + if(f->ivec != H){ + if(f->ivec->len < 8) + error(exBadIvec); + ivec = f->ivec->data; + }else + ivec = nil; + + h = heap(TDESstate); + ds = H2D(XDESstate*, h); + setupDESstate(&ds->state, f->key->data, ivec); + + *f->ret = (Crypt_DESstate*)ds; +} + +void +Crypt_desecb(void *fp) +{ + F_Crypt_desecb *f; + XDESstate *ds; + int i; + uchar *p; + + f = fp; + + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + if(f->n & 7) + error(exBadBsize); + + ds = checktype(f->state, TDESstate, exBadState, 0); + p = f->buf->data; + + for(i = 8; i <= f->n; i += 8, p += 8) + block_cipher(ds->state.expanded, p, f->direction); +} + +void +Crypt_descbc(void *fp) +{ + F_Crypt_descbc *f; + XDESstate *ds; + uchar *p, *ep, *ip, *p2, *eip; + uchar tmp[8]; + + f = fp; + + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + if(f->n & 7) + error(exBadBsize); + + ds = checktype(f->state, TDESstate, exBadState, 0); + p = f->buf->data; + + if(f->direction == 0){ + for(ep = p + f->n; p < ep; p += 8){ + p2 = p; + ip = ds->state.ivec; + for(eip = ip+8; ip < eip; ) + *p2++ ^= *ip++; + block_cipher(ds->state.expanded, p, 0); + memmove(ds->state.ivec, p, 8); + } + } else { + for(ep = p + f->n; p < ep; ){ + memmove(tmp, p, 8); + block_cipher(ds->state.expanded, p, 1); + p2 = tmp; + ip = ds->state.ivec; + for(eip = ip+8; ip < eip; ){ + *p++ ^= *ip; + *ip++ = *p2++; + } + } + } +} + +void +Crypt_ideasetup(void *fp) +{ + F_Crypt_ideasetup *f; + Heap *h; + XIDEAstate *is; + uchar *ivec; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->key == H) + error(exNilref); + if(f->key->len < 16) + error(exBadKey); + if(f->ivec != H){ + if(f->ivec->len < 8) + error(exBadIvec); + ivec = f->ivec->data; + }else + ivec = nil; + + h = heap(TIDEAstate); + is = H2D(XIDEAstate*, h); + + setupIDEAstate(&is->state, f->key->data, ivec); + + *f->ret = (Crypt_IDEAstate*)is; +} + +void +Crypt_ideaecb(void *fp) +{ + F_Crypt_ideaecb *f; + XIDEAstate *is; + int i; + uchar *p; + + f = fp; + + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + if(f->n & 7) + error(exBadBsize); + + is = checktype(f->state, TIDEAstate, exBadState, 0); + p = f->buf->data; + + for(i = 8; i <= f->n; i += 8, p += 8) + idea_cipher(is->state.edkey, p, f->direction); +} + +void +Crypt_ideacbc(void *fp) +{ + F_Crypt_ideacbc *f; + XIDEAstate *is; + uchar *p, *ep, *ip, *p2, *eip; + uchar tmp[8]; + + f = fp; + + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + if(f->n & 7) + error(exBadBsize); + + is = checktype(f->state, TIDEAstate, exBadState, 0); + p = f->buf->data; + + if(f->direction == 0){ + for(ep = p + f->n; p < ep; p += 8){ + p2 = p; + ip = is->state.ivec; + for(eip = ip+8; ip < eip; ) + *p2++ ^= *ip++; + idea_cipher(is->state.edkey, p, 0); + memmove(is->state.ivec, p, 8); + } + } else { + for(ep = p + f->n; p < ep; ){ + memmove(tmp, p, 8); + idea_cipher(is->state.edkey, p, 1); + p2 = tmp; + ip = is->state.ivec; + for(eip = ip+8; ip < eip; ){ + *p++ ^= *ip; + *ip++ = *p2++; + } + } + } +} + +void +Crypt_aessetup(void *fp) +{ + F_Crypt_aessetup *f; + Heap *h; + XAESstate *is; + uchar *ivec; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->key == H) + error(exNilref); + if(f->key->len != 16 && f->key->len != 24 && f->key->len != 32) + error(exBadKey); + if(f->ivec != H){ + if(f->ivec->len < AESbsize) + error(exBadIvec); + ivec = f->ivec->data; + }else + ivec = nil; + + h = heap(TAESstate); + is = H2D(XAESstate*, h); + + setupAESstate(&is->state, f->key->data, f->key->len, ivec); + + *f->ret = (Crypt_AESstate*)is; +} + +void +Crypt_aescbc(void *fp) +{ + F_Crypt_aescbc *f; + XAESstate *is; + uchar *p; + + f = fp; + + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + + is = checktype(f->state, TAESstate, exBadState, 0); + p = f->buf->data; + + if(f->direction == 0) + aesCBCencrypt(p, f->n, &is->state); + else + aesCBCdecrypt(p, f->n, &is->state); +} + +void +Crypt_blowfishsetup(void *fp) +{ + F_Crypt_blowfishsetup *f; + Heap *h; + XBFstate *is; + uchar *ivec; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->key == H) + error(exNilref); + if(f->key->len <= 0) + error(exBadKey); + if(f->ivec != H){ + if(f->ivec->len != BFbsize) + error(exBadIvec); + ivec = f->ivec->data; + }else + ivec = nil; + + h = heap(TBFstate); + is = H2D(XBFstate*, h); + + setupBFstate(&is->state, f->key->data, f->key->len, ivec); + + *f->ret = (Crypt_BFstate*)is; +} + +void +Crypt_blowfishcbc(void *fp) +{ + F_Crypt_blowfishcbc *f; + XBFstate *is; + uchar *p; + + f = fp; + + if(f->state == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + if(f->n & 7) + error(exBadBsize); + + is = checktype(f->state, TBFstate, exBadState, 0); + p = f->buf->data; + + if(f->direction == 0) + bfCBCencrypt(p, f->n, &is->state); + else + bfCBCdecrypt(p, f->n, &is->state); +} + +void +Crypt_rc4setup(void *fp) +{ + F_Crypt_rc4setup *f; + Heap *h; + XRC4state *is; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->seed == H) + error(exNilref); + + h = heap(TRC4state); + is = H2D(XRC4state*, h); + + setupRC4state(&is->state, f->seed->data, f->seed->len); + + *f->ret = (Crypt_RC4state*)is; +} + +void +Crypt_rc4(void *fp) +{ + F_Crypt_rc4 *f; + XRC4state *is; + uchar *p; + + f = fp; + if(f->buf == H) + return; + if(f->n < 0 || f->n > f->buf->len) + error(exBounds); + is = checktype(f->state, TRC4state, exBadState, 0); + p = f->buf->data; + rc4(&is->state, p, f->n); +} + +void +Crypt_rc4skip(void *fp) +{ + F_Crypt_rc4skip *f; + XRC4state *is; + + f = fp; + is = checktype(f->state, TRC4state, exBadState, 0); + rc4skip(&is->state, f->n); +} + +void +Crypt_rc4back(void *fp) +{ + F_Crypt_rc4back *f; + XRC4state *is; + + f = fp; + is = checktype(f->state, TRC4state, exBadState, 0); + rc4back(&is->state, f->n); +} + +/* + * public/secret keys, signing and verifying + */ + +/* + * DSA + */ + +static void +dsapk2pub(DSApub* p, Crypt_PK* pk) +{ + if(pk == H) + error(exNilref); + if(pk->pick != Crypt_PK_DSA) + error(exType); + p->p = MPX(pk->u.DSA.p); + p->q = MPX(pk->u.DSA.q); + p->alpha = MPX(pk->u.DSA.alpha); + p->key = MPX(pk->u.DSA.key); +} + +static void +dsask2priv(DSApriv* p, Crypt_SK* sk) +{ + if(sk == H) + error(exNilref); + if(sk->pick != Crypt_SK_DSA) + error(exType); + dsapk2pub(&p->pub, sk->u.DSA.pk); + p->secret = MPX(sk->u.DSA.secret); +} + +static void +dsapriv2sk(Crypt_SK* sk, DSApriv* p) +{ + Crypt_PK *pk; + + pk = sk->u.DSA.pk; + pk->u.DSA.p = ipcopymp(p->pub.p); + pk->u.DSA.q = ipcopymp(p->pub.q); + pk->u.DSA.alpha = ipcopymp(p->pub.alpha); + pk->u.DSA.key = ipcopymp(p->pub.key); + sk->u.DSA.secret = ipcopymp(p->secret); +} + +static void +dsaxgen(Crypt_SK* sk, DSApub* oldpk) +{ + DSApriv *p; + + release(); + p = dsagen(oldpk); + acquire(); + dsapriv2sk(sk, p); + dsaprivfree(p); +} + +void +Crypt_dsagen(void *fp) +{ + F_Crypt_dsagen *f; + Crypt_SK *sk; + DSApub pub, *oldpk; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + sk = newSK(f->ret, TSKdsa, Crypt_SK_DSA); + oldpk = nil; + if(f->oldpk != H && f->oldpk->pick == Crypt_PK_DSA){ + dsapk2pub(&pub, f->oldpk); + oldpk = &pub; + } + dsaxgen(sk, oldpk); +} + +/* + * Elgamal + */ + +static void +egpk2pub(EGpub* p, Crypt_PK* pk) +{ + if(pk == H) + error(exNilref); + if(pk->pick != Crypt_PK_Elgamal) + error(exType); + p->p = MPX(pk->u.Elgamal.p); + p->alpha = MPX(pk->u.Elgamal.alpha); + p->key = MPX(pk->u.Elgamal.key); +} + +static void +egsk2priv(EGpriv* p, Crypt_SK* sk) +{ + if(sk == H) + error(exNilref); + if(sk->pick != Crypt_SK_Elgamal) + error(exType); + egpk2pub(&p->pub, sk->u.Elgamal.pk); + p->secret = MPX(sk->u.Elgamal.secret); +} + +static void +egpriv2sk(Crypt_SK* sk, EGpriv* p) +{ + Crypt_PK* pk; + + pk = sk->u.Elgamal.pk; + pk->u.Elgamal.p = ipcopymp(p->pub.p); + pk->u.Elgamal.alpha = ipcopymp(p->pub.alpha); + pk->u.Elgamal.key = ipcopymp(p->pub.key); + sk->u.Elgamal.secret = ipcopymp(p->secret); +} + +static void +egxgen(Crypt_SK* sk, int nlen, int nrep) +{ + EGpriv *p; + + release(); + for(;;){ + p = eggen(nlen, nrep); + if(mpsignif(p->pub.p) == nlen) + break; + egprivfree(p); + } + acquire(); + egpriv2sk(sk, p); + egprivfree(p); +} + + +void +Crypt_eggen(void *fp) +{ + F_Crypt_eggen *f; + Crypt_SK *sk; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + sk = newSK(f->ret, TSKeg, Crypt_SK_Elgamal); + egxgen(sk, f->nlen, f->nrep); +} + +/* + * RSA + */ + +static void +rsapk2pub(RSApub* p, Crypt_PK* pk) +{ + if(pk == H) + error(exNilref); + if(pk->pick != Crypt_PK_RSA) + error(exType); + p->n = MPX(pk->u.RSA.n); + p->ek = MPX(pk->u.RSA.ek); +} + +static void +rsask2priv(RSApriv* p, Crypt_SK* sk) +{ + if(sk == H) + error(exNilref); + if(sk->pick != Crypt_SK_RSA) + error(exType); + rsapk2pub(&p->pub, sk->u.RSA.pk); + p->dk = MPX(sk->u.RSA.dk); + p->p = MPX(sk->u.RSA.p); + p->q = MPX(sk->u.RSA.q); + p->kp = MPX(sk->u.RSA.kp); + p->kq = MPX(sk->u.RSA.kq); + p->c2 = MPX(sk->u.RSA.c2); +} + +static void +rsapriv2sk(Crypt_SK* sk, RSApriv* p) +{ + Crypt_PK *pk; + + pk = sk->u.RSA.pk; + pk->u.RSA.n = ipcopymp(p->pub.n); + pk->u.RSA.ek = ipcopymp(p->pub.ek); + sk->u.RSA.dk = ipcopymp(p->dk); + sk->u.RSA.p = ipcopymp(p->p); + sk->u.RSA.q = ipcopymp(p->q); + sk->u.RSA.kp = ipcopymp(p->kp); + sk->u.RSA.kq = ipcopymp(p->kq); + sk->u.RSA.c2 = ipcopymp(p->c2); +} + +static void +rsaxgen(Crypt_SK *sk, int nlen, int elen, int nrep) +{ + RSApriv *p; + + release(); + for(;;){ + p = rsagen(nlen, elen, nrep); + if(mpsignif(p->pub.n) == nlen) + break; + rsaprivfree(p); + } + acquire(); + rsapriv2sk(sk, p); + rsaprivfree(p); +} + +void +Crypt_rsagen(void *fp) +{ + F_Crypt_rsagen *f; + Crypt_SK *sk; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + sk = newSK(f->ret, TSKrsa, Crypt_SK_RSA); + rsaxgen(sk, f->nlen, f->elen, f->nrep); +} + +void +Crypt_rsafill(void *fp) +{ + F_Crypt_rsafill *f; + Crypt_SK *sk; + RSApriv *p; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + sk = newSK(f->ret, TSKrsa, Crypt_SK_RSA); + release(); + p = rsafill(MPX(f->n), MPX(f->ek), MPX(f->dk), + MPX(f->p), MPX(f->q)); + acquire(); + if(p == nil) { + *f->ret = H; + destroy(sk); + }else{ + rsapriv2sk(sk, p); + rsaprivfree(p); + } +} + +void +Crypt_rsaencrypt(void *fp) +{ + F_Crypt_rsaencrypt *f; + RSApub p; + mpint *m, *o; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + rsapk2pub(&p, f->k); + m = MPX(f->m); + release(); + o = rsaencrypt(&p, m, nil); + acquire(); + *f->ret = newIPint(o); +} + +void +Crypt_rsadecrypt(void *fp) +{ + F_Crypt_rsadecrypt *f; + RSApriv p; + mpint *m, *o; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + rsask2priv(&p, f->k); + m = MPX(f->m); + release(); + o = rsadecrypt(&p, m, nil); + acquire(); + *f->ret = newIPint(o); +} + +/* + * generic key functions + */ + +void +Crypt_genSK(void *fp) +{ + F_Crypt_genSK *f; + Crypt_SK *sk; + char *sa; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + sa = string2c(f->algname); + if(strcmp(sa, "rsa") == 0){ + sk = newSK(f->ret, TSKrsa, Crypt_SK_RSA); + rsaxgen(sk, f->length, 6, 0); + }else if(strcmp(sa, "dsa") == 0){ + sk = newSK(f->ret, TSKdsa, Crypt_SK_DSA); + dsaxgen(sk, nil); + }else if(strcmp(sa, "elgamal") == 0){ + sk = newSK(f->ret, TSKeg, Crypt_SK_Elgamal); + egxgen(sk, f->length, 0); + } + /* genSK returns nil for unknown algorithm */ +} + +void +Crypt_genSKfromPK(void *fp) +{ + F_Crypt_genSKfromPK *f; + Crypt_SK *sk; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->pk == H) + error(exNilref); + switch(f->pk->pick){ + case Crypt_PK_RSA: { + RSApub p; + + rsapk2pub(&p, f->pk); + sk = newSK(f->ret, TSKrsa, Crypt_SK_RSA); + rsaxgen(sk, mpsignif(p.n), mpsignif(p.ek), 0); + } + break; + case Crypt_PK_Elgamal: { + EGpub p; + + egpk2pub(&p, f->pk); + sk = newSK(f->ret, TSKeg, Crypt_SK_Elgamal); + egxgen(sk, mpsignif(p.p), 0); + } + break; + case Crypt_PK_DSA: { + DSApub p; + + dsapk2pub(&p, f->pk); + sk = newSK(f->ret, TSKdsa, Crypt_SK_DSA); + dsaxgen(sk, &p); + } + break; + default: + /* shouldn't happen */ + error(exType); + } +} + +void +Crypt_sktopk(void *fp) +{ + F_Crypt_sktopk *f; + Crypt_PK *pk; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + if(f->sk == H) + error(exNilref); + switch(f->sk->pick){ + case Crypt_PK_RSA: + pk = f->sk->u.RSA.pk; + break; + case Crypt_PK_Elgamal: + pk = f->sk->u.Elgamal.pk; + break; + case Crypt_PK_DSA: + pk = f->sk->u.DSA.pk; + break; + default: + pk = H; + error(exType); + } + if(pk == H) + return; + D2H(pk)->ref++; + *f->ret = pk; +} + +void +Crypt_sign(void *fp) +{ + F_Crypt_sign *f; + Crypt_PKsig *sig; + mpint *m; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + if(f->m == H || f->sk == H) + error(exNilref); + m = MPX(f->m); + switch(f->sk->pick){ + case Crypt_SK_RSA: { + RSApriv p; + mpint *s; + + rsask2priv(&p, f->sk); + release(); + s = rsadecrypt(&p, m, nil); + acquire(); + sig = newPKsig(TPKsigrsa, Crypt_PKsig_RSA); + sig->u.RSA.n = newIPint(s); + } + break; + case Crypt_SK_Elgamal: { + EGpriv p; + EGsig *s; + + egsk2priv(&p, f->sk); + release(); + s = egsign(&p, m); + acquire(); + sig = newPKsig(TPKsigeg, Crypt_PKsig_Elgamal); + sig->u.Elgamal.r = ipcopymp(s->r); + sig->u.Elgamal.s = ipcopymp(s->s); + egsigfree(s); + } + break; + case Crypt_SK_DSA: { + DSApriv p; + DSAsig *s; + + dsask2priv(&p, f->sk); + m = MPX(f->m); + release(); + s = dsasign(&p, m); + acquire(); + sig = newPKsig(TPKsigdsa, Crypt_PKsig_DSA); + sig->u.DSA.r = ipcopymp(s->r); + sig->u.DSA.s = ipcopymp(s->s); + dsasigfree(s); + } + break; + default: + sig = H; + error(exType); + } + *f->ret = sig; +} + +void +Crypt_verify(void *fp) +{ + F_Crypt_verify *f; + mpint *m; + + f = fp; + *f->ret = 0; + if(f->sig == H || f->pk == H) + error(exNilref); + if(f->sig->pick != f->pk->pick) + return; /* key type and signature mismatch, doesn't validate */ + m = MPX(f->m); + switch(f->pk->pick){ + case Crypt_PK_RSA: { + RSApub p; + mpint *sig, *t; + + rsapk2pub(&p, f->pk); + sig = MPX(f->sig->u.RSA.n); + release(); + t = rsaencrypt(&p, sig, nil); + *f->ret = mpcmp(t, m) == 0; + mpfree(t); + acquire(); + } + break; + case Crypt_PK_Elgamal: { + EGpub p; + EGsig sig; + + egpk2pub(&p, f->pk); + sig.r = MPX(f->sig->u.Elgamal.r); + sig.s = MPX(f->sig->u.Elgamal.s); + release(); + *f->ret = egverify(&p, &sig, m) == 0; + acquire(); + } + break; + case Crypt_PK_DSA: { + DSApub p; + DSAsig sig; + + dsapk2pub(&p, f->pk); + sig.r = MPX(f->sig->u.DSA.r); + sig.s = MPX(f->sig->u.DSA.s); + release(); + *f->ret = dsaverify(&p, &sig, m) == 0; + acquire(); + } + break; + default: + error(exType); + } +} diff --git a/libinterp/heap.c b/libinterp/heap.c index 5eff79a5..1ac715f7 100644 --- a/libinterp/heap.c +++ b/libinterp/heap.c @@ -237,6 +237,40 @@ destroy(void *v) poolfree(heapmem, h); } +Type* +dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize) +{ + Type *t; + + t = malloc(sizeof(Type)+mapsize); + if(t != nil) { + t->ref = 1; + t->free = destroy; + t->mark = markheap; + t->size = size; + t->np = mapsize; + memmove(t->map, map, mapsize); + } + return t; +} + +void* +checktype(void *v, Type *t, char *name, int newref) +{ + Heap *h; + + if(v == H || v == nil) + error(exNilref); + h = D2H(v); + if(t == nil || h->t != t) + errorf("%s: %s", exType, name); + if(newref){ + h->ref++; + Setmark(h); + } + return v; +} + void freetype(Type *t) { diff --git a/libinterp/ipint.c b/libinterp/ipint.c index b4967843..5728420c 100644 --- a/libinterp/ipint.c +++ b/libinterp/ipint.c @@ -6,13 +6,39 @@ #include <mp.h> #include <libsec.h> #include "pool.h" -#include "../libkeyring/keys.h" +#include "ipint.h" #include "raise.h" -extern Type *TIPint; +#include "ipintsmod.h" + +enum +{ + MaxBigBytes = 1024 +}; + +/* infinite precision integer */ +struct IPint +{ + IPints_IPint x; + mpint* b; +}; + +Type *TIPint; +static uchar IPintmap[] = IPints_IPint_map; + #define MP(x) checkIPint((x)) -Keyring_IPint* +void +ipintsmodinit(void) +{ + /* can be called from modinit, Keyring or Crypt */ + if(TIPint == nil) + TIPint = dtype(freeIPint, sizeof(IPint), IPintmap, sizeof(IPintmap)); + builtinmod("$IPints", IPintsmodtab, IPintsmodlen); +} + +//IPints_IPint* +void* newIPint(mpint* b) { Heap *h; @@ -23,20 +49,22 @@ newIPint(mpint* b) h = heap(TIPint); /* TO DO: caller might lose other values if heap raises error here */ ip = H2D(IPint*, h); ip->b = b; - return (Keyring_IPint*)ip; + return (IPints_IPint*)ip; } mpint* -checkIPint(Keyring_IPint *v) +checkIPint(void *a) { + IPints_IPint *v; IPint *ip; + v = a; ip = (IPint*)v; if(ip == H || ip == nil) error(exNilref); if(D2H(ip)->t != TIPint) error(exType); - return ip->b; + return ip->b; /* non-nil by construction */ } void @@ -151,7 +179,7 @@ IPint_iptostr(void *fp) retstr(buf, f->ret); } -static Keyring_IPint* +static IPints_IPint* strtoipint(String *s, int base) { char *p, *q; @@ -250,7 +278,7 @@ IPint_random(void *fp) destroy(v); release(); - b = mprand(f->maxbits, genrandom, nil); + b = mprand(f->nbits, genrandom, nil); acquire(); *f->ret = newIPint(b); } @@ -712,3 +740,109 @@ IPint_not(void *fp) mpnot(i1, ret); *f->ret = newIPint(ret); } + +/* + * primes + */ + +void +IPints_probably_prime(void *fp) +{ + F_IPints_probably_prime *f; + + f = fp; + release(); + *f->ret = probably_prime(checkIPint(f->n), f->nrep); + acquire(); +} + +void +IPints_genprime(void *fp) +{ + F_IPints_genprime *f; + mpint *p; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + p = mpnew(0); + release(); + genprime(p, f->nbits, f->nrep); + acquire(); + *f->ret = newIPint(p); +} + +void +IPints_genstrongprime(void *fp) +{ + F_IPints_genstrongprime *f; + mpint *p; + void *r; + + f = fp; + r = *f->ret; + *f->ret = H; + destroy(r); + p = mpnew(0); + release(); + genstrongprime(p, f->nbits, f->nrep); + acquire(); + *f->ret = newIPint(p); +} + +void +IPints_gensafeprime(void *fp) +{ + F_IPints_gensafeprime *f; + mpint *p, *alpha; + void *v; + + f = fp; + v = f->ret->t0; + f->ret->t0 = H; + destroy(v); + v = f->ret->t1; + f->ret->t1 = H; + destroy(v); + + p = mpnew(0); + alpha = mpnew(0); + release(); + gensafeprime(p, alpha, f->nbits, f->nrep); + acquire(); + f->ret->t0 = newIPint(p); + f->ret->t1 = newIPint(alpha); +} + +void +IPints_DSAprimes(void *fp) +{ + F_IPints_DSAprimes *f; + mpint *p, *q; + Heap *h; + void *v; + + f = fp; + v = f->ret->t0; + f->ret->t0 = H; + destroy(v); + v = f->ret->t1; + f->ret->t1 = H; + destroy(v); + v = f->ret->t2; + f->ret->t2 = H; + destroy(v); + + h = heaparray(&Tbyte, SHA1dlen); + f->ret->t2 = H2D(Array*, h); + + p = mpnew(0); + q = mpnew(0); + release(); + DSAprimes(q, p, f->ret->t2->data); + acquire(); + f->ret->t0 = newIPint(q); + f->ret->t1 = newIPint(p); +} diff --git a/libinterp/ipint.h b/libinterp/ipint.h new file mode 100644 index 00000000..a730f4f2 --- /dev/null +++ b/libinterp/ipint.h @@ -0,0 +1,12 @@ +typedef struct IPint IPint; + +#pragma incomplete IPint + +//Keyring_IPint* newIPint(mpint*); +void* newIPint(mpint*); +//mpint* checkIPint(Keyring_IPint*); +mpint* checkIPint(void*); +void freeIPint(Heap*, int); +void ipintsmodinit(void); + +extern Type* TIPint; diff --git a/libinterp/keyring.c b/libinterp/keyring.c index 7bc5b5d3..8b7fd406 100644 --- a/libinterp/keyring.c +++ b/libinterp/keyring.c @@ -2,69 +2,73 @@ #include "kernel.h" #include <isa.h> #include "interp.h" -#include "runt.h" -#include "keyring.h" #include <mp.h> #include <libsec.h> #include "pool.h" #include "raise.h" -#include "../libkeyring/keys.h" +/* arguably limbo -t should qualify type name */ +#define DigestState_copy Keyring_DigestState_copy +#define IPint_random Keyring_IPint_random +#include "keyringif.h" +#include "keyring.h" + +#include "ipint.h" +#include "../libkeyring/keys.h" -Type *TSigAlg; -Type *TCertificate; -Type *TSK; -Type *TPK; -Type *TDigestState; -Type *TAuthinfo; -Type *TAESstate; -Type *TDESstate; -Type *TIDEAstate; -Type *TBFstate; -Type *TRC4state; -Type *TIPint; -Type *TDSAsk; -Type *TDSApk; -Type *TDSAsig; -Type *TEGsk; -Type *TEGpk; -Type *TEGsig; -Type *TRSAsk; -Type *TRSApk; -Type *TRSAsig; +static Type* TDigestState; +static Type* TAESstate; +static Type* TDESstate; +static Type* TIDEAstate; +static Type* TBFstate; +static Type* TRC4state; + +static Type* TSigAlg; +static Type* TCertificate; +static Type* TSK; +static Type* TPK; +static Type* TAuthinfo; + +static Type* TDSAsk; +static Type* TDSApk; +static Type* TDSAsig; +static Type* TEGsk; +static Type* TEGpk; +static Type* TEGsig; +static Type* TRSAsk; +static Type* TRSApk; +static Type* TRSAsig; enum { Maxmsg= 4096 }; -uchar IPintmap[] = Keyring_IPint_map; -uchar SigAlgmap[] = Keyring_SigAlg_map; -uchar SKmap[] = Keyring_SK_map; -uchar PKmap[] = Keyring_PK_map; -uchar Certificatemap[] = Keyring_Certificate_map; -uchar DigestStatemap[] = Keyring_DigestState_map; -uchar Authinfomap[] = Keyring_Authinfo_map; -uchar AESstatemap[] = Keyring_AESstate_map; -uchar DESstatemap[] = Keyring_DESstate_map; -uchar IDEAstatemap[] = Keyring_IDEAstate_map; -uchar BFstatemap[] = Keyring_BFstate_map; -uchar RC4statemap[] = Keyring_RC4state_map; -uchar DSAskmap[] = Keyring_DSAsk_map; -uchar DSApkmap[] = Keyring_DSApk_map; -uchar DSAsigmap[] = Keyring_DSAsig_map; -uchar EGskmap[] = Keyring_EGsk_map; -uchar EGpkmap[] = Keyring_EGpk_map; -uchar EGsigmap[] = Keyring_EGsig_map; -uchar RSAskmap[] = Keyring_RSAsk_map; -uchar RSApkmap[] = Keyring_RSApk_map; -uchar RSAsigmap[] = Keyring_RSAsig_map; - -PK* checkPK(Keyring_PK *k); +static uchar DigestStatemap[] = Keyring_DigestState_map; +static uchar AESstatemap[] = Keyring_AESstate_map; +static uchar DESstatemap[] = Keyring_DESstate_map; +static uchar IDEAstatemap[] = Keyring_IDEAstate_map; +static uchar BFstatemap[] = Keyring_BFstate_map; +static uchar RC4statemap[] = Keyring_RC4state_map; + +static uchar SigAlgmap[] = Keyring_SigAlg_map; +static uchar SKmap[] = Keyring_SK_map; +static uchar PKmap[] = Keyring_PK_map; +static uchar Certificatemap[] = Keyring_Certificate_map; +static uchar Authinfomap[] = Keyring_Authinfo_map; +static uchar DSAskmap[] = Keyring_DSAsk_map; +static uchar DSApkmap[] = Keyring_DSApk_map; +static uchar DSAsigmap[] = Keyring_DSAsig_map; +static uchar EGskmap[] = Keyring_EGsk_map; +static uchar EGpkmap[] = Keyring_EGpk_map; +static uchar EGsigmap[] = Keyring_EGsig_map; +static uchar RSAskmap[] = Keyring_RSAsk_map; +static uchar RSApkmap[] = Keyring_RSApk_map; +static uchar RSAsigmap[] = Keyring_RSAsig_map; + +static PK* checkPK(Keyring_PK *k); extern void setid(char*, int); extern vlong osusectime(void); -extern Keyring_IPint* newIPint(mpint*); -extern mpint* checkIPint(Keyring_IPint*); extern void freeIPint(Heap*, int); static char exBadSA[] = "bad signature algorithm"; @@ -86,10 +90,6 @@ struct XBFstate BFstate state; }; -/* - * Infinite (actually kind of big) precision integers - */ - /* convert a Big to base64 ascii */ int bigtobase64(mpint* b, char *buf, int len) @@ -567,7 +567,7 @@ freePK(Heap *h, int swept) freeheap(h, swept); } -PK* +static PK* checkPK(Keyring_PK *k) { PK *pk; @@ -1170,28 +1170,11 @@ Keyring_verifym(void *fp) acquire(); } -static void* -checktype(void *v, Type *t, char *name, int newref) -{ - Heap *h; - - if(v == H || v == nil) - error(exNilref); - h = D2H(v); - if(h->t != t) - errorf("%s: %s", exType, name); - if(newref){ - h->ref++; - Setmark(h); - } - return v; -} - /* * digests */ void -DigestState_copy(void *fp) +Keyring_DigestState_copy(void *fp) { F_DigestState_copy *f; Heap *h; @@ -1933,18 +1916,17 @@ Keyring_writeauthinfo(void *fp) PK *spk; SK *mysk; Certificate *c; + mpint *p, *alpha; f = fp; *f->ret = -1; if(f->filename == H) - return; + error(exNilref); if(f->info == H) - return; - if(f->info->alpha == H || f->info->p == H) - return; - if(((IPint*)f->info->alpha)->b == 0 || ((IPint*)f->info->p)->b == H) - return; + error(exNilref); + alpha = checkIPint(f->info->alpha); + p = checkIPint(f->info->p); spk = checkPK(f->info->spk); mysk = checkSK(f->info->mysk); c = checkCertificate(f->info->cert); @@ -1985,12 +1967,12 @@ Keyring_writeauthinfo(void *fp) goto out; /* diffie hellman base */ - n = bigtobase64(((IPint*)f->info->alpha)->b, buf, Maxbuf); + n = bigtobase64(alpha, buf, Maxbuf); if(sendmsg(fd, buf, n) <= 0) goto out; /* diffie hellman modulus */ - n = bigtobase64(((IPint*)f->info->p)->b, buf, Maxbuf); + n = bigtobase64(p, buf, Maxbuf); if(sendmsg(fd, buf, n) <= 0) goto out; @@ -2108,7 +2090,7 @@ keyringmodinit(void) extern SigAlgVec* rsainit(void); extern SigAlgVec* dsainit(void); - TIPint = dtype(freeIPint, sizeof(IPint), IPintmap, sizeof(IPintmap)); + ipintsmodinit(); /* in case only Keyring is configured */ TSigAlg = dtype(freeSigAlg, sizeof(SigAlg), SigAlgmap, sizeof(SigAlgmap)); TSK = dtype(freeSK, sizeof(SK), SKmap, sizeof(SKmap)); TPK = dtype(freePK, sizeof(PK), PKmap, sizeof(PKmap)); @@ -3081,3 +3063,21 @@ RSApk_verify(void *fp) mpfree(t); acquire(); } + +void +Keyring_IPint_random(void *fp) +{ + F_IPint_random *f; + mpint *b; + void *v; + + f = fp; + v = *f->ret; + *f->ret = H; + destroy(v); + + release(); + b = mprand(f->maxbits, genrandom, nil); + acquire(); + *f->ret = newIPint(b); +} diff --git a/libinterp/keyringif.m b/libinterp/keyringif.m new file mode 100644 index 00000000..8eed5143 --- /dev/null +++ b/libinterp/keyringif.m @@ -0,0 +1,4 @@ +# temporary hack to prevent clashes with DigestState +include "sys.m"; + +include "keyring.m"; diff --git a/libinterp/load.c b/libinterp/load.c index 8645338a..2e3aa216 100644 --- a/libinterp/load.c +++ b/libinterp/load.c @@ -79,23 +79,6 @@ load(char *path) return readmod(path, nil, 0); } -Type* -dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize) -{ - Type *t; - - t = malloc(sizeof(Type)+mapsize); - if(t != nil) { - t->ref = 1; - t->free = destroy; - t->mark = markheap; - t->size = size; - t->np = mapsize; - memmove(t->map, map, mapsize); - } - return t; -} - int brpatch(Inst *ip, Module *m) { diff --git a/libinterp/mkfile b/libinterp/mkfile index 50d86f5d..81f39198 100644 --- a/libinterp/mkfile +++ b/libinterp/mkfile @@ -6,6 +6,7 @@ OFILES=\ alt.$O\ comp-$OBJTYPE.$O\ conv.$O\ + crypt.$O\ dec.$O\ dlm-$TARGMODEL.$O\ draw.$O\ @@ -48,6 +49,9 @@ MODULES=\ ../module/keyring.m\ ../module/loader.m\ ../module/freetype.m\ + ../module/ipints.m\ + ../module/crypt.m\ + keyringif.m\ <$ROOT/mkfiles/mksyslib-$SHELLTYPE @@ -58,7 +62,7 @@ sysmod.h:D: $MODULES rm -f $target && limbo -t Sys -I../module ../module/runt.m > $target keyring.h:D: $MODULES - rm -f $target && limbo -t Keyring -I../module ../module/runt.m > $target + rm -f $target && limbo -t Keyring -I../module keyringif.m > $target drawmod.h:D: $MODULES rm -f $target && limbo -t Draw -I../module ../module/runt.m > $target @@ -78,9 +82,19 @@ loadermod.h:D: $MODULES freetypemod.h:D: $MODULES rm -f $target && limbo -t Freetype -I../module ../module/runt.m > $target +ipintsmod.h:D: $MODULES + rm -f $target && limbo -t IPints -I../module ../module/ipints.m > $target + benchmod.h:D: ../module/bench.m rm -f $target && limbo -t Bench -I../module ../module/bench.m > $target +cryptmod.h:D: $MODULES + rm -f $target && limbo -t Crypt -I../module ../module/runt.m > $target + +keyringif.h:D: $MODULES keyringif.m + rm -f $target && limbo -a -I../module keyringif.m > $target + + bench.h:D:../module/bench.m rm -f $target && limbo -a -I../module ../module/bench.m > $target @@ -95,8 +109,9 @@ prefab.$O: prefabmod.h draw.$O: drawmod.h tk.$O: $ROOT/include/draw.h tkmod.h math.$O: mathmod.h -keyring.$O: keyring.h $ROOT/libkeyring/keys.h -ipint.$O: keyring.h +keyring.$O: keyring.h ipint.h keyringif.h +crypt.$O: ipint.h runt.h cryptmod.h +ipint.$O: ipint.h ipintsmod.h loader.$O: loadermod.h freetype.$O: freetypemod.h $ROOT/include/freetype.h math.$O: $ROOT/include/mathi.h @@ -105,11 +120,6 @@ das-spim.c:N: das-mips.c das-68000.c:N: das-68020.c comp-spim.c:N: comp-mips.c -kif.c: kif.h - rm -f $target && kif -t $SYSTARG kif.h > $target -kif.$O: kif.c - $CC $CFLAGS kif.c && rm -f kif.c - # optab.h: $ROOT/include/isa.h mkoptab # $SHELLNAME mkoptab > $target @@ -117,4 +127,4 @@ kif.$O: kif.c # it works only on UNIX and Plan 9. nuke:EV: nuke-std - rm -f runt.h sysmod.h drawmod.h prefabmod.h tkmod.h mathmod.h keyring.h readimagemod.h loadermod.h freetypemod.h kif.c + rm -f runt.h sysmod.h drawmod.h prefabmod.h tkmod.h mathmod.h keyring.h readimagemod.h loadermod.h freetypemod.h cryptmod.h keyringif.h ipintsmod.h diff --git a/libkeyring/dsaalg.c b/libkeyring/dsaalg.c index 9845d5f0..2bf659f7 100644 --- a/libkeyring/dsaalg.c +++ b/libkeyring/dsaalg.c @@ -2,7 +2,7 @@ #include <kernel.h> #include <isa.h> #include "interp.h" -#include "../libinterp/runt.h" +#include "../libinterp/keyringif.h" #include "mp.h" #include "libsec.h" #include "keys.h" diff --git a/libkeyring/egalg.c b/libkeyring/egalg.c index 0c6b88d1..28202c1c 100644 --- a/libkeyring/egalg.c +++ b/libkeyring/egalg.c @@ -2,7 +2,7 @@ #include <kernel.h> #include <isa.h> #include "interp.h" -#include "../libinterp/runt.h" +#include "../libinterp/keyringif.h" #include "mp.h" #include "libsec.h" #include "keys.h" diff --git a/libkeyring/keys.h b/libkeyring/keys.h index ff1eb149..4071ca02 100644 --- a/libkeyring/keys.h +++ b/libkeyring/keys.h @@ -1,4 +1,3 @@ -typedef struct IPint IPint; typedef struct SigAlg SigAlg; typedef struct SigAlgVec SigAlgVec; typedef struct SK SK; @@ -16,13 +15,6 @@ enum MaxBigBytes = 1024 }; -/* infininite precision integer */ -struct IPint -{ - Keyring_IPint x; - mpint* b; -}; - /* generic certificate */ struct Certificate { @@ -115,4 +107,5 @@ struct SigAlg int bigtobase64(mpint* b, char *buf, int blen); mpint* base64tobig(char *str, char **strp); SigAlgVec* findsigalg(char*); -Keyring_IPint* newIPint(mpint*); +//Keyring_IPint* newIPint(mpint*); +void* newIPint(mpint*); diff --git a/libkeyring/rsaalg.c b/libkeyring/rsaalg.c index f522f485..46df7e50 100644 --- a/libkeyring/rsaalg.c +++ b/libkeyring/rsaalg.c @@ -2,7 +2,7 @@ #include <kernel.h> #include <isa.h> #include "interp.h" -#include "../libinterp/runt.h" +#include "../libinterp/keyringif.h" #include "mp.h" #include "libsec.h" #include "keys.h" diff --git a/libmp/port/mpextendedgcd.c b/libmp/port/mpextendedgcd.c index 413a05c2..ba7365bf 100644 --- a/libmp/port/mpextendedgcd.c +++ b/libmp/port/mpextendedgcd.c @@ -101,6 +101,4 @@ mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y) mpfree(u); mpfree(a); mpfree(b); - - return; } diff --git a/man/2/crypt-0intro b/man/2/crypt-0intro new file mode 100644 index 00000000..3add273e --- /dev/null +++ b/man/2/crypt-0intro @@ -0,0 +1,98 @@ +.TH CRYPT-INTRO 2 +.SH NAME +Crypt intro \- introduction to the +.B Crypt +cryptography +module +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +include "crypt.m"; +crypt := load Crypt Crypt->PATH; +.EE +.SH DESCRIPTION +.B Crypt +contains a mixed set of functions that variously: +.IP \(bu +form cryptographically secure digests; see +.IR crypt-sha1 (2) +.IP \(bu +generate public/private key pairs; see +.IR crypt-gensk (2) +.IP \(bu +encrypt data, using AES, DES, or IDEA; see +.IR crypt-crypt (2) +.IP \(bu +create and verify cryptographic signatures using the +public keys; see +.IR crypt-sign (2) +.SS "Public Key Cryptography" +Public key cryptography has many uses. +Inferno relies on it only for digital signatures. +The private key may be used to digitally +sign data, the public one to verify the signature. +.PP +Inferno provides three data types to represent the different components of the public key signature scheme. +The +.B PK +adt contains the data necessary to construct a public key; +the +.B SK +adt contains the data necessary to construct a secret key. +A key contains the public or secret parameters for the signature algorithm specified by the adt's pick tag. +Ownership of a key is not recorded in the key value itself but in a separate certificate. +Finally, +the +.B PKsig +adt contains one or more values representing a given form of digital signature. +.PP +Certificates and indeed signature representations are varied, and implemented by other modules. +.SS "Large Precision Arithmetic" +Many +.B Crypt +operations require integers much larger than +.B int +or +.BR big . +It therefore uses the multiple-precision package +.IR ipints (2). +That module's +.B IPint +adt +stands for infinite precision integer, though, for +space considerations, our +implementation limits the maximum integer to +2\u\s-2\&8192\s0\d-1. +.PP +An +.B IPint +can be converted into two external formats. +The first is +an array of bytes in which the first byte is the highest order +byte of the integer. This format is useful when +communicating with the +.IR ssl (3) +device. +The second is similar but represents the array of bytes as text, using either base 16 or a MIME base 64 format, +allowing +.BR IPint s +to be stored in files or transmitted across +networks in a human readable form. +.SH SOURCE +.br +.B /libinterp/crypt.c +.br +.B /libinterp/ipint.c +.br +.B /libmp +.br +.B /libsec +.SH SEE ALSO +.IR security-intro (2) +.br +B. Schneier, +.IR "Applied Cryptography" , +1996, J. Wiley & Sons, Inc. diff --git a/man/2/crypt-crypt b/man/2/crypt-crypt new file mode 100644 index 00000000..5d079ca4 --- /dev/null +++ b/man/2/crypt-crypt @@ -0,0 +1,142 @@ +.TH CRYPT-CRYPT 2 +.SH NAME +crypt: aessetup, aescbc, dessetup, descbc, desecb, ideasetup, ideacbc, ideaecb \- data encryption +.SH SYNOPSIS +.EX +include "ipints.m"; +include "crypt.m"; +crypt := load Crypt Crypt->PATH; + +Encrypt: con 0; +Decrypt: con 1; + +AESbsize: con 16; + +aessetup: fn(key: array of byte, ivec: array of byte): ref AESstate; +aescbc: fn(state: ref AESstate, buf: array of byte, + n: int, direction: int); + +BFbsize: con 8; + +blowfishsetup: fn(key: array of byte, ivec: array of byte): ref BFstate; +blowfishcbc: fn(state: ref BFstate, buf: array of byte, + n: int, direction: int); + +DESbsize: con 8; + +dessetup: fn(key: array of byte, ivec: array of byte): ref DESstate; +descbc: fn(state: ref DESstate, buf: array of byte, + n: int, direction: int); +desecb: fn(state: ref DESstate, buf: array of byte, + n: int, direction: int); + +IDEAbsize: con 8; + +ideasetup: fn(key: array of byte, ivec: array of byte): ref IDEAstate; +ideacbc: fn(state: ref IDEAstate, buf: array of byte, + n: int, direction: int); +ideaecb: fn(state: ref IDEAstate, buf: array of byte, + n: int, direction: int); +.EE +.SH DESCRIPTION +These functions encrypt and decrypt blocks of data using different +encryption algorithms. +The interfaces are similar. +.PP +Each algorithm has an adt that holds the current state for a given encryption. +It is produced by the setup function for the algorithm, +.IB alg setup , +which is given a secret +.I key +and an initialisation vector +.IR ivec . +A sequence of blocks of data can then be encrypted or decrypted by repeatedly calling +.IB alg cbc +(for `cipher block chaining'), or +.IB alg ebc +(the less secure `electronic code book', if provided). +On each call, +.I buf +provides +.I n +bytes of the data to encrypt or decrypt. +.I N +must be a multiple of the encryption block size +.IB ALG bsize . +Exceptionally, +.B aescbc +allows +.I n +to be other than a multiple of +.B AESbsize +in length, but then +for successful decryption, the decryptor must use the same +sequence of buffer sizes as the encryptor. +.I Direction +is the constant +.B Encrypt +or +.B Decrypt +as required. +.I State +maintains the encryption state, initially produced by the setup function, +and updated as each buffer is encrypted or decrypted. +.PP +The algorithms currently available are: +.TP +.B aes +The Advanced Encryption Standard, AES (also known as Rijndael). +The +.I key +should be 16, 24 or 32 bytes long (128, 192 or 256 bits). +.I Ivec +should be +.B AESbsize +bytes of random data: random enough to be unlikely to be reused but +not cryptographically strongly unpredictable. +.TP +.B blowfish +Bruce Schneier's symmetric block cipher. +The +.I key +is any length from 4 to 56 bytes. +.I Ivec +if non-nil is +.B BFbsize +bytes of random data. +For +.BR blowfishcbc , +.I n +must be a multiple of +.BR BFbsize . +.TP +.B des +The older Data Encryption Standard, DES. +.I Key +is 8 bytes (64 bits), containing a 56-bit key +encoded into 64 bits where every eighth bit is parity. +.I Ivec +is +.B DESbsize +bytes of random data. +.TP +.B idea +The International Data Encryption Standard, IDEA™. +The +.I key +is 16 bytes long (128 bits). +.I Ivec +is +.B IDEAbsize +bytes of random data. +.SH SEE ALSO +.IR crypt-intro (2), +.IR crypt-rc4 (2), +.IR security-random (2) +.PP +IDEA was patented by Ascom-Tech AG (EP 0 482 154 B1, US005214703), +currently held by iT_SEC Systec Ltd. +At time of writing, there was no licence fee required for noncommercial use +but check +the current licensing policy of iT_SEC Systec Ltd, +especially for commercial use. diff --git a/man/2/crypt-dsagen b/man/2/crypt-dsagen new file mode 100644 index 00000000..7ccedc16 --- /dev/null +++ b/man/2/crypt-dsagen @@ -0,0 +1,94 @@ +.TH CRYPT-DSAGEN 2 +.SH NAME +crypt: dsagen, eggen, rsagen, rsafill, rsaencrypt, rsadecrypt \- specific public key systems +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +include "crypt.m"; +crypt := load Crypt Crypt->PATH; + +dsagen: fn(oldpk: ref PK.DSA): ref SK.DSA; + +eggen: fn(nlen: int, nrep: int): ref SK.Elgamal; + +rsagen: fn(nlen: int, elen: int, nrep: int): ref SK.RSA; +rsafill: fn(n: ref IPint, ek: ref IPint, dk: ref IPint, + p: ref IPint, q: ref IPint): ref SK.RSA; +rsaencrypt: fn(k: ref PK.RSA, m: ref IPint): ref IPint; +rsadecrypt: fn(k: ref SK.RSA, m: ref IPint): ref IPint; +.EE +.SH DESCRIPTION +.IR Crypt-gensk (2) +describes a set of functions that generate public/private key pairs given an algorithm name +and a key length. +Some key types allow further parameters for key generation or support further operations. +.PP +.B Dsagen +generates a DSA public/private key pair, represented by the pick adt +.BR SK.DSA , +and compatible with the containing type +.BR SK . +If the parameter +.B oldpk +is not nil, +.B dsagen +takes the new key's modulus and group order from the existing key; +otherwise it generates a new pair of primes. +.PP +.B Eggen +generates a new El-Gamal key pair, represented by the pick adt +.BR SK.Elgamal . +.I Nlen +is the length of the modulus; +.I nrep +is the number of repetitions of the Miller-Rabin primality test (0 gives the default, currently 18). +.PP +.B Rsagen +generates an RSA public/private key pair, represented by the pick adt +.BR SK.RSA , +and compatible with the containing type +.BR SK . +.I Nlen +gives the length of the key modulus in bits; +.I elen +gives the exponent length in bits; and +.I nrep +is as above. +.PP +The RSA private key representation used by Inferno includes some extra values to speed computation. +.B Rsagen +provides those values but keys imported from other systems might not. +Given the essential set of RSA private key parameters for a given key, represented as IPints, +.B rsafill +returns a suitable +.B SK.RSA +for that key, including the extra values. +.PP +The public key of type +.B PK.RSA +can be extracted from a given private key value +.I sk +by referencing the field +.BI sk .pk . +.PP +.B Rsaencrypt +encrypts a message +.IR m , +represented by an IPint, +using the public key +.IR pk . +.PP +.B Rsadecrypt +decrypts +.I m +using private key +.IR sk . +The result is again returned as an IPint. +.SH SEE ALSO +.IR crypt-gensk (2), +.IR crypt-sha1 (2), +.IR security-auth (2), +.IR security-oldauth (2) diff --git a/man/2/crypt-gensk b/man/2/crypt-gensk new file mode 100644 index 00000000..df51b4ee --- /dev/null +++ b/man/2/crypt-gensk @@ -0,0 +1,159 @@ +.TH CRYPT-GENSK 2 +.SH NAME +crypt: genSK, genSKfromPK, sktopk, dhparams, sign, verify \- generate keys and digital signatures +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +include "crypt.m"; +crypt := load Crypt Crypt->PATH; + +PK: adt +{ + pick { + RSA => + n: ref IPint; # modulus + ek: ref IPint; # exp (encryption key) + Elgamal => + p: ref IPint; # modulus + alpha: ref IPint; # generator + key: ref IPint; # encryption key (alpha**secret mod p) + DSA => + p: ref IPint; # modulus + q: ref IPint; # group order, q divides p-1 + alpha: ref IPint; # group generator + key: ref IPint; # encryption key (alpha**secret mod p) + } +}; + +SK: adt +{ + pick { + RSA => + pk: ref PK.RSA; + dk: ref IPint; # exp (decryption key) + p: ref IPint; # q in pkcs + q: ref IPint; # p in pkcs + # precomputed crt values + kp: ref IPint; # k mod p-1 + kq: ref IPint; # k mod q-1 + c2: ref IPint; # for converting residues to number + Elgamal => + pk: ref PK.Elgamal; + secret: ref IPint; # decryption key + DSA => + pk: ref PK.DSA; + secret: ref IPint; # decryption key + } +}; + +PKsig: adt +{ + pick { + RSA => + n: ref IPint; + Elgamal => + r: ref IPint; + s: ref IPint; + DSA => + r: ref IPint; + s: ref IPint; + } +}; + +genSK: fn(algname: string, length: int): ref SK; +genSKfromPK: fn(pk: ref PK): ref SK; +sktopk: fn(sk: ref SK): ref PK; + +sign: fn(sk: ref SK, m: ref IPint): ref PKsig; +verify: fn(pk: ref PK, sig: ref PKsig, m: ref IPint): int; + +dhparams: fn(nbits: int): (ref IPint, ref IPint); +.EE +.SH DESCRIPTION +.B Crypt +implements a set of public-key signature algorithms. +The public/private key pairs are represented by values of the adt +.BR SK , +containing both the private (secret) and public parts of the pair, +and +.BR PK , +containing only the public part. +The several algorithms are represented by different pick variants. +.PP +.B GenSK +generates a new public/private key pair, represented by +.BR SK . +.I Algname +is the name of the algorithm to use; in the current implementation, +.BR dsa , +.B elgamal +and +.B rsa +are possible. +.I Length +gives the length of the key modulus in bits. +.B GenSK +returns nil if an unknown algorithm has been specified. +.PP +.B GenSKfromPK +generates a private key that has the system parameters as the public key +.IR pk . +It is used to generate new keys that are of the same complexity as old keys. +.PP +.B Sktopk +returns a reference to the public part of private key +.IR sk . +.PP +.B Sign +creates a digital signature of a message +.IR m , +represented by an IPint, +using the private key +.IR sk . +Typically +.I m +represents a secure hash (eg, using +.IR crypt-sha1 (2)) +of a much larger message. +.PP +.B Verify +uses public key +.I pk +to verify that the value +.I sig +is a digital signature of the message +.I m +using the private key corresponding to +.IR pk . +It returns non-zero (true) if the signature is valid; zero (false) otherwise. +.PP +Most applications use generic operations on public and private keys, +referring to +.B PK +and +.BR SK , +but specific variants can be named, such as +.BR PK.RSA +for RSA keys, allowing use of RSA-specific operations. +.IR Crypt-dsagen (2) +describes functions for key generation that are specific to various algorithms, +using algorithm-specific parameters. +.PP +.B Dhparams +creates Diffie-Hellman parameters. It returns +a tuple of IPints +.RI ( alpha , p ). +.I P +is an +.I nbits +long prime number that serves as the modulus. +.I Alpha +is a primitive root in the integer field defined by that modulus. +.SH SEE ALSO +.IR crypt-dsagen (2), +.IR crypt-sha1 (2), +.IR security-auth (2), +.IR security-oldauth (2) diff --git a/man/2/crypt-rc4 b/man/2/crypt-rc4 new file mode 100644 index 00000000..8f04705e --- /dev/null +++ b/man/2/crypt-rc4 @@ -0,0 +1,49 @@ +.TH CRYPT-RC4 2 +.SH NAME +crypt: rc4setup, rc4, rc4skip, rc4back \- RC4 encryption +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +include "crypt.m"; +crypt := load Crypt Crypt->PATH; + +rc4setup: fn(seed: array of byte): ref RC4state; +rc4: fn(state: ref RC4state, buf: array of byte, n: int); +rc4skip: fn(state: ref RC4state, n: int); +rc4back: fn(state: ref RC4state, n: int); +.EE +.SH DESCRIPTION +These functions implement the stream encryption algorithm that is claimed to +be equivalent to RSA Security's RC4. +It is a pseudo-random number generator with a 256 +byte state and a long cycle. +.PP +.B Rc4setup +sets the initial +.IR seed , +which can be any non-zero length, and +returns a representation of the initial state of the algorithm, +which is used in subsequent calls. +.PP +.B Rc4 +runs the generator starting with the given +.IR state , +and XORs the output of the generator with +the first +.I n +bytes of +.IR buf , +updating the +.IR state . +.B Rc4 +is symmetric and is used both to encrypt and decrypt. +.B Rc4skip +skips over bytes (eg, to account for lost transmissions); +.B rc4back +runs the generator backwards (eg, to account for retransmissions). +.SH SEE ALSO +.IR crypt-intro (2), +.IR crypt-crypt (2) diff --git a/man/2/crypt-sha1 b/man/2/crypt-sha1 new file mode 100644 index 00000000..adfe763a --- /dev/null +++ b/man/2/crypt-sha1 @@ -0,0 +1,144 @@ +.TH CRYPT-SHA1 2 +.SH NAME +crypt: sha1, sha224, sha256, sha384, sha512, md4, md5, hmac_sha1, hmac_md5 \- cryptographic digests +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +include "crypt.m"; +crypt := load Crypt Crypt->PATH; + +DigestState: adt +{ + # hidden state + copy: fn(d: self ref DigestState): ref DigestState; +}; + +.ta \w'verify:\ 'u +\w'fn(\ \ \ 'u +sha1: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +sha224: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +sha256: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +sha384: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +sha512: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +md4: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; +md5: fn(buf: array of byte, n: int, digest: array of byte, + state: ref DigestState): ref DigestState; + +SHA1dlen, SHA224dlen, SHA256dlen, SHA384dlen, SHA512dlen, MD4dlen, MD5dlen: con ...; + +hmac_sha1: fn(buf: array of byte, n: int, key: array of byte, + digest: array of byte, + state: ref DigestState): ref DigestState; +hmac_md5: fn(buf: array of byte, n: int, key: array of byte, + digest: array of byte, + state: ref DigestState): ref DigestState; +.EE +.SH DESCRIPTION +.BR Sha1 , +.BR sha224 , +.BR sha256 , +.BR sha384 , +.BR sha512 , +.B md4 +and +.B md5 +are cryptographically secure hash functions that produce output called a message digest. +Each function computes a hash of +.I n +bytes of the data in +.IR buf , +using the named algorithm, +and updates the current +.IR state . +They can be called iteratively to form a single digest for many data blocks. +The state is kept in the +.B DigestState +value referenced by +.I state +between calls. +.I State +should be +.B nil +on the first call, and a newly allocated +.B DigestState +will be returned for use in subsequent calls. +On a call in which +.I digest +is not +.BR nil , +the hash is completed and copied into the +.I digest +array. +.B Sha1 +produces a 20-byte hash +.RB ( SHA1dlen ), +.B sha224 +a 28-byte hash +.RB ( SHA224dlen ), +.B sha256 +a 32-byte hash +.RB ( SHA256dlen ), +.B sha384 +a 48-byte hash +.RB ( SHA384dlen ), +.B sha256 +a 64-byte hash +.RB ( SHA512dlen ), +.B md4 +and +.B md5 +a 16-byte one +.RB ( MD4len +and +.BR MD5len ). +.PP +.B Hmac_sha1 +and +.B hmac_md5 +are keyed versions of the hashing functions, following Internet RFC2104. +The +.I key +must be provided in each call, but otherwise +the calling conventions are those of +.BR sha1 . +The +.I key +must currently be no more than 64 bytes. +.PP +.B DigestState +hides the state of partially completed hash functions during processing. +Its +.B copy +operation returns a reference to a new copy of a given state. +.SH EXAMPLES +A program to read a file and hash it using SHA might contain the following inner loop: +.IP +.EX +state: ref DigestState = nil; +while((n := sys->read(fd, buf, len buf)) > 0) + state = kr->sha1(buf, n, nil, state); +digest := array[kr->SHA1dlen] of byte; +kr->sha1(buf, 0, digest, state); +.EE +.SH SOURCE +.B /libinterp/crypt.c +.br +.B /libsec/port/hmac.c +.br +.B /libsec/port/md4.c +.br +.B /libsec/port/md5.c +.br +.B /libsec/port/sha1.c +.SH BUGS +The MD4 algorithm is included only to allow communication with software +that might still use it; it should not otherwise be used now, because it +is easily broken. diff --git a/man/2/ipints b/man/2/ipints new file mode 100644 index 00000000..2d4bdb8b --- /dev/null +++ b/man/2/ipints @@ -0,0 +1,193 @@ +.TH IPINTS 2 +.SH NAME +ipints: IPint \- `infinite' precision integer utility functions +.SH SYNOPSIS +.EX +include "ipints.m" +ipints:= load IPints IPints->PATH; + +IPint: adt +{ + iptob64: fn(i: self ref IPint): string; + iptob64z: fn(i: self ref IPint): string; + b64toip: fn(str: string) : ref IPint; + iptobytes: fn(i: self ref IPint): array of byte; + bytestoip: fn(buf: array of byte): ref IPint; + iptobebytes: fn(i: self ref IPint): array of byte; + bebytestoip: fn(buf: array of byte): ref IPint; + inttoip: fn(i: int): ref IPint; + iptoint: fn(i: self ref IPint): int; + iptostr: fn(i: self ref IPint, base: int): string; + strtoip: fn(str: string, base: int): ref IPint; + random: fn(nbits: int): ref IPint; + copy: fn(i: self ref IPint): ref IPint; + bits: fn(i: self ref IPint): int; + expmod: fn(base: self ref IPint, exp, mod: ref IPint):ref IPint; + add: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + sub: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + neg: fn(i: self ref IPint): ref IPint; + mul: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + div: fn(i1: self ref IPint, i2: ref IPint): (ref IPint, ref IPint); + mod: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + eq: fn(i1: self ref IPint, i2: ref IPint): int; + cmp: fn(i1: self ref IPint, i2: ref IPint): int; + shl: fn(i: self ref IPint, n: int): ref IPint; + shr: fn(i: self ref IPint, n: int): ref IPint; + and: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + ori: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + not: fn(i: self ref IPint): ref IPint; + xor: fn(i1: self ref IPint, i2: ref IPint): ref IPint; +}; +.EE +.SH DESCRIPTION +.B IPint +provides the following arbitrary-length integer manipulation functions required for cryptographic support in Limbo: +.TP +.IB i .iptob64() +Returns a string that represents a large integer textually in base 64 for convenient transmission over a network connection. +.TP +.IB i .iptob64z() +Returns a similar representation to +.B iptob64 +but ensures that the top bit of the received value is zero. +.TP +.BI b64toip( str ) +Returns the +.B IPint +represented by the base-64 encoded +.IR str . +.TP +.IB i .iptobytes() +Returns an array of bytes representing a large integer. The representation includes both positive and negative numbers. +.TP +.BI bytestoip( buf ) +The inverse operation of +.BR iptobytes . +.TP +.IB i .iptobebytes() +Returns an array of bytes in big-endian format representing the magnitude of a large integer; used for instance to pass a value to +.IR ssl (3). +Only non-negative numbers are represented. +.TP +.BI bebytestoip( buf ) +The inverse operation of +.BR iptobebytes . +.TP +.BI inttoip( i ) +Creates a new large integer from integer +.IR i . +.TP +.IB i .iptoint() +Converts a large integer +.I i +to an +.BR int ; +returns 0 on error. +.TP +.IB i .iptostr( base ) +Converts a large integer to a string in base +.IR base ; +returns nil on error. +Only the bases 10, 16, 32, and 64 are +supported. Anything else defaults to 16. +.TP +.BI strtoip( str , base ) +Converts a string +.I str +representing a number in in base +.I base +to a large integer; returns nil on error. +Only the bases 10, 16, 32, and 64 are +supported. +.TP +.BI random( nbits ) +Returns a large random number of length at most +.IR minbits . +The largest number allowed in the current implementation is +2^8192-1 . +The seed for the generator is obtained by duelling clocks. +.TP +.IB i .copy() +Returns a reference to the same value as +.IR i . +.TP +.IB i .bits() +Returns the number of bits of precision of +.IR i . +.TP +.IB base .expmod( "exp , mod" ) +Returns +.BI ( base ** exp ") mod " mod. +.TP +.IB i1 .add( i2 ) +Returns +.RI ( i1 + i2 ). +.TP +.IB i1 .sub( i2 ) +Returns +.RI ( i1 - i2 ). +.TP +.IB i1 .mul ( i2 ) +Returns +.IR i1*i2 . +.TP +.IB i1 .div ( i2 ) +Returns +.RI ( i1 / i2, +.IR i1 rem i2 ). +.TP +.IB i1 .mod ( i2 ) +Returns +.RI ( i1 mod i2 ). +.TP +.IB i1 .eq( i2 ) +Returns 1 if +.I i1 +and +.I i2 +are equal; 0 otherwise. +.TP +.IB i1 .cmp( i2 ) +Compares two large integers, returning 1 if +.I i1 +is larger, +-1 if +.I i2 +is larger, and 0 if they are equal. +.TP +.IB i .shl( n ) +Returns +.IR i << n +.TP +.IB i .shr( n ) +Returns +.IR i >> n +.TP +.IB i1 .and( i2 ) +Returns +.IR i & n , +bitwise AND +.TP +.IB i1 .ori( i2 ) +Returns +.IR i | n , +bitwise inclusive-OR +(it is +.B ori +because plain +.B or +is a Limbo keyword) +.TP +.IB i .not() +Returns +.RI ~ i , +bitwise ones-complement +.TP +.IB i1 .xor( i2 ) +Returns +.IR i ^ n , +bitwise exclusive-OR +.SH SOURCE +.B /libinterp/ipint.c +.br +.B /libmp diff --git a/man/2/ipints-genprime b/man/2/ipints-genprime new file mode 100644 index 00000000..5ec5f66c --- /dev/null +++ b/man/2/ipints-genprime @@ -0,0 +1,112 @@ +.TH IPINTS-GENPRIME 2 +.SH NAME +ipints: genprime, gensafeprime, genstrongprime, DSAprimes, probably_prime \- prime number generation +.SH SYNOPSIS +.EX +include "ipints.m"; +ipints := load IPints IPints->PATH; +IPint: import ipints; + +probably_prime: fn(n: ref IPint, nrep: int): int; + +genprime: fn(nbits: int, nrep: int): ref IPint; +gensafeprime: fn(nbits: int, nrep: int): (ref IPint, ref IPint); # p, alpha +genstrongprime: fn(nbits: int, nrep: int): ref IPint; +DSAprimes: fn(): (ref IPint, ref IPint, array of byte); # q, p, seed +.EE +.SH DESCRIPTION +This set of functions in +.B IPints +(see +.IR ipints (2)) +helps Limbo applications +generate and test large prime numbers with relative efficiency. +The numbers are all represented by +.BR IPint . +.PP +.I Probably_prime +uses the Miller-Rabin test to test +.IR n . +It returns true (non-zero) if +.I P +is probably prime. The probability of +.I n +not being prime is +1/4**\fInrep\fR. +If +.I probably_prime +returns false (zero), +.I n +is certainly not prime. +.PP +.I Genprime +returns a random prime of length +.IR nbits . +Since it uses the Miller-Rabin test, +.I nrep +is the repetition count passed to +.IR probably_prime . +.PP +.I Gensafeprime +returns a tuple +.BI ( p,\ alpha ), +where +.I p +is a prime of length +.I nbits +and +.I alpha +is a generator of the multiplicative group of integers mod \fIp\fR; +there is a prime \fIq\fR such that \fIp-1=2*q\fR. +.PP +.I Genstrongprime +returns a prime +.I p +with the following properties: +.IP \- +(\fIp\fR-1)/2 is prime. Therefore +.IR p -1 +has a large prime factor, +.IR p '. +.IP \- +.IR p '-1 +has a large prime factor +.IP \- +.IR p +1 +has a large prime factor +.PP +.I DSAprimes +uses the NIST recommended algorithm for generating DSA primes and +returns a tuple +.BI ( q,\ p,\ seed ) , +where +.I p +and +.I q +are primes, and +.I q +divides +.IR p -1. +The random +.I seed +used is also returned, so that sceptics +can later confirm the computation. +.SH SOURCE +.B /libinterp/ipint.c +.br +.B /libsec/port/probably_prime.c +.br +.B /libsec/port/dsaprimes.c +.br +.B /libsec/port/genprime.c +.br +.B /libsec/port/gensafeprime.c +.br +.B /libsec/port/genstrongprime.c +.br +.SH SEE ALSO +.IR crypt-intro (2), +.IR crypt-crypt (2), +.IR crypt-dsagen (2), +.IR crypt-gensk (2), +.IR ipints (2) diff --git a/module/crypt.m b/module/crypt.m new file mode 100644 index 00000000..db344d08 --- /dev/null +++ b/module/crypt.m @@ -0,0 +1,191 @@ +# +# basic cryptography routines implemented in C +# +Crypt: module +{ + PATH: con "$Crypt"; + + # state held while creating digests + DigestState: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + + copy: fn(d: self ref DigestState): ref DigestState; + }; + + # expanded AES key + state for chaining + AESstate: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + }; + + # expanded DES key + state for chaining + DESstate: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + }; + + # expanded IDEA key + state for chaining + IDEAstate: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + }; + + # expanded RC4 key + encryption state + RC4state: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + }; + + # expanded Blowfish key + state for chaining + BFstate: adt + { + x: int; # dummy for C compiler for runt.h + # all the state is hidden + }; + + # digests + sha1: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + sha224: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + sha256: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + sha384: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + sha512: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + md4: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + md5: fn(buf: array of byte, n: int, digest: array of byte, state: ref DigestState): + ref DigestState; + + hmac_sha1: fn(data: array of byte, n: int, key: array of byte, digest: array of byte, state: ref DigestState): + ref DigestState; + hmac_md5: fn(data: array of byte, n: int, key: array of byte, digest: array of byte, state: ref DigestState): + ref DigestState; + + SHA1dlen: con 20; + SHA224dlen: con 28; + SHA256dlen: con 32; + SHA384dlen: con 48; + SHA512dlen: con 64; + MD5dlen: con 16; + MD4dlen: con 16; + + # encryption interfaces + Encrypt: con 0; + Decrypt: con 1; + + AESbsize: con 16; + + aessetup: fn(key: array of byte, ivec: array of byte): ref AESstate; + aescbc: fn(state: ref AESstate, buf: array of byte, n: int, direction: int); + + DESbsize: con 8; + + dessetup: fn(key: array of byte, ivec: array of byte): ref DESstate; + desecb: fn(state: ref DESstate, buf: array of byte, n: int, direction: int); + descbc: fn(state: ref DESstate, buf: array of byte, n: int, direction: int); + + IDEAbsize: con 8; + + ideasetup: fn(key: array of byte, ivec: array of byte): ref IDEAstate; + ideaecb: fn(state: ref IDEAstate, buf: array of byte, n: int, direction: int); + ideacbc: fn(state: ref IDEAstate, buf: array of byte, n: int, direction: int); + + BFbsize: con 8; + + blowfishsetup: fn(key: array of byte, ivec: array of byte): ref BFstate; +# blowfishecb: fn(state: ref BFstate, buf: array of byte, n: int, direction: int); + blowfishcbc: fn(state: ref BFstate, buf: array of byte, n: int, direction: int); + + rc4setup: fn(seed: array of byte): ref RC4state; + rc4: fn(state: ref RC4state, buf: array of byte, n: int); + rc4skip: fn(state: ref RC4state, n: int); + rc4back: fn(state: ref RC4state, n: int); + + # create an alpha and p for diffie helman exchanges + dhparams: fn(nbits: int): (ref IPints->IPint, ref IPints->IPint); + + # public key + PK: adt + { + pick { + RSA => + n: ref IPints->IPint; # modulus + ek: ref IPints->IPint; # exp (encryption key) + Elgamal => + p: ref IPints->IPint; # modulus + alpha: ref IPints->IPint; # generator + key: ref IPints->IPint; # encryption key (alpha**secret mod p) + DSA => + p: ref IPints->IPint; # modulus + q: ref IPints->IPint; # group order, q divides p-1 + alpha: ref IPints->IPint; # group generator + key: ref IPints->IPint; # encryption key (alpha**secret mod p) + } + }; + + # secret key (private/public key pair) + SK: adt + { + pick { + RSA => + pk: ref PK.RSA; + dk: ref IPints->IPint; # exp (decryption key) + p: ref IPints->IPint; # q in pkcs + q: ref IPints->IPint; # p in pkcs + # precomputed crt values + kp: ref IPints->IPint; # k mod p-1 + kq: ref IPints->IPint; # k mod q-1 + c2: ref IPints->IPint; # for converting residues to number + Elgamal => + pk: ref PK.Elgamal; + secret: ref IPints->IPint; # decryption key + DSA => + pk: ref PK.DSA; + secret: ref IPints->IPint; # decryption key + } + }; + + # public key signature + PKsig: adt + { + # could just have list or array of ref IPints->IPint + pick { + RSA => + n: ref IPints->IPint; + Elgamal => + r: ref IPints->IPint; + s: ref IPints->IPint; + DSA => + r: ref IPints->IPint; + s: ref IPints->IPint; + } + }; + + # RSA keys + rsagen: fn(nlen: int, elen: int, nrep: int): ref SK.RSA; + rsafill: fn(n: ref IPints->IPint, ek: ref IPints->IPint, dk: ref IPints->IPint, p: ref IPints->IPint, q: ref IPints->IPint): ref SK.RSA; + rsadecrypt: fn(k: ref SK.RSA, m: ref IPints->IPint): ref IPints->IPint; + rsaencrypt: fn(k: ref PK.RSA, m: ref IPints->IPint): ref IPints->IPint; + + # Elgamal + eggen: fn(nlen: int, nrep: int): ref SK.Elgamal; + + # DSA + dsagen: fn(oldpk: ref PK.DSA): ref SK.DSA; + + # generic signature functions + genSK: fn(algname: string, length: int): ref SK; + genSKfromPK: fn(pk: ref PK): ref SK; + sign: fn(sk: ref SK, m: ref IPints->IPint): ref PKsig; + verify: fn(pk: ref PK, sig: ref PKsig, m: ref IPints->IPint): int; + sktopk: fn(sk: ref SK): ref PK; +}; diff --git a/module/ipints.m b/module/ipints.m new file mode 100644 index 00000000..443b9f4e --- /dev/null +++ b/module/ipints.m @@ -0,0 +1,57 @@ +IPints: module +{ + PATH: con "$IPints"; + + # infinite precision integers + IPint: adt + { + x: int; # dummy for C compiler for runt.h + + # conversions + iptob64: fn(i: self ref IPint): string; + iptob64z: fn(i: self ref IPint): string; + b64toip: fn(str: string): ref IPint; + iptobytes: fn(i: self ref IPint): array of byte; + iptobebytes: fn(i: self ref IPint): array of byte; + bytestoip: fn(buf: array of byte): ref IPint; + bebytestoip: fn(mag: array of byte): ref IPint; + inttoip: fn(i: int): ref IPint; + iptoint: fn(i: self ref IPint): int; + iptostr: fn(i: self ref IPint, base: int): string; + strtoip: fn(str: string, base: int): ref IPint; + + # create a random large integer + random: fn(nbits: int): ref IPint; + + # operations + bits: fn(i: self ref IPint): int; + expmod: fn(base: self ref IPint, exp, mod: ref IPint): ref IPint; + invert: fn(base: self ref IPint, mod: ref IPint): ref IPint; + add: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + sub: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + neg: fn(i: self ref IPint): ref IPint; + mul: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + div: fn(i1: self ref IPint, i2: ref IPint): (ref IPint, ref IPint); + mod: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + eq: fn(i1: self ref IPint, i2: ref IPint): int; + cmp: fn(i1: self ref IPint, i2: ref IPint): int; + copy: fn(i: self ref IPint): ref IPint; + + # shifts + shl: fn(i: self ref IPint, n: int): ref IPint; + shr: fn(i: self ref IPint, n: int): ref IPint; + + # bitwise + and: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + ori: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + xor: fn(i1: self ref IPint, i2: ref IPint): ref IPint; + not: fn(i1: self ref IPint): ref IPint; + }; + + # primes + probably_prime: fn(n: ref IPint, nrep: int): int; + genprime: fn(nbits: int, nrep: int): ref IPint; + genstrongprime: fn(nbits: int, nrep: int): ref IPint; + gensafeprime: fn(nbits: int, nrep: int): (ref IPint, ref IPint); + DSAprimes: fn(): (ref IPint, ref IPint, array of byte); +}; diff --git a/module/runt.m b/module/runt.m index 1021041a..e9d290a3 100644 --- a/module/runt.m +++ b/module/runt.m @@ -5,7 +5,7 @@ include "draw.m"; include "prefab.m"; include "tk.m"; include "math.m"; -include "keyring.m"; +include "ipints.m"; +include "crypt.m"; include "loader.m"; -# include "readimage.m"; include "freetype.m"; diff --git a/os/cerf1110/cerf b/os/cerf1110/cerf index 24002405..2ef05c37 100644 --- a/os/cerf1110/cerf +++ b/os/cerf1110/cerf @@ -57,7 +57,9 @@ mod sys # draw # tk - keyring + keyring crypt + ipints + port alarm diff --git a/os/cerf250/cerf b/os/cerf250/cerf index 820fba8d..57a6ed1b 100644 --- a/os/cerf250/cerf +++ b/os/cerf250/cerf @@ -60,7 +60,9 @@ mod sys # draw # tk - keyring + keyring crypt + ipints + port alarm diff --git a/os/cerf405/cerf b/os/cerf405/cerf index 87e475b2..2673ed7f 100644 --- a/os/cerf405/cerf +++ b/os/cerf405/cerf @@ -53,7 +53,9 @@ link mod math sys - keyring + keyring crypt + ipints + port alarm diff --git a/os/fads/fads b/os/fads/fads index 1f1a2959..ef63ee47 100644 --- a/os/fads/fads +++ b/os/fads/fads @@ -63,7 +63,9 @@ mod draw tk math - keyring + keyring crypt + ipints + port alarm @@ -10,7 +10,7 @@ dev dup ssl cap - sign +# sign # draw screen # pointer @@ -59,7 +59,9 @@ mod sys # draw # tk - keyring + keyring crypt + ipints + port alarm diff --git a/os/ipaq1110/ipaq b/os/ipaq1110/ipaq index 19559326..7fe4648e 100644 --- a/os/ipaq1110/ipaq +++ b/os/ipaq1110/ipaq @@ -58,7 +58,9 @@ mod sys draw tk - keyring + keyring crypt + ipints + port alarm diff --git a/os/ipengine/ipe b/os/ipengine/ipe index 8e00c855..44b9a1d1 100644 --- a/os/ipengine/ipe +++ b/os/ipengine/ipe @@ -50,7 +50,9 @@ link mod math sys - keyring + keyring crypt + ipints + port alarm @@ -49,7 +49,9 @@ mod draw prefab tk - keyring + keyring crypt + ipints + link pppmedium ppp compress diff --git a/os/manga/manga b/os/manga/manga index 725e275e..0e6a24ad 100644 --- a/os/manga/manga +++ b/os/manga/manga @@ -40,7 +40,9 @@ lib mod math sys - keyring + keyring crypt + ipints + port alarm @@ -64,7 +64,9 @@ mod sys draw tk - keyring + keyring crypt + ipints + math init diff --git a/os/pc/pcdisk b/os/pc/pcdisk index 4ae6338a..470a6e8e 100644 --- a/os/pc/pcdisk +++ b/os/pc/pcdisk @@ -73,7 +73,9 @@ mod sys draw tk - keyring + keyring crypt + ipints + math init @@ -68,7 +68,9 @@ mod sys # draw # tk - keyring + keyring crypt + ipints + math init diff --git a/os/rpcg/rpcg b/os/rpcg/rpcg index c5c90ece..c2198be9 100644 --- a/os/rpcg/rpcg +++ b/os/rpcg/rpcg @@ -61,7 +61,9 @@ mod # draw # tk math - keyring + keyring crypt + ipints + port alarm |
