====== 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 [[:buildcfg: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 [[:buildcfg:IMAGE_TRUST_CMD]] build configuration option, and use the ''[[:cmd:imgtrust]]'' command within an [[:embed|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 [[:buildcfg: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: * TLS_RSA_WITH_AES_128_CBC_SHA * TLS_DHE_RSA_WITH_AES_128_CBC_SHA * TLS_RSA_WITH_AES_256_CBC_SHA * TLS_DHE_RSA_WITH_AES_256_CBC_SHA * TLS_RSA_WITH_AES_128_CBC_SHA256 * TLS_RSA_WITH_AES_256_CBC_SHA256 * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 * TLS_RSA_WITH_AES_128_GCM_SHA256 * TLS_RSA_WITH_AES_256_GCM_SHA384 * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ===== Trusted root certificates ===== In the default configuration, iPXE trusts only a single root certificate: the {{:certs:ca.crt|"iPXE root CA" certificate}}. This root certificate is used to cross-sign the standard [[https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt|Mozilla list of public CA certificates]]. In the default configuration, iPXE will therefore automatically trust the same set of certificates as the [[https://www.mozilla.org/firefox/|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 [[:download|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. {{ :clipart:warning.png?90x75|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 {{:certs:ca.crt|"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 ''[[:cfg: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 ''[[:cfg:crosscert]]'' server, or by including the root certificate within all certificate chains presented to iPXE (as documented below), or by explicitly [[#embedded_certificates|embedding the full root certificate]] within the iPXE binary. {{ :clipart:books.png?160x160|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 [[http://cert.startcom.org/|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 ''[[:cmd: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 [[:download|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|trusted root certificates]] explicitly using the ''%%TRUST=...%%'' build parameter. For example: make bin/ipxe.iso CERT=ca.crt TRUST=ca.crt {{ :clipart:warning.png?90x75|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 ''[[:cfg: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 [[:download|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. {{ :clipart:warning.png?90x75|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 ''[[https://github.com/ipxe/ipxe/blob/master/contrib/crypto|contrib/crypto]]'' directory, since current versions of ''openssl cms'' do not yet support detached encrypted data. You can then use the ''[[:cmd: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