Table of Contents

Cryptography

iPXE supports the HTTPS protocol, which allows you to encrypt all communication with a web server and to verify the server's identity. To enable support for the HTTPS protocol, you must enable the DOWNLOAD_PROTO_HTTPS build configuration option.

iPXE supports code signing, which allows you to verify the authenticity and integrity of files downloaded by iPXE. To enable support for code signing, you must enable the IMAGE_TRUST_CMD build configuration option, and use the imgtrust command within an embedded script.

iPXE supports file decryption, which allows you to decrypt encrypted files downloaded by iPXE. To enable support for file decryption, you must enable the IMAGE_CRYPT_CMD build configuration option.

Supported configurations

Protocol versions TLSv1.0 TLSv1.1 TLSv1.2
Public-key algorithms RSA
Key exchange algorithms RSA DHE ECDHE
Block cipher algorithms AES-128-GCM AES-256-GCM AES-128-CBC AES-256-CBC
Hash algorithms MD5 SHA-1 SHA-224 SHA-256 SHA-384 SHA-512 SHA-512/224 SHA-512/256
Named curves X25519

The exact list of supported cipher suites is:

Trusted root certificates

In the default configuration, iPXE trusts only a single root certificate: the "iPXE root CA" certificate. This root certificate is used to cross-sign the standard Mozilla list of public CA certificates.

In the default configuration, iPXE will therefore automatically trust the same set of certificates as the Firefox web browser.

If you want more control over the chain of trust, then you can generate your own private root certificate ca.crt using:

  openssl req -x509 -newkey rsa:2048 -out ca.crt -keyout ca.key -days 1000

You can change the list of trusted root certificates when you build iPXE using the TRUST=... build parameter. For example, to trust your private root certificate ca.crt:

  make bin/ipxe.iso TRUST=ca.crt

This will create a custom version of the iPXE binary ipxe.iso which trusts your private root certificate ca.crt.

You can specify multiple root certificates to trust. For example:

  make bin/ipxe.iso TRUST=/path/to/ca1.crt,/path/to/ca2.crt

Certificates must be in PEM format.

Warning

The full root certificates are generally too large to be embedded into the iPXE binary, and so only the SHA-256 fingerprints will be included by default. If you are using the default "iPXE root CA" certificate, then iPXE will automatically download the full root certificate as needed from http://ca.ipxe.org/ca.crt (or from a mirror specified using the crosscert setting).

If you are using a private root certificate, then you must make this certificate available to iPXE either by setting up your own crosscert server, or by including the root certificate within all certificate chains presented to iPXE (as documented below), or by explicitly embedding the full root certificate within the iPXE binary.

Some books

Issuing certificates

You can use your private root certificate ca.crt to issue certificates that will be trusted by iPXE. To do this, you must create a minimal private CA infrastructure:

  echo 01 > ca.srl
  touch ca.idx
  mkdir signed

You must also create a minimal CA configuration file ca.cnf, containing:

  [ ca ]
  default_ca             = ca_default
  
  [ ca_default ]
  certificate            = ca.crt
  private_key            = ca.key
  serial                 = ca.srl
  database               = ca.idx
  new_certs_dir          = signed
  default_md             = default
  policy                 = policy_anything
  preserve               = yes
  default_days           = 90
  unique_subject         = no
  
  [ policy_anything ]
  countryName            = optional
  stateOrProvinceName    = optional
  localityName           = optional
  organizationName       = optional
  organizationalUnitName = optional
  commonName             = optional
  emailAddress           = optional
  
  [ cross ]
  basicConstraints       = critical,CA:true
  keyUsage               = critical,cRLSign,keyCertSign
  
  [ codesigning ]
  keyUsage                = digitalSignature
  extendedKeyUsage        = codeSigning

You can now generate a new server certificate server.crt and the corresponding private key server.key using:

  openssl req -newkey rsa -keyout server.key -out server.req
  openssl ca -config ca.cnf -in server.req -out server.crt

This will create a server certificate server.crt which is signed by your private root certificate. You can optionally create a full certificate chain including both server.crt and your private root certificiate ca.crt using:

  cat server.crt ca.crt > server-full.crt

Cross-signing certificates

You can use your private CA infrastructure to cross-sign an existing public CA root certificate. For example, to cross-sign the StartCom root certificate:

  openssl ca -config ca.cnf -extensions cross -notext -preserveDN -ss_cert startcom.crt -out startcom-cross.crt

This will create a cross-signed certificate startcom-cross.crt. This allows you to extend the trust from your private root certificate to include certificates signed by startcom.crt, without having to directly include startcom.crt as an iPXE trusted root certificate.

Code signing

You can use a code-signing certificate to sign a binary so that it will be trusted by iPXE. Certificates used for code signing must include the digitalSignature key usage extension and the codeSigning extended key usage extension. You can generate a new code-signing certificate codesign.crt and the corresponding private key codesign.key using:

  openssl req -newkey rsa -keyout codesign.key -out codesign.req
  openssl ca -config ca.cnf -extensions codesigning -in codesign.req -out codesign.crt

You can now use this certificate to sign a binary that will then be trusted by iPXE. For example, to sign the binary vmlinuz:

  openssl cms -sign -binary -noattr -in vmlinuz \
              -signer codesign.crt -inkey codesign.key -certfile ca.crt \
              -outform DER -out vmlinuz.sig

This will create the signature file vmlinuz.sig, which you can use with the imgverify command to verify the binary vmlinuz. For example, suppose that you want to use an embedded script to download vmlinuz over an untrusted network:

  #!ipxe
  
  imgtrust --permanent
  dhcp
  kernel http://${next-server}/boot/vmlinuz
  imgverify vmlinuz http://${next-server}/boot/vmlinuz.sig
  boot vmlinuz

This embedded script would refuse to boot unless the downloaded version of vmlinuz could be successfully verified using the signature file vmlinuz.sig.

Embedded certificates

You can embed one or more full certificates when you build iPXE using the CERT=... build parameter. For example:

make bin/ipxe.iso CERT=cert1.crt,cert2.crt

Embedded certificates are not automatically trusted; you will need to specify any trusted root certificates explicitly using the TRUST=... build parameter. For example:

make bin/ipxe.iso CERT=ca.crt TRUST=ca.crt

Warning

Note that embedded certificates are generally quite large, and you should embed a certificate only if it is not feasible to obtain the certificate from another source (e.g. by configuring a crosscert server).

Client certificates

You can generate a client certificate client.crt and the corresponding private key client.key using:

  openssl req -newkey rsa -keyout client.key -out client.req
  openssl ca -config ca.cnf -in client.req -out client.crt

You can embed this client certificate (and the corresponding private key) when you build iPXE using the CERT=... and PRIVKEY=... build parameters. For example:

make bin/ipxe.iso CERT=client.crt PRIVKEY=client.key

This will create a custom version of the iPXE binary which includes your client certificate (and the corresponding private key). You can now configure your web server to require the use of this client certificate for authentication.

The certificate and key must both be in PEM format.

Warning

Note that the private key is stored unencrypted within the iPXE binary. You should therefore treat the iPXE binary as being confidential information.

Using a client certificate will add a noticeable delay (approximately one second) to each HTTPS connection.

File decryption

You can encrypt a file using a client certificate, and then decrypt it within iPXE. For example, to encrypt the binary vmlinuz:

  openssl cms -encrypt -binary -aes-256-gcm -recip client.crt \
              -in vmlinuz -outform DER -out vmlinuz.cms
  
  ./contrib/crypto/cmsdetach vmlinuz.cms -d vmlinuz.dat -e vmlinuz.env

This uses the cmsdetach utility, which you can find in iPXE's contrib/crypto directory, since current versions of openssl cms do not yet support detached encrypted data.

You can then use the imgdecrypt command to decrypt the image. For example:

  #!ipxe
      
  dhcp
  imgfetch http://${next-server}/boot/vmlinuz.dat
  imgfetch http://${next-server}/boot/vmlinuz.env
  imgdecrypt vmlinuz.dat vmlinuz.env
  boot vmlinuz