When the TLS connection is closed by the underlying socket, the
closure alert will not be able to be sent. This currently results in
a harmless but mildly irritating error message when debugging is
enabled.
Fix by sending the closure alert only when we are actively choosing to
close the connection.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Ephemeral key exchange is currently handled as part of sending the
ClientKeyExchange handshake record, with almost entirely separate
implementations for DHE and ECDHE.
Create wrappers around the underlying key exchange algorithm to handle
the TLS-specific aspects (such as padding and stripping leading zeros
for DHE), and use these for both DHE and ECDHE key exchange.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Requests for metadata within Google Compute Engine require a custom
HTTP header "Metadata-Flavor: Google" to guard against Server-Side
Request Forgery (SSRF) attacks.
Support for this was originally implemented in 2017 using a custom
HTTP request header generator that added this header to any requests
made to metadata.google.com.
In commit 96bb6ba ("[params] Allow for arbitrary HTTP request headers
to be specified"), iPXE gained the ability to generate arbitrary HTTP
headers via the "param" command.
Remove the custom HTTP request header generator, enable the "param"
command for cloud builds, and update the embedded script for Google
Compute Engine to construct the required Metadata-Flavor header.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Calls to the key derivation function tls_prf() currently have to pass
the relevant secret (i.e. the pre-master secret or the master secret)
as a parameter.
Restructure to more closely match the design of the TLS version 1.3
key schedule, which maintains a single running secret (which we choose
to name the "key derivation function master secret") that is always
implicitly used as the secret for key expansion.
The secret value is currently used by tls_prf() only as the key to
hmac_init(). We can therefore use hmac_key() to reduce the secret to
a fixed-length value. (The TLS master secret is already a fixed 48
bytes, but the pre-master secret may be any length.)
The fixed length of the secret is dependent upon the protocol version
and the cipher suite digest algorithm. For TLS version 1.2, the
length is the HMAC key size for the digest algorithm. For TLS version
1.1, which uses separate invocations of HMAC-MD5 and HMAC-SHA1, the
length is the sum of the HMAC-MD5 and HMAC-SHA1 key sizes. (For TLS
version 1.3, the length will be the HKDF key size, i.e. the output
size of the digest algorithm.)
To avoid introducing some very messy memory allocation code paths, we
continue to use a fixed size of 48 bytes for the resumption master
secret stored in the TLS session. This is sufficient to hold the
48-byte raw master secret for TLS version 1.2 and earlier, and will
also be sufficient to hold the HKDF Derive-Secret output for the
longest supported digest algorithm (SHA-384) in TLS version 1.3.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When resuming a session in TLS versions 1.2 and earlier, the master
secret is simply reused. The value stored in the session is therefore
the same as the master secret used in the connection.
For TLS version 1.3, there is a separate concept of a "resumption
master secret" that is derived from the original connection's master
secret, and from which the resumed connection's new master secret will
be derived.
Rename the session master_secret to resumption_master_secret to
clarify this separation.
Resume use of the master secret (i.e. copy the secret from the session
to the connection) only after the cipher suite has been selected, to
reduce differences with the expected flow for TLS version 1.3.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When using QEMU with the KVM accelerator, MMIO writes to the queue
doorbell register are likely to hit an ioeventfd region. KVM will
signal readiness on the ioeventfd file descriptor (which will
eventually wake up the QEMU userspace process to handle the MMIO
write) and then immediately resume execution of the iPXE guest.
This can result in high latencies in processing submitted descriptors.
With the small transmit queue fill level used by iPXE, this can easily
overrun the transmit queue and result in large numbers of dropped
transmissions.
Increase the transmit queue fill level to utilise the whole queue if
needed, and use the transmission deferral mechanism to avoid dropping
packets when high latencies occur during operation.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The queue size calculations currently do not take into account the
fact that each packet requires a pair of descriptors. If the device
happens to present an extremely small queue (16 descriptors for Q0, 32
descriptors for Q1) then this will result in the driver submitting
descriptors beyond the queue's descriptor count. This does not result
in any invalid memory accesses (since the descriptor ring length is
rounded up to a 4kB boundary), but does result in an unusable network
device.
Fix by scaling the packet count and descriptor count values as
required.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The digest algorithm selected by the cipher suite is used for both
calculating the handshake digest and as the tls_prf() key derivation
function digest algorithm. (In TLS version 1.3, it will similarly be
used as the HKDF digest algorithm.)
Move the digest algorithm selection within the key schedule, to
clarify that the scope of this digest algorithm is wider than solely
being used to calculate the handshake digest.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The term "key" has a large number of uses in the context of TLS.
Reduce opportunities for confusion by renaming tls_key_init() and
tls_key_reset() to less generic names.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The hybrid PRF used in TLS version 1.1 and earlier does not use HMAC
with the hybrid MD5+SHA1 algorithm: it uses separate invocations of
HMAC-MD5 and HMAC-SHA1.
Using hmac_keysize(&md5_sha1_algorithm) would produce a size too small
to hold the combined HMAC-MD5 and HMAC-SHA1 keys. One option would be
to set the (currently unused) MD5+SHA1 block size to 128, thereby
ensuring that hmac_keysize() would happen to return a length large
enough to hold both HMAC keys. This would avoid the need to
special-case the MD5+SHA1 algorithm when calculating the required HMAC
key size for the PRF, but would inevitably cause confusion in future.
Set the MD5+SHA1 block size to 64 (since both algorithms have the same
underlying block size, and this would therefore produce the "correct"
result if anything were ever to use HMAC directly with the hybrid
MD5+SHA1 algorithm), and define a separate structure for holding the
separated HMAC keys used by the PRF in TLS version 1.1 and earlier.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The minimum supported TLS version is already configurable via
TLS_VERSION_MIN in config/crypto.h, but changing the maximum TLS
version currently requires editing the source code proper. This makes
it cumbersome to test older TLS versions, and therefore increases the
chances that support for older versions will end up breaking as new
features are added.
Move TLS_VERSION_MAX from include/ipxe/tls.h to config/crypto.h to
ease the process of testing older TLS versions.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit efa9515 ("[tls] Split out hybrid MD5+SHA1 algorithm used in TLS
version 1.1") accidentally removed the empty RSA digestInfo prefix
required for verifying DHE and ECDHE ServerKeyExchange messages when
using TLS version 1.1. (Non-ephemeral cipher suites using RSA key
transport would still work, since the digestInfo is required only for
signatures, not for encryption/decryption.)
Fix by restoring the dummy digestInfo prefix for MD5+SHA1.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
As described in commit 05cb930 ("[build] Extend default configuration
for non-BIOS builds"), the default configuration for EFI needs to
allow for the unfortunate fact that users will not be able to rebuild
the Secure Boot binaries for themselves.
The keyboard map currently defaults to "us" (i.e. no keyboard
remapping) on all platforms. Switch to using the "dynamic" keyboard
map by default for EFI platforms.
Do not use the "dynamic" keyboard map by default on Linux platforms
(where the input character read by iPXE has already passed through the
host's keyboard mapping) or on RISC-V SBI (where input is expected to
come via a serial port rather than a directly attached keyboard).
Requested-by: Simon Fonteneau <blog@lesfourmisduweb.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
An HMAC key can always be reduced to the block size of the underlying
digest algorithm. Provide hmac_key() that can be used to perform this
reduction, and hmac_init_key() as a way to initialise an HMAC digest
operation from a previously reduced key.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The S/390 architecture provides instructions to read the Time-of-Day
(TOD) clock, which increments at a well-defined rate regardless of the
underlying physical clock speed, and has an epoch that starts from
zero at the beginning of the 20th century.
Use this clock to provide both interval timing (i.e. udelay() and
currticks()) and the wall-clock time source. For short interval
timing, we choose to save on code size by treating one millisecond as
1024 microseconds.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The "prno" instruction available on newer CPUs provides a hardware
True Random Number Generator (TRNG) that can be used as an entropy
source, similar to the x86 "rdrand" instruction.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Remove the now-unused implementation of DHE that requires explicit
group parameters, since we now use a standalone key exchange algorithm
abstraction instead.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Now that key exchange algorithms are allowed to fail to construct a
shared public key, we can allocate the temporary working space for
FFDHE calculations on demand rather than using a static buffer.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit 70d63be ("[crypto] Add RFC 3526 FFDHE key exchange algorithms")
defined FFDHE_LEN as a fixed value (rather than deriving it from the
stored length of the Euler constant) and accidentally expressed it as
a bit length rather than a byte length, resulting in substantial
amounts of wasted space.
Fix the maximum length of the modulus and add static assertions to
ensure that the two constants are exactly the required size for this
length.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
All of our current digest algorithms (MD4, MD5, SHA-1, and the SHA-2
family) use a Merkle-Damgård construction, with only the compression
function, the initial digest values, the field sizes, and the
endianness differing between algorithms.
Provide a common implementation for Merkle-Damgård hash algorithms to
reduce code size. Values are now held as host-endian quantities, with
any swapping performed byte-by-byte as data is accumulated (using a
compile-time constant that is XORed with the byte index).
For the SHA family of algorithms, the values w[] are now calculated
iteratively as we progress through the main loop: this substantially
reduces the stack space required for the compression function.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
atl_close() freed the descriptor rings but left the posted receive I/O
buffers allocated, leaking them and tripping an assertion on the next
open. Free any outstanding receive I/O buffers in atl_close().
Signed-off-by: Animesh Bhatt <animeshb@marvell.com>
On AQC113 adapters with an IOMMU (e.g. Intel VT-d) enabled, no packets
are received and DHCP fails: the driver never set netdev->dma, leaving
the transmit buffers unmapped for DMA. This worked without an IOMMU
because the physical address equals the device address, but with an
IOMMU the unmapped DMA access faults and stalls the receive path. Set
netdev->dma and a 64-bit DMA mask so that transmit buffers are mapped
through the firmware IOMMU, as done by the other iPXE drivers.
Signed-off-by: Animesh Bhatt <animeshb@marvell.com>
TLS version 1.3 has a formal key schedule based on HKDF, and requires
the client to be able to recall ephemeral secrets at multiple points
within the connection lifecycle. For example: the ephemeral private
key for X25519 key exchange may be required when constructing
ClientHello (for a TLS version 1.3 key share) or when constructing
ClientKeyExchange (if subsequently falling back to use TLS version
1.2), and again when parsing a ServerHello key share or a
ServerKeyExchange.
Some ephemeral private keys may be large (e.g. for ffdhe4096). Avoid
the need to store these large (and variably sized) private keys by
instead instantiating a standalone HKDF instance that we seed with
per-connection random data and subsequently use to generate ephemeral
private keys on demand. (Note that this instance is unrelated to the
HKDF instance defined in the formal key schedule for TLS: we are
choosing to reuse HKDF for this purpose simply because supporting TLS
version 1.3 will already require HKDF support to be present.)
We use the key exchange algorithm name (e.g. "x25519") as additional
information to ensure separation between keys used for different
purposes. Since the initial random seed is generated afresh for each
connection, and since there can meaningfully be only one ephemeral
private key per key exchange algorithm per connection, this is
sufficient to ensure separation.
Having instantiated this HKDF, we then also use it to generate the
client random bytes (with the label "client random"), to generate the
random portion of the pre-master secret for classic RSA key exchange
(with the label "classic pre-master"), and to generate the random
portion of record IVs (using the authentication header structure,
which is already guaranteed to be unique per record within a
connection). Doing this allows us to eliminate all other calls to the
RNG, and removes some potential failure paths.
We reset the HKDF on a connection restart and on connection close, to
preserve the property of forward secrecy.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Calling hkdf_extract() with no salt and with the input keying material
provided in the same buffer that will hold the output pseudorandom key
is a valid potential use case. This will currently fail silently
since the input keying material would be overwritten by the
constructed all-zero salt before being consumed.
Fix by using a local buffer for the all-zero salt, rather than
constructing the salt in the output buffer.
Document the permitted behaviour in terms of overlapping input and
output buffers for both hkdf_extract() and hkdf_expand(), and extend
the test cases to verify this behaviour.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Following the example of commit 25072c1 ("[crypto] Use private data
field for key exchange algorithms"), extend the definition of a
public-key algorithm to include an opaque private data field, and use
this to eliminate the wrapper functions for PKCS#1 and RSA-PSS.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
GCM ciphers can accept initialisation vectors of any length. Move the
responsibility for checking the initialisation vector length from the
caller into the implementation of cipher_setiv().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Following the example of commit 25072c1 ("[crypto] Use private data
field for key exchange algorithms"), extend the definition of a cipher
algorithm to include an opaque private data field, and use this to
eliminate the wrapper functions generated for the various block cipher
modes of operation by ECB_CIPHER(), CBC_CIPHER(), and GCM_CIPHER().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Following the example of commit 25072c1 ("[crypto] Use private data
field for key exchange algorithms"), extend the definition of a digest
algorithm to include an opaque private data field.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
With algorithm private data pointers now available, the general
mechanism for key exchange using uncompressed elliptic curve points
can be separated from the Weierstrass curve implementation.
Generalise the mechanism for performing elliptic curve key exchange
using uncompressed affine co-ordinates.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Following the example of commit 25072c1 ("[crypto] Use private data
field for key exchange algorithms"), extend the definition of an
elliptic curve to include an opaque private data field, and use this
to eliminate the wrapper functions generated by WEIERSTRASS_CURVE().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Almost all cryptographic algorithm method names are currently verbs
(e.g. pubkey_sign(), cipher_encrypt(), digest_update(), etc).
Rename the two key exchange methods to also use verbs, for the sake of
consistency and to better match the TLS usage of "key_share".
Signed-off-by: Michael Brown <mcb30@ipxe.org>
We do not currently perform any validation on the DHE field prime or
generator. RFC 7919 defines a family of known-safe finite fields, and
TLS version 1.3 completely removes the ability to provide an explicit
field prime and generator.
Verify that the field prime and generator correspond to one of the
explicitly configured groups.
This may break connections to the (now very rare) TLS servers that use
custom FFDHE groups and that choose to use DHE rather than ECDHE (or
that do not support ECDHE). We already advertise ECDHE cipher suites
as preferred over DHE cipher suites, and advertise all ECDHE groups as
preferred over all FFDHE groups. It is therefore very unlikely that
this change will cause any issues in practice.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The RFC 3526 FFDHE groups may plausibly be used by TLS servers, but do
not have IANA-assigned codes.
Allow for the existence of TLS named groups that have no code value
(and can therefore be identified only by matching the group parameter
values).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
In TLS version 1.3, the expected flow is that the client offers at
least one key share in the initial ClientHello, so that key exchange
can take place as soon as the ServerHello is received (without
requiring a HelloRetryRequest and a second round trip).
We cannot viably offer key shares for all supported groups, since the
FFDHE groups have large public key values. The most likely approach
will be that we offer a single key share for our most preferred group.
Experiments suggest that X25519 is currently the most widely supported
key exchange group. Make this the most preferred group to maximise
the chance that a (future) TLS version 1.3 handshake will avoid the
extra round trip for a HelloRetryRequest.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Provide is_ffdhe() and ffdhe_has_params() as a way to check if a key
exchange algorithm happens to match against an explicit pair of prime
modulus and generator values.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
For historical reasons, TLS versions 1.2 and earlier identify FFDHE
groups by specifying the raw group prime and generator (the "dh_p" and
"dh_g" fields in ServerDHParams), rather than using a numeric code to
identify a named group.
This adds complexity to the process of identifying the internal key
exchange algorithm. One option would be to extend the definition of
struct tls_key_exchange_algorithm to include the identifying values
for the field prime and generator, but this is undesirable since the
field prime values may be large, and these values are already
available (indirectly) in ffdhe.c.
Extend our definition of a key exchange algorithm to include an opaque
private data field. This allows us to remove the wrapper functions
currently created by FFDHE_GROUP() and WEIERSTRASS_CURVE(), and opens
up the option of accessing the existing FFDHE field prime and
generator values from within the TLS layer.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The family of finite fields defined in RFC 7919 is almost identical to
that defined in RFC 3526, with the difference being that the older
standard uses the constant "pi" rather than "e".
Extend the definition of an FFDHE group to include a pointer to the
group constant, add the value of "pi", and define the modp2048,
modp3072, and modp4096 FFDHE groups.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The bigint_grow() and bigint_shrink() functions are used on the fast
path for big integer calculations (e.g. within the X25519 Montgomery
ladder step). Use inline assembly implementations of these functions
on all architectures.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The XOR instruction has a storage-and-storage format "xc" that can be
used to zero small blocks of memory without needing to set up the four
registers required for "mvcle".
Signed-off-by: Michael Brown <mcb30@ipxe.org>
RFC 7919 renames the NamedCurve enumeration to NamedGroup, reflecting
its extended usage to handle key exchange groups that are not
constructed using elliptic curves.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
In some configurations, newer versions of QEMU will end up placing the
modern interface's BAR4 above 4GB, rendering it inaccessible in a
32-bit build of iPXE. We will currently detect the existence of the
modern interface and attempt to use it, but fail at the point of
attempting to map the PCI BARs.
Fix by ignoring any virtio capabilities that describe an inaccessible
PCI BAR, and thereby allowing iPXE to fall back to using the legacy
interface if the modern interface's BAR cannot be used.
Reported-by: Jan ONDREJ (SAL) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allow the system time offset to be modified by writing a new time
value to builtin/unixtime, e.g.:
set builtin/unixtime 0x10d1a884
As with the NTP client, this does not attempt to write to the
underlying clock source (e.g. the RTC clock). Only the internal
system time offset is updated.
Any system time offset may be reset by clearing the setting:
clear builtin/unixtime
This will reset the system time offset to zero and so can be used to
undo the effect of a previous "set builtin/unixtime" or "ntp" command.
Requested-by: Christian I. Nilsson <ChristianN@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>