Why does OpenVPN give the error: "unsupported certificate purpose" for an intermediate certificate?

Solution 1:

It's the EKU (ExtendedKeyUsage extension)

rfc 5280 4.2.1.12 extKeyUsage says

In general, this extension will appear only in end entity certificates.

CABforum Baseline Requirements (v1.3.4) 7.2.2 g affirms this, but along with 7.1.5 allows one case:

For a Subordinate CA Certificate to be considered Technically Constrained, the certificate MUST include an Extended Key Usage (EKU) extension specifying all extended key usages that the Subordinate CA Certificate is authorized to issue certificates for. The anyExtendedKeyUsage KeyPurposeId MUST NOT appear within this extension.

EKU thus is not a restriction on the CA's use of its own key, but on EE use of keys with certificates under the CA. This is similar to the way Policies (mostly) and NameConstraints propagate downward, and unlike KeyUsage which does apply to the CA itself.

And this is what OpenSSL implements and therefore OpenVPN using OpenSSL does. On each CA cert in a server chain, if EKU is present it must include serverAuth or SGC. Similarly each CA cert in a client chain with EKU must include clientAuth.

Your intermediate CA above your server has EKU with OCSPSign but not serverAuth, so it is rejected.

Reference: crypto/x509/x509_vfy.c and crypto/x509v3/v3_purp.c in openssl-1.0.2h

Solution 2:

Hmm, OpenVPN's easyrsa creates certificates like this:

CA1:

X509v3 Subject Key Identifier:
87:13:73:D4:7C:9A:E1:EA:9A:F8:90:48:93:18:5A:B0:AF:B9:B6:25
X509v3 Authority Key Identifier:
keyid:87:13:73:D4:7C:9A:E1:EA:9A:F8:90:48:93:18:5A:B0:AF:B9:B6:25
DirName:/CN=Easy-RSA CA
serial:8B:E0:6F:16:C0:46:46:FC

X509v3 Basic Constraints:
CA:TRUE
X509v3 Key Usage:
Certificate Sign, CRL Sign

CA2:

X509v3 Basic Constraints:
CA:TRUE
X509v3 Subject Key Identifier:
D6:60:98:E7:6E:7C:73:9A:38:62:09:EC:C7:5D:62:15:89:AA:B2:8E
X509v3 Authority Key Identifier:
keyid:87:13:73:D4:7C:9A:E1:EA:9A:F8:90:48:93:18:5A:B0:AF:B9:B6:25
DirName:/CN=Easy-RSA CA
serial:8B:E0:6F:16:C0:46:46:FC

X509v3 Key Usage:
Certificate Sign, CRL Sign

Server:

X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
53:BA:B4:3B:87:AC:89:41:14:28:8F:C9:A2:F3:38:D4:43:90:EF:A6
X509v3 Authority Key Identifier:
keyid:D6:60:98:E7:6E:7C:73:9A:38:62:09:EC:C7:5D:62:15:89:AA:B2:8E
DirName:/CN=Easy-RSA CA
serial:CB:8A:25:7F:5A:8A:A9:BD:63:D2:BE:B7:6C:5E:3E:75

X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication

Client:

X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
F5:34:3A:39:C6:90:E0:2F:E3:92:A7:D2:0D:18:C7:48:E6:48:9F:DA
X509v3 Authority Key Identifier:
keyid:D6:60:98:E7:6E:7C:73:9A:38:62:09:EC:C7:5D:62:15:89:AA:B2:8E
DirName:/CN=Easy-RSA CA
serial:CB:8A:25:7F:5A:8A:A9:BD:63:D2:BE:B7:6C:5E:3E:75

X509v3 Key Usage:
Digital Signature
X509v3 Extended Key Usage:
TLS Web Client Authentication

But you have these Key Usage values too, so your config should be working... But there is not intermediate CA...

Have you tries to set --ca to the root CA cert and set --extra-certs to the intermediate CA and --cert to the server cert to form a complete chain? And don't forget --key too.

Actually i've got it working:

Server:

Tue Jun 21 04:39:49 2016 VERIFY OK: depth=2, CN=Easy-RSA CA
Tue Jun 21 04:39:49 2016 VERIFY OK: depth=1, O=Easy-RSA CA2, CN=Easy-RSA CA2
Tue Jun 21 04:39:49 2016 VERIFY OK: depth=0, O=client, CN=client

Client:

Tue Jun 21 04:39:49 2016 VERIFY OK: depth=2, CN=Easy-RSA CA
Tue Jun 21 04:39:49 2016 VERIFY OK: depth=1, O=Easy-RSA CA2, CN=Easy-RSA CA2
Tue Jun 21 04:39:49 2016 VERIFY OK: depth=0, O=server, CN=server

Server conf:

port 1194
proto tcp-server
dev tun
ca ca1.crt
extra-certs ca2.crt
cert server.crt
key server-key.pem
dh dh.pem
tls-server
tls-auth ta.key 0

Client conf:

client
remote localhost 1194
port 1194
proto tcp-client
dev tun
ca ca1.crt
extra-certs ca2.crt
cert client.crt
key client-key.pem
dh dh.pem
tls-client
tls-auth ta.key 1

XCA

Solution 3:

I had a similar problem with stunnel and openssl on linux

I found that the server side expected all client and CA certs to include: Extended Key Usage: TLS Web Client Authentication

And, found that the client side expected all server and CA certs to include: X509v3 Extended Key Usage: TLS Web Server Authentication

Since I was using the same CA's to sign both the client and server certs I tested by setting the CA, CA1 and CA2 certs to include both clientAuth and serverAuth and it fixed the issue.

CA, CA1 and CA2: X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication

client cert: X509v3 Extended Key Usage: TLS Web Client Authentication

server cert: X509v3 Extended Key Usage: TLS Web Server Authentication