Service Desk (from b.cama@kerlink.fr): Re: String comparison for DN should by type-insensitive
Hello,
I allow myself to follow up on this old issue: I saw that it has been reported by someone else on gitlab as #553 (closed). I realize that this does not happen with a “normal” workflow, but as nmav requested a reproducer, here it is:
# generate keys for a CA
certtool --generate-privkey --outfile ca.key
# generate self-signed cert with OpenSSL
cat > ca-openssl.cfg <<EOF
[ req ]
distinguished_name = req_dn
x509_extensions = v3_ca
[ req_dn ]
commonName = "Test CA"
[ v3_ca ]
basicConstraints = CA:true
EOF
openssl req -x509 -key ca.key -config ca-openssl.cfg -out ca.crt -days 1 -subj '/CN=Test CA/'
# we end up with a subject DN encoded as UTF8String.
# generate a certificate request for a client
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.crq -days 1 -subj '/CN=Test client/'
# generate a cert for the client with GnuTLS
echo dn=\"CN=Test client\" > client-gnutls.cfg
certtool --load-ca-privkey ca.key --load-ca-certificate ca.crt --generate-certificate --load-request client.crq --outfile client.crt --template client.cfg
# check that the chain from client to CA is OK
cat client.crt ca.crt | certtool -e # OK with certtool
openssl verify -CAfile ca.crt client.crt # OK with openssl
# now, re-generate a certificate for the CA from the same key,
# but with a user-specified all-ASCII name that match the one
# given earlier, but with a different tool: certtool; we end up
# with a subject DN encoded as PrintableString, even though the
# string content is exactly the same
cat > ca-gnutls.cfg <<-EOF
dn="CN=Test CA"
ca >> ca.cfg
expiration_days = 1
EOF
certtool --generate-self-signed --load-privkey ca.key --template ca-gnutls.cfg --outfile ca.crt
# check that the chain from client to CA is still OK
cat client.crt ca.crt | certtool -e # NOT OK with certtool!
openssl verify -CAfile ca.crt client.crt # OK with openssl!
This is not “legit” of course, but happened to me as I was trying to create a cross-CA certificate for an old CA from which I could not get a proper certificate request (for bad reasons, I know), so I ended up extracting the public key from its old-chain certificate and just duplicated the subject DN. I had to hack certtool to allow for raw oid as DN to have certtool create a certificate in this case with a subject (of the cross-signed CA, issued by my new GnuTLS-managed CA) having the correct encoding (i.e. UTF8String) even though its name was all ASCII.
As I noted earlier, libnss also behave like GnuTLS. But according to the RFC, OpenSSL seems “more correct”.
The deeper problem I see here is rather that with GnuTLS, one cannot really know in advance the encoding of some string of its certificate: if it is all ASCII, it will be PrintableString, but if it contains non- ASCII characters, it will be UTF-8 (I do not remember the exact place of the detection routine). OpenSSL has chosen to use UTF-8 everywhere to simplify this; RFC 3280 even wanted to force UTF-8 for all the DNs, before being amended by RFC 4630. I believe the more predictable way of doing things of OpenSSL makes more sense.
And I also agree with David Caldwell that heterogeneous tooling is not practiced enough (as I am doing here) and there are quite some strange bugs that are still to find, I think. I can confirm that working with something else than OpenSSL makes one life very difficult, and it takes some will to want to keep some diversity.
Thanks for listening anyway.