Commit Graph

302 Commits

Author SHA1 Message Date
Michael Brown
b1125007ca [fdt] Add basic tests for reading values from a flattened device tree
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-14 14:20:31 +01:00
Michael Brown
da3024d257 [cpio] Allow for the construction of pure directories
Allow for the possibility of creating empty directories (without
having to include a dummy file inside the directory) using a
zero-length image and a CPIO filename with a trailing slash, such as:

  initrd emptyfile /usr/share/oem/

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-12 14:32:41 +00:00
Michael Brown
d6ee9a9242 [cpio] Fix calculation of name lengths in CPIO headers
Commit 12ea8c4 ("[cpio] Allow for construction of parent directories
as needed") introduced a regression in constructing CPIO archive
headers for relative paths (e.g. simple filenames with no leading
slash).

Fix by counting the number of path components rather than the number
of path separators, and add some test cases to cover CPIO header
construction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-12 14:27:44 +00:00
Michael Brown
5f3ecbde5a [crypto] Support extracting certificates from EFI signature list images
Add support for the EFI signature list image format (as produced by
tools such as efisecdb).

The parsing code does not require any EFI boot services functions and
so may be enabled even in non-EFI builds.  We default to enabling it
only for EFI builds.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-11 12:58:19 +00:00
Michael Brown
8e6b914c53 [crypto] Support direct reduction only for Montgomery constant R^2 mod N
The only remaining use case for direct reduction (outside of the unit
tests) is in calculating the constant R^2 mod N used during Montgomery
multiplication.

The current implementation of direct reduction requires a writable
copy of the modulus (to allow for shifting), and both the modulus and
the result buffer must be padded to be large enough to hold (R^2 - N),
which is twice the size of the actual values involved.

For the special case of reducing R^2 mod N (or any power of two mod
N), we can run the same algorithm without needing either a writable
copy of the modulus or a padded result buffer.  The working state
required is only two bits larger than the result buffer, and these
additional bits may be held in local variables instead.

Rewrite bigint_reduce() to handle only this use case, and remove the
no longer necessary uses of double-sized big integers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-14 13:03:20 +00:00
Michael Brown
5056e8ad93 [crypto] Expose shifted out bit from big integer shifts
Expose the bit shifted out as a result of shifting a big integer left
or right.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-13 15:25:35 +00:00
Michael Brown
c85de315a6 [crypto] Add definitions and tests for the NIST P-384 elliptic curve
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-30 15:35:34 +00:00
Michael Brown
bc5f3dbe3e [crypto] Add definitions and tests for the NIST P-256 elliptic curve
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-28 16:57:40 +00:00
Michael Brown
c2f21a2185 [test] Add generic tests for elliptic curve point multiplication
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-22 15:07:02 +00:00
Michael Brown
83ba34076a [crypto] Allow for relaxed Montgomery reduction
Classic Montgomery reduction involves a single conditional subtraction
to ensure that the result is strictly less than the modulus.

When performing chains of Montgomery multiplications (potentially
interspersed with additions and subtractions), it can be useful to
work with values that are stored modulo some small multiple of the
modulus, thereby allowing some reductions to be elided.  Each addition
and subtraction stage will increase this running multiple, and the
following multiplication stages can be used to reduce the running
multiple since the reduction carried out for multiplication products
is generally strong enough to absorb some additional bits in the
inputs.  This approach is already used in the x25519 code, where
multiplication takes two 258-bit inputs and produces a 257-bit output.

Split out the conditional subtraction from bigint_montgomery() and
provide a separate bigint_montgomery_relaxed() for callers who do not
require immediate reduction to within the range of the modulus.

Modular exponentiation could potentially make use of relaxed
Montgomery multiplication, but this would require R>4N, i.e. that the
two most significant bits of the modulus be zero.  For both RSA and
DHE, this would necessitate extending the modulus size by one element,
which would negate any speed increase from omitting the conditional
subtractions.  We therefore retain the use of classic Montgomery
reduction for modular exponentiation, apart from the final conversion
out of Montgomery form.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-18 14:31:24 +00:00
Michael Brown
97079553b6 [crypto] Calculate inverse of modulus on demand in bigint_montgomery()
Reduce the number of parameters passed to bigint_montgomery() by
calculating the inverse of the modulus modulo the element size on
demand.  Cache the result, since Montgomery reduction will be used
repeatedly with the same modulus value.

In all currently supported algorithms, the modulus is a public value
(or a fixed value defined by specification) and so this non-constant
timing does not leak any private information.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-16 15:13:37 +00:00
Michael Brown
5202f83345 [crypto] Remove obsolete bigint_mod_multiply()
There is no further need for a standalone modular multiplication
primitive, since the only consumer is modular exponentiation (which
now uses Montgomery multiplication instead).

Remove the now obsolete bigint_mod_multiply().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-28 15:06:17 +00:00
Michael Brown
83ac98ce22 [crypto] Use Montgomery reduction for modular exponentiation
Speed up modular exponentiation by using Montgomery reduction rather
than direct modular reduction.

Montgomery reduction in base 2^n requires the modulus to be coprime to
2^n, which would limit us to requiring that the modulus is an odd
number.  Extend the implementation to include support for
exponentiation with even moduli via Garner's algorithm as described in
"Montgomery reduction with even modulus" (Koç, 1994).

Since almost all use cases for modular exponentation require a large
prime (and hence odd) modulus, the support for even moduli could
potentially be removed in future.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-28 15:06:01 +00:00
Michael Brown
4f7dd7fbba [crypto] Add bigint_montgomery() to perform Montgomery reduction
Montgomery reduction is substantially faster than direct reduction,
and is better suited for modular exponentiation operations.

Add bigint_montgomery() to perform the Montgomery reduction operation
(often referred to as "REDC"), along with some test vectors.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:25:18 +00:00
Michael Brown
96f385d7a4 [crypto] Use inverse size as effective size for bigint_mod_invert()
Montgomery reduction requires only the least significant element of an
inverse modulo 2^k, which in turn depends upon only the least
significant element of the invertend.

Use the inverse size (rather than the invertend size) as the effective
size for bigint_mod_invert().  This eliminates around 97% of the loop
iterations for a typical 2048-bit RSA modulus.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:16:05 +00:00
Michael Brown
7c2e68cc87 [crypto] Eliminate temporary working space for bigint_mod_invert()
With a slight modification to the algorithm to ignore bits of the
residue that can never contribute to the result, it is possible to
reuse the as-yet uncalculated portions of the inverse to hold the
residue.  This removes the requirement for additional temporary
working space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:05:18 +00:00
Michael Brown
9cbf5c4f86 [crypto] Eliminate temporary working space for bigint_reduce()
Direct modular reduction is expected to be used in situations where
there is no requirement to retain the original (unreduced) value.

Modify the API for bigint_reduce() to reduce the value in place,
(removing the separate result buffer), impose a constraint that the
modulus and value have the same size, and require the modulus to be
passed in writable memory (to allow for scaling in place).  This
removes the requirement for additional temporary working space.

Reverse the order of arguments so that the constant input is first,
to match the usage pattern for bigint_add() et al.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-26 14:45:51 +00:00
Michael Brown
167a08f089 [crypto] Expose carry flag from big integer addition and subtraction
Expose the effective carry (or borrow) out flag from big integer
addition and subtraction, and use this to elide an explicit bit test
when performing x25519 reduction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-26 12:55:13 +00:00
Michael Brown
fa1c24d14b [crypto] Add bigint_mod_invert() to calculate inverse modulo a power of two
Montgomery multiplication requires calculating the inverse of the
modulus modulo a larger power of two.

Add bigint_mod_invert() to calculate the inverse of any (odd) big
integer modulo an arbitrary power of two, using a lightly modified
version of the algorithm presented in "A New Algorithm for Inversion
mod p^k (Koç, 2017)".

The power of two is taken to be 2^k, where k is the number of bits
available in the big integer representation of the invertend.  The
inverse modulo any smaller power of two may be obtained simply by
masking off the relevant bits in the inverse.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-21 17:24:53 +01:00
Michael Brown
2bf16c6ffc [crypto] Separate out bigint_reduce() from bigint_mod_multiply()
Faster modular multiplication algorithms such as Montgomery
multiplication will still require the ability to perform a single
direct modular reduction.

Neaten up the implementation of direct reduction and split it out into
a separate bigint_reduce() function, complete with its own unit tests.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-15 13:50:51 +01:00
Michael Brown
7e0bf4ec5c [crypto] Rename bigint_rol()/bigint_ror() to bigint_shl()/bigint_shr()
The big integer shift operations are misleadingly described as
rotations since the original x86 implementations are essentially
trivial loops around the relevant rotate-through-carry instruction.

The overall operation performed is a shift rather than a rotation.
Update the function names and descriptions to reflect this.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-07 13:13:43 +01:00
Michael Brown
3f4f843920 [crypto] Eliminate temporary carry space for big integer multiplication
An n-bit multiplication product may be added to up to two n-bit
integers without exceeding the range of a (2n)-bit integer:

  (2^n - 1)*(2^n - 1) + (2^n - 1) + (2^n - 1) = 2^(2n) - 1

Exploit this to perform big integer multiplication in constant time
without requiring the caller to provide temporary carry space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-27 13:51:24 +01:00
Michael Brown
3def13265d [crypto] Use constant-time big integer multiplication
Big integer multiplication currently performs immediate carry
propagation from each step of the long multiplication, relying on the
fact that the overall result has a known maximum value to minimise the
number of carries performed without ever needing to explicitly check
against the result buffer size.

This is not a constant-time algorithm, since the number of carries
performed will be a function of the input values.  We could make it
constant-time by always continuing to propagate the carry until
reaching the end of the result buffer, but this would introduce a
large number of redundant zero carries.

Require callers of bigint_multiply() to provide a temporary carry
storage buffer, of the same size as the result buffer.  This allows
the carry-out from the accumulation of each double-element product to
be accumulated in the temporary carry space, and then added in via a
single call to bigint_add() after the multiplication is complete.

Since the structure of big integer multiplication is identical across
all current CPU architectures, provide a single shared implementation
of bigint_multiply().  The architecture-specific operation then
becomes the multiplication of two big integer elements and the
accumulation of the double-element product.

Note that any intermediate carry arising from accumulating the lower
half of the double-element product may be added to the upper half of
the double-element product without risk of overflow, since the result
of multiplying two n-bit integers can never have all n bits set in its
upper half.  This simplifies the carry calculations for architectures
such as RISC-V and LoongArch64 that do not have a carry flag.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-23 13:19:58 +01:00
Michael Brown
1d43e535fb [test] Add tests for 64-bit logical and arithmetic shifts
For some 32-bit CPUs, we need to provide implementations of 64-bit
shifts as libgcc helper functions.  Add test cases to cover these.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-15 10:01:35 +01:00
Michael Brown
301644ab48 [test] Add CMS decryption self-tests
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 23:36:00 +01:00
Michael Brown
b053ba1988 [test] Update CMS self-test terminology
Generalise CMS self-test data structure and macro names to refer to
"messages" rather than "signatures", in preparation for adding image
decryption tests.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-28 13:03:55 +01:00
Michael Brown
46937a9df6 [crypto] Remove the concept of a public-key algorithm reusable context
Instances of cipher and digest algorithms tend to get called
repeatedly to process substantial amounts of data.  This is not true
for public-key algorithms, which tend to get called only once or twice
for a given key.

Simplify the public-key algorithm API so that there is no reusable
algorithm context.  In particular, this allows callers to omit the
error handling currently required to handle memory allocation (or key
parsing) errors from pubkey_init(), and to omit the cleanup calls to
pubkey_final().

This change does remove the ability for a caller to distinguish
between a verification failure due to a memory allocation failure and
a verification failure due to a bad signature.  This difference is not
material in practice: in both cases, for whatever reason, the caller
was unable to verify the signature and so cannot proceed further, and
the cause of the error will be visible to the user via the return
status code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-21 21:00:57 +01:00
Michael Brown
633f4f362d [test] Generalise public-key algorithm tests and use okx()
Generalise the existing support for performing RSA public-key
encryption, decryption, signature, and verification tests, and update
the code to use okx() for neater reporting of test results.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-18 23:51:43 +01:00
Michael Brown
53f089b723 [crypto] Pass asymmetric keys as ASN.1 cursors
Asymmetric keys are invariably encountered within ASN.1 structures
such as X.509 certificates, and the various large integers within an
RSA key are themselves encoded using ASN.1.

Simplify all code handling asymmetric keys by passing keys as a single
ASN.1 cursor, rather than separate data and length pointers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-18 15:44:38 +01:00
Michael Brown
97635eb71b [crypto] Generalise cms_signature to cms_message
There is some exploitable similarity between the data structures used
for representing CMS signatures and CMS encryption keys.  In both
cases, the CMS message fundamentally encodes a list of participants
(either message signers or message recipients), where each participant
has an associated certificate and an opaque octet string representing
the signature or encrypted cipher key.  The ASN.1 structures are not
identical, but are sufficiently similar to be worth exploiting: for
example, the SignerIdentifier and RecipientIdentifier data structures
are defined identically.

Rename data structures and functions, and add the concept of a CMS
message type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-14 13:04:01 +01:00
Michael Brown
3b4d0cb555 [crypto] Pass image as parameter to CMS functions
The cms_signature() and cms_verify() functions currently accept raw
data pointers.  This will not be possible for cms_decrypt(), which
will need the ability to extract fragments of ASN.1 data from a
potentially large image.

Change cms_signature() and cms_verify() to accept an image as an input
parameter, and move the responsibility for setting the image trust
flag within cms_verify() since that now becomes a more natural fit.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-13 12:30:51 +01:00
Michael Brown
e965f179e1 [libc] Add stpcpy()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-05-31 10:11:22 +01:00
Michael Brown
d7e58c5a81 [test] Add test cases for editable strings
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-04-17 15:56:08 +01:00
Michael Brown
88c2a01e1a [settings] Expose current working URI and directory URI via settings
iPXE maintains a concept of a current working URI, which is used when
resolving relative URIs and allows scripts to download files using
URIs relative to the script itself.

There are situations in which it is valuable for a script to be able
to access the URI explicitly as a string, not just implicitly as a
base URI for subsequent downloads.  For example, when booting a Fedora
installer, the "inst.repo" command-line parameter may be used to pass
the URI of the repository to the installer.

Expose the current working URI as ${cwuri}.  Since relative URIs may
be constructed as strings only from a directory URI (not from a full
URI), also expose the current working directory URI as ${cwduri}.

This feature may be used as e.g.

  #!ipxe
  echo Booting from ${cwuri}
  prompt -k 0x197e -t 2000 Press F12 to install Fedora... || exit
  kernel images/pxeboot/vmlinux inst.repo=${cwduri}
  initrd images/pxeboot/initrd.img
  boot

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-19 13:33:21 +00:00
Michael Brown
0eb8fbd0bf [settings] Add parsing for UUID and GUID settings types
The ":uuid" and ":guid" settings types are currently format-only: it
is possible to format a setting as a UUID (via e.g. "show foo:uuid")
but it is not currently possible to parse a string into a UUID setting
(via e.g. "set foo:uuid 406343fe-998b-44be-8a28-44ca38cb202b").

Use uuid_aton() to implement parsing of these settings types, and add
appropriate test cases for both.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-29 15:20:44 +00:00
Michael Brown
da7b266289 [uuid] Add uuid_aton() to parse a UUID from a string
Add uuid_aton() to parse a UUID value from a string (analogous to
inet_aton(), inet6_aton(), sock_aton(), etc), treating it as a
32-digit hex string with optional hyphen separators.  The placement of
the separators is not checked: each byte within the hex string may be
separated by a hyphen, or not separated at all.

Add dedicated self-tests for UUID parsing and formatting (already
partially covered by the ":uuid" and ":guid" settings self-tests).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-29 14:43:55 +00:00
Michael Brown
075292cc2d [crypto] Add implementation of MS-CHAPv2 authentication
Add an implementation of the authentication portions of the MS-CHAPv2
algorithm as defined in RFC 2759, along with the single test vector
provided therein.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-22 00:08:27 +00:00
Michael Brown
943d75b557 [crypto] Add x509_is_self_signed() helper function
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-15 12:45:58 +00:00
Michael Brown
3e721e0c08 [crypto] Add x509_truncate() to truncate a certificate chain
Downloading a cross-signed certificate chain to partially replace
(rather than simply extend) an existing chain will require the ability
to discard all certificates after a specified link in the chain.

Extract the relevant logic from x509_free_chain() and expose it
separately as x509_truncate().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14 16:40:05 +00:00
Michael Brown
e10dfe5dc7 [list] Add list_for_each_entry_safe_continue()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14 16:40:05 +00:00
Michael Brown
88b291d647 [list] Add list_is_head_entry()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14 16:25:21 +00:00
Michael Brown
e7ae51b0d7 [crypto] Add implementation of the DES cipher
The DES block cipher dates back to the 1970s.  It is no longer
relevant for use in TLS cipher suites, but it is still used by the
MS-CHAPv2 authentication protocol which remains unfortunately common
for 802.1x port authentication.

Add an implementation of the DES block cipher, complete with the
extremely comprehensive test vectors published by NBS (the precursor
to NIST) in the form of an utterly adorable typewritten and hand-drawn
paper document.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-07 23:32:10 +00:00
Michael Brown
af4583b214 [test] Remove dummy initialisation vector for ECB-mode AES tests
A block cipher in ECB mode has no concept of an initialisation vector,
and any data provided to cipher_setiv() for an ECB cipher will be
ignored.  There is no requirement within our cipher algorithm
abstraction for a dummy initialisation vector to be provided.

Remove the entirely spurious dummy 16-byte initialisation vector from
the ECB test cases.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-07 21:16:47 +00:00
Michael Brown
27398f1360 [crypto] Check for all-zeros result from X25519 key exchange
RFC7748 states that it is entirely optional for X25519 Diffie-Hellman
implementations to check whether or not the result is the all-zero
value (indicating that an attacker sent a malicious public key with a
small order).  RFC8422 states that implementations in TLS must abort
the handshake if the all-zero value is obtained.

Return an error if the all-zero value is obtained, so that the TLS
code will not require knowledge specific to the X25519 curve.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 13:21:01 +00:00
Michael Brown
2eea04c02c [crypto] Add X25519 key exchange algorithm
Add an implementation of the X25519 key exchange algorithm as defined
in RFC7748.

This implementation is inspired by and partially based upon the paper
"Implementing Curve25519/X25519: A Tutorial on Elliptic Curve
Cryptography" by Martin Kleppmann, available for download from
https://www.cl.cam.ac.uk/teaching/2122/Crypto/curve25519.pdf

The underlying modular addition, subtraction, and multiplication
operations are completely redesigned for substantially improved
efficiency compared to the TweetNaCl implementation studied in that
paper (approximately 5x-10x faster and with 70% less memory usage).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 16:44:30 +00:00
Michael Brown
908174ec7e [loong64] Replace broken big integer arithmetic implementations
The slightly incomprehensible LoongArch64 implementation for
bigint_subtract() is observed to produce incorrect results for some
input values.

Replace the suspicious LoongArch64 implementations of bigint_add(),
bigint_subtract(), bigint_rol() and bigint_ror(), and add a test case
for a subtraction that was producing an incorrect result with the
previous implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 16:40:11 +00:00
Michael Brown
bac13ba1f6 [crypto] Add bigint_swap() to conditionally swap big integers
Add a helper function bigint_swap() that can be used to conditionally
swap a pair of big integers in constant time.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 12:34:02 +00:00
Michael Brown
13e390d54e [crypto] Add bigint_copy() as a convenient wrapper macro
Big integers may be efficiently copied using bigint_shrink() (which
will always copy only the size of the destination integer), but this
is potentially confusing to a reader of the code.

Provide bigint_copy() as an alias for bigint_shrink() so that the
intention of the calling code may be more obvious.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 12:29:29 +00:00
Michael Brown
26d3ef062b [crypto] Allow multiplicand and multiplier to differ in size
Big integer multiplication is currently used only as part of modular
exponentiation, where both multiplicand and multiplier will be the
same size.

Relax this requirement to allow for the use of big integer
multiplication in other contexts.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-16 16:09:16 +00:00
Michael Brown
b0093571f8 [crypto] Add support for PKCS#8 private key format
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-02 13:54:42 +01:00