ref: 065d312a1728a00c7a12f8cc64f05b8b210d8426
parent: 22a5a98241a10902152b66dde3cb3d9682c83b21
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Dec 2 20:24:22 EST 2024
libsec.diff: update libsec to verify cert chains, make matching pki changes
--- a/fs.c
+++ b/fs.c
@@ -89,6 +89,8 @@
int
checkchain(CertTab *tab, CertX509 *c, char *name)
{
+ if(c == nil)
+ return Sreject;
if(strcmp(c->subject, name) != 0)
return Sreject;
if(vfcert(tab, c) == 0)
@@ -243,7 +245,7 @@
return Enomem;
v->phase = xphase(v, Scdata);
e = certfill(v, r->ifcall.data + n, r->ifcall.count - n);
- if(e != nil)
+ if(e == nil)
r->ofcall.count = r->ifcall.count;
return e;
@@ -259,7 +261,7 @@
if(v == nil || v->phase != Scdata)
return Ephase;
e = certfill(v, r->ifcall.data, r->ifcall.count);
- if(e != nil)
+ if(e == nil)
r->ofcall.count = r->ifcall.count;
return e;
}
@@ -516,11 +518,12 @@
roottab = mktab(nil, 512);
ARGBEGIN{
- case 'r': loadcerts(roottab, EARGF(usage()), 1); break;
- case 'n': mntname = EARGF(usage()); break;
- case 's': srvname = EARGF(usage()); break;
- case 'd': debug++; chatty9p++; break;
- default: usage(); break;
+ case 'n': mntname = EARGF(usage()); break;
+ case 's': srvname = EARGF(usage()); break;
+ case 'r': loadroots(EARGF(usage())); break;
+ case 't': loadthumbs(EARGF(usage())); break;
+ case 'd': if(debug++) chatty9p++; break;
+ default: usage(); break;
}ARGEND;
postmountsrv(&pkisrv, srvname, mntname, MREPL);
--- a/libsec.diff
+++ b/libsec.diff
@@ -1,19 +1,15 @@
-diff 5a39d5532beb8f49ef0cbd0a260d7248787952f9 uncommitted
+diff 051804186780ef7f3b2f4cb548be1dd0685de5fe uncommitted
--- a/sys/include/libsec.h
+++ b/sys/include/libsec.h
-@@ -1,11 +1,6 @@
+@@ -1,7 +1,6 @@
#pragma lib "libsec.a"
#pragma src "/sys/src/libsec"
-
--#ifndef _MPINT
--typedef struct mpint mpint;
--#endif
--
- /*
- * AES definitions
- */
-@@ -318,6 +313,7 @@
+ #ifndef _MPINT
+ typedef struct mpint mpint;
+ #endif
+@@ -318,6 +317,7 @@
typedef struct RSApub RSApub;
typedef struct RSApriv RSApriv;
typedef struct PEMChain PEMChain;
@@ -21,7 +17,7 @@
/* public/encryption key */
struct RSApub
-@@ -347,6 +343,22 @@
+@@ -347,6 +347,24 @@
int pemlen;
};
@@ -31,6 +27,8 @@
+ vlong validity_start;
+ vlong validity_end;
+ char* subject;
++ char** altsubject;
++ int naltsubject;
+ int publickey_alg;
+ void* publickey;
+ int signature_alg;
@@ -44,7 +42,7 @@
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);
-@@ -356,6 +368,9 @@
+@@ -356,6 +374,9 @@
RSApriv* rsaprivalloc(void);
void rsaprivfree(RSApriv*);
RSApub* rsaprivtopub(RSApriv*);
@@ -54,15 +52,465 @@
RSApub* X509toRSApub(uchar*, int, char*, int);
RSApub* X509reqtoRSApub(uchar*, int, char*, int);
RSApub* asn1toRSApub(uchar*, int);
-@@ -476,6 +491,8 @@
- uchar *sessionID;
- uchar *psk;
- int certlen;
-+ uchar **certchain;
-+ int *certchainlen;
- int sessionIDlen;
- int psklen;
- int (*trace)(char*fmt, ...);
+@@ -368,7 +389,7 @@
+ char* X509rsaverify(uchar *cert, int ncert, RSApub *pk);
+ char* X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
+
+-void X509dump(uchar *cert, int ncert);
++void X509dump(int fd, uchar *cert, int ncert);
+
+ mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);
+ int pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);
+@@ -488,7 +509,51 @@
+ char *pskID;
+ } TLSconn;
+
++typedef struct TLSClientConf {
++ uchar *cert;
++ int ncert;
++ int noverify;
++ char *sessiontype;
++ int (*trace)(char*fmt, ...);
++ struct {
++ uchar *key;
++ int nkey;
++ char *id;
++ } psk;
++ struct {
++ int nkey;
++ char *constant;
++ } ttls;
++} TLSClientConf;
++
++typedef struct TLSServerConf {
++ PEMChain *certs;
++ char *sessiontype;
++ int (*trace)(char*fmt, ...);
++ struct {
++ uchar *key;
++ int nkey;
++ char *id;
++ } psk;
++ struct {
++ int nkey;
++ char *constant;
++ } ttls;
++} TLSServerConf;
++
++typedef struct TLSParams {
++ char dir[40]; /* connection directory */
++ PEMChain *certs;
++ struct {
++ uchar *key;
++ int nkey;
++ } ttls;
++} TLSParams;
++
+ /* tlshand.c */
++int tlsclient(int fd, char *srv, TLSClientConf *cfg, TLSParams **pparam);
++int tlsserver(int fd, TLSServerConf *cfg, TLSParams **pparam);
++void tlsparamfree(TLSParams *p);
+ int tlsClient(int fd, TLSconn *c);
+ int tlsServer(int fd, TLSconn *c);
+
+--- a/sys/src/libsec/port/tlshand.c
++++ b/sys/src/libsec/port/tlshand.c
+@@ -91,7 +91,8 @@
+ int erred; // set when tlsError called
+ int (*trace)(char*fmt, ...); // for debugging
+ int version; // protocol we are speaking
+- Bytes *cert; // server certificate; only last - no chain
++ Bytes **certs; // server certificate; only last - no chain
++ int ncerts;
+
+ int cipher;
+ int nsecret; // amount of secret data to init keys
+@@ -406,6 +407,8 @@
+ static Bytes* pkcs1_decrypt(TlsSec *sec, Bytes *data);
+ static Bytes* pkcs1_sign(TlsSec *sec, uchar *digest, int digestlen, int sigalg);
+
++static int validCert(char *rsrc, PEMChain *pc);
++
+ static void* emalloc(int);
+ static void* erealloc(void*, int);
+ static void put32(uchar *p, u32int);
+@@ -424,6 +427,78 @@
+
+ //================= client/server ========================
+
++int
++tlsserver(int fd, TLSServerConf *cfg, TLSParams **pparam)
++{
++ char buf[8];
++ char dname[32];
++ uchar seed[2*RandomSize];
++ int n, data, ctl, hand;
++ TlsConnection *tls;
++ TLSParams *param;
++
++ param = emalloc(sizeof(TLSParams));
++ ctl = open("/net/tls/clone", ORDWR|OCEXEC);
++ if(ctl < 0)
++ return -1;
++ n = read(ctl, buf, sizeof(buf)-1);
++ if(n < 0){
++ close(ctl);
++ return -1;
++ }
++ buf[n] = 0;
++ snprint(param->dir, sizeof(param->dir), "/net/tls/%s", buf);
++ snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
++ hand = open(dname, ORDWR|OCEXEC);
++ if(hand < 0){
++ close(ctl);
++ return -1;
++ }
++ data = -1;
++ fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
++ tls = tlsServer2(ctl, hand,
++ cfg->certs->pem, cfg->certs->pemlen,
++ cfg->psk.id, cfg->psk.key, cfg->psk.nkey,
++ cfg->trace, cfg->certs->next);
++ if(tls != nil){
++ snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
++ data = open(dname, ORDWR);
++ }
++ close(hand);
++ close(ctl);
++ if(data < 0){
++ tlsparamfree(param);
++ tlsConnectionFree(tls);
++ return -1;
++ }
++ param->certs = nil; // client certificates are not yet implemented
++ if(cfg->sessiontype != nil){
++ if(strcmp(cfg->sessiontype, "ttls") != 0 || cfg->ttls.nkey == 0){
++ werrstr("invalid tls session: %s", cfg->sessiontype);
++ close(data);
++ tlsparamfree(param);
++ tlsConnectionFree(tls);
++ return -1;
++ }
++ param->ttls.key = emalloc(param->ttls.nkey);
++ memmove(seed, tls->sec->crandom, RandomSize);
++ memmove(seed+RandomSize, tls->sec->srandom, RandomSize);
++ tls->sec->prf(
++ param->ttls.key, param->ttls.nkey,
++ tls->sec->sec, MasterSecretSize,
++ cfg->ttls.constant,
++ seed, sizeof(seed));
++ }
++ tlsConnectionFree(tls);
++ close(fd);
++ if(pparam == nil)
++ tlsparamfree(param);
++ else
++ *pparam = param;
++ return data;
++
++}
++
+ // push TLS onto fd, returning new (application) file descriptor
+ // or -1 if error.
+ int
+@@ -491,7 +566,7 @@
+ }
+
+ static uchar*
+-tlsClientExtensions(TLSconn *conn, int *plen)
++tlsClientExtensions(char *srvname, int *plen)
+ {
+ uchar *b, *p;
+ int i, n, m;
+@@ -499,7 +574,7 @@
+ p = b = nil;
+
+ // RFC6066 - Server Name Identification
+- if(conn->serverName != nil && (n = strlen(conn->serverName)) > 0){
++ if(srvname != nil && (n = strlen(srvname)) > 0){
+ m = p - b;
+ b = erealloc(b, m + 2+2+2+1+2+n);
+ p = b + m;
+@@ -509,7 +584,7 @@
+ 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);
++ memmove(p, srvname, n);
+ p += n;
+ }
+
+@@ -557,6 +632,118 @@
+ return b;
+ }
+
++int
++tlsclient(int fd, char *srvname, TLSClientConf *cfg, TLSParams **pparam)
++{
++ char buf[8];
++ char dname[32];
++ uchar seed[2*RandomSize];
++ int i, n, data, ctl, hand;
++ TlsConnection *tls;
++ TLSParams *param;
++ PEMChain *pc, **ppc;
++ uchar *ext;
++
++ param = emalloc(sizeof(TLSParams));
++ ctl = open("/net/tls/clone", ORDWR|OCEXEC);
++ if(ctl < 0)
++ return -1;
++ n = read(ctl, buf, sizeof(buf)-1);
++ if(n < 0){
++ close(ctl);
++ return -1;
++ }
++ buf[n] = 0;
++ snprint(param->dir, sizeof(param->dir), "/net/tls/%s", buf);
++ snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
++ hand = open(dname, ORDWR|OCEXEC);
++ if(hand < 0){
++ close(ctl);
++ return -1;
++ }
++ snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
++ data = open(dname, ORDWR);
++ if(data < 0){
++ close(hand);
++ close(ctl);
++ return -1;
++ }
++ fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
++ ext = tlsClientExtensions(srvname, &n);
++ tls = tlsClient2(ctl, hand,
++ cfg->cert, cfg->ncert,
++ cfg->psk.id, cfg->psk.key, cfg->psk.nkey,
++ ext, n, cfg->trace);
++ free(ext);
++ close(hand);
++ close(ctl);
++ if(tls == nil){
++ tlsparamfree(param);
++ close(data);
++ return -1;
++ }
++fprint(2, "certs: %#p, ncerts: %d\n", tls->certs, tls->ncerts);
++ if(tls->certs != nil){
++ ppc = ¶m->certs;
++ for(i = 0; i < tls->ncerts; i++){
++fprint(2, "add cert [%d]\n", i);
++ pc = emalloc(sizeof(PEMChain) + tls->certs[i]->len);
++ pc->next = nil;
++ pc->pem = (uchar*)(pc+1);
++ pc->pemlen = tls->certs[i]->len;
++ memcpy(pc->pem, tls->certs[i]->data, pc->pemlen);
++ *ppc = pc;
++ ppc = &pc->next;
++ }
++ } else {
++ param->certs = nil;
++ }
++ param->ttls.nkey = cfg->ttls.nkey;
++ if(cfg->sessiontype != nil){
++ if(strcmp(cfg->sessiontype, "ttls") != 0 || cfg->ttls.nkey == 0){
++ werrstr("invalid tls session: %s", cfg->sessiontype);
++ tlsparamfree(param);
++ close(data);
++ return -1;
++ }
++ param->ttls.key = emalloc(param->ttls.nkey);
++ memmove(seed, tls->sec->crandom, RandomSize);
++ memmove(seed+RandomSize, tls->sec->srandom, RandomSize);
++ tls->sec->prf(
++ param->ttls.key, param->ttls.nkey,
++ tls->sec->sec, MasterSecretSize,
++ cfg->ttls.constant,
++ seed, sizeof(seed));
++ }
++ tlsConnectionFree(tls);
++ close(fd);
++ if(cfg->noverify == 0
++ && cfg->psk.key == nil
++ && validCert("orib.dev", param->certs) == 0){
++ tlsparamfree(param);
++ close(data);
++ return -1;
++ }
++ if(pparam == nil)
++ tlsparamfree(param);
++ else
++ *pparam = param;
++ return data;
++}
++
++void
++tlsparamfree(TLSParams *param)
++{
++ PEMChain *pc, *pn;
++
++ for(pc = param->certs; pc != nil; pc = pn){
++ pn = pc->next;
++ free(pc);
++ }
++ free(param->ttls.key);
++ free(param);
++}
++
+ // push TLS onto fd, returning new (application) file descriptor
+ // or -1 if error.
+ int
+@@ -595,7 +782,7 @@
+ return -1;
+ }
+ fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+- ext = tlsClientExtensions(conn, &n);
++ ext = tlsClientExtensions(conn->serverName, &n);
+ tls = tlsClient2(ctl, hand,
+ conn->cert, conn->certlen,
+ conn->pskID, conn->psk, conn->psklen,
+@@ -608,10 +795,10 @@
+ return -1;
+ }
+ free(conn->cert);
+- if(tls->cert != nil){
+- conn->certlen = tls->cert->len;
++ if(tls->certs != nil){
++ conn->certlen = tls->certs[0]->len;
+ conn->cert = emalloc(conn->certlen);
+- memcpy(conn->cert, tls->cert->data, conn->certlen);
++ memcpy(conn->cert, tls->certs[0]->data, conn->certlen);
+ } else {
+ conn->certlen = 0;
+ conn->cert = nil;
+@@ -1042,7 +1229,7 @@
+ uchar *ext, int extlen,
+ int (*trace)(char*fmt, ...))
+ {
+- int creq, dhx, cipher;
++ int i, creq, dhx, cipher;
+ TlsConnection *c;
+ Bytes *epm;
+ Msg m;
+@@ -1057,7 +1244,7 @@
+ c->ctl = ctl;
+ c->hand = hand;
+ c->trace = trace;
+- c->cert = nil;
++ c->certs = nil;
+ c->sendp = c->buf;
+
+ c->version = ProtocolVersion;
+@@ -1118,11 +1305,15 @@
+ if(!msgRecv(c, &m))
+ goto Err;
+ if(m.tag == HCertificate){
++fprint(2, "here! %d\n", m.u.certificate.ncert);
+ 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);
++ c->ncerts = m.u.certificate.ncert;
++ c->certs = emalloc(c->ncerts * sizeof(Bytes*));
++ for(i = 0; i < c->ncerts; i++)
++ c->certs[i] = makebytes(m.u.certificate.certs[i]->data, m.u.certificate.certs[i]->len);
+ if(!msgRecv(c, &m))
+ goto Err;
+ } else if(psklen == 0) {
+@@ -1133,7 +1324,7 @@
+ if(dhx){
+ char *err = verifyDHparams(c->sec,
+ m.u.serverKeyExchange.dh_parameters,
+- c->cert,
++ c->certs[0],
+ m.u.serverKeyExchange.dh_signature,
+ c->version<TLS12Version ? 0x01 : m.u.serverKeyExchange.sigalg);
+ if(err != nil){
+@@ -1179,8 +1370,8 @@
+ msgClear(&m);
+
+ if(!dhx){
+- if(c->cert != nil){
+- epm = tlsSecRSAc(c->sec, c->cert->data, c->cert->len);
++ if(c->certs != nil){
++ epm = tlsSecRSAc(c->sec, c->certs[0]->data, c->certs[0]->len);
+ if(epm == nil){
+ tlsError(c, EBadCertificate, "bad certificate: %r");
+ goto Err;
+@@ -2100,11 +2291,12 @@
+ static void
+ tlsConnectionFree(TlsConnection *c)
+ {
++ int i;
++
+ if(c == nil)
+ return;
+
+ dh_finish(&c->sec->dh, nil);
+-
+ mpfree(c->sec->ec.Q.x);
+ mpfree(c->sec->ec.Q.y);
+ mpfree(c->sec->ec.Q.d);
+@@ -2112,12 +2304,58 @@
+
+ factotum_rsa_close(c->sec->rpc);
+ rsapubfree(c->sec->rsapub);
+- freebytes(c->cert);
++ for(i = 0; i < c->ncerts; i++)
++ freebytes(c->certs[i]);
++ free(c->certs);
+
+ memset(c, 0, sizeof(*c));
+ free(c);
+ }
+
++static int
++validCert(char *host, PEMChain *pc)
++{
++ char *q, *t, buf[64];
++ PEMChain *e;
++ int n, fd, r;
++
++print("host: %s\n", host);
++ if(host == nil)
++ return 0;
++ if((fd = open("/mnt/pki/new", ORDWR)) == -1)
++ return 0;
++ q = quotestrdup(host);
++ fprint(fd, "verify host %s", q);
++ free(q);
++
++ t = "cert";
++ for(e = pc; e != nil; e = e->next){
++fprint(2, "%s der %d\n", t, e->pemlen);
++ if((r = fprint(fd, "%s der %d\n", t, e->pemlen)) == -1){
++fprint(2, "nope0[%d]: %r", r);
++ close(fd);
++ return 0;
++ }
++ if((write(fd, e->pem, e->pemlen)) != e->pemlen){
++fprint(2, "nope1: %r");
++ close(fd);
++ return 0;
++ }
++ t = "icert";
++ }
++ fprint(fd, "done\n");
++ if((n = pread(fd, buf, sizeof(buf)-1, 0)) == -1){
++ close(fd);
++ return 0;
++ }
++ buf[n] = 0;
++ close(fd);
++ if(strcmp(buf, "accept") != 0){
++ werrstr("cert validation failed: %s", buf);
++ return 0;
++ }
++ return 1;
++}
+
+ //================= cipher choices ========================
+
--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -128,7 +128,7 @@
@@ -618,8 +1066,12 @@
return 0;
}
-@@ -3230,42 +3262,37 @@
- X509dump(uchar *cert, int ncert)
+@@ -3227,60 +3259,55 @@
+ }
+
+ void
+-X509dump(uchar *cert, int ncert)
++X509dump(int fd, uchar *cert, int ncert)
{
char *e;
+ Bits *pk, *sig;
@@ -630,11 +1082,13 @@
- int digestlen;
uchar digest[MAXdlen];
- print("begin X509dump\n");
+- print("begin X509dump\n");
- c = decode_cert(cert, ncert);
++ fprint(fd, "begin X509dump\n");
+ c = X509decode(cert, ncert);
if(c == nil){
- print("cannot decode cert\n");
+- print("cannot decode cert\n");
++ fprint(fd, "cannot decode cert\n");
return;
}
@@ -644,35 +1098,41 @@
- print("cannot decode certinfo\n");
- return;
- }
--
+ pk = c->publickey;
+ sig = c->signature;
- print("serial %d\n", c->serial);
- print("issuer %s\n", c->issuer);
++ fprint(fd, "serial %d\n", c->serial);
++ fprint(fd, "issuer %s\n", c->issuer);
++ fprint(fd, "validity %lld %lld\n", c->validity_start, c->validity_end);
++ fprint(fd, "subject %s\n", c->subject);
++ fprint(fd, "sigalg=%d digest=%.*H\n", c->signature_alg, c->digestlen, c->digest);
++ fprint(fd, "publickey_alg=%d pubkey[%d] %.*H\n", c->publickey_alg, pk->len,
++ pk->len, pk->data);
+
+- print("serial %d\n", c->serial);
+- print("issuer %s\n", c->issuer);
- print("validity %s %s\n", c->validity_start, c->validity_end);
-+ print("validity %lld %lld\n", c->validity_start, c->validity_end);
- print("subject %s\n", c->subject);
+- print("subject %s\n", c->subject);
- 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);
-+ print("sigalg=%d digest=%.*H\n", c->signature_alg, c->digestlen, c->digest);
-+ print("publickey_alg=%d pubkey[%d] %.*H\n", c->publickey_alg, pk->len,
-+ pk->len, pk->data);
-
+-
switch(c->publickey_alg){
case ALG_rsaEncryption:
- rsapub = asn1toRSApub(c->publickey->data, c->publickey->len);
+ rsapub = asn1toRSApub(pk->data, pk->len);
if(rsapub != nil){
- print("rsa pubkey e=%B n(%d)=%B\n", rsapub->ek, mpsignif(rsapub->n), rsapub->n);
+- 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);
++ fprint(fd, "rsa pubkey e=%B n(%d)=%B\n", rsapub->ek, mpsignif(rsapub->n), rsapub->n);
+ e = X509rsaverifydigest(sig->data, sig->len,
+ c->digest, c->digestlen, rsapub);
if(e==nil)
e = "nil (meaning ok)";
- print("self-signed X509rsaverifydigest returns: %s\n", e);
-@@ -3274,10 +3301,10 @@
+- print("self-signed X509rsaverifydigest returns: %s\n", e);
++ fprint(fd, "self-signed X509rsaverifydigest returns: %s\n", e);
+ rsapubfree(rsapub);
+ }
break;
case ALG_ecPublicKey:
ecdominit(&ecdom, namedcurves[c->curve]);
@@ -685,8 +1145,12 @@
+ c->digest, c->digestlen, &ecdom, ecpub);
if(e==nil)
e = "nil (meaning ok)";
- print("self-signed X509ecdsaverifydigest returns: %s\n", e);
-@@ -3287,8 +3314,8 @@
+- print("self-signed X509ecdsaverifydigest returns: %s\n", e);
++ fprint(fd, "self-signed X509ecdsaverifydigest returns: %s\n", e);
+ ecpubfree(ecpub);
+ }
+ ecdomfree(&ecdom);
+@@ -3287,15 +3314,15 @@
break;
}
@@ -693,15 +1157,18 @@
- digestSPKI(c->publickey_alg, c->publickey->data, c->publickey->len, sha2_256, digest);
- print("publickey_thumbprint sha256=%.*[\n", SHA2_256dlen, digest);
+ digestSPKI(c->publickey_alg, pk->data, pk->len, sha2_256, c->digest);
-+ print("publickey_thumbprint sha256=%.*[\n", SHA2_256dlen, c->digest);
++ fprint(fd, "publickey_thumbprint sha256=%.*[\n", SHA2_256dlen, c->digest);
sha2_256(cert, ncert, digest, nil);
- print("cert_thumbprint sha256=%.*[\n", SHA2_256dlen, digest);
-@@ -3296,6 +3323,6 @@
+- print("cert_thumbprint sha256=%.*[\n", SHA2_256dlen, digest);
++ fprint(fd, "cert_thumbprint sha256=%.*[\n", SHA2_256dlen, digest);
+
sha1(cert, ncert, digest, nil);
- print("cert_thumbprint sha1=%.*H\n", SHA1dlen, digest);
+- print("cert_thumbprint sha1=%.*H\n", SHA1dlen, digest);
++ fprint(fd, "cert_thumbprint sha1=%.*H\n", SHA1dlen, digest);
- freecert(c);
+- print("end X509dump\n");
+ X509free(c);
- print("end X509dump\n");
++ fprint(fd, "end X509dump\n");
}
--- a/pki.c
+++ b/pki.c
@@ -7,6 +7,7 @@
#include "pki.h"
CertTab *roottab;
+Thumbprint *thumbtab;
static u32int
strhash(char *s)
@@ -105,12 +106,12 @@
vfsig(CertX509 *crt, CertX509 *vrf)
{
char *r;
+
r = X509verify(crt, vrf);
- if(r != nil){
- werrstr("%s", r);
- return -1;
- }
- return 0;
+ if(r == nil || okThumbprint(crt->digest, crt->digestlen, thumbtab))
+ return 0;
+ werrstr("%s", r);
+ return -1;
}
static int
@@ -155,7 +156,7 @@
}
void
-loadcerts(CertTab *tab, char *path, int isroot)
+loadroots(char *path)
{
PEMChain *pc, *e;
CertX509 *c;
@@ -165,6 +166,13 @@
for(e = pc; e != nil; e = e->next){
if((c = X509decode(e->pem, e->pemlen)) == nil)
sysfatal("decode cert: %r");
- addcert(tab, c, isroot);
+ addcert(roottab, c, 1);
}
+}
+
+void
+loadthumbs(char *path)
+{
+ if((thumbtab = initThumbprints(path, nil, "x509")) == nil)
+ sysfatal("load thumbprints: %r");
}
--- a/pki.h
+++ b/pki.h
@@ -29,6 +29,7 @@
CertEnt *next;
CertX509 *c;
int isroot;
+ int thumbok;
};
struct Issuer {
@@ -62,7 +63,8 @@
};
extern CertTab *roottab;
-void loadcerts(CertTab*, char*, int);
+void loadroots(char*);
+void loadthumbs(char*);
int addcert(CertTab*, CertX509*, int);
CertTab* mktab(CertTab*, int);
int vfcert(CertTab*, CertX509*);
--
⑨