diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-12-30 03:07:47 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-12-30 03:07:47 +0100 |
commit | 57f8b6ec7591007ff22627038b51c4f4aa2a9be8 (patch) | |
tree | 3d4cbe53bdb48b2c2b4145bafb5b4f2853f638fa /sys/src | |
parent | b42d441a230bad9fd1ae8e3543b1c0f28c7c62aa (diff) |
libsec: implement SPKI fingerprinting for okCertificate()
Instead of only using a hash over the whole certificate for
white/black-listing, now we can also use a hash over the
Subject Public Key Info (SPKI) field of the certificate which
contians the public key algorithm and the public key itself.
This allows certificates to be renewed independendtly of the
public key.
X509dump() now prints the public key thumbprint in addition
to the certificate thumbprint.
tlsclient will print the certificate when run with -D flag.
okCertificate() will print the public key thumbprint in its
error string when no match has been found.
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/cmd/tlsclient.c | 5 | ||||
-rw-r--r-- | sys/src/libsec/port/thumb.c | 5 | ||||
-rw-r--r-- | sys/src/libsec/port/x509.c | 36 |
3 files changed, 46 insertions, 0 deletions
diff --git a/sys/src/cmd/tlsclient.c b/sys/src/cmd/tlsclient.c index 1b79fb739..7be56c279 100644 --- a/sys/src/cmd/tlsclient.c +++ b/sys/src/cmd/tlsclient.c @@ -49,6 +49,8 @@ main(int argc, char **argv) Thumbprint *thumb; AuthInfo *ai = nil; + fmtinstall('B', mpfmt); + fmtinstall('[', encodefmt); fmtinstall('H', encodefmt); ARGBEGIN{ @@ -122,6 +124,9 @@ main(int argc, char **argv) if(fd < 0) sysfatal("tlsclient: %r"); + if(debug) + X509dump(conn->cert, conn->certlen); + if(thumb){ if(!okCertificate(conn->cert, conn->certlen, thumb)) sysfatal("cert for %s not recognized: %r", servername ? servername : addr); diff --git a/sys/src/libsec/port/thumb.c b/sys/src/libsec/port/thumb.c index 39757939b..73add8db1 100644 --- a/sys/src/libsec/port/thumb.c +++ b/sys/src/libsec/port/thumb.c @@ -66,6 +66,11 @@ okCertificate(uchar *cert, int len, Thumbprint *table) if(okThumbprint(hash, SHA2_256dlen, table)) return 1; + if(X509digestSPKI(cert, len, sha2_256, hash) < 0) + return 0; + if(okThumbprint(hash, SHA2_256dlen, table)) + return 1; + len = enc64(thumb, sizeof(thumb), hash, SHA2_256dlen); while(len > 0 && thumb[len-1] == '=') len--; diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c index e5b92039c..2ec9d9551 100644 --- a/sys/src/libsec/port/x509.c +++ b/sys/src/libsec/port/x509.c @@ -2897,6 +2897,32 @@ errret: return cert; } +static void +digestSPKI(int alg, uchar *pubkey, int npubkey, DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest) +{ + Bytes *b = nil; + Elem e = mkseq(mkel(mkalg(alg), mkel(mkbits(pubkey, npubkey), nil))); + encode(e, &b); + freevalfields(&e.val); + (*fun)(b->data, b->len, digest, nil); + freebytes(b); +} + +int +X509digestSPKI(uchar *cert, int ncert, DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest) +{ + CertX509 *c; + + c = decode_cert(cert, ncert); + if(c == nil){ + werrstr("cannot decode cert"); + return -1; + } + digestSPKI(c->publickey_alg, c->publickey->data, c->publickey->len, fun, digest); + freecert(c); + return 0; +} + static char* tagdump(Tag tag) { @@ -3047,6 +3073,16 @@ X509dump(uchar *cert, int ncert) ecdomfree(&ecdom); break; } + + digestSPKI(c->publickey_alg, c->publickey->data, c->publickey->len, sha2_256, digest); + print("publickey_thumbprint sha256=%.*[\n", SHA2_256dlen, digest); + + sha2_256(cert, ncert, digest, nil); + print("cert_thumbprint sha256=%.*[\n", SHA2_256dlen, digest); + + sha1(cert, ncert, digest, nil); + print("cert_thumbprint sha1=%.*H\n", SHA1dlen, digest); + freecert(c); print("end X509dump\n"); } |