diff --git a/sys/include/libsec.h b/sys/include/libsec.h index a9c24b91c..4ab074fdb 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -439,3 +439,22 @@ void base58enc(uchar *, char *, int); int base58dec(char *, uchar *, int); DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *); + +/* + * Diffie-Hellman key exchange + */ + +typedef struct DHstate DHstate; +struct DHstate +{ + mpint *g; /* base g */ + mpint *p; /* large prime */ + mpint *x; /* random secret */ + mpint *y; /* public key y = g ^ x % p */ +}; + +/* generate new public key: y = g ^ x % p */ +mpint* dh_new(DHstate *dh, mpint *p, mpint *g); + +/* calculate shared key: k = pub ^ x % p */ +mpint* dh_finish(DHstate *dh, mpint *pub); diff --git a/sys/src/libsec/port/dh.c b/sys/src/libsec/port/dh.c new file mode 100644 index 000000000..70f6a864c --- /dev/null +++ b/sys/src/libsec/port/dh.c @@ -0,0 +1,40 @@ +#include "os.h" +#include +#include + +mpint* +dh_new(DHstate *dh, mpint *p, mpint *g) +{ + memset(dh, 0, sizeof(*dh)); + dh->g = mpcopy(g); + dh->p = mpcopy(p); + if(dh->g != nil && dh->p != nil){ + dh->x = mprand(mpsignif(dh->p), genrandom, nil); + dh->y = mpnew(0); + if(dh->x != nil && dh->y != nil){ + mpexp(dh->g, dh->x, dh->p, dh->y); + return dh->y; + } + } + dh_finish(dh, nil); + return nil; +} + +mpint* +dh_finish(DHstate *dh, mpint *pub) +{ + mpint *k; + + k = nil; + if(pub != nil && dh->x != nil && dh->p != nil){ + if((k = mpnew(0)) != nil) + mpexp(pub, dh->x, dh->p, k); + } + mpfree(dh->g); + mpfree(dh->p); + mpfree(dh->x); + mpfree(dh->y); + memset(dh, 0, sizeof(*dh)); + return k; +} + diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index 59d2f17ac..c99fcc85d 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -20,6 +20,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ aes_xts.c \ ecc.c\ ripemd.c\ + dh.c\ ALLOFILES=${CFILES:%.c=%.$O}