iPXE discussion forum

Full Version: iPXE TLS requiring trusting the intermediate certificate
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I've got a TLS server online providing images to be bootable. It presents a certificate bundle that is signed by a private CA. The private CA has a root and intermediate certificate, the intermediate is used to sign leaf certificates.

I'm also doing client authentication as well, so the ipxe client gets a leaf + intermediate certificate bundle and a leaf key.

So I've tested my server using curl and it works.

```
curl \
--cert "./ipxe.crt" \
--key "./ipxe.key" \
--cacert "./root.crt" \
https://example.com
```

I had to mess around with the server to make sure it supported RSA, and that leaf, intermediate and root are all using RSA keys and signatures because iPXE only supports RSA. Also to make sure that the ciphers are compatible, which they are now.

Anyway, now everything should work with compilation flags like:

```
CERT=./ipxe.crt
PRIVKEY=./ipxe.key
TRUST=./root.crt
```

Now when I build and try to run, I get TLS debug logs like this:

```
TLS 0xbe684628 created session example.com
Sending plaintext data:
Received plaintext data:
TLS 0xbe684628 using protocol version 3.3
TLS 0xbe684628 selected rsa-aes_cbc-256-sha1
TLS 0xbe684628 pre-master-secret:
TLS 0xbe684628 client random bytes:
TLS 0xbe684628 server random bytes:
TLS 0xbe684628 sha256 secret:
TLS 0xbe684628 sha256 A(1):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 generated master secret:
TLS 0xbe684628 sha256 secret:
TLS 0xbe684628 sha256 A(1):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 sha256 output:
TLS 0xbe684628 sha256 A(n):
TLS 0xbe684628 TX MAC secret:
TLS 0xbe684628 RX MAC secret:
TLS 0xbe684628 TX key:
TLS 0xbe684628 RX key:
TLS 0xbe684628 TX IV:
TLS 0xbe684628 RX IV:
Received plaintext data:
TLS 0xbe684628 found certificate example.com
TLS 0xbe684628 found certificate Example Intermediate CA
Received plaintext data:
TLS 0xbe684628 sending client certificate netboot-client
Received plaintext data:
. [XCRT Formbay Intermediate CA]
TLS 0xbe684628 certificate validation failed: No such file or directory (http://ipxe.org/2d0c618e)
```

Pretty strange error. Now I tried to see what would happen if I made iPXE trust the intermediate certificate. This is not needed by curl, and not needed by browsers so I wasn't sure if this made sense. But I got a very different behaviour.

```
CERT=./ipxe.crt
PRIVKEY=./ipxe.key
TRUST=./root.crt,./intermediate.crt
```

```
TLS 0xbe6841a8 created session example.com
Sending plaintext data:
Received plaintext data:
TLS 0xbe6841a8 using protocol version 3.3
TLS 0xbe6841a8 selected rsa-aes_cbc-256-sha1
TLS 0xbe6841a8 pre-master-secret:
TLS 0xbe6841a8 client random bytes:
TLS 0xbe6841a8 server random bytes:
TLS 0xbe6841a8 sha256 secret:
TLS 0xbe6841a8 sha256 A(1):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 generated master secret:
TLS 0xbe6841a8 sha256 secret:
TLS 0xbe6841a8 sha256 A(1):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 sha256 output:
TLS 0xbe6841a8 sha256 A(n):
TLS 0xbe6841a8 TX MAC secret:
TLS 0xbe6841a8 RX MAC secret:
TLS 0xbe6841a8 TX key:
TLS 0xbe6841a8 RX key:
TLS 0xbe6841a8 TX IV:
TLS 0xbe6841a8 RX IV:
Received plaintext data:
TLS 0xbe6841a8 found certificate example.com
TLS 0xbe6841a8 found certificate Example Intermediate CA
Received plaintext data:
TLS 0xbe6841a8 sending client certificate netboot-client
Received plaintext data:
TLS 0xbe6841a8 certificate validation succeeded
Sending plaintext data:
Sending plaintext data:
Received plaintext data:
be67a446 : 02 2a : .*
TLS 0xbe684628 received fatal alert 42
Operation not permitted (http://ipxe.org/410de18f)
```

So the certificate validation succeeded now. This seems like a bug, iPXE should only need to trust the root certificate for it to validate the certificate chain just like curl.

However I still get a `fatal alert 42` at the end. So I'm not sure what's wrong here either.

I omitted the bytes being sent above to reduce size. Can somebody explain what I'm doing wrong with iPXE TLS client/server authentication given that ciphers are correct, compatible tls version, path validation works, curl testing works... etc.
Ok I've tested now with just server authentication, not client authentication. The same issue occurs. This time without trusting the intermediate certificate, the TLS download fails. But by trusting the intermediate certificate (and you don't even need to trust the root certificate), the TLS download succeeds.

This is a bug. No other TLS tools (including curl and browsers) require trusting the intermediate certificate. They only require trusting the root certificate, the intermediate path validation should go up to the root. I've tried this on the latest ipxe 1.20.1.

Certificate path validation logic in iPXE is quite different from other tools then.
Using wireshark shows that the difference between using `openssl s_client` and iPXE. The iPXE is not sending the entire client certificate chain (unlike openssl which builds a "client certificate chain"), it is sending just the very first certificate in the pem file put into `CERT=client-chain.pem`). This of course fails, because the server side requires verifying the client certificate against the root certificate.

I'm now testing with the server side putting the intermediate certificate in the trusted store and seeing what happens.
Reference URL's