--- /sys/include/libsec.h +++ /sys/include/libsec.h @@ -442,3 +442,8 @@ PEMChain*readcertchain(char *filename); /* password-based key derivation function 2 (rfc2898) */ void pbkdf2_x(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d, ulong dlen, DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); + +/* hmac-based key derivation function (rfc5869) */ +void hkdf_x(uchar *salt, ulong nsalt, uchar *info, ulong ninfo, uchar *key, ulong nkey, uchar *d, ulong dlen, + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); + --- /sys/src/libsec/port/hkdf.c +++ /sys/src/libsec/port/hkdf.c @@ -0,0 +1,36 @@ +#include "os.h" +#include + +/* rfc5869 */ +void +hkdf_x(uchar *salt, ulong nsalt, uchar *info, ulong ninfo, + uchar *key, ulong nkey, uchar *d, ulong dlen, + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen) +{ + uchar prk[256], tmp[256], cnt; + DigestState *ds; + + assert(xlen <= sizeof(tmp)); + + memset(tmp, 0, xlen); + if(nsalt == 0){ + salt = tmp; + nsalt = xlen; + } + /* note that salt and key are swapped in this case */ + (*x)(key, nkey, salt, nsalt, prk, nil); + ds = nil; + for(cnt=1;; cnt++) { + if(ninfo > 0) + ds = (*x)(info, ninfo, prk, xlen, nil, ds); + (*x)(&cnt, 1, prk, xlen, tmp, ds); + if(dlen <= xlen){ + memmove(d, tmp, dlen); + break; + } + memmove(d, tmp, xlen); + dlen -= xlen; + d += xlen; + ds = (*x)(tmp, xlen, prk, xlen, nil, nil); + } +} --- /sys/src/libsec/port/mkfile +++ /sys/src/libsec/port/mkfile @@ -17,7 +17,8 @@ dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \ tlshand.c thumb.c readcert.c \ pbkdf2.c\ + hkdf.c\ ALLOFILES=${CFILES:%.c=%.$O}