ref: 065d312a1728a00c7a12f8cc64f05b8b210d8426
dir: /pki.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <mp.h>
#include <libsec.h>
#include "pki.h"
CertTab *roottab;
Thumbprint *thumbtab;
static u32int
strhash(char *s)
{
u32int h;
h = 33;
for(; *s; s++)
h = h*33 + *s;
return h;
}
CertTab*
mktab(CertTab *up, int nent)
{
CertTab *tab;
Issuer **ent;
tab = malloc(sizeof(CertTab));
ent = mallocz(nent*sizeof(Issuer*), 1);
if(tab == nil || ent == nil){
free(ent);
free(tab);
return nil;
}
tab->up = up;
tab->ent = ent;
tab->nent = nent;
return tab;
}
static void
freetab(CertTab *tab)
{
free(tab->ent);
free(tab);
}
static Issuer*
ctabget(CertTab *tab, char *name)
{
Issuer *ci;
u32int h;
h = strhash(name) % tab->nent;
for(ci = tab->ent[h]; ci != nil; ci = ci->next)
if(strcmp(ci->name, name) == 0)
return ci;
if(tab->up != nil)
return ctabget(tab->up, name);
return nil;
}
int
addcert(CertTab *tab, CertX509 *crt, int isroot)
{
Issuer *ci;
CertEnt *c;
u32int h;
ci = nil;
if((c = mallocz(sizeof(CertEnt), 1)) == nil)
goto Error;
h = strhash(crt->subject) % tab->nent;
c->c = crt;
for(ci = tab->ent[h]; ci != nil; ci = ci->next)
if(strcmp(ci->name, c->c->subject) == 0)
goto Found;
if((ci = mallocz(sizeof(Issuer), 1)) == nil)
goto Error;
if((ci->name = strdup(c->c->subject)) == nil)
goto Error;
ci->next = tab->ent[h];
tab->ent[h] = ci;
Found:
c->isroot = isroot;
c->next = ci->certs;
ci->certs = c;
return 0;
Error:
free(ci);
free(c);
return -1;
}
static int
expired(CertX509 *crt)
{
vlong now;
now = time(nil);
return now < crt->validity_start || now > crt->validity_end;
}
static int
vfsig(CertX509 *crt, CertX509 *vrf)
{
char *r;
r = X509verify(crt, vrf);
if(r == nil || okThumbprint(crt->digest, crt->digestlen, thumbtab))
return 0;
werrstr("%s", r);
return -1;
}
static int
matchesname(CertX509 *crt, CertX509 *vrf)
{
USED(crt, vrf);
return 1;
}
static int
vfconstraints(CertX509 *crt, CertX509 *vrf)
{
if(expired(crt)){
werrstr("certificate revoked");
return -1;
}
if(!matchesname(crt, vrf)){
werrstr("name constraint failure");
return -1;
}
return 0;
}
int
vfcert(CertTab *tab, CertX509 *crt)
{
CertEnt *ce;
Issuer *ci;
if((ci = ctabget(tab, crt->issuer)) == nil)
return -1;
for(ce = ci->certs; ce != nil; ce = ce->next){
if(vfsig(crt, ce->c) != 0)
continue;
if(vfconstraints(crt, ce->c) != 0)
continue;
if(!ce->isroot && vfcert(tab, ce->c) == -1)
continue;
return 0;
}
return -1;
}
void
loadroots(char *path)
{
PEMChain *pc, *e;
CertX509 *c;
if((pc = readcertchain(path)) == nil)
sysfatal("load pem chain: %r");
for(e = pc; e != nil; e = e->next){
if((c = X509decode(e->pem, e->pemlen)) == nil)
sysfatal("decode cert: %r");
addcert(roottab, c, 1);
}
}
void
loadthumbs(char *path)
{
if((thumbtab = initThumbprints(path, nil, "x509")) == nil)
sysfatal("load thumbprints: %r");
}