]> git.lizzy.rs Git - plan9front.git/commitdiff
libsec: implement SPKI fingerprinting for okCertificate()
authorcinap_lenrek <cinap_lenrek@felloff.net>
Sat, 30 Dec 2017 02:07:47 +0000 (03:07 +0100)
committercinap_lenrek <cinap_lenrek@felloff.net>
Sat, 30 Dec 2017 02:07:47 +0000 (03:07 +0100)
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.

sys/include/ape/libsec.h
sys/include/libsec.h
sys/man/8/tlssrv
sys/src/cmd/tlsclient.c
sys/src/libsec/port/thumb.c
sys/src/libsec/port/x509.c

index bd4b352f7bbef06e226d048bade6d54899841a4c..610e69e2876e64d3bc58da68ef230e306bfa02c0 100644 (file)
@@ -382,7 +382,9 @@ int         pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 int            asn1encodeRSApub(RSApub *pk, uchar *buf, int len);
 int            asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*),
                        uchar *digest, uchar *buf, int len);
+
+int            X509digestSPKI(uchar *, int, DigestState* (*)(uchar*, ulong, uchar*, DigestState*), uchar *);
+
 /*
  * elgamal
  */
index b1616782f680c4e286db179fa6e45ef7d0fb2eb3..f9c75306b71be08602e3198acf15d794a42dc923 100644 (file)
@@ -375,6 +375,7 @@ int         asn1encodeRSApub(RSApub *pk, uchar *buf, int len);
 int            asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*),
                        uchar *digest, uchar *buf, int len);
 
+int            X509digestSPKI(uchar *, int, DigestState* (*)(uchar*, ulong, uchar*, DigestState*), uchar *);
 
 /*
  * elgamal
index 462be928b999320bc41218dbcec4b3d3f8d7c654..9ebaa01043e0a348be8c14926981984cd89442ed 100644 (file)
@@ -134,9 +134,8 @@ flag
 (and, optionally, the
 .B -x
 flag)
-is given, the remote server must present a key
-whose SHA1 hash is listed in
-the file
+is given, the remote server must present a public key
+whose SHA1 or SHA256 hash is listed in the file
 .I trustedkeys
 but not in the file
 .IR excludedkeys .
index 1b79fb739f57f9d4170f744e755c06e909c7e1d1..7be56c2798a244e80a8cafb07902bdb83cc4d2a5 100644 (file)
@@ -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);
index 39757939b658521f5c8b4266939be91313de89bc..73add8db1dfe8edc6d8a94cabc7bbe0110042718 100644 (file)
@@ -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--;
index e5b92039cda3e5bad061cb2f63d80a9199a6a28c..2ec9d9551d318ba00e2412548c142a431bc4fad3 100644 (file)
@@ -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");
 }