Table of Contents
Client Certificate PKI Configuration
The idea is simple, the implementation is complex and the execution simple.
The idea is that the client sends a certificate (and key) to the server. The server checks the certificate against a CA and, if it matches, approves the authentication.
The implemention means creating a CA (NOT using a commercial one - this is completely insecure) and a client certificate from the CA. This PKI could be really complicated (Root, Intermediates, signing etc.) or it could be a single Root CA and one certificate per device or user.
The complications are that the certs must contain certain attributes and have certain attribute values formatted in certain ways. Different OSes have different requirements.
The execution is easy. The client sends the cert to the server, which compares it to the stored CA. Again, this could be made more complex by having the CA stored elsewhere and the RADIUS server having to make a call to it.
The approach here is going to be simple. A Root CA with a single certificate and using eapol_test to test.
openssl.conf:
# # OpenSSL configuration file. # # Establish working directory. dir = . [ ca ] default_ca = CA_default [ CA_default ] serial = $dir/serial database = $dir/index.txt new_certs_dir = $dir/newcerts certificate = $dir/cacert-2021.pem private_key = $dir/private/cakey.pem default_days = 36526 default_md = SHA256 preserve = no email_in_dn = no nameopt = default_ca certopt = default_ca policy = policy_match crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl [ policy_match ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 2048 # Size of keys default_keyfile = key.pem # name of generated keys string_mask = default # permitted characters distinguished_name = req_distinguished_name x509_extensions = v3_ca [ req_distinguished_name ] # Variable name Prompt string #---------------------- ---------------------------------- countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (city, district) 0.organizationName = Organization Name (company) organizationalUnitName = Organizational Unit Name (department, division) emailAddress = Email Address emailAddress_max = 40 commonName = Common Name (hostname, IP, or your name) commonName_max = 64 # Default values for the above, for consistency and less typing. # Variable name Value #------------------------------ ------------------------------ countryName_default = GB stateOrProvinceName_default = England localityName_default = Manchester 0.organizationName_default = Scarfolk organizationalUnitName_default = Scarfolk emailAddress_default = mike.richardson@jisc.ac.uk distinguished_name = req_distinguished_name req_extensions = v3_req [ v3_ca ] basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl [ v3_req ] basicConstraints = CA:FALSE subjectKeyIdentifier = hash [ xpclient_ext ] extendedKeyUsage = 1.3.6.1.5.5.7.3.2 crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl [ xpserver_ext ] extendedKeyUsage = 1.3.6.1.5.5.7.3.1 crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl [ server ] basicConstraints = CA:FALSE subjectKeyIdentifier = hash nsCertType = server nsComment = "OpenSSL Generated Server Certificate" keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment #extendedKeyUsage = serverAuth extendedKeyUsage = 1.3.6.1.5.5.7.3.1, serverAuth crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl [ client ] basicConstraints = CA:FALSE nsCertType = client, email, server nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth, emailProtection crlDistributionPoints = URI:http://crldp.govroam.uk/crldp.crl
The defaults need changing, as do the crlDistributionPoints. The config has been adapted to many things over years so is far from optimal. There will be stuff that's unnecessary and stuff left out but it's been tested and I know it works.
xpextensions:
[ xpclient_ext ] extendedKeyUsage = 1.3.6.1.5.5.7.3.2 [ xpserver_ext ] extendedKeyUsage = 1.3.6.1.5.5.7.3.1
The Root CA
First, generate the certificate:
openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 36500 -config ./openssl.cnf -sha256
Remember the password, you'll need it later for the client cert.
Then, convert it to a PCKS12 file:
openssl pkcs12 -export -out cacert.pfx -inkey private/cakey.pem -in cacert.pem
Example:
Certificate: Data: Version: 3 (0x2) Serial Number: 1f:87:4b:2f:67:d2:6f:30:81:3a:fd:20:00:4f:03:eb:3d:c4:57:38 Signature Algorithm: sha256WithRSAEncryption Issuer: C = GB, ST = England, L = Manchester, O = Scarfolk, OU = Scarfolk, emailAddress = mike.richardson@jisc.ac.uk Validity Not Before: May 4 13:15:23 2021 GMT Not After : Apr 10 13:15:23 2121 GMT Subject: C = GB, ST = England, L = Manchester, O = Scarfolk, OU = Scarfolk, emailAddress = mike.richardson@jisc.ac.uk Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: 00:cb:c3:99:ed:69:cc:ee:3b:0f:e1:2d:a6:f9:94: 33:b7:f6:bb:b7:4a:b7:37:9f:c7:36:f6:24:5c:89: 67:36:67:36:2f:51:c0:c3:34:e3:74:a4:88:68:7f: 03:48:97:f2:79:ba:25:24:66:70:b8:58:38:9b:de: bf:53:6d:09:81:13:75:0a:75:cd:2f:35:18:e8:7f: 33:a9:81:7f:72:2d:bf:97:1c:9a:5c:95:8e:e5:97: 1c:cb:83:5b:ed:7b:e7:af:da:84:97:22:1b:52:7b: 34:a5:5f:ae:88:94:1e:56:27:74:74:2d:a9:41:bf: f8:69:8a:73:7b:1d:96:0f:52:cd:6c:d5:fd:d9:ea: 61:5e:a6:b4:49:0a:c0:5f:0f:4e:f4:3c:ad:11:2c: 05:10:39:8f:67:d5:85:1b:be:ee:5e:ac:f9:6c:47: 6a:f3:95:91:13:23:08:45:a0:f0:b1:55:62:90:ed: e8:ee:b5:83:29:8a:e3:78:27:31:13:51:33:e4:71: 25:7a:50:34:5f:a8:55:8e:85:70:32:11:29:bb:dc: 33:65:c9:31:a2:3b:5f:12:51:63:01:6d:95:20:37: 52:60:73:2e:49:98:6c:3c:b1:f0:56:ba:fb:6a:5d: 68:19:c0:cd:8f:7b:16:52:2f:44:90:16:97:a3:51: 7f:4f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:TRUE X509v3 Subject Key Identifier: 7B:99:3E:6D:8D:80:6F:71:4F:B9:2B:56:F1:E3:3B:E0:A1:7D:16:2B X509v3 Authority Key Identifier: keyid:7B:99:3E:6D:8D:80:6F:71:4F:B9:2B:56:F1:E3:3B:E0:A1:7D:16:2B DirName:/C=GB/ST=England/L=Manchester/O=Scarfolk/OU=Scarfolk/emailAddress=mike.richardson@jisc.ac.uk serial:1F:87:4B:2F:67:D2:6F:30:81:3A:FD:20:00:4F:03:EB:3D:C4:57:38 X509v3 CRL Distribution Points: Full Name: URI:http://crldp.govroam.uk/crldp.crl Signature Algorithm: sha256WithRSAEncryption 30:63:ea:1f:33:2f:47:ff:2b:49:15:d5:d0:64:97:f1:d9:e0: be:3a:f8:01:73:ac:7a:79:24:2e:a8:6c:c3:bb:eb:75:fa:88: c3:e3:49:cc:35:c4:03:f7:ee:ba:32:06:9b:97:b2:82:48:f9: 28:85:8a:97:ee:b6:0f:87:12:79:cf:c9:cb:f9:12:fe:4d:2f: 57:64:52:45:b6:ad:39:c6:b7:07:5e:33:5b:c3:8d:00:26:b1: 0e:08:8e:24:0b:35:48:b4:7b:34:09:37:83:f7:01:2c:ce:12: 4a:48:3a:f6:08:c9:2e:2e:6e:a3:bd:2e:01:ca:16:0d:3f:72: 39:05:86:2c:a0:16:a1:c5:b0:d7:7c:8c:a7:9d:e8:4a:6b:67: 50:ae:7a:12:60:29:04:7e:61:be:fb:e6:c5:97:f2:cb:5c:6d: fd:41:88:7e:5d:0e:04:52:b4:5e:69:9c:a2:43:1e:c1:a8:8b: 66:76:b1:39:7c:20:df:d8:e9:a2:81:81:be:e5:6c:8a:55:42: e8:d3:f9:7e:eb:57:44:ab:da:de:c3:c8:01:34:e2:69:2f:d5: d7:5a:3b:86:d9:c6:b5:e8:08:4c:b3:ed:5c:48:f1:ad:41:ce: fd:49:27:ac:3c:e4:57:18:e6:ed:0c:1d:0f:8a:2a:0c:c5:e0: f3:78:b3:98
The Client Certificate
First, the CSR:
openssl req -new -nodes -reqexts client -out newclients/client-req.pem -days 3650 -config ./openssl.cnf
It will prompt for a number of fields. The key one is the hostname. It must be set to the username@realm needed. The realm will be used in the outer ID so should be in the right format for routing. The username part is mostly irrelevant, unless used at other points for authorisation.
Then the cert is signed against the CA:
openssl ca -out newclients/client-cert.pem -extensions client -config ./openssl.cnf -infiles newclients/client-req.pem
Convert the certificate to PKCS12:
openssl pkcs12 -export -out newclients/client-cert.pfx -inkey key.pem -in newclients/client-cert.pem
And you're done.
Example:
Certificate: Data: Version: 3 (0x2) Serial Number: 7 (0x7) Signature Algorithm: sha256WithRSAEncryption Issuer: C = GB, ST = England, L = Manchester, O = Scarfolk, OU = Scarfolk, emailAddress = mike.richardson@jisc.ac.uk Validity Not Before: May 6 13:35:02 2021 GMT Not After : May 8 13:35:02 2121 GMT Subject: C = GB, ST = England, L = Manchester, O = Scarfolk, OU = Scarfolk, CN = staff@fr.fr.scarfolk.local Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: 00:d0:59:65:a4:9e:5b:cb:82:cf:e0:39:ac:12:f1: 60:d0:13:3f:76:4b:e7:47:ad:01:f7:c5:a8:2c:61: 8f:49:23:da:54:d8:a9:85:5e:24:53:2c:03:4d:bf: 25:48:65:06:7b:2d:f5:3a:26:9f:f4:3c:d6:53:1d: 8e:a5:81:13:da:c6:23:72:96:97:ca:b2:20:fd:85: e1:e1:73:71:3a:92:c8:d0:6d:52:cc:48:8d:10:59: 6f:65:7b:fe:ae:fe:66:ff:62:ab:48:a2:b2:c8:03: aa:38:50:70:43:29:6a:65:30:e8:ee:04:42:66:30: 9b:62:2a:93:41:19:8e:1c:53:f0:9f:59:f4:47:a3: 8b:a5:f0:e4:be:a4:d8:f5:a2:a9:d7:bd:d0:b8:19: 4f:22:2c:15:1c:cf:08:42:65:d3:45:fb:88:b5:5e: 24:14:68:46:8e:0a:c7:66:e7:99:eb:96:08:a9:3e: 48:1f:e9:8b:1d:6d:7a:98:09:a7:3c:4d:5f:9a:3f: 1e:e6:b9:2e:35:0a:07:09:38:23:8b:b4:4b:6a:c6: 65:6a:ca:5e:92:fc:4f:6d:0e:7c:6c:8c:6c:42:54: 74:40:18:b9:bb:0e:5e:37:2f:77:56:0a:95:40:37: 49:d5:f8:e0:a0:dc:23:f3:8f:e9:0a:54:23:e4:da: 83:11 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Client, SSL Server, S/MIME Netscape Comment: OpenSSL Generated Client Certificate X509v3 Subject Key Identifier: B8:51:36:FD:01:CD:20:BF:5D:09:52:66:F9:46:F8:35:11:73:E6:AE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection X509v3 CRL Distribution Points: Full Name: URI:http://crldp.govroam.uk/crldp.crl Signature Algorithm: sha256WithRSAEncryption 81:45:59:55:1d:8c:27:0c:02:0e:44:7e:ef:ab:fc:8c:df:3e: 3e:1d:fc:2b:46:24:c3:65:f5:73:7a:47:b7:89:0b:5a:8c:27: 44:47:ea:90:78:04:d2:fd:9f:56:d7:ff:cb:60:9e:84:f6:bb: 36:e9:ac:7d:8f:c7:ca:a7:05:7a:57:d8:d3:88:fd:b9:87:9b: 6f:20:cc:de:e1:68:9b:81:1b:97:1c:d2:72:c7:d8:a4:c1:84: 54:d3:20:fd:66:19:b2:5d:69:f2:b5:df:20:ba:6e:75:2c:1e: ae:fe:bb:bc:07:9d:80:ef:42:06:e9:15:d6:0b:07:ff:37:91: d0:7b:4c:88:bd:22:3d:82:34:3f:22:21:51:d0:55:01:3d:3f: 14:f4:c4:a9:15:36:9e:fa:5b:e0:e7:41:58:34:c1:12:9a:7f: 63:a4:52:97:a3:da:3f:45:6f:00:4e:b1:f5:e1:33:bf:6e:06: aa:90:f1:75:43:3a:dc:fe:57:f4:5b:e9:b6:f8:a2:3b:d9:e9: bd:47:a8:7e:4b:bf:4c:c7:28:9e:43:15:ee:f7:ff:29:31:82: 29:49:6d:33:b1:e6:b9:b9:70:3f:86:ac:50:26:35:c4:1d:c5: 9b:02:82:67:b0:94:9e:e0:0a:2a:aa:5e:16:75:cd:8c:90:78: a6:a5:d0:ed