2020-01-21, 09:36
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.
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.