ref: a7d243ef71a1b27166c158ba148da2363402f328
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->spkidigest)) == 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"); }