ref: d6ca0cfb326c9ac13c1796de917cc0547d421626
parent: 445b6293d60eb6ebd6d361596cbbc92eb8e81dc8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Feb 18 13:37:53 EST 2016
port 9front libauthsrv/libsec/libmp and implement dp9ik and rcpu support
--- a/Make.win32
+++ b/Make.win32
@@ -3,7 +3,7 @@
# on another platform. Otherwise the binaries are just
# named gcc, etc.
-MING=i586-mingw32msvc-
+MING=i686-w64-mingw32-
#MING=
AR=$(MING)ar
CC=$(MING)gcc
--- a/cpu-bl.c
+++ /dev/null
@@ -1,714 +1,0 @@
-/*
- * cpu.c - Make a connection to a cpu server
- *
- * Invoked by listen as 'cpu -R | -N service net netdir'
- * by users as 'cpu [-h system] [-c cmd args ...]'
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include <authsrv.h>
-#include <libsec.h>
-#include "args.h"
-#include "drawterm.h"
-
-#define Maxfdata 8192
-#define MaxStr 128
-
-static void fatal(int, char*, ...);
-static void usage(void);
-static void writestr(int, char*, char*, int);
-static int readstr(int, char*, int);
-static char *rexcall(int*, char*, char*);
-static char *keyspec = "";
-static AuthInfo *p9any(int);
-
-#define system csystem
-static char *system;
-static int cflag;
-extern int dbg;
-
-static char *srvname = "ncpu";
-static char *ealgs = "rc4_256 sha1";
-
-/* message size for exportfs; may be larger so we can do big graphics in CPU window */
-static int msgsize = Maxfdata+IOHDRSZ;
-
-/* authentication mechanisms */
-static int netkeyauth(int);
-static int netkeysrvauth(int, char*);
-static int p9auth(int);
-static int srvp9auth(int, char*);
-
-char *authserver;
-
-typedef struct AuthMethod AuthMethod;
-struct AuthMethod {
- char *name; /* name of method */
- int (*cf)(int); /* client side authentication */
- int (*sf)(int, char*); /* server side authentication */
-} authmethod[] =
-{
- { "p9", p9auth, srvp9auth,},
- { "netkey", netkeyauth, netkeysrvauth,},
-// { "none", noauth, srvnoauth,},
- { nil, nil}
-};
-AuthMethod *am = authmethod; /* default is p9 */
-
-char *p9authproto = "p9any";
-
-int setam(char*);
-
-void
-exits(char *s)
-{
- print("\ngoodbye\n");
- for(;;) osyield();
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n");
- exits("usage");
-}
-int fdd;
-
-int
-mountfactotum(void)
-{
- int fd;
-
- if((fd = dialfactotum()) < 0)
- return -1;
- if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){
- fprint(2, "mount factotum: %r\n");
- return -1;
- }
- if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){
- fprint(2, "open /mnt/factotum/ctl: %r\n");
- return -1;
- }
- close(fd);
- return 0;
-}
-
-void
-cpumain(int argc, char **argv)
-{
- char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s;
- int fd, ms, data;
-
- /* see if we should use a larger message size */
- fd = open("/dev/draw", OREAD);
- if(fd > 0){
- ms = iounit(fd);
- if(msgsize < ms+IOHDRSZ)
- msgsize = ms+IOHDRSZ;
- close(fd);
- }
-
- user = getenv("USER");
- if(user == nil)
- user = readcons("user", nil, 0);
- secstoreserver = nil;
- authserver = getenv("auth");
- if(authserver == nil)
- authserver = "lookout.cs.bell-labs.com";
- system = getenv("cpu");
- if(system == nil)
- system = "anna.cs.bell-labs.com";
- ARGBEGIN{
- case 'o':
- authserver = "plan9.bell-labs.com";
- system = "plan9.bell-labs.com";
- break;
- case 'a':
- authserver = EARGF(usage());
- break;
- case 'c':
- system = EARGF(usage());
- break;
- case 'd':
- dbg++;
- break;
- case 'e':
- ealgs = EARGF(usage());
- if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
- ealgs = nil;
- break;
- case 'C':
- cflag++;
- cmd[0] = '!';
- cmd[1] = '\0';
- while((p = ARGF()) != nil) {
- strcat(cmd, " ");
- strcat(cmd, p);
- }
- break;
- case 'k':
- keyspec = EARGF(usage());
- break;
- case 'u':
- user = EARGF(usage());
- break;
- case 's':
- secstoreserver = EARGF(usage());
- break;
- default:
- usage();
- }ARGEND;
-
- if(argc != 0)
- usage();
-
- if(mountfactotum() < 0){
- if(secstoreserver == nil)
- secstoreserver = authserver;
- if(havesecstore(secstoreserver, user)){
- s = secstorefetch(secstoreserver, user, nil);
- if(s){
- if(strlen(s) >= sizeof secstorebuf)
- sysfatal("secstore data too big");
- strcpy(secstorebuf, s);
- }
- }
- }
-
- if((err = rexcall(&data, system, srvname)))
- fatal(1, "%s: %s", err, system);
-
- /* Tell the remote side the command to execute and where our working directory is */
- if(cflag)
- writestr(data, cmd, "command", 0);
- if(getcwd(dat, sizeof(dat)) == 0)
- writestr(data, "NO", "dir", 0);
- else
- writestr(data, dat, "dir", 0);
-
- /*
- * Wait for the other end to execute and start our file service
- * of /mnt/term
- */
- if(readstr(data, buf, sizeof(buf)) < 0)
- fatal(1, "waiting for FS: %r");
- if(strncmp("FS", buf, 2) != 0) {
- print("remote cpu: %s", buf);
- exits(buf);
- }
-
- if(readstr(data, buf, sizeof buf) < 0)
- fatal(1, "waiting for remote export: %r");
- if(strcmp(buf, "/") != 0){
- print("remote cpu: %s" , buf);
- exits(buf);
- }
- write(data, "OK", 2);
-
- /* Begin serving the gnot namespace */
- exportfs(data, msgsize);
- fatal(1, "starting exportfs");
-}
-
-void
-fatal(int syserr, char *fmt, ...)
-{
- Fmt f;
- char *str;
- va_list arg;
-
- fmtstrinit(&f);
- fmtprint(&f, "cpu: ");
- va_start(arg, fmt);
- fmtvprint(&f, fmt, arg);
- va_end(arg);
- if(syserr)
- fmtprint(&f, ": %r");
- fmtprint(&f, "\n");
- str = fmtstrflush(&f);
- write(2, str, strlen(str));
- exits(str);
-}
-
-char *negstr = "negotiating authentication method";
-
-char bug[256];
-
-char*
-rexcall(int *fd, char *host, char *service)
-{
- char *na;
- char dir[MaxStr];
- char err[ERRMAX];
- char msg[MaxStr];
- int n;
-
- na = netmkaddr(host, "tcp", "17010");
- if((*fd = dial(na, 0, dir, 0)) < 0)
- return "can't dial";
-
- /* negotiate authentication mechanism */
- if(ealgs != nil)
- snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
- else
- snprint(msg, sizeof(msg), "%s", am->name);
- writestr(*fd, msg, negstr, 0);
- n = readstr(*fd, err, sizeof err);
- if(n < 0)
- return negstr;
- if(*err){
- werrstr(err);
- return negstr;
- }
-
- /* authenticate */
- *fd = (*am->cf)(*fd);
- if(*fd < 0)
- return "can't authenticate";
- return 0;
-}
-
-void
-writestr(int fd, char *str, char *thing, int ignore)
-{
- int l, n;
-
- l = strlen(str);
- n = write(fd, str, l+1);
- if(!ignore && n < 0)
- fatal(1, "writing network: %s", thing);
-}
-
-int
-readstr(int fd, char *str, int len)
-{
- int n;
-
- while(len) {
- n = read(fd, str, 1);
- if(n < 0)
- return -1;
- if(*str == '\0')
- return 0;
- str++;
- len--;
- }
- return -1;
-}
-
-static int
-readln(char *buf, int n)
-{
- int i;
- char *p;
-
- n--; /* room for \0 */
- p = buf;
- for(i=0; i<n; i++){
- if(read(0, p, 1) != 1)
- break;
- if(*p == '\n' || *p == '\r')
- break;
- p++;
- }
- *p = '\0';
- return p-buf;
-}
-
-/*
- * user level challenge/response
- */
-static int
-netkeyauth(int fd)
-{
- char chall[32];
- char resp[32];
-
- strecpy(chall, chall+sizeof chall, getuser());
- print("user[%s]: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- return -1;
- if(*resp != 0)
- strcpy(chall, resp);
- writestr(fd, chall, "challenge/response", 1);
-
- for(;;){
- if(readstr(fd, chall, sizeof chall) < 0)
- break;
- if(*chall == 0)
- return fd;
- print("challenge: %s\nresponse: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- break;
- writestr(fd, resp, "challenge/response", 1);
- }
- return -1;
-}
-
-static int
-netkeysrvauth(int fd, char *user)
-{
- return -1;
-}
-
-static void
-mksecret(char *t, uchar *f)
-{
- sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
- f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
-}
-
-/*
- * plan9 authentication followed by rc4 encryption
- */
-static int
-p9auth(int fd)
-{
- uchar key[16];
- uchar digest[SHA1dlen];
- char fromclientsecret[21];
- char fromserversecret[21];
- int i;
- AuthInfo *ai;
-
- ai = p9any(fd);
- if(ai == nil)
- return -1;
- memmove(key+4, ai->secret, ai->nsecret);
- if(ealgs == nil)
- return fd;
-
- /* exchange random numbers */
- for(i = 0; i < 4; i++)
- key[i] = fastrand();
- if(write(fd, key, 4) != 4)
- return -1;
- if(readn(fd, key+12, 4) != 4)
- return -1;
-
- /* scramble into two secrets */
- sha1(key, sizeof(key), digest, nil);
- mksecret(fromclientsecret, digest);
- mksecret(fromserversecret, digest+10);
-
- /* set up encryption */
- i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
- if(i < 0)
- werrstr("can't establish ssl connection: %r");
- return i;
-}
-
-int
-authdial(char *net, char *dom)
-{
- int fd;
- fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0);
- //print("authdial %d\n", fd);
- return fd;
-}
-
-static int
-getastickets(Ticketreq *tr, char *trbuf, char *tbuf)
-{
- int asfd, rv;
- char *dom;
-
- dom = tr->authdom;
- asfd = authdial(nil, dom);
- if(asfd < 0)
- return -1;
- rv = _asgetticket(asfd, trbuf, tbuf);
- close(asfd);
- return rv;
-}
-
-static int
-mkserverticket(Ticketreq *tr, char *authkey, char *tbuf)
-{
- int i;
- Ticket t;
-
- if(strcmp(tr->authid, tr->hostid) != 0)
- return -1;
- memset(&t, 0, sizeof(t));
- memmove(t.chal, tr->chal, CHALLEN);
- strcpy(t.cuid, tr->uid);
- strcpy(t.suid, tr->uid);
- for(i=0; i<DESKEYLEN; i++)
- t.key[i] = fastrand();
- t.num = AuthTc;
- convT2M(&t, tbuf, authkey);
- t.num = AuthTs;
- convT2M(&t, tbuf+TICKETLEN, authkey);
- return 0;
-}
-
-static int
-gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf)
-{
- if(getastickets(tr, trbuf, tbuf) >= 0)
- return 0;
- return mkserverticket(tr, key, tbuf);
-}
-
-/*
- * prompt user for a key. don't care about memory leaks, runs standalone
- */
-static Attr*
-promptforkey(char *params)
-{
- char *v;
- int fd;
- Attr *a, *attr;
- char *def;
-
- fd = open("/dev/cons", ORDWR);
- if(fd < 0)
- sysfatal("opening /dev/cons: %r");
-
- attr = _parseattr(params);
- fprint(fd, "\n!Adding key:");
- for(a=attr; a; a=a->next)
- if(a->type != AttrQuery && a->name[0] != '!')
- fprint(fd, " %q=%q", a->name, a->val);
- fprint(fd, "\n");
-
- for(a=attr; a; a=a->next){
- v = a->name;
- if(a->type != AttrQuery || v[0]=='!')
- continue;
- def = nil;
- if(strcmp(v, "user") == 0)
- def = getuser();
- a->val = readcons(v, def, 0);
- if(a->val == nil)
- sysfatal("user terminated key input");
- a->type = AttrNameval;
- }
- for(a=attr; a; a=a->next){
- v = a->name;
- if(a->type != AttrQuery || v[0]!='!')
- continue;
- def = nil;
- if(strcmp(v+1, "user") == 0)
- def = getuser();
- a->val = readcons(v+1, def, 1);
- if(a->val == nil)
- sysfatal("user terminated key input");
- a->type = AttrNameval;
- }
- fprint(fd, "!\n");
- close(fd);
- return attr;
-}
-
-/*
- * send a key to the mounted factotum
- */
-static int
-sendkey(Attr *attr)
-{
- int fd, rv;
- char buf[1024];
-
- fd = open("/mnt/factotum/ctl", ORDWR);
- if(fd < 0)
- sysfatal("opening /mnt/factotum/ctl: %r");
- rv = fprint(fd, "key %A\n", attr);
- read(fd, buf, sizeof buf);
- close(fd);
- return rv;
-}
-
-int
-askuser(char *params)
-{
- Attr *attr;
-
- fmtinstall('A', _attrfmt);
-
- attr = promptforkey(params);
- if(attr == nil)
- sysfatal("no key supplied");
- if(sendkey(attr) < 0)
- sysfatal("sending key to factotum: %r");
- return 0;
-}
-
-AuthInfo*
-p9anyfactotum(int fd, int afd)
-{
- return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec);
-}
-
-AuthInfo*
-p9any(int fd)
-{
- char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u;
- char *pass;
- char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN];
- char authkey[DESKEYLEN];
- Authenticator auth;
- int afd, i, v2;
- Ticketreq tr;
- Ticket t;
- AuthInfo *ai;
-
- if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0)
- return p9anyfactotum(fd, afd);
-
- if(readstr(fd, buf, sizeof buf) < 0)
- fatal(1, "cannot read p9any negotiation");
- bbuf = buf;
- v2 = 0;
- if(strncmp(buf, "v.2 ", 4) == 0){
- v2 = 1;
- bbuf += 4;
- }
- if((p = strchr(bbuf, ' ')))
- *p = 0;
- p = bbuf;
- if((dom = strchr(p, '@')) == nil)
- fatal(1, "bad p9any domain");
- *dom++ = 0;
- if(strcmp(p, "p9sk1") != 0)
- fatal(1, "server did not offer p9sk1");
-
- sprint(buf2, "%s %s", p, dom);
- if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1)
- fatal(1, "cannot write user/domain choice in p9any");
- if(v2){
- if(readstr(fd, buf, sizeof buf) != 3)
- fatal(1, "cannot read OK in p9any");
- if(memcmp(buf, "OK\0", 3) != 0)
- fatal(1, "did not get OK in p9any");
- }
- for(i=0; i<CHALLEN; i++)
- cchal[i] = fastrand();
- if(write(fd, cchal, 8) != 8)
- fatal(1, "cannot write p9sk1 challenge");
-
- if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN)
- fatal(1, "cannot read ticket request in p9sk1");
-
-
- convM2TR(trbuf, &tr);
- u = user;
- pass = findkey(&u, tr.authdom);
- if(pass == nil)
- again:
- pass = getkey(u, tr.authdom);
- if(pass == nil)
- fatal(1, "no password");
-
- passtokey(authkey, pass);
- memset(pass, 0, strlen(pass));
-
- tr.type = AuthTreq;
- strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u);
- strecpy(tr.uid, tr.uid+sizeof tr.uid, u);
- convTR2M(&tr, trbuf);
-
- if(gettickets(&tr, authkey, trbuf, tbuf) < 0)
- fatal(1, "cannot get auth tickets in p9sk1");
-
- convM2T(tbuf, &t, authkey);
- if(t.num != AuthTc){
- print("?password mismatch with auth server\n");
- goto again;
- }
- memmove(tbuf, tbuf+TICKETLEN, TICKETLEN);
-
- auth.num = AuthAc;
- memmove(auth.chal, tr.chal, CHALLEN);
- auth.id = 0;
- convA2M(&auth, tbuf+TICKETLEN, t.key);
-
- if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
- fatal(1, "cannot send ticket and authenticator back in p9sk1");
-
- if(readn(fd, tbuf, AUTHENTLEN) != AUTHENTLEN)
- fatal(1, "cannot read authenticator in p9sk1");
-
- convM2A(tbuf, &auth, t.key);
- if(auth.num != AuthAs
- || memcmp(auth.chal, cchal, CHALLEN) != 0
- || auth.id != 0){
- print("?you and auth server agree about password.\n");
- print("?server is confused.\n");
- fatal(1, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0);
- }
- //print("i am %s there.\n", t.suid);
- ai = mallocz(sizeof(AuthInfo), 1);
- ai->secret = mallocz(8, 1);
- des56to64((uchar*)t.key, ai->secret);
- ai->nsecret = 8;
- ai->suid = strdup(t.suid);
- ai->cuid = strdup(t.cuid);
- memset(authkey, 0, sizeof authkey);
- return ai;
-}
-
-/*
-static int
-noauth(int fd)
-{
- ealgs = nil;
- return fd;
-}
-
-static int
-srvnoauth(int fd, char *user)
-{
- strecpy(user, user+MaxStr, getuser());
- ealgs = nil;
- return fd;
-}
-*/
-
-void
-loghex(uchar *p, int n)
-{
- char buf[100];
- int i;
-
- for(i = 0; i < n; i++)
- sprint(buf+2*i, "%2.2ux", p[i]);
-// syslog(0, "cpu", buf);
-}
-
-static int
-srvp9auth(int fd, char *user)
-{
- return -1;
-}
-
-/*
- * set authentication mechanism
- */
-int
-setam(char *name)
-{
- for(am = authmethod; am->name != nil; am++)
- if(strcmp(am->name, name) == 0)
- return 0;
- am = authmethod;
- return -1;
-}
-
-/*
- * set authentication mechanism and encryption/hash algs
- *
-int
-setamalg(char *s)
-{
- ealgs = strchr(s, ' ');
- if(ealgs != nil)
- *ealgs++ = 0;
- return setam(s);
-}
-
-*/
--- a/cpu.c
+++ b/cpu.c
@@ -38,8 +38,6 @@
static int msgsize = Maxfdata+IOHDRSZ;
/* authentication mechanisms */
-static int netkeyauth(int);
-static int netkeysrvauth(int, char*);
static int p9auth(int);
static int srvp9auth(int, char*);
@@ -53,8 +51,6 @@
} authmethod[] =
{
{ "p9", p9auth, srvp9auth,},
- { "netkey", netkeyauth, netkeysrvauth,},
-// { "none", noauth, srvnoauth,},
{ 0 }
};
AuthMethod *am = authmethod; /* default is p9 */
@@ -98,6 +94,47 @@
}
void
+rcpu(char *host)
+{
+ static char script[] =
+"mount -nc /fd/0 /mnt/term || exit \n"
+"bind -q /mnt/term/dev/cons /dev/cons \n"
+"</dev/cons >/dev/cons >[2=1] { \n"
+" service=cpu exec rc -li \n"
+"} \n";
+ AuthInfo *ai;
+ TLSconn *conn;
+ char *na;
+ int fd;
+
+ na = netmkaddr(host, "tcp", "17019");
+ if((fd = dial(na, 0, 0, 0)) < 0)
+ return;
+
+ ai = p9any(fd);
+ if(ai == nil)
+ fatal(1, "can't authenticate");
+
+ conn = mallocz(sizeof(TLSconn), 1);
+ conn->pskID = "p9secret";
+ conn->psk = ai->secret;
+ conn->psklen = ai->nsecret;
+
+ fd = tlsClient(fd, conn);
+ if(fd < 0)
+ fatal(1, "tlsClient");
+
+ auth_freeAI(ai);
+
+ if(fprint(fd, "%7ld\n%s", strlen(script), script) < 0)
+ fatal(1, "sending script");
+
+ /* Begin serving the namespace */
+ exportfs(fd, msgsize);
+ fatal(1, "starting exportfs");
+}
+
+void
cpumain(int argc, char **argv)
{
char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s;
@@ -179,6 +216,8 @@
}
}
+ rcpu(system);
+
if((err = rexcall(&data, system, srvname)))
fatal(1, "%s: %s", err, system);
@@ -300,61 +339,6 @@
return -1;
}
-static int
-readln(char *buf, int n)
-{
- int i;
- char *p;
-
- n--; /* room for \0 */
- p = buf;
- for(i=0; i<n; i++){
- if(read(0, p, 1) != 1)
- break;
- if(*p == '\n' || *p == '\r')
- break;
- p++;
- }
- *p = '\0';
- return p-buf;
-}
-
-/*
- * user level challenge/response
- */
-static int
-netkeyauth(int fd)
-{
- char chall[32];
- char resp[32];
-
- strecpy(chall, chall+sizeof chall, getuser());
- print("user[%s]: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- return -1;
- if(*resp != 0)
- strcpy(chall, resp);
- writestr(fd, chall, "challenge/response", 1);
-
- for(;;){
- if(readstr(fd, chall, sizeof chall) < 0)
- break;
- if(*chall == 0)
- return fd;
- print("challenge: %s\nresponse: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- break;
- writestr(fd, resp, "challenge/response", 1);
- }
- return -1;
-}
-
-static int
-netkeysrvauth(int fd, char *user)
-{
- return -1;
-}
-
static void
mksecret(char *t, uchar *f)
{
@@ -378,13 +362,17 @@
ai = p9any(fd);
if(ai == nil)
return -1;
- memmove(key+4, ai->secret, ai->nsecret);
if(ealgs == nil)
return fd;
+ if(ai->nsecret < 8){
+ werrstr("secret too small");
+ return -1;
+ }
+ memmove(key+4, ai->secret, 8);
+
/* exchange random numbers */
- for(i = 0; i < 4; i++)
- key[i] = fastrand();
+ genrandom(key, 4);
if(write(fd, key, 4) != 4)
return -1;
if(readn(fd, key+12, 4) != 4)
@@ -412,7 +400,7 @@
}
static int
-getastickets(Ticketreq *tr, char *trbuf, char *tbuf)
+getastickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen)
{
int asfd, rv;
char *dom;
@@ -421,38 +409,71 @@
asfd = authdial(nil, dom);
if(asfd < 0)
return -1;
- rv = _asgetticket(asfd, trbuf, tbuf);
+ if(y != nil){
+ PAKpriv p;
+
+ rv = -1;
+ tr->type = AuthPAK;
+ if(_asrequest(asfd, tr) != 0 || write(asfd, y, PAKYLEN) != PAKYLEN)
+ goto Out;
+
+ authpak_new(&p, key, (uchar*)tbuf, 1);
+ if(write(asfd, tbuf, PAKYLEN) != PAKYLEN)
+ goto Out;
+
+ if(_asrdresp(asfd, tbuf, 2*PAKYLEN) != 2*PAKYLEN)
+ goto Out;
+
+ memmove(y, tbuf, PAKYLEN);
+ if(authpak_finish(&p, key, (uchar*)tbuf+PAKYLEN))
+ goto Out;
+ }
+ tr->type = AuthTreq;
+ rv = _asgetticket(asfd, tr, tbuf, tbuflen);
+Out:
close(asfd);
return rv;
}
static int
-mkserverticket(Ticketreq *tr, char *authkey, char *tbuf)
+mkservertickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen)
{
- int i;
Ticket t;
+ int ret;
if(strcmp(tr->authid, tr->hostid) != 0)
return -1;
memset(&t, 0, sizeof(t));
+ ret = 0;
+ if(y != nil){
+ PAKpriv p;
+
+ t.form = 1;
+ memmove(tbuf, y, PAKYLEN);
+ authpak_new(&p, key, y, 0);
+ authpak_finish(&p, key, (uchar*)tbuf);
+ }
memmove(t.chal, tr->chal, CHALLEN);
strcpy(t.cuid, tr->uid);
strcpy(t.suid, tr->uid);
- for(i=0; i<DESKEYLEN; i++)
- t.key[i] = fastrand();
+ genrandom((uchar*)t.key, sizeof(t.key));
t.num = AuthTc;
- convT2M(&t, tbuf, authkey);
+ ret += convT2M(&t, tbuf+ret, tbuflen-ret, key);
t.num = AuthTs;
- convT2M(&t, tbuf+TICKETLEN, authkey);
- return 0;
+ ret += convT2M(&t, tbuf+ret, tbuflen-ret, key);
+ memset(&t, 0, sizeof(t));
+
+ return ret;
}
static int
-gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf)
+gettickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen)
{
- if(getastickets(tr, trbuf, tbuf) >= 0)
- return 0;
- return mkserverticket(tr, key, tbuf);
+ int ret;
+ ret = getastickets(key, tr, y, tbuf, tbuflen);
+ if(ret > 0)
+ return ret;
+ return mkservertickets(key, tr, y, tbuf, tbuflen);
}
/*
@@ -548,12 +569,13 @@
AuthInfo*
p9any(int fd)
{
- char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u;
+ char buf[1024], buf2[1024], *bbuf, *p, *proto, *dom, *u;
char *pass;
- char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN];
- char authkey[DESKEYLEN];
+ uchar crand[2*NONCELEN], cchal[CHALLEN], y[PAKYLEN];
+ char tbuf[2*MAXTICKETLEN+MAXAUTHENTLEN+PAKYLEN], trbuf[TICKREQLEN+PAKYLEN];
+ Authkey authkey;
Authenticator auth;
- int afd, i, n, v2;
+ int afd, i, n, m, v2, dp9ik;
Ticketreq tr;
Ticket t;
AuthInfo *ai;
@@ -570,16 +592,26 @@
v2 = 1;
bbuf += 4;
}
- if((p = strchr(bbuf, ' ')))
- *p = 0;
- p = bbuf;
- if((dom = strchr(p, '@')) == nil)
- fatal(1, "bad p9any domain");
- *dom++ = 0;
- if(strcmp(p, "p9sk1") != 0)
- fatal(1, "server did not offer p9sk1");
-
- sprint(buf2, "%s %s", p, dom);
+ dp9ik = 0;
+ proto = nil;
+ while(bbuf != nil){
+ if((p = strchr(bbuf, ' ')))
+ *p++ = 0;
+ if((dom = strchr(bbuf, '@')) == nil)
+ fatal(1, "bad p9any domain");
+ *dom++ = 0;
+ if(strcmp(bbuf, "p9sk1") == 0 || strcmp(bbuf, "dp9ik") == 0){
+ proto = bbuf;
+ if(strcmp(proto, "dp9ik") == 0){
+ dp9ik = 1;
+ break;
+ }
+ }
+ bbuf = p;
+ }
+ if(proto == nil)
+ fatal(1, "server did not offer p9sk1 or dp9ik");
+ sprint(buf2, "%s %s", proto, dom);
if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1)
fatal(1, "cannot write user/domain choice in p9any");
if(v2){
@@ -588,16 +620,18 @@
if(memcmp(buf, "OK\0", 3) != 0)
fatal(1, "did not get OK in p9any");
}
- for(i=0; i<CHALLEN; i++)
- cchal[i] = fastrand();
- if(write(fd, cchal, 8) != 8)
+ genrandom(crand, 2*NONCELEN);
+ genrandom(cchal, CHALLEN);
+ if(write(fd, cchal, CHALLEN) != CHALLEN)
fatal(1, "cannot write p9sk1 challenge");
- if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN)
+ n = TICKREQLEN;
+ if(dp9ik)
+ n += PAKYLEN;
+
+ if(readn(fd, trbuf, n) != n || convM2TR(trbuf, TICKREQLEN, &tr) <= 0)
fatal(1, "cannot read ticket request in p9sk1");
-
- convM2TR(trbuf, &tr);
u = user;
pass = findkey(&u, tr.authdom);
if(pass == nil)
@@ -606,36 +640,45 @@
if(pass == nil)
fatal(1, "no password");
- passtokey(authkey, pass);
+ passtokey(&authkey, pass);
memset(pass, 0, strlen(pass));
- tr.type = AuthTreq;
strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u);
strecpy(tr.uid, tr.uid+sizeof tr.uid, u);
- convTR2M(&tr, trbuf);
- if(gettickets(&tr, authkey, trbuf, tbuf) < 0)
+ if(dp9ik){
+ authpak_hash(&authkey, tr.hostid);
+ memmove(y, trbuf+TICKREQLEN, PAKYLEN);
+ n = gettickets(&authkey, &tr, y, tbuf, sizeof(tbuf));
+ } else {
+ n = gettickets(&authkey, &tr, nil, tbuf, sizeof(tbuf));
+ }
+ if(n <= 0)
fatal(1, "cannot get auth tickets in p9sk1");
- convM2T(tbuf, &t, authkey);
- if(t.num != AuthTc){
+ m = convM2T(tbuf, n, &t, &authkey);
+ if(m <= 0 || t.num != AuthTc){
print("?password mismatch with auth server\n");
goto again;
}
- memmove(tbuf, tbuf+TICKETLEN, TICKETLEN);
+ n -= m;
+ memmove(tbuf, tbuf+m, n);
+ if(dp9ik && write(fd, y, PAKYLEN) != PAKYLEN)
+ fatal(1, "cannot send authpak public key back");
+
auth.num = AuthAc;
+ memmove(auth.rand, crand, NONCELEN);
memmove(auth.chal, tr.chal, CHALLEN);
- auth.id = 0;
- convA2M(&auth, tbuf+TICKETLEN, t.key);
+ m = convA2M(&auth, tbuf+n, sizeof(tbuf)-n, &t);
+ n += m;
- if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
- fatal(1, "cannot send ticket and authenticator back in p9sk1");
+ if(write(fd, tbuf, n) != n)
+ fatal(1, "cannot send ticket and authenticator back");
- if((n=readn(fd, tbuf, AUTHENTLEN)) != AUTHENTLEN ||
- memcmp(tbuf, "cpu:", 4) == 0){
+ if((n=readn(fd, tbuf, m)) != m || memcmp(tbuf, "cpu:", 4) == 0){
if(n <= 4)
- fatal(1, "cannot read authenticator in p9sk1");
+ fatal(1, "cannot read authenticator");
/*
* didn't send back authenticator:
@@ -650,53 +693,43 @@
fatal(0, "server says: %s", buf);
}
- convM2A(tbuf, &auth, t.key);
- if(auth.num != AuthAs
- || memcmp(auth.chal, cchal, CHALLEN) != 0
- || auth.id != 0){
+ if(convM2A(tbuf, n, &auth, &t) <= 0
+ || auth.num != AuthAs || tsmemcmp(auth.chal, cchal, CHALLEN) != 0){
print("?you and auth server agree about password.\n");
print("?server is confused.\n");
- fatal(0, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0);
+ fatal(0, "server lies got %llux want %llux", *(vlong*)auth.chal, *(vlong*)cchal);
}
- //print("i am %s there.\n", t.suid);
+ memmove(crand+NONCELEN, auth.rand, NONCELEN);
+
+ // print("i am %s there.\n", t.suid);
+
ai = mallocz(sizeof(AuthInfo), 1);
- ai->secret = mallocz(8, 1);
- des56to64((uchar*)t.key, ai->secret);
- ai->nsecret = 8;
ai->suid = strdup(t.suid);
ai->cuid = strdup(t.cuid);
- memset(authkey, 0, sizeof authkey);
- return ai;
-}
+ if(dp9ik){
+ static char info[] = "Plan 9 session secret";
+ ai->nsecret = 256;
+ ai->secret = mallocz(ai->nsecret, 1);
+ hkdf_x( crand, 2*NONCELEN,
+ (uchar*)info, sizeof(info)-1,
+ (uchar*)t.key, NONCELEN,
+ ai->secret, ai->nsecret,
+ hmac_sha2_256, SHA2_256dlen);
+ } else {
+ ai->nsecret = 8;
+ ai->secret = mallocz(ai->nsecret, 1);
+ des56to64((uchar*)t.key, ai->secret);
+ }
-/*
-static int
-noauth(int fd)
-{
- ealgs = nil;
- return fd;
-}
+ memset(&t, 0, sizeof(t));
+ memset(&auth, 0, sizeof(auth));
+ memset(&authkey, 0, sizeof(authkey));
+ memset(cchal, 0, sizeof(cchal));
+ memset(crand, 0, sizeof(crand));
-static int
-srvnoauth(int fd, char *user)
-{
- strecpy(user, user+MaxStr, getuser());
- ealgs = nil;
- return fd;
+ return ai;
}
-*/
-void
-loghex(uchar *p, int n)
-{
- char buf[100];
- int i;
-
- for(i = 0; i < n; i++)
- sprint(buf+2*i, "%2.2ux", p[i]);
-// syslog(0, "cpu", buf);
-}
-
static int
srvp9auth(int fd, char *user)
{
@@ -715,17 +748,3 @@
am = authmethod;
return -1;
}
-
-/*
- * set authentication mechanism and encryption/hash algs
- *
-int
-setamalg(char *s)
-{
- ealgs = strchr(s, ' ');
- if(ealgs != nil)
- *ealgs++ = 0;
- return setam(s);
-}
-
-*/
--- a/include/authsrv.h
+++ b/include/authsrv.h
@@ -1,8 +1,3 @@
-#ifdef PLAN9
-#pragma src "/sys/src/libauthsrv"
-#pragma lib "libauthsrv.a"
-#endif
-
/*
* Interface for talking to authentication server.
*/
@@ -14,21 +9,35 @@
typedef struct OChapreply OChapreply;
typedef struct OMSchapreply OMSchapreply;
+typedef struct Authkey Authkey;
+
enum
{
- ANAMELEN= 28, /* maximum size of name in previous proto */
- AERRLEN= 64, /* maximum size of errstr in previous proto */
- DOMLEN= 48, /* length of an authentication domain name */
- DESKEYLEN= 7, /* length of a des key for encrypt/decrypt */
- CHALLEN= 8, /* length of a plan9 sk1 challenge */
- NETCHLEN= 16, /* max network challenge length (used in AS protocol) */
+ ANAMELEN= 28, /* name max size in previous proto */
+ AERRLEN= 64, /* errstr max size in previous proto */
+ DOMLEN= 48, /* authentication domain name length */
+ DESKEYLEN= 7, /* encrypt/decrypt des key length */
+ AESKEYLEN= 16, /* encrypt/decrypt aes key length */
+
+ CHALLEN= 8, /* plan9 sk1 challenge length */
+ NETCHLEN= 16, /* max network challenge length (used in AS protocol) */
CONFIGLEN= 14,
- SECRETLEN= 32, /* max length of a secret */
+ SECRETLEN= 32, /* secret max size */
- KEYDBOFF= 8, /* length of random data at the start of key file */
- OKEYDBLEN= ANAMELEN+DESKEYLEN+4+2, /* length of an entry in old key file */
- KEYDBLEN= OKEYDBLEN+SECRETLEN, /* length of an entry in key file */
+ NONCELEN= 32,
+
+ KEYDBOFF= 8, /* bytes of random data at key file's start */
+ OKEYDBLEN= ANAMELEN+DESKEYLEN+4+2, /* old key file entry length */
+ KEYDBLEN= OKEYDBLEN+SECRETLEN, /* key file entry length */
OMD5LEN= 16,
+
+ /* AuthPAK constants */
+ PAKKEYLEN= 32,
+ PAKSLEN= (448+7)/8, /* ed448 scalar */
+ PAKPLEN= 4*PAKSLEN, /* point in extended format X,Y,Z,T */
+ PAKHASHLEN= 2*PAKPLEN, /* hashed points PM,PN */
+ PAKXLEN= PAKSLEN, /* random scalar secret key */
+ PAKYLEN= PAKSLEN, /* decaf encoded public key */
};
/* encryption numberings (anti-replay) */
@@ -47,8 +56,7 @@
AuthCram=12, /* CRAM verification for IMAP (RFC2195 & rfc2104) */
AuthHttp=13, /* http domain login */
AuthVNC=14, /* VNC server login (deprecated) */
-
-
+ AuthPAK=19, /* authenticated diffie hellman key agreement */
AuthTs=64, /* ticket encrypted with server's key */
AuthTc, /* ticket encrypted with client's key */
AuthAs, /* server generated authenticator */
@@ -74,17 +82,19 @@
char chal[CHALLEN]; /* server challenge */
char cuid[ANAMELEN]; /* uid on client */
char suid[ANAMELEN]; /* uid on server */
- char key[DESKEYLEN]; /* nonce DES key */
+ uchar key[NONCELEN]; /* nonce key */
+
+ char form; /* (not transmitted) format (0 = des, 1 = ccpoly) */
};
-#define TICKETLEN (CHALLEN+2*ANAMELEN+DESKEYLEN+1)
+#define MAXTICKETLEN (12+CHALLEN+2*ANAMELEN+NONCELEN+16)
struct Authenticator
{
char num; /* replay protection */
- char chal[CHALLEN];
- ulong id; /* authenticator id, ++'d with each auth */
+ char chal[CHALLEN]; /* server/client challenge */
+ uchar rand[NONCELEN]; /* server/client nonce */
};
-#define AUTHENTLEN (CHALLEN+4+1)
+#define MAXAUTHENTLEN (12+CHALLEN+NONCELEN+16)
struct Passwordreq
{
@@ -94,7 +104,7 @@
char changesecret;
char secret[SECRETLEN]; /* new secret */
};
-#define PASSREQLEN (2*ANAMELEN+1+1+SECRETLEN)
+#define MAXPASSREQLEN (12+2*ANAMELEN+1+SECRETLEN+16)
struct OChapreply
{
@@ -102,6 +112,7 @@
char uid[ANAMELEN];
char resp[OMD5LEN];
};
+#define OCHAPREPLYLEN (1+ANAMELEN+OMD5LEN)
struct OMSchapreply
{
@@ -109,50 +120,70 @@
char LMresp[24]; /* Lan Manager response */
char NTresp[24]; /* NT response */
};
+#define OMSCHAPREPLYLEN (ANAMELEN+24+24)
+struct Authkey
+{
+ char des[DESKEYLEN]; /* DES key from password */
+ uchar aes[AESKEYLEN]; /* AES key from password */
+ uchar pakkey[PAKKEYLEN]; /* shared key from AuthPAK exchange (see authpak_finish()) */
+ uchar pakhash[PAKHASHLEN]; /* secret hash from AES key and user name (see authpak_hash()) */
+};
+
/*
* convert to/from wire format
*/
-extern int convT2M(Ticket*, char*, char*);
-extern void convM2T(char*, Ticket*, char*);
-extern void convM2Tnoenc(char*, Ticket*);
-extern int convA2M(Authenticator*, char*, char*);
-extern void convM2A(char*, Authenticator*, char*);
-extern int convTR2M(Ticketreq*, char*);
-extern void convM2TR(char*, Ticketreq*);
-extern int convPR2M(Passwordreq*, char*, char*);
-extern void convM2PR(char*, Passwordreq*, char*);
+extern int convT2M(Ticket*, char*, int, Authkey*);
+extern int convM2T(char*, int, Ticket*, Authkey*);
+extern int convA2M(Authenticator*, char*, int, Ticket*);
+extern int convM2A(char*, int, Authenticator*, Ticket*);
+extern int convTR2M(Ticketreq*, char*, int);
+extern int convM2TR(char*, int, Ticketreq*);
+extern int convPR2M(Passwordreq*, char*, int, Ticket*);
+extern int convM2PR(char*, int, Passwordreq*, Ticket*);
/*
- * convert ascii password to DES key
+ * convert ascii password to auth key
*/
-extern int opasstokey(char*, char*);
-extern int passtokey(char*, char*);
+extern void passtokey(Authkey*, char*);
+extern void passtodeskey(char key[DESKEYLEN], char *p);
+extern void passtoaeskey(uchar key[AESKEYLEN], char *p);
+
/*
* Nvram interface
*/
enum {
- NVwrite = 1<<0, /* always prompt and rewrite nvram */
- NVwriteonerr = 1<<1, /* prompt and rewrite nvram when corrupt */
+ NVread = 0, /* just read */
+ NVwrite = 1<<0, /* always prompt and rewrite nvram */
+ NVwriteonerr = 1<<1, /* prompt and rewrite nvram when corrupt */
+ NVwritemem = 1<<2, /* don't prompt, write nvram from argument */
};
+/* storage layout */
struct Nvrsafe
{
- char machkey[DESKEYLEN];
+ char machkey[DESKEYLEN]; /* file server's authid's des key */
uchar machsum;
- char authkey[DESKEYLEN];
+ char authkey[DESKEYLEN]; /* authid's des key from password */
uchar authsum;
+ /*
+ * file server config string of device holding full configuration;
+ * secstore key on non-file-servers.
+ */
char config[CONFIGLEN];
uchar configsum;
- char authid[ANAMELEN];
+ char authid[ANAMELEN]; /* auth userid, e.g., bootes */
uchar authidsum;
- char authdom[DOMLEN];
+ char authdom[DOMLEN]; /* auth domain, e.g., cs.bell-labs.com */
uchar authdomsum;
+
+ uchar aesmachkey[AESKEYLEN];
+ uchar aesmachsum;
};
extern uchar nvcsum(void*, int);
-extern int readnvram(Nvrsafe*, int);
+extern int readnvram(Nvrsafe*, int);
/*
* call up auth server
@@ -162,7 +193,23 @@
/*
* exchange messages with auth server
*/
-extern int _asgetticket(int, char*, char*);
+extern int _asgetpakkey(int, Ticketreq*, Authkey*);
+extern int _asgetticket(int, Ticketreq*, char*, int);
+extern int _asrequest(int, Ticketreq*);
+extern int _asgetresp(int, Ticket*, Authenticator*, Authkey *);
extern int _asrdresp(int, char*, int);
-extern int sslnegotiate(int, Ticket*, char**, char**);
-extern int srvsslnegotiate(int, Ticket*, char**, char**);
+
+/*
+ * AuthPAK protocol
+ */
+typedef struct PAKpriv PAKpriv;
+struct PAKpriv
+{
+ int isclient;
+ uchar x[PAKXLEN];
+ uchar y[PAKYLEN];
+};
+
+extern void authpak_hash(Authkey *k, char *u);
+extern void authpak_new(PAKpriv *p, Authkey *k, uchar y[PAKYLEN], int isclient);
+extern int authpak_finish(PAKpriv *p, Authkey *k, uchar y[PAKYLEN]);
--- a/include/lib.h
+++ b/include/lib.h
@@ -20,6 +20,7 @@
#define strtoll libstrtoll
#undef timeradd
#define timeradd xtimeradd
+#define gmtime libgmtime
#define nil ((void*)0)
@@ -32,6 +33,7 @@
typedef unsigned short p9_ushort;
typedef unsigned int Rune;
typedef unsigned int p9_u32int;
+typedef unsigned long long p9_u64int;
typedef p9_u32int mpdigit;
/* make sure we don't conflict with predefined types */
@@ -40,6 +42,7 @@
#define ushort p9_ushort
#define uint p9_uint
#define u32int p9_u32int
+#define u64int p9_u64int
/* #define long int rather than p9_long so that "unsigned long" is valid */
#define long int
@@ -277,3 +280,23 @@
extern int (*fmtdoquote)(int);
+
+/*
+ * Time-of-day
+ */
+
+typedef
+struct Tm
+{
+ int sec;
+ int min;
+ int hour;
+ int mday;
+ int mon;
+ int year;
+ int wday;
+ int yday;
+ char zone[4];
+ int tzoff;
+} Tm;
+extern Tm* gmtime(long);
--- a/include/libsec.h
+++ b/include/libsec.h
@@ -1,11 +1,10 @@
-
#ifndef _MPINT
typedef struct mpint mpint;
#endif
-/////////////////////////////////////////////////////////
-// AES definitions
-/////////////////////////////////////////////////////////
+/*
+ * AES definitions
+ */
enum
{
@@ -20,27 +19,35 @@
ulong setup;
int rounds;
int keybytes;
- uchar key[AESmaxkey]; /* unexpanded key */
- u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */
- u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */
- uchar ivec[AESbsize]; /* initialization vector */
+ uchar key[AESmaxkey]; /* unexpanded key */
+ ulong ekey[4*(AESmaxrounds + 1)]; /* encryption key */
+ ulong dkey[4*(AESmaxrounds + 1)]; /* decryption key */
+ uchar ivec[AESbsize]; /* initialization vector */
+ uchar mackey[3 * AESbsize]; /* 3 XCBC mac 96 keys */
};
+/* block ciphers */
+void aes_encrypt(ulong rk[], int Nr, uchar pt[16], uchar ct[16]);
+void aes_decrypt(ulong rk[], int Nr, uchar ct[16], uchar pt[16]);
+
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
void aesCBCencrypt(uchar *p, int len, AESstate *s);
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
-/////////////////////////////////////////////////////////
-// Blowfish Definitions
-/////////////////////////////////////////////////////////
+void setupAESXCBCstate(AESstate *s);
+uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
+/*
+ * Blowfish Definitions
+ */
+
enum
{
BFbsize = 8,
- BFrounds = 16
+ BFrounds= 16
};
-// 16-round Blowfish
+/* 16-round Blowfish */
typedef struct BFstate BFstate;
struct BFstate
{
@@ -59,16 +66,80 @@
void bfECBencrypt(uchar*, int, BFstate*);
void bfECBdecrypt(uchar*, int, BFstate*);
-/////////////////////////////////////////////////////////
-// DES definitions
-/////////////////////////////////////////////////////////
+/*
+ * Chacha definitions
+ */
enum
{
+ ChachaBsize= 64,
+ ChachaKeylen= 256/8,
+ ChachaIVlen= 96/8,
+};
+
+typedef struct Chachastate Chachastate;
+struct Chachastate
+{
+ union{
+ u32int input[16];
+ struct {
+ u32int constant[4];
+ u32int key[8];
+ u32int counter;
+ u32int iv[3];
+ };
+ };
+ int rounds;
+ int ivwords;
+};
+
+void setupChachastate(Chachastate*, uchar*, ulong, uchar*, ulong, int);
+void chacha_setiv(Chachastate *, uchar*);
+void chacha_setblock(Chachastate*, u64int);
+void chacha_encrypt(uchar*, ulong, Chachastate*);
+void chacha_encrypt2(uchar*, uchar*, ulong, Chachastate*);
+
+void ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs);
+int ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs);
+
+/*
+ * Salsa definitions
+ */
+enum
+{
+ SalsaBsize= 64,
+ SalsaKeylen= 256/8,
+ SalsaIVlen= 64/8,
+ XSalsaIVlen= 192/8,
+};
+
+typedef struct Salsastate Salsastate;
+struct Salsastate
+{
+ u32int input[16];
+ u32int key[8];
+ int rounds;
+ int ivwords;
+};
+
+void setupSalsastate(Salsastate*, uchar*, ulong, uchar*, ulong, int);
+void salsa_setiv(Salsastate*, uchar*);
+void salsa_setblock(Salsastate*, u64int);
+void salsa_encrypt(uchar*, ulong, Salsastate*);
+void salsa_encrypt2(uchar*, uchar*, ulong, Salsastate*);
+
+void hsalsa(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds);
+
+/*
+ * DES definitions
+ */
+
+enum
+{
DESbsize= 8
};
-// single des
+/* single des */
typedef struct DESstate DESstate;
struct DESstate
{
@@ -86,12 +157,12 @@
void desECBencrypt(uchar*, int, DESstate*);
void desECBdecrypt(uchar*, int, DESstate*);
-// for backward compatibility with 7 byte DES key format
+/* for backward compatibility with 7-byte DES key format */
void des56to64(uchar *k56, uchar *k64);
void des64to56(uchar *k64, uchar *k56);
void key_setup(uchar[7], ulong[32]);
-// triple des encrypt/decrypt orderings
+/* triple des encrypt/decrypt orderings */
enum {
DES3E= 0,
DES3D= 1,
@@ -117,67 +188,97 @@
void des3ECBencrypt(uchar*, int, DES3state*);
void des3ECBdecrypt(uchar*, int, DES3state*);
-/////////////////////////////////////////////////////////
-// digests
-/////////////////////////////////////////////////////////
+/*
+ * digests
+ */
enum
{
SHA1dlen= 20, /* SHA digest length */
+ SHA2_224dlen= 28, /* SHA-224 digest length */
+ SHA2_256dlen= 32, /* SHA-256 digest length */
+ SHA2_384dlen= 48, /* SHA-384 digest length */
+ SHA2_512dlen= 64, /* SHA-512 digest length */
MD4dlen= 16, /* MD4 digest length */
- MD5dlen= 16 /* MD5 digest length */
+ MD5dlen= 16, /* MD5 digest length */
+ Poly1305dlen= 16, /* Poly1305 digest length */
+
+ Hmacblksz = 64, /* in bytes; from rfc2104 */
};
typedef struct DigestState DigestState;
struct DigestState
{
- ulong len;
- u32int state[5];
- uchar buf[128];
- int blen;
- char malloced;
- char seeded;
+ uvlong len;
+ union {
+ u32int state[8];
+ u64int bstate[8];
+ };
+ uchar buf[256];
+ int blen;
+ char malloced;
+ char seeded;
};
typedef struct DigestState SHAstate; /* obsolete name */
typedef struct DigestState SHA1state;
+typedef struct DigestState SHA2_224state;
+typedef struct DigestState SHA2_256state;
+typedef struct DigestState SHA2_384state;
+typedef struct DigestState SHA2_512state;
typedef struct DigestState MD5state;
typedef struct DigestState MD4state;
-DigestState* md4(uchar*, ulong, uchar*, DigestState*);
-DigestState* md5(uchar*, ulong, uchar*, DigestState*);
-DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
-DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
-DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
-char* sha1pickle(SHA1state*);
-SHA1state* sha1unpickle(char*);
+DigestState* md4(uchar*, ulong, uchar*, DigestState*);
+DigestState* md5(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha2_224(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha2_256(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha2_384(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha2_512(uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_x(uchar *p, ulong len, uchar *key, ulong klen,
+ uchar *digest, DigestState *s,
+ DigestState*(*x)(uchar*, ulong, uchar*, DigestState*),
+ int xlen);
+DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha2_224(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha2_256(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha2_384(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha2_512(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+char* md5pickle(MD5state*);
+MD5state* md5unpickle(char*);
+char* sha1pickle(SHA1state*);
+SHA1state* sha1unpickle(char*);
-/////////////////////////////////////////////////////////
-// random number generation
-/////////////////////////////////////////////////////////
+DigestState* poly1305(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+
+/*
+ * random number generation
+ */
void genrandom(uchar *buf, int nbytes);
void prng(uchar *buf, int nbytes);
ulong fastrand(void);
ulong nfastrand(ulong);
-/////////////////////////////////////////////////////////
-// primes
-/////////////////////////////////////////////////////////
-void genprime(mpint *p, int n, int accuracy); // generate an n bit probable prime
-void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy); // prime and generator
-void genstrongprime(mpint *p, int n, int accuracy); // generate an n bit strong prime
+/*
+ * primes
+ */
+void genprime(mpint *p, int n, int accuracy); /* generate n-bit probable prime */
+void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy); /* prime & generator */
+void genstrongprime(mpint *p, int n, int accuracy); /* generate n-bit strong prime */
void DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]);
-int probably_prime(mpint *n, int nrep); // miller-rabin test
-int smallprimetest(mpint *p); // returns -1 if not prime, 0 otherwise
+int probably_prime(mpint *n, int nrep); /* miller-rabin test */
+int smallprimetest(mpint *p); /* returns -1 if not prime, 0 otherwise */
-/////////////////////////////////////////////////////////
-// rc4
-/////////////////////////////////////////////////////////
+/*
+ * rc4
+ */
typedef struct RC4state RC4state;
struct RC4state
{
- uchar state[256];
- uchar x;
- uchar y;
+ uchar state[256];
+ uchar x;
+ uchar y;
};
void setupRC4state(RC4state*, uchar*, int);
@@ -185,34 +286,41 @@
void rc4skip(RC4state*, int);
void rc4back(RC4state*, int);
-/////////////////////////////////////////////////////////
-// rsa
-/////////////////////////////////////////////////////////
+/*
+ * rsa
+ */
typedef struct RSApub RSApub;
typedef struct RSApriv RSApriv;
+typedef struct PEMChain PEMChain;
-// public/encryption key
+/* public/encryption key */
struct RSApub
{
- mpint *n; // modulus
- mpint *ek; // exp (encryption key)
+ mpint *n; /* modulus */
+ mpint *ek; /* exp (encryption key) */
};
-// private/decryption key
+/* private/decryption key */
struct RSApriv
{
RSApub pub;
- mpint *dk; // exp (decryption key)
+ mpint *dk; /* exp (decryption key) */
- // precomputed values to help with chinese remainder theorem calc
+ /* precomputed values to help with chinese remainder theorem calc */
mpint *p;
mpint *q;
- mpint *kp; // dk mod p-1
- mpint *kq; // dk mod q-1
- mpint *c2; // (inv p) mod q
+ mpint *kp; /* dk mod p-1 */
+ mpint *kq; /* dk mod q-1 */
+ mpint *c2; /* (inv p) mod q */
};
+struct PEMChain{
+ PEMChain*next;
+ uchar *pem;
+ int pemlen;
+};
+
RSApriv* rsagen(int nlen, int elen, int rounds);
RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q);
mpint* rsaencrypt(RSApub *k, mpint *in, mpint *out);
@@ -225,34 +333,38 @@
RSApub* X509toRSApub(uchar*, int, char*, int);
RSApriv* asn1toRSApriv(uchar*, int);
void asn1dump(uchar *der, int len);
-uchar* decodepem(char *s, char *type, int *len);
-uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
-uchar* X509req(RSApriv *priv, char *subj, int *certlen);
-char* X509verify(uchar *cert, int ncert, RSApub *pk);
+uchar* decodePEM(char *s, char *type, int *len, char **new_s);
+PEMChain* decodepemchain(char *s, char *type);
+uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
+uchar* X509rsareq(RSApriv *priv, char *subj, int *certlen);
+char* X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
+char* X509rsaverify(uchar *cert, int ncert, RSApub *pk);
+
void X509dump(uchar *cert, int ncert);
-/////////////////////////////////////////////////////////
-// elgamal
-/////////////////////////////////////////////////////////
+
+/*
+ * elgamal
+ */
typedef struct EGpub EGpub;
typedef struct EGpriv EGpriv;
typedef struct EGsig EGsig;
-// public/encryption key
+/* public/encryption key */
struct EGpub
{
- mpint *p; // modulus
- mpint *alpha; // generator
- mpint *key; // (encryption key) alpha**secret mod p
+ mpint *p; /* modulus */
+ mpint *alpha; /* generator */
+ mpint *key; /* (encryption key) alpha**secret mod p */
};
-// private/decryption key
+/* private/decryption key */
struct EGpriv
{
EGpub pub;
- mpint *secret; // (decryption key)
+ mpint *secret; /* (decryption key) */
};
-// signature
+/* signature */
struct EGsig
{
mpint *r, *s;
@@ -259,7 +371,7 @@
};
EGpriv* eggen(int nlen, int rounds);
-mpint* egencrypt(EGpub *k, mpint *in, mpint *out);
+mpint* egencrypt(EGpub *k, mpint *in, mpint *out); /* deprecated */
mpint* egdecrypt(EGpriv *k, mpint *in, mpint *out);
EGsig* egsign(EGpriv *k, mpint *m);
int egverify(EGpub *k, EGsig *sig, mpint *m);
@@ -271,36 +383,36 @@
void egsigfree(EGsig*);
EGpub* egprivtopub(EGpriv*);
-/////////////////////////////////////////////////////////
-// dsa
-/////////////////////////////////////////////////////////
+/*
+ * dsa
+ */
typedef struct DSApub DSApub;
typedef struct DSApriv DSApriv;
typedef struct DSAsig DSAsig;
-// public/encryption key
+/* public/encryption key */
struct DSApub
{
- mpint *p; // modulus
- mpint *q; // group order, q divides p-1
- mpint *alpha; // group generator
- mpint *key; // (encryption key) alpha**secret mod p
+ mpint *p; /* modulus */
+ mpint *q; /* group order, q divides p-1 */
+ mpint *alpha; /* group generator */
+ mpint *key; /* (encryption key) alpha**secret mod p */
};
-// private/decryption key
+/* private/decryption key */
struct DSApriv
{
DSApub pub;
- mpint *secret; // (decryption key)
+ mpint *secret; /* (decryption key) */
};
-// signature
+/* signature */
struct DSAsig
{
mpint *r, *s;
};
-DSApriv* dsagen(DSApub *opub);
+DSApriv* dsagen(DSApub *opub); /* opub not checked for consistency! */
DSAsig* dsasign(DSApriv *k, mpint *m);
int dsaverify(DSApub *k, DSAsig *sig, mpint *m);
DSApub* dsapuballoc(void);
@@ -310,31 +422,135 @@
DSAsig* dsasigalloc(void);
void dsasigfree(DSAsig*);
DSApub* dsaprivtopub(DSApriv*);
+DSApriv* asn1toDSApriv(uchar*, int);
-/////////////////////////////////////////////////////////
-// TLS
-/////////////////////////////////////////////////////////
+/*
+ * TLS
+ */
typedef struct Thumbprint{
struct Thumbprint *next;
- uchar sha1[SHA1dlen];
+ uchar sha1[SHA1dlen];
} Thumbprint;
typedef struct TLSconn{
- char dir[40]; // connection directory
- uchar *cert; // certificate (local on input, remote on output)
- uchar *sessionID;
- int certlen, sessionIDlen;
- int (*trace)(char*fmt, ...);
+ char dir[40]; /* connection directory */
+ uchar *cert; /* certificate (local on input, remote on output) */
+ uchar *sessionID;
+ uchar *psk;
+ int certlen;
+ int sessionIDlen;
+ int psklen;
+ int (*trace)(char*fmt, ...);
+ PEMChain*chain; /* optional extra certificate evidence for servers to present */
+ char *sessionType;
+ uchar *sessionKey;
+ int sessionKeylen;
+ char *sessionConst;
+ char *serverName;
+ char *pskID;
} TLSconn;
-// tlshand.c
-extern int tlsClient(int fd, TLSconn *c);
-extern int tlsServer(int fd, TLSconn *c);
+/* tlshand.c */
+int tlsClient(int fd, TLSconn *c);
+int tlsServer(int fd, TLSconn *c);
-// thumb.c
-extern Thumbprint* initThumbprints(char *ok, char *crl);
-extern void freeThumbprints(Thumbprint *ok);
-extern int okThumbprint(uchar *sha1, Thumbprint *ok);
+/* thumb.c */
+Thumbprint* initThumbprints(char *ok, char *crl);
+void freeThumbprints(Thumbprint *ok);
+int okThumbprint(uchar *sha1, Thumbprint *ok);
-// readcert.c
-extern uchar *readcert(char *filename, int *pcertlen);
+/* readcert.c */
+uchar *readcert(char *filename, int *pcertlen);
+PEMChain*readcertchain(char *filename);
+
+/* aes_xts.c */
+int aes_xts_encrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) ;
+int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len);
+
+typedef struct ECpoint{
+ int inf;
+ mpint *x;
+ mpint *y;
+} ECpoint;
+
+typedef ECpoint ECpub;
+typedef struct ECpriv{
+ ECpoint;
+ mpint *d;
+} ECpriv;
+
+typedef struct ECdomain{
+ mpint *p;
+ mpint *a;
+ mpint *b;
+ ECpoint G;
+ mpint *n;
+ mpint *h;
+} ECdomain;
+
+void ecdominit(ECdomain *, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h));
+void ecdomfree(ECdomain *);
+
+void ecassign(ECdomain *, ECpoint *old, ECpoint *new);
+void ecadd(ECdomain *, ECpoint *a, ECpoint *b, ECpoint *s);
+void ecmul(ECdomain *, ECpoint *a, mpint *k, ECpoint *s);
+ECpoint* strtoec(ECdomain *, char *, char **, ECpoint *);
+ECpriv* ecgen(ECdomain *, ECpriv*);
+int ecverify(ECdomain *, ECpoint *);
+int ecpubverify(ECdomain *, ECpub *);
+void ecdsasign(ECdomain *, ECpriv *, uchar *, int, mpint *, mpint *);
+int ecdsaverify(ECdomain *, ECpub *, uchar *, int, mpint *, mpint *);
+void base58enc(uchar *, char *, int);
+int base58dec(char *, uchar *, int);
+
+ECpub* ecdecodepub(ECdomain *dom, uchar *, int);
+int ecencodepub(ECdomain *dom, ECpub *, uchar *, int);
+void ecpubfree(ECpub *);
+
+ECpub* X509toECpub(uchar *cert, int ncert, ECdomain *dom);
+char* X509ecdsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, ECdomain *dom, ECpub *pub);
+char* X509ecdsaverify(uchar *sig, int siglen, ECdomain *dom, ECpub *pub);
+
+/* curves */
+void secp256r1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
+void secp256k1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
+
+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 *q; /* subgroup 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 *q, mpint *g);
+
+/* calculate shared key: k = y**x % p */
+mpint* dh_finish(DHstate *dh, mpint *y);
+
+/* Curve25519 elliptic curve, public key function */
+void curve25519(uchar mypublic[32], uchar secret[32], uchar basepoint[32]);
+
+/* Curve25519 diffie hellman */
+void curve25519_dh_new(uchar x[32], uchar y[32]);
+void curve25519_dh_finish(uchar x[32], uchar y[32], uchar z[32]);
+
+/* 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);
+
+/* timing safe memcmp() */
+int tsmemcmp(void*, void*, ulong);
--- a/include/mp.h
+++ b/include/mp.h
@@ -1,16 +1,17 @@
#define _MPINT 1
-// the code assumes mpdigit to be at least an int
-// mpdigit must be an atomic type. mpdigit is defined
-// in the architecture specific u.h
-
+/*
+ * the code assumes mpdigit to be at least an int
+ * mpdigit must be an atomic type. mpdigit is defined
+ * in the architecture specific u.h
+ */
typedef struct mpint mpint;
struct mpint
{
- int sign; // +1 or -1
- int size; // allocated digits
- int top; // significant digits
+ int sign; /* +1 or -1 */
+ int size; /* allocated digits */
+ int top; /* significant digits */
mpdigit *p;
char flags;
};
@@ -17,118 +18,158 @@
enum
{
- MPstatic= 0x01,
- Dbytes= sizeof(mpdigit), // bytes per digit
- Dbits= Dbytes*8 // bits per digit
+ MPstatic= 0x01, /* static constant */
+ MPnorm= 0x02, /* normalization status */
+ MPtimesafe= 0x04, /* request time invariant computation */
+ MPfield= 0x08, /* this mpint is a field modulus */
+
+ Dbytes= sizeof(mpdigit), /* bytes per digit */
+ Dbits= Dbytes*8 /* bits per digit */
};
-// allocation
-void mpsetminbits(int n); // newly created mpint's get at least n bits
-mpint* mpnew(int n); // create a new mpint with at least n bits
+/* allocation */
+void mpsetminbits(int n); /* newly created mpint's get at least n bits */
+mpint* mpnew(int n); /* create a new mpint with at least n bits */
void mpfree(mpint *b);
-void mpbits(mpint *b, int n); // ensure that b has at least n bits
-void mpnorm(mpint *b); // dump leading zeros
+void mpbits(mpint *b, int n); /* ensure that b has at least n bits */
+mpint* mpnorm(mpint *b); /* dump leading zeros */
mpint* mpcopy(mpint *b);
void mpassign(mpint *old, mpint *new);
-// random bits
+/* random bits */
mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b);
+/* return uniform random [0..n-1] */
+mpint* mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b);
-// conversion
-mpint* strtomp(char*, char**, int, mpint*); // ascii
+/* conversion */
+mpint* strtomp(char*, char**, int, mpint*); /* ascii */
int mpfmt(Fmt*);
char* mptoa(mpint*, int, char*, int);
-mpint* letomp(uchar*, uint, mpint*); // byte array, little-endian
+mpint* letomp(uchar*, uint, mpint*); /* byte array, little-endian */
int mptole(mpint*, uchar*, uint, uchar**);
-mpint* betomp(uchar*, uint, mpint*); // byte array, little-endian
+void mptolel(mpint *b, uchar *p, int n);
+mpint* betomp(uchar*, uint, mpint*); /* byte array, big-endian */
int mptobe(mpint*, uchar*, uint, uchar**);
-uint mptoui(mpint*); // unsigned int
+void mptober(mpint *b, uchar *p, int n);
+uint mptoui(mpint*); /* unsigned int */
mpint* uitomp(uint, mpint*);
-int mptoi(mpint*); // int
+int mptoi(mpint*); /* int */
mpint* itomp(int, mpint*);
-uvlong mptouv(mpint*); // unsigned vlong
+uvlong mptouv(mpint*); /* unsigned vlong */
mpint* uvtomp(uvlong, mpint*);
-vlong mptov(mpint*); // vlong
+vlong mptov(mpint*); /* vlong */
mpint* vtomp(vlong, mpint*);
-// divide 2 digits by one
+/* divide 2 digits by one */
void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
-// in the following, the result mpint may be
-// the same as one of the inputs.
-void mpadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
-void mpsub(mpint *b1, mpint *b2, mpint *diff); // diff = b1-b2
-void mpleft(mpint *b, int shift, mpint *res); // res = b<<shift
-void mpright(mpint *b, int shift, mpint *res); // res = b>>shift
-void mpmul(mpint *b1, mpint *b2, mpint *prod); // prod = b1*b2
-void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); // res = b**e mod m
-void mpmod(mpint *b, mpint *m, mpint *remainder); // remainder = b mod m
+/* in the following, the result mpint may be */
+/* the same as one of the inputs. */
+void mpadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
+void mpsub(mpint *b1, mpint *b2, mpint *diff); /* diff = b1-b2 */
+void mpleft(mpint *b, int shift, mpint *res); /* res = b<<shift */
+void mpright(mpint *b, int shift, mpint *res); /* res = b>>shift */
+void mpmul(mpint *b1, mpint *b2, mpint *prod); /* prod = b1*b2 */
+void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); /* res = b**e mod m */
+void mpmod(mpint *b, mpint *m, mpint *remainder); /* remainder = b mod m */
-// quotient = dividend/divisor, remainder = dividend % divisor
+/* logical operations */
+void mpand(mpint *b1, mpint *b2, mpint *res);
+void mpbic(mpint *b1, mpint *b2, mpint *res);
+void mpor(mpint *b1, mpint *b2, mpint *res);
+void mpnot(mpint *b, mpint *res);
+void mpxor(mpint *b1, mpint *b2, mpint *res);
+void mptrunc(mpint *b, int n, mpint *res);
+void mpxtend(mpint *b, int n, mpint *res);
+
+/* modular arithmetic, time invariant when 0≤b1≤m-1 and 0≤b2≤m-1 */
+void mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum); /* sum = b1+b2 % m */
+void mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff); /* diff = b1-b2 % m */
+void mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod); /* prod = b1*b2 % m */
+
+/* quotient = dividend/divisor, remainder = dividend % divisor */
void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder);
-// return neg, 0, pos as b1-b2 is neg, 0, pos
+/* return neg, 0, pos as b1-b2 is neg, 0, pos */
int mpcmp(mpint *b1, mpint *b2);
-// extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d
+/* res = s != 0 ? b1 : b2 */
+void mpsel(int s, mpint *b1, mpint *b2, mpint *res);
+
+/* extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d */
void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
-// res = b**-1 mod m
+/* res = b**-1 mod m */
void mpinvert(mpint *b, mpint *m, mpint *res);
-// bit counting
-int mpsignif(mpint*); // number of sigificant bits in mantissa
-int mplowbits0(mpint*); // k, where n = 2**k * q for odd q
+/* bit counting */
+int mpsignif(mpint*); /* number of sigificant bits in mantissa */
+int mplowbits0(mpint*); /* k, where n = 2**k * q for odd q */
-// well known constants
+/* well known constants */
extern mpint *mpzero, *mpone, *mptwo;
-// sum[0:alen] = a[0:alen-1] + b[0:blen-1]
-// prereq: alen >= blen, sum has room for alen+1 digits
+/* sum[0:alen] = a[0:alen-1] + b[0:blen-1] */
+/* prereq: alen >= blen, sum has room for alen+1 digits */
void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
-// diff[0:alen-1] = a[0:alen-1] - b[0:blen-1]
-// prereq: alen >= blen, diff has room for alen digits
+/* diff[0:alen-1] = a[0:alen-1] - b[0:blen-1] */
+/* prereq: alen >= blen, diff has room for alen digits */
void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
-// p[0:n] += m * b[0:n-1]
-// prereq: p has room for n+1 digits
+/* p[0:n] += m * b[0:n-1] */
+/* prereq: p has room for n+1 digits */
void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
-// p[0:n] -= m * b[0:n-1]
-// prereq: p has room for n+1 digits
+/* p[0:n] -= m * b[0:n-1] */
+/* prereq: p has room for n+1 digits */
int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
-// p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1]
-// prereq: alen >= blen, p has room for m*n digits
+/* p[0:alen+blen-1] = a[0:alen-1] * b[0:blen-1] */
+/* prereq: alen >= blen, p has room for m*n digits */
void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
+void mpvectsmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
-// sign of a - b or zero if the same
+/* sign of a - b or zero if the same */
int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
+int mpvectscmp(mpdigit *a, int alen, mpdigit *b, int blen);
-// divide the 2 digit dividend by the one digit divisor and stick in quotient
-// we assume that the result is one digit - overflow is all 1's
+/* divide the 2 digit dividend by the one digit divisor and stick in quotient */
+/* we assume that the result is one digit - overflow is all 1's */
void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
-// playing with magnitudes
+/* playing with magnitudes */
int mpmagcmp(mpint *b1, mpint *b2);
-void mpmagadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
-void mpmagsub(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
+void mpmagadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
+void mpmagsub(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
-// chinese remainder theorem
-typedef struct CRTpre CRTpre; // precomputed values for converting
- // twixt residues and mpint
-typedef struct CRTres CRTres; // residue form of an mpint
+/* chinese remainder theorem */
+typedef struct CRTpre CRTpre; /* precomputed values for converting */
+ /* twixt residues and mpint */
+typedef struct CRTres CRTres; /* residue form of an mpint */
struct CRTres
{
- int n; // number of residues
- mpint *r[1]; // residues
+ int n; /* number of residues */
+ mpint *r[1]; /* residues */
};
-CRTpre* crtpre(int, mpint**); // precompute conversion values
-CRTres* crtin(CRTpre*, mpint*); // convert mpint to residues
-void crtout(CRTpre*, CRTres*, mpint*); // convert residues to mpint
+CRTpre* crtpre(int, mpint**); /* precompute conversion values */
+CRTres* crtin(CRTpre*, mpint*); /* convert mpint to residues */
+void crtout(CRTpre*, CRTres*, mpint*); /* convert residues to mpint */
void crtprefree(CRTpre*);
void crtresfree(CRTres*);
+/* fast field arithmetic */
+typedef struct Mfield Mfield;
+
+struct Mfield
+{
+ mpint;
+ int (*reduce)(Mfield*, mpint*, mpint*);
+};
+
+mpint *mpfield(mpint*);
+
+Mfield *gmfield(mpint*);
+Mfield *cnfield(mpint*);
--- a/include/user.h
+++ b/include/user.h
@@ -81,6 +81,7 @@
extern void sleep(int);
extern void osyield(void);
extern void setmalloctag(void*, uintptr);
+extern void setrealloctag(void*, uintptr);
extern int errstr(char*, uint);
extern int rerrstr(char*, uint);
extern int encrypt(void*, void*, int);
@@ -91,3 +92,4 @@
extern void lock(Lock*);
extern void unlock(Lock*);
extern int iprint(char*, ...);
+extern void exits(char*);
--- a/kern/devcons.c
+++ b/kern/devcons.c
@@ -1191,3 +1191,29 @@
return n;
}
+static ulong randn;
+
+static void
+seedrand(void)
+{
+ if(!waserror()){
+ randomread((void*)&randn, sizeof(randn));
+ poperror();
+ }
+}
+
+int
+nrand(int n)
+{
+ if(randn == 0)
+ seedrand();
+ randn = randn*1103515245 + 12345;
+ return (randn>>16) % n;
+}
+
+int
+rand(void)
+{
+ nrand(1);
+ return randn;
+}
--- a/kern/devssl.c
+++ b/kern/devssl.c
@@ -717,7 +717,7 @@
randfill(uchar *buf, int len)
{
while(len-- > 0)
- *buf++ = fastrand();
+ *buf++ = nrand(256);
}
static long
--- a/kern/devtls.c
+++ b/kern/devtls.c
@@ -8,9 +8,9 @@
#include "error.h"
#include "libsec.h"
-
+
typedef struct OneWay OneWay;
-typedef struct Secret Secret;
+typedef struct Secret Secret;
typedef struct TlsRec TlsRec;
typedef struct TlsErrs TlsErrs;
@@ -17,15 +17,16 @@
enum {
Statlen= 1024, /* max. length of status or stats message */
/* buffer limits */
- MaxRecLen = 1<<14, /* max payload length of a record layer message */
+ MaxRecLen = 1<<14, /* max payload length of a record layer message */
MaxCipherRecLen = MaxRecLen + 2048,
- RecHdrLen = 5,
- MaxMacLen = SHA1dlen,
+ RecHdrLen = 5,
+ MaxMacLen = SHA2_256dlen,
/* protocol versions we can accept */
- TLSVersion = 0x0301,
- SSL3Version = 0x0300,
- ProtocolVersion = 0x0301, /* maximum version we speak */
+ SSL3Version = 0x0300,
+ TLS10Version = 0x0301,
+ TLS11Version = 0x0302,
+ TLS12Version = 0x0303,
MinProtoVersion = 0x0300, /* limits on version we accept */
MaxProtoVersion = 0x03ff,
@@ -72,6 +73,7 @@
EInternalError = 80,
EUserCanceled = 90,
ENoRenegotiation = 100,
+ EUnrecognizedName = 112,
EMAX = 256
};
@@ -84,10 +86,14 @@
int (*dec)(Secret*, uchar*, int);
int (*unpad)(uchar*, int, int);
DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+
+ int (*aead_enc)(Secret*, uchar*, int, uchar*, int);
+ int (*aead_dec)(Secret*, uchar*, int, uchar*, int);
+
int block; /* encryption block len, 0 if none */
int maclen;
void *enckey;
- uchar mackey[MaxMacLen];
+ uchar mackey[MaxMacLen];
};
struct OneWay
@@ -94,7 +100,7 @@
{
QLock io; /* locks io access */
QLock seclock; /* locks secret paramaters */
- ulong seq;
+ u64int seq;
Secret *sec; /* cipher in use */
Secret *new; /* cipher waiting for enable */
};
@@ -116,8 +122,11 @@
int state;
int debug;
- /* record layer mac functions for different protocol versions */
- void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
+ /*
+ * function to genrate authenticated data blob for different
+ * protocol versions
+ */
+ int (*packAAD)(u64int, uchar*, uchar*);
/* input side -- protected by in.io */
OneWay in;
@@ -218,13 +227,14 @@
static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void put64(uchar *p, vlong x);
+static int sslPackAAD(u64int, uchar*, uchar*);
+static int tlsPackAAD(u64int, uchar*, uchar*);
+static void packMac(Secret*, uchar*, int, uchar*, int, uchar*);
+static void put64(uchar *p, u64int);
static void put32(uchar *p, u32int);
static void put24(uchar *p, int);
static void put16(uchar *p, int);
-/* static u32int get32(uchar *p); */
+static u32int get32(uchar *p);
static int get16(uchar *p);
static void tlsSetState(TlsRec *tr, int new, int old);
static void rcvAlert(TlsRec *tr, int err);
@@ -233,6 +243,10 @@
static int rc4enc(Secret *sec, uchar *buf, int n);
static int des3enc(Secret *sec, uchar *buf, int n);
static int des3dec(Secret *sec, uchar *buf, int n);
+static int aesenc(Secret *sec, uchar *buf, int n);
+static int aesdec(Secret *sec, uchar *buf, int n);
+static int ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len);
+static int ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len);
static int noenc(Secret *sec, uchar *buf, int n);
static int sslunpad(uchar *buf, int n, int block);
static int tlsunpad(uchar *buf, int n, int block);
@@ -241,24 +255,20 @@
static void pdump(int, void*, char*);
static char *tlsnames[] = {
- /* unused */ 0,
- /* topdir */ 0,
- /* protodir */ 0,
- "clone",
- "encalgs",
- "hashalgs",
- /* convdir */ 0,
- "data",
- "ctl",
- "hand",
- "status",
- "stats",
+[Qclonus] "clone",
+[Qencalgs] "encalgs",
+[Qhashalgs] "hashalgs",
+[Qdata] "data",
+[Qctl] "ctl",
+[Qhand] "hand",
+[Qstatus] "status",
+[Qstats] "stats",
};
static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats };
static int
-tlsgen(Chan *c, char*unused1, Dirtab *unused2, int unused3, int s, Dir *dp)
+tlsgen(Chan *c, char *unused1, Dirtab *unused2, int unused3, int s, Dir *dp)
{
Qid q;
TlsRec *tr;
@@ -377,7 +387,6 @@
unlock(&tdlock);
return 1;
}
- return -1;
}
static Chan*
@@ -467,7 +476,7 @@
lock(&tr->hqlock);
if(tr->handq != nil)
error(Einuse);
- tr->handq = qopen(2 * MaxCipherRecLen, 0, 0, nil);
+ tr->handq = qopen(2 * MaxCipherRecLen, 0, nil, nil);
if(tr->handq == nil)
error("cannot allocate handshake queue");
tr->hqref = 1;
@@ -732,9 +741,10 @@
{
OneWay *volatile in;
Block *volatile b;
- uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
+ uchar *p, aad[8+RecHdrLen], header[RecHdrLen], hmac[MaxMacLen];
int volatile nconsumed;
- int len, type, ver, unpad_len;
+ int len, type, ver, unpad_len, aadlen, ivlen;
+ Secret *sec;
nconsumed = 0;
if(waserror()){
@@ -796,25 +806,46 @@
}
qlock(&in->seclock);
p = b->rp;
- if(in->sec != nil) {
+ sec = in->sec;
+ if(sec != nil) {
/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
should look alike, including timing of the response. */
- unpad_len = (*in->sec->dec)(in->sec, p, len);
- if(unpad_len >= in->sec->maclen)
- len = unpad_len - in->sec->maclen;
+ if(sec->aead_dec != nil)
+ unpad_len = len;
+ else {
+ unpad_len = (*sec->dec)(sec, p, len);
if(tr->debug) pprint("decrypted %d\n", unpad_len);
if(tr->debug) pdump(unpad_len, p, "decrypted:");
+ }
+ if(tr->version >= TLS11Version){
+ ivlen = sec->block;
+ len -= ivlen;
+ if(len < 0)
+ rcvError(tr, EDecodeError, "runt record message");
+ unpad_len -= ivlen;
+ p += ivlen;
+ }
+
+ if(unpad_len >= sec->maclen)
+ len = unpad_len - sec->maclen;
+
/* update length */
put16(header+3, len);
- put64(seq, in->seq);
- in->seq++;
- (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
- if(unpad_len < in->sec->maclen)
- rcvError(tr, EBadRecordMac, "short record mac");
- if(memcmp(hmac, p+len, in->sec->maclen) != 0)
- rcvError(tr, EBadRecordMac, "record mac mismatch");
- b->wp = b->rp + len;
+ aadlen = (*tr->packAAD)(in->seq++, header, aad);
+ if(sec->aead_dec != nil) {
+ len = (*sec->aead_dec)(sec, aad, aadlen, p, unpad_len);
+ if(len < 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ } else {
+ packMac(sec, aad, aadlen, p, len, hmac);
+ if(unpad_len < sec->maclen)
+ rcvError(tr, EBadRecordMac, "short record mac");
+ if(tsmemcmp(hmac, p + len, sec->maclen) != 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ }
+ b->rp = p;
+ b->wp = p+len;
}
qunlock(&in->seclock);
poperror();
@@ -823,7 +854,7 @@
switch(type) {
default:
- rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type);
+ rcvError(tr, EIllegalParameter, "invalid record message %#x", type);
break;
case RChangeCipherSpec:
if(len != 1 || p[0] != 1)
@@ -848,20 +879,27 @@
rcvError(tr, EIllegalParameter, "invalid alert fatal code");
/*
- * propate non-fatal alerts to handshaker
+ * propagate non-fatal alerts to handshaker
*/
- if(p[1] == ECloseNotify) {
+ switch(p[1]){
+ case ECloseNotify:
tlsclosed(tr, SRClose);
if(tr->opened)
error("tls hungup");
error("close notify");
- }
- if(p[1] == ENoRenegotiation)
+ break;
+ case ENoRenegotiation:
alertHand(tr, "no renegotiation");
- else if(p[1] == EUserCanceled)
+ break;
+ case EUserCanceled:
alertHand(tr, "handshake canceled by user");
- else
+ break;
+ case EUnrecognizedName:
+ /* happens in response to SNI, can be ignored. */
+ break;
+ default:
rcvError(tr, EIllegalParameter, "invalid alert code");
+ }
break;
case RHandshake:
/*
@@ -1074,7 +1112,7 @@
/* return at most what was asked for */
b = qgrab(&tr->processed, n);
-if(tr->debug) pprint("consumed processed %d\n", BLEN(b));
+if(tr->debug) pprint("consumed processed %zd\n", BLEN(b));
if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");
qunlock(&tr->in.io);
poperror();
@@ -1142,7 +1180,7 @@
s = buf;
e = buf + Statlen;
s = seprint(s, e, "State: %s\n", tlsstate(tr->state));
- s = seprint(s, e, "Version: 0x%x\n", tr->version);
+ s = seprint(s, e, "Version: %#x\n", tr->version);
if(tr->in.sec != nil)
s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);
if(tr->in.new != nil)
@@ -1202,6 +1240,13 @@
return n;
}
+static void
+randfill(uchar *buf, int len)
+{
+ while(len-- > 0)
+ *buf++ = nrand(256);
+}
+
/*
* write a block in tls records
*/
@@ -1210,9 +1255,10 @@
{
Block *volatile bb;
Block *nb;
- uchar *p, seq[8];
+ uchar *p, aad[8+RecHdrLen];
OneWay *volatile out;
- int n, maclen, pad, ok;
+ int n, ivlen, maclen, aadlen, pad, ok;
+ Secret *sec;
out = &tr->out;
bb = b;
@@ -1223,7 +1269,7 @@
nexterror();
}
qlock(&out->io);
-if(tr->debug)pprint("send %d\n", BLEN(b));
+if(tr->debug)pprint("send %zd\n", BLEN(b));
if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
@@ -1245,21 +1291,25 @@
qlock(&out->seclock);
maclen = 0;
pad = 0;
- if(out->sec != nil){
- maclen = out->sec->maclen;
- pad = maclen + out->sec->block;
+ ivlen = 0;
+ sec = out->sec;
+ if(sec != nil){
+ maclen = sec->maclen;
+ pad = maclen + sec->block;
+ if(tr->version >= TLS11Version)
+ ivlen = sec->block;
}
n = BLEN(bb);
if(n > MaxRecLen){
n = MaxRecLen;
- nb = allocb(n + pad + RecHdrLen);
- memmove(nb->wp + RecHdrLen, bb->rp, n);
+ nb = allocb(RecHdrLen + ivlen + n + pad);
+ memmove(nb->wp + RecHdrLen + ivlen, bb->rp, n);
bb->rp += n;
}else{
/*
* carefully reuse bb so it will get freed if we're out of memory
*/
- bb = padblock(bb, RecHdrLen);
+ bb = padblock(bb, RecHdrLen + ivlen);
if(pad)
nb = padblock(bb, -pad);
else
@@ -1272,14 +1322,16 @@
put16(p+1, tr->version);
put16(p+3, n);
- if(out->sec != nil){
- put64(seq, out->seq);
- out->seq++;
- (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
- n += maclen;
-
- /* encrypt */
- n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+ if(sec != nil){
+ if(ivlen > 0)
+ randfill(p + RecHdrLen, ivlen);
+ aadlen = (*tr->packAAD)(out->seq++, p, aad);
+ if(sec->aead_enc != nil)
+ n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen + ivlen, n) + ivlen;
+ else {
+ packMac(sec, aad, aadlen, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
+ n = (*sec->enc)(sec, p + RecHdrLen, ivlen + n + maclen);
+ }
nb->wp = p + RecHdrLen + n;
/* update length */
@@ -1323,7 +1375,7 @@
tr = tlsdevs[CONV(c->qid)];
if(tr == nil)
- panic("tlsbread");
+ panic("tlsbwrite");
ty = TYPE(c->qid);
switch(ty) {
@@ -1363,7 +1415,7 @@
}
static void
-initclearmac(Hashalg *unused1, int unused2, Secret *s, uchar *unused3)
+initclearmac(Hashalg *ha, int version, Secret *s, uchar *p)
{
s->maclen = 0;
s->mac = nomac;
@@ -1380,11 +1432,22 @@
memmove(s->mackey, p, ha->maclen);
}
+static void
+initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ if(version == SSL3Version)
+ error("sha256 cannot be used with SSL");
+ s->maclen = ha->maclen;
+ s->mac = hmac_sha2_256;
+ memmove(s->mackey, p, ha->maclen);
+}
+
static Hashalg hashtab[] =
{
- { "clear", 0, initclearmac, },
- { "md5", MD5dlen, initmd5key, },
- { "sha1", SHA1dlen, initsha1key, },
+ { "clear", 0, initclearmac, },
+ { "md5", MD5dlen, initmd5key, },
+ { "sha1", SHA1dlen, initsha1key, },
+ { "sha256", SHA2_256dlen, initsha2_256key, },
{ 0 }
};
@@ -1410,7 +1473,7 @@
};
static void
-initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *unused1)
+initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(RC4state));
s->enc = rc4enc;
@@ -1420,7 +1483,7 @@
}
static void
-initDES3key(Encalg *unused1, Secret *s, uchar *p, uchar *iv)
+initDES3key(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
s->enckey = smalloc(sizeof(DES3state));
s->enc = des3enc;
@@ -1430,18 +1493,53 @@
}
static void
-initclearenc(Encalg *unused1, Secret *s, uchar *unused2, uchar *unused3)
+initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
+ s->enckey = smalloc(sizeof(AESstate));
+ s->enc = aesenc;
+ s->dec = aesdec;
+ s->block = 16;
+ setupAESstate(s->enckey, p, ea->keylen, iv);
+}
+
+static void
+initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+ s->enckey = smalloc(sizeof(Chachastate));
s->enc = noenc;
s->dec = noenc;
+ s->mac = nomac;
+ s->aead_enc = ccpoly_aead_enc;
+ s->aead_dec = ccpoly_aead_dec;
s->block = 0;
+ s->maclen = Poly1305dlen;
+ if(ea->ivlen == 0) {
+ /* older draft version, iv is 64-bit sequence number */
+ setupChachastate(s->enckey, p, ea->keylen, nil, 64/8, 20);
+ } else {
+ /* IETF standard, 96-bit iv xored with sequence number */
+ memmove(s->mackey, iv, ea->ivlen);
+ setupChachastate(s->enckey, p, ea->keylen, iv, ea->ivlen, 20);
+ }
}
+static void
+initclearenc(Encalg *ea, Secret *s, uchar *key, uchar *iv)
+{
+ s->enc = noenc;
+ s->dec = noenc;
+ s->block = 0;
+}
+
static Encalg encrypttab[] =
{
{ "clear", 0, 0, initclearenc },
{ "rc4_128", 128/8, 0, initRC4key },
{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
+ { "aes_128_cbc", 128/8, 16, initAESkey },
+ { "aes_256_cbc", 256/8, 16, initAESkey },
+ { "ccpoly64_aead", 256/8, 0, initccpolykey },
+ { "ccpoly96_aead", 256/8, 96/8, initccpolykey },
{ 0 }
};
@@ -1543,12 +1641,12 @@
if(tr->verset)
error("version already set");
m = strtol(cb->f[1], nil, 0);
+ if(m < MinProtoVersion || m > MaxProtoVersion)
+ error("unsupported version");
if(m == SSL3Version)
- tr->packMac = sslPackMac;
- else if(m == TLSVersion)
- tr->packMac = tlsPackMac;
+ tr->packAAD = sslPackAAD;
else
- error("unsupported version");
+ tr->packAAD = tlsPackAAD;
tr->verset = 1;
tr->version = m;
}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1812,7 +1910,7 @@
{
int s;
-if(tr->debug)pprint("tleError %s\n", msg);
+if(tr->debug)pprint("tlsError %s\n", msg);
lock(&tr->statelk);
s = tr->state;
tr->state = SError;
@@ -1951,7 +2049,7 @@
}
static int
-noenc(Secret *unused1, uchar *unused2, int n)
+noenc(Secret *sec, uchar *buf, int n)
{
return n;
}
@@ -2017,9 +2115,64 @@
des3CBCdecrypt(buf, n, sec->enckey);
return (*sec->unpad)(buf, n, 8);
}
+
+static int
+aesenc(Secret *sec, uchar *buf, int n)
+{
+ n = blockpad(buf, n, 16);
+ aesCBCencrypt(buf, n, sec->enckey);
+ return n;
+}
+
+static int
+aesdec(Secret *sec, uchar *buf, int n)
+{
+ aesCBCdecrypt(buf, n, sec->enckey);
+ return (*sec->unpad)(buf, n, 16);
+}
+
+static void
+ccpoly_aead_setiv(Secret *sec, uchar seq[8])
+{
+ uchar iv[ChachaIVlen];
+ Chachastate *cs;
+ int i;
+
+ cs = (Chachastate*)sec->enckey;
+ if(cs->ivwords == 2){
+ chacha_setiv(cs, seq);
+ return;
+ }
+
+ memmove(iv, sec->mackey, ChachaIVlen);
+ for(i=0; i<8; i++)
+ iv[i+(ChachaIVlen-8)] ^= seq[i];
+
+ chacha_setiv(cs, iv);
+}
+
+static int
+ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len)
+{
+ ccpoly_aead_setiv(sec, aad);
+ ccpoly_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+ return len + sec->maclen;
+}
+
+static int
+ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len)
+{
+ len -= sec->maclen;
+ if(len < 0)
+ return -1;
+ ccpoly_aead_setiv(sec, aad);
+ if(ccpoly_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+ return -1;
+ return len;
+}
+
static DigestState*
-nomac(uchar *unused1, ulong unused2, uchar *unused3, ulong unused4,
- uchar *unused5, DigestState *unused6)
+nomac(uchar *p, ulong len, uchar *key, ulong keylen, uchar *digest, DigestState *s)
{
return nil;
}
@@ -2077,32 +2230,35 @@
return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
}
-static void
-sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+static int
+sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
{
- DigestState *s;
- uchar buf[11];
+ put64(aad, seq);
+ aad[8] = hdr[0];
+ aad[9] = hdr[3];
+ aad[10] = hdr[4];
+ return 11;
+}
- memmove(buf, seq, 8);
- buf[8] = header[0];
- buf[9] = header[3];
- buf[10] = header[4];
-
- s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
- (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+static int
+tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+{
+ put64(aad, seq);
+ aad[8] = hdr[0];
+ aad[9] = hdr[1];
+ aad[10] = hdr[2];
+ aad[11] = hdr[3];
+ aad[12] = hdr[4];
+ return 13;
}
static void
-tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+packMac(Secret *sec, uchar *aad, int aadlen, uchar *body, int bodylen, uchar *mac)
{
DigestState *s;
- uchar buf[13];
- memmove(buf, seq, 8);
- memmove(&buf[8], header, 5);
-
- s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
- (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+ s = (*sec->mac)(aad, aadlen, sec->mackey, sec->maclen, nil, nil);
+ (*sec->mac)(body, bodylen, sec->mackey, sec->maclen, mac, s);
}
static void
@@ -2115,10 +2271,10 @@
}
static void
-put64(uchar *p, vlong x)
+put64(uchar *p, u64int x)
{
- put32(p, (u32int)(x >> 32));
- put32(p+4, (u32int)x);
+ put32(p, x >> 32);
+ put32(p+4, x);
}
static void
@@ -2136,13 +2292,11 @@
p[1] = x;
}
-/*
static u32int
get32(uchar *p)
{
return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
}
-*/
static int
get16(uchar *p)
--- a/kern/stub.c
+++ b/kern/stub.c
@@ -145,6 +145,13 @@
USED(tag);
}
+void
+setrealloctag(void *v, uintptr tag)
+{
+ USED(v);
+ USED(tag);
+}
+
int
postnote(Proc *p, int x, char *msg, int flag)
{
--- a/kern/sysfile.c
+++ b/kern/sysfile.c
@@ -850,7 +850,6 @@
return l;
}
-
static void
starterror(void)
{
@@ -858,6 +857,13 @@
}
static void
+enderror(void)
+{
+ assert(up->nerrlab == 1);
+ poperror();
+}
+
+static void
_syserror(void)
{
char *p;
@@ -865,13 +871,6 @@
p = up->syserrstr;
up->syserrstr = up->errstr;
up->errstr = p;
-}
-
-static void
-enderror(void)
-{
- assert(up->nerrlab == 1);
- poperror();
}
int
--- a/libauth/attr.c
+++ b/libauth/attr.c
@@ -139,7 +139,7 @@
a = nil;
for(i=ntok-1; i>=0; i--){
t = tok[i];
- if((p = strchr(t, '='))){
+ if(p = strchr(t, '=')){
*p++ = '\0';
// if(p-2 >= t && p[-2] == ':'){
// p[-2] = '\0';
--- a/libauth/auth_getuserpasswd.c
+++ b/libauth/auth_getuserpasswd.c
@@ -15,7 +15,7 @@
for(;;){
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
return ret;
- if(getkey == 0)
+ if(getkey == nil)
return ARgiveup; /* don't know how */
if((*getkey)(rpc->arg) < 0)
return ARgiveup; /* user punted */
--- a/libauth/auth_proxy.c
+++ b/libauth/auth_proxy.c
@@ -4,7 +4,7 @@
#include <auth.h>
#include "authlocal.h"
-enum {
+enum {
ARgiveup = 100,
};
@@ -90,7 +90,6 @@
if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
return nil;
- a = nil;
if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
werrstr("bad auth info from factotum");
return nil;
@@ -106,7 +105,7 @@
for(;;){
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
return ret;
- if(getkey == 0)
+ if(getkey == nil)
return ARgiveup; /* don't know how */
if((*getkey)(rpc->arg) < 0)
return ARgiveup; /* user punted */
@@ -124,6 +123,11 @@
AuthInfo *a;
char oerr[ERRMAX];
+ if(rpc == nil){
+ werrstr("fauth_proxy - no factotum");
+ return nil;
+ }
+
rerrstr(oerr, sizeof oerr);
werrstr("UNKNOWN AUTH ERROR");
@@ -140,7 +144,8 @@
case ARdone:
free(buf);
a = auth_getinfo(rpc);
- errstr(oerr, sizeof oerr); /* no error, restore whatever was there */
+ /* no error, restore whatever was there */
+ errstr(oerr, sizeof oerr);
return a;
case ARok:
if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
@@ -152,18 +157,21 @@
n = 0;
memset(buf, 0, AuthRpcMax);
while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
- if(atoi(rpc->arg) > AuthRpcMax)
+ m = atoi(rpc->arg);
+ if(m <= n || m > AuthRpcMax)
break;
- m = read(fd, buf+n, atoi(rpc->arg)-n);
+ m = read(fd, buf + n, m - n);
if(m <= 0){
if(m == 0)
- werrstr("auth_proxy short read: %s", buf);
+ werrstr("auth_proxy short read");
+ else
+ werrstr("auth_proxy read fd: %r");
goto Error;
}
n += m;
}
if(ret != ARok){
- werrstr("auth_proxy rpc write: %s: %r", buf);
+ werrstr("auth_proxy rpc write: %r");
goto Error;
}
break;
@@ -191,6 +199,7 @@
p = vsmprint(fmt, arg);
va_end(arg);
+ ai = nil;
afd = open("/mnt/factotum/rpc", ORDWR);
if(afd < 0){
werrstr("opening /mnt/factotum/rpc: %r");
@@ -199,15 +208,11 @@
}
rpc = auth_allocrpc(afd);
- if(rpc == nil){
- free(p);
- return nil;
+ if(rpc){
+ ai = fauth_proxy(fd, rpc, getkey, p);
+ auth_freerpc(rpc);
}
-
- ai = fauth_proxy(fd, rpc, getkey, p);
- free(p);
- auth_freerpc(rpc);
close(afd);
+ free(p);
return ai;
}
-
--- a/libauth/auth_respond.c
+++ b/libauth/auth_respond.c
@@ -16,7 +16,7 @@
for(;;){
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
return ret;
- if(getkey == 0)
+ if(getkey == nil)
return ARgiveup; /* don't know how */
if((*getkey)(rpc->arg) < 0)
return ARgiveup; /* user punted */
--- a/libauth/auth_userpasswd.c
+++ b/libauth/auth_userpasswd.c
@@ -11,22 +11,21 @@
* this was copied from inet's guard.
*/
static void
-netresp(char *key, long chal, char *answer)
+netresp(char key[DESKEYLEN], long chal, char *answer)
{
uchar buf[8];
- memset(buf, 0, 8);
- sprint((char *)buf, "%lud", chal);
+ memset(buf, 0, sizeof buf);
+ snprint((char *)buf, sizeof buf, "%lud", chal);
if(encrypt(key, buf, 8) < 0)
abort();
- chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
- sprint(answer, "%.8lux", chal);
+ sprint(answer, "%.8ux", buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]);
}
AuthInfo*
auth_userpasswd(char *user, char *passwd)
{
- char key[DESKEYLEN], resp[16];
+ char resp[16], key[DESKEYLEN];
AuthInfo *ai;
Chalstate *ch;
@@ -38,9 +37,9 @@
if((ch = auth_challenge("user=%q proto=p9cr role=server", user)) == nil)
return nil;
- passtokey(key, passwd);
+ passtodeskey(key, passwd);
netresp(key, atol(ch->chal), resp);
- memset(key, 0, sizeof key);
+ memset(key, 0, sizeof(key));
ch->resp = resp;
ch->nresp = strlen(resp);
--- a/libauthsrv/Makefile
+++ b/libauthsrv/Makefile
@@ -16,11 +16,19 @@
nvcsum.$O\
opasstokey.$O\
passtokey.$O\
+ _asgetpakkey.$O\
+ _asgetresp.$O\
+ _asrequest.$O\
+ authpak.$O\
+ form1.$O\
+
default: $(LIB)
$(LIB): $(OFILES)
$(AR) r $(LIB) $(OFILES)
$(RANLIB) $(LIB)
+
+authpak.$O: msqrt.mpc edwards.mpc ed448.mpc decaf.mpc elligator2.mpc spake2ee.mpc
%.$O: %.c
$(CC) $(CFLAGS) $*.c
--- /dev/null
+++ b/libauthsrv/_asgetpakkey.c
@@ -1,0 +1,26 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+
+int
+_asgetpakkey(int fd, Ticketreq *tr, Authkey *a)
+{
+ uchar y[PAKYLEN];
+ PAKpriv p;
+ int type;
+
+ type = tr->type;
+ tr->type = AuthPAK;
+ if(_asrequest(fd, tr) != 0){
+ tr->type = type;
+ return -1;
+ }
+ tr->type = type;
+ authpak_new(&p, a, y, 1);
+ if(write(fd, y, PAKYLEN) != PAKYLEN
+ || _asrdresp(fd, (char*)y, PAKYLEN) != PAKYLEN){
+ memset(&p, 0, sizeof(p));
+ return -1;
+ }
+ return authpak_finish(&p, a, y);
+}
--- /dev/null
+++ b/libauthsrv/_asgetresp.c
@@ -1,0 +1,44 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+
+int
+_asgetresp(int fd, Ticket *t, Authenticator *a, Authkey *k)
+{
+ char buf[MAXTICKETLEN+MAXAUTHENTLEN], err[ERRMAX];
+ int n, m;
+
+ memset(t, 0, sizeof(Ticket));
+ if(a != nil)
+ memset(a, 0, sizeof(Authenticator));
+
+ strcpy(err, "AS protocol botch");
+ errstr(err, ERRMAX);
+
+ if(_asrdresp(fd, buf, 0) < 0)
+ return -1;
+
+ for(n = 0; (m = convM2T(buf, n, t, k)) <= 0; n += m){
+ m = -m;
+ if(m <= n || m > sizeof(buf))
+ return -1;
+ m -= n;
+ if(readn(fd, buf+n, m) != m)
+ return -1;
+ }
+
+ if(a != nil){
+ for(n = 0; (m = convM2A(buf, n, a, t)) <= 0; n += m){
+ m = -m;
+ if(m <= n || m > sizeof(buf))
+ return -1;
+ m -= n;
+ if(readn(fd, buf+n, m) != m)
+ return -1;
+ }
+ }
+
+ errstr(err, ERRMAX);
+
+ return 0;
+}
--- a/libauthsrv/_asgetticket.c
+++ b/libauthsrv/_asgetticket.c
@@ -2,15 +2,36 @@
#include <libc.h>
#include <authsrv.h>
-static char *pbmsg = "AS protocol botch";
-
int
-_asgetticket(int fd, char *trbuf, char *tbuf)
+_asgetticket(int fd, Ticketreq *tr, char *tbuf, int tbuflen)
{
- if(write(fd, trbuf, TICKREQLEN) < 0){
- close(fd);
- werrstr(pbmsg);
+ char err[ERRMAX];
+ int i, n, m, r;
+
+ strcpy(err, "AS protocol botch");
+ errstr(err, ERRMAX);
+
+ if(_asrequest(fd, tr) < 0)
return -1;
+ if(_asrdresp(fd, tbuf, 0) < 0)
+ return -1;
+
+ r = 0;
+ for(i = 0; i<2; i++){
+ for(n=0; (m = convM2T(tbuf, n, nil, nil)) <= 0; n += m){
+ m = -m;
+ if(m <= n || m > tbuflen)
+ return -1;
+ m -= n;
+ if(readn(fd, tbuf+n, m) != m)
+ return -1;
+ }
+ r += n;
+ tbuf += n;
+ tbuflen -= n;
}
- return _asrdresp(fd, tbuf, 2*TICKETLEN);
+
+ errstr(err, ERRMAX);
+
+ return r;
}
--- /dev/null
+++ b/libauthsrv/_asrequest.c
@@ -1,0 +1,16 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+
+int
+_asrequest(int fd, Ticketreq *tr)
+{
+ char trbuf[TICKREQLEN];
+ int n;
+
+ n = convTR2M(tr, trbuf, sizeof(trbuf));
+ if(write(fd, trbuf, n) != n)
+ return -1;
+
+ return 0;
+}
--- a/libauthsrv/authdial.c
+++ b/libauthsrv/authdial.c
@@ -7,25 +7,45 @@
int
authdial(char *netroot, char *dom)
{
- char server[Ndbvlen];
- Ndbtuple *nt;
+ Ndbtuple *t, *nt;
+ char *p;
+ int rv;
-
- if(dom != nil){
- /* look up an auth server in an authentication domain */
- nt = csgetval(netroot, "authdom", dom, "auth", server);
-
- /* if that didn't work, just try the IP domain */
- if(nt == nil)
- nt = csgetval(netroot, "dom", dom, "auth", server);
- if(nt == nil){
- werrstr("no auth server found for %s", dom);
- return -1;
- }
- ndbfree(nt);
- return dial(netmkaddr(server, netroot, "ticket"), 0, 0, 0);
- } else {
+ if(dom == nil)
/* look for one relative to my machine */
return dial(netmkaddr("$auth", netroot, "ticket"), 0, 0, 0);
+
+ /* look up an auth server in an authentication domain */
+ p = csgetvalue(netroot, "authdom", dom, "auth", &t);
+
+ /* if that didn't work, just try the IP domain */
+ if(p == nil)
+ p = csgetvalue(netroot, "dom", dom, "auth", &t);
+
+ /*
+ * if that didn't work, try p9auth.$dom. this is very helpful if
+ * you can't edit /lib/ndb.
+ */
+ if(p == nil) {
+ p = smprint("p9auth.%s", dom);
+ t = ndbnew("auth", p);
}
+ free(p);
+
+ /*
+ * allow multiple auth= attributes for backup auth servers,
+ * try each one in order.
+ */
+ rv = -1;
+ for(nt = t; nt != nil; nt = nt->entry) {
+ if(strcmp(nt->attr, "auth") == 0) {
+ p = netmkaddr(nt->val, netroot, "ticket");
+ rv = dial(p, 0, 0, 0);
+ if(rv >= 0)
+ break;
+ }
+ }
+ ndbfree(t);
+
+ return rv;
}
--- /dev/null
+++ b/libauthsrv/authpak.c
@@ -1,0 +1,214 @@
+#include <u.h>
+#include <libc.h>
+#include <mp.h>
+#include <libsec.h>
+#include <authsrv.h>
+
+#include "msqrt.mpc"
+#include "decaf.mpc"
+#include "edwards.mpc"
+#include "elligator2.mpc"
+#include "spake2ee.mpc"
+#include "ed448.mpc"
+
+typedef struct PAKcurve PAKcurve;
+struct PAKcurve
+{
+ Lock;
+ mpint *P;
+ mpint *A;
+ mpint *D;
+ mpint *X;
+ mpint *Y;
+};
+
+static PAKcurve*
+authpak_curve(void)
+{
+ static PAKcurve a;
+
+ lock(&a);
+ if(a.P == nil){
+ a.P = mpnew(0);
+ a.A = mpnew(0);
+ a.D = mpnew(0);
+ a.X = mpnew(0);
+ a.Y = mpnew(0);
+ ed448_curve(a.P, a.A, a.D, a.X, a.Y);
+ a.P = mpfield(a.P);
+ }
+ unlock(&a);
+ return &a;
+}
+
+void
+authpak_hash(Authkey *k, char *u)
+{
+ static char info[] = "Plan 9 AuthPAK hash";
+ uchar *bp, salt[SHA2_256dlen], h[2*PAKSLEN];
+ mpint *H, *PX,*PY,*PZ,*PT;
+ PAKcurve *c;
+
+ H = mpnew(0);
+ PX = mpnew(0);
+ PY = mpnew(0);
+ PZ = mpnew(0);
+ PT = mpnew(0);
+
+ sha2_256((uchar*)u, strlen(u), salt, nil);
+
+ hkdf_x( salt, SHA2_256dlen,
+ (uchar*)info, sizeof(info)-1,
+ k->aes, AESKEYLEN,
+ h, sizeof(h),
+ hmac_sha2_256, SHA2_256dlen);
+
+ c = authpak_curve();
+
+ betomp(h + 0*PAKSLEN, PAKSLEN, H); /* HM */
+ spake2ee_h2P(c->P,c->A,c->D, H, PX,PY,PZ,PT); /* PM */
+
+ bp = k->pakhash;
+ mptober(PX, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PY, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PZ, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PT, bp, PAKSLEN), bp += PAKSLEN;
+
+ betomp(h + 1*PAKSLEN, PAKSLEN, H); /* HN */
+ spake2ee_h2P(c->P,c->A,c->D, H, PX,PY,PZ,PT); /* PN */
+
+ mptober(PX, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PY, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PZ, bp, PAKSLEN), bp += PAKSLEN;
+ mptober(PT, bp, PAKSLEN);
+
+ mpfree(PX);
+ mpfree(PY);
+ mpfree(PZ);
+ mpfree(PT);
+ mpfree(H);
+}
+
+void
+authpak_new(PAKpriv *p, Authkey *k, uchar y[PAKYLEN], int isclient)
+{
+ mpint *PX,*PY,*PZ,*PT, *X, *Y;
+ PAKcurve *c;
+ uchar *bp;
+
+ memset(p, 0, sizeof(PAKpriv));
+ p->isclient = isclient != 0;
+
+ X = mpnew(0);
+ Y = mpnew(0);
+
+ PX = mpnew(0);
+ PY = mpnew(0);
+ PZ = mpnew(0);
+ PT = mpnew(0);
+
+ PX->flags |= MPtimesafe;
+ PY->flags |= MPtimesafe;
+ PZ->flags |= MPtimesafe;
+ PT->flags |= MPtimesafe;
+
+ bp = k->pakhash + PAKPLEN*(p->isclient == 0);
+ betomp(bp, PAKSLEN, PX), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PY), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PZ), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PT);
+
+ c = authpak_curve();
+
+ X->flags |= MPtimesafe;
+ mpnrand(c->P, genrandom, X);
+
+ spake2ee_1(c->P,c->A,c->D, X, c->X,c->Y, PX,PY,PZ,PT, Y);
+
+ mptober(X, p->x, PAKXLEN);
+ mptober(Y, p->y, PAKYLEN);
+
+ memmove(y, p->y, PAKYLEN);
+
+ mpfree(PX);
+ mpfree(PY);
+ mpfree(PZ);
+ mpfree(PT);
+
+ mpfree(X);
+ mpfree(Y);
+}
+
+int
+authpak_finish(PAKpriv *p, Authkey *k, uchar y[PAKYLEN])
+{
+ static char info[] = "Plan 9 AuthPAK key";
+ uchar *bp, z[PAKSLEN], salt[SHA2_256dlen];
+ mpint *PX,*PY,*PZ,*PT, *X, *Y, *Z, *ok;
+ DigestState *s;
+ PAKcurve *c;
+ int ret;
+
+ X = mpnew(0);
+ Y = mpnew(0);
+ Z = mpnew(0);
+ ok = mpnew(0);
+
+ PX = mpnew(0);
+ PY = mpnew(0);
+ PZ = mpnew(0);
+ PT = mpnew(0);
+
+ PX->flags |= MPtimesafe;
+ PY->flags |= MPtimesafe;
+ PZ->flags |= MPtimesafe;
+ PT->flags |= MPtimesafe;
+
+ bp = k->pakhash + PAKPLEN*(p->isclient != 0);
+ betomp(bp, PAKSLEN, PX), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PY), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PZ), bp += PAKSLEN;
+ betomp(bp, PAKSLEN, PT);
+
+ Z->flags |= MPtimesafe;
+ X->flags |= MPtimesafe;
+ betomp(p->x, PAKXLEN, X);
+
+ betomp(y, PAKYLEN, Y);
+
+ c = authpak_curve();
+ spake2ee_2(c->P,c->A,c->D, PX,PY,PZ,PT, X, Y, ok, Z);
+
+ if(mpcmp(ok, mpzero) == 0){
+ ret = -1;
+ goto out;
+ }
+
+ mptober(Z, z, sizeof(z));
+
+ s = sha2_256(p->isclient ? p->y : y, PAKYLEN, nil, nil);
+ sha2_256(p->isclient ? y : p->y, PAKYLEN, salt, s);
+
+ hkdf_x( salt, SHA2_256dlen,
+ (uchar*)info, sizeof(info)-1,
+ z, sizeof(z),
+ k->pakkey, PAKKEYLEN,
+ hmac_sha2_256, SHA2_256dlen);
+
+ ret = 0;
+out:
+ memset(z, 0, sizeof(z));
+ memset(p, 0, sizeof(PAKpriv));
+
+ mpfree(PX);
+ mpfree(PY);
+ mpfree(PZ);
+ mpfree(PT);
+
+ mpfree(X);
+ mpfree(Y);
+ mpfree(Z);
+ mpfree(ok);
+
+ return ret;
+}
--- a/libauthsrv/convA2M.c
+++ b/libauthsrv/convA2M.c
@@ -2,24 +2,35 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) *p++ = f->x
-#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2
-#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(p, f->x, n); p += n
+extern int form1B2M(char *ap, int n, uchar key[32]);
int
-convA2M(Authenticator *f, char *ap, char *key)
+convA2M(Authenticator *f, char *ap, int n, Ticket *t)
{
- int n;
uchar *p;
+ if(n < 1+CHALLEN)
+ return 0;
+
p = (uchar*)ap;
- CHAR(num);
- STRING(chal, CHALLEN);
- LONG(id);
- n = p - (uchar*)ap;
- if(key)
- encrypt(key, ap, n);
- return n;
+ *p++ = f->num;
+ memmove(p, f->chal, CHALLEN), p += CHALLEN;
+ switch(t->form){
+ case 0:
+ if(n < 1+CHALLEN+4)
+ return 0;
+
+ memset(p, 0, 4), p += 4; /* unused id field */
+ n = p - (uchar*)ap;
+ encrypt(t->key, ap, n);
+ return n;
+ case 1:
+ if(n < 12+CHALLEN+NONCELEN+16)
+ return 0;
+
+ memmove(p, f->rand, NONCELEN), p += NONCELEN;
+ return form1B2M(ap, (char*)p - ap, t->key);
+ }
+
+ return 0;
}
--- a/libauthsrv/convM2A.c
+++ b/libauthsrv/convM2A.c
@@ -2,22 +2,35 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) f->x = *p++
-#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
-#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(f->x, p, n); p += n
+extern int form1M2B(char *ap, int n, uchar key[32]);
-void
-convM2A(char *ap, Authenticator *f, char *key)
+int
+convM2A(char *ap, int n, Authenticator *f, Ticket *t)
{
- uchar *p;
+ uchar buf[MAXAUTHENTLEN], *p;
+ int m;
- if(key)
- decrypt(key, ap, AUTHENTLEN);
- p = (uchar*)ap;
- CHAR(num);
- STRING(chal, CHALLEN);
- LONG(id);
- USED(p);
+ memset(f, 0, sizeof(Authenticator));
+ if(t->form == 0){
+ m = 1+CHALLEN+4;
+ if(n < m)
+ return -m;
+ memmove(buf, ap, m);
+ decrypt(t->key, buf, m);
+ } else {
+ m = 12+CHALLEN+NONCELEN+16;
+ if(n < m)
+ return -m;
+ memmove(buf, ap, m);
+ if(form1M2B((char*)buf, m, t->key) < 0)
+ return m;
+ }
+ p = buf;
+ f->num = *p++;
+ memmove(f->chal, p, CHALLEN);
+ p += CHALLEN;
+ if(t->form == 1)
+ memmove(f->rand, p, NONCELEN);
+
+ return m;
}
--- a/libauthsrv/convM2PR.c
+++ b/libauthsrv/convM2PR.c
@@ -2,27 +2,38 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) f->x = *p++
-#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
-#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(f->x, p, n); p += n
+extern int form1M2B(char *ap, int n, uchar key[32]);
-void
-convM2PR(char *ap, Passwordreq *f, char *key)
+int
+convM2PR(char *ap, int n, Passwordreq *f, Ticket *t)
{
- uchar *p;
+ uchar *p, buf[MAXPASSREQLEN];
+ int m;
- p = (uchar*)ap;
- if(key)
- decrypt(key, ap, PASSREQLEN);
- CHAR(num);
- STRING(old, ANAMELEN);
+ memset(f, 0, sizeof(Passwordreq));
+ if(t->form == 0){
+ m = 1+2*ANAMELEN+1+SECRETLEN;
+ if(n < m)
+ return -m;
+ memmove(buf, ap, m);
+ decrypt(t->key, buf, m);
+ } else {
+ m = 12+2*ANAMELEN+1+SECRETLEN+16;
+ if(n < m)
+ return -m;
+ memmove(buf, ap, m);
+ if(form1M2B((char*)buf, m, t->key) < 0)
+ return m;
+ }
+ p = buf;
+ f->num = *p++;
+ memmove(f->old, p, ANAMELEN), p += ANAMELEN;
+ memmove(f->new, p, ANAMELEN), p += ANAMELEN;
+ f->changesecret = *p++;
+ memmove(f->secret, p, SECRETLEN);
f->old[ANAMELEN-1] = 0;
- STRING(new, ANAMELEN);
f->new[ANAMELEN-1] = 0;
- CHAR(changesecret);
- STRING(secret, SECRETLEN);
f->secret[SECRETLEN-1] = 0;
- USED(p);
+
+ return m;
}
--- a/libauthsrv/convM2T.c
+++ b/libauthsrv/convM2T.c
@@ -2,27 +2,50 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) f->x = *p++
-#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
-#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(f->x, p, n); p += n
+extern int form1check(char *ap, int n);
+extern int form1M2B(char *ap, int n, uchar key[32]);
-void
-convM2T(char *ap, Ticket *f, char *key)
+int
+convM2T(char *ap, int n, Ticket *f, Authkey *k)
{
- uchar *p;
+ uchar buf[MAXTICKETLEN], *p;
+ int m;
- if(key)
- decrypt(key, ap, TICKETLEN);
- p = (uchar*)ap;
- CHAR(num);
- STRING(chal, CHALLEN);
- STRING(cuid, ANAMELEN);
+ if(f != nil)
+ memset(f, 0, sizeof(Ticket));
+
+ if(n < 8)
+ return -8;
+
+ if(form1check(ap, n) < 0){
+ m = 1+CHALLEN+2*ANAMELEN+DESKEYLEN;
+ if(n < m)
+ return -m;
+ if(f == nil || k == nil)
+ return m;
+ f->form = 0;
+ memmove(buf, ap, m);
+ decrypt(k->des, buf, m);
+ } else {
+ m = 12+CHALLEN+2*ANAMELEN+NONCELEN+16;
+ if(n < m)
+ return -m;
+ if(f == nil || k == nil)
+ return m;
+ f->form = 1;
+ memmove(buf, ap, m);
+ if(form1M2B((char*)buf, m, k->pakkey) < 0)
+ return m;
+ }
+ p = buf;
+ f->num = *p++;
+ memmove(f->chal, p, CHALLEN), p += CHALLEN;
+ memmove(f->cuid, p, ANAMELEN), p += ANAMELEN;
+ memmove(f->suid, p, ANAMELEN), p += ANAMELEN;
+ memmove(f->key, p, f->form == 0 ? DESKEYLEN : NONCELEN);
+
f->cuid[ANAMELEN-1] = 0;
- STRING(suid, ANAMELEN);
f->suid[ANAMELEN-1] = 0;
- STRING(key, DESKEYLEN);
- USED(p);
-}
+ return m;
+}
--- a/libauthsrv/convM2TR.c
+++ b/libauthsrv/convM2TR.c
@@ -2,27 +2,28 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) f->x = *p++
-#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
-#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(f->x, p, n); p += n
-
-void
-convM2TR(char *ap, Ticketreq *f)
+int
+convM2TR(char *ap, int n, Ticketreq *f)
{
uchar *p;
+ memset(f, 0, sizeof(Ticketreq));
+ if(n < TICKREQLEN)
+ return -TICKREQLEN;
+
p = (uchar*)ap;
- CHAR(type);
- STRING(authid, ANAMELEN);
+ f->type = *p++;
+ memmove(f->authid, p, ANAMELEN), p += ANAMELEN;
+ memmove(f->authdom, p, DOMLEN), p += DOMLEN;
+ memmove(f->chal, p, CHALLEN), p += CHALLEN;
+ memmove(f->hostid, p, ANAMELEN), p += ANAMELEN;
+ memmove(f->uid, p, ANAMELEN), p += ANAMELEN;
+
f->authid[ANAMELEN-1] = 0;
- STRING(authdom, DOMLEN);
f->authdom[DOMLEN-1] = 0;
- STRING(chal, CHALLEN);
- STRING(hostid, ANAMELEN);
f->hostid[ANAMELEN-1] = 0;
- STRING(uid, ANAMELEN);
f->uid[ANAMELEN-1] = 0;
- USED(p);
+ n = p - (uchar*)ap;
+
+ return n;
}
--- a/libauthsrv/convPR2M.c
+++ b/libauthsrv/convPR2M.c
@@ -2,27 +2,33 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) *p++ = f->x
-#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2
-#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(p, f->x, n); p += n
+extern int form1B2M(char *ap, int n, uchar key[32]);
int
-convPR2M(Passwordreq *f, char *ap, char *key)
+convPR2M(Passwordreq *f, char *ap, int n, Ticket *t)
{
- int n;
uchar *p;
+ if(n < 1+2*ANAMELEN+1+SECRETLEN)
+ return 0;
+
p = (uchar*)ap;
- CHAR(num);
- STRING(old, ANAMELEN);
- STRING(new, ANAMELEN);
- CHAR(changesecret);
- STRING(secret, SECRETLEN);
- n = p - (uchar*)ap;
- if(key)
- encrypt(key, ap, n);
- return n;
+ *p++ = f->num;
+ memmove(p, f->old, ANAMELEN), p += ANAMELEN;
+ memmove(p, f->new, ANAMELEN), p += ANAMELEN;
+ *p++ = f->changesecret;
+ memmove(p, f->secret, SECRETLEN), p += SECRETLEN;
+ switch(t->form){
+ case 0:
+ n = p - (uchar*)ap;
+ encrypt(t->key, ap, n);
+ return n;
+ case 1:
+ if(n < 12+2*ANAMELEN+1+SECRETLEN+16)
+ return 0;
+ return form1B2M(ap, p - (uchar*)ap, t->key);
+ }
+
+ return 0;
}
--- a/libauthsrv/convT2M.c
+++ b/libauthsrv/convT2M.c
@@ -1,27 +1,39 @@
#include <u.h>
#include <libc.h>
#include <authsrv.h>
+#include <libsec.h>
-#define CHAR(x) *p++ = f->x
-#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2
-#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(p, f->x, n); p += n
+extern int form1B2M(char *ap, int n, uchar key[32]);
int
-convT2M(Ticket *f, char *ap, char *key)
+convT2M(Ticket *f, char *ap, int n, Authkey *key)
{
- int n;
uchar *p;
+ if(n < 1+CHALLEN+2*ANAMELEN)
+ return 0;
+
p = (uchar*)ap;
- CHAR(num);
- STRING(chal, CHALLEN);
- STRING(cuid, ANAMELEN);
- STRING(suid, ANAMELEN);
- STRING(key, DESKEYLEN);
- n = p - (uchar*)ap;
- if(key)
- encrypt(key, ap, n);
- return n;
+ *p++ = f->num;
+ memmove(p, f->chal, CHALLEN), p += CHALLEN;
+ memmove(p, f->cuid, ANAMELEN), p += ANAMELEN;
+ memmove(p, f->suid, ANAMELEN), p += ANAMELEN;
+ switch(f->form){
+ case 0:
+ if(n < 1+CHALLEN+2*ANAMELEN+DESKEYLEN)
+ return 0;
+
+ memmove(p, f->key, DESKEYLEN), p += DESKEYLEN;
+ n = p - (uchar*)ap;
+ encrypt(key->des, ap, n);
+ return n;
+ case 1:
+ if(n < 12+CHALLEN+2*ANAMELEN+NONCELEN+16)
+ return 0;
+
+ memmove(p, f->key, NONCELEN), p += NONCELEN;
+ return form1B2M(ap, p - (uchar*)ap, key->pakkey);
+ }
+
+ return 0;
}
--- a/libauthsrv/convTR2M.c
+++ b/libauthsrv/convTR2M.c
@@ -2,26 +2,22 @@
#include <libc.h>
#include <authsrv.h>
-#define CHAR(x) *p++ = f->x
-#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2
-#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
-#define LONG(x) VLONG(f->x)
-#define STRING(x,n) memmove(p, f->x, n); p += n
-
int
-convTR2M(Ticketreq *f, char *ap)
+convTR2M(Ticketreq *f, char *ap, int n)
{
- int n;
uchar *p;
+ if(n < TICKREQLEN)
+ return 0;
+
p = (uchar*)ap;
- CHAR(type);
- STRING(authid, 28); /* BUG */
- STRING(authdom, DOMLEN);
- STRING(chal, CHALLEN);
- STRING(hostid, 28); /* BUG */
- STRING(uid, 28); /* BUG */
+ *p++ = f->type;
+ memmove(p, f->authid, ANAMELEN), p += ANAMELEN;
+ memmove(p, f->authdom, DOMLEN), p += DOMLEN;
+ memmove(p, f->chal, CHALLEN), p += CHALLEN;
+ memmove(p, f->hostid, ANAMELEN), p += ANAMELEN;
+ memmove(p, f->uid, ANAMELEN), p += ANAMELEN;
n = p - (uchar*)ap;
+
return n;
}
-
--- /dev/null
+++ b/libauthsrv/decaf.mpc
@@ -1,0 +1,130 @@
+void decaf_neg(mpint *p, mpint *n, mpint *r){
+ mpint *m = mpnew(0);
+ mpmodsub(mpzero, r, p, m);
+ mpint *tmp1 = mpnew(0);
+ mpsub(p, mpone, tmp1);
+ mpright(tmp1, 1, tmp1);
+ mpsel(-mpcmp(n, tmp1) >> (sizeof(int)*8-1), m, r, r);
+ mpfree(tmp1);
+ mpfree(m);
+ }
+void decaf_encode(mpint *p, mpint *a, mpint *d, mpint *X, mpint *Y, mpint *Z, mpint *T, mpint *s){
+ mpint *u = mpnew(0);
+ mpint *r = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ mpint *tmp2 = mpnew(0);
+ mpint *tmp3 = mpnew(0);
+ mpmodsub(a, d, p, tmp3);
+ mpint *tmp4 = mpnew(0);
+ mpmodadd(Z, Y, p, tmp4);
+ mpmodmul(tmp3, tmp4, p, tmp2);
+ mpfree(tmp3);
+ mpfree(tmp4);
+ tmp4 = mpnew(0);
+ mpmodsub(Z, Y, p, tmp4);
+ mpmodmul(tmp2, tmp4, p, tmp1);
+ mpfree(tmp2);
+ mpfree(tmp4);
+ misqrt(tmp1, p, r);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ mpmodsub(a, d, p, tmp1);
+ mpmodmul(tmp1, r, p, u);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ tmp4 = mpnew(0);
+ mpmodadd(u, u, p, tmp4); // 2*u
+ mpmodmul(tmp4, Z, p, tmp1);
+ mpfree(tmp4);
+ mpmodsub(mpzero, tmp1, p, tmp1);
+ decaf_neg(p, tmp1, r);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ tmp4 = mpnew(0);
+ tmp2 = mpnew(0);
+ tmp3 = mpnew(0);
+ mpmodmul(a, Z, p, tmp3);
+ mpmodmul(tmp3, X, p, tmp2);
+ mpfree(tmp3);
+ tmp3 = mpnew(0);
+ mpint *tmp5 = mpnew(0);
+ mpmodmul(d, Y, p, tmp5);
+ mpmodmul(tmp5, T, p, tmp3);
+ mpfree(tmp5);
+ mpmodsub(tmp2, tmp3, p, tmp2);
+ mpfree(tmp3);
+ mpmodmul(r, tmp2, p, tmp4);
+ mpfree(tmp2);
+ mpmodadd(tmp4, Y, p, tmp4);
+ mpmodmul(u, tmp4, p, tmp1);
+ mpfree(tmp4);
+ tmp4 = mpnew(0);
+ mpinvert(a, p, tmp4);
+ mpmodmul(tmp1, tmp4, p, s);
+ mpfree(tmp4);
+ mpfree(tmp1);
+ decaf_neg(p, s, s);
+ mpfree(u);
+ mpfree(r);
+ }
+void decaf_decode(mpint *p, mpint *a, mpint *d, mpint *s, mpint *ok, mpint *X, mpint *Y, mpint *Z, mpint *T){
+ mpint *w = mpnew(0);
+ mpint *v = mpnew(0);
+ mpint *u = mpnew(0);
+ mpint *ss = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ mpsub(p, mpone, tmp1);
+ mpright(tmp1, 1, tmp1);
+ if(mpcmp(s, tmp1) > 0){
+ mpassign(mpzero, ok);
+ }else{
+ mpmodmul(s, s, p, ss);
+ mpmodmul(a, ss, p, Z);
+ mpmodadd(mpone, Z, p, Z);
+ mpmodmul(Z, Z, p, u);
+ mpint *tmp2 = mpnew(0);
+ mpint *tmp3 = mpnew(0);
+ mpint *tmp4 = mpnew(0);
+ uitomp(4UL, tmp4);
+ mpmodmul(tmp4, d, p, tmp3);
+ mpfree(tmp4);
+ mpmodmul(tmp3, ss, p, tmp2);
+ mpfree(tmp3);
+ mpmodsub(u, tmp2, p, u);
+ mpfree(tmp2);
+ mpmodmul(u, ss, p, v);
+ if(mpcmp(v, mpzero) == 0){
+ mpassign(mpone, ok);
+ }else{
+ msqrt(v, p, ok);
+ if(mpcmp(ok, mpzero) != 0){
+ mpinvert(ok, p, v);
+ mpassign(mpone, ok);
+ }
+ }
+ if(mpcmp(ok, mpzero) != 0){
+ mpint *tmp5 = mpnew(0);
+ mpmodmul(u, v, p, tmp5);
+ decaf_neg(p, tmp5, v);
+ mpfree(tmp5);
+ tmp5 = mpnew(0);
+ mpmodmul(v, s, p, tmp5);
+ mpint *tmp6 = mpnew(0);
+ mpmodsub(mptwo, Z, p, tmp6);
+ mpmodmul(tmp5, tmp6, p, w);
+ mpfree(tmp5);
+ mpfree(tmp6);
+ if(mpcmp(s, mpzero) == 0){
+ mpmodadd(w, mpone, p, w);
+ }
+ mpmodadd(s, s, p, X); // 2*s
+ mpmodmul(w, Z, p, Y);
+ mpmodmul(w, X, p, T);
+ }
+ }
+ mpfree(tmp1);
+ mpfree(w);
+ mpfree(v);
+ mpfree(u);
+ mpfree(ss);
+ }
--- /dev/null
+++ b/libauthsrv/ed448.mpc
@@ -1,0 +1,8 @@
+void ed448_curve(mpint *p, mpint *a, mpint *d, mpint *x, mpint *y){
+ strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", nil, 16, p);
+ mpassign(mpone, a);
+ uitomp(39081UL, d);
+ d->sign = -1;
+ strtomp("297EA0EA2692FF1B4FAFF46098453A6A26ADF733245F065C3C59D0709CECFA96147EAAF3932D94C63D96C170033F4BA0C7F0DE840AED939F", nil, 16, x);
+ uitomp(19UL, y);
+ }
--- /dev/null
+++ b/libauthsrv/edwards.mpc
@@ -1,0 +1,98 @@
+void edwards_add(mpint *p, mpint *a, mpint *d, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X2, mpint *Y2, mpint *Z2, mpint *T2, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){
+ mpint *H = mpnew(0);
+ mpint *G = mpnew(0);
+ mpint *F = mpnew(0);
+ mpint *E = mpnew(0);
+ mpint *D = mpnew(0);
+ mpint *C = mpnew(0);
+ mpint *B = mpnew(0);
+ mpint *A = mpnew(0);
+ mpmodmul(X1, X2, p, A);
+ mpmodmul(Y1, Y2, p, B);
+ mpint *tmp1 = mpnew(0);
+ mpmodmul(d, T1, p, tmp1);
+ mpmodmul(tmp1, T2, p, C);
+ mpfree(tmp1);
+ mpmodmul(Z1, Z2, p, D);
+ tmp1 = mpnew(0);
+ mpmodadd(X1, Y1, p, tmp1);
+ mpint *tmp2 = mpnew(0);
+ mpmodadd(X2, Y2, p, tmp2);
+ mpmodmul(tmp1, tmp2, p, E);
+ mpfree(tmp1);
+ mpfree(tmp2);
+ mpmodsub(E, A, p, E);
+ mpmodsub(E, B, p, E);
+ mpmodsub(D, C, p, F);
+ mpmodadd(D, C, p, G);
+ mpmodmul(a, A, p, H);
+ mpmodsub(B, H, p, H);
+ mpmodmul(E, F, p, X3);
+ mpmodmul(G, H, p, Y3);
+ mpmodmul(F, G, p, Z3);
+ mpmodmul(E, H, p, T3);
+ mpfree(H);
+ mpfree(G);
+ mpfree(F);
+ mpfree(E);
+ mpfree(D);
+ mpfree(C);
+ mpfree(B);
+ mpfree(A);
+ }
+void edwards_sel(mpint *s, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X2, mpint *Y2, mpint *Z2, mpint *T2, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){
+ mpsel(mpcmp(s, mpzero), X1, X2, X3);
+ mpsel(mpcmp(s, mpzero), Y1, Y2, Y3);
+ mpsel(mpcmp(s, mpzero), Z1, Z2, Z3);
+ mpsel(mpcmp(s, mpzero), T1, T2, T3);
+ }
+void edwards_new(mpint *x, mpint *y, mpint *z, mpint *t, mpint *X, mpint *Y, mpint *Z, mpint *T){
+ mpassign(x, X);
+ mpassign(y, Y);
+ mpassign(z, Z);
+ mpassign(t, T);
+ }
+void edwards_scale(mpint *p, mpint *a, mpint *d, mpint *s, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){
+ mpint *j = mpnew(0);
+ mpint *k = mpnew(0);
+ mpint *T4 = mpnew(0);
+ mpint *Z4 = mpnew(0);
+ mpint *Y4 = mpnew(0);
+ mpint *X4 = mpnew(0);
+ mpint *T2 = mpnew(0);
+ mpint *Z2 = mpnew(0);
+ mpint *Y2 = mpnew(0);
+ mpint *X2 = mpnew(0);
+ edwards_new(X1, Y1, Z1, T1, X2, Y2, Z2, T2);
+ edwards_new(mpzero, mpone, mpone, mpzero, X4, Y4, Z4, T4);
+ mpint *tmp1 = mpnew(0);
+ mpmod(s, mptwo, tmp1);
+ edwards_sel(tmp1, X2, Y2, Z2, T2, X4, Y4, Z4, T4, X3, Y3, Z3, T3);
+ mpfree(tmp1);
+ mpright(s, 1, k);
+ mpright(p, 1, j);
+ for(;;){
+ if(mpcmp(j, mpzero) != 0){
+ edwards_add(p, a, d, X2, Y2, Z2, T2, X2, Y2, Z2, T2, X2, Y2, Z2, T2);
+ edwards_add(p, a, d, X2, Y2, Z2, T2, X3, Y3, Z3, T3, X4, Y4, Z4, T4);
+ mpint *tmp2 = mpnew(0);
+ mpmod(k, mptwo, tmp2);
+ edwards_sel(tmp2, X4, Y4, Z4, T4, X3, Y3, Z3, T3, X3, Y3, Z3, T3);
+ mpfree(tmp2);
+ mpright(k, 1, k);
+ mpright(j, 1, j);
+ }else{
+ break;
+ }
+ }
+ mpfree(j);
+ mpfree(k);
+ mpfree(T4);
+ mpfree(Z4);
+ mpfree(Y4);
+ mpfree(X4);
+ mpfree(T2);
+ mpfree(Z2);
+ mpfree(Y2);
+ mpfree(X2);
+ }
--- /dev/null
+++ b/libauthsrv/elligator2.mpc
@@ -1,0 +1,129 @@
+void elligator2(mpint *p, mpint *a, mpint *d, mpint *n, mpint *r0, mpint *X, mpint *Y, mpint *Z, mpint *T){
+ mpint *t = mpnew(0);
+ mpint *s = mpnew(0);
+ mpint *e = mpnew(0);
+ mpint *c = mpnew(0);
+ mpint *ND = mpnew(0);
+ mpint *N = mpnew(0);
+ mpint *D = mpnew(0);
+ mpint *r = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ mpmodmul(n, r0, p, tmp1);
+ mpmodmul(tmp1, r0, p, r);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ mpmodmul(d, r, p, tmp1);
+ mpmodadd(tmp1, a, p, tmp1);
+ mpmodsub(tmp1, d, p, tmp1);
+ mpint *tmp2 = mpnew(0);
+ mpmodmul(d, r, p, tmp2);
+ mpint *tmp3 = mpnew(0);
+ mpmodmul(a, r, p, tmp3);
+ mpmodsub(tmp2, tmp3, p, tmp2);
+ mpfree(tmp3);
+ mpmodsub(tmp2, d, p, tmp2);
+ mpmodmul(tmp1, tmp2, p, D);
+ mpfree(tmp1);
+ mpfree(tmp2);
+ tmp2 = mpnew(0);
+ mpmodadd(r, mpone, p, tmp2);
+ tmp1 = mpnew(0);
+ mpmodadd(d, d, p, tmp1); // 2*d
+ mpmodsub(a, tmp1, p, tmp1);
+ mpmodmul(tmp2, tmp1, p, N);
+ mpfree(tmp2);
+ mpfree(tmp1);
+ mpmodmul(N, D, p, ND);
+ if(mpcmp(ND, mpzero) == 0){
+ mpassign(mpone, c);
+ mpassign(mpzero, e);
+ }else{
+ msqrt(ND, p, e);
+ if(mpcmp(e, mpzero) != 0){
+ mpassign(mpone, c);
+ mpinvert(e, p, e);
+ }else{
+ mpmodsub(mpzero, mpone, p, c);
+ mpint *tmp4 = mpnew(0);
+ mpmodmul(n, r0, p, tmp4);
+ mpint *tmp5 = mpnew(0);
+ mpint *tmp6 = mpnew(0);
+ mpmodmul(n, ND, p, tmp6);
+ misqrt(tmp6, p, tmp5);
+ mpfree(tmp6);
+ mpmodmul(tmp4, tmp5, p, e);
+ mpfree(tmp4);
+ mpfree(tmp5);
+ }
+ }
+ tmp1 = mpnew(0);
+ mpmodmul(c, N, p, tmp1);
+ mpmodmul(tmp1, e, p, s);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ tmp2 = mpnew(0);
+ mpmodmul(c, N, p, tmp2);
+ tmp3 = mpnew(0);
+ mpmodsub(r, mpone, p, tmp3);
+ mpmodmul(tmp2, tmp3, p, tmp1);
+ mpfree(tmp2);
+ mpfree(tmp3);
+ tmp3 = mpnew(0);
+ tmp2 = mpnew(0);
+ mpmodadd(d, d, p, tmp2); // 2*d
+ mpmodsub(a, tmp2, p, tmp2);
+ mpmodmul(tmp2, e, p, tmp3);
+ mpfree(tmp2);
+ mpmodmul(tmp3, tmp3, p, tmp3);
+ mpmodmul(tmp1, tmp3, p, t);
+ mpfree(tmp1);
+ mpfree(tmp3);
+ mpmodsub(mpzero, t, p, t);
+ mpmodsub(t, mpone, p, t);
+ tmp3 = mpnew(0);
+ mpmodadd(s, s, p, tmp3); // 2*s
+ mpmodmul(tmp3, t, p, X);
+ mpfree(tmp3);
+ tmp3 = mpnew(0);
+ tmp1 = mpnew(0);
+ mpmodmul(a, s, p, tmp1);
+ mpmodmul(tmp1, s, p, tmp3);
+ mpfree(tmp1);
+ mpmodsub(mpone, tmp3, p, tmp3);
+ tmp1 = mpnew(0);
+ tmp2 = mpnew(0);
+ mpmodmul(a, s, p, tmp2);
+ mpmodmul(tmp2, s, p, tmp1);
+ mpfree(tmp2);
+ mpmodadd(mpone, tmp1, p, tmp1);
+ mpmodmul(tmp3, tmp1, p, Y);
+ mpfree(tmp3);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ tmp3 = mpnew(0);
+ mpmodmul(a, s, p, tmp3);
+ mpmodmul(tmp3, s, p, tmp1);
+ mpfree(tmp3);
+ mpmodadd(mpone, tmp1, p, tmp1);
+ mpmodmul(tmp1, t, p, Z);
+ mpfree(tmp1);
+ tmp1 = mpnew(0);
+ mpmodadd(s, s, p, tmp1); // 2*s
+ tmp3 = mpnew(0);
+ tmp2 = mpnew(0);
+ mpmodmul(a, s, p, tmp2);
+ mpmodmul(tmp2, s, p, tmp3);
+ mpfree(tmp2);
+ mpmodsub(mpone, tmp3, p, tmp3);
+ mpmodmul(tmp1, tmp3, p, T);
+ mpfree(tmp1);
+ mpfree(tmp3);
+ mpfree(t);
+ mpfree(s);
+ mpfree(e);
+ mpfree(c);
+ mpfree(ND);
+ mpfree(N);
+ mpfree(D);
+ mpfree(r);
+ }
--- /dev/null
+++ b/libauthsrv/form1.c
@@ -1,0 +1,90 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <libsec.h>
+
+/*
+ * new ticket format: the reply protector/type is replaced by a
+ * 8 byte signature and a 4 byte counter forming the 12 byte
+ * nonce for chacha20/poly1305 encryption. a 16 byte poly1305
+ * authentication tag is appended for message authentication.
+ * the counter is needed for the AuthPass message which uses
+ * the same key for several messages.
+ */
+
+static struct {
+ char num;
+ char sig[8];
+} form1sig[] = {
+ AuthPass, "form1 PR", /* password change request encrypted with ticket key */
+ AuthTs, "form1 Ts", /* ticket encrypted with server's key */
+ AuthTc, "form1 Tc", /* ticket encrypted with client's key */
+ AuthAs, "form1 As", /* server generated authenticator */
+ AuthAc, "form1 Ac", /* client generated authenticator */
+ AuthTp, "form1 Tp", /* ticket encrypted with client's key for password change */
+ AuthHr, "form1 Hr", /* http reply */
+};
+
+int
+form1check(char *ap, int n)
+{
+ if(n < 8)
+ return -1;
+
+ for(n=0; n<nelem(form1sig); n++)
+ if(memcmp(form1sig[n].sig, ap, 8) == 0)
+ return form1sig[n].num;
+
+ return -1;
+}
+
+int
+form1B2M(char *ap, int n, uchar key[32])
+{
+ static u32int counter;
+ Chachastate s;
+ uchar *p;
+ int i;
+
+ for(i=nelem(form1sig)-1; i>=0; i--)
+ if(form1sig[i].num == *ap)
+ break;
+ if(i < 0)
+ abort();
+
+ p = (uchar*)ap + 12;
+ memmove(p, ap+1, --n);
+
+ /* nonce[12] = sig[8] | counter[4] */
+ memmove(ap, form1sig[i].sig, 8);
+ i = counter++;
+ ap[8] = i, ap[9] = i>>8, ap[10] = i>>16, ap[11] = i>>24;
+
+ setupChachastate(&s, key, 32, (uchar*)ap, 12, 20);
+ ccpoly_encrypt(p, n, nil, 0, p+n, &s);
+ return 12+16 + n;
+}
+
+int
+form1M2B(char *ap, int n, uchar key[32])
+{
+ Chachastate s;
+ uchar *p;
+ int num;
+
+ num = form1check(ap, n);
+ if(num < 0)
+ return -1;
+ n -= 12+16;
+ if(n <= 0)
+ return -1;
+
+ p = (uchar*)ap + 12;
+ setupChachastate(&s, key, 32, (uchar*)ap, 12, 20);
+ if(ccpoly_decrypt(p, n, nil, 0, p+n, &s))
+ return -1;
+
+ memmove(ap+1, p, n);
+ ap[0] = num;
+ return n+1;
+}
--- /dev/null
+++ b/libauthsrv/msqrt.mpc
@@ -1,0 +1,149 @@
+void legendresymbol(mpint *a, mpint *p, mpint *r){
+ mpint *pm1 = mpnew(0);
+ mpsub(p, mpone, pm1);
+ mpright(pm1, 1, r);
+ mpexp(a, r, p, r);
+ if(mpcmp(r, pm1) == 0){
+ mpassign(mpone, r);
+ r->sign = -1;
+ }
+ mpfree(pm1);
+ }
+void msqrt(mpint *a, mpint *p, mpint *r){
+ mpint *gs = mpnew(0);
+ mpint *m = mpnew(0);
+ mpint *t = mpnew(0);
+ mpint *g = mpnew(0);
+ mpint *b = mpnew(0);
+ mpint *x = mpnew(0);
+ mpint *n = mpnew(0);
+ mpint *s = mpnew(0);
+ mpint *e = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ legendresymbol(a, p, tmp1);
+ if(mpcmp(tmp1, mpone) != 0){
+ mpassign(mpzero, r);
+ }else{
+ if(mpcmp(a, mpzero) == 0){
+ mpassign(mpzero, r);
+ }else{
+ if(mpcmp(p, mptwo) == 0){
+ mpassign(a, r);
+ }else{
+ mpint *tmp2 = mpnew(0);
+ uitomp(4UL, tmp2);
+ mpmod(p, tmp2, tmp2);
+ mpint *tmp3 = mpnew(0);
+ uitomp(3UL, tmp3);
+ if(mpcmp(tmp2, tmp3) == 0){
+ mpadd(p, mpone, e);
+ mpright(e, 2, e);
+ mpexp(a, e, p, r);
+ }else{
+ mpsub(p, mpone, s);
+ mpassign(mpzero, e);
+ for(;;){
+ mpint *tmp4 = mpnew(0);
+ mpmod(s, mptwo, tmp4);
+ if(mpcmp(tmp4, mpzero) == 0){
+ mpright(s, 1, s);
+ mpadd(e, mpone, e);
+ }else{
+ mpfree(tmp4);
+ break;
+ }
+ mpfree(tmp4);
+ }
+ mpassign(mptwo, n);
+ for(;;){
+ mpint *tmp5 = mpnew(0);
+ legendresymbol(n, p, tmp5);
+ mpint *tmp6 = mpnew(0);
+ mpassign(mpone, tmp6);
+ tmp6->sign = -1;
+ if(mpcmp(tmp5, tmp6) != 0){
+ mpadd(n, mpone, n);
+ }else{
+ mpfree(tmp6);
+ mpfree(tmp5);
+ break;
+ }
+ mpfree(tmp5);
+ mpfree(tmp6);
+ }
+ mpmodadd(s, mpone, p, x);
+ mpright(x, 1, x);
+ mpexp(a, x, p, x);
+ mpexp(a, s, p, b);
+ mpexp(n, s, p, g);
+ for(;;){
+ if(0 == 0){
+ mpassign(b, t);
+ mpassign(mpzero, m);
+ for(;;){
+ if(mpcmp(m, e) < 0){
+ if(mpcmp(t, mpone) == 0){
+ break;
+ }
+ mpmul(t, t, t);
+ mpmod(t, p, t);
+ mpadd(m, mpone, m);
+ }else{
+ break;
+ }
+ }
+ if(mpcmp(m, mpzero) == 0){
+ mpassign(x, r);
+ break;
+ }
+ mpsub(e, m, t);
+ mpsub(t, mpone, t);
+ mpexp(mptwo, t, nil, t);
+ mpexp(g, t, p, gs);
+ mpmodmul(gs, gs, p, g);
+ mpmodmul(x, gs, p, x);
+ mpmodmul(b, g, p, b);
+ mpassign(m, e);
+ }else{
+ break;
+ }
+ }
+ }
+ mpfree(tmp2);
+ mpfree(tmp3);
+ }
+ }
+ }
+ mpfree(tmp1);
+ mpfree(gs);
+ mpfree(m);
+ mpfree(t);
+ mpfree(g);
+ mpfree(b);
+ mpfree(x);
+ mpfree(n);
+ mpfree(s);
+ mpfree(e);
+ }
+void misqrt(mpint *a, mpint *p, mpint *r){
+ mpint *e = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ uitomp(4UL, tmp1);
+ mpmod(p, tmp1, tmp1);
+ mpint *tmp2 = mpnew(0);
+ uitomp(3UL, tmp2);
+ if(mpcmp(tmp1, tmp2) == 0){
+ uitomp(3UL, e);
+ mpsub(p, e, e);
+ mpright(e, 2, e);
+ mpexp(a, e, p, r);
+ }else{
+ msqrt(a, p, r);
+ if(mpcmp(r, mpzero) != 0){
+ mpinvert(r, p, r);
+ }
+ }
+ mpfree(tmp1);
+ mpfree(tmp2);
+ mpfree(e);
+ }
--- a/libauthsrv/passtokey.c
+++ b/libauthsrv/passtokey.c
@@ -1,9 +1,10 @@
#include <u.h>
#include <libc.h>
#include <authsrv.h>
+#include <libsec.h>
-int
-passtokey(char *key, char *p)
+void
+passtodeskey(char key[DESKEYLEN], char *p)
{
uchar buf[ANAMELEN], *t;
int i, n;
@@ -20,7 +21,7 @@
for(i = 0; i < DESKEYLEN; i++)
key[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1)));
if(n <= 8)
- return 1;
+ return;
n -= 8;
t += 8;
if(n < 8){
@@ -29,5 +30,19 @@
}
encrypt(key, t, 8);
}
- return 1; /* not reached */
+}
+
+void
+passtoaeskey(uchar key[AESKEYLEN], char *p)
+{
+ static char salt[] = "Plan 9 key derivation";
+ pbkdf2_x((uchar*)p, strlen(p), (uchar*)salt, sizeof(salt)-1, 9001, key, AESKEYLEN, hmac_sha1, SHA1dlen);
+}
+
+void
+passtokey(Authkey *key, char *pw)
+{
+ memset(key, 0, sizeof(Authkey));
+ passtodeskey(key->des, pw);
+ passtoaeskey(key->aes, pw);
}
--- a/libauthsrv/readnvram.c
+++ b/libauthsrv/readnvram.c
@@ -27,15 +27,29 @@
"sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe),
"pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe),
"pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe),
+ "pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe),
+ "pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe),
+ "pc", "#S/sdD0/nvram", 0, sizeof(Nvrsafe),
+ "pc", "#S/sdD0/9fat", -1, sizeof(Nvrsafe),
+ "pc", "#S/sdE0/nvram", 0, sizeof(Nvrsafe),
+ "pc", "#S/sdE0/9fat", -1, sizeof(Nvrsafe),
+ "pc", "#S/sdF0/nvram", 0, sizeof(Nvrsafe),
+ "pc", "#S/sdF0/9fat", -1, sizeof(Nvrsafe),
"pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe),
"pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe),
"pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe),
"pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe),
+ "pc", "#S/sd10/nvram", 0, sizeof(Nvrsafe),
+ "pc", "#S/sd10/9fat", -1, sizeof(Nvrsafe),
"pc", "#f/fd0disk", -1, 512, /* 512: #f requires whole sector reads */
"pc", "#f/fd1disk", -1, 512,
"mips", "#r/nvram", 1024+900, sizeof(Nvrsafe),
- "power", "#F/flash/flash0", 0x300000, sizeof(Nvrsafe),
+ "power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe),
+ "power", "#F/flash/flash", 0x440000, sizeof(Nvrsafe),
"power", "#r/nvram", 4352, sizeof(Nvrsafe), /* OK for MTX-604e */
+ "power", "/nvram", 0, sizeof(Nvrsafe), /* OK for Ucu */
+ "arm", "#F/flash/flash0", 0x100000, sizeof(Nvrsafe),
+ "arm", "#F/flash/flash", 0x100000, sizeof(Nvrsafe),
"debug", "/tmp/nvram", 0, sizeof(Nvrsafe),
};
@@ -109,67 +123,72 @@
buf[m++] = line[0];
}
}
- return buf; /* how does this happen */
}
+typedef struct {
+ int fd;
+ int safelen;
+ vlong safeoff;
+} Nvrwhere;
-/*
- * get key info out of nvram. since there isn't room in the PC's nvram use
- * a disk partition there.
- */
-int
-readnvram(Nvrsafe *safep, int flag)
+static char *nvrfile = nil, *cputype = nil;
+
+/* returns with *locp filled in and locp->fd open, if possible */
+static void
+findnvram(Nvrwhere *locp)
{
- char buf[1024], in[128], *cputype, *nvrfile, *nvrlen, *nvroff, *v[2];
- int fd, err, i, safeoff, safelen;
- Nvrsafe *safe;
+ char *nvrlen, *nvroff, *v[2];
+ int fd, i, safelen;
+ vlong safeoff;
- err = 0;
- memset(safep, 0, sizeof(*safep));
-
- nvrfile = getenv("nvram");
- cputype = getenv("cputype");
+ if (nvrfile == nil)
+ nvrfile = getenv("nvram");
+ if (cputype == nil)
+ cputype = getenv("cputype");
if(cputype == nil)
- cputype = "mips";
- if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0)
- cputype = "pc";
+ cputype = strdup("mips");
+ if(strcmp(cputype, "386")==0 || strcmp(cputype, "amd64")==0 || strcmp(cputype, "alpha")==0) {
+ free(cputype);
+ cputype = strdup("pc");
+ }
- safe = (Nvrsafe*)buf;
-
fd = -1;
safeoff = -1;
safelen = -1;
- if(nvrfile != nil){
+ if(nvrfile != nil && *nvrfile != '\0'){
/* accept device and device!file */
i = gettokens(nvrfile, v, nelem(v), "!");
+ if (i < 1) {
+ i = 1;
+ v[0] = "";
+ v[1] = nil;
+ }
fd = open(v[0], ORDWR);
+ if (fd < 0)
+ fd = open(v[0], OREAD);
safelen = sizeof(Nvrsafe);
if(strstr(v[0], "/9fat") == nil)
safeoff = 0;
nvrlen = getenv("nvrlen");
if(nvrlen != nil)
- safelen = atoi(nvrlen);
+ safelen = strtol(nvrlen, 0, 0);
nvroff = getenv("nvroff");
- if(nvroff != nil){
+ if(nvroff != nil)
if(strcmp(nvroff, "dos") == 0)
safeoff = -1;
else
- safeoff = atoi(nvroff);
- }
+ safeoff = strtoll(nvroff, 0, 0);
if(safeoff < 0 && fd >= 0){
safelen = 512;
- safeoff = finddosfile(fd, i == 2 ? v[1] : "plan9.nvr");
- if(safeoff < 0){
+ safeoff = finddosfile(fd, i == 2? v[1]: "plan9.nvr");
+ if(safeoff < 0){ /* didn't find plan9.nvr? */
close(fd);
fd = -1;
}
}
- free(nvrfile);
- if(nvrlen != nil)
- free(nvrlen);
- if(nvroff != nil)
- free(nvroff);
- }else{
+ free(nvroff);
+ free(nvrlen);
+ }else
for(i=0; i<nelem(nvtab); i++){
if(strcmp(cputype, nvtab[i].cputype) != 0)
continue;
@@ -179,7 +198,7 @@
safelen = nvtab[i].len;
if(safeoff == -1){
safeoff = finddosfile(fd, "plan9.nvr");
- if(safeoff < 0){
+ if(safeoff < 0){ /* didn't find plan9.nvr? */
close(fd);
fd = -1;
continue;
@@ -187,43 +206,123 @@
}
break;
}
+ locp->fd = fd;
+ locp->safelen = safelen;
+ locp->safeoff = safeoff;
+}
+
+/*
+ * get key info out of nvram. since there isn't room in the PC's nvram use
+ * a disk partition there.
+ */
+int
+readnvram(Nvrsafe *safep, int flag)
+{
+ int err;
+ char buf[512], in[128]; /* 512 for floppy i/o */
+ Nvrsafe *safe;
+ Nvrwhere loc;
+
+ err = 0;
+ safe = (Nvrsafe*)buf;
+ memset(&loc, 0, sizeof loc);
+ findnvram(&loc);
+ if (loc.safelen < 0)
+ loc.safelen = sizeof *safe;
+ else if (loc.safelen > sizeof buf)
+ loc.safelen = sizeof buf;
+ if (loc.safeoff < 0) {
+ fprint(2, "readnvram: couldn't find nvram\n");
+ if(!(flag&NVwritemem))
+ memset(safep, 0, sizeof(*safep));
+ safe = safep;
+ /*
+ * allow user to type the data for authentication,
+ * even if there's no nvram to store it in.
+ */
}
- if(fd < 0
- || seek(fd, safeoff, 0) < 0
- || read(fd, buf, safelen) != safelen){
- err = 1;
- if(flag&(NVwrite|NVwriteonerr))
- fprint(2, "can't read nvram: %r\n");
- memset(safep, 0, sizeof(*safep));
+ if(flag&NVwritemem)
safe = safep;
- }else{
- *safep = *safe;
- safe = safep;
+ else {
+ memset(safep, 0, sizeof(*safep));
+ if(loc.fd < 0
+ || seek(loc.fd, loc.safeoff, 0) < 0
+ || read(loc.fd, buf, loc.safelen) != loc.safelen){
+ err = 1;
+ if(flag&(NVwrite|NVwriteonerr))
+ if(loc.fd < 0)
+ fprint(2, "can't open %s: %r\n", nvrfile);
+ else if (seek(loc.fd, loc.safeoff, 0) < 0)
+ fprint(2, "can't seek %s to %lld: %r\n",
+ nvrfile, loc.safeoff);
+ else
+ fprint(2, "can't read %d bytes from %s: %r\n",
+ loc.safelen, nvrfile);
+ /* start from scratch */
+ memset(safep, 0, sizeof(*safep));
+ safe = safep;
+ }else{
+ *safep = *safe; /* overwrite arg with data read */
+ safe = safep;
- err |= check(safe->machkey, DESKEYLEN, safe->machsum, "bad nvram key");
-// err |= check(safe->config, CONFIGLEN, safe->configsum, "bad secstore key");
- err |= check(safe->authid, ANAMELEN, safe->authidsum, "bad authentication id");
- err |= check(safe->authdom, DOMLEN, safe->authdomsum, "bad authentication domain");
+ /* verify data read */
+ err |= check(safe->machkey, DESKEYLEN, safe->machsum,
+ "bad nvram des key");
+ err |= check(safe->authid, ANAMELEN, safe->authidsum,
+ "bad authentication id");
+ err |= check(safe->authdom, DOMLEN, safe->authdomsum,
+ "bad authentication domain");
+ if(0){
+ err |= check(safe->config, CONFIGLEN, safe->configsum,
+ "bad secstore key");
+ err |= check(safe->aesmachkey, AESKEYLEN, safe->aesmachsum,
+ "bad nvram aes key");
+ } else {
+ if(nvcsum(safe->config, CONFIGLEN) != safe->configsum)
+ memset(safe->config, 0, CONFIGLEN);
+ if(nvcsum(safe->aesmachkey, AESKEYLEN) != safe->aesmachsum)
+ memset(safe->aesmachkey, 0, AESKEYLEN);
+ }
+ if(err == 0)
+ if(safe->authid[0]==0 || safe->authdom[0]==0){
+ fprint(2, "empty nvram authid or authdom\n");
+ err = 1;
+ }
+ }
}
- if((flag&NVwrite) || (err && (flag&NVwriteonerr))){
- readcons("authid", nil, 0, safe->authid, sizeof(safe->authid));
- readcons("authdom", nil, 0, safe->authdom, sizeof(safe->authdom));
- readcons("secstore key", nil, 1, safe->config, sizeof(safe->config));
- for(;;){
- if(readcons("password", nil, 1, in, sizeof in) == nil)
- goto Out;
- if(passtokey(safe->machkey, in))
+ if((flag&(NVwrite|NVwritemem)) || (err && (flag&NVwriteonerr))){
+ if (!(flag&NVwritemem)) {
+ readcons("authid", nil, 0, safe->authid,
+ sizeof safe->authid);
+ readcons("authdom", nil, 0, safe->authdom,
+ sizeof safe->authdom);
+ readcons("secstore key", nil, 1, safe->config,
+ sizeof safe->config);
+ for(;;){
+ Authkey k;
+
+ if(readcons("password", nil, 1, in, sizeof in) == nil)
+ goto Out;
+ passtokey(&k, in);
+ memmove(safe->machkey, k.des, DESKEYLEN);
+ memmove(safe->aesmachkey, k.aes, AESKEYLEN);
break;
+ }
}
+
safe->machsum = nvcsum(safe->machkey, DESKEYLEN);
+ // safe->authsum = nvcsum(safe->authkey, DESKEYLEN);
safe->configsum = nvcsum(safe->config, CONFIGLEN);
- safe->authidsum = nvcsum(safe->authid, sizeof(safe->authid));
- safe->authdomsum = nvcsum(safe->authdom, sizeof(safe->authdom));
+ safe->authidsum = nvcsum(safe->authid, sizeof safe->authid);
+ safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom);
+ safe->aesmachsum = nvcsum(safe->aesmachkey, AESKEYLEN);
+
*(Nvrsafe*)buf = *safe;
- if(seek(fd, safeoff, 0) < 0
- || write(fd, buf, safelen) != safelen){
+ if(loc.fd < 0
+ || seek(loc.fd, loc.safeoff, 0) < 0
+ || write(loc.fd, buf, loc.safelen) != loc.safelen){
fprint(2, "can't write key to nvram: %r\n");
err = 1;
}else
@@ -230,8 +329,9 @@
err = 0;
}
Out:
- close(fd);
- return err ? -1 : 0;
+ if (loc.fd >= 0)
+ close(loc.fd);
+ return err? -1: 0;
}
typedef struct Dosboot Dosboot;
@@ -340,7 +440,7 @@
if(rootsects <= 0 || rootsects > 64)
return -1;
- /*
+ /*
* read root. it is contiguous to make stuff like
* this easier
*/
--- /dev/null
+++ b/libauthsrv/spake2ee.mpc
@@ -1,0 +1,63 @@
+void spake2ee_h2P(mpint *p, mpint *a, mpint *d, mpint *h, mpint *PX, mpint *PY, mpint *PZ, mpint *PT){
+ mpint *n = mpnew(0);
+ mpassign(mptwo, n);
+ for(;;){
+ mpint *tmp1 = mpnew(0);
+ legendresymbol(n, p, tmp1);
+ mpint *tmp2 = mpnew(0);
+ mpassign(mpone, tmp2);
+ tmp2->sign = -1;
+ if(mpcmp(tmp1, tmp2) != 0){
+ mpadd(n, mpone, n);
+ }else{
+ mpfree(tmp2);
+ mpfree(tmp1);
+ break;
+ }
+ mpfree(tmp1);
+ mpfree(tmp2);
+ }
+ mpint *tmp3 = mpnew(0);
+ mpmod(h, p, tmp3);
+ elligator2(p, a, d, n, tmp3, PX, PY, PZ, PT);
+ mpfree(tmp3);
+ mpfree(n);
+ }
+void spake2ee_1(mpint *p, mpint *a, mpint *d, mpint *x, mpint *GX, mpint *GY, mpint *PX, mpint *PY, mpint *PZ, mpint *PT, mpint *y){
+ mpint *T = mpnew(0);
+ mpint *Z = mpnew(0);
+ mpint *Y = mpnew(0);
+ mpint *X = mpnew(0);
+ mpint *tmp1 = mpnew(0);
+ mpmodmul(GX, GY, p, tmp1);
+ edwards_scale(p, a, d, x, GX, GY, mpone, tmp1, X, Y, Z, T);
+ mpfree(tmp1);
+ edwards_add(p, a, d, X, Y, Z, T, PX, PY, PZ, PT, X, Y, Z, T);
+ decaf_encode(p, a, d, X, Y, Z, T, y);
+ mpfree(T);
+ mpfree(Z);
+ mpfree(Y);
+ mpfree(X);
+ }
+void spake2ee_2(mpint *p, mpint *a, mpint *d, mpint *PX, mpint *PY, mpint *PZ, mpint *PT, mpint *x, mpint *y, mpint *ok, mpint *z){
+ mpint *T = mpnew(0);
+ mpint *Z = mpnew(0);
+ mpint *Y = mpnew(0);
+ mpint *X = mpnew(0);
+ decaf_decode(p, a, d, y, ok, X, Y, Z, T);
+ if(mpcmp(ok, mpzero) != 0){
+ mpint *tmp1 = mpnew(0);
+ mpmodsub(mpzero, PX, p, tmp1);
+ mpint *tmp2 = mpnew(0);
+ mpmodsub(mpzero, PT, p, tmp2);
+ edwards_add(p, a, d, X, Y, Z, T, tmp1, PY, PZ, tmp2, X, Y, Z, T);
+ mpfree(tmp1);
+ mpfree(tmp2);
+ edwards_scale(p, a, d, x, X, Y, Z, T, X, Y, Z, T);
+ decaf_encode(p, a, d, X, Y, Z, T, z);
+ }
+ mpfree(T);
+ mpfree(Z);
+ mpfree(Y);
+ mpfree(X);
+ }
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -9,6 +9,7 @@
convM2D.$O\
convM2S.$O\
convS2M.$O\
+ ctime.$O\
crypt.$O\
dial.$O\
dirfstat.$O\
--- /dev/null
+++ b/libc/ctime.c
@@ -1,0 +1,118 @@
+/*
+ * This routine converts time as follows.
+ * The epoch is 0000 Jan 1 1970 GMT.
+ * The argument time is in seconds since then.
+ * The localtime(t) entry returns a pointer to an array
+ * containing
+ *
+ * seconds (0-59)
+ * minutes (0-59)
+ * hours (0-23)
+ * day of month (1-31)
+ * month (0-11)
+ * year-1970
+ * weekday (0-6, Sun is 0)
+ * day of the year
+ * daylight savings flag
+ *
+ * The routine gets the daylight savings time from the environment.
+ *
+ * asctime(tvec))
+ * where tvec is produced by localtime
+ * returns a ptr to a character string
+ * that has the ascii time in the form
+ *
+ * \\
+ * Thu Jan 01 00:00:00 GMT 1970n0
+ * 012345678901234567890123456789
+ * 0 1 2
+ *
+ * ctime(t) just calls localtime, then asctime.
+ */
+
+#include <u.h>
+#include <libc.h>
+
+static char dmsize[12] =
+{
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * The following table is used for 1974 and 1975 and
+ * gives the day number of the first day after the Sunday of the
+ * change.
+ */
+
+static int dysize(int);
+
+
+Tm*
+gmtime(long tim)
+{
+ int d0, d1;
+ long hms, day;
+ static Tm xtime;
+
+ /*
+ * break initial number into days
+ */
+ hms = tim % 86400L;
+ day = tim / 86400L;
+ if(hms < 0) {
+ hms += 86400L;
+ day -= 1;
+ }
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ xtime.sec = hms % 60;
+ d1 = hms / 60;
+ xtime.min = d1 % 60;
+ d1 /= 60;
+ xtime.hour = d1;
+
+ /*
+ * day is the day number.
+ * generate day of the week.
+ * The addend is 4 mod 7 (1/1/1970 was Thursday)
+ */
+
+ xtime.wday = (day + 7340036L) % 7;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d1 = 1970; day >= dysize(d1); d1++)
+ day -= dysize(d1);
+ else
+ for (d1 = 1970; day < 0; d1--)
+ day += dysize(d1-1);
+ xtime.year = d1-1900;
+ xtime.yday = d0 = day;
+
+ /*
+ * generate month
+ */
+
+ if(dysize(d1) == 366)
+ dmsize[1] = 29;
+ for(d1 = 0; d0 >= dmsize[d1]; d1++)
+ d0 -= dmsize[d1];
+ dmsize[1] = 28;
+ xtime.mday = d0 + 1;
+ xtime.mon = d1;
+ strcpy(xtime.zone, "GMT");
+ return &xtime;
+}
+
+static int
+dysize(int y)
+{
+
+ if(y%4 == 0 && (y%100 != 0 || y%400 == 0))
+ return 366;
+ return 365;
+}
--- a/libmp/Makefile
+++ b/libmp/Makefile
@@ -6,7 +6,9 @@
OFILES=\
betomp.$O\
+ cnfield.$O\
crt.$O\
+ gmfield.$O\
letomp.$O\
mpadd.$O\
mpaux.$O\
@@ -16,17 +18,25 @@
mpeuclid.$O\
mpexp.$O\
mpextendedgcd.$O\
+ mpfactorial.$O\
+ mpfield.$O\
mpfmt.$O\
mpinvert.$O\
mpleft.$O\
+ mplogic.$O\
mpmod.$O\
+ mpmodop.$O\
mpmul.$O\
+ mpnrand.$O\
mprand.$O\
mpright.$O\
+ mpsel.$O\
mpsub.$O\
mptobe.$O\
+ mptober.$O\
mptoi.$O\
mptole.$O\
+ mptolel.$O\
mptoui.$O\
mptouv.$O\
mptov.$O\
@@ -34,6 +44,7 @@
mpveccmp.$O\
mpvecdigmuladd.$O\
mpvecsub.$O\
+ mpvectscmp.$O\
strtomp.$O
default: $(LIB)
--- a/libmp/betomp.c
+++ b/libmp/betomp.c
@@ -9,21 +9,16 @@
int m, s;
mpdigit x;
- if(b == nil)
+ if(b == nil){
b = mpnew(0);
-
- // dump leading zeros
- while(*p == 0 && n > 1){
- p++;
- n--;
+ setmalloctag(b, getcallerpc(&p));
}
-
- // get the space
mpbits(b, n*8);
- b->top = DIGITS(n*8);
- m = b->top-1;
- // first digit might not be Dbytes long
+ m = DIGITS(n*8);
+ b->top = m--;
+ b->sign = 1;
+
s = ((n-1)*8)%Dbits;
x = 0;
for(; n > 0; n--){
@@ -35,6 +30,5 @@
x = 0;
}
}
-
- return b;
+ return mpnorm(b);
}
--- /dev/null
+++ b/libmp/cnfield.c
@@ -1,0 +1,114 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+/*
+ * fast reduction for crandall numbers of the form: 2^n - c
+ */
+
+enum {
+ MAXDIG = 1024 / Dbits,
+};
+
+typedef struct CNfield CNfield;
+struct CNfield
+{
+ Mfield;
+
+ mpint m[1];
+
+ int s;
+ mpdigit c;
+};
+
+static int
+cnreduce(Mfield *m, mpint *a, mpint *r)
+{
+ mpdigit q[MAXDIG-1], t[MAXDIG], d;
+ CNfield *f = (CNfield*)m;
+ int qn, tn, k;
+
+ k = f->top;
+ if((a->top - k) >= MAXDIG)
+ return -1;
+
+ mpleft(a, f->s, r);
+ if(r->top <= k)
+ mpbits(r, (k+1)*Dbits);
+
+ /* q = hi(r) */
+ qn = r->top - k;
+ memmove(q, r->p+k, qn*Dbytes);
+
+ /* r = lo(r) */
+ r->top = k;
+ r->sign = 1;
+
+ do {
+ /* t = q*c */
+ tn = qn+1;
+ memset(t, 0, tn*Dbytes);
+ mpvecdigmuladd(q, qn, f->c, t);
+
+ /* q = hi(t) */
+ qn = tn - k;
+ if(qn <= 0) qn = 0;
+ else memmove(q, t+k, qn*Dbytes);
+
+ /* r += lo(t) */
+ if(tn > k)
+ tn = k;
+ mpvecadd(r->p, k, t, tn, r->p);
+
+ /* if(r >= m) r -= m */
+ mpvecsub(r->p, k+1, f->m->p, k, t);
+ d = t[k];
+ for(tn = 0; tn < k; tn++)
+ r->p[tn] = (r->p[tn] & d) | (t[tn] & ~d);
+ } while(qn > 0);
+
+ if(f->s != 0)
+ mpright(r, f->s, r);
+ mpnorm(r);
+
+ return 0;
+}
+
+Mfield*
+cnfield(mpint *N)
+{
+ mpint *M, *C;
+ CNfield *f;
+ mpdigit d;
+ int s;
+
+ if(N->top <= 2 || N->top >= MAXDIG)
+ return nil;
+ f = nil;
+ d = N->p[N->top-1];
+ for(s = 0; (d & (mpdigit)1<<Dbits-1) == 0; s++)
+ d <<= 1;
+ C = mpnew(0);
+ M = mpcopy(N);
+ mpleft(N, s, M);
+ mpleft(mpone, M->top*Dbits, C);
+ mpsub(C, M, C);
+ if(C->top != 1)
+ goto out;
+ f = mallocz(sizeof(CNfield) + M->top*sizeof(mpdigit), 1);
+ if(f == nil)
+ goto out;
+ f->s = s;
+ f->c = C->p[0];
+ f->m->size = M->top;
+ f->m->p = (mpdigit*)&f[1];
+ mpassign(M, f->m);
+ mpassign(N, (mpint*)f);
+ f->reduce = cnreduce;
+ f->flags |= MPfield;
+out:
+ mpfree(M);
+ mpfree(C);
+
+ return (Mfield*)f;
+}
--- a/libmp/crt.c
+++ b/libmp/crt.c
@@ -1,6 +1,5 @@
#include "os.h"
#include <mp.h>
-#include <libsec.h>
// chinese remainder theorem
//
--- a/libmp/crttest.c
+++ b/libmp/crttest.c
@@ -1,6 +1,5 @@
#include "os.h"
#include <mp.h>
-#include <libsec.h>
void
testcrt(mpint **p)
@@ -8,9 +7,8 @@
CRTpre *crt;
CRTres *res;
mpint *m, *x, *y;
- int i;
- fmtinstall('B', mpconv);
+ fmtinstall('B', mpfmt);
// get a modulus and a test number
m = mpnew(1024+160);
@@ -49,6 +47,6 @@
mpfree(p[0]);
mpfree(p[1]);
}
- print("%d secs with more\n", time(0)-start);
+ print("%ld secs with more\n", time(0)-start);
exits(0);
}
--- a/libmp/dat.h
+++ b/libmp/dat.h
@@ -1,4 +1,4 @@
-#define mpdighi (mpdigit)(1U<<(Dbits-1))
+#define mpdighi (mpdigit)(1<<(Dbits-1))
#define DIGITS(x) ((Dbits - 1 + (x))/Dbits)
// for converting between int's and mpint's
@@ -7,9 +7,6 @@
#define MININT (MAXINT+1)
// for converting between vlongs's and mpint's
-// #define MAXUVLONG (~0ULL)
-// #define MAXVLONG (MAXUVLONG>>1)
-// #define MINVLONG (MAXVLONG+1ULL)
-#define MAXUVLONG ((uvlong) ~0)
+#define MAXUVLONG (~0ULL)
#define MAXVLONG (MAXUVLONG>>1)
-#define MINVLONG (MAXVLONG+((uvlong) 1))
+#define MINVLONG (MAXVLONG+1ULL)
--- /dev/null
+++ b/libmp/gmfield.c
@@ -1,0 +1,173 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+/*
+ * fast reduction for generalized mersenne numbers (GM)
+ * using a series of additions and subtractions.
+ */
+
+enum {
+ MAXDIG = 1024/Dbits,
+};
+
+typedef struct GMfield GMfield;
+struct GMfield
+{
+ Mfield;
+
+ mpint m2[1];
+
+ int nadd;
+ int nsub;
+ int indx[256];
+};
+
+static int
+gmreduce(Mfield *m, mpint *a, mpint *r)
+{
+ GMfield *g = (GMfield*)m;
+ mpdigit d0, t[MAXDIG];
+ int i, j, d, *x;
+
+ if(mpmagcmp(a, g->m2) >= 0)
+ return -1;
+
+ if(a != r)
+ mpassign(a, r);
+
+ d = g->top;
+ mpbits(r, (d+1)*Dbits*2);
+ memmove(t+d, r->p+d, d*Dbytes);
+
+ r->sign = 1;
+ r->top = d;
+ r->p[d] = 0;
+
+ if(g->nsub > 0)
+ mpvecdigmuladd(g->p, d, g->nsub, r->p);
+
+ x = g->indx;
+ for(i=0; i<g->nadd; i++){
+ t[0] = 0;
+ d0 = t[*x++];
+ for(j=1; j<d; j++)
+ t[j] = t[*x++];
+ t[0] = d0;
+
+ mpvecadd(r->p, d+1, t, d, r->p);
+ }
+
+ for(i=0; i<g->nsub; i++){
+ t[0] = 0;
+ d0 = t[*x++];
+ for(j=1; j<d; j++)
+ t[j] = t[*x++];
+ t[0] = d0;
+
+ mpvecsub(r->p, d+1, t, d, r->p);
+ }
+
+ mpvecdigmulsub(g->p, d, r->p[d], r->p);
+ r->p[d] = 0;
+
+ mpvecsub(r->p, d+1, g->p, d, r->p+d+1);
+ d0 = r->p[2*d+1];
+ for(j=0; j<d; j++)
+ r->p[j] = (r->p[j] & d0) | (r->p[j+d+1] & ~d0);
+
+ mpnorm(r);
+
+ return 0;
+}
+
+Mfield*
+gmfield(mpint *N)
+{
+ int i,j,d, s, *C, *X, *x, *e;
+ mpint *M, *T;
+ GMfield *g;
+
+ d = N->top;
+ if(d <= 2 || d > MAXDIG/2 || (mpsignif(N) % Dbits) != 0)
+ return nil;
+ g = nil;
+ T = mpnew(0);
+ M = mpcopy(N);
+ C = malloc(sizeof(int)*(d+1));
+ X = malloc(sizeof(int)*(d*d));
+ if(C == nil || X == nil)
+ goto out;
+
+ for(i=0; i<=d; i++){
+ if((M->p[i]>>8) != 0 && (~M->p[i]>>8) != 0)
+ goto out;
+ j = M->p[i];
+ C[d - i] = -j;
+ itomp(j, T);
+ mpleft(T, i*Dbits, T);
+ mpsub(M, T, M);
+ }
+ for(j=0; j<d; j++)
+ X[j] = C[d-j];
+ for(i=1; i<d; i++){
+ X[d*i] = X[d*(i-1) + d-1]*C[d];
+ for(j=1; j<d; j++)
+ X[d*i + j] = X[d*(i-1) + j-1] + X[d*(i-1) + d-1]*C[d-j];
+ }
+ g = mallocz(sizeof(GMfield) + (d+1)*sizeof(mpdigit)*2, 1);
+ if(g == nil)
+ goto out;
+
+ g->m2->p = (mpdigit*)&g[1];
+ g->m2->size = d*2+1;
+ mpmul(N, N, g->m2);
+ mpassign(N, (mpint*)g);
+ g->reduce = gmreduce;
+ g->flags |= MPfield;
+
+ s = 0;
+ x = g->indx;
+ e = x + nelem(g->indx) - d;
+ for(g->nadd=0; x <= e; x += d, g->nadd++){
+ s = 0;
+ for(i=0; i<d; i++){
+ for(j=0; j<d; j++){
+ if(X[d*i+j] > 0 && x[j] == 0){
+ X[d*i+j]--;
+ x[j] = d+i;
+ s = 1;
+ break;
+ }
+ }
+ }
+ if(s == 0)
+ break;
+ }
+ for(g->nsub=0; x <= e; x += d, g->nsub++){
+ s = 0;
+ for(i=0; i<d; i++){
+ for(j=0; j<d; j++){
+ if(X[d*i+j] < 0 && x[j] == 0){
+ X[d*i+j]++;
+ x[j] = d+i;
+ s = 1;
+ break;
+ }
+ }
+ }
+ if(s == 0)
+ break;
+ }
+ if(s != 0){
+ mpfree((mpint*)g);
+ g = nil;
+ }
+out:
+ free(C);
+ free(X);
+ mpfree(M);
+ mpfree(T);
+ return (Mfield*)g;
+}
+
--- a/libmp/letomp.c
+++ b/libmp/letomp.c
@@ -9,10 +9,11 @@
int i=0, m = 0;
mpdigit x=0;
- if(b == nil)
+ if(b == nil){
b = mpnew(0);
+ setmalloctag(b, getcallerpc(&s));
+ }
mpbits(b, 8*n);
- b->top = DIGITS(8*n);
for(; n > 0; n--){
x |= ((mpdigit)(*s++)) << i;
i += 8;
@@ -25,5 +26,6 @@
if(i > 0)
b->p[m++] = x;
b->top = m;
- return b;
+ b->sign = 1;
+ return mpnorm(b);
}
--- a/libmp/mpadd.c
+++ b/libmp/mpadd.c
@@ -9,6 +9,8 @@
int m, n;
mpint *t;
+ sum->flags |= (b1->flags | b2->flags) & MPtimesafe;
+
// get the sizes right
if(b2->top > b1->top){
t = b1;
@@ -41,6 +43,7 @@
int sign;
if(b1->sign != b2->sign){
+ assert(((b1->flags | b2->flags | sum->flags) & MPtimesafe) == 0);
if(b1->sign < 0)
mpmagsub(b2, b1, sum);
else
--- a/libmp/mpaux.c
+++ b/libmp/mpaux.c
@@ -5,11 +5,9 @@
static mpdigit _mptwodata[1] = { 2 };
static mpint _mptwo =
{
- 1,
- 1,
- 1,
+ 1, 1, 1,
_mptwodata,
- MPstatic
+ MPstatic|MPnorm
};
mpint *mptwo = &_mptwo;
@@ -16,11 +14,9 @@
static mpdigit _mponedata[1] = { 1 };
static mpint _mpone =
{
- 1,
- 1,
- 1,
+ 1, 1, 1,
_mponedata,
- MPstatic
+ MPstatic|MPnorm
};
mpint *mpone = &_mpone;
@@ -27,11 +23,9 @@
static mpdigit _mpzerodata[1] = { 0 };
static mpint _mpzero =
{
- 1,
- 1,
- 0,
+ 1, 1, 0,
_mpzerodata,
- MPstatic
+ MPstatic|MPnorm
};
mpint *mpzero = &_mpzero;
@@ -41,6 +35,8 @@
void
mpsetminbits(int n)
{
+ if(n < 0)
+ sysfatal("mpsetminbits: n < 0");
if(n == 0)
n = 1;
mpmindigits = DIGITS(n);
@@ -52,18 +48,20 @@
{
mpint *b;
- b = mallocz(sizeof(mpint), 1);
- if(b == nil)
- sysfatal("mpnew: %r");
+ if(n < 0)
+ sysfatal("mpsetminbits: n < 0");
+
n = DIGITS(n);
if(n < mpmindigits)
n = mpmindigits;
- n = n;
- b->p = (mpdigit*)mallocz(n*Dbytes, 1);
- if(b->p == nil)
+ b = mallocz(sizeof(mpint) + n*Dbytes, 1);
+ if(b == nil)
sysfatal("mpnew: %r");
+ setmalloctag(b, getcallerpc(&n));
+ b->p = (mpdigit*)&b[1];
b->size = n;
b->sign = 1;
+ b->flags = MPnorm;
return b;
}
@@ -78,16 +76,23 @@
if(b->size >= n){
if(b->top >= n)
return;
- memset(&b->p[b->top], 0, Dbytes*(n - b->top));
- b->top = n;
- return;
+ } else {
+ if(b->p == (mpdigit*)&b[1]){
+ b->p = (mpdigit*)mallocz(n*Dbytes, 0);
+ if(b->p == nil)
+ sysfatal("mpbits: %r");
+ memmove(b->p, &b[1], Dbytes*b->top);
+ memset(&b[1], 0, Dbytes*b->size);
+ } else {
+ b->p = (mpdigit*)realloc(b->p, n*Dbytes);
+ if(b->p == nil)
+ sysfatal("mpbits: %r");
+ }
+ b->size = n;
}
- b->p = (mpdigit*)realloc(b->p, n*Dbytes);
- if(b->p == nil)
- sysfatal("mpbits: %r");
memset(&b->p[b->top], 0, Dbytes*(n - b->top));
- b->size = n;
b->top = n;
+ b->flags &= ~MPnorm;
}
void
@@ -97,16 +102,22 @@
return;
if(b->flags & MPstatic)
sysfatal("freeing mp constant");
- memset(b->p, 0, b->top*Dbytes); // information hiding
- free(b->p);
+ memset(b->p, 0, b->size*Dbytes);
+ if(b->p != (mpdigit*)&b[1])
+ free(b->p);
free(b);
}
-void
+mpint*
mpnorm(mpint *b)
{
int i;
+ if(b->flags & MPtimesafe){
+ assert(b->sign == 1);
+ b->flags &= ~MPnorm;
+ return b;
+ }
for(i = b->top-1; i >= 0; i--)
if(b->p[i] != 0)
break;
@@ -113,6 +124,8 @@
b->top = i+1;
if(b->top == 0)
b->sign = 1;
+ b->flags |= MPnorm;
+ return b;
}
mpint*
@@ -121,8 +134,10 @@
mpint *new;
new = mpnew(Dbits*old->size);
- new->top = old->top;
+ setmalloctag(new, getcallerpc(&old));
new->sign = old->sign;
+ new->top = old->top;
+ new->flags = old->flags & ~(MPstatic|MPfield);
memmove(new->p, old->p, Dbytes*old->top);
return new;
}
@@ -130,9 +145,14 @@
void
mpassign(mpint *old, mpint *new)
{
+ if(new == nil || old == new)
+ return;
+ new->top = 0;
mpbits(new, Dbits*old->top);
new->sign = old->sign;
new->top = old->top;
+ new->flags &= ~MPnorm;
+ new->flags |= old->flags & ~(MPstatic|MPfield);
memmove(new->p, old->p, Dbytes*old->top);
}
@@ -162,6 +182,7 @@
int k, bit, digit;
mpdigit d;
+ assert(n->flags & MPnorm);
if(n->top==0)
return 0;
k = 0;
@@ -182,4 +203,3 @@
}
return k;
}
-
--- a/libmp/mpcmp.c
+++ b/libmp/mpcmp.c
@@ -2,16 +2,20 @@
#include <mp.h>
#include "dat.h"
-// return 1, 0, -1 as abs(b1)-abs(b2) is neg, 0, pos
+// return neg, 0, pos as abs(b1)-abs(b2) is neg, 0, pos
int
mpmagcmp(mpint *b1, mpint *b2)
{
int i;
- i = b1->top - b2->top;
- if(i)
- return i;
-
+ i = b1->flags | b2->flags;
+ if(i & MPtimesafe)
+ return mpvectscmp(b1->p, b1->top, b2->p, b2->top);
+ if(i & MPnorm){
+ i = b1->top - b2->top;
+ if(i)
+ return i;
+ }
return mpveccmp(b1->p, b1->top, b2->p, b2->top);
}
@@ -19,10 +23,8 @@
int
mpcmp(mpint *b1, mpint *b2)
{
- if(b1->sign != b2->sign)
- return b1->sign - b2->sign;
- if(b1->sign < 0)
- return mpmagcmp(b2, b1);
- else
- return mpmagcmp(b1, b2);
+ int sign;
+
+ sign = (b1->sign - b2->sign) >> 1; // -1, 0, 1
+ return sign | (sign&1)-1 & mpmagcmp(b1, b2)*b1->sign;
}
--- a/libmp/mpdigdiv.c
+++ b/libmp/mpdigdiv.c
@@ -21,6 +21,19 @@
return;
}
+ // very common case
+ if(~divisor == 0){
+ lo += hi;
+ if(lo < hi){
+ hi++;
+ lo++;
+ }
+ if(lo+1 == 0)
+ hi++;
+ *quotient = hi;
+ return;
+ }
+
// at this point we know that hi < divisor
// just shift and subtract till we're done
q = 0;
--- a/libmp/mpdiv.c
+++ b/libmp/mpdiv.c
@@ -13,10 +13,29 @@
mpdigit qd, *up, *vp, *qp;
mpint *u, *v, *t;
+ assert(quotient != remainder);
+ assert(divisor->flags & MPnorm);
+
// divide bv zero
if(divisor->top == 0)
abort();
+ // division by one or small powers of two
+ if(divisor->top == 1 && (divisor->p[0] & divisor->p[0]-1) == 0){
+ vlong r = (vlong)dividend->sign * (dividend->p[0] & divisor->p[0]-1);
+ if(quotient != nil){
+ for(s = 0; ((divisor->p[0] >> s) & 1) == 0; s++)
+ ;
+ mpright(dividend, s, quotient);
+ }
+ if(remainder != nil){
+ remainder->flags |= dividend->flags & MPtimesafe;
+ vtomp(r, remainder);
+ }
+ return;
+ }
+ assert((dividend->flags & MPtimesafe) == 0);
+
// quick check
if(mpmagcmp(dividend, divisor) < 0){
if(remainder != nil)
@@ -95,6 +114,7 @@
*up-- = 0;
}
if(qp != nil){
+ assert((quotient->flags & MPtimesafe) == 0);
mpnorm(quotient);
if(dividend->sign != divisor->sign)
quotient->sign = -1;
@@ -101,6 +121,7 @@
}
if(remainder != nil){
+ assert((remainder->flags & MPtimesafe) == 0);
mpright(u, s, remainder); // u is the remainder shifted
remainder->sign = dividend->sign;
}
--- a/libmp/mpeuclid.c
+++ b/libmp/mpeuclid.c
@@ -13,6 +13,12 @@
{
mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r;
+ assert((a->flags&b->flags) & MPnorm);
+ assert(((a->flags|b->flags|d->flags|x->flags|y->flags) & MPtimesafe) == 0);
+
+ if(a->sign<0 || b->sign<0)
+ sysfatal("mpeuclid: negative arg");
+
if(mpcmp(a, b) < 0){
tmp = a;
a = b;
--- a/libmp/mpexp.c
+++ b/libmp/mpexp.c
@@ -22,6 +22,18 @@
mpdigit d, bit;
int i, j;
+ assert(m == nil || m->flags & MPnorm);
+ assert((e->flags & MPtimesafe) == 0);
+ res->flags |= b->flags & MPtimesafe;
+
+ i = mpcmp(e,mpzero);
+ if(i==0){
+ mpassign(mpone, res);
+ return;
+ }
+ if(i<0)
+ sysfatal("mpexp: negative exponent");
+
t[0] = mpcopy(b);
t[1] = res;
@@ -49,24 +61,22 @@
j = 0;
for(;;){
for(; bit != 0; bit >>= 1){
- mpmul(t[j], t[j], t[j^1]);
- if(bit & d)
- mpmul(t[j^1], b, t[j]);
+ if(m != nil)
+ mpmodmul(t[j], t[j], m, t[j^1]);
else
+ mpmul(t[j], t[j], t[j^1]);
+ if(bit & d) {
+ if(m != nil)
+ mpmodmul(t[j^1], b, m, t[j]);
+ else
+ mpmul(t[j^1], b, t[j]);
+ } else
j ^= 1;
- if(m != nil && t[j]->top > m->top){
- mpmod(t[j], m, t[j^1]);
- j ^= 1;
- }
}
if(--i < 0)
break;
bit = mpdighi;
d = e->p[i];
- }
- if(m != nil){
- mpmod(t[j], m, t[j^1]);
- j ^= 1;
}
if(t[j] == res){
mpfree(t[j^1]);
--- a/libmp/mpextendedgcd.c
+++ b/libmp/mpextendedgcd.c
@@ -5,7 +5,7 @@
// extended binary gcd
//
-// For a anv b it solves, v = gcd(a,b) and finds x and y s.t.
+// For a and b it solves, v = gcd(a,b) and finds x and y s.t.
// ax + by = v
//
// Handbook of Applied Cryptography, Menezes et al, 1997, pg 608.
@@ -15,6 +15,16 @@
mpint *u, *A, *B, *C, *D;
int g;
+ assert((a->flags&b->flags) & MPnorm);
+ assert(((a->flags|b->flags|v->flags|x->flags|y->flags) & MPtimesafe) == 0);
+
+ if(a->sign < 0 || b->sign < 0){
+ mpassign(mpzero, v);
+ mpassign(mpzero, y);
+ mpassign(mpzero, x);
+ return;
+ }
+
if(a->top == 0){
mpassign(b, v);
mpassign(mpone, y);
@@ -94,4 +104,6 @@
mpfree(u);
mpfree(a);
mpfree(b);
+
+ return;
}
--- /dev/null
+++ b/libmp/mpfactorial.c
@@ -1,0 +1,74 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+mpint*
+mpfactorial(ulong n)
+{
+ int i;
+ ulong k;
+ unsigned cnt;
+ int max, mmax;
+ mpdigit p, pp[2];
+ mpint *r, *s, *stk[31];
+
+ cnt = 0;
+ max = mmax = -1;
+ p = 1;
+ r = mpnew(0);
+ for(k=2; k<=n; k++){
+ pp[0] = 0;
+ pp[1] = 0;
+ mpvecdigmuladd(&p, 1, (mpdigit)k, pp);
+ if(pp[1] == 0) /* !overflow */
+ p = pp[0];
+ else{
+ cnt++;
+ if((cnt & 1) == 0){
+ s = stk[max];
+ mpbits(r, Dbits*(s->top+1+1));
+ memset(r->p, 0, Dbytes*(s->top+1+1));
+ mpvecmul(s->p, s->top, &p, 1, r->p);
+ r->sign = 1;
+ r->top = s->top+1+1; /* XXX: norm */
+ mpassign(r, s);
+ for(i=4; (cnt & (i-1)) == 0; i=i<<1){
+ mpmul(stk[max], stk[max-1], r);
+ mpassign(r, stk[max-1]);
+ max--;
+ }
+ }else{
+ max++;
+ if(max > mmax){
+ mmax++;
+ if(max > nelem(stk))
+ abort();
+ stk[max] = mpnew(Dbits);
+ }
+ stk[max]->top = 1;
+ stk[max]->p[0] = p;
+ }
+ p = (mpdigit)k;
+ }
+ }
+ if(max < 0){
+ mpbits(r, Dbits);
+ r->top = 1;
+ r->sign = 1;
+ r->p[0] = p;
+ }else{
+ s = stk[max--];
+ mpbits(r, Dbits*(s->top+1+1));
+ memset(r->p, 0, Dbytes*(s->top+1+1));
+ mpvecmul(s->p, s->top, &p, 1, r->p);
+ r->sign = 1;
+ r->top = s->top+1+1; /* XXX: norm */
+ }
+
+ while(max >= 0)
+ mpmul(r, stk[max--], r);
+ for(max=mmax; max>=0; max--)
+ mpfree(stk[max]);
+ mpnorm(r);
+ return r;
+}
--- /dev/null
+++ b/libmp/mpfield.c
@@ -1,0 +1,21 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+mpint*
+mpfield(mpint *N)
+{
+ Mfield *f;
+
+ if(N == nil || N->flags & (MPfield|MPstatic))
+ return N;
+ if((f = cnfield(N)) != nil)
+ goto Exchange;
+ if((f = gmfield(N)) != nil)
+ goto Exchange;
+ return N;
+Exchange:
+ setmalloctag(f, getcallerpc(&N));
+ mpfree(N);
+ return (mpint*)f;
+}
--- a/libmp/mpfmt.c
+++ b/libmp/mpfmt.c
@@ -1,10 +1,9 @@
#include "os.h"
#include <mp.h>
-#include <libsec.h>
#include "dat.h"
static int
-to64(mpint *b, char *buf, int len)
+toencx(mpint *b, char *buf, int len, int (*enc)(char*, int, uchar*, int))
{
uchar *p;
int n, rv;
@@ -13,52 +12,30 @@
n = mptobe(b, nil, 0, &p);
if(n < 0)
return -1;
- rv = enc64(buf, len, p, n);
+ rv = (*enc)(buf, len, p, n);
free(p);
return rv;
}
-static int
-to32(mpint *b, char *buf, int len)
-{
- uchar *p;
- int n, rv;
-
- // leave room for a multiple of 5 buffer size
- n = b->top*Dbytes + 5;
- p = malloc(n);
- if(p == nil)
- return -1;
- n = mptobe(b, p, n, nil);
- if(n < 0)
- return -1;
-
- // round up buffer size, enc32 only accepts a multiple of 5
- if(n%5)
- n += 5 - (n%5);
- rv = enc32(buf, len, p, n);
- free(p);
- return rv;
-}
-
static char set16[] = "0123456789ABCDEF";
static int
-to16(mpint *b, char *buf, int len)
+topow2(mpint *b, char *buf, int len, int s)
{
mpdigit *p, x;
- int i, j;
+ int i, j, sn;
char *out, *eout;
if(len < 1)
return -1;
+ sn = 1<<s;
out = buf;
eout = buf+len;
for(p = &b->p[b->top-1]; p >= b->p; p--){
x = *p;
- for(i = Dbits-4; i >= 0; i -= 4){
- j = 0xf & (x>>i);
+ for(i = Dbits-s; i >= 0; i -= s){
+ j = x >> i & sn - 1;
if(j != 0 || out != buf){
if(out >= eout)
return -1;
@@ -102,6 +79,8 @@
return -1;
d = mpcopy(b);
+ d->flags &= ~MPtimesafe;
+ mpnorm(d);
r = mpnew(0);
billion = uitomp(1000000000, nil);
out = buf+len;
@@ -124,23 +103,91 @@
return 0;
}
+static int
+to8(mpint *b, char *buf, int len)
+{
+ mpdigit x, y;
+ char *out;
+ int i, j;
+
+ if(len < 2)
+ return -1;
+
+ out = buf+len;
+ *--out = 0;
+
+ i = j = 0;
+ x = y = 0;
+ while(j < b->top){
+ y = b->p[j++];
+ if(i > 0)
+ x |= y << i;
+ else
+ x = y;
+ i += Dbits;
+ while(i >= 3){
+Digout: i -= 3;
+ if(out > buf)
+ out--;
+ else if(x != 0)
+ return -1;
+ *out = '0' + (x & 7);
+ x = y >> Dbits-i;
+ }
+ }
+ if(i > 0)
+ goto Digout;
+
+ while(*out == '0') out++;
+ if(*out == '\0')
+ *--out = '0';
+
+ len -= out-buf;
+ if(out != buf)
+ memmove(buf, out, len);
+ return 0;
+}
+
int
mpfmt(Fmt *fmt)
{
mpint *b;
- char *p;
+ char *x, *p;
+ int base;
b = va_arg(fmt->args, mpint*);
if(b == nil)
return fmtstrcpy(fmt, "*");
-
- p = mptoa(b, fmt->prec, nil, 0);
- fmt->flags &= ~FmtPrec;
+ base = fmt->prec;
+ if(base == 0)
+ base = 16; /* default */
+ fmt->flags &= ~FmtPrec;
+ p = mptoa(b, base, nil, 0);
if(p == nil)
return fmtstrcpy(fmt, "*");
else{
- fmtstrcpy(fmt, p);
+ if((fmt->flags & FmtSharp) != 0){
+ switch(base){
+ case 16:
+ x = "0x";
+ break;
+ case 8:
+ x = "0";
+ break;
+ case 2:
+ x = "0b";
+ break;
+ default:
+ x = "";
+ }
+ if(*p == '-')
+ fmtprint(fmt, "-%s%s", x, p + 1);
+ else
+ fmtprint(fmt, "%s%s", x, p);
+ }
+ else
+ fmtstrcpy(fmt, p);
free(p);
return 0;
}
@@ -152,9 +199,14 @@
char *out;
int rv, alloced;
+ if(base == 0)
+ base = 16; /* default */
alloced = 0;
if(buf == nil){
- len = ((b->top+1)*Dbits+2)/3 + 1;
+ /* rv <= log₂(base) */
+ for(rv=1; (base >> rv) > 1; rv++)
+ ;
+ len = 10 + (b->top*Dbits / rv);
buf = malloc(len);
if(buf == nil)
return nil;
@@ -171,18 +223,29 @@
}
switch(base){
case 64:
- rv = to64(b, out, len);
+ rv = toencx(b, out, len, enc64);
break;
case 32:
- rv = to32(b, out, len);
+ rv = toencx(b, out, len, enc32);
break;
- default:
case 16:
- rv = to16(b, out, len);
+ rv = topow2(b, out, len, 4);
break;
case 10:
rv = to10(b, out, len);
break;
+ case 8:
+ rv = to8(b, out, len);
+ break;
+ case 4:
+ rv = topow2(b, out, len, 2);
+ break;
+ case 2:
+ rv = topow2(b, out, len, 1);
+ break;
+ default:
+ abort();
+ return nil;
}
if(rv < 0){
if(alloced)
--- a/libmp/mpleft.c
+++ b/libmp/mpleft.c
@@ -9,8 +9,14 @@
int d, l, r, i, otop;
mpdigit this, last;
- // a negative left shift is a right shift
- if(shift < 0){
+ res->sign = b->sign;
+ if(b->top==0){
+ res->top = 0;
+ return;
+ }
+
+ // a zero or negative left shift is a right shift
+ if(shift <= 0){
mpright(b, -shift, res);
return;
}
@@ -40,7 +46,6 @@
for(i = 0; i < d; i++)
res->p[i] = 0;
- // normalize
- while(res->top > 0 && res->p[res->top-1] == 0)
- res->top--;
+ res->flags |= b->flags & MPtimesafe;
+ mpnorm(res);
}
--- /dev/null
+++ b/libmp/mplogic.c
@@ -1,0 +1,194 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+/*
+ mplogic calculates b1|b2 subject to the
+ following flag bits (fl)
+
+ bit 0: subtract 1 from b1
+ bit 1: invert b1
+ bit 2: subtract 1 from b2
+ bit 3: invert b2
+ bit 4: add 1 to output
+ bit 5: invert output
+
+ it inverts appropriate bits automatically
+ depending on the signs of the inputs
+*/
+
+static void
+mplogic(mpint *b1, mpint *b2, mpint *sum, int fl)
+{
+ mpint *t;
+ mpdigit *dp1, *dp2, *dpo, d1, d2, d;
+ int c1, c2, co;
+ int i;
+
+ assert(((b1->flags | b2->flags | sum->flags) & MPtimesafe) == 0);
+ if(b1->sign < 0) fl ^= 0x03;
+ if(b2->sign < 0) fl ^= 0x0c;
+ sum->sign = (int)(((fl|fl>>2)^fl>>4)<<30)>>31|1;
+ if(sum->sign < 0) fl ^= 0x30;
+ if(b2->top > b1->top){
+ t = b1;
+ b1 = b2;
+ b2 = t;
+ fl = fl >> 2 & 0x03 | fl << 2 & 0x0c | fl & 0x30;
+ }
+ mpbits(sum, b1->top*Dbits);
+ dp1 = b1->p;
+ dp2 = b2->p;
+ dpo = sum->p;
+ c1 = fl & 1;
+ c2 = fl >> 2 & 1;
+ co = fl >> 4 & 1;
+ for(i = 0; i < b1->top; i++){
+ d1 = dp1[i] - c1;
+ if(i < b2->top)
+ d2 = dp2[i] - c2;
+ else
+ d2 = 0;
+ if(d1 != (mpdigit)-1) c1 = 0;
+ if(d2 != (mpdigit)-1) c2 = 0;
+ if((fl & 2) != 0) d1 ^= -1;
+ if((fl & 8) != 0) d2 ^= -1;
+ d = d1 | d2;
+ if((fl & 32) != 0) d ^= -1;
+ d += co;
+ if(d != 0) co = 0;
+ dpo[i] = d;
+ }
+ sum->top = i;
+ mpnorm(sum);
+}
+
+void
+mpor(mpint *b1, mpint *b2, mpint *sum)
+{
+ mplogic(b1, b2, sum, 0);
+}
+
+void
+mpand(mpint *b1, mpint *b2, mpint *sum)
+{
+ mplogic(b1, b2, sum, 0x2a);
+}
+
+void
+mpbic(mpint *b1, mpint *b2, mpint *sum)
+{
+ mplogic(b1, b2, sum, 0x22);
+}
+
+void
+mpnot(mpint *b, mpint *r)
+{
+ mpadd(b, mpone, r);
+ r->sign ^= -2;
+}
+
+void
+mpxor(mpint *b1, mpint *b2, mpint *sum)
+{
+ mpint *t;
+ mpdigit *dp1, *dp2, *dpo, d1, d2, d;
+ int c1, c2, co;
+ int i, fl;
+
+ assert(((b1->flags | b2->flags | sum->flags) & MPtimesafe) == 0);
+ if(b2->top > b1->top){
+ t = b1;
+ b1 = b2;
+ b2 = t;
+ }
+ fl = (b1->sign & 10) ^ (b2->sign & 12);
+ sum->sign = (int)(fl << 28) >> 31;
+ mpbits(sum, b1->top*Dbits);
+ dp1 = b1->p;
+ dp2 = b2->p;
+ dpo = sum->p;
+ c1 = fl >> 1 & 1;
+ c2 = fl >> 2 & 1;
+ co = fl >> 3 & 1;
+ for(i = 0; i < b1->top; i++){
+ d1 = dp1[i] - c1;
+ if(i < b2->top)
+ d2 = dp2[i] - c2;
+ else
+ d2 = 0;
+ if(d1 != (mpdigit)-1) c1 = 0;
+ if(d2 != (mpdigit)-1) c2 = 0;
+ d = d1 ^ d2;
+ d += co;
+ if(d != 0) co = 0;
+ dpo[i] = d;
+ }
+ sum->top = i;
+ mpnorm(sum);
+}
+
+void
+mptrunc(mpint *b, int n, mpint *r)
+{
+ int d, m, i, c;
+
+ assert(((b->flags | r->flags) & MPtimesafe) == 0);
+ mpbits(r, n);
+ r->top = DIGITS(n);
+ d = n / Dbits;
+ m = n % Dbits;
+ if(b->sign == -1){
+ c = 1;
+ for(i = 0; i <= r->top; i++){
+ if(i < b->top)
+ r->p[i] = ~(b->p[i] - c);
+ else
+ r->p[i] = -1;
+ if(r->p[i] != 0)
+ c = 0;
+ }
+ if(m != 0)
+ r->p[d] &= (1<<m) - 1;
+ }else if(b->sign == 1){
+ if(d >= b->top){
+ mpassign(b, r);
+ return;
+ }
+ if(b != r)
+ for(i = 0; i < d; i++)
+ r->p[i] = b->p[i];
+ if(m != 0)
+ r->p[d] = b->p[d] & (1<<m)-1;
+ }
+ r->sign = 1;
+ mpnorm(r);
+}
+
+void
+mpxtend(mpint *b, int n, mpint *r)
+{
+ int d, m, c, i;
+
+ d = (n - 1) / Dbits;
+ m = (n - 1) % Dbits;
+ if(d >= b->top){
+ mpassign(b, r);
+ return;
+ }
+ mptrunc(b, n, r);
+ mpbits(r, n);
+ if((r->p[d] & 1<<m) == 0){
+ mpnorm(r);
+ return;
+ }
+ r->p[d] |= -(1<<m);
+ r->sign = -1;
+ c = 1;
+ for(i = 0; i < r->top; i++){
+ r->p[i] = ~(r->p[i] - c);
+ if(r->p[i] != 0)
+ c = 0;
+ }
+ mpnorm(r);
+}
--- a/libmp/mpmod.c
+++ b/libmp/mpmod.c
@@ -2,14 +2,15 @@
#include <mp.h>
#include "dat.h"
-// remainder = b mod m
-//
-// knuth, vol 2, pp 398-400
-
void
-mpmod(mpint *b, mpint *m, mpint *remainder)
+mpmod(mpint *x, mpint *n, mpint *r)
{
- mpdiv(b, m, nil, remainder);
- if(remainder->sign < 0)
- mpadd(m, remainder, remainder);
+ int sign;
+
+ sign = x->sign;
+ if((n->flags & MPfield) == 0
+ || ((Mfield*)n)->reduce((Mfield*)n, x, r) != 0)
+ mpdiv(x, n, nil, r);
+ if(sign < 0)
+ mpmagsub(n, r, r);
}
--- /dev/null
+++ b/libmp/mpmodop.c
@@ -1,0 +1,96 @@
+#include <u.h>
+#include <libc.h>
+#include <mp.h>
+
+/* operands need to have m->top+1 digits of space and satisfy 0 ≤ a ≤ m-1 */
+static mpint*
+modarg(mpint *a, mpint *m)
+{
+ if(a->size <= m->top || a->sign < 0 || mpmagcmp(a, m) >= 0){
+ a = mpcopy(a);
+ mpmod(a, m, a);
+ mpbits(a, Dbits*(m->top+1));
+ a->top = m->top;
+ } else if(a->top < m->top){
+ memset(&a->p[a->top], 0, (m->top - a->top)*Dbytes);
+ }
+ return a;
+}
+
+void
+mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum)
+{
+ mpint *a, *b;
+ mpdigit d;
+ int i, j;
+
+ a = modarg(b1, m);
+ b = modarg(b2, m);
+
+ sum->flags |= (a->flags | b->flags) & MPtimesafe;
+ mpbits(sum, Dbits*2*(m->top+1));
+
+ mpvecadd(a->p, m->top, b->p, m->top, sum->p);
+ mpvecsub(sum->p, m->top+1, m->p, m->top, sum->p+m->top+1);
+
+ d = sum->p[2*m->top+1];
+ for(i = 0, j = m->top+1; i < m->top; i++, j++)
+ sum->p[i] = (sum->p[i] & d) | (sum->p[j] & ~d);
+
+ sum->top = m->top;
+ sum->sign = 1;
+ mpnorm(sum);
+
+ if(a != b1)
+ mpfree(a);
+ if(b != b2)
+ mpfree(b);
+}
+
+void
+mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff)
+{
+ mpint *a, *b;
+ mpdigit d;
+ int i, j;
+
+ a = modarg(b1, m);
+ b = modarg(b2, m);
+
+ diff->flags |= (a->flags | b->flags) & MPtimesafe;
+ mpbits(diff, Dbits*2*(m->top+1));
+
+ a->p[m->top] = 0;
+ mpvecsub(a->p, m->top+1, b->p, m->top, diff->p);
+ mpvecadd(diff->p, m->top, m->p, m->top, diff->p+m->top+1);
+
+ d = ~diff->p[m->top];
+ for(i = 0, j = m->top+1; i < m->top; i++, j++)
+ diff->p[i] = (diff->p[i] & d) | (diff->p[j] & ~d);
+
+ diff->top = m->top;
+ diff->sign = 1;
+ mpnorm(diff);
+
+ if(a != b1)
+ mpfree(a);
+ if(b != b2)
+ mpfree(b);
+}
+
+void
+mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod)
+{
+ mpint *a, *b;
+
+ a = modarg(b1, m);
+ b = modarg(b2, m);
+
+ mpmul(a, b, prod);
+ mpmod(prod, m, prod);
+
+ if(a != b1)
+ mpfree(a);
+ if(b != b2)
+ mpfree(b);
+}
--- a/libmp/mpmul.c
+++ b/libmp/mpmul.c
@@ -113,10 +113,6 @@
a = b;
b = t;
}
- if(blen == 0){
- memset(p, 0, Dbytes*(alen+blen));
- return;
- }
if(alen >= KARATSUBAMIN && blen > 1){
// O(n^1.585)
@@ -132,24 +128,48 @@
}
void
+mpvectsmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p)
+{
+ int i;
+ mpdigit *t;
+
+ if(alen < blen){
+ i = alen;
+ alen = blen;
+ blen = i;
+ t = a;
+ a = b;
+ b = t;
+ }
+ if(blen == 0)
+ return;
+ for(i = 0; i < blen; i++)
+ mpvecdigmuladd(a, alen, b[i], &p[i]);
+}
+
+void
mpmul(mpint *b1, mpint *b2, mpint *prod)
{
mpint *oprod;
- oprod = nil;
+ oprod = prod;
if(prod == b1 || prod == b2){
- oprod = prod;
prod = mpnew(0);
+ prod->flags = oprod->flags;
}
+ prod->flags |= (b1->flags | b2->flags) & MPtimesafe;
prod->top = 0;
mpbits(prod, (b1->top+b2->top+1)*Dbits);
- mpvecmul(b1->p, b1->top, b2->p, b2->top, prod->p);
+ if(prod->flags & MPtimesafe)
+ mpvectsmul(b1->p, b1->top, b2->p, b2->top, prod->p);
+ else
+ mpvecmul(b1->p, b1->top, b2->p, b2->top, prod->p);
prod->top = b1->top+b2->top+1;
prod->sign = b1->sign*b2->sign;
mpnorm(prod);
- if(oprod != nil){
+ if(oprod != prod){
mpassign(prod, oprod);
mpfree(prod);
}
--- /dev/null
+++ b/libmp/mpnrand.c
@@ -1,0 +1,35 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+/* return uniform random [0..n-1] */
+mpint*
+mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b)
+{
+ mpint *m;
+ int bits;
+
+ /* m = 2^bits - 1 */
+ bits = mpsignif(n);
+ m = mpnew(bits+1);
+ mpleft(mpone, bits, m);
+ mpsub(m, mpone, m);
+
+ if(b == nil){
+ b = mpnew(bits);
+ setmalloctag(b, getcallerpc(&n));
+ }
+
+ /* m = m - (m % n) */
+ mpmod(m, n, b);
+ mpsub(m, b, m);
+
+ do {
+ mprand(bits, gen, b);
+ } while(mpcmp(b, m) >= 0);
+
+ mpmod(b, n, b);
+ mpfree(m);
+
+ return b;
+}
--- a/libmp/mprand.c
+++ b/libmp/mprand.c
@@ -1,24 +1,24 @@
#include "os.h"
#include <mp.h>
-#include <libsec.h>
#include "dat.h"
mpint*
mprand(int bits, void (*gen)(uchar*, int), mpint *b)
{
- int n, m;
mpdigit mask;
+ int n, m;
uchar *p;
n = DIGITS(bits);
- if(b == nil)
+ if(b == nil){
b = mpnew(bits);
- else
+ setmalloctag(b, getcallerpc(&bits));
+ }else
mpbits(b, bits);
p = malloc(n*Dbytes);
if(p == nil)
- return nil;
+ sysfatal("mprand: %r");
(*gen)(p, n*Dbytes);
betomp(p, n*Dbytes, b);
free(p);
@@ -25,18 +25,12 @@
// make sure we don't give too many bits
m = bits%Dbits;
- n--;
- if(m > 0){
- mask = 1;
- mask <<= m;
- mask--;
- b->p[n] &= mask;
- }
+ if(m == 0)
+ return b;
- for(; n >= 0; n--)
- if(b->p[n] != 0)
- break;
- b->top = n+1;
- b->sign = 1;
- return b;
+ mask = 1;
+ mask <<= m;
+ mask--;
+ b->p[n-1] &= mask;
+ return mpnorm(b);
}
--- a/libmp/mpright.c
+++ b/libmp/mpright.c
@@ -9,6 +9,12 @@
int d, l, r, i;
mpdigit this, last;
+ res->sign = b->sign;
+ if(b->top==0){
+ res->top = 0;
+ return;
+ }
+
// a negative right shift is a left shift
if(shift < 0){
mpleft(b, -shift, res);
@@ -17,10 +23,20 @@
if(res != b)
mpbits(res, b->top*Dbits - shift);
+ else if(shift == 0)
+ return;
+
d = shift/Dbits;
r = shift - d*Dbits;
l = Dbits - r;
+ // shift all the bits out == zero
+ if(d>=b->top){
+ res->sign = 1;
+ res->top = 0;
+ return;
+ }
+
// special case digit shifts
if(r == 0){
for(i = 0; i < b->top-d; i++)
@@ -34,7 +50,8 @@
}
res->p[i++] = last>>r;
}
- while(i > 0 && res->p[i-1] == 0)
- i--;
+
res->top = i;
+ res->flags |= b->flags & MPtimesafe;
+ mpnorm(res);
}
--- /dev/null
+++ b/libmp/mpsel.c
@@ -1,0 +1,42 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+// res = s != 0 ? b1 : b2
+void
+mpsel(int s, mpint *b1, mpint *b2, mpint *res)
+{
+ mpdigit d;
+ int n, m, i;
+
+ res->flags |= (b1->flags | b2->flags) & MPtimesafe;
+ if((res->flags & MPtimesafe) == 0){
+ mpassign(s ? b1 : b2, res);
+ return;
+ }
+ res->flags &= ~MPnorm;
+
+ n = b1->top;
+ m = b2->top;
+ mpbits(res, Dbits*(n >= m ? n : m));
+ res->top = n >= m ? n : m;
+
+ s = (-s^s|s)>>(sizeof(s)*8-1);
+ res->sign = (b1->sign & s) | (b2->sign & ~s);
+
+ d = -((mpdigit)s & 1);
+
+ i = 0;
+ while(i < n && i < m){
+ res->p[i] = (b1->p[i] & d) | (b2->p[i] & ~d);
+ i++;
+ }
+ while(i < n){
+ res->p[i] = b1->p[i] & d;
+ i++;
+ }
+ while(i < m){
+ res->p[i] = b2->p[i] & ~d;
+ i++;
+ }
+}
--- a/libmp/mpsub.c
+++ b/libmp/mpsub.c
@@ -11,12 +11,15 @@
// get the sizes right
if(mpmagcmp(b1, b2) < 0){
+ assert(((b1->flags | b2->flags | diff->flags) & MPtimesafe) == 0);
sign = -1;
t = b1;
b1 = b2;
b2 = t;
- } else
+ } else {
+ diff->flags |= (b1->flags | b2->flags) & MPtimesafe;
sign = 1;
+ }
n = b1->top;
m = b2->top;
if(m == 0){
@@ -39,6 +42,7 @@
int sign;
if(b1->sign != b2->sign){
+ assert(((b1->flags | b2->flags | diff->flags) & MPtimesafe) == 0);
sign = b1->sign;
mpmagadd(b1, b2, diff);
diff->sign = sign;
--- a/libmp/mptobe.c
+++ b/libmp/mptobe.c
@@ -2,56 +2,31 @@
#include <mp.h>
#include "dat.h"
-// convert an mpint into a big endian byte array (most significant byte first)
+// convert an mpint into a big endian byte array (most significant byte first; left adjusted)
// return number of bytes converted
// if p == nil, allocate and result array
int
mptobe(mpint *b, uchar *p, uint n, uchar **pp)
{
- int i, j, suppress;
- mpdigit x;
- uchar *e, *s, c;
+ int m;
+ m = (mpsignif(b)+7)/8;
+ if(m == 0)
+ m++;
if(p == nil){
- n = (b->top+1)*Dbytes;
+ n = m;
p = malloc(n);
+ if(p == nil)
+ sysfatal("mptobe: %r");
+ setmalloctag(p, getcallerpc(&b));
+ } else {
+ if(n < m)
+ return -1;
+ if(n > m)
+ memset(p+m, 0, n-m);
}
- if(p == nil)
- return -1;
if(pp != nil)
*pp = p;
- memset(p, 0, n);
-
- // special case 0
- if(b->top == 0){
- if(n < 1)
- return -1;
- else
- return 1;
- }
-
- s = p;
- e = s+n;
- suppress = 1;
- for(i = b->top-1; i >= 0; i--){
- x = b->p[i];
- for(j = Dbits-8; j >= 0; j -= 8){
- c = x>>j;
- if(c == 0 && suppress)
- continue;
- if(p >= e)
- return -1;
- *p++ = c;
- suppress = 0;
- }
- }
-
- // guarantee at least one byte
- if(s == p){
- if(p >= e)
- return -1;
- *p++ = 0;
- }
-
- return p - s;
+ mptober(b, p, m);
+ return m;
}
--- /dev/null
+++ b/libmp/mptober.c
@@ -1,0 +1,34 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+void
+mptober(mpint *b, uchar *p, int n)
+{
+ int i, j, m;
+ mpdigit x;
+
+ memset(p, 0, n);
+
+ p += n;
+ m = b->top*Dbytes;
+ if(m < n)
+ n = m;
+
+ i = 0;
+ while(n >= Dbytes){
+ n -= Dbytes;
+ x = b->p[i++];
+ for(j = 0; j < Dbytes; j++){
+ *--p = x;
+ x >>= 8;
+ }
+ }
+ if(n > 0){
+ x = b->p[i];
+ for(j = 0; j < n; j++){
+ *--p = x;
+ x >>= 8;
+ }
+ }
+}
--- a/libmp/mptoi.c
+++ b/libmp/mptoi.c
@@ -10,17 +10,15 @@
mpint*
itomp(int i, mpint *b)
{
- if(b == nil)
+ if(b == nil){
b = mpnew(0);
- mpassign(mpzero, b);
- if(i != 0)
- b->top = 1;
- if(i < 0){
- b->sign = -1;
- *b->p = -i;
- } else
- *b->p = i;
- return b;
+ setmalloctag(b, getcallerpc(&i));
+ }
+ b->sign = (i >> (sizeof(i)*8 - 1)) | 1;
+ i *= b->sign;
+ *b->p = i;
+ b->top = 1;
+ return mpnorm(b);
}
int
@@ -28,6 +26,8 @@
{
uint x;
+ if(b->top==0)
+ return 0;
x = *b->p;
if(b->sign > 0){
if(b->top > 1 || (x > MAXINT))
--- a/libmp/mptole.c
+++ b/libmp/mptole.c
@@ -3,52 +3,26 @@
#include "dat.h"
// convert an mpint into a little endian byte array (least significant byte first)
-
// return number of bytes converted
// if p == nil, allocate and result array
int
mptole(mpint *b, uchar *p, uint n, uchar **pp)
{
- int i, j;
- mpdigit x;
- uchar *e, *s;
+ int m;
+ m = (mpsignif(b)+7)/8;
+ if(m == 0)
+ m++;
if(p == nil){
- n = (b->top+1)*Dbytes;
+ n = m;
p = malloc(n);
- }
+ if(p == nil)
+ sysfatal("mptole: %r");
+ setmalloctag(p, getcallerpc(&b));
+ } else if(n < m)
+ return -1;
if(pp != nil)
*pp = p;
- if(p == nil)
- return -1;
- memset(p, 0, n);
-
- // special case 0
- if(b->top == 0){
- if(n < 1)
- return -1;
- else
- return 0;
- }
-
- s = p;
- e = s+n;
- for(i = 0; i < b->top-1; i++){
- x = b->p[i];
- for(j = 0; j < Dbytes; j++){
- if(p >= e)
- return -1;
- *p++ = x;
- x >>= 8;
- }
- }
- x = b->p[i];
- while(x > 0){
- if(p >= e)
- return -1;
- *p++ = x;
- x >>= 8;
- }
-
- return p - s;
+ mptolel(b, p, n);
+ return m;
}
--- /dev/null
+++ b/libmp/mptolel.c
@@ -1,0 +1,33 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+void
+mptolel(mpint *b, uchar *p, int n)
+{
+ int i, j, m;
+ mpdigit x;
+
+ memset(p, 0, n);
+
+ m = b->top*Dbytes;
+ if(m < n)
+ n = m;
+
+ i = 0;
+ while(n >= Dbytes){
+ n -= Dbytes;
+ x = b->p[i++];
+ for(j = 0; j < Dbytes; j++){
+ *p++ = x;
+ x >>= 8;
+ }
+ }
+ if(n > 0){
+ x = b->p[i];
+ for(j = 0; j < n; j++){
+ *p++ = x;
+ x >>= 8;
+ }
+ }
+}
--- a/libmp/mptoui.c
+++ b/libmp/mptoui.c
@@ -10,13 +10,14 @@
mpint*
uitomp(uint i, mpint *b)
{
- if(b == nil)
+ if(b == nil){
b = mpnew(0);
- mpassign(mpzero, b);
- if(i != 0)
- b->top = 1;
+ setmalloctag(b, getcallerpc(&i));
+ }
*b->p = i;
- return b;
+ b->top = 1;
+ b->sign = 1;
+ return mpnorm(b);
}
uint
@@ -25,11 +26,9 @@
uint x;
x = *b->p;
- if(b->sign < 0){
+ if(b->sign < 0)
x = 0;
- } else {
- if(b->top > 1 || x > MAXUINT)
- x = MAXUINT;
- }
+ else if(b->top > 1 || (sizeof(mpdigit) > sizeof(uint) && x > MAXUINT))
+ x = MAXUINT;
return x;
}
--- a/libmp/mptouv.c
+++ b/libmp/mptouv.c
@@ -13,19 +13,18 @@
{
int s;
- if(b == nil)
+ if(b == nil){
b = mpnew(VLDIGITS*sizeof(mpdigit));
- else
+ setmalloctag(b, getcallerpc(&v));
+ }else
mpbits(b, VLDIGITS*sizeof(mpdigit));
- mpassign(mpzero, b);
- if(v == 0)
- return b;
- for(s = 0; s < VLDIGITS && v != 0; s++){
+ b->sign = 1;
+ for(s = 0; s < VLDIGITS; s++){
b->p[s] = v;
v >>= sizeof(mpdigit)*8;
}
b->top = s;
- return b;
+ return mpnorm(b);
}
uvlong
@@ -35,15 +34,14 @@
int s;
if(b->top == 0)
- return (vlong) 0;
+ return 0LL;
- mpnorm(b);
if(b->top > VLDIGITS)
return MAXVLONG;
- v = (uvlong) 0;
+ v = 0ULL;
for(s = 0; s < b->top; s++)
- v |= b->p[s]<<(s*sizeof(mpdigit)*8);
+ v |= (uvlong)b->p[s]<<(s*sizeof(mpdigit)*8);
return v;
}
--- a/libmp/mptov.c
+++ b/libmp/mptov.c
@@ -14,24 +14,19 @@
int s;
uvlong uv;
- if(b == nil)
+ if(b == nil){
b = mpnew(VLDIGITS*sizeof(mpdigit));
- else
+ setmalloctag(b, getcallerpc(&v));
+ }else
mpbits(b, VLDIGITS*sizeof(mpdigit));
- mpassign(mpzero, b);
- if(v == 0)
- return b;
- if(v < 0){
- b->sign = -1;
- uv = -v;
- } else
- uv = v;
- for(s = 0; s < VLDIGITS && uv != 0; s++){
+ b->sign = (v >> (sizeof(v)*8 - 1)) | 1;
+ uv = v * b->sign;
+ for(s = 0; s < VLDIGITS; s++){
b->p[s] = uv;
uv >>= sizeof(mpdigit)*8;
}
b->top = s;
- return b;
+ return mpnorm(b);
}
vlong
@@ -41,9 +36,8 @@
int s;
if(b->top == 0)
- return (vlong) 0;
+ return 0LL;
- mpnorm(b);
if(b->top > VLDIGITS){
if(b->sign > 0)
return (vlong)MAXVLONG;
@@ -51,7 +45,7 @@
return (vlong)MINVLONG;
}
- v = (uvlong) 0;
+ v = 0ULL;
for(s = 0; s < b->top; s++)
v |= b->p[s]<<(s*sizeof(mpdigit)*8);
--- a/libmp/mpveccmp.c
+++ b/libmp/mpveccmp.c
@@ -2,7 +2,6 @@
#include <mp.h>
#include "dat.h"
-// prereq: alen >= blen
int
mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen)
{
--- /dev/null
+++ b/libmp/mpvectscmp.c
@@ -1,0 +1,34 @@
+#include "os.h"
+#include <mp.h>
+#include "dat.h"
+
+int
+mpvectscmp(mpdigit *a, int alen, mpdigit *b, int blen)
+{
+ mpdigit x, y, z, v;
+ int m, p;
+
+ if(alen > blen){
+ v = 0;
+ while(alen > blen)
+ v |= a[--alen];
+ m = p = (-v^v|v)>>Dbits-1;
+ } else if(blen > alen){
+ v = 0;
+ while(blen > alen)
+ v |= b[--blen];
+ m = (-v^v|v)>>Dbits-1;
+ p = m^1;
+ } else
+ m = p = 0;
+ while(alen-- > 0){
+ x = a[alen];
+ y = b[alen];
+ z = x - y;
+ x = ~x;
+ v = ((-z^z|z)>>Dbits-1) & ~m;
+ p = ((~(x&y|x&z|y&z)>>Dbits-1) & v) | (p & ~v);
+ m |= v;
+ }
+ return (p-m) | m;
+}
--- a/libmp/strtomp.c
+++ b/libmp/strtomp.c
@@ -1,6 +1,5 @@
#include "os.h"
#include <mp.h>
-#include <libsec.h>
#include "dat.h"
static struct {
@@ -32,37 +31,40 @@
memset(tab.t10, INVAL, sizeof(tab.t10));
for(p = set64; *p; p++)
- tab.t64[(uchar)*p] = p-set64;
+ tab.t64[*p] = p-set64;
for(p = set32; *p; p++)
- tab.t32[(uchar)*p] = p-set32;
+ tab.t32[*p] = p-set32;
for(p = set16; *p; p++)
- tab.t16[(uchar)*p] = (p-set16)%16;
+ tab.t16[*p] = (p-set16)%16;
for(p = set10; *p; p++)
- tab.t10[(uchar)*p] = (p-set10);
+ tab.t10[*p] = (p-set10);
tab.inited = 1;
}
static char*
-from16(char *a, mpint *b)
+frompow2(char *a, mpint *b, int s)
{
char *p, *next;
int i;
mpdigit x;
+ int sn;
- b->top = 0;
+ sn = 1<<s;
for(p = a; *p; p++)
- if(tab.t16[(uchar)*p] == INVAL)
+ if(tab.t16[*(uchar*)p] >= sn)
break;
- mpbits(b, (p-a)*4);
+
+ mpbits(b, (p-a)*s);
b->top = 0;
next = p;
+
while(p > a){
x = 0;
- for(i = 0; i < Dbits; i += 4){
+ for(i = 0; i < Dbits; i += s){
if(p <= a)
break;
- x |= tab.t16[(uchar)*--p]<<i;
+ x |= tab.t16[*(uchar*)--p]<<i;
}
b->p[b->top++] = x;
}
@@ -69,6 +71,40 @@
return next;
}
+static char*
+from8(char *a, mpint *b)
+{
+ char *p, *next;
+ mpdigit x, y;
+ int i;
+
+ for(p = a; *p; p++)
+ if(tab.t10[*(uchar*)p] >= 8)
+ break;
+
+ mpbits(b, (a-p)*3);
+ b->top = 0;
+ next = p;
+
+ i = 0;
+ x = y = 0;
+ while(p > a){
+ y = tab.t10[*(uchar*)--p];
+ x |= y << i;
+ i += 3;
+ if(i >= Dbits){
+Digout:
+ i -= Dbits;
+ b->p[b->top++] = x;
+ x = y >> 3-i;
+ }
+ }
+ if(i > 0)
+ goto Digout;
+
+ return next;
+}
+
static ulong mppow10[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
};
@@ -88,7 +124,7 @@
// do a billion at a time in native arithmetic
x = 0;
for(i = 0; i < 9; i++){
- y = tab.t10[(uchar)*a];
+ y = tab.t10[*(uchar*)a];
if(y == INVAL)
break;
a++;
@@ -112,45 +148,28 @@
}
static char*
-from64(char *a, mpint *b)
+fromdecx(char *a, mpint *b, uchar tab[256], int (*dec)(uchar*, int, char*, int))
{
char *buf = a;
uchar *p;
int n, m;
- for(; tab.t64[(uchar)*a] != INVAL; a++)
+ b->top = 0;
+ for(; tab[*(uchar*)a] != INVAL; a++)
;
n = a-buf;
- mpbits(b, n*6);
- p = malloc(n);
- if(p == nil)
- return a;
- m = dec64(p, n, buf, n);
- betomp(p, m, b);
- free(p);
+ if(n > 0){
+ p = malloc(n);
+ if(p == nil)
+ sysfatal("malloc: %r");
+ m = (*dec)(p, n, buf, n);
+ if(m > 0)
+ betomp(p, m, b);
+ free(p);
+ }
return a;
}
-static char*
-from32(char *a, mpint *b)
-{
- char *buf = a;
- uchar *p;
- int n, m;
-
- for(; tab.t64[(uchar)*a] != INVAL; a++)
- ;
- n = a-buf;
- mpbits(b, n*5);
- p = malloc(n);
- if(p == nil)
- return a;
- m = dec32(p, n, buf, n);
- betomp(p, m, b);
- free(p);
- return a;
-}
-
mpint*
strtomp(char *a, char **pp, int base, mpint *b)
{
@@ -157,8 +176,10 @@
int sign;
char *e;
- if(b == nil)
+ if(b == nil){
b = mpnew(0);
+ setmalloctag(b, getcallerpc(&a));
+ }
if(tab.inited == 0)
init();
@@ -176,20 +197,47 @@
break;
}
+ if(base == 0){
+ base = 10;
+ if(a[0] == '0'){
+ if(a[1] == 'x' || a[1] == 'X') {
+ a += 2;
+ base = 16;
+ } else if(a[1] == 'b' || a[1] == 'B') {
+ a += 2;
+ base = 2;
+ } else if(a[1] >= '0' && a[1] <= '7') {
+ a++;
+ base = 8;
+ }
+ }
+ }
+
switch(base){
+ case 2:
+ e = frompow2(a, b, 1);
+ break;
+ case 4:
+ e = frompow2(a, b, 2);
+ break;
+ case 8:
+ e = from8(a, b);
+ break;
case 10:
e = from10(a, b);
break;
- default:
case 16:
- e = from16(a, b);
+ e = frompow2(a, b, 4);
break;
case 32:
- e = from32(a, b);
+ e = fromdecx(a, b, tab.t32, dec32);
break;
case 64:
- e = from64(a, b);
+ e = fromdecx(a, b, tab.t64, dec64);
break;
+ default:
+ abort();
+ return nil;
}
// if no characters parsed, there wasn't a number to convert
@@ -196,10 +244,9 @@
if(e == a)
return nil;
- mpnorm(b);
- b->sign = sign;
if(pp != nil)
*pp = e;
- return b;
+ b->sign = sign;
+ return mpnorm(b);
}
--- a/libsec/Makefile
+++ b/libsec/Makefile
@@ -4,7 +4,12 @@
OFILES=\
aes.$O\
+ aes_xts.$O\
blowfish.$O\
+ ccpoly.$O\
+ chacha.$O\
+ curve25519.$O\
+ curve25519_dh.$O\
decodepem.$O\
des.$O\
des3CBC.$O\
@@ -12,6 +17,7 @@
desCBC.$O\
desECB.$O\
desmodes.$O\
+ dh.$O\
dsaalloc.$O\
dsagen.$O\
dsaprimes.$O\
@@ -18,6 +24,7 @@
dsaprivtopub.$O\
dsasign.$O\
dsaverify.$O\
+ ecc.$O\
egalloc.$O\
egdecrypt.$O\
egencrypt.$O\
@@ -30,14 +37,18 @@
genrandom.$O\
gensafeprime.$O\
genstrongprime.$O\
+ hkdf.$O\
hmac.$O\
md4.$O\
md5.$O\
md5pickle.$O\
nfastrand.$O\
+ pbkdf2.$O\
+ poly1305.$O\
prng.$O\
probably_prime.$O\
rc4.$O\
+ ripemd.$O\
rsaalloc.$O\
rsadecrypt.$O\
rsaencrypt.$O\
@@ -44,9 +55,19 @@
rsafill.$O\
rsagen.$O\
rsaprivtopub.$O\
+ salsa.$O\
+ secp256k1.$O\
+ secp256r1.$O\
sha1.$O\
sha1pickle.$O\
- smallprimes.$O
+ sha2_128.$O\
+ sha2_64.$O\
+ sha2block128.$O\
+ sha2block64.$O\
+ smallprimes.$O\
+ tsmemcmp.$O\
+ tlshand.$O\
+ x509.$O
default: $(LIB)
$(LIB): $(OFILES)
--- a/libsec/aes.c
+++ b/libsec/aes.c
@@ -30,11 +30,14 @@
*/
#include <u.h>
#include <libc.h>
+#include <mp.h>
#include <libsec.h>
typedef uchar u8;
-typedef u32int u32;
+typedef ulong u32;
+
#define FULL_UNROLL
+#define const
static const u32 Td0[256];
static const u32 Td1[256];
@@ -41,15 +44,30 @@
static const u32 Td2[256];
static const u32 Td3[256];
static const u8 Te4[256];
+static uchar basekey[3][16] = {
+ {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ },
+ {
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ },
+ {
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ },
+};
-static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
+static int aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
+ int keyBits);
+static int aes_setupDec(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
+ int keyBits);
+static int aes_setup(ulong erk[/*4*(Nr + 1)*/], ulong drk[/*4*(Nr + 1)*/],
+ const uchar cipherKey[], int keyBits);
-#ifdef NOT
-static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-#endif
-static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-static void rijndaelEncrypt(const u32int rk[], int Nr, const uchar pt[16], uchar ct[16]);
-static void rijndaelDecrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]);
+void aes_encrypt(const ulong rk[], int Nr, const uchar pt[16], uchar ct[16]);
+void aes_decrypt(const ulong rk[], int Nr, const uchar ct[16], uchar pt[16]);
void
setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
@@ -59,18 +77,97 @@
keybytes = AESmaxkey;
memmove(s->key, key, keybytes);
s->keybytes = keybytes;
- s->rounds = rijndaelKeySetup(s->ekey, s->dkey, s->key, keybytes * 8);
+ s->rounds = aes_setup(s->ekey, s->dkey, s->key, keybytes * 8);
if(ivec != nil)
memmove(s->ivec, ivec, AESbsize);
if(keybytes==16 || keybytes==24 || keybytes==32)
s->setup = 0xcafebabe;
- // else rijndaelKeySetup was invalid
+ /* else aes_setup was invalid */
}
-// Define by analogy with desCBCencrypt; AES modes are not standardized yet.
-// Because of the way that non-multiple-of-16 buffers are handled,
-// the decryptor must be fed buffers of the same size as the encryptor.
+/*
+ * AES-XCBC-MAC-96 message authentication, per rfc3566.
+ */
+
void
+setupAESXCBCstate(AESstate *s) /* was setupmac96 */
+{
+ int i, j;
+ uint q[16 / sizeof(uint)];
+ uchar *p;
+
+ assert(s->keybytes == 16);
+ for(i = 0; i < 3; i++)
+ aes_encrypt(s->ekey, s->rounds, basekey[i],
+ s->mackey + AESbsize*i);
+
+ p = s->mackey;
+ memset(q, 0, AESbsize);
+
+ /*
+ * put the in the right endian. once figured, probably better
+ * to use some fcall macros.
+ * keys for encryption in local endianness for the algorithm...
+ * only key1 is used for encryption;
+ * BUG!!: I think this is what I got wrong.
+ */
+ for(i = 0; i < 16 / sizeof(uint); i ++){
+ for(j = 0; j < sizeof(uint); j++)
+ q[i] |= p[sizeof(uint)-j-1] << 8*j;
+ p += sizeof(uint);
+ }
+ memmove(s->mackey, q, 16);
+}
+
+/*
+ * Not dealing with > 128-bit keys, not dealing with strange corner cases like
+ * empty message. Should be fine for AES-XCBC-MAC-96.
+ */
+uchar*
+aesXCBCmac(uchar *p, int len, AESstate *s)
+{
+ uchar *p2, *ip, *eip, *mackey;
+ uchar q[AESbsize];
+
+ assert(s->keybytes == 16); /* more complicated for bigger */
+ memset(s->ivec, 0, AESbsize); /* E[0] is 0+ */
+
+ for(; len > AESbsize; len -= AESbsize){
+ memmove(q, p, AESbsize);
+ p2 = q;
+ ip = s->ivec;
+ for(eip = ip + AESbsize; ip < eip; )
+ *p2++ ^= *ip++;
+ aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
+ p += AESbsize;
+ }
+ /* the last one */
+
+ memmove(q, p, len);
+ p2 = q+len;
+ if(len == AESbsize)
+ mackey = s->mackey + AESbsize; /* k2 */
+ else{
+ mackey = s->mackey+2*AESbsize; /* k3 */
+ *p2++ = 1 << 7; /* padding */
+ len = AESbsize - len - 1;
+ memset(p2, 0, len);
+ }
+
+ ip = s->ivec;
+ p2 = q;
+ for(eip = ip + AESbsize; ip < eip; )
+ *p2++ ^= *ip++ ^ *mackey++;
+ aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
+ return s->ivec; /* only the 12 bytes leftmost */
+}
+
+/*
+ * Define by analogy with desCBCencrypt; AES modes are not standardized yet.
+ * Because of the way that non-multiple-of-16 buffers are handled,
+ * the decryptor must be fed buffers of the same size as the encryptor.
+ */
+void
aesCBCencrypt(uchar *p, int len, AESstate *s)
{
uchar *p2, *ip, *eip;
@@ -81,7 +178,7 @@
ip = s->ivec;
for(eip = ip+AESbsize; ip < eip; )
*p2++ ^= *ip++;
- rijndaelEncrypt(s->ekey, s->rounds, p, q);
+ aes_encrypt(s->ekey, s->rounds, p, q);
memmove(s->ivec, q, AESbsize);
memmove(p, q, AESbsize);
p += AESbsize;
@@ -89,7 +186,7 @@
if(len > 0){
ip = s->ivec;
- rijndaelEncrypt(s->ekey, s->rounds, ip, q);
+ aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; )
*p++ ^= *ip++;
@@ -104,7 +201,7 @@
for(; len >= AESbsize; len -= AESbsize){
memmove(tmp, p, AESbsize);
- rijndaelDecrypt(s->dkey, s->rounds, p, q);
+ aes_decrypt(s->dkey, s->rounds, p, q);
memmove(p, q, AESbsize);
tp = tmp;
ip = s->ivec;
@@ -116,7 +213,7 @@
if(len > 0){
ip = s->ivec;
- rijndaelEncrypt(s->ekey, s->rounds, ip, q);
+ aes_encrypt(s->ekey, s->rounds, ip, q);
memmove(s->ivec, q, AESbsize);
for(eip = ip+len; ip < eip; )
*p++ ^= *ip++;
@@ -129,23 +226,26 @@
*
* @return the number of rounds for the given cipher key size.
*/
-static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+static int
+aes_setup(ulong erk[/* 4*(Nr + 1) */], ulong drk[/* 4*(Nr + 1) */],
+ const uchar cipherKey[], int keyBits)
+{
int Nr, i;
/* expand the cipher key: */
- Nr = rijndaelKeySetupEnc(erk, cipherKey, keyBits);
+ Nr = aes_setupEnc(erk, cipherKey, keyBits);
/*
- * invert the order of the round keys and
- * apply the inverse MixColumn transform to all round keys but the first and the last
+ * invert the order of the round keys and apply the inverse MixColumn
+ * transform to all round keys but the first and the last
*/
- drk[0 ] = erk[4*Nr ];
+ drk[0 ] = erk[4*Nr ];
drk[1 ] = erk[4*Nr + 1];
- drk[2 ] = erk[4*Nr + 2];
+ drk[2 ] = erk[4*Nr + 2];
drk[3 ] = erk[4*Nr + 3];
- drk[4*Nr ] = erk[0 ];
+ drk[4*Nr ] = erk[0 ];
drk[4*Nr + 1] = erk[1 ];
- drk[4*Nr + 2] = erk[2 ];
+ drk[4*Nr + 2] = erk[2 ];
drk[4*Nr + 3] = erk[3 ];
erk += 4 * Nr;
for (i = 1; i < Nr; i++) {
@@ -175,6 +275,7 @@
return Nr;
}
+
/*
Te0[x] = S [x].[02, 01, 01, 03];
Te1[x] = S [x].[03, 02, 01, 01];
@@ -854,26 +955,24 @@
static const u32 rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
- 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
};
-#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(pt) (((u32)(pt)[0]<<24) ^ ((u32)(pt)[1]<<16) ^ \
+ ((u32)(pt)[2]<< 8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st)>>24); (ct)[1] = (u8)((st)>>16); \
+ (ct)[2] = (u8)((st)>> 8); (ct)[3] = (u8)(st); }
-#ifdef _MSC_VER
-#define GETU32(p) SWAP(*((u32 *)(p)))
-#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
-#else
-#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
-#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
-#endif
-
-/**
+/*
* Expand the cipher key into the encryption key schedule.
*
* @return the number of rounds for the given cipher key size.
*/
-static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
- int i = 0;
+static int
+aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[], int keyBits)
+{
+ int i = 0;
u32 temp;
rk[0] = GETU32(cipherKey );
@@ -923,32 +1022,31 @@
rk[6] = GETU32(cipherKey + 24);
rk[7] = GETU32(cipherKey + 28);
if (keyBits == 256) {
- for (;;) {
- temp = rk[ 7];
- rk[ 8] = rk[ 0] ^
- (Te4[(temp >> 16) & 0xff] << 24) ^
- (Te4[(temp >> 8) & 0xff] << 16) ^
- (Te4[(temp ) & 0xff] << 8) ^
- (Te4[(temp >> 24) ] ) ^
- rcon[i];
- rk[ 9] = rk[ 1] ^ rk[ 8];
- rk[10] = rk[ 2] ^ rk[ 9];
- rk[11] = rk[ 3] ^ rk[10];
+ for (;;) {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[(temp >> 16) & 0xff] << 24) ^
+ (Te4[(temp >> 8) & 0xff] << 16) ^
+ (Te4[(temp ) & 0xff] << 8) ^
+ (Te4[(temp >> 24) ] ) ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
if (++i == 7) {
return 14;
}
- temp = rk[11];
- rk[12] = rk[ 4] ^
- (Te4[(temp >> 24) ] << 24) ^
- (Te4[(temp >> 16) & 0xff] << 16) ^
- (Te4[(temp >> 8) & 0xff] << 8) ^
- (Te4[(temp ) & 0xff] );
- rk[13] = rk[ 5] ^ rk[12];
- rk[14] = rk[ 6] ^ rk[13];
- rk[15] = rk[ 7] ^ rk[14];
-
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[(temp >> 24) ] << 24) ^
+ (Te4[(temp >> 16) & 0xff] << 16) ^
+ (Te4[(temp >> 8) & 0xff] << 8) ^
+ (Te4[(temp ) & 0xff] );
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
rk += 8;
- }
+ }
}
return 0;
}
@@ -958,13 +1056,14 @@
*
* @return the number of rounds for the given cipher key size.
*/
-#ifdef NOTUSED
-static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+static int
+aes_setupDec(ulong rk[/* 4*(Nr + 1) */], const uchar cipherKey[], int keyBits)
+{
int Nr, i, j;
- u32 temp;
+ ulong temp;
/* expand the cipher key: */
- Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+ Nr = aes_setupEnc(rk, cipherKey, keyBits);
/* invert the order of the round keys: */
for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
@@ -972,7 +1071,10 @@
temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
}
- /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ /*
+ * apply the inverse MixColumn transform to all round keys
+ * but the first and the last:
+ */
for (i = 1; i < Nr; i++) {
rk += 4;
rk[0] =
@@ -998,15 +1100,18 @@
}
return Nr;
}
-#endif
-static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
- u32 s0, s1, s2, s3, t0, t1, t2, t3;
+/* using round keys in rk, perform Nr rounds of encrypting pt into ct */
+void
+aes_encrypt(const ulong rk[/* 4*(Nr + 1) */], int Nr, const uchar pt[16],
+ uchar ct[16])
+{
+ ulong s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
- int r;
+ int r;
#endif /* ?FULL_UNROLL */
- /*
+ /*
* map byte array block to cipher state
* and add initial round key:
*/
@@ -1015,7 +1120,7 @@
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];
#ifdef FULL_UNROLL
- /* round 1: */
+ /* round 1: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
@@ -1025,7 +1130,7 @@
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
- /* round 3: */
+ /* round 3: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
@@ -1035,7 +1140,7 @@
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
- /* round 5: */
+ /* round 5: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
@@ -1045,7 +1150,7 @@
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
- /* round 7: */
+ /* round 7: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
@@ -1055,99 +1160,98 @@
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
- /* round 9: */
+ /* round 9: */
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
- if (Nr > 10) {
- /* round 10: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
- /* round 11: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
- if (Nr > 12) {
- /* round 12: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
- /* round 13: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
- }
- }
- rk += Nr << 2;
-#else /* !FULL_UNROLL */
- /*
+ if (Nr > 10) {
+ /* round 10: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+ if (Nr > 12) {
+ /* round 12: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+ }
+ }
+ rk += Nr << 2;
+#else /* !FULL_UNROLL */
+ /*
* Nr - 1 full rounds:
*/
- r = Nr >> 1;
- for (;;) {
- t0 =
- Te0[(s0 >> 24) ] ^
- Te1[(s1 >> 16) & 0xff] ^
- Te2[(s2 >> 8) & 0xff] ^
- Te3[(s3 ) & 0xff] ^
- rk[4];
- t1 =
- Te0[(s1 >> 24) ] ^
- Te1[(s2 >> 16) & 0xff] ^
- Te2[(s3 >> 8) & 0xff] ^
- Te3[(s0 ) & 0xff] ^
- rk[5];
- t2 =
- Te0[(s2 >> 24) ] ^
- Te1[(s3 >> 16) & 0xff] ^
- Te2[(s0 >> 8) & 0xff] ^
- Te3[(s1 ) & 0xff] ^
- rk[6];
- t3 =
- Te0[(s3 >> 24) ] ^
- Te1[(s0 >> 16) & 0xff] ^
- Te2[(s1 >> 8) & 0xff] ^
- Te3[(s2 ) & 0xff] ^
- rk[7];
+ r = Nr >> 1;
+ for (;;) {
+ t0 =
+ Te0[(s0 >> 24) ] ^
+ Te1[(s1 >> 16) & 0xff] ^
+ Te2[(s2 >> 8) & 0xff] ^
+ Te3[(s3 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Te0[(s1 >> 24) ] ^
+ Te1[(s2 >> 16) & 0xff] ^
+ Te2[(s3 >> 8) & 0xff] ^
+ Te3[(s0 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Te0[(s2 >> 24) ] ^
+ Te1[(s3 >> 16) & 0xff] ^
+ Te2[(s0 >> 8) & 0xff] ^
+ Te3[(s1 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Te0[(s3 >> 24) ] ^
+ Te1[(s0 >> 16) & 0xff] ^
+ Te2[(s1 >> 8) & 0xff] ^
+ Te3[(s2 ) & 0xff] ^
+ rk[7];
- rk += 8;
- if (--r == 0) {
- break;
- }
+ rk += 8;
+ if (--r == 0)
+ break;
- s0 =
- Te0[(t0 >> 24) ] ^
- Te1[(t1 >> 16) & 0xff] ^
- Te2[(t2 >> 8) & 0xff] ^
- Te3[(t3 ) & 0xff] ^
- rk[0];
- s1 =
- Te0[(t1 >> 24) ] ^
- Te1[(t2 >> 16) & 0xff] ^
- Te2[(t3 >> 8) & 0xff] ^
- Te3[(t0 ) & 0xff] ^
- rk[1];
- s2 =
- Te0[(t2 >> 24) ] ^
- Te1[(t3 >> 16) & 0xff] ^
- Te2[(t0 >> 8) & 0xff] ^
- Te3[(t1 ) & 0xff] ^
- rk[2];
- s3 =
- Te0[(t3 >> 24) ] ^
- Te1[(t0 >> 16) & 0xff] ^
- Te2[(t1 >> 8) & 0xff] ^
- Te3[(t2 ) & 0xff] ^
- rk[3];
- }
-#endif /* ?FULL_UNROLL */
- /*
+ s0 =
+ Te0[(t0 >> 24) ] ^
+ Te1[(t1 >> 16) & 0xff] ^
+ Te2[(t2 >> 8) & 0xff] ^
+ Te3[(t3 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Te0[(t1 >> 24) ] ^
+ Te1[(t2 >> 16) & 0xff] ^
+ Te2[(t3 >> 8) & 0xff] ^
+ Te3[(t0 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Te0[(t2 >> 24) ] ^
+ Te1[(t3 >> 16) & 0xff] ^
+ Te2[(t0 >> 8) & 0xff] ^
+ Te3[(t1 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Te0[(t3 >> 24) ] ^
+ Te1[(t0 >> 16) & 0xff] ^
+ Te2[(t1 >> 8) & 0xff] ^
+ Te3[(t2 ) & 0xff] ^
+ rk[3];
+ }
+#endif /* ?FULL_UNROLL */
+ /*
* apply last round and
* map cipher state to byte array block:
*/
@@ -1181,13 +1285,16 @@
PUTU32(ct + 12, s3);
}
-static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
- u32 s0, s1, s2, s3, t0, t1, t2, t3;
+void
+aes_decrypt(const ulong rk[/* 4*(Nr + 1) */], int Nr, const uchar ct[16],
+ uchar pt[16])
+{
+ ulong s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
- int r;
-#endif /* ?FULL_UNROLL */
+ int r;
+#endif /* ?FULL_UNROLL */
- /*
+ /*
* map byte array block to cipher state
* and add initial round key:
*/
@@ -1265,8 +1372,8 @@
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
}
}
- rk += Nr << 2;
-#else /* !FULL_UNROLL */
+ rk += Nr << 2;
+#else /* !FULL_UNROLL */
/*
* Nr - 1 full rounds:
*/
@@ -1298,9 +1405,8 @@
rk[7];
rk += 8;
- if (--r == 0) {
+ if (--r == 0)
break;
- }
s0 =
Td0[(t0 >> 24) ] ^
@@ -1327,8 +1433,8 @@
Td3[(t0 ) & 0xff] ^
rk[3];
}
-#endif /* ?FULL_UNROLL */
- /*
+#endif /* ?FULL_UNROLL */
+ /*
* apply last round and
* map cipher state to byte array block:
*/
@@ -1364,11 +1470,14 @@
#ifdef INTERMEDIATE_VALUE_KAT
-static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
+static void
+aes_encryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
+ int rounds)
+{
int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3;
- /*
+ /*
* map byte array block to cipher state
* and add initial round key:
*/
@@ -1376,9 +1485,9 @@
s1 = GETU32(block + 4) ^ rk[1];
s2 = GETU32(block + 8) ^ rk[2];
s3 = GETU32(block + 12) ^ rk[3];
- rk += 4;
+ rk += 4;
- /*
+ /*
* Nr - 1 full rounds:
*/
for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
@@ -1406,45 +1515,42 @@
Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^
rk[3];
-
s0 = t0;
s1 = t1;
s2 = t2;
s3 = t3;
rk += 4;
+ }
- }
-
- /*
+ /*
* apply last round and
* map cipher state to byte array block:
*/
if (rounds == Nr) {
- t0 =
- (Te4[(s0 >> 24) ] << 24) ^
- (Te4[(s1 >> 16) & 0xff] << 16) ^
- (Te4[(s2 >> 8) & 0xff] << 8) ^
- (Te4[(s3 ) & 0xff] ) ^
- rk[0];
- t1 =
- (Te4[(s1 >> 24) ] << 24) ^
- (Te4[(s2 >> 16) & 0xff] << 16) ^
- (Te4[(s3 >> 8) & 0xff] << 8) ^
- (Te4[(s0 ) & 0xff] ) ^
- rk[1];
- t2 =
- (Te4[(s2 >> 24) ] << 24) ^
- (Te4[(s3 >> 16) & 0xff] << 16) ^
- (Te4[(s0 >> 8) & 0xff] << 8) ^
- (Te4[(s1 ) & 0xff] ) ^
- rk[2];
- t3 =
- (Te4[(s3 >> 24) ] << 24) ^
- (Te4[(s0 >> 16) & 0xff] << 16) ^
- (Te4[(s1 >> 8) & 0xff] << 8) ^
- (Te4[(s2 ) & 0xff] ) ^
- rk[3];
-
+ t0 =
+ (Te4[(s0 >> 24) ] << 24) ^
+ (Te4[(s1 >> 16) & 0xff] << 16) ^
+ (Te4[(s2 >> 8) & 0xff] << 8) ^
+ (Te4[(s3 ) & 0xff] ) ^
+ rk[0];
+ t1 =
+ (Te4[(s1 >> 24) ] << 24) ^
+ (Te4[(s2 >> 16) & 0xff] << 16) ^
+ (Te4[(s3 >> 8) & 0xff] << 8) ^
+ (Te4[(s0 ) & 0xff] ) ^
+ rk[1];
+ t2 =
+ (Te4[(s2 >> 24) ] << 24) ^
+ (Te4[(s3 >> 16) & 0xff] << 16) ^
+ (Te4[(s0 >> 8) & 0xff] << 8) ^
+ (Te4[(s1 ) & 0xff] ) ^
+ rk[2];
+ t3 =
+ (Te4[(s3 >> 24) ] << 24) ^
+ (Te4[(s0 >> 16) & 0xff] << 16) ^
+ (Te4[(s1 >> 8) & 0xff] << 8) ^
+ (Te4[(s2 ) & 0xff] ) ^
+ rk[3];
s0 = t0;
s1 = t1;
s2 = t2;
@@ -1457,11 +1563,14 @@
PUTU32(block + 12, s3);
}
-static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
+static void
+aes_decryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
+ int rounds)
+{
int r;
u32 s0, s1, s2, s3, t0, t1, t2, t3;
- /*
+ /*
* map byte array block to cipher state
* and add initial round key:
*/
@@ -1469,9 +1578,9 @@
s1 = GETU32(block + 4) ^ rk[1];
s2 = GETU32(block + 8) ^ rk[2];
s3 = GETU32(block + 12) ^ rk[3];
- rk += 4;
+ rk += 4;
- /*
+ /*
* Nr - 1 full rounds:
*/
for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
@@ -1505,10 +1614,9 @@
s2 = t2;
s3 = t3;
rk += 4;
+ }
- }
-
- /*
+ /*
* complete the last round and
* map cipher state to byte array block:
*/
@@ -1534,10 +1642,10 @@
(Td4[(s0 ) & 0xff] );
if (rounds == Nr) {
- t0 ^= rk[0];
- t1 ^= rk[1];
- t2 ^= rk[2];
- t3 ^= rk[3];
+ t0 ^= rk[0];
+ t1 ^= rk[1];
+ t2 ^= rk[2];
+ t3 ^= rk[3];
}
PUTU32(block , t0);
@@ -1546,4 +1654,4 @@
PUTU32(block + 12, t3);
}
-#endif /* INTERMEDIATE_VALUE_KAT */
+#endif /* INTERMEDIATE_VALUE_KAT */
--- /dev/null
+++ b/libsec/aes_xts.c
@@ -1,0 +1,70 @@
+// Author Taru Karttunen <taruti@taruti.net>
+// This file can be used as both Public Domain or Creative Commons CC0.
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+#define AesBlockSize 16
+
+static void xor128(uchar* o,uchar* i1,uchar* i2) {
+ ((ulong*)o)[0] = ((ulong*)i1)[0] ^ ((ulong*)i2)[0];
+ ((ulong*)o)[1] = ((ulong*)i1)[1] ^ ((ulong*)i2)[1];
+ ((ulong*)o)[2] = ((ulong*)i1)[2] ^ ((ulong*)i2)[2];
+ ((ulong*)o)[3] = ((ulong*)i1)[3] ^ ((ulong*)i2)[3];
+}
+
+static void gf_mulx(uchar* x) {
+ ulong t = ((((ulong*)(x))[3] & 0x80000000u) ? 0x00000087u : 0);;
+ ((ulong*)(x))[3] = (((ulong*)(x))[3] << 1) | (((ulong*)(x))[2] & 0x80000000u ? 1 : 0);
+ ((ulong*)(x))[2] = (((ulong*)(x))[2] << 1) | (((ulong*)(x))[1] & 0x80000000u ? 1 : 0);
+ ((ulong*)(x))[1] = (((ulong*)(x))[1] << 1) | (((ulong*)(x))[0] & 0x80000000u ? 1 : 0);
+ ((ulong*)(x))[0] = (((ulong*)(x))[0] << 1) ^ t;
+
+}
+
+int aes_xts_encrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) {
+ uchar T[16], x[16];
+ int i;
+
+ if(len % 16 != 0)
+ return -1;
+
+ for(i=0; i<AesBlockSize; i++) {
+ T[i] = (uchar)(sectorNumber & 0xFF);
+ sectorNumber = sectorNumber >> 8;
+ }
+
+ aes_encrypt(tweak, 10, T, T);
+
+ for (i=0; i<len; i+=AesBlockSize) {
+ xor128(&x[0], &input[i], &T[0]);
+ aes_encrypt(ecb, 10, x, x);
+ xor128(&output[i], &x[0], &T[0]);
+ gf_mulx(&T[0]);
+ }
+ return 0;
+}
+
+int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) {
+ uchar T[16], x[16];
+ int i;
+
+ if(len % 16 != 0)
+ return -1;
+
+ for(i=0; i<AesBlockSize; i++) {
+ T[i] = (uchar)(sectorNumber & 0xFF);
+ sectorNumber = sectorNumber >> 8;
+ }
+
+ aes_encrypt(tweak, 10, T, T);
+
+ for (i=0; i<len; i+=AesBlockSize) {
+ xor128(&x[0], &input[i], &T[0]);
+ aes_decrypt(ecb, 10, x, x);
+ xor128(&output[i], &x[0], &T[0]);
+ gf_mulx(&T[0]);
+ }
+ return 0;
+}
+
--- a/libsec/blowfish.c
+++ b/libsec/blowfish.c
@@ -13,6 +13,37 @@
static void bfencrypt(u32int *, BFstate *);
static void bfdecrypt(u32int *, BFstate *);
+/*
+ * Endianess agnostic functions to convert a
+ * block (8-byte buffer) to a u32int array and
+ * viceversa.
+ */
+
+static void
+buf2ints(uchar *p, u32int *b)
+{
+ b[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
+ b[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
+}
+
+static void
+ints2buf(u32int *b, uchar *p)
+{
+ u32int u;
+
+ u = b[0];
+ p[0] = u>>24;
+ p[1] = u>>16;
+ p[2] = u>>8;
+ p[3] = u;
+
+ u = b[1];
+ p[4] = u>>24;
+ p[5] = u>>16;
+ p[6] = u>>8;
+ p[7] = u;
+}
+
void
setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec)
{
@@ -31,7 +62,7 @@
memmove(s->ivec, ivec, sizeof(s->ivec));
else
memset(s->ivec, 0, sizeof(s->ivec));
-
+
memmove(s->pbox, pbox, sizeof(pbox));
memmove(s->sbox, sbox, sizeof(sbox));
@@ -76,17 +107,13 @@
bfCBCencrypt(uchar *buf, int n, BFstate *s)
{
int i;
- uchar *p;
- u32int bo[2], bi[2], b;
+ u32int bo[2], bi[2];
assert((n & 7) == 0);
- bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24);
- bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24);
-
+ buf2ints(s->ivec, bo);
for(i=0; i < n; i += 8, buf += 8) {
- bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
- bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
+ buf2ints(buf, bi);
bi[0] ^= bo[0];
bi[1] ^= bo[1];
@@ -96,36 +123,9 @@
bo[0] = bi[0];
bo[1] = bi[1];
- p = buf;
- b = bo[0];
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
-
- b = bo[1];
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p = b;
+ ints2buf(bi, buf);
}
-
- s->ivec[7] = bo[1] >> 24;
- s->ivec[6] = bo[1] >> 16;
- s->ivec[5] = bo[1] >> 8;
- s->ivec[4] = bo[1];
-
- s->ivec[3] = bo[0] >> 24;
- s->ivec[2] = bo[0] >> 16;
- s->ivec[1] = bo[0] >> 8;
- s->ivec[0] = bo[0];
-
+ ints2buf(bo, s->ivec);
return;
}
@@ -133,17 +133,13 @@
bfCBCdecrypt(uchar *buf, int n, BFstate *s)
{
int i;
- uchar *p;
- u32int b, bo[2], bi[2], xr[2];
+ u32int bo[2], bi[2], xr[2];
assert((n & 7) == 0);
- bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24);
- bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24);
-
+ buf2ints(s->ivec, bo);
for(i=0; i < n; i += 8, buf += 8) {
- bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
- bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
+ buf2ints(buf, bi);
xr[0] = bi[0];
xr[1] = bi[1];
@@ -153,39 +149,12 @@
bo[0] ^= bi[0];
bo[1] ^= bi[1];
- p = buf;
- b = bo[0];
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
+ ints2buf(bo, buf);
- b = bo[1];
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p++ = b;
- b >>= 8;
- *p = b;
-
bo[0] = xr[0];
bo[1] = xr[1];
}
-
- s->ivec[7] = bo[1] >> 24;
- s->ivec[6] = bo[1] >> 16;
- s->ivec[5] = bo[1] >> 8;
- s->ivec[4] = bo[1];
-
- s->ivec[3] = bo[0] >> 24;
- s->ivec[2] = bo[0] >> 16;
- s->ivec[1] = bo[0] >> 8;
- s->ivec[0] = bo[0];
-
+ ints2buf(bo, s->ivec);
return;
}
@@ -196,20 +165,9 @@
u32int b[2];
for(i=0; i < n; i += 8, buf += 8) {
- b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
- b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
-
+ buf2ints(buf, b);
bfencrypt(b, s);
-
- buf[7] = b[1] >> 24;
- buf[6] = b[1] >> 16;
- buf[5] = b[1] >> 8;
- buf[4] = b[1];
-
- buf[3] = b[0] >> 24;
- buf[2] = b[0] >> 16;
- buf[1] = b[0] >> 8;
- buf[0] = b[0];
+ ints2buf(b, buf);
}
return;
@@ -222,20 +180,9 @@
u32int b[2];
for(i=0; i < n; i += 8, buf += 8) {
- b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
- b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
-
+ buf2ints(buf, b);
bfdecrypt(b, s);
-
- buf[7] = b[1] >> 24;
- buf[6] = b[1] >> 16;
- buf[5] = b[1] >> 8;
- buf[4] = b[1];
-
- buf[3] = b[0] >> 24;
- buf[2] = b[0] >> 16;
- buf[1] = b[0] >> 8;
- buf[0] = b[0];
+ ints2buf(b, buf);
}
return;
@@ -575,5 +522,4 @@
0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL,
0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L,
};
-
--- /dev/null
+++ b/libsec/ccpoly.c
@@ -1,0 +1,91 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+static void
+ccpolyotk(Chachastate *cs, DigestState *ds)
+{
+ uchar otk[ChachaBsize];
+
+ memset(ds, 0, sizeof(*ds));
+ memset(otk, 0, 32);
+ chacha_setblock(cs, 0);
+ chacha_encrypt(otk, ChachaBsize, cs);
+ poly1305(nil, 0, otk, 32, nil, ds);
+}
+
+static void
+ccpolypad(uchar *buf, ulong nbuf, DigestState *ds)
+{
+ static uchar zeros[16] = {0};
+ ulong npad;
+
+ if(nbuf == 0)
+ return;
+ poly1305(buf, nbuf, nil, 0, nil, ds);
+ npad = nbuf % 16;
+ if(npad == 0)
+ return;
+ poly1305(zeros, 16 - npad, nil, 0, nil, ds);
+}
+
+static void
+ccpolylen(ulong n, uchar tag[16], DigestState *ds)
+{
+ uchar info[8];
+
+ info[0] = n;
+ info[1] = n>>8;
+ info[2] = n>>16;
+ info[3] = n>>24;
+ info[4] = 0;
+ info[5] = 0;
+ info[6] = 0;
+ info[7] = 0;
+ poly1305(info, 8, nil, 0, tag, ds);
+}
+
+void
+ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs)
+{
+ DigestState ds;
+
+ ccpolyotk(cs, &ds);
+ if(cs->ivwords == 2){
+ poly1305(aad, naad, nil, 0, nil, &ds);
+ ccpolylen(naad, nil, &ds);
+ chacha_encrypt(dat, ndat, cs);
+ poly1305(dat, ndat, nil, 0, nil, &ds);
+ ccpolylen(ndat, tag, &ds);
+ } else {
+ ccpolypad(aad, naad, &ds);
+ chacha_encrypt(dat, ndat, cs);
+ ccpolypad(dat, ndat, &ds);
+ ccpolylen(naad, nil, &ds);
+ ccpolylen(ndat, tag, &ds);
+ }
+}
+
+int
+ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs)
+{
+ DigestState ds;
+ uchar tmp[16];
+
+ ccpolyotk(cs, &ds);
+ if(cs->ivwords == 2){
+ poly1305(aad, naad, nil, 0, nil, &ds);
+ ccpolylen(naad, nil, &ds);
+ poly1305(dat, ndat, nil, 0, nil, &ds);
+ ccpolylen(ndat, tmp, &ds);
+ } else {
+ ccpolypad(aad, naad, &ds);
+ ccpolypad(dat, ndat, &ds);
+ ccpolylen(naad, nil, &ds);
+ ccpolylen(ndat, tmp, &ds);
+ }
+ if(tsmemcmp(tag, tmp, 16) != 0)
+ return -1;
+ chacha_encrypt(dat, ndat, cs);
+ return 0;
+}
--- /dev/null
+++ b/libsec/chacha.c
@@ -1,0 +1,187 @@
+/*
+Adapted from chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+
+modified for use in Plan 9 and Inferno (no algorithmic changes),
+and including the changes to block number and nonce defined in RFC7539
+*/
+
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+enum{
+ Blockwords= ChachaBsize/sizeof(u32int)
+};
+
+/* little-endian data order */
+#define GET4(p) ((((((p)[3]<<8) | (p)[2])<<8) | (p)[1])<<8 | (p)[0])
+#define PUT4(p, v) (((p)[0]=v), (v>>=8), ((p)[1]=v), (v>>=8), ((p)[2]=v), (v>>=8), ((p)[3]=v))
+
+#define ROTATE(v,c) ((u32int)((v) << (c)) | ((v) >> (32 - (c))))
+
+#define QUARTERROUND(ia,ib,ic,id) { \
+ u32int a, b, c, d, t;\
+ a = x[ia]; b = x[ib]; c = x[ic]; d = x[id]; \
+ a += b; t = d^a; d = ROTATE(t,16); \
+ c += d; t = b^c; b = ROTATE(t,12); \
+ a += b; t = d^a; d = ROTATE(t, 8); \
+ c += d; t = b^c; b = ROTATE(t, 7); \
+ x[ia] = a; x[ib] = b; x[ic] = c; x[id] = d; \
+}
+
+#define ENCRYPT(s, x, y, d) {\
+ u32int v; \
+ uchar *sp, *dp; \
+ sp = (s); \
+ v = GET4(sp); \
+ v ^= (x)+(y); \
+ dp = (d); \
+ PUT4(dp, v); \
+}
+
+static uchar sigma[16] = "expand 32-byte k";
+static uchar tau[16] = "expand 16-byte k";
+
+static void
+load(u32int *d, uchar *s, int nw)
+{
+ int i;
+
+ for(i = 0; i < nw; i++, s+=4)
+ d[i] = GET4(s);
+}
+
+void
+setupChachastate(Chachastate *s, uchar *key, ulong keylen, uchar *iv, ulong ivlen, int rounds)
+{
+ if(keylen != 256/8 && keylen != 128/8)
+ sysfatal("invalid chacha key length");
+ if(ivlen != 96/8 && ivlen != 64/8)
+ sysfatal("invalid chacha iv length");
+ if(rounds == 0)
+ rounds = 20;
+ s->rounds = rounds;
+ if(keylen == 256/8) { /* recommended */
+ load(&s->input[0], sigma, 4);
+ load(&s->input[4], key, 8);
+ }else{
+ load(&s->input[0], tau, 4);
+ load(&s->input[4], key, 4);
+ load(&s->input[8], key, 4);
+ }
+ s->ivwords = ivlen/sizeof(u32int);
+ s->input[12] = 0;
+ s->input[13] = 0;
+ if(iv == nil){
+ s->input[14] = 0;
+ s->input[15] = 0;
+ }else
+ chacha_setiv(s, iv);
+}
+
+void
+chacha_setiv(Chachastate *s, uchar *iv)
+{
+ load(&s->input[16 - s->ivwords], iv, s->ivwords);
+}
+
+void
+chacha_setblock(Chachastate *s, u64int blockno)
+{
+ s->input[12] = blockno;
+ if(s->ivwords == 2)
+ s->input[13] = blockno>>32;
+}
+
+static void
+encryptblock(Chachastate *s, uchar *src, uchar *dst)
+{
+ u32int x[Blockwords];
+ int i, rounds;
+
+ rounds = s->rounds;
+ x[0] = s->input[0];
+ x[1] = s->input[1];
+ x[2] = s->input[2];
+ x[3] = s->input[3];
+ x[4] = s->input[4];
+ x[5] = s->input[5];
+ x[6] = s->input[6];
+ x[7] = s->input[7];
+ x[8] = s->input[8];
+ x[9] = s->input[9];
+ x[10] = s->input[10];
+ x[11] = s->input[11];
+ x[12] = s->input[12];
+ x[13] = s->input[13];
+ x[14] = s->input[14];
+ x[15] = s->input[15];
+
+ for(i = rounds; i > 0; i -= 2) {
+ QUARTERROUND(0, 4, 8,12)
+ QUARTERROUND(1, 5, 9,13)
+ QUARTERROUND(2, 6,10,14)
+ QUARTERROUND(3, 7,11,15)
+
+ QUARTERROUND(0, 5,10,15)
+ QUARTERROUND(1, 6,11,12)
+ QUARTERROUND(2, 7, 8,13)
+ QUARTERROUND(3, 4, 9,14)
+ }
+
+#ifdef FULL_UNROLL
+ ENCRYPT(src+0*4, x[0], s->input[0], dst+0*4);
+ ENCRYPT(src+1*4, x[1], s->input[1], dst+1*4);
+ ENCRYPT(src+2*4, x[2], s->input[2], dst+2*4);
+ ENCRYPT(src+3*4, x[3], s->input[3], dst+3*4);
+ ENCRYPT(src+4*4, x[4], s->input[4], dst+4*4);
+ ENCRYPT(src+5*4, x[5], s->input[5], dst+5*4);
+ ENCRYPT(src+6*4, x[6], s->input[6], dst+6*4);
+ ENCRYPT(src+7*4, x[7], s->input[7], dst+7*4);
+ ENCRYPT(src+8*4, x[8], s->input[8], dst+8*4);
+ ENCRYPT(src+9*4, x[9], s->input[9], dst+9*4);
+ ENCRYPT(src+10*4, x[10], s->input[10], dst+10*4);
+ ENCRYPT(src+11*4, x[11], s->input[11], dst+11*4);
+ ENCRYPT(src+12*4, x[12], s->input[12], dst+12*4);
+ ENCRYPT(src+13*4, x[13], s->input[13], dst+13*4);
+ ENCRYPT(src+14*4, x[14], s->input[14], dst+14*4);
+ ENCRYPT(src+15*4, x[15], s->input[15], dst+15*4);
+#else
+ for(i=0; i<nelem(x); i+=4){
+ ENCRYPT(src, x[i], s->input[i], dst);
+ ENCRYPT(src+4, x[i+1], s->input[i+1], dst+4);
+ ENCRYPT(src+8, x[i+2], s->input[i+2], dst+8);
+ ENCRYPT(src+12, x[i+3], s->input[i+3], dst+12);
+ src += 16;
+ dst += 16;
+ }
+#endif
+
+ if(++s->input[12] == 0 && s->ivwords == 2)
+ s->input[13]++;
+}
+
+void
+chacha_encrypt2(uchar *src, uchar *dst, ulong bytes, Chachastate *s)
+{
+ uchar tmp[ChachaBsize];
+
+ for(; bytes >= ChachaBsize; bytes -= ChachaBsize){
+ encryptblock(s, src, dst);
+ src += ChachaBsize;
+ dst += ChachaBsize;
+ }
+ if(bytes > 0){
+ memmove(tmp, src, bytes);
+ encryptblock(s, tmp, tmp);
+ memmove(dst, tmp, bytes);
+ }
+}
+
+void
+chacha_encrypt(uchar *buf, ulong bytes, Chachastate *s)
+{
+ chacha_encrypt2(buf, buf, bytes, s);
+}
--- /dev/null
+++ b/libsec/curve25519.c
@@ -1,0 +1,571 @@
+/* Copyright 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * curve25519: Curve25519 elliptic curve, public key function
+ *
+ * http://code.google.com/p/curve25519-donna/
+ *
+ * Adam Langley <agl@imperialviolet.org>
+ *
+ * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * More information about curve25519 can be found here
+ * http://cr.yp.to/ecdh.html
+ *
+ * djb's sample implementation of curve25519 is written in a special assembly
+ * language called qhasm and uses the floating point registers.
+ *
+ * This is, almost, a clean room reimplementation from the curve25519 paper. It
+ * uses many of the tricks described therein. Only the crecip function is taken
+ * from the sample implementation.
+ */
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+typedef vlong felem;
+
+/* Sum two numbers: output += in */
+static void fsum(felem *output, felem *in) {
+ unsigned i;
+ for (i = 0; i < 10; i += 2) {
+ output[0+i] = (output[0+i] + in[0+i]);
+ output[1+i] = (output[1+i] + in[1+i]);
+ }
+}
+
+/* Find the difference of two numbers: output = in - output
+ * (note the order of the arguments!)
+ */
+static void fdifference(felem *output, felem *in) {
+ unsigned i;
+ for (i = 0; i < 10; ++i) {
+ output[i] = (in[i] - output[i]);
+ }
+}
+
+/* Multiply a number my a scalar: output = in * scalar */
+static void fscalar_product(felem *output, felem *in, felem scalar) {
+ unsigned i;
+ for (i = 0; i < 10; ++i) {
+ output[i] = in[i] * scalar;
+ }
+}
+
+/* Multiply two numbers: output = in2 * in
+ *
+ * output must be distinct to both inputs. The inputs are reduced coefficient
+ * form, the output is not.
+ */
+static void fproduct(felem *output, felem *in2, felem *in) {
+ output[0] = in2[0] * in[0];
+ output[1] = in2[0] * in[1] +
+ in2[1] * in[0];
+ output[2] = 2 * in2[1] * in[1] +
+ in2[0] * in[2] +
+ in2[2] * in[0];
+ output[3] = in2[1] * in[2] +
+ in2[2] * in[1] +
+ in2[0] * in[3] +
+ in2[3] * in[0];
+ output[4] = in2[2] * in[2] +
+ 2 * (in2[1] * in[3] +
+ in2[3] * in[1]) +
+ in2[0] * in[4] +
+ in2[4] * in[0];
+ output[5] = in2[2] * in[3] +
+ in2[3] * in[2] +
+ in2[1] * in[4] +
+ in2[4] * in[1] +
+ in2[0] * in[5] +
+ in2[5] * in[0];
+ output[6] = 2 * (in2[3] * in[3] +
+ in2[1] * in[5] +
+ in2[5] * in[1]) +
+ in2[2] * in[4] +
+ in2[4] * in[2] +
+ in2[0] * in[6] +
+ in2[6] * in[0];
+ output[7] = in2[3] * in[4] +
+ in2[4] * in[3] +
+ in2[2] * in[5] +
+ in2[5] * in[2] +
+ in2[1] * in[6] +
+ in2[6] * in[1] +
+ in2[0] * in[7] +
+ in2[7] * in[0];
+ output[8] = in2[4] * in[4] +
+ 2 * (in2[3] * in[5] +
+ in2[5] * in[3] +
+ in2[1] * in[7] +
+ in2[7] * in[1]) +
+ in2[2] * in[6] +
+ in2[6] * in[2] +
+ in2[0] * in[8] +
+ in2[8] * in[0];
+ output[9] = in2[4] * in[5] +
+ in2[5] * in[4] +
+ in2[3] * in[6] +
+ in2[6] * in[3] +
+ in2[2] * in[7] +
+ in2[7] * in[2] +
+ in2[1] * in[8] +
+ in2[8] * in[1] +
+ in2[0] * in[9] +
+ in2[9] * in[0];
+ output[10] = 2 * (in2[5] * in[5] +
+ in2[3] * in[7] +
+ in2[7] * in[3] +
+ in2[1] * in[9] +
+ in2[9] * in[1]) +
+ in2[4] * in[6] +
+ in2[6] * in[4] +
+ in2[2] * in[8] +
+ in2[8] * in[2];
+ output[11] = in2[5] * in[6] +
+ in2[6] * in[5] +
+ in2[4] * in[7] +
+ in2[7] * in[4] +
+ in2[3] * in[8] +
+ in2[8] * in[3] +
+ in2[2] * in[9] +
+ in2[9] * in[2];
+ output[12] = in2[6] * in[6] +
+ 2 * (in2[5] * in[7] +
+ in2[7] * in[5] +
+ in2[3] * in[9] +
+ in2[9] * in[3]) +
+ in2[4] * in[8] +
+ in2[8] * in[4];
+ output[13] = in2[6] * in[7] +
+ in2[7] * in[6] +
+ in2[5] * in[8] +
+ in2[8] * in[5] +
+ in2[4] * in[9] +
+ in2[9] * in[4];
+ output[14] = 2 * (in2[7] * in[7] +
+ in2[5] * in[9] +
+ in2[9] * in[5]) +
+ in2[6] * in[8] +
+ in2[8] * in[6];
+ output[15] = in2[7] * in[8] +
+ in2[8] * in[7] +
+ in2[6] * in[9] +
+ in2[9] * in[6];
+ output[16] = in2[8] * in[8] +
+ 2 * (in2[7] * in[9] +
+ in2[9] * in[7]);
+ output[17] = in2[8] * in[9] +
+ in2[9] * in[8];
+ output[18] = 2 * in2[9] * in[9];
+}
+
+/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
+static void freduce_degree(felem *output) {
+ output[8] += 19 * output[18];
+ output[7] += 19 * output[17];
+ output[6] += 19 * output[16];
+ output[5] += 19 * output[15];
+ output[4] += 19 * output[14];
+ output[3] += 19 * output[13];
+ output[2] += 19 * output[12];
+ output[1] += 19 * output[11];
+ output[0] += 19 * output[10];
+}
+
+/* Reduce all coefficients of the short form input to be -2**25 <= x <= 2**25
+ */
+static void freduce_coefficients(felem *output) {
+ unsigned i;
+ do {
+ output[10] = 0;
+
+ for (i = 0; i < 10; i += 2) {
+ felem over = output[i] / 0x2000000l;
+ felem over2 = (over + ((over >> 63) * 2) + 1) / 2;
+ output[i+1] += over2;
+ output[i] -= over2 * 0x4000000l;
+
+ over = output[i+1] / 0x2000000;
+ output[i+2] += over;
+ output[i+1] -= over * 0x2000000;
+ }
+ output[0] += 19 * output[10];
+ } while (output[10]);
+}
+
+/* A helpful wrapper around fproduct: output = in * in2.
+ *
+ * output must be distinct to both inputs. The output is reduced degree and
+ * reduced coefficient.
+ */
+static void
+fmul(felem *output, felem *in, felem *in2) {
+ felem t[19];
+ fproduct(t, in, in2);
+ freduce_degree(t);
+ freduce_coefficients(t);
+ memcpy(output, t, sizeof(felem) * 10);
+}
+
+static void fsquare_inner(felem *output, felem *in) {
+ felem tmp;
+ output[0] = in[0] * in[0];
+ output[1] = 2 * in[0] * in[1];
+ output[2] = 2 * (in[1] * in[1] +
+ in[0] * in[2]);
+ output[3] = 2 * (in[1] * in[2] +
+ in[0] * in[3]);
+ output[4] = in[2] * in[2] +
+ 4 * in[1] * in[3] +
+ 2 * in[0] * in[4];
+ output[5] = 2 * (in[2] * in[3] +
+ in[1] * in[4] +
+ in[0] * in[5]);
+ output[6] = 2 * (in[3] * in[3] +
+ in[2] * in[4] +
+ in[0] * in[6] +
+ 2 * in[1] * in[5]);
+ output[7] = 2 * (in[3] * in[4] +
+ in[2] * in[5] +
+ in[1] * in[6] +
+ in[0] * in[7]);
+ tmp = in[1] * in[7] + in[3] * in[5];
+ output[8] = in[4] * in[4] +
+ 2 * (in[2] * in[6] +
+ in[0] * in[8] +
+ 2 * tmp);
+ output[9] = 2 * (in[4] * in[5] +
+ in[3] * in[6] +
+ in[2] * in[7] +
+ in[1] * in[8] +
+ in[0] * in[9]);
+ tmp = in[3] * in[7] + in[1] * in[9];
+ output[10] = 2 * (in[5] * in[5] +
+ in[4] * in[6] +
+ in[2] * in[8] +
+ 2 * tmp);
+ output[11] = 2 * (in[5] * in[6] +
+ in[4] * in[7] +
+ in[3] * in[8] +
+ in[2] * in[9]);
+ output[12] = in[6] * in[6] +
+ 2 * (in[4] * in[8] +
+ 2 * (in[5] * in[7] +
+ in[3] * in[9]));
+ output[13] = 2 * (in[6] * in[7] +
+ in[5] * in[8] +
+ in[4] * in[9]);
+ output[14] = 2 * (in[7] * in[7] +
+ in[6] * in[8] +
+ 2 * in[5] * in[9]);
+ output[15] = 2 * (in[7] * in[8] +
+ in[6] * in[9]);
+ output[16] = in[8] * in[8] +
+ 4 * in[7] * in[9];
+ output[17] = 2 * in[8] * in[9];
+ output[18] = 2 * in[9] * in[9];
+}
+
+static void
+fsquare(felem *output, felem *in) {
+ felem t[19];
+ fsquare_inner(t, in);
+ freduce_degree(t);
+ freduce_coefficients(t);
+ memcpy(output, t, sizeof(felem) * 10);
+}
+
+/* Take a little-endian, 32-byte number and expand it into polynomial form */
+static void
+fexpand(felem *output, uchar *input) {
+#define F(n,start,shift,mask) \
+ output[n] = ((((felem) input[start + 0]) | \
+ ((felem) input[start + 1]) << 8 | \
+ ((felem) input[start + 2]) << 16 | \
+ ((felem) input[start + 3]) << 24) >> shift) & mask;
+ F(0, 0, 0, 0x3ffffff);
+ F(1, 3, 2, 0x1ffffff);
+ F(2, 6, 3, 0x3ffffff);
+ F(3, 9, 5, 0x1ffffff);
+ F(4, 12, 6, 0x3ffffff);
+ F(5, 16, 0, 0x1ffffff);
+ F(6, 19, 1, 0x3ffffff);
+ F(7, 22, 3, 0x1ffffff);
+ F(8, 25, 4, 0x3ffffff);
+ F(9, 28, 6, 0x1ffffff);
+#undef F
+}
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * little-endian, 32-byte array
+ */
+static void
+fcontract(uchar *output, felem *input) {
+ int i;
+
+ do {
+ for (i = 0; i < 9; ++i) {
+ if ((i & 1) == 1) {
+ while (input[i] < 0) {
+ input[i] += 0x2000000;
+ input[i + 1]--;
+ }
+ } else {
+ while (input[i] < 0) {
+ input[i] += 0x4000000;
+ input[i + 1]--;
+ }
+ }
+ }
+ while (input[9] < 0) {
+ input[9] += 0x2000000;
+ input[0] -= 19;
+ }
+ } while (input[0] < 0);
+
+ input[1] <<= 2;
+ input[2] <<= 3;
+ input[3] <<= 5;
+ input[4] <<= 6;
+ input[6] <<= 1;
+ input[7] <<= 3;
+ input[8] <<= 4;
+ input[9] <<= 6;
+#define F(i, s) \
+ output[s+0] |= input[i] & 0xff; \
+ output[s+1] = (input[i] >> 8) & 0xff; \
+ output[s+2] = (input[i] >> 16) & 0xff; \
+ output[s+3] = (input[i] >> 24) & 0xff;
+ output[0] = 0;
+ output[16] = 0;
+ F(0,0);
+ F(1,3);
+ F(2,6);
+ F(3,9);
+ F(4,12);
+ F(5,16);
+ F(6,19);
+ F(7,22);
+ F(8,25);
+ F(9,28);
+#undef F
+}
+
+/* Input: Q, Q', Q-Q'
+ * Output: 2Q, Q+Q'
+ *
+ * x2 z3: long form
+ * x3 z3: long form
+ * x z: short form, destroyed
+ * xprime zprime: short form, destroyed
+ * qmqp: short form, preserved
+ */
+static void fmonty(felem *x2, felem *z2, /* output 2Q */
+ felem *x3, felem *z3, /* output Q + Q' */
+ felem *x, felem *z, /* input Q */
+ felem *xprime, felem *zprime, /* input Q' */
+ felem *qmqp /* input Q - Q' */) {
+ felem origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
+ zzprime[19], zzzprime[19], xxxprime[19];
+
+ memcpy(origx, x, 10 * sizeof(felem));
+ fsum(x, z);
+ fdifference(z, origx); // does x - z
+
+ memcpy(origxprime, xprime, sizeof(felem) * 10);
+ fsum(xprime, zprime);
+ fdifference(zprime, origxprime);
+ fproduct(xxprime, xprime, z);
+ fproduct(zzprime, x, zprime);
+ freduce_degree(xxprime);
+ freduce_coefficients(xxprime);
+ freduce_degree(zzprime);
+ freduce_coefficients(zzprime);
+ memcpy(origxprime, xxprime, sizeof(felem) * 10);
+ fsum(xxprime, zzprime);
+ fdifference(zzprime, origxprime);
+ fsquare(xxxprime, xxprime);
+ fsquare(zzzprime, zzprime);
+ fproduct(zzprime, zzzprime, qmqp);
+ freduce_degree(zzprime);
+ freduce_coefficients(zzprime);
+ memcpy(x3, xxxprime, sizeof(felem) * 10);
+ memcpy(z3, zzprime, sizeof(felem) * 10);
+
+ fsquare(xx, x);
+ fsquare(zz, z);
+ fproduct(x2, xx, zz);
+ freduce_degree(x2);
+ freduce_coefficients(x2);
+ fdifference(zz, xx); // does zz = xx - zz
+ memset(zzz + 10, 0, sizeof(felem) * 9);
+ fscalar_product(zzz, zz, 121665);
+ freduce_degree(zzz);
+ freduce_coefficients(zzz);
+ fsum(zzz, xx);
+ fproduct(z2, zz, zzz);
+ freduce_degree(z2);
+ freduce_coefficients(z2);
+}
+
+/* Calculates nQ where Q is the x-coordinate of a point on the curve
+ *
+ * resultx/resultz: the x coordinate of the resulting curve point (short form)
+ * n: a little endian, 32-byte number
+ * q: a point of the curve (short form)
+ */
+static void
+cmult(felem *resultx, felem *resultz, uchar *n, felem *q) {
+ felem a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
+ felem *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
+ felem e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
+ felem *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
+
+ unsigned i, j;
+
+ memcpy(nqpqx, q, sizeof(felem) * 10);
+
+ for (i = 0; i < 32; ++i) {
+ uchar byte = n[31 - i];
+ for (j = 0; j < 8; ++j) {
+ if (byte & 0x80) {
+ fmonty(nqpqx2, nqpqz2,
+ nqx2, nqz2,
+ nqpqx, nqpqz,
+ nqx, nqz,
+ q);
+ } else {
+ fmonty(nqx2, nqz2,
+ nqpqx2, nqpqz2,
+ nqx, nqz,
+ nqpqx, nqpqz,
+ q);
+ }
+
+ t = nqx;
+ nqx = nqx2;
+ nqx2 = t;
+ t = nqz;
+ nqz = nqz2;
+ nqz2 = t;
+ t = nqpqx;
+ nqpqx = nqpqx2;
+ nqpqx2 = t;
+ t = nqpqz;
+ nqpqz = nqpqz2;
+ nqpqz2 = t;
+
+ byte <<= 1;
+ }
+ }
+
+ memcpy(resultx, nqx, sizeof(felem) * 10);
+ memcpy(resultz, nqz, sizeof(felem) * 10);
+}
+
+// -----------------------------------------------------------------------------
+// Shamelessly copied from djb's code
+// -----------------------------------------------------------------------------
+static void
+crecip(felem *out, felem *z) {
+ felem z2[10];
+ felem z9[10];
+ felem z11[10];
+ felem z2_5_0[10];
+ felem z2_10_0[10];
+ felem z2_20_0[10];
+ felem z2_50_0[10];
+ felem z2_100_0[10];
+ felem t0[10];
+ felem t1[10];
+ int i;
+
+ /* 2 */ fsquare(z2,z);
+ /* 4 */ fsquare(t1,z2);
+ /* 8 */ fsquare(t0,t1);
+ /* 9 */ fmul(z9,t0,z);
+ /* 11 */ fmul(z11,z9,z2);
+ /* 22 */ fsquare(t0,z11);
+ /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
+
+ /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
+ /* 2^7 - 2^2 */ fsquare(t1,t0);
+ /* 2^8 - 2^3 */ fsquare(t0,t1);
+ /* 2^9 - 2^4 */ fsquare(t1,t0);
+ /* 2^10 - 2^5 */ fsquare(t0,t1);
+ /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
+
+ /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
+ /* 2^12 - 2^2 */ fsquare(t1,t0);
+ /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
+
+ /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
+ /* 2^22 - 2^2 */ fsquare(t1,t0);
+ /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
+
+ /* 2^41 - 2^1 */ fsquare(t1,t0);
+ /* 2^42 - 2^2 */ fsquare(t0,t1);
+ /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+ /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
+
+ /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
+ /* 2^52 - 2^2 */ fsquare(t1,t0);
+ /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
+
+ /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
+ /* 2^102 - 2^2 */ fsquare(t0,t1);
+ /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+ /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
+
+ /* 2^201 - 2^1 */ fsquare(t0,t1);
+ /* 2^202 - 2^2 */ fsquare(t1,t0);
+ /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
+
+ /* 2^251 - 2^1 */ fsquare(t1,t0);
+ /* 2^252 - 2^2 */ fsquare(t0,t1);
+ /* 2^253 - 2^3 */ fsquare(t1,t0);
+ /* 2^254 - 2^4 */ fsquare(t0,t1);
+ /* 2^255 - 2^5 */ fsquare(t1,t0);
+ /* 2^255 - 21 */ fmul(out,t1,z11);
+}
+
+void
+curve25519(uchar mypublic[32], uchar secret[32], uchar basepoint[32]) {
+ felem bp[10], x[10], z[10], zmone[10];
+ fexpand(bp, basepoint);
+ cmult(x, z, secret, bp);
+ crecip(zmone, z);
+ fmul(z, x, zmone);
+ fcontract(mypublic, z);
+}
--- /dev/null
+++ b/libsec/curve25519_dh.c
@@ -1,0 +1,34 @@
+#include "os.h"
+#include <mp.h>
+#include <libsec.h>
+
+static uchar nine[32] = {9};
+
+void
+curve25519_dh_new(uchar x[32], uchar y[32])
+{
+ uchar b;
+
+ /* new public/private key pair */
+ genrandom(x, 32);
+ b = x[31];
+ x[0] &= ~7; /* clear bit 0,1,2 */
+ x[31] = 0x40 | (b & 0x7f); /* set bit 254, clear bit 255 */
+ curve25519(y, x, nine);
+
+ /* bit 255 is always 0, so make it random */
+ y[31] |= b & 0x80;
+}
+
+void
+curve25519_dh_finish(uchar x[32], uchar y[32], uchar z[32])
+{
+ /* remove the random bit */
+ y[31] &= 0x7f;
+
+ /* calculate dhx key */
+ curve25519(z, x, y);
+
+ memset(x, 0, 32);
+ memset(y, 0, 32);
+}
--- a/libsec/decodepem.c
+++ b/libsec/decodepem.c
@@ -6,12 +6,14 @@
#define STRLEN(s) (sizeof(s)-1)
uchar*
-decodepem(char *s, char *type, int *len)
+decodePEM(char *s, char *type, int *len, char **new_s)
{
uchar *d;
char *t, *e, *tt;
int n;
+ *len = 0;
+
/*
* find the correct section of the file, stripping garbage at the beginning and end.
* the data is delimited by -----BEGIN <type>-----\n and -----END <type>-----\n
@@ -42,6 +44,8 @@
return nil;
}
+ if(new_s)
+ *new_s = tt+1;
n = ((tt - t) * 6 + 7) / 8;
d = malloc(n);
if(d == nil){
@@ -56,4 +60,30 @@
}
*len = n;
return d;
+}
+
+PEMChain*
+decodepemchain(char *s, char *type)
+{
+ PEMChain *first = nil, *last = nil, *chp;
+ uchar *d;
+ char *e;
+ int n;
+
+ e = strchr(s, '\0');
+ while (s < e) {
+ d = decodePEM(s, type, &n, &s);
+ if(d == nil)
+ break;
+ chp = malloc(sizeof(PEMChain));
+ chp->next = nil;
+ chp->pem = d;
+ chp->pemlen = n;
+ if (first == nil)
+ first = chp;
+ else
+ last->next = chp;
+ last = chp;
+ }
+ return first;
}
--- /dev/null
+++ b/libsec/dh.c
@@ -1,0 +1,74 @@
+#include "os.h"
+#include <mp.h>
+#include <libsec.h>
+
+mpint*
+dh_new(DHstate *dh, mpint *p, mpint *q, mpint *g)
+{
+ mpint *pm1;
+ int n;
+
+ memset(dh, 0, sizeof(*dh));
+ if(mpcmp(g, mpone) <= 0)
+ return nil;
+
+ n = mpsignif(p);
+ pm1 = mpnew(n);
+ mpsub(p, mpone, pm1);
+ dh->p = mpcopy(p);
+ dh->g = mpcopy(g);
+ dh->q = mpcopy(q != nil ? q : pm1);
+ dh->x = mpnew(mpsignif(dh->q));
+ dh->y = mpnew(n);
+ for(;;){
+ mpnrand(dh->q, genrandom, dh->x);
+ mpexp(dh->g, dh->x, dh->p, dh->y);
+ if(mpcmp(dh->y, mpone) > 0 && mpcmp(dh->y, pm1) < 0)
+ break;
+ }
+ mpfree(pm1);
+
+ return dh->y;
+}
+
+mpint*
+dh_finish(DHstate *dh, mpint *y)
+{
+ mpint *k = nil;
+
+ if(y == nil || dh->x == nil || dh->p == nil || dh->q == nil)
+ goto Out;
+
+ /* y > 1 */
+ if(mpcmp(y, mpone) <= 0)
+ goto Out;
+
+ k = mpnew(mpsignif(dh->p));
+
+ /* y < p-1 */
+ mpsub(dh->p, mpone, k);
+ if(mpcmp(y, k) >= 0){
+Bad:
+ mpfree(k);
+ k = nil;
+ goto Out;
+ }
+
+ /* y**q % p == 1 if q < p-1 */
+ if(mpcmp(dh->q, k) < 0){
+ mpexp(y, dh->q, dh->p, k);
+ if(mpcmp(k, mpone) != 0)
+ goto Bad;
+ }
+
+ mpexp(y, dh->x, dh->p, k);
+
+Out:
+ mpfree(dh->p);
+ mpfree(dh->q);
+ mpfree(dh->g);
+ mpfree(dh->x);
+ mpfree(dh->y);
+ memset(dh, 0, sizeof(*dh));
+ return k;
+}
--- a/libsec/dsaalloc.c
+++ b/libsec/dsaalloc.c
@@ -22,6 +22,7 @@
mpfree(dsa->q);
mpfree(dsa->alpha);
mpfree(dsa->key);
+ free(dsa);
}
@@ -46,6 +47,7 @@
mpfree(dsa->pub.alpha);
mpfree(dsa->pub.key);
mpfree(dsa->secret);
+ free(dsa);
}
DSAsig*
@@ -66,4 +68,5 @@
return;
mpfree(dsa->r);
mpfree(dsa->s);
+ free(dsa);
}
--- a/libsec/dsagen.c
+++ b/libsec/dsagen.c
@@ -32,9 +32,6 @@
// find a generator alpha of the multiplicative
// group Z*p, i.e., of order n = p-1. We use the
// fact that q divides p-1 to reduce the exponent.
- //
- // This isn't very efficient. If anyone has a better
- // idea, mail presotto@closedmind.org
exp = mpnew(0);
g = mpnew(0);
r = mpnew(0);
--- a/libsec/dsaprimes.c
+++ b/libsec/dsaprimes.c
@@ -12,7 +12,7 @@
static void
Hrand(uchar *s)
{
- ulong *u = (ulong*)s;
+ u32int *u = (u32int*)s;
*u++ = fastrand();
*u++ = fastrand();
*u++ = fastrand();
--- a/libsec/dsasign.c
+++ b/libsec/dsasign.c
@@ -21,16 +21,16 @@
// find a k that has an inverse mod q
while(1){
mprand(qlen, genrandom, k);
- if((mpcmp(mpone, k) > 0) || (mpcmp(k, qm1) >= 0))
+ if((mpcmp(mpone, k) > 0) || (mpcmp(k, pub->q) >= 0))
continue;
mpextendedgcd(k, q, r, kinv, s);
if(mpcmp(r, mpone) != 0)
- continue;
+ sysfatal("dsasign: pub->q not prime");
break;
}
// make kinv positive
- mpmod(kinv, qm1, kinv);
+ mpmod(kinv, pub->q, kinv);
// r = ((alpha**k) mod p) mod q
mpexp(alpha, k, p, r);
--- a/libsec/dsaverify.c
+++ b/libsec/dsaverify.c
@@ -8,9 +8,9 @@
int rv = -1;
mpint *u1, *u2, *v, *sinv;
- if(sig->r->sign < 0 || mpcmp(sig->r, pub->q) >= 0)
+ if(mpcmp(sig->r, mpone) < 0 || mpcmp(sig->r, pub->q) >= 0)
return rv;
- if(sig->s->sign < 0 || mpcmp(sig->s, pub->q) >= 0)
+ if(mpcmp(sig->s, mpone) < 0 || mpcmp(sig->s, pub->q) >= 0)
return rv;
u1 = mpnew(0);
u2 = mpnew(0);
--- /dev/null
+++ b/libsec/ecc.c
@@ -1,0 +1,620 @@
+#include "os.h"
+#include <mp.h>
+#include <libsec.h>
+#include <ctype.h>
+
+void
+ecassign(ECdomain *dom, ECpoint *a, ECpoint *b)
+{
+ USED(dom);
+ b->inf = a->inf;
+ mpassign(a->x, b->x);
+ mpassign(a->y, b->y);
+}
+
+void
+ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s)
+{
+ mpint *l, *k, *sx, *sy;
+
+ if(a->inf && b->inf){
+ s->inf = 1;
+ return;
+ }
+ if(a->inf){
+ ecassign(dom, b, s);
+ return;
+ }
+ if(b->inf){
+ ecassign(dom, a, s);
+ return;
+ }
+ if(mpcmp(a->x, b->x) == 0 && (mpcmp(a->y, mpzero) == 0 || mpcmp(a->y, b->y) != 0)){
+ s->inf = 1;
+ return;
+ }
+ l = mpnew(0);
+ k = mpnew(0);
+ sx = mpnew(0);
+ sy = mpnew(0);
+ if(mpcmp(a->x, b->x) == 0 && mpcmp(a->y, b->y) == 0){
+ mpadd(mpone, mptwo, k);
+ mpmul(a->x, a->x, l);
+ mpmul(l, k, l);
+ mpadd(l, dom->a, l);
+ mpleft(a->y, 1, k);
+ mpmod(k, dom->p, k);
+ mpinvert(k, dom->p, k);
+ mpmul(k, l, l);
+ mpmod(l, dom->p, l);
+
+ mpleft(a->x, 1, k);
+ mpmul(l, l, sx);
+ mpsub(sx, k, sx);
+ mpmod(sx, dom->p, sx);
+
+ mpsub(a->x, sx, sy);
+ mpmul(l, sy, sy);
+ mpsub(sy, a->y, sy);
+ mpmod(sy, dom->p, sy);
+ mpassign(sx, s->x);
+ mpassign(sy, s->y);
+ mpfree(sx);
+ mpfree(sy);
+ mpfree(l);
+ mpfree(k);
+ return;
+ }
+ mpsub(b->y, a->y, l);
+ mpmod(l, dom->p, l);
+ mpsub(b->x, a->x, k);
+ mpmod(k, dom->p, k);
+ mpinvert(k, dom->p, k);
+ mpmul(k, l, l);
+ mpmod(l, dom->p, l);
+
+ mpmul(l, l, sx);
+ mpsub(sx, a->x, sx);
+ mpsub(sx, b->x, sx);
+ mpmod(sx, dom->p, sx);
+
+ mpsub(a->x, sx, sy);
+ mpmul(sy, l, sy);
+ mpsub(sy, a->y, sy);
+ mpmod(sy, dom->p, sy);
+
+ mpassign(sx, s->x);
+ mpassign(sy, s->y);
+ mpfree(sx);
+ mpfree(sy);
+ mpfree(l);
+ mpfree(k);
+}
+
+void
+ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
+{
+ ECpoint ns, na;
+ mpint *l;
+
+ if(a->inf || mpcmp(k, mpzero) == 0){
+ s->inf = 1;
+ return;
+ }
+ ns.inf = 1;
+ ns.x = mpnew(0);
+ ns.y = mpnew(0);
+ na.x = mpnew(0);
+ na.y = mpnew(0);
+ ecassign(dom, a, &na);
+ l = mpcopy(k);
+ l->sign = 1;
+ while(mpcmp(l, mpzero) != 0){
+ if(l->p[0] & 1)
+ ecadd(dom, &na, &ns, &ns);
+ ecadd(dom, &na, &na, &na);
+ mpright(l, 1, l);
+ }
+ if(k->sign < 0){
+ ns.y->sign = -1;
+ mpmod(ns.y, dom->p, ns.y);
+ }
+ ecassign(dom, &ns, s);
+ mpfree(ns.x);
+ mpfree(ns.y);
+ mpfree(na.x);
+ mpfree(na.y);
+ mpfree(l);
+}
+
+int
+ecverify(ECdomain *dom, ECpoint *a)
+{
+ mpint *p, *q;
+ int r;
+
+ if(a->inf)
+ return 1;
+
+ p = mpnew(0);
+ q = mpnew(0);
+ mpmul(a->y, a->y, p);
+ mpmod(p, dom->p, p);
+ mpmul(a->x, a->x, q);
+ mpadd(q, dom->a, q);
+ mpmul(a->x, q, q);
+ mpadd(q, dom->b, q);
+ mpmod(q, dom->p, q);
+ r = mpcmp(p, q);
+ mpfree(p);
+ mpfree(q);
+ return r == 0;
+}
+
+int
+ecpubverify(ECdomain *dom, ECpub *a)
+{
+ ECpoint p;
+ int r;
+
+ if(a->inf)
+ return 0;
+ if(!ecverify(dom, a))
+ return 0;
+ p.x = mpnew(0);
+ p.y = mpnew(0);
+ ecmul(dom, a, dom->n, &p);
+ r = p.inf;
+ mpfree(p.x);
+ mpfree(p.y);
+ return r;
+}
+
+static void
+fixnibble(uchar *a)
+{
+ if(*a >= 'a')
+ *a -= 'a'-10;
+ else if(*a >= 'A')
+ *a -= 'A'-10;
+ else
+ *a -= '0';
+}
+
+static int
+octet(char **s)
+{
+ uchar c, d;
+
+ c = *(*s)++;
+ if(!isxdigit(c))
+ return -1;
+ d = *(*s)++;
+ if(!isxdigit(d))
+ return -1;
+ fixnibble(&c);
+ fixnibble(&d);
+ return (c << 4) | d;
+}
+
+static mpint*
+halfpt(ECdomain *dom, char *s, char **rptr, mpint *out)
+{
+ char *buf, *r;
+ int n;
+ mpint *ret;
+
+ n = ((mpsignif(dom->p)+7)/8)*2;
+ if(strlen(s) < n)
+ return 0;
+ buf = malloc(n+1);
+ buf[n] = 0;
+ memcpy(buf, s, n);
+ ret = strtomp(buf, &r, 16, out);
+ *rptr = s + (r - buf);
+ free(buf);
+ return ret;
+}
+
+static int
+mpleg(mpint *a, mpint *b)
+{
+ int r, k;
+ mpint *m, *n, *t;
+
+ r = 1;
+ m = mpcopy(a);
+ n = mpcopy(b);
+ for(;;){
+ if(mpcmp(m, n) > 0)
+ mpmod(m, n, m);
+ if(mpcmp(m, mpzero) == 0){
+ r = 0;
+ break;
+ }
+ if(mpcmp(m, mpone) == 0)
+ break;
+ k = mplowbits0(m);
+ if(k > 0){
+ if(k & 1)
+ switch(n->p[0] & 15){
+ case 3: case 5: case 11: case 13:
+ r = -r;
+ }
+ mpright(m, k, m);
+ }
+ if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3)
+ r = -r;
+ t = m;
+ m = n;
+ n = t;
+ }
+ mpfree(m);
+ mpfree(n);
+ return r;
+}
+
+static int
+mpsqrt(mpint *n, mpint *p, mpint *r)
+{
+ mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N;
+
+ if(mpleg(n, p) == -1)
+ return 0;
+ a = mpnew(0);
+ t = mpnew(0);
+ s = mpnew(0);
+ N = mpnew(0);
+ xp = mpnew(0);
+ xq = mpnew(0);
+ yp = mpnew(0);
+ yq = mpnew(0);
+ zp = mpnew(0);
+ zq = mpnew(0);
+ for(;;){
+ for(;;){
+ mprand(mpsignif(p), genrandom, a);
+ if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0)
+ break;
+ }
+ mpmul(a, a, t);
+ mpsub(t, n, t);
+ mpmod(t, p, t);
+ if(mpleg(t, p) == -1)
+ break;
+ }
+ mpadd(p, mpone, N);
+ mpright(N, 1, N);
+ mpmul(a, a, t);
+ mpsub(t, n, t);
+ mpassign(a, xp);
+ uitomp(1, xq);
+ uitomp(1, yp);
+ uitomp(0, yq);
+ while(mpcmp(N, mpzero) != 0){
+ if(N->p[0] & 1){
+ mpmul(xp, yp, zp);
+ mpmul(xq, yq, zq);
+ mpmul(zq, t, zq);
+ mpadd(zp, zq, zp);
+ mpmod(zp, p, zp);
+ mpmul(xp, yq, zq);
+ mpmul(xq, yp, s);
+ mpadd(zq, s, zq);
+ mpmod(zq, p, yq);
+ mpassign(zp, yp);
+ }
+ mpmul(xp, xp, zp);
+ mpmul(xq, xq, zq);
+ mpmul(zq, t, zq);
+ mpadd(zp, zq, zp);
+ mpmod(zp, p, zp);
+ mpmul(xp, xq, zq);
+ mpadd(zq, zq, zq);
+ mpmod(zq, p, xq);
+ mpassign(zp, xp);
+ mpright(N, 1, N);
+ }
+ if(mpcmp(yq, mpzero) != 0)
+ abort();
+ mpassign(yp, r);
+ mpfree(a);
+ mpfree(t);
+ mpfree(s);
+ mpfree(N);
+ mpfree(xp);
+ mpfree(xq);
+ mpfree(yp);
+ mpfree(yq);
+ mpfree(zp);
+ mpfree(zq);
+ return 1;
+}
+
+ECpoint*
+strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
+{
+ int allocd, o;
+ mpint *r;
+
+ allocd = 0;
+ if(ret == nil){
+ allocd = 1;
+ ret = mallocz(sizeof(*ret), 1);
+ if(ret == nil)
+ return nil;
+ ret->x = mpnew(0);
+ ret->y = mpnew(0);
+ }
+ o = 0;
+ switch(octet(&s)){
+ case 0:
+ ret->inf = 1;
+ return ret;
+ case 3:
+ o = 1;
+ case 2:
+ if(halfpt(dom, s, &s, ret->x) == nil)
+ goto err;
+ r = mpnew(0);
+ mpmul(ret->x, ret->x, r);
+ mpadd(r, dom->a, r);
+ mpmul(r, ret->x, r);
+ mpadd(r, dom->b, r);
+ if(!mpsqrt(r, dom->p, r)){
+ mpfree(r);
+ goto err;
+ }
+ if((r->p[0] & 1) != o)
+ mpsub(dom->p, r, r);
+ mpassign(r, ret->y);
+ mpfree(r);
+ if(!ecverify(dom, ret))
+ goto err;
+ return ret;
+ case 4:
+ if(halfpt(dom, s, &s, ret->x) == nil)
+ goto err;
+ if(halfpt(dom, s, &s, ret->y) == nil)
+ goto err;
+ if(!ecverify(dom, ret))
+ goto err;
+ return ret;
+ }
+err:
+ if(rptr)
+ *rptr = s;
+ if(allocd){
+ mpfree(ret->x);
+ mpfree(ret->y);
+ free(ret);
+ }
+ return nil;
+}
+
+ECpriv*
+ecgen(ECdomain *dom, ECpriv *p)
+{
+ if(p == nil){
+ p = mallocz(sizeof(*p), 1);
+ if(p == nil)
+ return nil;
+ p->x = mpnew(0);
+ p->y = mpnew(0);
+ p->d = mpnew(0);
+ }
+ for(;;){
+ mprand(mpsignif(dom->n), genrandom, p->d);
+ if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
+ break;
+ }
+ ecmul(dom, &dom->G, p->d, (ECpoint*)p);
+ return p;
+}
+
+void
+ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
+{
+ ECpriv tmp;
+ mpint *E, *t;
+
+ tmp.x = mpnew(0);
+ tmp.y = mpnew(0);
+ tmp.d = mpnew(0);
+ E = betomp(dig, len, nil);
+ t = mpnew(0);
+ if(mpsignif(dom->n) < 8*len)
+ mpright(E, 8*len - mpsignif(dom->n), E);
+ for(;;){
+ ecgen(dom, &tmp);
+ mpmod(tmp.x, dom->n, r);
+ if(mpcmp(r, mpzero) == 0)
+ continue;
+ mpmul(r, priv->d, s);
+ mpadd(E, s, s);
+ mpinvert(tmp.d, dom->n, t);
+ mpmul(s, t, s);
+ mpmod(s, dom->n, s);
+ if(mpcmp(s, mpzero) != 0)
+ break;
+ }
+ mpfree(t);
+ mpfree(E);
+ mpfree(tmp.x);
+ mpfree(tmp.y);
+ mpfree(tmp.d);
+}
+
+int
+ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
+{
+ mpint *E, *t, *u1, *u2;
+ ECpoint R, S;
+ int ret;
+
+ if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0)
+ return 0;
+ E = betomp(dig, len, nil);
+ if(mpsignif(dom->n) < 8*len)
+ mpright(E, 8*len - mpsignif(dom->n), E);
+ t = mpnew(0);
+ u1 = mpnew(0);
+ u2 = mpnew(0);
+ R.x = mpnew(0);
+ R.y = mpnew(0);
+ S.x = mpnew(0);
+ S.y = mpnew(0);
+ mpinvert(s, dom->n, t);
+ mpmul(E, t, u1);
+ mpmod(u1, dom->n, u1);
+ mpmul(r, t, u2);
+ mpmod(u2, dom->n, u2);
+ ecmul(dom, &dom->G, u1, &R);
+ ecmul(dom, pub, u2, &S);
+ ecadd(dom, &R, &S, &R);
+ ret = 0;
+ if(!R.inf){
+ mpmod(R.x, dom->n, t);
+ ret = mpcmp(r, t) == 0;
+ }
+ mpfree(E);
+ mpfree(t);
+ mpfree(u1);
+ mpfree(u2);
+ mpfree(R.x);
+ mpfree(R.y);
+ mpfree(S.x);
+ mpfree(S.y);
+ return ret;
+}
+
+static char *code = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
+
+void
+base58enc(uchar *src, char *dst, int len)
+{
+ mpint *n, *r, *b;
+ char *sdst, t;
+
+ sdst = dst;
+ n = betomp(src, len, nil);
+ b = uitomp(58, nil);
+ r = mpnew(0);
+ while(mpcmp(n, mpzero) != 0){
+ mpdiv(n, b, n, r);
+ *dst++ = code[mptoui(r)];
+ }
+ for(; *src == 0; src++)
+ *dst++ = code[0];
+ dst--;
+ while(dst > sdst){
+ t = *sdst;
+ *sdst++ = *dst;
+ *dst-- = t;
+ }
+}
+
+int
+base58dec(char *src, uchar *dst, int len)
+{
+ mpint *n, *b, *r;
+ char *t;
+
+ n = mpnew(0);
+ r = mpnew(0);
+ b = uitomp(58, nil);
+ for(; *src; src++){
+ t = strchr(code, *src);
+ if(t == nil){
+ mpfree(n);
+ mpfree(r);
+ mpfree(b);
+ werrstr("invalid base58 char");
+ return -1;
+ }
+ uitomp(t - code, r);
+ mpmul(n, b, n);
+ mpadd(n, r, n);
+ }
+ mptober(n, dst, len);
+ mpfree(n);
+ mpfree(r);
+ mpfree(b);
+ return 0;
+}
+
+void
+ecdominit(ECdomain *dom, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h))
+{
+ memset(dom, 0, sizeof(*dom));
+ dom->p = mpnew(0);
+ dom->a = mpnew(0);
+ dom->b = mpnew(0);
+ dom->G.x = mpnew(0);
+ dom->G.y = mpnew(0);
+ dom->n = mpnew(0);
+ dom->h = mpnew(0);
+ if(init){
+ (*init)(dom->p, dom->a, dom->b, dom->G.x, dom->G.y, dom->n, dom->h);
+ dom->p = mpfield(dom->p);
+ }
+}
+
+void
+ecdomfree(ECdomain *dom)
+{
+ mpfree(dom->p);
+ mpfree(dom->a);
+ mpfree(dom->b);
+ mpfree(dom->G.x);
+ mpfree(dom->G.y);
+ mpfree(dom->n);
+ mpfree(dom->h);
+ memset(dom, 0, sizeof(*dom));
+}
+
+int
+ecencodepub(ECdomain *dom, ECpub *pub, uchar *data, int len)
+{
+ int n;
+
+ n = (mpsignif(dom->p)+7)/8;
+ if(len < 1 + 2*n)
+ return 0;
+ len = 1 + 2*n;
+ data[0] = 0x04;
+ mptober(pub->x, data+1, n);
+ mptober(pub->y, data+1+n, n);
+ return len;
+}
+
+ECpub*
+ecdecodepub(ECdomain *dom, uchar *data, int len)
+{
+ ECpub *pub;
+ int n;
+
+ n = (mpsignif(dom->p)+7)/8;
+ if(len != 1 + 2*n || data[0] != 0x04)
+ return nil;
+ pub = mallocz(sizeof(*pub), 1);
+ if(pub == nil)
+ return nil;
+ pub->x = betomp(data+1, n, nil);
+ pub->y = betomp(data+1+n, n, nil);
+ if(!ecpubverify(dom, pub)){
+ ecpubfree(pub);
+ pub = nil;
+ }
+ return pub;
+}
+
+void
+ecpubfree(ECpub *p)
+{
+ if(p == nil)
+ return;
+ mpfree(p->x);
+ mpfree(p->y);
+ free(p);
+}
--- a/libsec/egalloc.c
+++ b/libsec/egalloc.c
@@ -21,6 +21,7 @@
mpfree(eg->p);
mpfree(eg->alpha);
mpfree(eg->key);
+ free(eg);
}
@@ -44,6 +45,7 @@
mpfree(eg->pub.alpha);
mpfree(eg->pub.key);
mpfree(eg->secret);
+ free(eg);
}
EGsig*
@@ -64,4 +66,5 @@
return;
mpfree(eg->r);
mpfree(eg->s);
+ free(eg);
}
--- a/libsec/genprime.c
+++ b/libsec/genprime.c
@@ -17,6 +17,7 @@
p->p[p->top-1] &= (x-1);
p->p[p->top-1] |= x;
p->p[0] |= 1;
+ mpnorm(p);
// keep icrementing till it looks prime
for(;;){
--- /dev/null
+++ b/libsec/hkdf.c
@@ -1,0 +1,39 @@
+#include "os.h"
+#include <mp.h>
+#include <libsec.h>
+
+/* rfc5869 */
+void
+hkdf_x(salt, nsalt, info, ninfo, key, nkey, d, dlen, x, xlen)
+ uchar *salt, *info, *key, *d;
+ ulong nsalt, ninfo, nkey, 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);
+ }
+}
--- a/libsec/hmac.c
+++ b/libsec/hmac.c
@@ -2,27 +2,30 @@
#include <libsec.h>
/* rfc2104 */
-static DigestState*
+DigestState*
hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen)
{
int i;
- uchar pad[65], innerdigest[256];
+ uchar pad[Hmacblksz+1], innerdigest[256];
if(xlen > sizeof(innerdigest))
return nil;
+ if(klen > Hmacblksz){
+ if(xlen > Hmacblksz)
+ return nil;
+ (*x)(key, klen, innerdigest, nil);
+ key = innerdigest;
+ klen = xlen;
+ }
- if(klen>64)
- return nil;
-
/* first time through */
- if(s == nil){
- for(i=0; i<64; i++)
- pad[i] = 0x36;
- pad[64] = 0;
- for(i=0; i<klen; i++)
+ if(s == nil || s->seeded == 0){
+ memset(pad, 0x36, Hmacblksz);
+ pad[Hmacblksz] = 0;
+ for(i = 0; i < klen; i++)
pad[i] ^= key[i];
- s = (*x)(pad, 64, nil, nil);
+ s = (*x)(pad, Hmacblksz, nil, s);
if(s == nil)
return nil;
}
@@ -32,25 +35,12 @@
return s;
/* last time through */
- for(i=0; i<64; i++)
- pad[i] = 0x5c;
- pad[64] = 0;
- for(i=0; i<klen; i++)
+ memset(pad, 0x5c, Hmacblksz);
+ pad[Hmacblksz] = 0;
+ for(i = 0; i < klen; i++)
pad[i] ^= key[i];
(*x)(nil, 0, innerdigest, s);
- s = (*x)(pad, 64, nil, nil);
+ s = (*x)(pad, Hmacblksz, nil, nil);
(*x)(innerdigest, xlen, digest, s);
return nil;
-}
-
-DigestState*
-hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
- return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
-}
-
-DigestState*
-hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
- return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
}
--- a/libsec/hmactest.c
+++ /dev/null
@@ -1,19 +1,0 @@
-#include "os.h"
-#include <mp.h>
-#include <libsec.h>
-
-uchar key[] = "Jefe";
-uchar data[] = "what do ya want for nothing?";
-
-void
-main(void)
-{
- int i;
- uchar hash[MD5dlen];
-
- hmac_md5(data, strlen((char*)data), key, 4, hash, nil);
- for(i=0; i<MD5dlen; i++)
- print("%2.2x", hash[i]);
- print("\n");
- print("750c783e6ab0b503eaa86e310a5db738\n");
-}
--- a/libsec/md4test.c
+++ /dev/null
@@ -1,31 +1,0 @@
-#include "os.h"
-#include <mp.h>
-#include <libsec.h>
-
-char *tests[] = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
- 0
-};
-
-void
-main(void)
-{
- char **pp;
- uchar *p;
- int i;
- uchar digest[MD5dlen];
-
- for(pp = tests; *pp; pp++){
- p = (uchar*)*pp;
- md4(p, strlen(*pp), digest, 0);
- for(i = 0; i < MD5dlen; i++)
- print("%2.2ux", digest[i]);
- print("\n");
- }
-}
--- a/libsec/md5.c
+++ b/libsec/md5.c
@@ -145,3 +145,10 @@
*output++ = x >> 24;
}
}
+
+DigestState*
+hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
+}
--- a/libsec/md5pickle.c
+++ b/libsec/md5pickle.c
@@ -7,11 +7,12 @@
char *p;
int m, n;
- m = 4*9+4*((s->blen+3)/3);
+ m = 17+4*9+4*((s->blen+3)/3 + 1);
p = malloc(m);
if(p == nil)
return p;
- n = sprint(p, "%8.8ux %8.8ux %8.8ux %8.8ux ",
+ n = sprint(p, "%16.16llux %8.8ux %8.8ux %8.8ux %8.8ux ",
+ s->len,
s->state[0], s->state[1], s->state[2],
s->state[3]);
enc64(p+n, m-n, s->buf, s->blen);
@@ -26,6 +27,7 @@
s = malloc(sizeof(*s));
if(s == nil)
return nil;
+ s->len = strtoull(p, &p, 16);
s->state[0] = strtoul(p, &p, 16);
s->state[1] = strtoul(p, &p, 16);
s->state[2] = strtoul(p, &p, 16);
--- a/libsec/nfastrand.c
+++ b/libsec/nfastrand.c
@@ -14,7 +14,7 @@
* so we want a random number < m.
*/
if(n > Maxrand)
- abort();
+ sysfatal("nfastrand: n too large");
m = Maxrand - Maxrand % n;
while((r = fastrand()) >= m)
--- /dev/null
+++ b/libsec/pbkdf2.c
@@ -1,0 +1,35 @@
+#include "os.h"
+#include <mp.h>
+#include <libsec.h>
+
+/* rfc2898 */
+void
+pbkdf2_x(p, plen, s, slen, rounds, d, dlen, x, xlen)
+ uchar *p, *s, *d;
+ ulong plen, slen, dlen, rounds;
+ DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+ int xlen;
+{
+ uchar block[256], tmp[256];
+ ulong i, j, k, n;
+ DigestState *ds;
+
+ assert(xlen <= sizeof(tmp));
+
+ for(i = 1; dlen > 0; i++, d += n, dlen -= n){
+ tmp[3] = i;
+ tmp[2] = i >> 8;
+ tmp[1] = i >> 16;
+ tmp[0] = i >> 24;
+ ds = (*x)(s, slen, p, plen, nil, nil);
+ (*x)(tmp, 4, p, plen, block, ds);
+ memmove(tmp, block, xlen);
+ for(j = 1; j < rounds; j++){
+ (*x)(tmp, xlen, p, plen, tmp, nil);
+ for(k=0; k<xlen; k++)
+ block[k] ^= tmp[k];
+ }
+ n = dlen > xlen ? xlen : dlen;
+ memmove(d, block, n);
+ }
+}
--- /dev/null
+++ b/libsec/poly1305.c
@@ -1,0 +1,196 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+/*
+ poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition
+
+ derived from http://github.com/floodberry/poly1305-donna
+*/
+
+#define U8TO32(p) ((u32int)(p)[0] | (u32int)(p)[1]<<8 | (u32int)(p)[2]<<16 | (u32int)(p)[3]<<24)
+#define U32TO8(p, v) (p)[0]=(v), (p)[1]=(v)>>8, (p)[2]=(v)>>16, (p)[3]=(v)>>24
+
+/* (r,s) = (key[0:15],key[16:31]), the one time key */
+DigestState*
+poly1305(uchar *m, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
+{
+ u32int r0,r1,r2,r3,r4, s1,s2,s3,s4, h0,h1,h2,h3,h4, g0,g1,g2,g3,g4;
+ u64int d0,d1,d2,d3,d4, f;
+ u32int hibit, mask, c;
+
+ if(s == nil){
+ s = malloc(sizeof(*s));
+ if(s == nil)
+ return nil;
+ memset(s, 0, sizeof(*s));
+ s->malloced = 1;
+ }
+
+ if(s->seeded == 0){
+ assert(klen == 32);
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ s->state[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff;
+ s->state[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03;
+ s->state[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff;
+ s->state[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff;
+ s->state[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
+
+ /* h = 0 */
+ s->state[5] = 0;
+ s->state[6] = 0;
+ s->state[7] = 0;
+ s->state[8] = 0;
+ s->state[9] = 0;
+
+ /* save pad for later */
+ s->state[10] = U8TO32(&key[16]);
+ s->state[11] = U8TO32(&key[20]);
+ s->state[12] = U8TO32(&key[24]);
+ s->state[13] = U8TO32(&key[28]);
+
+ s->seeded = 1;
+ }
+
+ if(s->blen){
+ c = 16 - s->blen;
+ if(c > len)
+ c = len;
+ memmove(s->buf + s->blen, m, c);
+ len -= c, m += c;
+ s->blen += c;
+ if(s->blen == 16){
+ s->blen = 0;
+ poly1305(s->buf, 16, key, klen, nil, s);
+ } else if(len == 0){
+ m = s->buf;
+ len = s->blen;
+ s->blen = 0;
+ }
+ }
+
+ r0 = s->state[0];
+ r1 = s->state[1];
+ r2 = s->state[2];
+ r3 = s->state[3];
+ r4 = s->state[4];
+
+ h0 = s->state[5];
+ h1 = s->state[6];
+ h2 = s->state[7];
+ h3 = s->state[8];
+ h4 = s->state[9];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ hibit = 1<<24; /* 1<<128 */
+
+ while(len >= 16){
+Block:
+ /* h += m[i] */
+ h0 += (U8TO32(&m[0]) ) & 0x3ffffff;
+ h1 += (U8TO32(&m[3]) >> 2) & 0x3ffffff;
+ h2 += (U8TO32(&m[6]) >> 4) & 0x3ffffff;
+ h3 += (U8TO32(&m[9]) >> 6) & 0x3ffffff;
+ h4 += (U8TO32(&m[12])>> 8) | hibit;
+
+ /* h *= r */
+ d0 = ((u64int)h0 * r0) + ((u64int)h1 * s4) + ((u64int)h2 * s3) + ((u64int)h3 * s2) + ((u64int)h4 * s1);
+ d1 = ((u64int)h0 * r1) + ((u64int)h1 * r0) + ((u64int)h2 * s4) + ((u64int)h3 * s3) + ((u64int)h4 * s2);
+ d2 = ((u64int)h0 * r2) + ((u64int)h1 * r1) + ((u64int)h2 * r0) + ((u64int)h3 * s4) + ((u64int)h4 * s3);
+ d3 = ((u64int)h0 * r3) + ((u64int)h1 * r2) + ((u64int)h2 * r1) + ((u64int)h3 * r0) + ((u64int)h4 * s4);
+ d4 = ((u64int)h0 * r4) + ((u64int)h1 * r3) + ((u64int)h2 * r2) + ((u64int)h3 * r1) + ((u64int)h4 * r0);
+
+ /* (partial) h %= p */
+ c = (u32int)(d0 >> 26); h0 = (u32int)d0 & 0x3ffffff;
+ d1 += c; c = (u32int)(d1 >> 26); h1 = (u32int)d1 & 0x3ffffff;
+ d2 += c; c = (u32int)(d2 >> 26); h2 = (u32int)d2 & 0x3ffffff;
+ d3 += c; c = (u32int)(d3 >> 26); h3 = (u32int)d3 & 0x3ffffff;
+ d4 += c; c = (u32int)(d4 >> 26); h4 = (u32int)d4 & 0x3ffffff;
+ h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ len -= 16, m += 16;
+ }
+
+ if(len){
+ s->blen = len;
+ memmove(s->buf, m, len);
+ }
+
+ if(digest == nil){
+ s->state[5] = h0;
+ s->state[6] = h1;
+ s->state[7] = h2;
+ s->state[8] = h3;
+ s->state[9] = h4;
+ return s;
+ }
+
+ if(len){
+ m = s->buf;
+ m[len++] = 1;
+ while(len < 16)
+ m[len++] = 0;
+ hibit = 0;
+ goto Block;
+ }
+
+ c = h1 >> 26; h1 = h1 & 0x3ffffff;
+ h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
+ h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
+ h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
+ h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
+ g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
+ g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
+ g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
+ g4 = h4 + c - (1 << 26);
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> 31) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = (h0 ) | (h1 << 26);
+ h1 = (h1 >> 6) | (h2 << 20);
+ h2 = (h2 >> 12) | (h3 << 14);
+ h3 = (h3 >> 18) | (h4 << 8);
+
+ /* digest = (h + pad) % (2^128) */
+ f = (u64int)h0 + s->state[10] ; h0 = (u32int)f;
+ f = (u64int)h1 + s->state[11] + (f >> 32); h1 = (u32int)f;
+ f = (u64int)h2 + s->state[12] + (f >> 32); h2 = (u32int)f;
+ f = (u64int)h3 + s->state[13] + (f >> 32); h3 = (u32int)f;
+
+ U32TO8(&digest[0], h0);
+ U32TO8(&digest[4], h1);
+ U32TO8(&digest[8], h2);
+ U32TO8(&digest[12], h3);
+
+ if(s->malloced){
+ memset(s, 0, sizeof(*s));
+ free(s);
+ return nil;
+ }
+
+ memset(s, 0, sizeof(*s));
+ return nil;
+}
--- a/libsec/probably_prime.c
+++ b/libsec/probably_prime.c
@@ -2,14 +2,16 @@
#include <mp.h>
#include <libsec.h>
-// Miller-Rabin probabilistic primality testing
-// Knuth (1981) Seminumerical Algorithms, p.379
-// Menezes et al () Handbook, p.39
-// 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep
+/*
+ * Miller-Rabin probabilistic primality testing
+ * Knuth (1981) Seminumerical Algorithms, p.379
+ * Menezes et al () Handbook, p.39
+ * 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep
+ */
int
probably_prime(mpint *n, int nrep)
{
- int j, k, rep, nbits, isprime = 1;
+ int j, k, rep, nbits, isprime;
mpint *nm1, *q, *x, *y, *r;
if(n->sign < 0)
@@ -19,18 +21,18 @@
nrep = 18;
k = mptoi(n);
- if(k == 2) // 2 is prime
+ if(k < 2) /* 1 is not prime */
+ return 0;
+ if(k == 2 || k == 3) /* 2, 3 is prime */
return 1;
- if(k < 2) // 1 is not prime
+ if((n->p[0] & 1) == 0) /* even is not prime */
return 0;
- if((n->p[0] & 1) == 0) // even is not prime
- return 0;
- // test against small prime numbers
+ /* test against small prime numbers */
if(smallprimetest(n) < 0)
return 0;
- // fermat test, 2^n mod n == 2 if p is prime
+ /* fermat test, 2^n mod n == 2 if p is prime */
x = uitomp(2, nil);
y = mpnew(0);
mpexp(x, n, n, y);
@@ -43,38 +45,43 @@
nbits = mpsignif(n);
nm1 = mpnew(nbits);
- mpsub(n, mpone, nm1); // nm1 = n - 1 */
+ mpsub(n, mpone, nm1); /* nm1 = n - 1 */
k = mplowbits0(nm1);
q = mpnew(0);
- mpright(nm1, k, q); // q = (n-1)/2**k
+ mpright(nm1, k, q); /* q = (n-1)/2**k */
for(rep = 0; rep < nrep; rep++){
-
- // x = random in [2, n-2]
- r = mprand(nbits, prng, nil);
- mpmod(r, nm1, x);
- mpfree(r);
- if(mpcmp(x, mpone) <= 0)
- continue;
+ for(;;){
+ /* find x = random in [2, n-2] */
+ r = mprand(nbits, prng, nil);
+ mpmod(r, nm1, x);
+ mpfree(r);
+ if(mpcmp(x, mpone) > 0)
+ break;
+ }
- // y = x**q mod n
+ /* y = x**q mod n */
mpexp(x, q, n, y);
if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0)
- goto done;
+ continue;
- for(j = 1; j < k; j++){
- mpmul(y, y, x);
- mpmod(x, n, y); // y = y*y mod n
- if(mpcmp(y, nm1) == 0)
- goto done;
- if(mpcmp(y, mpone) == 0){
- isprime = 0;
- goto done;
- }
+ for(j = 1;; j++){
+ if(j >= k) {
+ isprime = 0;
+ goto done;
+ }
+ mpmul(y, y, x);
+ mpmod(x, n, y); /* y = y*y mod n */
+ if(mpcmp(y, nm1) == 0)
+ break;
+ if(mpcmp(y, mpone) == 0){
+ isprime = 0;
+ goto done;
+ }
}
- isprime = 0;
}
+ isprime = 1;
done:
mpfree(y);
mpfree(x);
--- a/libsec/readcert.c
+++ b/libsec/readcert.c
@@ -1,5 +1,6 @@
#include <u.h>
#include <libc.h>
+#include <auth.h>
#include <mp.h>
#include <libsec.h>
@@ -13,8 +14,10 @@
fd = open(name, OREAD);
if(fd < 0)
return nil;
- if((d = dirfstat(fd)) == nil)
+ if((d = dirfstat(fd)) == nil) {
+ close(fd);
return nil;
+ }
s = malloc(d->length + 1);
if(s == nil || readn(fd, s, d->length) != d->length){
free(s);
@@ -36,10 +39,10 @@
pem = readfile(filename);
if(pem == nil){
- werrstr("can't read %s", filename);
+ werrstr("can't read %s: %r", filename);
return nil;
}
- binary = decodepem(pem, "CERTIFICATE", pcertlen);
+ binary = decodePEM(pem, "CERTIFICATE", pcertlen, nil);
free(pem);
if(binary == nil){
werrstr("can't parse %s", filename);
@@ -46,5 +49,18 @@
return nil;
}
return binary;
+}
+
+PEMChain *
+readcertchain(char *filename)
+{
+ char *chfile;
+
+ chfile = readfile(filename);
+ if (chfile == nil) {
+ werrstr("can't read %s: %r", filename);
+ return nil;
+ }
+ return decodepemchain(chfile, "CERTIFICATE");
}
--- /dev/null
+++ b/libsec/ripemd.c
@@ -1,0 +1,383 @@
+#include "os.h"
+
+#include <libsec.h>
+
+#define BYTES_TO_DWORD(strptr) \
+ (((u32int) *((strptr)+3) << 24) | \
+ ((u32int) *((strptr)+2) << 16) | \
+ ((u32int) *((strptr)+1) << 8) | \
+ ((u32int) *(strptr)))
+
+#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s) {\
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define GG(a, b, c, d, e, x, s) {\
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define HH(a, b, c, d, e, x, s) {\
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define II(a, b, c, d, e, x, s) {\
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define JJ(a, b, c, d, e, x, s) {\
+ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define FFF(a, b, c, d, e, x, s) {\
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define GGG(a, b, c, d, e, x, s) {\
+ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define HHH(a, b, c, d, e, x, s) {\
+ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define III(a, b, c, d, e, x, s) {\
+ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define JJJ(a, b, c, d, e, x, s) {\
+ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+
+
+static void MDinit(u32int *MDbuf)
+{
+ MDbuf[0] = 0x67452301UL;
+ MDbuf[1] = 0xefcdab89UL;
+ MDbuf[2] = 0x98badcfeUL;
+ MDbuf[3] = 0x10325476UL;
+ MDbuf[4] = 0xc3d2e1f0UL;
+
+ return;
+}
+
+static void compress(u32int *MDbuf, u32int *X)
+{
+ u32int aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2],
+ dd = MDbuf[3], ee = MDbuf[4];
+ u32int aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
+ ddd = MDbuf[3], eee = MDbuf[4];
+
+ /* round 1 */
+ FF(aa, bb, cc, dd, ee, X[ 0], 11);
+ FF(ee, aa, bb, cc, dd, X[ 1], 14);
+ FF(dd, ee, aa, bb, cc, X[ 2], 15);
+ FF(cc, dd, ee, aa, bb, X[ 3], 12);
+ FF(bb, cc, dd, ee, aa, X[ 4], 5);
+ FF(aa, bb, cc, dd, ee, X[ 5], 8);
+ FF(ee, aa, bb, cc, dd, X[ 6], 7);
+ FF(dd, ee, aa, bb, cc, X[ 7], 9);
+ FF(cc, dd, ee, aa, bb, X[ 8], 11);
+ FF(bb, cc, dd, ee, aa, X[ 9], 13);
+ FF(aa, bb, cc, dd, ee, X[10], 14);
+ FF(ee, aa, bb, cc, dd, X[11], 15);
+ FF(dd, ee, aa, bb, cc, X[12], 6);
+ FF(cc, dd, ee, aa, bb, X[13], 7);
+ FF(bb, cc, dd, ee, aa, X[14], 9);
+ FF(aa, bb, cc, dd, ee, X[15], 8);
+
+ /* round 2 */
+ GG(ee, aa, bb, cc, dd, X[ 7], 7);
+ GG(dd, ee, aa, bb, cc, X[ 4], 6);
+ GG(cc, dd, ee, aa, bb, X[13], 8);
+ GG(bb, cc, dd, ee, aa, X[ 1], 13);
+ GG(aa, bb, cc, dd, ee, X[10], 11);
+ GG(ee, aa, bb, cc, dd, X[ 6], 9);
+ GG(dd, ee, aa, bb, cc, X[15], 7);
+ GG(cc, dd, ee, aa, bb, X[ 3], 15);
+ GG(bb, cc, dd, ee, aa, X[12], 7);
+ GG(aa, bb, cc, dd, ee, X[ 0], 12);
+ GG(ee, aa, bb, cc, dd, X[ 9], 15);
+ GG(dd, ee, aa, bb, cc, X[ 5], 9);
+ GG(cc, dd, ee, aa, bb, X[ 2], 11);
+ GG(bb, cc, dd, ee, aa, X[14], 7);
+ GG(aa, bb, cc, dd, ee, X[11], 13);
+ GG(ee, aa, bb, cc, dd, X[ 8], 12);
+
+ /* round 3 */
+ HH(dd, ee, aa, bb, cc, X[ 3], 11);
+ HH(cc, dd, ee, aa, bb, X[10], 13);
+ HH(bb, cc, dd, ee, aa, X[14], 6);
+ HH(aa, bb, cc, dd, ee, X[ 4], 7);
+ HH(ee, aa, bb, cc, dd, X[ 9], 14);
+ HH(dd, ee, aa, bb, cc, X[15], 9);
+ HH(cc, dd, ee, aa, bb, X[ 8], 13);
+ HH(bb, cc, dd, ee, aa, X[ 1], 15);
+ HH(aa, bb, cc, dd, ee, X[ 2], 14);
+ HH(ee, aa, bb, cc, dd, X[ 7], 8);
+ HH(dd, ee, aa, bb, cc, X[ 0], 13);
+ HH(cc, dd, ee, aa, bb, X[ 6], 6);
+ HH(bb, cc, dd, ee, aa, X[13], 5);
+ HH(aa, bb, cc, dd, ee, X[11], 12);
+ HH(ee, aa, bb, cc, dd, X[ 5], 7);
+ HH(dd, ee, aa, bb, cc, X[12], 5);
+
+ /* round 4 */
+ II(cc, dd, ee, aa, bb, X[ 1], 11);
+ II(bb, cc, dd, ee, aa, X[ 9], 12);
+ II(aa, bb, cc, dd, ee, X[11], 14);
+ II(ee, aa, bb, cc, dd, X[10], 15);
+ II(dd, ee, aa, bb, cc, X[ 0], 14);
+ II(cc, dd, ee, aa, bb, X[ 8], 15);
+ II(bb, cc, dd, ee, aa, X[12], 9);
+ II(aa, bb, cc, dd, ee, X[ 4], 8);
+ II(ee, aa, bb, cc, dd, X[13], 9);
+ II(dd, ee, aa, bb, cc, X[ 3], 14);
+ II(cc, dd, ee, aa, bb, X[ 7], 5);
+ II(bb, cc, dd, ee, aa, X[15], 6);
+ II(aa, bb, cc, dd, ee, X[14], 8);
+ II(ee, aa, bb, cc, dd, X[ 5], 6);
+ II(dd, ee, aa, bb, cc, X[ 6], 5);
+ II(cc, dd, ee, aa, bb, X[ 2], 12);
+
+ /* round 5 */
+ JJ(bb, cc, dd, ee, aa, X[ 4], 9);
+ JJ(aa, bb, cc, dd, ee, X[ 0], 15);
+ JJ(ee, aa, bb, cc, dd, X[ 5], 5);
+ JJ(dd, ee, aa, bb, cc, X[ 9], 11);
+ JJ(cc, dd, ee, aa, bb, X[ 7], 6);
+ JJ(bb, cc, dd, ee, aa, X[12], 8);
+ JJ(aa, bb, cc, dd, ee, X[ 2], 13);
+ JJ(ee, aa, bb, cc, dd, X[10], 12);
+ JJ(dd, ee, aa, bb, cc, X[14], 5);
+ JJ(cc, dd, ee, aa, bb, X[ 1], 12);
+ JJ(bb, cc, dd, ee, aa, X[ 3], 13);
+ JJ(aa, bb, cc, dd, ee, X[ 8], 14);
+ JJ(ee, aa, bb, cc, dd, X[11], 11);
+ JJ(dd, ee, aa, bb, cc, X[ 6], 8);
+ JJ(cc, dd, ee, aa, bb, X[15], 5);
+ JJ(bb, cc, dd, ee, aa, X[13], 6);
+
+ /* parallel round 1 */
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
+ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
+ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
+ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
+
+ /* parallel round 2 */
+ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
+ III(ddd, eee, aaa, bbb, ccc, X[11], 13);
+ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
+ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
+ III(eee, aaa, bbb, ccc, ddd, X[13], 8);
+ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
+ III(ccc, ddd, eee, aaa, bbb, X[10], 11);
+ III(bbb, ccc, ddd, eee, aaa, X[14], 7);
+ III(aaa, bbb, ccc, ddd, eee, X[15], 7);
+ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
+ III(ddd, eee, aaa, bbb, ccc, X[12], 7);
+ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
+ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
+ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
+ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
+
+ /* parallel round 3 */
+ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
+ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
+ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
+ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
+ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
+ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
+ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
+ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
+ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
+ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
+
+ /* parallel round 4 */
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
+ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
+ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
+ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
+ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
+ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
+ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
+ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
+ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
+ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
+ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
+ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
+
+ /* parallel round 5 */
+ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
+ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
+ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
+ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
+ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
+ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
+ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
+ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
+ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
+ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
+
+ /* combine results */
+ ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */
+ MDbuf[1] = MDbuf[2] + dd + eee;
+ MDbuf[2] = MDbuf[3] + ee + aaa;
+ MDbuf[3] = MDbuf[4] + aa + bbb;
+ MDbuf[4] = MDbuf[0] + bb + ccc;
+ MDbuf[0] = ddd;
+
+ return;
+}
+
+static void MDfinish(u32int *MDbuf, uchar *strptr, u32int lswlen, u32int mswlen)
+{
+ unsigned int i; /* counter */
+ u32int X[16]; /* message words */
+
+ memset(X, 0, 16*sizeof(u32int));
+
+ /* put bytes from strptr into X */
+ for (i=0; i<(lswlen&63); i++) {
+ /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */
+ X[i>>2] ^= (u32int) *strptr++ << (8 * (i&3));
+ }
+
+ /* append the bit m_n == 1 */
+ X[(lswlen>>2)&15] ^= (u32int)1 << (8*(lswlen&3) + 7);
+
+ if ((lswlen & 63) > 55) {
+ /* length goes to next block */
+ compress(MDbuf, X);
+ memset(X, 0, 16*sizeof(u32int));
+ }
+
+ /* append length in bits*/
+ X[14] = lswlen << 3;
+ X[15] = (lswlen >> 29) | (mswlen << 3);
+ compress(MDbuf, X);
+
+ return;
+}
+
+DigestState*
+ripemd160(uchar *p, ulong len, uchar *digest, DigestState *s)
+{
+ u32int x[16];
+ int i, j, k;
+
+ if(s == nil){
+ s = malloc(sizeof(*s));
+ if(s == nil)
+ return nil;
+ memset(s, 0, sizeof(*s));
+ s->malloced = 1;
+ }
+
+ if(s->seeded == 0){
+ MDinit(s->state);
+ s->seeded = 1;
+ }
+
+ /* fill out the partial 64 byte block from previous calls */
+ if(s->blen){
+ i = 64 - s->blen;
+ if(len < i)
+ i = len;
+ memmove(s->buf + s->blen, p, i);
+ len -= i;
+ s->blen += i;
+ p += i;
+ if(s->blen == 64){
+ for(i = 0; i < 16; i++)
+ x[i] = BYTES_TO_DWORD(s->buf + i * 4);
+ compress(s->state, x);
+ s->len += s->blen;
+ s->blen = 0;
+ }
+ }
+
+ /* do 64 byte blocks */
+ i = len & ~0x3f;
+ if(i){
+ for(j = 0; j < i; j += 64){
+ for(k = 0; k < 16; k++)
+ x[k] = BYTES_TO_DWORD(p + j + k * 4);
+ compress(s->state, x);
+ }
+ s->len += i;
+ len -= i;
+ p += i;
+ }
+
+ /* save the left overs if not last call */
+ if(digest == 0){
+ if(len){
+ memmove(s->buf, p, len);
+ s->blen += len;
+ }
+ return s;
+ }
+
+ MDfinish(s->state, p, s->len + len, 0);
+ for(i = 0; i < 5; i++){
+ digest[4 * i] = s->state[i];
+ digest[4 * i + 1] = s->state[i] >> 8;
+ digest[4 * i + 2] = s->state[i] >> 16;
+ digest[4 * i + 3] = s->state[i] >> 24;
+
+ }
+ if(s->malloced == 1)
+ free(s);
+ return nil;
+
+}
--- a/libsec/rsagen.c
+++ b/libsec/rsagen.c
@@ -2,21 +2,6 @@
#include <mp.h>
#include <libsec.h>
-static void
-genrand(mpint *p, int n)
-{
- mpdigit x;
-
- // generate n random bits with high set
- mpbits(p, n);
- genrandom((uchar*)p->p, (n+7)/8);
- p->top = (n+Dbits-1)/Dbits;
- x = 1;
- x <<= ((n-1)%Dbits);
- p->p[p->top-1] &= (x-1);
- p->p[p->top-1] |= x;
-}
-
RSApriv*
rsagen(int nlen, int elen, int rounds)
{
@@ -31,8 +16,8 @@
phi = mpnew(nlen);
// create the prime factors and euclid's function
- genstrongprime(p, nlen/2, rounds);
- genstrongprime(q, nlen - mpsignif(p) + 1, rounds);
+ genprime(p, nlen/2, rounds);
+ genprime(q, nlen - mpsignif(p) + 1, rounds);
mpmul(p, q, n);
mpsub(p, mpone, e);
mpsub(q, mpone, d);
@@ -41,18 +26,21 @@
// find an e relatively prime to phi
t1 = mpnew(0);
t2 = mpnew(0);
- genrand(e, elen);
+ mprand(elen, genrandom, e);
+ if(mpcmp(e,mptwo) <= 0)
+ itomp(3, e);
+ // See Menezes et al. p.291 "8.8 Note (selecting primes)" for discussion
+ // of the merits of various choices of primes and exponents. e=3 is a
+ // common and recommended exponent, but doesn't necessarily work here
+ // because we chose strong rather than safe primes.
for(;;){
- mpextendedgcd(e, phi, d, t1, t2);
- if(mpcmp(d, mpone) == 0)
+ mpextendedgcd(e, phi, t1, d, t2);
+ if(mpcmp(t1, mpone) == 0)
break;
mpadd(mpone, e, e);
}
mpfree(t1);
mpfree(t2);
-
- // d = e**-1 mod phi
- mpinvert(e, phi, d);
// compute chinese remainder coefficient
c2 = mpnew(0);
--- /dev/null
+++ b/libsec/salsa.c
@@ -1,0 +1,320 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+enum{
+ Blockwords= SalsaBsize/sizeof(u32int)
+};
+
+/* little-endian data order */
+#define GET4(p) ((((((p)[3]<<8) | (p)[2])<<8) | (p)[1])<<8 | (p)[0])
+#define PUT4(p, v) (((p)[0]=v), (v>>=8), ((p)[1]=v), (v>>=8), ((p)[2]=v), (v>>=8), ((p)[3]=v))
+
+#define ROTATE(v,c) (t = v, (u32int)(t << (c)) | (t >> (32 - (c))))
+
+#define ENCRYPT(s, x, y, d) {\
+ u32int v; \
+ uchar *sp, *dp; \
+ sp = (s); \
+ v = GET4(sp); \
+ v ^= (x)+(y); \
+ dp = (d); \
+ PUT4(dp, v); \
+}
+
+static uchar sigma[16] = "expand 32-byte k";
+static uchar tau[16] = "expand 16-byte k";
+
+static void
+load(u32int *d, uchar *s, int nw)
+{
+ int i;
+
+ for(i = 0; i < nw; i++, s+=4)
+ d[i] = GET4(s);
+}
+
+void
+setupSalsastate(Salsastate *s, uchar *key, ulong keylen, uchar *iv, ulong ivlen, int rounds)
+{
+ if(keylen != 256/8 && keylen != 128/8)
+ sysfatal("invalid salsa key length");
+ if(ivlen != 64/8 && ivlen != 128/8 && ivlen != 192/8)
+ sysfatal("invalid salsa iv length");
+ if(rounds == 0)
+ rounds = 20;
+ s->rounds = rounds;
+ if(keylen == 256/8) { /* recommended */
+ load(&s->input[0], sigma+4*0, 1);
+ load(&s->input[1], key +16*0, 4);
+ load(&s->input[5], sigma+4*1, 1);
+ load(&s->input[10], sigma+4*2, 1);
+ load(&s->input[11], key +16*1, 4);
+ load(&s->input[15], sigma+4*3, 1);
+ }else{
+ load(&s->input[0], tau +4*0, 1);
+ load(&s->input[1], key, 4);
+ load(&s->input[5], tau +4*1, 1);
+ load(&s->input[10], tau +4*2, 1);
+ load(&s->input[11], key, 4);
+ load(&s->input[15], tau +4*3, 1);
+ }
+ s->key[0] = s->input[1];
+ s->key[1] = s->input[2];
+ s->key[2] = s->input[3];
+ s->key[3] = s->input[4];
+ s->key[4] = s->input[11];
+ s->key[5] = s->input[12];
+ s->key[6] = s->input[13];
+ s->key[7] = s->input[14];
+
+ s->ivwords = ivlen/4;
+ s->input[8] = 0;
+ s->input[9] = 0;
+ if(iv == nil){
+ s->input[6] = 0;
+ s->input[7] = 0;
+ }else
+ salsa_setiv(s, iv);
+}
+
+static void
+hsalsablock(uchar h[32], Salsastate *s)
+{
+ u32int x[Blockwords], t;
+ int i, rounds;
+
+ rounds = s->rounds;
+ x[0] = s->input[0];
+ x[1] = s->input[1];
+ x[2] = s->input[2];
+ x[3] = s->input[3];
+ x[4] = s->input[4];
+ x[5] = s->input[5];
+ x[6] = s->input[6];
+ x[7] = s->input[7];
+ x[8] = s->input[8];
+ x[9] = s->input[9];
+ x[10] = s->input[10];
+ x[11] = s->input[11];
+ x[12] = s->input[12];
+ x[13] = s->input[13];
+ x[14] = s->input[14];
+ x[15] = s->input[15];
+
+ for(i = rounds; i > 0; i -= 2) {
+ x[4] ^= ROTATE( x[0]+x[12], 7);
+ x[8] ^= ROTATE( x[4]+ x[0], 9);
+ x[12] ^= ROTATE( x[8]+ x[4],13);
+ x[0] ^= ROTATE(x[12]+ x[8],18);
+ x[9] ^= ROTATE( x[5]+ x[1], 7);
+ x[13] ^= ROTATE( x[9]+ x[5], 9);
+ x[1] ^= ROTATE(x[13]+ x[9],13);
+ x[5] ^= ROTATE( x[1]+x[13],18);
+ x[14] ^= ROTATE(x[10]+ x[6], 7);
+ x[2] ^= ROTATE(x[14]+x[10], 9);
+ x[6] ^= ROTATE( x[2]+x[14],13);
+ x[10] ^= ROTATE( x[6]+ x[2],18);
+ x[3] ^= ROTATE(x[15]+x[11], 7);
+ x[7] ^= ROTATE( x[3]+x[15], 9);
+ x[11] ^= ROTATE( x[7]+ x[3],13);
+ x[15] ^= ROTATE(x[11]+ x[7],18);
+ x[1] ^= ROTATE( x[0]+ x[3], 7);
+ x[2] ^= ROTATE( x[1]+ x[0], 9);
+ x[3] ^= ROTATE( x[2]+ x[1],13);
+ x[0] ^= ROTATE( x[3]+ x[2],18);
+ x[6] ^= ROTATE( x[5]+ x[4], 7);
+ x[7] ^= ROTATE( x[6]+ x[5], 9);
+ x[4] ^= ROTATE( x[7]+ x[6],13);
+ x[5] ^= ROTATE( x[4]+ x[7],18);
+ x[11] ^= ROTATE(x[10]+ x[9], 7);
+ x[8] ^= ROTATE(x[11]+x[10], 9);
+ x[9] ^= ROTATE( x[8]+x[11],13);
+ x[10] ^= ROTATE( x[9]+ x[8],18);
+ x[12] ^= ROTATE(x[15]+x[14], 7);
+ x[13] ^= ROTATE(x[12]+x[15], 9);
+ x[14] ^= ROTATE(x[13]+x[12],13);
+ x[15] ^= ROTATE(x[14]+x[13],18);
+ }
+
+ PUT4(h+0*4, x[0]);
+ PUT4(h+1*4, x[5]);
+ PUT4(h+2*4, x[10]);
+ PUT4(h+3*4, x[15]);
+ PUT4(h+4*4, x[6]);
+ PUT4(h+5*4, x[7]);
+ PUT4(h+6*4, x[8]);
+ PUT4(h+7*4, x[9]);
+}
+
+void
+salsa_setiv(Salsastate *s, uchar *iv)
+{
+ if(s->ivwords == 128/32){
+ /* hsalsa 128-bit iv */
+ load(&s->input[6], iv, 4);
+ return;
+ }
+ if(s->ivwords == 192/32){
+ /* xsalsa with 192-bit iv */
+ u32int counter[2];
+ uchar h[32];
+
+ counter[0] = s->input[8];
+ counter[1] = s->input[9];
+
+ s->input[1] = s->key[0];
+ s->input[2] = s->key[1];
+ s->input[3] = s->key[2];
+ s->input[4] = s->key[3];
+ s->input[11] = s->key[4];
+ s->input[12] = s->key[5];
+ s->input[13] = s->key[6];
+ s->input[14] = s->key[7];
+
+ load(&s->input[6], iv, 4);
+
+ hsalsablock(h, s);
+ load(&s->input[1], h+16*0, 4);
+ load(&s->input[11], h+16*1, 4);
+ memset(h, 0, 32);
+
+ s->input[8] = counter[0];
+ s->input[9] = counter[1];
+
+ iv += 16;
+ }
+ /* 64-bit iv */
+ load(&s->input[6], iv, 2);
+}
+
+void
+salsa_setblock(Salsastate *s, u64int blockno)
+{
+ s->input[8] = blockno;
+ s->input[9] = blockno>>32;
+}
+
+static void
+encryptblock(Salsastate *s, uchar *src, uchar *dst)
+{
+ u32int x[Blockwords], t;
+ int i, rounds;
+
+ rounds = s->rounds;
+ x[0] = s->input[0];
+ x[1] = s->input[1];
+ x[2] = s->input[2];
+ x[3] = s->input[3];
+ x[4] = s->input[4];
+ x[5] = s->input[5];
+ x[6] = s->input[6];
+ x[7] = s->input[7];
+ x[8] = s->input[8];
+ x[9] = s->input[9];
+ x[10] = s->input[10];
+ x[11] = s->input[11];
+ x[12] = s->input[12];
+ x[13] = s->input[13];
+ x[14] = s->input[14];
+ x[15] = s->input[15];
+
+ for(i = rounds; i > 0; i -= 2) {
+ x[4] ^= ROTATE( x[0]+x[12], 7);
+ x[8] ^= ROTATE( x[4]+ x[0], 9);
+ x[12] ^= ROTATE( x[8]+ x[4],13);
+ x[0] ^= ROTATE(x[12]+ x[8],18);
+ x[9] ^= ROTATE( x[5]+ x[1], 7);
+ x[13] ^= ROTATE( x[9]+ x[5], 9);
+ x[1] ^= ROTATE(x[13]+ x[9],13);
+ x[5] ^= ROTATE( x[1]+x[13],18);
+ x[14] ^= ROTATE(x[10]+ x[6], 7);
+ x[2] ^= ROTATE(x[14]+x[10], 9);
+ x[6] ^= ROTATE( x[2]+x[14],13);
+ x[10] ^= ROTATE( x[6]+ x[2],18);
+ x[3] ^= ROTATE(x[15]+x[11], 7);
+ x[7] ^= ROTATE( x[3]+x[15], 9);
+ x[11] ^= ROTATE( x[7]+ x[3],13);
+ x[15] ^= ROTATE(x[11]+ x[7],18);
+ x[1] ^= ROTATE( x[0]+ x[3], 7);
+ x[2] ^= ROTATE( x[1]+ x[0], 9);
+ x[3] ^= ROTATE( x[2]+ x[1],13);
+ x[0] ^= ROTATE( x[3]+ x[2],18);
+ x[6] ^= ROTATE( x[5]+ x[4], 7);
+ x[7] ^= ROTATE( x[6]+ x[5], 9);
+ x[4] ^= ROTATE( x[7]+ x[6],13);
+ x[5] ^= ROTATE( x[4]+ x[7],18);
+ x[11] ^= ROTATE(x[10]+ x[9], 7);
+ x[8] ^= ROTATE(x[11]+x[10], 9);
+ x[9] ^= ROTATE( x[8]+x[11],13);
+ x[10] ^= ROTATE( x[9]+ x[8],18);
+ x[12] ^= ROTATE(x[15]+x[14], 7);
+ x[13] ^= ROTATE(x[12]+x[15], 9);
+ x[14] ^= ROTATE(x[13]+x[12],13);
+ x[15] ^= ROTATE(x[14]+x[13],18);
+ }
+
+#ifdef FULL_UNROLL
+ ENCRYPT(src+0*4, x[0], s->input[0], dst+0*4);
+ ENCRYPT(src+1*4, x[1], s->input[1], dst+1*4);
+ ENCRYPT(src+2*4, x[2], s->input[2], dst+2*4);
+ ENCRYPT(src+3*4, x[3], s->input[3], dst+3*4);
+ ENCRYPT(src+4*4, x[4], s->input[4], dst+4*4);
+ ENCRYPT(src+5*4, x[5], s->input[5], dst+5*4);
+ ENCRYPT(src+6*4, x[6], s->input[6], dst+6*4);
+ ENCRYPT(src+7*4, x[7], s->input[7], dst+7*4);
+ ENCRYPT(src+8*4, x[8], s->input[8], dst+8*4);
+ ENCRYPT(src+9*4, x[9], s->input[9], dst+9*4);
+ ENCRYPT(src+10*4, x[10], s->input[10], dst+10*4);
+ ENCRYPT(src+11*4, x[11], s->input[11], dst+11*4);
+ ENCRYPT(src+12*4, x[12], s->input[12], dst+12*4);
+ ENCRYPT(src+13*4, x[13], s->input[13], dst+13*4);
+ ENCRYPT(src+14*4, x[14], s->input[14], dst+14*4);
+ ENCRYPT(src+15*4, x[15], s->input[15], dst+15*4);
+#else
+ for(i=0; i<nelem(x); i+=4){
+ ENCRYPT(src, x[i], s->input[i], dst);
+ ENCRYPT(src+4, x[i+1], s->input[i+1], dst+4);
+ ENCRYPT(src+8, x[i+2], s->input[i+2], dst+8);
+ ENCRYPT(src+12, x[i+3], s->input[i+3], dst+12);
+ src += 16;
+ dst += 16;
+ }
+#endif
+
+ if(++s->input[8] == 0)
+ s->input[9]++;
+}
+
+void
+salsa_encrypt2(uchar *src, uchar *dst, ulong bytes, Salsastate *s)
+{
+ uchar tmp[SalsaBsize];
+
+ for(; bytes >= SalsaBsize; bytes -= SalsaBsize){
+ encryptblock(s, src, dst);
+ src += SalsaBsize;
+ dst += SalsaBsize;
+ }
+ if(bytes > 0){
+ memmove(tmp, src, bytes);
+ encryptblock(s, tmp, tmp);
+ memmove(dst, tmp, bytes);
+ }
+}
+
+void
+salsa_encrypt(uchar *buf, ulong bytes, Salsastate *s)
+{
+ salsa_encrypt2(buf, buf, bytes, s);
+}
+
+void
+hsalsa(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds)
+{
+ Salsastate s[1];
+
+ setupSalsastate(s, key, keylen, nonce, 16, rounds);
+ hsalsablock(h, s);
+ memset(s, 0, sizeof(s));
+}
--- /dev/null
+++ b/libsec/secp256k1.c
@@ -1,0 +1,12 @@
+#include <u.h>
+#include <libc.h>
+#include <mp.h>
+void secp256k1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h){
+ strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", nil, 16, p);
+ mpassign(mpzero, a);
+ uitomp(7UL, b);
+ strtomp("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", nil, 16, x);
+ strtomp("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", nil, 16, y);
+ strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", nil, 16, n);
+ mpassign(mpone, h);
+ }
--- /dev/null
+++ b/libsec/secp256r1.c
@@ -1,0 +1,13 @@
+#include <u.h>
+#include <libc.h>
+#include <mp.h>
+void secp256r1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h){
+ strtomp("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", nil, 16, p);
+ uitomp(3UL, a);
+ mpsub(p, a, a);
+ strtomp("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", nil, 16, b);
+ strtomp("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", nil, 16, x);
+ strtomp("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", nil, 16, y);
+ strtomp("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", nil, 16, n);
+ mpassign(mpone, h);
+ }
--- a/libsec/sha1.c
+++ b/libsec/sha1.c
@@ -125,3 +125,10 @@
*output++ = x;
}
}
+
+DigestState*
+hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
+}
--- /dev/null
+++ b/libsec/sha2_128.c
@@ -1,0 +1,191 @@
+/*
+ * sha2 128-bit
+ */
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+static void encode64(uchar*, u64int*, ulong);
+static DigestState* sha2_128(uchar *, ulong, uchar *, SHA2_256state *, int);
+
+extern void _sha2block128(uchar*, ulong, u64int*);
+
+/*
+ * for sha2_384 and sha2_512, len must be multiple of 128 for all but
+ * the last call. There must be room in the input buffer to pad.
+ *
+ * Note: sha2_384 calls sha2_512block as sha2_384; it just uses a different
+ * initial seed to produce a truncated 384b hash result. otherwise
+ * it's the same as sha2_512.
+ */
+SHA2_384state*
+sha2_384(uchar *p, ulong len, uchar *digest, SHA2_384state *s)
+{
+ if(s == nil) {
+ s = mallocz(sizeof(*s), 1);
+ if(s == nil)
+ return nil;
+ s->malloced = 1;
+ }
+ if(s->seeded == 0){
+ /*
+ * seed the state with the first 64 bits of the fractional
+ * parts of the square roots of the 9th thru 16th primes.
+ */
+ s->bstate[0] = 0xcbbb9d5dc1059ed8LL;
+ s->bstate[1] = 0x629a292a367cd507LL;
+ s->bstate[2] = 0x9159015a3070dd17LL;
+ s->bstate[3] = 0x152fecd8f70e5939LL;
+ s->bstate[4] = 0x67332667ffc00b31LL;
+ s->bstate[5] = 0x8eb44a8768581511LL;
+ s->bstate[6] = 0xdb0c2e0d64f98fa7LL;
+ s->bstate[7] = 0x47b5481dbefa4fa4LL;
+ s->seeded = 1;
+ }
+ return sha2_128(p, len, digest, s, SHA2_384dlen);
+}
+
+SHA2_512state*
+sha2_512(uchar *p, ulong len, uchar *digest, SHA2_512state *s)
+{
+
+ if(s == nil) {
+ s = mallocz(sizeof(*s), 1);
+ if(s == nil)
+ return nil;
+ s->malloced = 1;
+ }
+ if(s->seeded == 0){
+ /*
+ * seed the state with the first 64 bits of the fractional
+ * parts of the square roots of the first 8 primes 2..19).
+ */
+ s->bstate[0] = 0x6a09e667f3bcc908LL;
+ s->bstate[1] = 0xbb67ae8584caa73bLL;
+ s->bstate[2] = 0x3c6ef372fe94f82bLL;
+ s->bstate[3] = 0xa54ff53a5f1d36f1LL;
+ s->bstate[4] = 0x510e527fade682d1LL;
+ s->bstate[5] = 0x9b05688c2b3e6c1fLL;
+ s->bstate[6] = 0x1f83d9abfb41bd6bLL;
+ s->bstate[7] = 0x5be0cd19137e2179LL;
+ s->seeded = 1;
+ }
+ return sha2_128(p, len, digest, s, SHA2_512dlen);
+}
+
+/* common 128 byte block padding and count code for SHA2_384 and SHA2_512 */
+static DigestState*
+sha2_128(uchar *p, ulong len, uchar *digest, SHA2_512state *s, int dlen)
+{
+ int i;
+ u64int x[16];
+ uchar buf[256];
+ uchar *e;
+
+ /* fill out the partial 128 byte block from previous calls */
+ if(s->blen){
+ i = 128 - s->blen;
+ if(len < i)
+ i = len;
+ memmove(s->buf + s->blen, p, i);
+ len -= i;
+ s->blen += i;
+ p += i;
+ if(s->blen == 128){
+ _sha2block128(s->buf, s->blen, s->bstate);
+ s->len += s->blen;
+ s->blen = 0;
+ }
+ }
+
+ /* do 128 byte blocks */
+ i = len & ~(128-1);
+ if(i){
+ _sha2block128(p, i, s->bstate);
+ s->len += i;
+ len -= i;
+ p += i;
+ }
+
+ /* save the left overs if not last call */
+ if(digest == 0){
+ if(len){
+ memmove(s->buf, p, len);
+ s->blen += len;
+ }
+ return s;
+ }
+
+ /*
+ * this is the last time through, pad what's left with 0x80,
+ * 0's, and the input count to create a multiple of 128 bytes.
+ */
+ if(s->blen){
+ p = s->buf;
+ len = s->blen;
+ } else {
+ memmove(buf, p, len);
+ p = buf;
+ }
+ s->len += len;
+ e = p + len;
+ if(len < 112)
+ i = 112 - len;
+ else
+ i = 240 - len;
+ memset(e, 0, i);
+ *e = 0x80;
+ len += i;
+
+ /* append the count */
+ x[0] = 0; /* assume 32b length, i.e. < 4GB */
+ x[1] = s->len<<3;
+ encode64(p+len, x, 16);
+
+ /* digest the last part */
+ _sha2block128(p, len+16, s->bstate);
+ s->len += len+16;
+
+ /* return result and free state */
+ encode64(digest, s->bstate, dlen);
+ if(s->malloced == 1)
+ free(s);
+ return nil;
+}
+
+/*
+ * Encodes input (ulong long) into output (uchar).
+ * Assumes len is a multiple of 8.
+ */
+static void
+encode64(uchar *output, u64int *input, ulong len)
+{
+ u64int x;
+ uchar *e;
+
+ for(e = output + len; output < e;) {
+ x = *input++;
+ *output++ = x >> 56;
+ *output++ = x >> 48;
+ *output++ = x >> 40;
+ *output++ = x >> 32;
+ *output++ = x >> 24;
+ *output++ = x >> 16;
+ *output++ = x >> 8;
+ *output++ = x;
+ }
+}
+
+DigestState*
+hmac_sha2_384(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, sha2_384, SHA2_384dlen);
+}
+
+DigestState*
+hmac_sha2_512(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, sha2_512, SHA2_512dlen);
+}
--- /dev/null
+++ b/libsec/sha2_64.c
@@ -1,0 +1,187 @@
+/*
+ * sha2 64-bit
+ */
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+static void encode32(uchar*, u32int*, ulong);
+static DigestState* sha2_64(uchar *, ulong, uchar *, SHA2_256state *, int);
+
+extern void _sha2block64(uchar*, ulong, u32int*);
+
+/*
+ * for sha2_224 and sha2_256, len must be multiple of 64 for all but
+ * the last call. There must be room in the input buffer to pad.
+ *
+ * Note: sha2_224 calls sha2_256block as sha2_224, just uses different
+ * initial seed and produces a 224b hash result. otherwise it's
+ * the same as sha2_256.
+ */
+
+SHA2_224state*
+sha2_224(uchar *p, ulong len, uchar *digest, SHA2_224state *s)
+{
+ if(s == nil) {
+ s = mallocz(sizeof(*s), 1);
+ if(s == nil)
+ return nil;
+ s->malloced = 1;
+ }
+ if(s->seeded == 0){
+ /*
+ * seed the state with the first 32 bits of the fractional
+ * parts of the square roots of the first 8 primes 2..19).
+ */
+ s->state[0] = 0xc1059ed8;
+ s->state[1] = 0x367cd507;
+ s->state[2] = 0x3070dd17;
+ s->state[3] = 0xf70e5939;
+ s->state[4] = 0xffc00b31;
+ s->state[5] = 0x68581511;
+ s->state[6] = 0x64f98fa7;
+ s->state[7] = 0xbefa4fa4;
+ s->seeded = 1;
+ }
+ return sha2_64(p, len, digest, s, SHA2_224dlen);
+}
+
+SHA2_256state*
+sha2_256(uchar *p, ulong len, uchar *digest, SHA2_256state *s)
+{
+ if(s == nil) {
+ s = mallocz(sizeof(*s), 1);
+ if(s == nil)
+ return nil;
+ s->malloced = 1;
+ }
+ if(s->seeded == 0){
+ /*
+ * seed the state with the first 32 bits of the fractional
+ * parts of the square roots of the first 8 primes 2..19).
+ */
+ s->state[0] = 0x6a09e667;
+ s->state[1] = 0xbb67ae85;
+ s->state[2] = 0x3c6ef372;
+ s->state[3] = 0xa54ff53a;
+ s->state[4] = 0x510e527f;
+ s->state[5] = 0x9b05688c;
+ s->state[6] = 0x1f83d9ab;
+ s->state[7] = 0x5be0cd19;
+ s->seeded = 1;
+ }
+ return sha2_64(p, len, digest, s, SHA2_256dlen);
+}
+
+/* common 64 byte block padding and count code for SHA2_224 and SHA2_256 */
+static DigestState*
+sha2_64(uchar *p, ulong len, uchar *digest, SHA2_256state *s, int dlen)
+{
+ int i;
+ u32int x[16];
+ uchar buf[128];
+ uchar *e;
+
+ /* fill out the partial 64 byte block from previous calls */
+ if(s->blen){
+ i = 64 - s->blen;
+ if(len < i)
+ i = len;
+ memmove(s->buf + s->blen, p, i);
+ len -= i;
+ s->blen += i;
+ p += i;
+ if(s->blen == 64){
+ _sha2block64(s->buf, s->blen, s->state);
+ s->len += s->blen;
+ s->blen = 0;
+ }
+ }
+
+ /* do 64 byte blocks */
+ i = len & ~(64-1);
+ if(i){
+ _sha2block64(p, i, s->state);
+ s->len += i;
+ len -= i;
+ p += i;
+ }
+
+ /* save the left overs if not last call */
+ if(digest == 0){
+ if(len){
+ memmove(s->buf, p, len);
+ s->blen += len;
+ }
+ return s;
+ }
+
+ /*
+ * this is the last time through, pad what's left with 0x80,
+ * 0's, and the input count to create a multiple of 64 bytes.
+ */
+ if(s->blen){
+ p = s->buf;
+ len = s->blen;
+ } else {
+ memmove(buf, p, len);
+ p = buf;
+ }
+ s->len += len;
+ e = p + len;
+ if(len < 56)
+ i = 56 - len;
+ else
+ i = 120 - len;
+ memset(e, 0, i);
+ *e = 0x80;
+ len += i;
+
+ /* append the count */
+ x[0] = s->len>>29;
+ x[1] = s->len<<3;
+ encode32(p+len, x, 8);
+
+ /* digest the last part */
+ _sha2block64(p, len+8, s->state);
+ s->len += len+8;
+
+ /* return result and free state */
+ encode32(digest, s->state, dlen);
+ if(s->malloced == 1)
+ free(s);
+ return nil;
+}
+
+/*
+ * Encodes input (ulong) into output (uchar).
+ * Assumes len is a multiple of 4.
+ */
+static void
+encode32(uchar *output, u32int *input, ulong len)
+{
+ u32int x;
+ uchar *e;
+
+ for(e = output + len; output < e;) {
+ x = *input++;
+ *output++ = x >> 24;
+ *output++ = x >> 16;
+ *output++ = x >> 8;
+ *output++ = x;
+ }
+}
+
+DigestState*
+hmac_sha2_224(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, sha2_224, SHA2_224dlen);
+}
+
+DigestState*
+hmac_sha2_256(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
+ DigestState *s)
+{
+ return hmac_x(p, len, key, klen, digest, s, sha2_256, SHA2_256dlen);
+}
--- /dev/null
+++ b/libsec/sha2block128.c
@@ -1,0 +1,101 @@
+/*
+ * sha2_512 block cipher
+ *
+ * Implementation straight from Federal Information Processing Standards
+ * publication 180-2 (+Change Notice to include SHA-224) August 1, 2002
+ * note: the following upper and lower case macro names are distinct
+ * and reflect the functions defined in FIPS pub. 180-2.
+ */
+#include <u.h>
+#include <libc.h>
+
+#define ROTR(x,n) (((x) >> (n)) | ((x) << (64-(n))))
+#define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x) >> 7))
+#define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x) >> 6))
+#define SIGMA0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+#define SIGMA1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/*
+ * first 64 bits of the fractional parts of cube roots of
+ * first 80 primes (2..311).
+ */
+static u64int K512[80] = {
+ 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL, 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
+ 0x3956c25bf348b538LL, 0x59f111f1b605d019LL, 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
+ 0xd807aa98a3030242LL, 0x12835b0145706fbeLL, 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
+ 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL, 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
+ 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL, 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
+ 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL, 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
+ 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL, 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
+ 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL, 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
+ 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL, 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
+ 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL, 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
+ 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL, 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
+ 0xd192e819d6ef5218LL, 0xd69906245565a910LL, 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
+ 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL, 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
+ 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL, 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
+ 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL, 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
+ 0x90befffa23631e28LL, 0xa4506cebde82bde9LL, 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
+ 0xca273eceea26619cLL, 0xd186b8c721c0c207LL, 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
+ 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL, 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
+ 0x28db77f523047d84LL, 0x32caab7b40c72493LL, 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
+ 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL, 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL };
+
+void
+_sha2block128(uchar *p, ulong len, u64int *s)
+{
+ u64int a, b, c, d, e, f, g, h, t1, t2;
+ u64int *kp, *wp;
+ u64int w[80];
+ uchar *end;
+
+ /* at this point, we have a multiple of 64 bytes */
+ for(end = p+len; p < end;){
+ a = s[0];
+ b = s[1];
+ c = s[2];
+ d = s[3];
+ e = s[4];
+ f = s[5];
+ g = s[6];
+ h = s[7];
+
+ for(wp = w; wp < &w[16]; wp++, p += 8)
+ wp[0] = ((vlong)p[0])<<56 | ((vlong)p[1])<<48 |
+ ((vlong)p[2])<<40 | ((vlong)p[3])<<32 |
+ p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7];
+ for(; wp < &w[80]; wp++) {
+ u64int s0, s1;
+
+ s0 = sigma0(wp[-15]);
+ s1 = sigma1(wp[-2]);
+// wp[0] = sigma1(wp[-2]) + wp[-7] + sigma0(wp[-15]) + wp[-16];
+ wp[0] = s1 + wp[-7] + s0 + wp[-16];
+ }
+
+ for(kp = K512, wp = w; wp < &w[80]; ) {
+ t1 = h + SIGMA1(e) + Ch(e,f,g) + *kp++ + *wp++;
+ t2 = SIGMA0(a) + Maj(a,b,c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2;
+ }
+
+ /* save state */
+ s[0] += a;
+ s[1] += b;
+ s[2] += c;
+ s[3] += d;
+ s[4] += e;
+ s[5] += f;
+ s[6] += g;
+ s[7] += h;
+ }
+}
--- /dev/null
+++ b/libsec/sha2block64.c
@@ -1,0 +1,92 @@
+/*
+ * sha2_256 block cipher
+ *
+ * Implementation straight from Federal Information Processing Standards
+ * publication 180-2 (+Change Notice to include SHA-224) August 1, 2002
+ * note: the following upper and lower case macro names are distinct
+ * and reflect the functions defined in FIPS pub. 180-2.
+ */
+
+#include <u.h>
+#include <libc.h>
+
+#define ROTR(x,n) (((x) >> (n)) | ((x) << (32-(n))))
+#define sigma0(x) (ROTR((x),7) ^ ROTR((x),18) ^ ((x) >> 3))
+#define sigma1(x) (ROTR((x),17) ^ ROTR((x),19) ^ ((x) >> 10))
+#define SIGMA0(x) (ROTR((x),2) ^ ROTR((x),13) ^ ROTR((x),22))
+#define SIGMA1(x) (ROTR((x),6) ^ ROTR((x),11) ^ ROTR((x),25))
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/*
+ * first 32 bits of the fractional parts of cube roots of
+ * first 64 primes (2..311).
+ */
+static u32int K256[64] = {
+ 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
+ 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
+ 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
+ 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
+ 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
+ 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
+ 0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
+ 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
+ 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2,
+};
+
+void
+_sha2block64(uchar *p, ulong len, u32int *s)
+{
+ u32int a, b, c, d, e, f, g, h, t1, t2;
+ u32int *kp, *wp;
+ u32int w[64];
+ uchar *end;
+
+ /* at this point, we have a multiple of 64 bytes */
+ for(end = p+len; p < end;){
+ a = s[0];
+ b = s[1];
+ c = s[2];
+ d = s[3];
+ e = s[4];
+ f = s[5];
+ g = s[6];
+ h = s[7];
+
+ for(wp = w; wp < &w[16]; wp++, p += 4)
+ wp[0] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ for(; wp < &w[64]; wp++)
+ wp[0] = sigma1(wp[-2]) + wp[-7] +
+ sigma0(wp[-15]) + wp[-16];
+
+ for(kp = K256, wp = w; wp < &w[64]; ) {
+ t1 = h + SIGMA1(e) + Ch(e,f,g) + *kp++ + *wp++;
+ t2 = SIGMA0(a) + Maj(a,b,c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2;
+ }
+
+ /* save state */
+ s[0] += a;
+ s[1] += b;
+ s[2] += c;
+ s[3] += d;
+ s[4] += e;
+ s[5] += f;
+ s[6] += g;
+ s[7] += h;
+ }
+}
--- a/libsec/smallprimetest.c
+++ /dev/null
@@ -1,1039 +1,0 @@
-#include "os.h"
-#include <mp.h>
-#include <libsec.h>
-
-static ulong smallprimes[] = {
- 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
- 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
- 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
- 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
- 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
- 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
- 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
- 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
- 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
- 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
- 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
- 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
- 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
- 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
- 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
- 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
- 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
- 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
- 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
- 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
- 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
- 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
- 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
- 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
- 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
- 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
- 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
- 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
- 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
- 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
- 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
- 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
- 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
- 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
- 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
- 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
- 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
- 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
- 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
- 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
- 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
- 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
- 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
- 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
- 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
- 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
- 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
- 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
- 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
- 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
- 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
- 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
- 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
- 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
- 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
- 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
- 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
- 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
- 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
- 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
- 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
- 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
- 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
- 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
- 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
- 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
- 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
- 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
- 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
- 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
- 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
- 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
- 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
- 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
- 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
- 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
- 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
- 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
- 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
- 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
- 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
- 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
- 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
- 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
- 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
- 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
- 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
- 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
- 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
- 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
- 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
- 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
- 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
- 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
- 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
- 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
- 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
- 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
- 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
- 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
- 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
- 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
- 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
- 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
- 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
- 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
- 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
- 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
- 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
- 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
- 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
- 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
- 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
- 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
- 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
- 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
- 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
- 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
- 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
- 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
- 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
- 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007,
- 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
- 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177,
- 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,
- 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343,
- 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
- 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567,
- 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657,
- 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
- 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
- 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949,
- 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059,
- 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,
- 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
- 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329,
- 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443,
- 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527,
- 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
- 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777,
- 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
- 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
- 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
- 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109,
- 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211,
- 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289,
- 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
- 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487,
- 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553,
- 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641,
- 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
- 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
- 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
- 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007,
- 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
- 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187,
- 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309,
- 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411,
- 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
- 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619,
- 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,
- 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781,
- 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
- 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
- 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081,
- 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197,
- 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
- 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419,
- 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519,
- 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,
- 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
- 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767,
- 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851,
- 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
- 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
- 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149,
- 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259,
- 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319,
- 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
- 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497,
- 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607,
- 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679,
- 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
- 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881,
- 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
- 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
- 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
- 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,
- 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381,
- 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481,
- 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
- 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691,
- 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811,
- 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903,
- 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
- 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
- 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
- 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317,
- 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
- 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477,
- 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573,
- 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669,
- 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
- 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891,
- 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971,
- 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059,
- 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
- 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233,
- 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313,
- 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427,
- 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517,
- 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637,
- 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749,
- 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899,
- 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009,
- 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121,
- 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219,
- 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
- 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423,
- 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477,
- 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571,
- 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699,
- 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793,
- 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891,
- 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991,
- 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071,
- 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149,
- 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261,
- 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
- 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443,
- 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551,
- 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693,
- 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771,
- 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897,
- 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983,
- 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067,
- 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169,
- 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277,
- 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383,
- 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
- 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563,
- 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647,
- 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751,
- 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841,
- 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943,
- 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039,
- 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123,
- 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229,
- 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307,
- 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441,
- 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
- 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643,
- 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727,
- 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817,
- 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943,
- 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029,
- 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099,
- 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203,
- 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321,
- 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447,
- 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561,
- 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
- 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743,
- 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827,
- 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909,
- 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007,
- 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091,
- 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169,
- 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281,
- 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413,
- 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517,
- 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659,
- 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
- 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877,
- 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977,
- 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097,
- 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183,
- 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303,
- 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391,
- 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471,
- 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603,
- 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693,
- 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799,
- 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
- 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999,
- 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111,
- 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203,
- 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297,
- 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399,
- 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497,
- 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633,
- 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711,
- 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801,
- 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891,
- 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
- 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077,
- 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211,
- 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329,
- 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449,
- 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551,
- 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691,
- 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767,
- 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827,
- 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947,
- 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051,
- 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
- 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283,
- 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403,
- 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499,
- 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579,
- 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649,
- 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729,
- 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837,
- 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933,
- 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059,
- 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167,
- 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
- 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363,
- 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443,
- 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573,
- 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671,
- 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819,
- 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921,
- 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059,
- 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137,
- 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241,
- 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341,
- 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
- 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559,
- 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689,
- 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803,
- 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871,
- 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983,
- 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091,
- 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183,
- 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259,
- 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357,
- 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511,
- 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
- 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721,
- 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817,
- 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973,
- 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063,
- 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159,
- 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257,
- 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353,
- 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423,
- 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531,
- 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609,
- 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
- 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831,
- 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939,
- 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023,
- 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113,
- 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211,
- 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343,
- 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427,
- 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533,
- 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613,
- 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713,
- 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
- 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893,
- 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031,
- 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157,
- 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261,
- 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337,
- 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457,
- 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537,
- 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649,
- 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739,
- 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847,
- 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
- 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083,
- 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159,
- 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291,
- 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401,
- 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509,
- 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593,
- 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759,
- 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863,
- 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969,
- 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061,
- 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
- 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277,
- 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383,
- 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497,
- 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587,
- 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691,
- 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781,
- 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877,
- 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947,
- 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057,
- 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189,
- 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
- 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397,
- 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507,
- 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573,
- 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663,
- 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813,
- 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951,
- 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047,
- 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183,
- 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281,
- 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371,
- 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
- 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639,
- 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713,
- 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821,
- 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921,
- 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041,
- 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133,
- 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227,
- 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323,
- 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419,
- 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541,
- 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
- 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769,
- 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857,
- 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971,
- 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087,
- 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169,
- 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283,
- 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433,
- 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531,
- 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639,
- 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787,
- 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
- 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973,
- 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081,
- 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183,
- 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257,
- 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387,
- 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507,
- 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603,
- 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669,
- 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801,
- 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897,
- 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
- 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073,
- 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187,
- 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283,
- 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379,
- 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457,
- 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557,
- 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677,
- 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743,
- 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841,
- 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953,
- 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
- 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189,
- 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319,
- 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451,
- 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579,
- 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661,
- 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783,
- 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933,
- 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017,
- 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101,
- 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201,
- 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
- 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449,
- 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537,
- 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641,
- 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741,
- 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843,
- 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953,
- 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077,
- 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181,
- 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307,
- 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403,
- 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
- 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641,
- 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757,
- 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853,
- 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979,
- 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099,
- 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199,
- 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309,
- 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447,
- 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549,
- 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643,
- 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
- 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831,
- 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993,
- 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119,
- 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221,
- 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317,
- 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419,
- 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527,
- 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629,
- 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717,
- 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819,
- 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
- 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049,
- 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179,
- 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299,
- 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409,
- 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497,
- 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611,
- 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733,
- 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817,
- 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907,
- 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033,
- 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
- 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211,
- 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339,
- 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433,
- 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537,
- 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663,
- 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757,
- 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853,
- 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957,
- 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069,
- 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147,
- 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273,
- 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377,
- 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503,
- 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593,
- 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753,
- 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867,
- 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971,
- 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109,
- 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203,
- 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329,
- 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421,
- 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487,
- 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593,
- 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683,
- 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803,
- 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899,
- 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009,
- 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127,
- 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237,
- 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361,
- 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501,
- 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579,
- 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709,
- 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813,
- 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919,
- 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017,
- 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117,
- 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231,
- 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327,
- 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441,
- 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593,
- 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657,
- 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783,
- 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
- 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993,
- 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121,
- 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269,
- 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367,
- 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443,
- 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541,
- 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629,
- 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751,
- 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877,
- 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983,
- 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103,
- 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217,
- 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337,
- 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457,
- 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603,
- 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673,
- 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793,
- 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849,
- 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949,
- 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087,
- 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179,
- 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299,
- 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431,
- 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503,
- 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599,
- 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711,
- 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809,
- 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909,
- 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989,
- 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097,
- 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191,
- 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283,
- 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389,
- 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529,
- 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653,
- 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737,
- 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839,
- 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947,
- 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061,
- 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169,
- 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237,
- 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379,
- 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453,
- 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601,
- 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711,
- 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889,
- 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967,
- 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053,
- 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141,
- 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233,
- 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359,
- 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443,
- 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557,
- 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659,
- 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747,
- 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887,
- 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029,
- 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127,
- 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251,
- 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353,
- 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497,
- 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623,
- 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719,
- 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811,
- 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919,
- 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043,
- 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169,
- 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333,
- 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441,
- 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543,
- 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631,
- 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717,
- 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861,
- 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981,
- 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071,
- 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189,
- 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303,
- 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459,
- 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549,
- 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653,
- 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773,
- 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903,
- 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989,
- 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127,
- 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281,
- 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367,
- 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463,
- 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559,
- 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647,
- 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719,
- 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809,
- 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929,
- 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067,
- 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189,
- 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319,
- 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453,
- 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601,
- 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693,
- 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
- 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937,
- 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063,
- 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147,
- 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267,
- 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381,
- 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497,
- 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581,
- 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677,
- 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761,
- 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867,
- 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983,
- 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103,
- 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239,
- 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377,
- 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499,
- 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593,
- 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721,
- 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841,
- 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943,
- 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049,
- 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153,
- 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231,
- 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369,
- 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453,
- 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547,
- 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651,
- 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763,
- 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867,
- 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961,
- 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087,
- 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213,
- 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371,
- 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489,
- 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597,
- 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713,
- 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819,
- 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917,
- 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061,
- 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191,
- 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263,
- 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403,
- 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493,
- 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691,
- 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821,
- 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929,
- 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039,
- 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139,
- 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223,
- 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321,
- 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451,
- 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549,
- 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657,
- 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793,
- 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901,
- 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981,
- 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089,
- 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209,
- 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327,
- 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389,
- 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473,
- 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593,
- 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713,
- 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843,
- 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933,
- 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031,
- 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109,
- 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229,
- 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341,
- 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481,
- 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617,
- 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701,
- 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823,
- 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923,
- 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013,
- 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127,
- 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303,
- 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417,
- 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529,
- 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613,
- 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721,
- 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859,
- 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973,
- 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099,
- 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197,
- 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297,
- 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411,
- 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521,
- 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611,
- 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731,
- 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843,
- 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929,
- 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079,
- 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209,
- 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307,
- 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401,
- 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533,
- 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619,
- 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709,
- 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821,
- 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979,
- 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081,
- 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207,
- 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303,
- 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441,
- 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541,
- 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667,
- 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781,
- 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907,
- 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023,
- 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153,
- 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261,
- 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351,
- 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477,
- 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551,
- 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641,
- 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723,
- 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839,
- 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977,
- 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101,
- 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193,
- 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311,
- 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479,
- 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571,
- 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697,
- 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803,
- 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901,
- 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063,
- 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181,
- 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283,
- 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393,
- 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531,
- 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621,
- 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699,
- 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841,
- 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939,
- 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051,
- 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173,
- 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263,
- 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369,
- 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513,
- 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629,
- 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713,
- 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809,
- 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923,
- 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023,
- 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101,
- 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223,
- 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349,
- 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463,
- 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569,
- 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689,
- 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799,
- 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929,
- 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009,
- 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139,
- 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219,
- 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339,
- 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469,
- 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559,
- 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651,
- 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781,
- 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891,
- 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047,
- 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177,
- 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267,
- 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399,
- 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471,
- 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609,
- 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719,
- 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869,
- 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987,
- 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127,
- 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221,
- 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319,
- 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437,
- 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521,
- 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659,
- 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761,
- 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913,
- 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027,
- 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121,
- 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237,
- 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363,
- 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469,
- 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601,
- 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691,
- 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829,
- 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933,
- 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111,
- 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197,
- 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291,
- 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371,
- 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477,
- 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587,
- 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743,
- 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861,
- 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993,
- 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119,
- 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223,
- 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323,
- 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473,
- 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553,
- 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641,
- 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721,
- 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853,
- 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961,
- 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079,
- 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259,
- 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411,
- 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547,
- 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667,
- 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801,
- 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873,
- 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003,
- 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087,
- 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209,
- 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317,
- 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431,
- 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527,
- 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627,
- 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759,
- 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849,
- 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963,
- 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031,
- 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149,
- 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239,
- 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373,
- 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481,
- 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617,
- 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709,
- 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847,
- 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977,
- 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121,
- 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193,
- 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303,
- 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411,
- 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529,
- 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673,
- 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807,
- 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939,
- 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033,
- 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173,
- 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243,
- 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363,
- 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431,
- 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567,
- 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669,
- 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753,
- 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849,
- 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951,
- 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083,
- 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179,
- 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281,
- 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383,
- 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497,
- 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607,
- 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787,
- 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911,
- 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997,
- 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111,
- 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253,
- 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349,
- 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447,
- 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559,
- 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687,
- 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793,
- 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903,
- 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021,
- 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111,
- 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231,
- 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317,
- 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441,
- 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539,
- 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633,
- 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773,
- 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873,
- 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971,
- 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097,
- 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223,
- 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331,
- 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461,
- 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581,
- 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731,
- 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799,
- 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931,
- 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021,
- 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169,
- 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303,
- 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429,
- 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549,
- 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649,
- 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813,
- 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883,
- 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011,
- 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179,
- 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317,
- 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411,
- 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507,
- 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639,
- 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737,
- 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873,
- 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947,
- 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053,
- 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139,
- 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259,
- 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397,
- 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529,
- 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643,
- 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733,
- 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839,
- 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971,
- 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109,
- 100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237,
- 100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361,
- 100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469,
- 100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549,
- 100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699,
- 100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823,
- 100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957,
- 100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089,
- 101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173,
- 101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281,
- 101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383,
- 101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501,
- 101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599,
- 101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719,
- 101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833,
- 101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929,
- 101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023,
- 102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107,
- 102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217,
- 102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317,
- 102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451,
- 102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551,
- 102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667,
- 102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811,
- 102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931,
- 102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079,
- 103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217,
- 103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387,
- 103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483,
- 103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591,
- 103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703,
- 103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867,
- 103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981,
- 103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059,
- 104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173,
- 104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297,
- 104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399,
- 104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543,
- 104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659,
- 104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729,
-};
-
-// return 1 if p is divisable by sp, 0 otherwise
-static int
-divides(mpint *dividend, ulong divisor)
-{
- mpdigit d[2], q;
- int i;
-
- d[1] = 0;
- for(i = dividend->top-1; i >= 0; i--){
- d[0] = dividend->p[i];
- mpdigdiv(d, divisor, &q);
- d[1] = d[0] - divisor*q;
- }
- return d[1] == 0;
-}
-
-// return -1 if p is divisable by one of the small primes, 0 otherwise
-int
-smallprimetest(mpint *p)
-{
- int i;
- ulong sp;
-
- for(i = 0; i < nelem(smallprimes); i++){
- sp = smallprimes[i];
- if(p->top == 1 && p->p[0] <= sp)
- break;
- if(divides(p, sp))
- return -1;
- }
- return 0;
-}
--- a/libsec/thumb.c
+++ b/libsec/thumb.c
@@ -7,18 +7,10 @@
enum{ ThumbTab = 1<<10 };
-static void *
-emalloc(int n)
+static Thumbprint*
+tablehead(uchar *sum, Thumbprint *table)
{
- void *p;
- if(n==0)
- n=1;
- p = malloc(n);
- if(p == nil){
- exits("out of memory");
- }
- memset(p, 0, n);
- return p;
+ return &table[((sum[0]<<8) + sum[1]) & (ThumbTab-1)];
}
void
@@ -25,8 +17,11 @@
freeThumbprints(Thumbprint *table)
{
Thumbprint *hd, *p, *q;
+
+ if(table == nil)
+ return;
for(hd = table; hd < table+ThumbTab; hd++){
- for(p = hd->next; p; p = q){
+ for(p = hd->next; p && p != hd; p = q){
q = p->next;
free(p);
}
@@ -37,61 +32,89 @@
int
okThumbprint(uchar *sum, Thumbprint *table)
{
- Thumbprint *p;
- int i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1);
+ Thumbprint *hd, *p;
- for(p = table[i].next; p; p = p->next)
+ if(table == nil)
+ return 0;
+ hd = tablehead(sum, table);
+ for(p = hd->next; p; p = p->next){
if(memcmp(sum, p->sha1, SHA1dlen) == 0)
return 1;
+ if(p == hd)
+ break;
+ }
return 0;
}
-static void
+static int
loadThumbprints(char *file, Thumbprint *table, Thumbprint *crltab)
{
- Thumbprint *entry;
- Biobuf *bin;
+ Thumbprint *hd, *entry;
char *line, *field[50];
uchar sum[SHA1dlen];
- int i;
+ Biobuf *bin;
- bin = Bopen(file, OREAD);
- if(bin == nil)
- return;
- for(; (line = Brdstr(bin, '\n', 1)) != 0; free(line)){
+ if(access(file, AEXIST) < 0)
+ return 0; /* not an error */
+ if((bin = Bopen(file, OREAD)) == nil)
+ return -1;
+ for(; (line = Brdstr(bin, '\n', 1)) != nil; free(line)){
if(tokenize(line, field, nelem(field)) < 2)
continue;
if(strcmp(field[0], "#include") == 0){
- loadThumbprints(field[1], table, crltab);
+ if(loadThumbprints(field[1], table, crltab) < 0)
+ goto err;
continue;
}
- if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", strlen("sha1=")) != 0)
+ if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", 5) != 0)
continue;
- field[1] += strlen("sha1=");
- dec16(sum, sizeof(sum), field[1], strlen(field[1]));
+ field[1] += 5;
+ if(dec16(sum, SHA1dlen, field[1], strlen(field[1])) != SHA1dlen){
+ werrstr("malformed x509 entry in %s: %s", file, field[1]);
+ goto err;
+ }
if(crltab && okThumbprint(sum, crltab))
continue;
- entry = (Thumbprint*)emalloc(sizeof(*entry));
+ hd = tablehead(sum, table);
+ if(hd->next == nil)
+ entry = hd;
+ else {
+ if((entry = malloc(sizeof(*entry))) == nil)
+ goto err;
+ entry->next = hd->next;
+ }
+ hd->next = entry;
memcpy(entry->sha1, sum, SHA1dlen);
- i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1);
- entry->next = table[i].next;
- table[i].next = entry;
}
Bterm(bin);
+ return 0;
+err:
+ free(line);
+ Bterm(bin);
+ return -1;
}
Thumbprint *
initThumbprints(char *ok, char *crl)
{
- Thumbprint *table, *crltab = nil;
+ Thumbprint *table, *crltab;
+ table = crltab = nil;
if(crl){
- crltab = emalloc(ThumbTab * sizeof(*table));
- loadThumbprints(crl, crltab, nil);
+ if((crltab = malloc(ThumbTab * sizeof(*crltab))) == nil)
+ goto err;
+ memset(crltab, 0, ThumbTab * sizeof(*crltab));
+ if(loadThumbprints(crl, crltab, nil) < 0)
+ goto err;
}
- table = emalloc(ThumbTab * sizeof(*table));
- loadThumbprints(ok, table, crltab);
- free(crltab);
+ if((table = malloc(ThumbTab * sizeof(*table))) == nil)
+ goto err;
+ memset(table, 0, ThumbTab * sizeof(*table));
+ if(loadThumbprints(ok, table, crltab) < 0){
+ freeThumbprints(table);
+ table = nil;
+ }
+err:
+ freeThumbprints(crltab);
return table;
}
-
--- a/libsec/tlshand.c
+++ b/libsec/tlshand.c
@@ -1,6 +1,5 @@
#include <u.h>
#include <libc.h>
-#include <bio.h>
#include <auth.h>
#include <mp.h>
#include <libsec.h>
@@ -17,8 +16,9 @@
enum {
TLSFinishedLen = 12,
SSL3FinishedLen = MD5dlen+SHA1dlen,
- MaxKeyData = 104, // amount of secret we may need
- MaxChunk = 1<<14,
+ MaxKeyData = 160, // amount of secret we may need
+ MaxChunk = 1<<15,
+ MAXdlen = SHA2_512dlen,
RandomSize = 32,
SidSize = 32,
MasterSecretSize = 48,
@@ -46,11 +46,22 @@
int ok;
} Algs;
+typedef struct Namedcurve{
+ int tlsid;
+ void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
+} Namedcurve;
+
typedef struct Finished{
uchar verify[SSL3FinishedLen];
int n;
} Finished;
+typedef struct HandshakeHash {
+ MD5state md5;
+ SHAstate sha1;
+ SHA2_256state sha2_256;
+} HandshakeHash;
+
typedef struct TlsConnection{
TlsSec *sec; // security management goo
int hand, ctl; // record layer file descriptors
@@ -67,19 +78,23 @@
int state; // must be set using setstate
// input buffer for handshake messages
- uchar buf[MaxChunk+2048];
+ uchar recvbuf[MaxChunk];
uchar *rp, *ep;
+ // output buffer
+ uchar sendbuf[MaxChunk];
+ uchar *sendp;
+
uchar crandom[RandomSize]; // client random
uchar srandom[RandomSize]; // server random
int clientVersion; // version in ClientHello
+ int cipher;
char *digest; // name of digest algorithm to use
char *enc; // name of encryption algorithm to use
int nsecret; // amount of secret data to init keys
// for finished messages
- MD5state hsmd5; // handshake hash
- SHAstate hssha1; // handshake hash
+ HandshakeHash handhash;
Finished finished;
} TlsConnection;
@@ -92,13 +107,15 @@
Bytes* sid;
Ints* ciphers;
Bytes* compressors;
+ Bytes* extensions;
} clientHello;
struct {
int version;
- uchar random[RandomSize];
+ uchar random[RandomSize];
Bytes* sid;
- int cipher;
- int compressor;
+ int cipher;
+ int compressor;
+ Bytes* extensions;
} serverHello;
struct {
int ncert;
@@ -106,12 +123,28 @@
} certificate;
struct {
Bytes *types;
+ Ints *sigalgs;
int nca;
Bytes **cas;
} certificateRequest;
struct {
+ Bytes *pskid;
Bytes *key;
} clientKeyExchange;
+ struct {
+ Bytes *pskid;
+ Bytes *dh_p;
+ Bytes *dh_g;
+ Bytes *dh_Ys;
+ Bytes *dh_parameters;
+ Bytes *dh_signature;
+ int sigalg;
+ int curve;
+ } serverKeyExchange;
+ struct {
+ int sigalg;
+ Bytes *signature;
+ } certificateVerify;
Finished finished;
} u;
} Msg;
@@ -118,9 +151,11 @@
typedef struct TlsSec{
char *server; // name of remote; nil for server
- int ok; // <0 killed; ==0 in progress; >0 reusable
+ int ok; // <0 killed; == 0 in progress; >0 reusable
RSApub *rsapub;
AuthRpc *rpc; // factotum for rsa private key
+ uchar *psk; // pre-shared key
+ int psklen;
uchar sec[MasterSecretSize]; // master secret
uchar crandom[RandomSize]; // client random
uchar srandom[RandomSize]; // server random
@@ -128,16 +163,18 @@
int vers; // final version
// byte generation and handshake checksum
void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int);
- void (*setFinished)(TlsSec*, MD5state, SHAstate, uchar*, int);
+ void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
int nfin;
} TlsSec;
enum {
- TLSVersion = 0x0301,
- SSL3Version = 0x0300,
- ProtocolVersion = 0x0301, // maximum version we speak
- MinProtoVersion = 0x0300, // limits on version we accept
+ SSL3Version = 0x0300,
+ TLS10Version = 0x0301,
+ TLS11Version = 0x0302,
+ TLS12Version = 0x0303,
+ ProtocolVersion = TLS12Version, // maximum version we speak
+ MinProtoVersion = 0x0300, // limits on version we accept
MaxProtoVersion = 0x03ff,
};
@@ -183,19 +220,20 @@
EInternalError = 80,
EUserCanceled = 90,
ENoRenegotiation = 100,
+ EUnknownPSKidentity = 115,
EMax = 256
};
// cipher suites
enum {
- TLS_NULL_WITH_NULL_NULL = 0x0000,
- TLS_RSA_WITH_NULL_MD5 = 0x0001,
- TLS_RSA_WITH_NULL_SHA = 0x0002,
- TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003,
- TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
- TLS_RSA_WITH_RC4_128_SHA = 0x0005,
+ TLS_NULL_WITH_NULL_NULL = 0x0000,
+ TLS_RSA_WITH_NULL_MD5 = 0x0001,
+ TLS_RSA_WITH_NULL_SHA = 0x0002,
+ TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003,
+ TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
+ TLS_RSA_WITH_RC4_128_SHA = 0x0005,
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0X0006,
- TLS_RSA_WITH_IDEA_CBC_SHA = 0X0007,
+ TLS_RSA_WITH_IDEA_CBC_SHA = 0X0007,
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X0008,
TLS_RSA_WITH_DES_CBC_SHA = 0X0009,
TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A,
@@ -212,12 +250,11 @@
TLS_DHE_RSA_WITH_DES_CBC_SHA = 0X0015,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016,
TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017,
- TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
+ TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0X0019,
TLS_DH_anon_WITH_DES_CBC_SHA = 0X001A,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0X001B,
-
- TLS_RSA_WITH_AES_128_CBC_SHA = 0X002f, // aes, aka rijndael with 128 bit blocks
+ TLS_RSA_WITH_AES_128_CBC_SHA = 0X002F, // aes, aka rijndael with 128 bit blocks
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0X0030,
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0X0031,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0X0032,
@@ -229,7 +266,25 @@
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0X0038,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039,
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0X003A,
- CipherMax
+ TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C,
+ TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0XC013,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0XC014,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
+
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9,
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA,
+
+ GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13,
+ GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14,
+ GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15,
+
+ TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB,
+ TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
+ TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
};
// compression methods
@@ -239,9 +294,32 @@
};
static Algs cipherAlgs[] = {
- {"rc4_128", "md5", 2 * (16 + MD5dlen), TLS_RSA_WITH_RC4_128_MD5},
- {"rc4_128", "sha1", 2 * (16 + SHA1dlen), TLS_RSA_WITH_RC4_128_SHA},
- {"3des_ede_cbc","sha1",2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
+ {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},
+ {"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305},
+
+ {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305},
+ {"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},
+ {"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305},
+
+ {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
+ {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+ {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+ {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_RSA_WITH_AES_128_CBC_SHA256},
+ {"aes_256_cbc", "sha256", 2*(32+16+SHA2_256dlen), TLS_RSA_WITH_AES_256_CBC_SHA256},
+ {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_RSA_WITH_AES_256_CBC_SHA},
+ {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"3des_ede_cbc","sha1", 2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+
+ // PSK cipher suits
+ {"ccpoly96_aead", "clear", 2*(32+12), TLS_PSK_WITH_CHACHA20_POLY1305},
+ {"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_PSK_WITH_AES_128_CBC_SHA256},
+ {"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_PSK_WITH_AES_128_CBC_SHA},
};
static uchar compressors[] = {
@@ -248,41 +326,82 @@
CompressionNull,
};
-static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...));
-static TlsConnection *tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...));
+static Namedcurve namedcurves[] = {
+ 0x0017, secp256r1,
+};
+static uchar pointformats[] = {
+ CompressionNull /* support of uncompressed point format is mandatory */
+};
+
+static struct {
+ DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*);
+ int len;
+} hashfun[] = {
+ [0x01] {md5, MD5dlen},
+ [0x02] {sha1, SHA1dlen},
+ [0x03] {sha2_224, SHA2_224dlen},
+ [0x04] {sha2_256, SHA2_256dlen},
+ [0x05] {sha2_384, SHA2_384dlen},
+ [0x06] {sha2_512, SHA2_512dlen},
+};
+
+// signature algorithms (only RSA and ECDSA at the moment)
+static int sigalgs[] = {
+ 0x0603, /* SHA512 ECDSA */
+ 0x0503, /* SHA384 ECDSA */
+ 0x0403, /* SHA256 ECDSA */
+ 0x0203, /* SHA1 ECDSA */
+
+ 0x0601, /* SHA512 RSA */
+ 0x0501, /* SHA384 RSA */
+ 0x0401, /* SHA256 RSA */
+ 0x0201, /* SHA1 RSA */
+};
+
+static TlsConnection *tlsServer2(int ctl, int hand,
+ uchar *cert, int certlen,
+ char *pskid, uchar *psk, int psklen,
+ int (*trace)(char*fmt, ...), PEMChain *chain);
+static TlsConnection *tlsClient2(int ctl, int hand,
+ uchar *csid, int ncsid,
+ uchar *cert, int certlen,
+ char *pskid, uchar *psk, int psklen,
+ uchar *ext, int extlen, int (*trace)(char*fmt, ...));
static void msgClear(Msg *m);
static char* msgPrint(char *buf, int n, Msg *m);
static int msgRecv(TlsConnection *c, Msg *m);
static int msgSend(TlsConnection *c, Msg *m, int act);
static void tlsError(TlsConnection *c, int err, char *msg, ...);
-#pragma varargck argpos tlsError 3
static int setVersion(TlsConnection *c, int version);
static int finishedMatch(TlsConnection *c, Finished *f);
static void tlsConnectionFree(TlsConnection *c);
static int setAlgs(TlsConnection *c, int a);
-static int okCipher(Ints *cv);
+static int okCipher(Ints *cv, int ispsk);
static int okCompression(Bytes *cv);
static int initCiphers(void);
-static Ints* makeciphers(void);
+static Ints* makeciphers(int ispsk);
-static TlsSec* tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom);
-static int tlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd);
+static TlsSec* tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom);
+static int tlsSecRSAs(TlsSec *sec, int vers, Bytes *epm);
+static int tlsSecPSKs(TlsSec *sec, int vers);
static TlsSec* tlsSecInitc(int cvers, uchar *crandom);
-static int tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd);
-static int tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient);
+static Bytes* tlsSecRSAc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers);
+static int tlsSecPSKc(TlsSec *sec, uchar *srandom, int vers);
+static Bytes* tlsSecDHEc(TlsSec *sec, uchar *srandom, int vers, Bytes *p, Bytes *g, Bytes *Ys);
+static Bytes* tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys);
+static int tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
static void tlsSecOk(TlsSec *sec);
static void tlsSecKill(TlsSec *sec);
static void tlsSecClose(TlsSec *sec);
static void setMasterSecret(TlsSec *sec, Bytes *pm);
-static void serverMasterSecret(TlsSec *sec, uchar *epm, int nepm);
static void setSecrets(TlsSec *sec, uchar *kd, int nkd);
-static int clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm);
-static Bytes *pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype);
-static Bytes *pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm);
-static void tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient);
-static void sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient);
+static Bytes* pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype);
+static Bytes* pkcs1_decrypt(TlsSec *sec, Bytes *cipher);
+static void tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
+static void tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
+static void sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
static void sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label,
uchar *seed0, int nseed0, uchar *seed1, int nseed1);
static int setVers(TlsSec *sec, int version);
@@ -301,11 +420,16 @@
static int get16(uchar *p);
static Bytes* newbytes(int len);
static Bytes* makebytes(uchar* buf, int len);
+static Bytes* mptobytes(mpint* big);
+static mpint* bytestomp(Bytes* bytes);
static void freebytes(Bytes* b);
static Ints* newints(int len);
-static Ints* makeints(int* buf, int len);
static void freeints(Ints* b);
+/* x509.c */
+extern mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus);
+extern int asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len);
+
//================= client/server ========================
// push TLS onto fd, returning new (application) file descriptor
@@ -329,8 +453,8 @@
return -1;
}
buf[n] = 0;
- sprint(conn->dir, "#a/tls/%s", buf);
- sprint(dname, "#a/tls/%s/hand", buf);
+ snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
+ snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
hand = open(dname, ORDWR);
if(hand < 0){
close(ctl);
@@ -337,30 +461,108 @@
return -1;
}
fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
- tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->trace);
- sprint(dname, "#a/tls/%s/data", buf);
+ tls = tlsServer2(ctl, hand,
+ conn->cert, conn->certlen,
+ conn->pskID, conn->psk, conn->psklen,
+ conn->trace, conn->chain);
+ snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
data = open(dname, ORDWR);
- close(fd);
close(hand);
close(ctl);
- if(data < 0){
+ if(data < 0 || tls == nil){
+ if(tls != nil)
+ tlsConnectionFree(tls);
return -1;
}
- if(tls == nil){
- close(data);
- return -1;
- }
- if(conn->cert)
- free(conn->cert);
- conn->cert = 0; // client certificates are not yet implemented
+ free(conn->cert);
+ conn->cert = nil; // client certificates are not yet implemented
conn->certlen = 0;
conn->sessionIDlen = tls->sid->len;
conn->sessionID = emalloc(conn->sessionIDlen);
memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
+ if(conn->sessionKey != nil
+ && conn->sessionType != nil
+ && strcmp(conn->sessionType, "ttls") == 0)
+ tls->sec->prf(
+ conn->sessionKey, conn->sessionKeylen,
+ tls->sec->sec, MasterSecretSize,
+ conn->sessionConst,
+ tls->sec->crandom, RandomSize,
+ tls->sec->srandom, RandomSize);
tlsConnectionFree(tls);
+ close(fd);
return data;
}
+static uchar*
+tlsClientExtensions(TLSconn *conn, int *plen)
+{
+ uchar *b, *p;
+ int i, n, m;
+
+ p = b = nil;
+
+ // RFC6066 - Server Name Identification
+ if(conn->serverName != nil){
+ n = strlen(conn->serverName);
+
+ m = p - b;
+ b = erealloc(b, m + 2+2+2+1+2+n);
+ p = b + m;
+
+ put16(p, 0), p += 2; /* Type: server_name */
+ put16(p, 2+1+2+n), p += 2; /* Length */
+ put16(p, 1+2+n), p += 2; /* Server Name list length */
+ *p++ = 0; /* Server Name Type: host_name */
+ put16(p, n), p += 2; /* Server Name length */
+ memmove(p, conn->serverName, n);
+ p += n;
+ }
+
+ // ECDHE
+ if(1){
+ m = p - b;
+ b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+ p = b + m;
+
+ n = nelem(namedcurves);
+ put16(p, 0x000a), p += 2; /* Type: elliptic_curves */
+ put16(p, (n+1)*2), p += 2; /* Length */
+ put16(p, n*2), p += 2; /* Elliptic Curves Length */
+ for(i=0; i < n; i++){ /* Elliptic curves */
+ put16(p, namedcurves[i].tlsid);
+ p += 2;
+ }
+
+ n = nelem(pointformats);
+ put16(p, 0x000b), p += 2; /* Type: ec_point_formats */
+ put16(p, n+1), p += 2; /* Length */
+ *p++ = n; /* EC point formats Length */
+ for(i=0; i < n; i++) /* Elliptic curves point formats */
+ *p++ = pointformats[i];
+ }
+
+ // signature algorithms
+ if(ProtocolVersion >= TLS12Version){
+ n = nelem(sigalgs);
+
+ m = p - b;
+ b = erealloc(b, m + 2+2+2+n*2);
+ p = b + m;
+
+ put16(p, 0x000d), p += 2;
+ put16(p, n*2 + 2), p += 2;
+ put16(p, n*2), p += 2;
+ for(i=0; i < n; i++){
+ put16(p, sigalgs[i]);
+ p += 2;
+ }
+ }
+
+ *plen = p - b;
+ return b;
+}
+
// push TLS onto fd, returning new (application) file descriptor
// or -1 if error.
int
@@ -370,8 +572,9 @@
char dname[64];
int n, data, ctl, hand;
TlsConnection *tls;
+ uchar *ext;
- if(!conn)
+ if(conn == nil)
return -1;
ctl = open("#a/tls/clone", ORDWR);
if(ctl < 0)
@@ -382,20 +585,28 @@
return -1;
}
buf[n] = 0;
- sprint(conn->dir, "#a/tls/%s", buf);
- sprint(dname, "#a/tls/%s/hand", buf);
+ snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
+ snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
hand = open(dname, ORDWR);
if(hand < 0){
close(ctl);
return -1;
}
- sprint(dname, "#a/tls/%s/data", buf);
+ snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
data = open(dname, ORDWR);
- if(data < 0)
+ if(data < 0){
+ close(hand);
+ close(ctl);
return -1;
+ }
fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
- tls = tlsClient2(ctl, hand, conn->sessionID, conn->sessionIDlen, conn->trace);
- close(fd);
+ ext = tlsClientExtensions(conn, &n);
+ tls = tlsClient2(ctl, hand,
+ conn->sessionID, conn->sessionIDlen,
+ conn->cert, conn->certlen,
+ conn->pskID, conn->psk, conn->psklen,
+ ext, n, conn->trace);
+ free(ext);
close(hand);
close(ctl);
if(tls == nil){
@@ -402,18 +613,48 @@
close(data);
return -1;
}
- conn->certlen = tls->cert->len;
- conn->cert = emalloc(conn->certlen);
- memcpy(conn->cert, tls->cert->data, conn->certlen);
+ if(tls->cert != nil){
+ conn->certlen = tls->cert->len;
+ conn->cert = emalloc(conn->certlen);
+ memcpy(conn->cert, tls->cert->data, conn->certlen);
+ } else {
+ conn->certlen = 0;
+ conn->cert = nil;
+ }
conn->sessionIDlen = tls->sid->len;
conn->sessionID = emalloc(conn->sessionIDlen);
memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
+ if(conn->sessionKey != nil
+ && conn->sessionType != nil
+ && strcmp(conn->sessionType, "ttls") == 0)
+ tls->sec->prf(
+ conn->sessionKey, conn->sessionKeylen,
+ tls->sec->sec, MasterSecretSize,
+ conn->sessionConst,
+ tls->sec->crandom, RandomSize,
+ tls->sec->srandom, RandomSize);
tlsConnectionFree(tls);
+ close(fd);
return data;
}
+static int
+countchain(PEMChain *p)
+{
+ int i = 0;
+
+ while (p) {
+ i++;
+ p = p->next;
+ }
+ return i;
+}
+
static TlsConnection *
-tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...))
+tlsServer2(int ctl, int hand,
+ uchar *cert, int certlen,
+ char *pskid, uchar *psk, int psklen,
+ int (*trace)(char*fmt, ...), PEMChain *chp)
{
TlsConnection *c;
Msg m;
@@ -420,7 +661,7 @@
Bytes *csid;
uchar sid[SidSize], kd[MaxKeyData];
char *secrets;
- int cipher, compressor, nsid, rv;
+ int cipher, compressor, nsid, rv, numcerts, i;
if(trace)
trace("tlsServer2\n");
@@ -445,13 +686,13 @@
c->clientVersion = m.u.clientHello.version;
if(trace)
trace("ClientHello version %x\n", c->clientVersion);
- if(setVersion(c, m.u.clientHello.version) < 0) {
+ if(setVersion(c, c->clientVersion) < 0) {
tlsError(c, EIllegalParameter, "incompatible version");
goto Err;
}
memmove(c->crandom, m.u.clientHello.random, RandomSize);
- cipher = okCipher(m.u.clientHello.ciphers);
+ cipher = okCipher(m.u.clientHello.ciphers, psklen > 0);
if(cipher < 0) {
// reply with EInsufficientSecurity if we know that's the case
if(cipher == -2)
@@ -472,18 +713,28 @@
csid = m.u.clientHello.sid;
if(trace)
- trace(" cipher %d, compressor %d, csidlen %d\n", cipher, compressor, csid->len);
+ trace(" cipher %x, compressor %x, csidlen %d\n", cipher, compressor, csid->len);
c->sec = tlsSecInits(c->clientVersion, csid->data, csid->len, c->crandom, sid, &nsid, c->srandom);
if(c->sec == nil){
tlsError(c, EHandshakeFailure, "can't initialize security: %r");
goto Err;
}
- c->sec->rpc = factotum_rsa_open(cert, ncert);
- if(c->sec->rpc == nil){
- tlsError(c, EHandshakeFailure, "factotum_rsa_open: %r");
- goto Err;
+ if(psklen > 0){
+ c->sec->psk = psk;
+ c->sec->psklen = psklen;
}
- c->sec->rsapub = X509toRSApub(cert, ncert, nil, 0);
+ if(certlen > 0){
+ c->sec->rpc = factotum_rsa_open(cert, certlen);
+ if(c->sec->rpc == nil){
+ tlsError(c, EHandshakeFailure, "factotum_rsa_open: %r");
+ goto Err;
+ }
+ c->sec->rsapub = X509toRSApub(cert, certlen, nil, 0);
+ if(c->sec->rsapub == nil){
+ tlsError(c, EHandshakeFailure, "invalid X509/rsa certificate");
+ goto Err;
+ }
+ }
msgClear(&m);
m.tag = HServerHello;
@@ -497,13 +748,18 @@
goto Err;
msgClear(&m);
- m.tag = HCertificate;
- m.u.certificate.ncert = 1;
- m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes));
- m.u.certificate.certs[0] = makebytes(cert, ncert);
- if(!msgSend(c, &m, AQueue))
- goto Err;
- msgClear(&m);
+ if(certlen > 0){
+ m.tag = HCertificate;
+ numcerts = countchain(chp);
+ m.u.certificate.ncert = 1 + numcerts;
+ m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes*));
+ m.u.certificate.certs[0] = makebytes(cert, certlen);
+ for (i = 0; i < numcerts && chp; i++, chp = chp->next)
+ m.u.certificate.certs[i+1] = makebytes(chp->pem, chp->pemlen);
+ if(!msgSend(c, &m, AQueue))
+ goto Err;
+ msgClear(&m);
+ }
m.tag = HServerHelloDone;
if(!msgSend(c, &m, AFlush))
@@ -516,10 +772,30 @@
tlsError(c, EUnexpectedMessage, "expected a client key exchange");
goto Err;
}
- if(tlsSecSecrets(c->sec, c->version, m.u.clientKeyExchange.key->data, m.u.clientKeyExchange.key->len, kd, c->nsecret) < 0){
- tlsError(c, EHandshakeFailure, "couldn't set secrets: %r");
+ if(pskid != nil){
+ if(m.u.clientKeyExchange.pskid == nil
+ || m.u.clientKeyExchange.pskid->len != strlen(pskid)
+ || memcmp(pskid, m.u.clientKeyExchange.pskid->data, m.u.clientKeyExchange.pskid->len) != 0){
+ tlsError(c, EUnknownPSKidentity, "unknown or missing pskid");
+ goto Err;
+ }
+ }
+ if(certlen > 0){
+ if(tlsSecRSAs(c->sec, c->version, m.u.clientKeyExchange.key) < 0){
+ tlsError(c, EHandshakeFailure, "couldn't set secrets: %r");
+ goto Err;
+ }
+ } else if(psklen > 0){
+ if(tlsSecPSKs(c->sec, c->version) < 0){
+ tlsError(c, EHandshakeFailure, "couldn't set secrets: %r");
+ goto Err;
+ }
+ } else {
+ tlsError(c, EInternalError, "no psk or certificate");
goto Err;
}
+
+ setSecrets(c->sec, kd, c->nsecret);
if(trace)
trace("tls secrets\n");
secrets = (char*)emalloc(2*c->nsecret);
@@ -535,7 +811,7 @@
msgClear(&m);
/* no CertificateVerify; skip to Finished */
- if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){
+ if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
tlsError(c, EInternalError, "can't set finished: %r");
goto Err;
}
@@ -557,7 +833,7 @@
goto Err;
}
- if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){
+ if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
tlsError(c, EInternalError, "can't set finished: %r");
goto Err;
}
@@ -580,14 +856,235 @@
return 0;
}
+static int
+isDHE(int tlsid)
+{
+ switch(tlsid){
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DHE_RSA_WITH_CHACHA20_POLY1305:
+ case GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305:
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isECDHE(int tlsid)
+{
+ switch(tlsid){
+ case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
+ case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:
+
+ case GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
+ case GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305:
+
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isPSK(int tlsid)
+{
+ switch(tlsid){
+ case TLS_PSK_WITH_CHACHA20_POLY1305:
+ case TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case TLS_PSK_WITH_AES_128_CBC_SHA:
+ return 1;
+ }
+ return 0;
+}
+
+static Bytes*
+tlsSecDHEc(TlsSec *sec, uchar *srandom, int vers,
+ Bytes *p, Bytes *g, Bytes *Ys)
+{
+ mpint *G, *P, *Y, *K;
+ Bytes *epm;
+ DHstate dh;
+
+ if(p == nil || g == nil || Ys == nil)
+ return nil;
+
+ memmove(sec->srandom, srandom, RandomSize);
+ if(setVers(sec, vers) < 0)
+ return nil;
+
+ epm = nil;
+ P = bytestomp(p);
+ G = bytestomp(g);
+ Y = bytestomp(Ys);
+ K = nil;
+
+ if(P == nil || G == nil || Y == nil || dh_new(&dh, P, nil, G) == nil)
+ goto Out;
+ epm = mptobytes(dh.y);
+ K = dh_finish(&dh, Y);
+ if(K == nil){
+ freebytes(epm);
+ epm = nil;
+ goto Out;
+ }
+ setMasterSecret(sec, mptobytes(K));
+
+Out:
+ mpfree(K);
+ mpfree(Y);
+ mpfree(G);
+ mpfree(P);
+
+ return epm;
+}
+
+static Bytes*
+tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
+{
+ Namedcurve *nc, *enc;
+ Bytes *epm;
+ ECdomain dom;
+ ECpub *pub;
+ ECpoint K;
+ ECpriv Q;
+
+ if(Ys == nil)
+ return nil;
+
+ enc = &namedcurves[nelem(namedcurves)];
+ for(nc = namedcurves; nc != enc; nc++)
+ if(nc->tlsid == curve)
+ break;
+
+ if(nc == enc)
+ return nil;
+
+ memmove(sec->srandom, srandom, RandomSize);
+ if(setVers(sec, vers) < 0)
+ return nil;
+
+ ecdominit(&dom, nc->init);
+ pub = ecdecodepub(&dom, Ys->data, Ys->len);
+ if(pub == nil){
+ ecdomfree(&dom);
+ return nil;
+ }
+
+ memset(&Q, 0, sizeof(Q));
+ Q.x = mpnew(0);
+ Q.y = mpnew(0);
+ Q.d = mpnew(0);
+
+ memset(&K, 0, sizeof(K));
+ K.x = mpnew(0);
+ K.y = mpnew(0);
+
+ epm = nil;
+ if(ecgen(&dom, &Q) != nil){
+ ecmul(&dom, pub, Q.d, &K);
+ setMasterSecret(sec, mptobytes(K.x));
+ epm = newbytes(1 + 2*((mpsignif(dom.p)+7)/8));
+ epm->len = ecencodepub(&dom, (ECpub*)&Q, epm->data, epm->len);
+ }
+
+ mpfree(K.x);
+ mpfree(K.y);
+ mpfree(Q.x);
+ mpfree(Q.y);
+ mpfree(Q.d);
+
+ ecpubfree(pub);
+ ecdomfree(&dom);
+
+ return epm;
+}
+
+static char*
+verifyDHparams(TlsConnection *c, Bytes *par, Bytes *sig, int sigalg)
+{
+ uchar digest[MAXdlen];
+ int digestlen;
+ ECdomain dom;
+ ECpub *ecpk;
+ RSApub *rsapk;
+ Bytes *blob;
+ char *err;
+
+ if(par == nil || par->len <= 0)
+ return "no dh parameters";
+
+ if(sig == nil || sig->len <= 0){
+ if(c->sec->psklen > 0)
+ return nil;
+ return "no signature";
+ }
+
+ if(c->cert == nil)
+ return "no certificate";
+
+ blob = newbytes(2*RandomSize + par->len);
+ memmove(blob->data+0*RandomSize, c->crandom, RandomSize);
+ memmove(blob->data+1*RandomSize, c->srandom, RandomSize);
+ memmove(blob->data+2*RandomSize, par->data, par->len);
+ if(c->version < TLS12Version){
+ digestlen = MD5dlen + SHA1dlen;
+ md5(blob->data, blob->len, digest, nil);
+ sha1(blob->data, blob->len, digest+MD5dlen, nil);
+ } else {
+ int hashalg = (sigalg>>8) & 0xFF;
+ digestlen = -1;
+ if(hashalg < nelem(hashfun) && hashfun[hashalg].fun != nil){
+ digestlen = hashfun[hashalg].len;
+ (*hashfun[hashalg].fun)(blob->data, blob->len, digest, nil);
+ }
+ }
+ freebytes(blob);
+
+ if(digestlen <= 0)
+ return "unknown signature digest algorithm";
+
+ switch(sigalg & 0xFF){
+ case 0x01:
+ rsapk = X509toRSApub(c->cert->data, c->cert->len, nil, 0);
+ if(rsapk == nil)
+ return "bad certificate";
+ err = X509rsaverifydigest(sig->data, sig->len, digest, digestlen, rsapk);
+ rsapubfree(rsapk);
+ break;
+ case 0x03:
+ ecpk = X509toECpub(c->cert->data, c->cert->len, &dom);
+ if(ecpk == nil)
+ return "bad certificate";
+ err = X509ecdsaverifydigest(sig->data, sig->len, digest, digestlen, &dom, ecpk);
+ ecdomfree(&dom);
+ ecpubfree(ecpk);
+ break;
+ default:
+ err = "signaure algorithm not RSA or ECDSA";
+ }
+
+ return err;
+}
+
static TlsConnection *
-tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...))
+tlsClient2(int ctl, int hand,
+ uchar *csid, int ncsid,
+ uchar *cert, int certlen,
+ char *pskid, uchar *psk, int psklen,
+ uchar *ext, int extlen,
+ int (*trace)(char*fmt, ...))
{
TlsConnection *c;
Msg m;
- uchar kd[MaxKeyData], *epm;
+ uchar kd[MaxKeyData];
char *secrets;
- int creq, nepm, rv;
+ int creq, dhx, rv, cipher;
+ Bytes *epm;
if(!initCiphers())
return nil;
@@ -594,16 +1091,23 @@
epm = nil;
c = emalloc(sizeof(TlsConnection));
c->version = ProtocolVersion;
+
c->ctl = ctl;
c->hand = hand;
c->trace = trace;
c->isClient = 1;
c->clientVersion = c->version;
+ c->cert = nil;
c->sec = tlsSecInitc(c->clientVersion, c->crandom);
if(c->sec == nil)
goto Err;
+ if(psklen > 0){
+ c->sec->psk = psk;
+ c->sec->psklen = psklen;
+ }
+
/* client hello */
memset(&m, 0, sizeof(m));
m.tag = HClientHello;
@@ -610,8 +1114,9 @@
m.u.clientHello.version = c->clientVersion;
memmove(m.u.clientHello.random, c->crandom, RandomSize);
m.u.clientHello.sid = makebytes(csid, ncsid);
- m.u.clientHello.ciphers = makeciphers();
+ m.u.clientHello.ciphers = makeciphers(psklen > 0);
m.u.clientHello.compressors = makebytes(compressors,sizeof(compressors));
+ m.u.clientHello.extensions = makebytes(ext, extlen);
if(!msgSend(c, &m, AFlush))
goto Err;
msgClear(&m);
@@ -624,7 +1129,7 @@
goto Err;
}
if(setVersion(c, m.u.serverHello.version) < 0) {
- tlsError(c, EIllegalParameter, "incompatible version %r");
+ tlsError(c, EIllegalParameter, "incompatible version: %r");
goto Err;
}
memmove(c->srandom, m.u.serverHello.random, RandomSize);
@@ -633,7 +1138,8 @@
tlsError(c, EIllegalParameter, "invalid server session identifier");
goto Err;
}
- if(!setAlgs(c, m.u.serverHello.cipher)) {
+ cipher = m.u.serverHello.cipher;
+ if((psklen > 0) != isPSK(cipher) || !setAlgs(c, cipher)) {
tlsError(c, EIllegalParameter, "invalid cipher suite");
goto Err;
}
@@ -643,26 +1149,53 @@
}
msgClear(&m);
- /* certificate */
- if(!msgRecv(c, &m) || m.tag != HCertificate) {
+ dhx = isDHE(cipher) || isECDHE(cipher);
+ if(!msgRecv(c, &m))
+ goto Err;
+ if(m.tag == HCertificate){
+ if(m.u.certificate.ncert < 1) {
+ tlsError(c, EIllegalParameter, "runt certificate");
+ goto Err;
+ }
+ c->cert = makebytes(m.u.certificate.certs[0]->data, m.u.certificate.certs[0]->len);
+ msgClear(&m);
+ if(!msgRecv(c, &m))
+ goto Err;
+ } else if(psklen == 0) {
tlsError(c, EUnexpectedMessage, "expected a certificate");
goto Err;
}
- if(m.u.certificate.ncert < 1) {
- tlsError(c, EIllegalParameter, "runt certificate");
- goto Err;
- }
- c->cert = makebytes(m.u.certificate.certs[0]->data, m.u.certificate.certs[0]->len);
- msgClear(&m);
-
- /* server key exchange (optional) */
- if(!msgRecv(c, &m))
- goto Err;
if(m.tag == HServerKeyExchange) {
- tlsError(c, EUnexpectedMessage, "got an server key exchange");
+ if(dhx){
+ char *err = verifyDHparams(c,
+ m.u.serverKeyExchange.dh_parameters,
+ m.u.serverKeyExchange.dh_signature,
+ m.u.serverKeyExchange.sigalg);
+ if(err != nil){
+ tlsError(c, EBadCertificate, "can't verify dh parameters: %s", err);
+ goto Err;
+ }
+ if(isECDHE(cipher))
+ epm = tlsSecECDHEc(c->sec, c->srandom, c->version,
+ m.u.serverKeyExchange.curve,
+ m.u.serverKeyExchange.dh_Ys);
+ else
+ epm = tlsSecDHEc(c->sec, c->srandom, c->version,
+ m.u.serverKeyExchange.dh_p,
+ m.u.serverKeyExchange.dh_g,
+ m.u.serverKeyExchange.dh_Ys);
+ if(epm == nil)
+ goto Badcert;
+ } else if(psklen == 0){
+ tlsError(c, EUnexpectedMessage, "got an server key exchange");
+ goto Err;
+ }
+ msgClear(&m);
+ if(!msgRecv(c, &m))
+ goto Err;
+ } else if(dhx){
+ tlsError(c, EUnexpectedMessage, "expected server key exchange");
goto Err;
- // If implementing this later, watch out for rollback attack
- // described in Wagner Schneier 1996, section 4.4.
}
/* certificate request (optional) */
@@ -680,12 +1213,25 @@
}
msgClear(&m);
- if(tlsSecSecretc(c->sec, c->sid->data, c->sid->len, c->srandom,
- c->cert->data, c->cert->len, c->version, &epm, &nepm,
- kd, c->nsecret) < 0){
- tlsError(c, EBadCertificate, "invalid x509/rsa certificate");
- goto Err;
+ if(!dhx){
+ if(c->cert != nil){
+ epm = tlsSecRSAc(c->sec, c->sid->data, c->sid->len, c->srandom,
+ c->cert->data, c->cert->len, c->version);
+ if(epm == nil){
+ Badcert:
+ tlsError(c, EBadCertificate, "bad certificate: %r");
+ goto Err;
+ }
+ } else if(psklen > 0) {
+ if(tlsSecPSKc(c->sec, c->srandom, c->version) < 0)
+ goto Badcert;
+ } else {
+ tlsError(c, EInternalError, "no psk or certificate");
+ goto Err;
+ }
}
+
+ setSecrets(c->sec, kd, c->nsecret);
secrets = (char*)emalloc(2*c->nsecret);
enc64(secrets, 2*c->nsecret, kd, c->nsecret);
rv = fprint(c->ctl, "secret %s %s 1 %s", c->digest, c->enc, secrets);
@@ -698,7 +1244,11 @@
}
if(creq) {
- /* send a zero length certificate */
+ if(cert != nil && certlen > 0){
+ m.u.certificate.ncert = 1;
+ m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes*));
+ m.u.certificate.certs[0] = makebytes(cert, certlen);
+ }
m.tag = HCertificate;
if(!msgSend(c, &m, AFlush))
goto Err;
@@ -707,17 +1257,71 @@
/* client key exchange */
m.tag = HClientKeyExchange;
- m.u.clientKeyExchange.key = makebytes(epm, nepm);
- free(epm);
- epm = nil;
- if(m.u.clientKeyExchange.key == nil) {
- tlsError(c, EHandshakeFailure, "can't set secret: %r");
- goto Err;
+ if(psklen > 0){
+ if(pskid == nil)
+ pskid = "";
+ m.u.clientKeyExchange.pskid = makebytes((uchar*)pskid, strlen(pskid));
}
+ m.u.clientKeyExchange.key = epm;
+ epm = nil;
+
if(!msgSend(c, &m, AFlush))
goto Err;
msgClear(&m);
+ /* certificate verify */
+ if(creq && cert != nil && certlen > 0) {
+ mpint *signedMP, *paddedHashes;
+ HandshakeHash hsave;
+ uchar buf[512];
+ int buflen;
+
+ c->sec->rpc = factotum_rsa_open(cert, certlen);
+ if(c->sec->rpc == nil){
+ tlsError(c, EHandshakeFailure, "factotum_rsa_open: %r");
+ goto Err;
+ }
+ c->sec->rsapub = X509toRSApub(cert, certlen, nil, 0);
+ if(c->sec->rsapub == nil){
+ tlsError(c, EHandshakeFailure, "invalid X509/rsa certificate");
+ goto Err;
+ }
+
+ /* save the state for the Finish message */
+ hsave = c->handhash;
+ if(c->version >= TLS12Version){
+ uchar digest[SHA2_256dlen];
+
+ m.u.certificateVerify.sigalg = 0x0401; /* RSA SHA256 */
+ sha2_256(nil, 0, digest, &c->handhash.sha2_256);
+ buflen = asn1encodedigest(sha2_256, digest, buf, sizeof(buf));
+ } else {
+ md5(nil, 0, buf, &c->handhash.md5);
+ sha1(nil, 0, buf+MD5dlen, &c->handhash.sha1);
+ buflen = MD5dlen+SHA1dlen;
+ }
+ c->handhash = hsave;
+
+ if(buflen <= 0){
+ tlsError(c, EInternalError, "can't encode handshake hashes");
+ goto Err;
+ }
+
+ paddedHashes = pkcs1padbuf(buf, buflen, c->sec->rsapub->n);
+ signedMP = factotum_rsa_decrypt(c->sec->rpc, paddedHashes);
+ if(signedMP == nil){
+ tlsError(c, EHandshakeFailure, "factotum_rsa_decrypt: %r");
+ goto Err;
+ }
+ m.u.certificateVerify.signature = mptobytes(signedMP);
+ mpfree(signedMP);
+
+ m.tag = HCertificateVerify;
+ if(!msgSend(c, &m, AFlush))
+ goto Err;
+ msgClear(&m);
+ }
+
/* change cipher spec */
if(fprint(c->ctl, "changecipher") < 0){
tlsError(c, EInternalError, "can't enable cipher: %r");
@@ -726,32 +1330,27 @@
// Cipherchange must occur immediately before Finished to avoid
// potential hole; see section 4.3 of Wagner Schneier 1996.
- if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){
+ if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
tlsError(c, EInternalError, "can't set finished 1: %r");
goto Err;
}
m.tag = HFinished;
m.u.finished = c->finished;
-
if(!msgSend(c, &m, AFlush)) {
- fprint(2, "tlsClient nepm=%d\n", nepm);
tlsError(c, EInternalError, "can't flush after client Finished: %r");
goto Err;
}
msgClear(&m);
- if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){
- fprint(2, "tlsClient nepm=%d\n", nepm);
+ if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
tlsError(c, EInternalError, "can't set finished 0: %r");
goto Err;
}
if(!msgRecv(c, &m)) {
- fprint(2, "tlsClient nepm=%d\n", nepm);
tlsError(c, EInternalError, "can't read server Finished: %r");
goto Err;
}
if(m.tag != HFinished) {
- fprint(2, "tlsClient nepm=%d\n", nepm);
tlsError(c, EUnexpectedMessage, "expected a Finished msg from server");
goto Err;
}
@@ -780,7 +1379,14 @@
//================= message functions ========================
-static uchar sendbuf[9000], *sendp;
+static void
+msgHash(TlsConnection *c, uchar *p, int n)
+{
+ md5(p, n, 0, &c->handhash.md5);
+ sha1(p, n, 0, &c->handhash.sha1);
+ if(c->version >= TLS12Version)
+ sha2_256(p, n, 0, &c->handhash.sha2_256);
+}
static int
msgSend(TlsConnection *c, Msg *m, int act)
@@ -788,11 +1394,11 @@
uchar *p; // sendp = start of new message; p = write pointer
int nn, n, i;
- if(sendp == nil)
- sendp = sendbuf;
- p = sendp;
+ if(c->sendp == nil)
+ c->sendp = c->sendbuf;
+ p = c->sendp;
if(c->trace)
- c->trace("send %s", msgPrint((char*)p, (sizeof sendbuf) - (p-sendbuf), m));
+ c->trace("send %s", msgPrint((char*)p, (sizeof(c->sendbuf)) - (p - c->sendbuf), m));
p[0] = m->tag; // header - fill in size later
p += 4;
@@ -831,6 +1437,15 @@
p[0] = n;
memmove(p+1, m->u.clientHello.compressors->data, n);
p += n+1;
+
+ if(m->u.clientHello.extensions == nil)
+ break;
+ n = m->u.clientHello.extensions->len;
+ if(n == 0)
+ break;
+ put16(p, n);
+ memmove(p+2, m->u.clientHello.extensions->data, n);
+ p += n+2;
break;
case HServerHello:
put16(p, m->u.serverHello.version);
@@ -851,6 +1466,15 @@
p += 2;
p[0] = m->u.serverHello.compressor;
p += 1;
+
+ if(m->u.serverHello.extensions == nil)
+ break;
+ n = m->u.serverHello.extensions->len;
+ if(n == 0)
+ break;
+ put16(p, n);
+ memmove(p+2, m->u.serverHello.extensions->data, n);
+ p += n+2;
break;
case HServerHelloDone:
break;
@@ -858,7 +1482,7 @@
nn = 0;
for(i = 0; i < m->u.certificate.ncert; i++)
nn += 3 + m->u.certificate.certs[i]->len;
- if(p + 3 + nn - sendbuf > sizeof(sendbuf)) {
+ if(p + 3 + nn - c->sendbuf > sizeof(c->sendbuf)) {
tlsError(c, EInternalError, "output buffer too small for certificate");
goto Err;
}
@@ -871,12 +1495,33 @@
p += m->u.certificate.certs[i]->len;
}
break;
+ case HCertificateVerify:
+ if(m->u.certificateVerify.sigalg != 0){
+ put16(p, m->u.certificateVerify.sigalg);
+ p += 2;
+ }
+ put16(p, m->u.certificateVerify.signature->len);
+ p += 2;
+ memmove(p, m->u.certificateVerify.signature->data, m->u.certificateVerify.signature->len);
+ p += m->u.certificateVerify.signature->len;
+ break;
case HClientKeyExchange:
- n = m->u.clientKeyExchange.key->len;
- if(c->version != SSL3Version){
+ if(m->u.clientKeyExchange.pskid != nil){
+ n = m->u.clientKeyExchange.pskid->len;
put16(p, n);
p += 2;
+ memmove(p, m->u.clientKeyExchange.pskid->data, n);
+ p += n;
}
+ if(m->u.clientKeyExchange.key == nil)
+ break;
+ n = m->u.clientKeyExchange.key->len;
+ if(c->version != SSL3Version){
+ if(isECDHE(c->cipher))
+ *p++ = n;
+ else
+ put16(p, n), p += 2;
+ }
memmove(p, m->u.clientKeyExchange.key->data, n);
p += n;
break;
@@ -887,20 +1532,18 @@
}
// go back and fill in size
- n = p-sendp;
- assert(p <= sendbuf+sizeof(sendbuf));
- put24(sendp+1, n-4);
+ n = p - c->sendp;
+ assert(p <= c->sendbuf + sizeof(c->sendbuf));
+ put24(c->sendp+1, n-4);
// remember hash of Handshake messages
- if(m->tag != HHelloRequest) {
- md5(sendp, n, 0, &c->hsmd5);
- sha1(sendp, n, 0, &c->hssha1);
- }
+ if(m->tag != HHelloRequest)
+ msgHash(c, c->sendp, n);
- sendp = p;
+ c->sendp = p;
if(act == AFlush){
- sendp = sendbuf;
- if(write(c->hand, sendbuf, p-sendbuf) < 0){
+ c->sendp = c->sendbuf;
+ if(write(c->hand, c->sendbuf, p - c->sendbuf) < 0){
fprint(2, "write error: %r\n");
goto Err;
}
@@ -920,10 +1563,10 @@
nn = c->ep - c->rp;
if(nn < n){
- if(c->rp != c->buf){
- memmove(c->buf, c->rp, nn);
- c->rp = c->buf;
- c->ep = &c->buf[nn];
+ if(c->rp != c->recvbuf){
+ memmove(c->recvbuf, c->rp, nn);
+ c->rp = c->recvbuf;
+ c->ep = &c->recvbuf[nn];
}
for(; nn < n; nn += nr) {
nr = read(c->hand, &c->rp[nn], n - nn);
@@ -940,7 +1583,7 @@
static int
msgRecv(TlsConnection *c, Msg *m)
{
- uchar *p;
+ uchar *p, *s;
int type, n, nn, i, nsid, nrandom, nciph;
for(;;) {
@@ -958,8 +1601,8 @@
}
}
- if(n > sizeof(c->buf)) {
- tlsError(c, EDecodeError, "handshake message too long %d %d", n, sizeof(c->buf));
+ if(n > sizeof(c->recvbuf)) {
+ tlsError(c, EDecodeError, "handshake message too long %d %d", n, sizeof(c->recvbuf));
return 0;
}
@@ -970,8 +1613,7 @@
p = tlsReadN(c, n);
if(p == nil)
return 0;
- md5(p, n, 0, &c->hsmd5);
- sha1(p, n, 0, &c->hssha1);
+ msgHash(c, p, n);
m->tag = HClientHello;
if(n < 22)
goto Short;
@@ -1008,16 +1650,13 @@
m->u.clientHello.compressors->data[0] = CompressionNull;
goto Ok;
}
+ msgHash(c, p, 4);
- md5(p, 4, 0, &c->hsmd5);
- sha1(p, 4, 0, &c->hssha1);
-
p = tlsReadN(c, n);
if(p == nil)
return 0;
- md5(p, n, 0, &c->hsmd5);
- sha1(p, n, 0, &c->hssha1);
+ msgHash(c, p, n);
m->tag = type;
@@ -1060,9 +1699,17 @@
if(n < 1 || n < p[0]+1 || p[0] == 0)
goto Short;
nn = p[0];
- m->u.clientHello.compressors = newbytes(nn);
- memmove(m->u.clientHello.compressors->data, p+1, nn);
+ m->u.clientHello.compressors = makebytes(p+1, nn);
+ p += nn + 1;
n -= nn + 1;
+
+ if(n < 2)
+ break;
+ nn = get16(p);
+ if(nn > n-2)
+ goto Short;
+ m->u.clientHello.extensions = makebytes(p+2, nn);
+ n -= nn + 2;
break;
case HServerHello:
if(n < 2)
@@ -1087,7 +1734,16 @@
goto Short;
m->u.serverHello.cipher = get16(p);
m->u.serverHello.compressor = p[2];
+ p += 3;
n -= 3;
+
+ if(n < 2)
+ break;
+ nn = get16(p);
+ if(nn > n-2)
+ goto Short;
+ m->u.serverHello.extensions = makebytes(p+2, nn);
+ n -= nn + 2;
break;
case HCertificate:
if(n < 3)
@@ -1095,7 +1751,7 @@
nn = get24(p);
p += 3;
n -= 3;
- if(n != nn)
+ if(nn == 0 && n > 0)
goto Short;
/* certs */
i = 0;
@@ -1108,7 +1764,7 @@
if(nn > n)
goto Short;
m->u.certificate.ncert = i+1;
- m->u.certificate.certs = erealloc(m->u.certificate.certs, (i+1)*sizeof(Bytes));
+ m->u.certificate.certs = erealloc(m->u.certificate.certs, (i+1)*sizeof(Bytes*));
m->u.certificate.certs[i] = makebytes(p, nn);
p += nn;
n -= nn;
@@ -1116,19 +1772,39 @@
}
break;
case HCertificateRequest:
+ if(n < 1)
+ goto Short;
+ nn = p[0];
+ p += 1;
+ n -= 1;
+ if(nn > n)
+ goto Short;
+ m->u.certificateRequest.types = makebytes(p, nn);
+ p += nn;
+ n -= nn;
+ if(c->version >= TLS12Version){
+ if(n < 2)
+ goto Short;
+ nn = get16(p);
+ p += 2;
+ n -= 2;
+ if(nn & 1)
+ goto Short;
+ m->u.certificateRequest.sigalgs = newints(nn>>1);
+ for(i = 0; i < nn; i += 2)
+ m->u.certificateRequest.sigalgs->data[i >> 1] = get16(&p[i]);
+ p += nn;
+ n -= nn;
+
+ }
if(n < 2)
goto Short;
nn = get16(p);
p += 2;
n -= 2;
- if(nn < 1 || nn > n)
+ /* nn == 0 can happen; yahoo's servers do it */
+ if(nn != n)
goto Short;
- m->u.certificateRequest.types = makebytes(p, nn);
- nn = get24(p);
- p += 3;
- n -= 3;
- if(nn == 0 || n != nn)
- goto Short;
/* cas */
i = 0;
while(n > 0) {
@@ -1140,7 +1816,8 @@
if(nn < 1 || nn > n)
goto Short;
m->u.certificateRequest.nca = i+1;
- m->u.certificateRequest.cas = erealloc(m->u.certificateRequest.cas, (i+1)*sizeof(Bytes));
+ m->u.certificateRequest.cas = erealloc(
+ m->u.certificateRequest.cas, (i+1)*sizeof(Bytes*));
m->u.certificateRequest.cas[i] = makebytes(p, nn);
p += nn;
n -= nn;
@@ -1149,11 +1826,99 @@
break;
case HServerHelloDone:
break;
+ case HServerKeyExchange:
+ if(isPSK(c->cipher)){
+ if(n < 2)
+ goto Short;
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn > n)
+ goto Short;
+ m->u.serverKeyExchange.pskid = makebytes(p, nn);
+ p += nn, n -= nn;
+ if(n == 0)
+ break;
+ }
+ if(n < 2)
+ goto Short;
+ s = p;
+ if(isECDHE(c->cipher)){
+ nn = *p;
+ p++, n--;
+ if(nn != 3 || nn > n) /* not a named curve */
+ goto Short;
+ nn = get16(p);
+ p += 2, n -= 2;
+ m->u.serverKeyExchange.curve = nn;
+
+ nn = *p++, n--;
+ if(nn < 1 || nn > n)
+ goto Short;
+ m->u.serverKeyExchange.dh_Ys = makebytes(p, nn);
+ p += nn, n -= nn;
+ }else if(isDHE(c->cipher)){
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn < 1 || nn > n)
+ goto Short;
+ m->u.serverKeyExchange.dh_p = makebytes(p, nn);
+ p += nn, n -= nn;
+
+ if(n < 2)
+ goto Short;
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn < 1 || nn > n)
+ goto Short;
+ m->u.serverKeyExchange.dh_g = makebytes(p, nn);
+ p += nn, n -= nn;
+
+ if(n < 2)
+ goto Short;
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn < 1 || nn > n)
+ goto Short;
+ m->u.serverKeyExchange.dh_Ys = makebytes(p, nn);
+ p += nn, n -= nn;
+ } else {
+ /* should not happen */
+ goto Short;
+ }
+ m->u.serverKeyExchange.dh_parameters = makebytes(s, p - s);
+ if(n >= 2){
+ m->u.serverKeyExchange.sigalg = 0;
+ if(c->version >= TLS12Version){
+ m->u.serverKeyExchange.sigalg = get16(p);
+ p += 2, n -= 2;
+ if(n < 2)
+ goto Short;
+ }
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn > 0 && nn <= n){
+ m->u.serverKeyExchange.dh_signature = makebytes(p, nn);
+ n -= nn;
+ }
+ }
+ break;
case HClientKeyExchange:
/*
* this message depends upon the encryption selected
* assume rsa.
*/
+ if(isPSK(c->cipher)){
+ if(n < 2)
+ goto Short;
+ nn = get16(p);
+ p += 2, n -= 2;
+ if(nn > n)
+ goto Short;
+ m->u.clientKeyExchange.pskid = makebytes(p, nn);
+ p += nn, n -= nn;
+ if(n == 0)
+ break;
+ }
if(c->version == SSL3Version)
nn = n;
else{
@@ -1177,16 +1942,18 @@
break;
}
- if(type != HClientHello && n != 0)
+ if(type != HClientHello && type != HServerHello && n != 0)
goto Short;
Ok:
if(c->trace){
- char buf[8000];
- c->trace("recv %s", msgPrint(buf, sizeof buf, m));
+ char *buf;
+ buf = emalloc(8000);
+ c->trace("recv %s", msgPrint(buf, 8000, m));
+ free(buf);
}
return 1;
Short:
- tlsError(c, EDecodeError, "handshake message has invalid length");
+ tlsError(c, EDecodeError, "handshake message (%d) has invalid length", type);
Err:
msgClear(m);
return 0;
@@ -1206,9 +1973,11 @@
freebytes(m->u.clientHello.sid);
freeints(m->u.clientHello.ciphers);
freebytes(m->u.clientHello.compressors);
+ freebytes(m->u.clientHello.extensions);
break;
case HServerHello:
- freebytes(m->u.clientHello.sid);
+ freebytes(m->u.serverHello.sid);
+ freebytes(m->u.serverHello.extensions);
break;
case HCertificate:
for(i=0; i<m->u.certificate.ncert; i++)
@@ -1217,13 +1986,26 @@
break;
case HCertificateRequest:
freebytes(m->u.certificateRequest.types);
+ freeints(m->u.certificateRequest.sigalgs);
for(i=0; i<m->u.certificateRequest.nca; i++)
freebytes(m->u.certificateRequest.cas[i]);
free(m->u.certificateRequest.cas);
break;
+ case HCertificateVerify:
+ freebytes(m->u.certificateVerify.signature);
+ break;
case HServerHelloDone:
break;
+ case HServerKeyExchange:
+ freebytes(m->u.serverKeyExchange.pskid);
+ freebytes(m->u.serverKeyExchange.dh_p);
+ freebytes(m->u.serverKeyExchange.dh_g);
+ freebytes(m->u.serverKeyExchange.dh_Ys);
+ freebytes(m->u.serverKeyExchange.dh_parameters);
+ freebytes(m->u.serverKeyExchange.dh_signature);
+ break;
case HClientKeyExchange:
+ freebytes(m->u.clientKeyExchange.pskid);
freebytes(m->u.clientKeyExchange.key);
break;
case HFinished:
@@ -1239,12 +2021,13 @@
if(s0)
bs = seprint(bs, be, "%s", s0);
- bs = seprint(bs, be, "[");
if(b == nil)
bs = seprint(bs, be, "nil");
- else
+ else {
+ bs = seprint(bs, be, "<%d> [", b->len);
for(i=0; i<b->len; i++)
bs = seprint(bs, be, "%.2x ", b->data[i]);
+ }
bs = seprint(bs, be, "]");
if(s1)
bs = seprint(bs, be, "%s", s1);
@@ -1290,6 +2073,8 @@
bs = bytesPrint(bs, be, "\tsid: ", m->u.clientHello.sid, "\n");
bs = intsPrint(bs, be, "\tciphers: ", m->u.clientHello.ciphers, "\n");
bs = bytesPrint(bs, be, "\tcompressors: ", m->u.clientHello.compressors, "\n");
+ if(m->u.clientHello.extensions != nil)
+ bs = bytesPrint(bs, be, "\textensions: ", m->u.clientHello.extensions, "\n");
break;
case HServerHello:
bs = seprint(bs, be, "ServerHello\n");
@@ -1301,6 +2086,8 @@
bs = bytesPrint(bs, be, "\tsid: ", m->u.serverHello.sid, "\n");
bs = seprint(bs, be, "\tcipher: %.4x\n", m->u.serverHello.cipher);
bs = seprint(bs, be, "\tcompressor: %.2x\n", m->u.serverHello.compressor);
+ if(m->u.serverHello.extensions != nil)
+ bs = bytesPrint(bs, be, "\textensions: ", m->u.serverHello.extensions, "\n");
break;
case HCertificate:
bs = seprint(bs, be, "Certificate\n");
@@ -1310,16 +2097,45 @@
case HCertificateRequest:
bs = seprint(bs, be, "CertificateRequest\n");
bs = bytesPrint(bs, be, "\ttypes: ", m->u.certificateRequest.types, "\n");
+ if(m->u.certificateRequest.sigalgs != nil)
+ bs = intsPrint(bs, be, "\tsigalgs: ", m->u.certificateRequest.sigalgs, "\n");
bs = seprint(bs, be, "\tcertificateauthorities\n");
for(i=0; i<m->u.certificateRequest.nca; i++)
bs = bytesPrint(bs, be, "\t\t", m->u.certificateRequest.cas[i], "\n");
break;
+ case HCertificateVerify:
+ bs = seprint(bs, be, "HCertificateVerify\n");
+ if(m->u.certificateVerify.sigalg != 0)
+ bs = seprint(bs, be, "\tsigalg: %.4x\n", m->u.certificateVerify.sigalg);
+ bs = bytesPrint(bs, be, "\tsignature: ", m->u.certificateVerify.signature,"\n");
+ break;
case HServerHelloDone:
bs = seprint(bs, be, "ServerHelloDone\n");
break;
+ case HServerKeyExchange:
+ bs = seprint(bs, be, "HServerKeyExchange\n");
+ if(m->u.serverKeyExchange.pskid != nil)
+ bs = bytesPrint(bs, be, "\tpskid: ", m->u.serverKeyExchange.pskid, "\n");
+ if(m->u.serverKeyExchange.dh_parameters == nil)
+ break;
+ if(m->u.serverKeyExchange.curve != 0){
+ bs = seprint(bs, be, "\tcurve: %.4x\n", m->u.serverKeyExchange.curve);
+ } else {
+ bs = bytesPrint(bs, be, "\tdh_p: ", m->u.serverKeyExchange.dh_p, "\n");
+ bs = bytesPrint(bs, be, "\tdh_g: ", m->u.serverKeyExchange.dh_g, "\n");
+ }
+ bs = bytesPrint(bs, be, "\tdh_Ys: ", m->u.serverKeyExchange.dh_Ys, "\n");
+ if(m->u.serverKeyExchange.sigalg != 0)
+ bs = seprint(bs, be, "\tsigalg: %.4x\n", m->u.serverKeyExchange.sigalg);
+ bs = bytesPrint(bs, be, "\tdh_parameters: ", m->u.serverKeyExchange.dh_parameters, "\n");
+ bs = bytesPrint(bs, be, "\tdh_signature: ", m->u.serverKeyExchange.dh_signature, "\n");
+ break;
case HClientKeyExchange:
bs = seprint(bs, be, "HClientKeyExchange\n");
- bs = bytesPrint(bs, be, "\tkey: ", m->u.clientKeyExchange.key, "\n");
+ if(m->u.clientKeyExchange.pskid != nil)
+ bs = bytesPrint(bs, be, "\tpskid: ", m->u.clientKeyExchange.pskid, "\n");
+ if(m->u.clientKeyExchange.key != nil)
+ bs = bytesPrint(bs, be, "\tkey: ", m->u.clientKeyExchange.key, "\n");
break;
case HFinished:
bs = seprint(bs, be, "HFinished\n");
@@ -1362,11 +2178,10 @@
if(version == SSL3Version) {
c->version = version;
c->finished.n = SSL3FinishedLen;
- }else if(version == TLSVersion){
+ }else {
c->version = version;
c->finished.n = TLSFinishedLen;
- }else
- return -1;
+ }
c->verset = 1;
return fprint(c->ctl, "version 0x%x", version);
}
@@ -1375,7 +2190,7 @@
static int
finishedMatch(TlsConnection *c, Finished *f)
{
- return memcmp(f->verify, c->finished.verify, f->n) == 0;
+ return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
}
// free memory associated with TlsConnection struct
@@ -1386,7 +2201,7 @@
tlsSecClose(c->sec);
freebytes(c->sid);
freebytes(c->cert);
- memset(c, 0, sizeof(c));
+ memset(c, 0, sizeof(*c));
free(c);
}
@@ -1393,36 +2208,36 @@
//================= cipher choices ========================
-static int weakCipher[CipherMax] =
+static char weakCipher[] =
{
- 1, /* TLS_NULL_WITH_NULL_NULL */
- 1, /* TLS_RSA_WITH_NULL_MD5 */
- 1, /* TLS_RSA_WITH_NULL_SHA */
- 1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
- 0, /* TLS_RSA_WITH_RC4_128_MD5 */
- 0, /* TLS_RSA_WITH_RC4_128_SHA */
- 1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */
- 0, /* TLS_RSA_WITH_IDEA_CBC_SHA */
- 1, /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */
- 0, /* TLS_RSA_WITH_DES_CBC_SHA */
- 0, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
- 1, /* TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA */
- 0, /* TLS_DH_DSS_WITH_DES_CBC_SHA */
- 0, /* TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA */
- 1, /* TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */
- 0, /* TLS_DH_RSA_WITH_DES_CBC_SHA */
- 0, /* TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA */
- 1, /* TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA */
- 0, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */
- 0, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */
- 1, /* TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA */
- 0, /* TLS_DHE_RSA_WITH_DES_CBC_SHA */
- 0, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */
- 1, /* TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 */
- 1, /* TLS_DH_anon_WITH_RC4_128_MD5 */
- 1, /* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA */
- 1, /* TLS_DH_anon_WITH_DES_CBC_SHA */
- 1, /* TLS_DH_anon_WITH_3DES_EDE_CBC_SHA */
+[TLS_NULL_WITH_NULL_NULL] 1,
+[TLS_RSA_WITH_NULL_MD5] 1,
+[TLS_RSA_WITH_NULL_SHA] 1,
+[TLS_RSA_EXPORT_WITH_RC4_40_MD5] 1,
+[TLS_RSA_WITH_RC4_128_MD5] 1,
+[TLS_RSA_WITH_RC4_128_SHA] 1,
+[TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5] 1,
+[TLS_RSA_WITH_IDEA_CBC_SHA] 0,
+[TLS_RSA_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_RSA_WITH_DES_CBC_SHA] 0,
+[TLS_RSA_WITH_3DES_EDE_CBC_SHA] 0,
+[TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_DH_DSS_WITH_DES_CBC_SHA] 0,
+[TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA] 0,
+[TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_DH_RSA_WITH_DES_CBC_SHA] 0,
+[TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA] 0,
+[TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_DHE_DSS_WITH_DES_CBC_SHA] 0,
+[TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA] 0,
+[TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_DHE_RSA_WITH_DES_CBC_SHA] 0,
+[TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA] 0,
+[TLS_DH_anon_EXPORT_WITH_RC4_40_MD5] 1,
+[TLS_DH_anon_WITH_RC4_128_MD5] 1,
+[TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA] 1,
+[TLS_DH_anon_WITH_DES_CBC_SHA] 1,
+[TLS_DH_anon_WITH_3DES_EDE_CBC_SHA] 1,
};
static int
@@ -1432,6 +2247,7 @@
for(i = 0; i < nelem(cipherAlgs); i++){
if(cipherAlgs[i].tlsid == a){
+ c->cipher = a;
c->enc = cipherAlgs[i].enc;
c->digest = cipherAlgs[i].digest;
c->nsecret = cipherAlgs[i].nsecret;
@@ -1444,7 +2260,7 @@
}
static int
-okCipher(Ints *cv)
+okCipher(Ints *cv, int ispsk)
{
int weak, i, j, c;
@@ -1451,10 +2267,14 @@
weak = 1;
for(i = 0; i < cv->len; i++) {
c = cv->data[i];
- if(c >= CipherMax)
+ if(c >= nelem(weakCipher))
weak = 0;
else
weak &= weakCipher[c];
+ if(isPSK(c) != ispsk)
+ continue;
+ if(isDHE(c) || isECDHE(c))
+ continue; /* TODO: not implemented for server */
for(j = 0; j < nelem(cipherAlgs); j++)
if(cipherAlgs[j].ok && cipherAlgs[j].tlsid == c)
return c;
@@ -1497,13 +2317,13 @@
j = open("#a/tls/encalgs", OREAD);
if(j < 0){
werrstr("can't open #a/tls/encalgs: %r");
- return 0;
+ goto out;
}
n = read(j, s, MaxAlgF-1);
close(j);
if(n <= 0){
werrstr("nothing in #a/tls/encalgs: %r");
- return 0;
+ goto out;
}
s[n] = 0;
n = getfields(s, flds, MaxAlgs, 1, " \t\r\n");
@@ -1521,13 +2341,13 @@
j = open("#a/tls/hashalgs", OREAD);
if(j < 0){
werrstr("can't open #a/tls/hashalgs: %r");
- return 0;
+ goto out;
}
n = read(j, s, MaxAlgF-1);
close(j);
if(n <= 0){
werrstr("nothing in #a/tls/hashalgs: %r");
- return 0;
+ goto out;
}
s[n] = 0;
n = getfields(s, flds, MaxAlgs, 1, " \t\r\n");
@@ -1543,12 +2363,13 @@
if(cipherAlgs[i].ok)
nciphers++;
}
+out:
unlock(&ciphLock);
return nciphers;
}
static Ints*
-makeciphers(void)
+makeciphers(int ispsk)
{
Ints *is;
int i, j;
@@ -1555,10 +2376,10 @@
is = newints(nciphers);
j = 0;
- for(i = 0; i < nelem(cipherAlgs); i++){
- if(cipherAlgs[i].ok)
+ for(i = 0; i < nelem(cipherAlgs); i++)
+ if(cipherAlgs[i].ok && isPSK(cipherAlgs[i].tlsid) == ispsk)
is->data[j++] = cipherAlgs[i].tlsid;
- }
+ is->len = j;
return is;
}
@@ -1615,20 +2436,21 @@
char *p;
int rv;
- if((p = mptoa(cipher, 16, nil, 0)) == nil)
+ p = mptoa(cipher, 16, nil, 0);
+ mpfree(cipher);
+ if(p == nil)
return nil;
rv = auth_rpc(rpc, "write", p, strlen(p));
free(p);
if(rv != ARok || auth_rpc(rpc, "read", nil, 0) != ARok)
return nil;
- mpfree(cipher);
return strtomp(rpc->arg, nil, 16, nil);
}
static void
-factotum_rsa_close(AuthRpc*rpc)
+factotum_rsa_close(AuthRpc *rpc)
{
- if(!rpc)
+ if(rpc == nil)
return;
close(rpc->afd);
auth_freerpc(rpc);
@@ -1692,20 +2514,55 @@
}
}
+static void
+p_sha256(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed, int nseed)
+{
+ uchar ai[SHA2_256dlen], tmp[SHA2_256dlen];
+ SHAstate *s;
+ int n;
+
+ // generate a1
+ s = hmac_sha2_256(label, nlabel, key, nkey, nil, nil);
+ hmac_sha2_256(seed, nseed, key, nkey, ai, s);
+
+ while(nbuf > 0) {
+ s = hmac_sha2_256(ai, SHA2_256dlen, key, nkey, nil, nil);
+ s = hmac_sha2_256(label, nlabel, key, nkey, nil, s);
+ hmac_sha2_256(seed, nseed, key, nkey, tmp, s);
+ n = SHA2_256dlen;
+ if(n > nbuf)
+ n = nbuf;
+ memmove(buf, tmp, n);
+ buf += n;
+ nbuf -= n;
+ hmac_sha2_256(ai, SHA2_256dlen, key, nkey, tmp, nil);
+ memmove(ai, tmp, SHA2_256dlen);
+ }
+}
+
// fill buf with md5(args)^sha1(args)
static void
-tlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
+tls10PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
{
- int i;
int nlabel = strlen(label);
int n = (nkey + 1) >> 1;
- for(i = 0; i < nbuf; i++)
- buf[i] = 0;
+ memset(buf, 0, nbuf);
tlsPmd5(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1);
tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1);
}
+static void
+tls12PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
+{
+ uchar seed[2*RandomSize];
+
+ assert(nseed0+nseed1 <= sizeof(seed));
+ memmove(seed, seed0, nseed0);
+ memmove(seed+nseed0, seed1, nseed1);
+ p_sha256(buf, nbuf, key, nkey, (uchar*)label, strlen(label), seed, nseed0+nseed1);
+}
+
/*
* for setting server session id's
*/
@@ -1742,17 +2599,29 @@
}
static int
-tlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd)
+tlsSecRSAs(TlsSec *sec, int vers, Bytes *epm)
{
- if(epm != nil){
- if(setVers(sec, vers) < 0)
- goto Err;
- serverMasterSecret(sec, epm, nepm);
- }else if(sec->vers != vers){
- werrstr("mismatched session versions");
+ Bytes *pm;
+
+ if(setVers(sec, vers) < 0)
goto Err;
+ if(epm == nil){
+ werrstr("no encrypted premaster secret");
+ goto Err;
}
- setSecrets(sec, kd, nkd);
+ // if the client messed up, just continue as if everything is ok,
+ // to prevent attacks to check for correctly formatted messages.
+ // Hence the fprint(2,) can't be replaced by tlsError(), which sends an Alert msg to the client.
+ pm = pkcs1_decrypt(sec, epm);
+ if(sec->ok < 0 || pm == nil || pm->len != MasterSecretSize || get16(pm->data) != sec->clientVers){
+ fprint(2, "tlsSecRSAs failed ok=%d pm=%p pmvers=%x cvers=%x nepm=%d\n",
+ sec->ok, pm, pm != nil ? get16(pm->data) : -1, sec->clientVers, epm->len);
+ sec->ok = -1;
+ freebytes(pm);
+ pm = newbytes(MasterSecretSize);
+ genrandom(pm->data, MasterSecretSize);
+ }
+ setMasterSecret(sec, pm);
return 0;
Err:
sec->ok = -1;
@@ -1759,6 +2628,17 @@
return -1;
}
+static int
+tlsSecPSKs(TlsSec *sec, int vers)
+{
+ if(setVers(sec, vers) < 0){
+ sec->ok = -1;
+ return -1;
+ }
+ setMasterSecret(sec, newbytes(sec->psklen));
+ return 0;
+}
+
static TlsSec*
tlsSecInitc(int cvers, uchar *crandom)
{
@@ -1771,40 +2651,49 @@
}
static int
-tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd)
+tlsSecPSKc(TlsSec *sec, uchar *srandom, int vers)
{
+ memmove(sec->srandom, srandom, RandomSize);
+ if(setVers(sec, vers) < 0){
+ sec->ok = -1;
+ return -1;
+ }
+ setMasterSecret(sec, newbytes(sec->psklen));
+ return 0;
+}
+
+static Bytes*
+tlsSecRSAc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers)
+{
RSApub *pub;
+ Bytes *pm, *epm;
- pub = nil;
-
USED(sid);
USED(nsid);
memmove(sec->srandom, srandom, RandomSize);
-
if(setVers(sec, vers) < 0)
goto Err;
-
pub = X509toRSApub(cert, ncert, nil, 0);
if(pub == nil){
werrstr("invalid x509/rsa certificate");
goto Err;
}
- if(clientMasterSecret(sec, pub, epm, nepm) < 0)
- goto Err;
+ pm = newbytes(MasterSecretSize);
+ put16(pm->data, sec->clientVers);
+ genrandom(pm->data+2, MasterSecretSize - 2);
+ epm = pkcs1_encrypt(pm, pub, 2);
+ setMasterSecret(sec, pm);
rsapubfree(pub);
- setSecrets(sec, kd, nkd);
- return 0;
-
+ if(epm != nil)
+ return epm;
Err:
- if(pub != nil)
- rsapubfree(pub);
sec->ok = -1;
- return -1;
+ return nil;
}
static int
-tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient)
+tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
{
if(sec->nfin != nfin){
sec->ok = -1;
@@ -1811,9 +2700,10 @@
werrstr("invalid finished exchange");
return -1;
}
- md5.malloced = 0;
- sha1.malloced = 0;
- (*sec->setFinished)(sec, md5, sha1, fin, isclient);
+ hsh.md5.malloced = 0;
+ hsh.sha1.malloced = 0;
+ hsh.sha2_256.malloced = 0;
+ (*sec->setFinished)(sec, hsh, fin, isclient);
return 1;
}
@@ -1836,7 +2726,7 @@
static void
tlsSecClose(TlsSec *sec)
{
- if(!sec)
+ if(sec == nil)
return;
factotum_rsa_close(sec->rpc);
free(sec->server);
@@ -1850,13 +2740,14 @@
sec->setFinished = sslSetFinished;
sec->nfin = SSL3FinishedLen;
sec->prf = sslPRF;
- }else if(v == TLSVersion){
- sec->setFinished = tlsSetFinished;
+ }else if(v < TLS12Version) {
+ sec->setFinished = tls10SetFinished;
sec->nfin = TLSFinishedLen;
- sec->prf = tlsPRF;
- }else{
- werrstr("invalid version");
- return -1;
+ sec->prf = tls10PRF;
+ }else {
+ sec->setFinished = tls12SetFinished;
+ sec->nfin = TLSFinishedLen;
+ sec->prf = tls12PRF;
}
sec->vers = v;
return 0;
@@ -1877,74 +2768,37 @@
}
/*
- * set the master secret from the pre-master secret.
+ * set the master secret from the pre-master secret,
+ * destroys premaster.
*/
static void
setMasterSecret(TlsSec *sec, Bytes *pm)
{
- (*sec->prf)(sec->sec, MasterSecretSize, pm->data, MasterSecretSize, "master secret",
- sec->crandom, RandomSize, sec->srandom, RandomSize);
-}
+ if(sec->psklen > 0){
+ Bytes *opm = pm;
+ uchar *p;
-static void
-serverMasterSecret(TlsSec *sec, uchar *epm, int nepm)
-{
- Bytes *pm;
+ /* concatenate psk to pre-master secret */
+ pm = newbytes(4 + opm->len + sec->psklen);
+ p = pm->data;
+ put16(p, opm->len), p += 2;
+ memmove(p, opm->data, opm->len), p += opm->len;
+ put16(p, sec->psklen), p += 2;
+ memmove(p, sec->psk, sec->psklen);
- pm = pkcs1_decrypt(sec, epm, nepm);
-
- // if the client messed up, just continue as if everything is ok,
- // to prevent attacks to check for correctly formatted messages.
- // Hence the fprint(2,) can't be replaced by tlsError(), which sends an Alert msg to the client.
- if(sec->ok < 0 || pm == nil || get16(pm->data) != sec->clientVers){
- fprint(2, "serverMasterSecret failed ok=%d pm=%p pmvers=%x cvers=%x nepm=%d\n",
- sec->ok, pm, pm ? get16(pm->data) : -1, sec->clientVers, nepm);
- sec->ok = -1;
- if(pm != nil)
- freebytes(pm);
- pm = newbytes(MasterSecretSize);
- genrandom(pm->data, MasterSecretSize);
+ memset(opm->data, 0, opm->len);
+ freebytes(opm);
}
- setMasterSecret(sec, pm);
- memset(pm->data, 0, pm->len);
- freebytes(pm);
-}
-static int
-clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm)
-{
- Bytes *pm, *key;
+ (*sec->prf)(sec->sec, MasterSecretSize, pm->data, pm->len, "master secret",
+ sec->crandom, RandomSize, sec->srandom, RandomSize);
- pm = newbytes(MasterSecretSize);
- put16(pm->data, sec->clientVers);
- genrandom(pm->data+2, MasterSecretSize - 2);
-
- setMasterSecret(sec, pm);
-
- key = pkcs1_encrypt(pm, pub, 2);
- memset(pm->data, 0, pm->len);
+ memset(pm->data, 0, pm->len);
freebytes(pm);
- if(key == nil){
- werrstr("tls pkcs1_encrypt failed");
- return -1;
- }
-
- *nepm = key->len;
- *epm = malloc(*nepm);
- if(*epm == nil){
- freebytes(key);
- werrstr("out of memory");
- return -1;
- }
- memmove(*epm, key->data, *nepm);
-
- freebytes(key);
-
- return 1;
}
static void
-sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient)
+sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient)
{
DigestState *s;
uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
@@ -1955,21 +2809,21 @@
else
label = "SRVR";
- md5((uchar*)label, 4, nil, &hsmd5);
- md5(sec->sec, MasterSecretSize, nil, &hsmd5);
+ md5((uchar*)label, 4, nil, &hsh.md5);
+ md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
memset(pad, 0x36, 48);
- md5(pad, 48, nil, &hsmd5);
- md5(nil, 0, h0, &hsmd5);
+ md5(pad, 48, nil, &hsh.md5);
+ md5(nil, 0, h0, &hsh.md5);
memset(pad, 0x5C, 48);
s = md5(sec->sec, MasterSecretSize, nil, nil);
s = md5(pad, 48, nil, s);
md5(h0, MD5dlen, finished, s);
- sha1((uchar*)label, 4, nil, &hssha1);
- sha1(sec->sec, MasterSecretSize, nil, &hssha1);
+ sha1((uchar*)label, 4, nil, &hsh.sha1);
+ sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
memset(pad, 0x36, 40);
- sha1(pad, 40, nil, &hssha1);
- sha1(nil, 0, h1, &hssha1);
+ sha1(pad, 40, nil, &hsh.sha1);
+ sha1(nil, 0, h1, &hsh.sha1);
memset(pad, 0x5C, 40);
s = sha1(sec->sec, MasterSecretSize, nil, nil);
s = sha1(pad, 40, nil, s);
@@ -1978,27 +2832,43 @@
// fill "finished" arg with md5(args)^sha1(args)
static void
-tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient)
+tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient)
{
uchar h0[MD5dlen], h1[SHA1dlen];
char *label;
// get current hash value, but allow further messages to be hashed in
- md5(nil, 0, h0, &hsmd5);
- sha1(nil, 0, h1, &hssha1);
+ md5(nil, 0, h0, &hsh.md5);
+ sha1(nil, 0, h1, &hsh.sha1);
if(isClient)
label = "client finished";
else
label = "server finished";
- tlsPRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen);
+ tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen);
}
static void
+tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient)
+{
+ uchar seed[SHA2_256dlen];
+ char *label;
+
+ // get current hash value, but allow further messages to be hashed in
+ sha2_256(nil, 0, seed, &hsh.sha2_256);
+
+ if(isClient)
+ label = "client finished";
+ else
+ label = "server finished";
+ p_sha256(finished, TLSFinishedLen, sec->sec, MasterSecretSize, (uchar*)label, strlen(label), seed, SHA2_256dlen);
+}
+
+static void
sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
{
- DigestState *s;
uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
+ DigestState *s;
int i, n, len;
USED(label);
@@ -2027,10 +2897,7 @@
static mpint*
bytestomp(Bytes* bytes)
{
- mpint* ans;
-
- ans = betomp(bytes->data, bytes->len, nil);
- return ans;
+ return betomp(bytes->data, bytes->len, nil);
}
/*
@@ -2039,13 +2906,13 @@
static Bytes*
mptobytes(mpint* big)
{
- int n, m;
- uchar *a;
Bytes* ans;
+ int n;
n = (mpsignif(big)+7)/8;
- m = mptobe(big, nil, n, &a);
- ans = makebytes(a, m);
+ if(n == 0) n = 1;
+ ans = newbytes(n);
+ mptober(big, ans->data, ans->len);
return ans;
}
@@ -2063,6 +2930,7 @@
mpfree(x);
ybytes = mptobytes(y);
ylen = ybytes->len;
+ mpfree(y);
if(ylen < modlen) {
a = newbytes(modlen);
@@ -2078,7 +2946,6 @@
freebytes(ybytes);
ybytes = a;
}
- mpfree(y);
return ybytes;
}
@@ -2119,36 +2986,34 @@
// decrypt data according to PKCS#1, with given key.
// expect a block type of 2.
static Bytes*
-pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm)
+pkcs1_decrypt(TlsSec *sec, Bytes *cipher)
{
- Bytes *eb, *ans = nil;
+ Bytes *eb;
int i, modlen;
mpint *x, *y;
modlen = (mpsignif(sec->rsapub->n)+7)/8;
- if(nepm != modlen)
+ if(cipher->len != modlen)
return nil;
- x = betomp(epm, nepm, nil);
+ x = bytestomp(cipher);
y = factotum_rsa_decrypt(sec->rpc, x);
if(y == nil)
return nil;
- eb = mptobytes(y);
- if(eb->len < modlen){ // pad on left with zeros
- ans = newbytes(modlen);
- memset(ans->data, 0, modlen-eb->len);
- memmove(ans->data+modlen-eb->len, eb->data, eb->len);
- freebytes(eb);
- eb = ans;
- }
+ eb = newbytes(modlen);
+ mptober(y, eb->data, eb->len);
+ mpfree(y);
if(eb->data[0] == 0 && eb->data[1] == 2) {
- for(i = 2; i < modlen; i++)
+ for(i = 2; i < eb->len; i++)
if(eb->data[i] == 0)
break;
- if(i < modlen - 1)
- ans = makebytes(eb->data+i+1, modlen-(i+1));
+ if(++i < eb->len){
+ eb->len -= i;
+ memmove(eb->data, eb->data+i, eb->len);
+ return eb;
+ }
}
freebytes(eb);
- return ans;
+ return nil;
}
@@ -2161,10 +3026,10 @@
if(n==0)
n=1;
p = malloc(n);
- if(p == nil){
- exits("out of memory");
- }
+ if(p == nil)
+ sysfatal("out of memory");
memset(p, 0, n);
+ setmalloctag(p, getcallerpc(&n));
return p;
}
@@ -2173,11 +3038,11 @@
{
if(ReallocN == 0)
ReallocN = 1;
- if(!ReallocP)
+ if(ReallocP == nil)
ReallocP = emalloc(ReallocN);
- else if(!(ReallocP = realloc(ReallocP, ReallocN))){
- exits("out of memory");
- }
+ else if((ReallocP = realloc(ReallocP, ReallocN)) == nil)
+ sysfatal("out of memory");
+ setrealloctag(ReallocP, getcallerpc(&ReallocP));
return(ReallocP);
}
@@ -2223,20 +3088,14 @@
return (p[0]<<8)|p[1];
}
-/* ANSI offsetof() */
-#define OFFSET(x, s) ((int)(&(((s*)0)->x)))
-
-/*
- * malloc and return a new Bytes structure capable of
- * holding len bytes. (len >= 0)
- * Used to use crypt_malloc, which aborts if malloc fails.
- */
static Bytes*
newbytes(int len)
{
Bytes* ans;
- ans = (Bytes*)malloc(OFFSET(data[0], Bytes) + len);
+ if(len < 0)
+ abort();
+ ans = emalloc(sizeof(Bytes) + len);
ans->len = len;
return ans;
}
@@ -2257,8 +3116,7 @@
static void
freebytes(Bytes* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
/* len is number of ints */
@@ -2267,25 +3125,15 @@
{
Ints* ans;
- ans = (Ints*)malloc(OFFSET(data[0], Ints) + len*sizeof(int));
+ if(len < 0 || len > ((uint)-1>>1)/sizeof(int))
+ abort();
+ ans = emalloc(sizeof(Ints) + len*sizeof(int));
ans->len = len;
return ans;
}
-static Ints*
-makeints(int* buf, int len)
-{
- Ints* ans;
-
- ans = newints(len);
- if(len > 0)
- memmove(ans->data, buf, len*sizeof(int));
- return ans;
-}
-
static void
freeints(Ints* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
--- /dev/null
+++ b/libsec/tsmemcmp.c
@@ -1,0 +1,26 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+/*
+ * timing safe memcmp()
+ */
+int
+tsmemcmp(void *a1, void *a2, ulong n)
+{
+ int lt, gt, c1, c2, r, m;
+ uchar *s1, *s2;
+
+ r = m = 0;
+ s1 = a1;
+ s2 = a2;
+ while(n--){
+ c1 = *s1++;
+ c2 = *s2++;
+ lt = (c1 - c2) >> 8;
+ gt = (c2 - c1) >> 8;
+ r |= (lt - gt) & ~m;
+ m |= lt | gt;
+ }
+ return r;
+}
--- a/libsec/x509.c
+++ b/libsec/x509.c
@@ -3,11 +3,6 @@
#include <mp.h>
#include <libsec.h>
-typedef DigestState*(*DigestFun)(uchar*,ulong,uchar*,DigestState*);
-
-/* ANSI offsetof, backwards. */
-#define OFFSETOF(a, b) offsetof(b, a)
-
/*=============================================================*/
/* general ASN1 declarations and parsing
*
@@ -40,6 +35,7 @@
#define REAL 9
#define ENUMERATED 10
#define EMBEDDED_PDV 11
+#define UTF8String 12
#define SEQUENCE 16 /* also SEQUENCE OF */
#define SETOF 17 /* also SETOF OF */
#define NumericString 18
@@ -62,13 +58,13 @@
struct Ints {
int len;
- int data[1];
+ int data[];
};
struct Bits {
int len; /* number of bytes */
int unusedbits; /* unused bits in last byte */
- uchar data[1]; /* most-significant bit first */
+ uchar data[]; /* most-significant bit first */
};
struct Tag {
@@ -134,15 +130,12 @@
static int is_string(Elem* pe, char** pstring);
static int is_time(Elem* pe, char** ptime);
static int decode(uchar* a, int alen, Elem* pelem);
-static int decode_seq(uchar* a, int alen, Elist** pelist);
-static int decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval);
static int encode(Elem e, Bytes** pbytes);
static int oid_lookup(Ints* o, Ints** tab);
static void freevalfields(Value* v);
static mpint *asn1mpint(Elem *e);
+static void edump(Elem);
-
-
#define TAG_MASK 0x1F
#define CONSTR_MASK 0x20
#define CLASS_MASK 0xC0
@@ -168,10 +161,10 @@
if(n==0)
n=1;
p = malloc(n);
- if(p == nil){
- exits("out of memory");
- }
+ if(p == nil)
+ sysfatal("out of memory");
memset(p, 0, n);
+ setmalloctag(p, getcallerpc(&n));
return p;
}
@@ -178,14 +171,13 @@
static char*
estrdup(char *s)
{
- char *d, *d0;
+ char *d;
+ int n;
- if(!s)
- return 0;
- d = d0 = emalloc(strlen(s)+1);
- while(*d++ = *s++)
- ;
- return d0;
+ n = strlen(s)+1;
+ d = emalloc(n);
+ memmove(d, s, n);
+ return d;
}
@@ -199,40 +191,15 @@
decode(uchar* a, int alen, Elem* pelem)
{
uchar* p = a;
+ int err;
- return ber_decode(&p, &a[alen], pelem);
+ err = ber_decode(&p, &a[alen], pelem);
+ if(err == ASN_OK && p != &a[alen])
+ err = ASN_EVALLEN;
+ return err;
}
/*
- * Like decode, but continue decoding after first element
- * of array ends.
- */
-static int
-decode_seq(uchar* a, int alen, Elist** pelist)
-{
- uchar* p = a;
-
- return seq_decode(&p, &a[alen], -1, 1, pelist);
-}
-
-/*
- * Decode the whole array as a BER encoding of an ASN1 value,
- * (i.e., the part after the tag and length).
- * Assume the value is encoded as universal tag "kind".
- * The constr arg is 1 if the value is constructed, 0 if primitive.
- * If there's an error, the return string will contain the error.
- * Depending on the error, the returned value may or may not
- * be nil.
- */
-static int
-decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval)
-{
- uchar* p = a;
-
- return value_decode(&p, &a[alen], alen, kind, isconstr, pval);
-}
-
-/*
* All of the following decoding routines take arguments:
* uchar **pp;
* uchar *pend;
@@ -255,6 +222,7 @@
Tag tag;
Value val;
+ memset(pelem, 0, sizeof(*pelem));
err = tag_decode(pp, pend, &tag, &isconstr);
if(err == ASN_OK) {
err = length_decode(pp, pend, &length);
@@ -316,8 +284,6 @@
v = *p++;
if(v&0x80)
err = int_decode(&p, pend, v&0x7F, 1, &num);
- else if(v == 0x80)
- num = -1;
else
num = v;
}
@@ -398,8 +364,7 @@
pval->u.bitstringval = makebits(0, 0, 0);
p += 2;
}
- else
- /* TODO: recurse and concat results */
+ else /* TODO: recurse and concat results */
err = ASN_EUNIMPL;
}
else {
@@ -513,7 +478,7 @@
pval->u.setval = vl;
}
break;
-
+ case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@@ -573,7 +538,7 @@
err = ASN_ETOOBIG;
else {
if(!unsgned && count > 0 && count < 4 && (*p&0x80))
- num = -1; // set all bits, initially
+ num = -1; /* set all bits, initially */
while(count--)
num = (num << 8)|(*p++);
}
@@ -661,18 +626,17 @@
switch(elem.val.tag) {
case VOctets:
newans = catbytes(ans, elem.val.u.octetsval);
+ freevalfields(&elem.val);
freebytes(ans);
ans = newans;
break;
case VEOC:
- if(length != -1) {
- p = pold;
- err = ASN_EINVAL;
- }
- goto cloop_done;
-
+ if(length == -1)
+ goto cloop_done;
+ /* no break */
default:
+ freevalfields(&elem.val);
p = pold;
err = ASN_EINVAL;
goto cloop_done;
@@ -679,7 +643,10 @@
}
}
cloop_done:
- ;
+ if(err != ASN_OK){
+ freebytes(ans);
+ ans = nil;
+ }
}
*pp = p;
*pbytes = ans;
@@ -732,7 +699,9 @@
else
lve = mkel(elem, lve);
}
- if(err == ASN_OK) {
+ if(err != ASN_OK)
+ freeelist(lve);
+ else {
/* reverse back to original order */
while(lve != nil) {
lveold = lve;
@@ -972,8 +941,8 @@
memmove(p, bb->data, bb->len);
p += bb->len;
}
- else
- err = ASN_EINVAL;
+ else
+ err = ASN_EINVAL;
break;
case NULLTAG:
@@ -1014,6 +983,7 @@
}
break;
+ case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@@ -1189,21 +1159,8 @@
static int
is_bigint(Elem* pe, Bytes** pbigint)
{
- int v, n, i;
-
- if(pe->tag.class == Universal && pe->tag.num == INTEGER) {
- if(pe->val.tag == VBigInt)
- *pbigint = pe->val.u.bigintval;
- else if(pe->val.tag == VInt){
- v = pe->val.u.intval;
- for(n = 1; n < 4; n++)
- if((1 << (8 * n)) > v)
- break;
- *pbigint = newbytes(n);
- for(i = 0; i < n; i++)
- (*pbigint)->data[i] = (v >> ((n - 1 - i) * 8));
- }else
- return 0;
+ if(pe->tag.class == Universal && pe->tag.num == INTEGER && pe->val.tag == VBigInt) {
+ *pbigint = pe->val.u.bigintval;
return 1;
}
return 0;
@@ -1244,6 +1201,7 @@
{
if(pe->tag.class == Universal) {
switch(pe->tag.num) {
+ case UTF8String:
case NumericString:
case PrintableString:
case TeletexString:
@@ -1285,7 +1243,9 @@
{
Bytes* ans;
- ans = (Bytes*)emalloc(OFFSETOF(data[0], Bytes) + len);
+ if(len < 0)
+ abort();
+ ans = emalloc(sizeof(Bytes) + len);
ans->len = len;
return ans;
}
@@ -1306,8 +1266,7 @@
static void
freebytes(Bytes* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
/*
@@ -1345,7 +1304,9 @@
{
Ints* ans;
- ans = (Ints*)emalloc(OFFSETOF(data[0], Ints) + len*sizeof(int));
+ if(len < 0 || len > ((uint)-1>>1)/sizeof(int))
+ abort();
+ ans = emalloc(sizeof(Ints) + len*sizeof(int));
ans->len = len;
return ans;
}
@@ -1356,8 +1317,7 @@
Ints* ans;
ans = newints(len);
- if(len > 0)
- memmove(ans->data, buf, len*sizeof(int));
+ memmove(ans->data, buf, len*sizeof(int));
return ans;
}
@@ -1364,8 +1324,7 @@
static void
freeints(Ints* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
/* len is number of bytes */
@@ -1374,7 +1333,9 @@
{
Bits* ans;
- ans = (Bits*)emalloc(OFFSETOF(data[0], Bits) + len);
+ if(len < 0)
+ abort();
+ ans = emalloc(sizeof(Bits) + len);
ans->len = len;
ans->unusedbits = 0;
return ans;
@@ -1394,8 +1355,7 @@
static void
freebits(Bits* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
static Elist*
@@ -1404,6 +1364,7 @@
Elist* el;
el = (Elist*)emalloc(sizeof(Elist));
+ setmalloctag(el, getcallerpc(&e));
el->hd = e;
el->tl = tail;
return el;
@@ -1461,7 +1422,7 @@
freeints(v->u.objidval);
break;
case VString:
- if (v->u.stringval)
+ if(v->u.stringval)
free(v->u.stringval);
break;
case VSeq:
@@ -1468,15 +1429,13 @@
el = v->u.seqval;
for(l = el; l != nil; l = l->tl)
freevalfields(&l->hd.val);
- if (el)
- freeelist(el);
+ freeelist(el);
break;
case VSet:
el = v->u.setval;
for(l = el; l != nil; l = l->tl)
freevalfields(&l->hd.val);
- if (el)
- freeelist(el);
+ freeelist(el);
break;
}
}
@@ -1564,6 +1523,7 @@
Bytes* publickey;
int signature_alg;
Bytes* signature;
+ int curve;
} CertX509;
/* Algorithm object-ids */
@@ -1572,45 +1532,140 @@
ALG_md2WithRSAEncryption,
ALG_md4WithRSAEncryption,
ALG_md5WithRSAEncryption,
+
ALG_sha1WithRSAEncryption,
+ ALG_sha1WithRSAEncryptionOiw,
+
+ ALG_sha256WithRSAEncryption,
+ ALG_sha384WithRSAEncryption,
+ ALG_sha512WithRSAEncryption,
+ ALG_sha224WithRSAEncryption,
+
+ ALG_ecPublicKey,
+ ALG_sha1WithECDSA,
+ ALG_sha256WithECDSA,
+ ALG_sha384WithECDSA,
+ ALG_sha512WithECDSA,
+
ALG_md5,
+ ALG_sha1,
+ ALG_sha256,
+ ALG_sha384,
+ ALG_sha512,
+ ALG_sha224,
+
NUMALGS
};
-typedef struct Ints7 {
+
+typedef struct Ints15 {
int len;
- int data[7];
-} Ints7;
-static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
-static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
-static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
-static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
-static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
-static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
+ int data[15];
+} Ints15;
+
+typedef struct DigestAlg {
+ int alg;
+ DigestState* (*fun)(uchar*,ulong,uchar*,DigestState*);
+ int len;
+} DigestAlg;
+
+static DigestAlg alg_md5 = { ALG_md5, md5, MD5dlen};
+static DigestAlg alg_sha1 = { ALG_sha1, sha1, SHA1dlen };
+static DigestAlg alg_sha256 = { ALG_sha256, sha2_256, SHA2_256dlen };
+static DigestAlg alg_sha384 = { ALG_sha384, sha2_384, SHA2_384dlen };
+static DigestAlg alg_sha512 = { ALG_sha512, sha2_512, SHA2_512dlen };
+static DigestAlg alg_sha224 = { ALG_sha224, sha2_224, SHA2_224dlen };
+
+/* maximum length of digest output of the digest algs above */
+enum {
+ MAXdlen = SHA2_512dlen,
+};
+
+static Ints15 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
+
+static Ints15 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
+static Ints15 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
+static Ints15 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
+static Ints15 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
+static Ints15 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 };
+static Ints15 oid_sha256WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 11 };
+static Ints15 oid_sha384WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 12 };
+static Ints15 oid_sha512WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 13 };
+static Ints15 oid_sha224WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 14 };
+
+static Ints15 oid_ecPublicKey = {6, 1, 2, 840, 10045, 2, 1 };
+static Ints15 oid_sha1WithECDSA = {6, 1, 2, 840, 10045, 4, 1 };
+static Ints15 oid_sha256WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 2 };
+static Ints15 oid_sha384WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 3 };
+static Ints15 oid_sha512WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 4 };
+
+static Ints15 oid_md5 = {6, 1, 2, 840, 113549, 2, 5 };
+static Ints15 oid_sha1 = {6, 1, 3, 14, 3, 2, 26 };
+static Ints15 oid_sha256= {9, 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+static Ints15 oid_sha384= {9, 2, 16, 840, 1, 101, 3, 4, 2, 2 };
+static Ints15 oid_sha512= {9, 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+static Ints15 oid_sha224= {9, 2, 16, 840, 1, 101, 3, 4, 2, 4 };
+
static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)&oid_rsaEncryption,
(Ints*)&oid_md2WithRSAEncryption,
(Ints*)&oid_md4WithRSAEncryption,
(Ints*)&oid_md5WithRSAEncryption,
+
(Ints*)&oid_sha1WithRSAEncryption,
+ (Ints*)&oid_sha1WithRSAEncryptionOiw,
+
+ (Ints*)&oid_sha256WithRSAEncryption,
+ (Ints*)&oid_sha384WithRSAEncryption,
+ (Ints*)&oid_sha512WithRSAEncryption,
+ (Ints*)&oid_sha224WithRSAEncryption,
+
+ (Ints*)&oid_ecPublicKey,
+ (Ints*)&oid_sha1WithECDSA,
+ (Ints*)&oid_sha256WithECDSA,
+ (Ints*)&oid_sha384WithECDSA,
+ (Ints*)&oid_sha512WithECDSA,
+
(Ints*)&oid_md5,
+ (Ints*)&oid_sha1,
+ (Ints*)&oid_sha256,
+ (Ints*)&oid_sha384,
+ (Ints*)&oid_sha512,
+ (Ints*)&oid_sha224,
nil
};
-static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, nil };
+static DigestAlg *digestalg[NUMALGS+1] = {
+ &alg_md5, &alg_md5, &alg_md5, &alg_md5,
+ &alg_sha1, &alg_sha1,
+ &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
+ &alg_sha256, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512,
+ &alg_md5, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
+ nil
+};
+
+static Ints15 oid_secp256r1 = {7, 1, 2, 840, 10045, 3, 1, 7};
+
+static Ints *namedcurves_oid_tab[] = {
+ (Ints*)&oid_secp256r1,
+ nil,
+};
+static void (*namedcurves[])(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h) = {
+ secp256r1,
+ nil,
+};
+
static void
freecert(CertX509* c)
{
- if (!c) return;
- if(c->issuer != nil)
- free(c->issuer);
- if(c->validity_start != nil)
- free(c->validity_start);
- if(c->validity_end != nil)
- free(c->validity_end);
- if(c->subject != nil)
- free(c->subject);
+ if(c == nil)
+ return;
+ free(c->issuer);
+ free(c->validity_start);
+ free(c->validity_end);
+ free(c->subject);
freebytes(c->publickey);
freebytes(c->signature);
+ free(c);
}
/*
@@ -1690,6 +1745,17 @@
return oid_lookup(oid, alg_oid_tab);
}
+static int
+parse_curve(Elem* e)
+{
+ Elist* el;
+ Ints* oid;
+
+ if(!is_seq(e, &el) || elistlen(el)<2 || !is_oid(&el->tl->hd, &oid))
+ return -1;
+ return oid_lookup(oid, namedcurves_oid_tab);
+}
+
static CertX509*
decode_cert(Bytes* a)
{
@@ -1792,7 +1858,7 @@
goto errret;
/* SubjectPublicKeyInfo */
- if(!is_seq(epubkey, &elpubkey))
+ if(!is_seq(epubkey, &elpubkey))
goto errret;
if(elistlen(elpubkey) != 2)
goto errret;
@@ -1800,6 +1866,12 @@
c->publickey_alg = parse_alg(&elpubkey->hd);
if(c->publickey_alg < 0)
goto errret;
+ c->curve = -1;
+ if(c->publickey_alg == ALG_ecPublicKey){
+ c->curve = parse_curve(&elpubkey->hd);
+ if(c->curve < 0)
+ goto errret;
+ }
if(!is_bitstring(&elpubkey->tl->hd, &bits))
goto errret;
if(bits->unusedbits != 0)
@@ -1824,7 +1896,7 @@
}
/*
- * RSAPublickKey :: SEQUENCE {
+ * RSAPublickKey ::= SEQUENCE {
* modulus INTEGER,
* publicExponent INTEGER
* }
@@ -1834,7 +1906,6 @@
{
Elem e;
Elist *el;
- mpint *mp;
RSApub* key;
key = rsapuballoc();
@@ -1842,17 +1913,15 @@
goto errret;
if(!is_seq(&e, &el) || elistlen(el) != 2)
goto errret;
-
- key->n = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->n = asn1mpint(&el->hd)) == nil)
goto errret;
-
el = el->tl;
- key->ek = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->ek = asn1mpint(&el->hd)) == nil)
goto errret;
+ freevalfields(&e.val);
return key;
errret:
+ freevalfields(&e.val);
rsapubfree(key);
return nil;
}
@@ -1875,7 +1944,6 @@
int version;
Elem e;
Elist *el;
- mpint *mp;
RSApriv* key;
key = rsaprivalloc();
@@ -1887,70 +1955,115 @@
goto errret;
el = el->tl;
- key->pub.n = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->pub.n = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->pub.ek = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->pub.ek = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->dk = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->dk = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->q = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->q = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->p = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->p = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->kq = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->kq = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->kp = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->kp = asn1mpint(&el->hd)) == nil)
goto errret;
el = el->tl;
- key->c2 = mp = asn1mpint(&el->hd);
- if(mp == nil)
+ if((key->c2 = asn1mpint(&el->hd)) == nil)
goto errret;
+ freevalfields(&e.val);
return key;
errret:
+ freevalfields(&e.val);
rsaprivfree(key);
return nil;
}
+/*
+ * DSAPrivateKey ::= SEQUENCE{
+ * version Version,
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER, -- alpha
+ * pub_key INTEGER, -- key
+ * priv_key INTEGER, -- secret
+ * }
+ */
+static DSApriv*
+decode_dsaprivkey(Bytes* a)
+{
+ int version;
+ Elem e;
+ Elist *el;
+ DSApriv* key;
+
+ key = dsaprivalloc();
+ if(decode(a->data, a->len, &e) != ASN_OK)
+ goto errret;
+ if(!is_seq(&e, &el) || elistlen(el) != 6)
+ goto errret;
+ version = -1;
+ if(!is_int(&el->hd, &version) || version != 0)
+ goto errret;
+
+ el = el->tl;
+ if((key->pub.p = asn1mpint(&el->hd)) == nil)
+ goto errret;
+
+ el = el->tl;
+ if((key->pub.q = asn1mpint(&el->hd)) == nil)
+ goto errret;
+
+ el = el->tl;
+ if((key->pub.alpha = asn1mpint(&el->hd)) == nil)
+ goto errret;
+
+ el = el->tl;
+ if((key->pub.key = asn1mpint(&el->hd)) == nil)
+ goto errret;
+
+ el = el->tl;
+ if((key->secret = asn1mpint(&el->hd)) == nil)
+ goto errret;
+
+ freevalfields(&e.val);
+ return key;
+errret:
+ freevalfields(&e.val);
+ dsaprivfree(key);
+ return nil;
+}
+
static mpint*
asn1mpint(Elem *e)
{
Bytes *b;
- mpint *mp;
int v;
if(is_int(e, &v))
return itomp(v, nil);
- if(is_bigint(e, &b)) {
- mp = betomp(b->data, b->len, nil);
- freebytes(b);
- return mp;
- }
+ if(is_bigint(e, &b))
+ return betomp(b->data, b->len, nil);
return nil;
}
-static mpint*
-pkcs1pad(Bytes *b, mpint *modulus)
+mpint*
+pkcs1padbuf(uchar *buf, int len, mpint *modulus)
{
int n = (mpsignif(modulus)+7)/8;
int pm1, i;
@@ -1957,7 +2070,7 @@
uchar *p;
mpint *mp;
- pm1 = n - 1 - b->len;
+ pm1 = n - 1 - len;
p = (uchar*)emalloc(n);
p[0] = 0;
p[1] = 1;
@@ -1964,12 +2077,18 @@
for(i = 2; i < pm1; i++)
p[i] = 0xFF;
p[pm1] = 0;
- memcpy(&p[pm1+1], b->data, b->len);
+ memcpy(&p[pm1+1], buf, len);
mp = betomp(p, n, nil);
free(p);
return mp;
}
+static mpint*
+pkcs1pad(Bytes *b, mpint *modulus)
+{
+ return pkcs1padbuf(b->data, b->len, modulus);
+}
+
RSApriv*
asn1toRSApriv(uchar *kd, int kn)
{
@@ -1982,13 +2101,25 @@
return key;
}
+DSApriv*
+asn1toDSApriv(uchar *kd, int kn)
+{
+ Bytes *b;
+ DSApriv *key;
+
+ b = makebytes(kd, kn);
+ key = decode_dsaprivkey(b);
+ freebytes(b);
+ return key;
+}
+
/*
* digest(CertificateInfo)
* Our ASN.1 library doesn't return pointers into the original
* data array, so we need to do a little hand decoding.
*/
-static void
-digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest)
+static int
+digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
{
uchar *info, *p, *pend;
ulong infolen;
@@ -1999,50 +2130,178 @@
p = cert->data;
pend = cert->data + cert->len;
if(tag_decode(&p, pend, &tag, &isconstr) != ASN_OK ||
- tag.class != Universal || tag.num != SEQUENCE ||
- length_decode(&p, pend, &length) != ASN_OK ||
- p+length > pend)
- return;
+ tag.class != Universal || tag.num != SEQUENCE ||
+ length_decode(&p, pend, &length) != ASN_OK ||
+ p+length > pend ||
+ p+length < p)
+ return -1;
info = p;
- if(ber_decode(&p, pend, &elem) != ASN_OK || elem.tag.num != SEQUENCE)
- return;
+ if(ber_decode(&p, pend, &elem) != ASN_OK)
+ return -1;
+ freevalfields(&elem.val);
+ if(elem.tag.num != SEQUENCE)
+ return -1;
infolen = p - info;
- (*digestfun)(info, infolen, digest, nil);
+ (*da->fun)(info, infolen, digest, nil);
+ return da->len;
}
-static char*
-verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
+static int
+pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf)
{
- Elem e;
- Elist *el;
- Bytes *digest;
- uchar *pkcs1buf, *buf;
- int buflen;
+ int nlen, buflen;
mpint *pkcs1;
+ uchar *buf;
+ *pbuf = nil;
+
+ /* one less than the byte length of the modulus */
+ nlen = (mpsignif(pk->n)-1)/8;
+
/* see 9.2.1 of rfc2437 */
- pkcs1 = betomp(signature->data, signature->len, nil);
+ pkcs1 = betomp(sig, siglen, nil);
mpexp(pkcs1, pk->ek, pk->n, pkcs1);
- buflen = mptobe(pkcs1, nil, 0, &pkcs1buf);
- buf = pkcs1buf;
- if(buflen < 4 || buf[0] != 1)
- return "expected 1";
- buf++;
- while(buf[0] == 0xff)
- buf++;
- if(buf[0] != 0)
- return "expected 0";
- buf++;
- buflen -= buf-pkcs1buf;
- if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
- !is_octetstring(&el->tl->hd, &digest))
- return "signature parse error";
- *psigalg = &el->hd;
- if(memcmp(digest->data, edigest, digest->len) == 0)
+ buflen = mptobe(pkcs1, nil, 0, pbuf);
+ mpfree(pkcs1);
+
+ buf = *pbuf;
+ if(buflen != nlen || buf[0] != 1)
+ goto bad;
+ buf++, buflen--;
+ while(buflen > 0 && buf[0] == 0xff)
+ buf++, buflen--;
+ if(buflen < 1 || buf[0] != 0)
+ goto bad;
+ buf++, buflen--;
+ memmove(*pbuf, buf, buflen);
+ return buflen;
+bad:
+ free(*pbuf);
+ *pbuf = nil;
+ return -1;
+}
+
+char*
+X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk)
+{
+ Elem e;
+ Elist *el;
+ Bytes *digest;
+ uchar *buf;
+ int alg, buflen;
+ char *err;
+
+ buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
+ if(buflen == edigestlen && tsmemcmp(buf, edigest, edigestlen) == 0){
+ free(buf);
return nil;
- return "digests did not match";
+ }
+ el = nil;
+ memset(&e, 0, sizeof(e));
+ if(buflen < 0 || decode(buf, buflen, &e) != ASN_OK
+ || !is_seq(&e, &el) || elistlen(el) != 2 || !is_octetstring(&el->tl->hd, &digest)) {
+ err = "signature parse error";
+ goto end;
+ }
+ alg = parse_alg(&el->hd);
+ if(alg < 0){
+ err = "unknown signature algorithm";
+ goto end;
+ }
+ if(digest->len != edigestlen || digest->len != digestalg[alg]->len){
+ err = "bad digest length";
+ goto end;
+ }
+ if(tsmemcmp(digest->data, edigest, edigestlen) != 0){
+ err = "digest did not match";
+ goto end;
+ }
+ err = nil;
+end:
+ freevalfields(&e.val);
+ free(buf);
+ return err;
}
-
+
+char*
+X509ecdsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, ECdomain *dom, ECpub *pub)
+{
+ Elem e;
+ Elist *el;
+ mpint *r, *s;
+ char *err;
+
+ r = s = nil;
+ err = "bad signature";
+ if(decode(sig, siglen, &e) != ASN_OK)
+ goto end;
+ if(!is_seq(&e, &el) || elistlen(el) != 2)
+ goto end;
+ r = asn1mpint(&el->hd);
+ if(r == nil)
+ goto end;
+ el = el->tl;
+ s = asn1mpint(&el->hd);
+ if(s == nil)
+ goto end;
+ if(ecdsaverify(dom, pub, edigest, edigestlen, r, s))
+ err = nil;
+end:
+ freevalfields(&e.val);
+ mpfree(s);
+ mpfree(r);
+ return err;
+}
+
+ECpub*
+X509toECpub(uchar *cert, int ncert, ECdomain *dom)
+{
+ CertX509 *c;
+ ECpub *pub;
+ Bytes *b;
+
+ b = makebytes(cert, ncert);
+ c = decode_cert(b);
+ freebytes(b);
+ if(c == nil)
+ return nil;
+ pub = nil;
+ if(c->publickey_alg == ALG_ecPublicKey){
+ ecdominit(dom, namedcurves[c->curve]);
+ pub = ecdecodepub(dom, c->publickey->data, c->publickey->len);
+ if(pub == nil)
+ ecdomfree(dom);
+ }
+ freecert(c);
+ return pub;
+}
+
+char*
+X509ecdsaverify(uchar *cert, int ncert, ECdomain *dom, ECpub *pk)
+{
+ char *e;
+ Bytes *b;
+ CertX509 *c;
+ int digestlen;
+ uchar digest[MAXdlen];
+
+ b = makebytes(cert, ncert);
+ c = decode_cert(b);
+ if(c == nil){
+ freebytes(b);
+ return "cannot decode cert";
+ }
+ digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+ freebytes(b);
+ if(digestlen <= 0){
+ freecert(c);
+ return "cannot decode certinfo";
+ }
+ e = X509ecdsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, dom, pk);
+ freecert(c);
+ return e;
+}
+
RSApub*
X509toRSApub(uchar *cert, int ncert, char *name, int nname)
{
@@ -2049,7 +2308,7 @@
char *e;
Bytes *b;
CertX509 *c;
- RSApub *pk;
+ RSApub *pub;
b = makebytes(cert, ncert);
c = decode_cert(b);
@@ -2059,31 +2318,38 @@
if(name != nil && c->subject != nil){
e = strchr(c->subject, ',');
if(e != nil)
- *e = 0; // take just CN part of Distinguished Name
+ *e = 0; /* take just CN part of Distinguished Name */
strncpy(name, c->subject, nname);
}
- pk = decode_rsapubkey(c->publickey);
+ pub = nil;
+ if(c->publickey_alg == ALG_rsaEncryption)
+ pub = decode_rsapubkey(c->publickey);
freecert(c);
- return pk;
+ return pub;
}
char*
-X509verify(uchar *cert, int ncert, RSApub *pk)
+X509rsaverify(uchar *cert, int ncert, RSApub *pk)
{
char *e;
Bytes *b;
CertX509 *c;
- uchar digest[SHA1dlen];
- Elem *sigalg;
+ int digestlen;
+ uchar digest[MAXdlen];
b = makebytes(cert, ncert);
c = decode_cert(b);
- if(c != nil)
- digest_certinfo(b, digestalg[c->signature_alg], digest);
- freebytes(b);
- if(c == nil)
+ if(c == nil){
+ freebytes(b);
return "cannot decode cert";
- e = verify_signature(c->signature, pk, digest, &sigalg);
+ }
+ digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+ freebytes(b);
+ if(digestlen <= 0){
+ freecert(c);
+ return "cannot decode certinfo";
+ }
+ e = X509rsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, pk);
freecert(c);
return e;
}
@@ -2128,13 +2394,33 @@
return e;
}
+static int
+printable(char *s)
+{
+ int c;
+
+ while((c = (uchar)*s++) != 0){
+ if((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || strchr("'=()+,-./:? ", c) != nil)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+#define DirectoryString 0
+
static Elem
-mkstring(char *s)
+mkstring(char *s, int t)
{
Elem e;
+ if(t == DirectoryString)
+ t = printable(s) ? PrintableString : UTF8String;
e.tag.class = Universal;
- e.tag.num = IA5String;
+ e.tag.num = t;
e.val.tag = VString;
e.val.u.stringval = estrdup(s);
return e;
@@ -2174,7 +2460,7 @@
e.tag.class = Universal;
e.tag.num = UTCTime;
e.val.tag = VString;
- snprint(utc, 50, "%.2d%.2d%.2d%.2d%.2d%.2dZ",
+ snprint(utc, sizeof(utc), "%.2d%.2d%.2d%.2d%.2d%.2dZ",
tm->year % 100, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec);
e.val.u.stringval = estrdup(utc);
return e;
@@ -2223,24 +2509,26 @@
}
typedef struct Ints7pref {
- int len;
- int data[7];
+ int len;
+ int data[7];
char prefix[4];
+ int stype;
} Ints7pref;
Ints7pref DN_oid[] = {
- {4, 2, 5, 4, 6, 0, 0, 0, "C="},
- {4, 2, 5, 4, 8, 0, 0, 0, "ST="},
- {4, 2, 5, 4, 7, 0, 0, 0, "L="},
- {4, 2, 5, 4, 10, 0, 0, 0, "O="},
- {4, 2, 5, 4, 11, 0, 0, 0, "OU="},
- {4, 2, 5, 4, 3, 0, 0, 0, "CN="},
- {7, 1,2,840,113549,1,9,1, "E="},
+ {4, 2, 5, 4, 6, 0, 0, 0, "C=", PrintableString},
+ {4, 2, 5, 4, 8, 0, 0, 0, "ST=",DirectoryString},
+ {4, 2, 5, 4, 7, 0, 0, 0, "L=", DirectoryString},
+ {4, 2, 5, 4, 10, 0, 0, 0, "O=", DirectoryString},
+ {4, 2, 5, 4, 11, 0, 0, 0, "OU=",DirectoryString},
+ {4, 2, 5, 4, 3, 0, 0, 0, "CN=",DirectoryString},
+ {7, 1,2,840,113549,1,9,1, "E=", IA5String},
+ {7, 0,9,2342,19200300,100,1,25, "DC=",IA5String},
};
static Elem
mkname(Ints7pref *oid, char *subj)
{
- return mkset(mkel(mkseq(mkel(mkoid((Ints*)oid), mkel(mkstring(subj), nil))), nil));
+ return mkset(mkel(mkseq(mkel(mkoid((Ints*)oid), mkel(mkstring(subj, oid->stype), nil))), nil));
}
static Elem
@@ -2264,61 +2552,106 @@
return mkseq(el);
}
+/*
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING }
+ */
+static Bytes*
+encode_digest(DigestAlg *da, uchar *digest)
+{
+ Bytes *ans;
+ int err;
+ Elem e;
+ e = mkseq(
+ mkel(mkalg(da->alg),
+ mkel(mkoctet(digest, da->len),
+ nil)));
+ err = encode(e, &ans);
+ freevalfields(&e.val);
+ if(err != ASN_OK)
+ return nil;
+
+ return ans;
+}
+
+int
+asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len)
+{
+ Bytes *bytes;
+ DigestAlg **dp;
+
+ for(dp = digestalg; *dp != nil; dp++){
+ if((*dp)->fun != fun)
+ continue;
+ bytes = encode_digest(*dp, digest);
+ if(bytes == nil)
+ break;
+ if(bytes->len > len){
+ freebytes(bytes);
+ break;
+ }
+ len = bytes->len;
+ memmove(buf, bytes->data, len);
+ freebytes(bytes);
+ return len;
+ }
+ return -1;
+}
+
uchar*
-X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
+X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
{
- int serial = 0;
+ int serial = 0, sigalg = ALG_sha256WithRSAEncryption;
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
- Elem e, certinfo, issuer, subject, pubkey, validity, sig;
- uchar digest[MD5dlen], *buf;
+ Elem e, certinfo;
+ DigestAlg *da;
+ uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
- e.val.tag = VInt; /* so freevalfields at errret is no-op */
- issuer = mkDN(subj);
- subject = mkDN(subj);
- pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
- if(encode(pubkey, &pkbytes) != ASN_OK)
+ e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+ if(encode(e, &pkbytes) != ASN_OK)
goto errret;
- freevalfields(&pubkey.val);
- pubkey = mkseq(
- mkel(mkalg(ALG_rsaEncryption),
- mkel(mkbits(pkbytes->data, pkbytes->len),
- nil)));
- freebytes(pkbytes);
- validity = mkseq(
- mkel(mkutc(valid[0]),
- mkel(mkutc(valid[1]),
- nil)));
- certinfo = mkseq(
+ freevalfields(&e.val);
+ e = mkseq(
mkel(mkint(serial),
- mkel(mkalg(ALG_md5WithRSAEncryption),
- mkel(issuer,
- mkel(validity,
- mkel(subject,
- mkel(pubkey,
+ mkel(mkalg(sigalg),
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkutc(valid[0]),
+ mkel(mkutc(valid[1]),
+ nil))),
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkalg(ALG_rsaEncryption),
+ mkel(mkbits(pkbytes->data, pkbytes->len),
+ nil))),
nil)))))));
- if(encode(certinfo, &certinfobytes) != ASN_OK)
+ freebytes(pkbytes);
+ if(encode(e, &certinfobytes) != ASN_OK)
goto errret;
- md5(certinfobytes->data, certinfobytes->len, digest, 0);
+
+ da = digestalg[sigalg];
+ (*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
- sig = mkseq(
- mkel(mkalg(ALG_md5),
- mkel(mkoctet(digest, MD5dlen),
- nil)));
- if(encode(sig, &sigbytes) != ASN_OK)
+ certinfo = e;
+
+ sigbytes = encode_digest(da, digest);
+ if(sigbytes == nil)
goto errret;
pkcs1 = pkcs1pad(sigbytes, pk->n);
freebytes(sigbytes);
+
rsadecrypt(priv, pkcs1, pkcs1);
buflen = mptobe(pkcs1, nil, 0, &buf);
mpfree(pkcs1);
e = mkseq(
mkel(certinfo,
- mkel(mkalg(ALG_md5WithRSAEncryption),
+ mkel(mkalg(sigalg),
mkel(mkbits(buf, buflen),
nil))));
free(buf);
@@ -2326,7 +2659,10 @@
goto errret;
if(certlen)
*certlen = certbytes->len;
- cert = certbytes->data;
+ cert = malloc(certbytes->len);
+ if(cert != nil)
+ memmove(cert, certbytes->data, certbytes->len);
+ freebytes(certbytes);
errret:
freevalfields(&e.val);
return cert;
@@ -2333,52 +2669,51 @@
}
uchar*
-X509req(RSApriv *priv, char *subj, int *certlen)
+X509rsareq(RSApriv *priv, char *subj, int *certlen)
{
/* RFC 2314, PKCS #10 Certification Request Syntax */
- int version = 0;
+ int version = 0, sigalg = ALG_sha256WithRSAEncryption;
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
- Elem e, certinfo, subject, pubkey, sig;
- uchar digest[MD5dlen], *buf;
+ Elem e, certinfo;
+ DigestAlg *da;
+ uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
- e.val.tag = VInt; /* so freevalfields at errret is no-op */
- subject = mkDN(subj);
- pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
- if(encode(pubkey, &pkbytes) != ASN_OK)
+ e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+ if(encode(e, &pkbytes) != ASN_OK)
goto errret;
- freevalfields(&pubkey.val);
- pubkey = mkseq(
- mkel(mkalg(ALG_rsaEncryption),
- mkel(mkbits(pkbytes->data, pkbytes->len),
- nil)));
- freebytes(pkbytes);
- certinfo = mkseq(
+ freevalfields(&e.val);
+ e = mkseq(
mkel(mkint(version),
- mkel(subject,
- mkel(pubkey,
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkalg(ALG_rsaEncryption),
+ mkel(mkbits(pkbytes->data, pkbytes->len),
+ nil))),
nil))));
- if(encode(certinfo, &certinfobytes) != ASN_OK)
+ freebytes(pkbytes);
+ if(encode(e, &certinfobytes) != ASN_OK)
goto errret;
- md5(certinfobytes->data, certinfobytes->len, digest, 0);
+ da = digestalg[sigalg];
+ (*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
- sig = mkseq(
- mkel(mkalg(ALG_md5),
- mkel(mkoctet(digest, MD5dlen),
- nil)));
- if(encode(sig, &sigbytes) != ASN_OK)
+ certinfo = e;
+
+ sigbytes = encode_digest(da, digest);
+ if(sigbytes == nil)
goto errret;
pkcs1 = pkcs1pad(sigbytes, pk->n);
freebytes(sigbytes);
+
rsadecrypt(priv, pkcs1, pkcs1);
buflen = mptobe(pkcs1, nil, 0, &buf);
mpfree(pkcs1);
e = mkseq(
mkel(certinfo,
- mkel(mkalg(ALG_md5),
+ mkel(mkalg(sigalg),
mkel(mkbits(buf, buflen),
nil))));
free(buf);
@@ -2386,7 +2721,10 @@
goto errret;
if(certlen)
*certlen = certbytes->len;
- cert = certbytes->data;
+ cert = malloc(certbytes->len);
+ if(cert != nil)
+ memmove(cert, certbytes->data, certbytes->len);
+ freebytes(certbytes);
errret:
freevalfields(&e.val);
return cert;
@@ -2398,33 +2736,34 @@
if(tag.class != Universal)
return smprint("class%d,num%d", tag.class, tag.num);
switch(tag.num){
- case BOOLEAN: return "BOOLEAN"; break;
- case INTEGER: return "INTEGER"; break;
- case BIT_STRING: return "BIT STRING"; break;
- case OCTET_STRING: return "OCTET STRING"; break;
- case NULLTAG: return "NULLTAG"; break;
- case OBJECT_ID: return "OID"; break;
- case ObjectDescriptor: return "OBJECT_DES"; break;
- case EXTERNAL: return "EXTERNAL"; break;
- case REAL: return "REAL"; break;
- case ENUMERATED: return "ENUMERATED"; break;
- case EMBEDDED_PDV: return "EMBEDDED PDV"; break;
- case SEQUENCE: return "SEQUENCE"; break;
- case SETOF: return "SETOF"; break;
- case NumericString: return "NumericString"; break;
- case PrintableString: return "PrintableString"; break;
- case TeletexString: return "TeletexString"; break;
- case VideotexString: return "VideotexString"; break;
- case IA5String: return "IA5String"; break;
- case UTCTime: return "UTCTime"; break;
- case GeneralizedTime: return "GeneralizedTime"; break;
- case GraphicString: return "GraphicString"; break;
- case VisibleString: return "VisibleString"; break;
- case GeneralString: return "GeneralString"; break;
- case UniversalString: return "UniversalString"; break;
- case BMPString: return "BMPString"; break;
- default:
- return smprint("Universal,num%d", tag.num);
+ case BOOLEAN: return "BOOLEAN";
+ case INTEGER: return "INTEGER";
+ case BIT_STRING: return "BIT STRING";
+ case OCTET_STRING: return "OCTET STRING";
+ case NULLTAG: return "NULLTAG";
+ case OBJECT_ID: return "OID";
+ case ObjectDescriptor: return "OBJECT_DES";
+ case EXTERNAL: return "EXTERNAL";
+ case REAL: return "REAL";
+ case ENUMERATED: return "ENUMERATED";
+ case EMBEDDED_PDV: return "EMBEDDED PDV";
+ case SEQUENCE: return "SEQUENCE";
+ case SETOF: return "SETOF";
+ case UTF8String: return "UTF8String";
+ case NumericString: return "NumericString";
+ case PrintableString: return "PrintableString";
+ case TeletexString: return "TeletexString";
+ case VideotexString: return "VideotexString";
+ case IA5String: return "IA5String";
+ case UTCTime: return "UTCTime";
+ case GeneralizedTime: return "GeneralizedTime";
+ case GraphicString: return "GraphicString";
+ case VisibleString: return "VisibleString";
+ case GeneralString: return "GeneralString";
+ case UniversalString: return "UniversalString";
+ case BMPString: return "BMPString";
+ default:
+ return smprint("Universal,num%d", tag.num);
}
}
@@ -2482,39 +2821,62 @@
char *e;
Bytes *b;
CertX509 *c;
- RSApub *pk;
- uchar digest[SHA1dlen];
- Elem *sigalg;
+ RSApub *rsapub;
+ ECpub *ecpub;
+ ECdomain ecdom;
+ int digestlen;
+ uchar digest[MAXdlen];
print("begin X509dump\n");
b = makebytes(cert, ncert);
c = decode_cert(b);
- if(c != nil)
- digest_certinfo(b, digestalg[c->signature_alg], digest);
- freebytes(b);
if(c == nil){
- print("cannot decode cert");
+ freebytes(b);
+ print("cannot decode cert\n");
return;
}
+ digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+ freebytes(b);
+ if(digestlen <= 0){
+ freecert(c);
+ print("cannot decode certinfo\n");
+ return;
+ }
print("serial %d\n", c->serial);
print("issuer %s\n", c->issuer);
print("validity %s %s\n", c->validity_start, c->validity_end);
print("subject %s\n", c->subject);
- pk = decode_rsapubkey(c->publickey);
- print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);
- print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest);
- e = verify_signature(c->signature, pk, digest, &sigalg);
- if(e==nil){
- e = "nil (meaning ok)";
- print("sigalg=\n");
- if(sigalg)
- edump(*sigalg);
- }
- print("self-signed verify_signature returns: %s\n", e);
+ print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
+ print("publickey_alg=%d pubkey[%d] %.*H\n", c->publickey_alg, c->publickey->len,
+ c->publickey->len, c->publickey->data);
- rsapubfree(pk);
+ switch(c->publickey_alg){
+ case ALG_rsaEncryption:
+ rsapub = decode_rsapubkey(c->publickey);
+ if(rsapub != nil){
+ print("rsa pubkey e=%B n(%d)=%B\n", rsapub->ek, mpsignif(rsapub->n), rsapub->n);
+ e = X509rsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, rsapub);
+ if(e==nil)
+ e = "nil (meaning ok)";
+ print("self-signed X509rsaverifydigest returns: %s\n", e);
+ rsapubfree(rsapub);
+ }
+ break;
+ case ALG_ecPublicKey:
+ ecdominit(&ecdom, namedcurves[c->curve]);
+ ecpub = ecdecodepub(&ecdom, c->publickey->data, c->publickey->len);
+ if(ecpub != nil){
+ e = X509ecdsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, &ecdom, ecpub);
+ if(e==nil)
+ e = "nil (meaning ok)";
+ print("self-signed X509ecdsaverifydigest returns: %s\n", e);
+ ecpubfree(ecpub);
+ }
+ ecdomfree(&ecdom);
+ break;
+ }
freecert(c);
print("end X509dump\n");
}