aboutsummaryrefslogtreecommitdiffstats
path: root/src/crypto
Commit message (Collapse)AuthorAgeFilesLines
* [crypto] Allow cms_decrypt() to be called on unregistered imagesMichael Brown2024-08-291-9/+15
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Support decryption of images via CMS envelopesMichael Brown2024-08-291-17/+494
| | | | | | | | Add support for decrypting images containing detached encrypted data using a cipher key obtained from a separate CMS envelope image (in DER or PEM format). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Allow for extraction of ASN.1 algorithm parametersMichael Brown2024-08-283-9/+75
| | | | | | | | | | | Some ASN.1 OID-identified algorithms require additional parameters, such as an initialisation vector for a block cipher. The structure of the parameters is defined by the individual algorithm. Extend asn1_algorithm() to allow these additional parameters to be returned via a separate ASN.1 cursor. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Hold CMS message as a single ASN.1 objectMichael Brown2024-08-231-26/+12
| | | | | | | | | | Reduce the number of dynamic allocations required to parse a CMS message by retaining the ASN.1 cursor returned from image_asn1() for the lifetime of the CMS message. This allows embedded ASN.1 cursors to be used for parsed objects within the message, such as embedded signatures. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Remove the concept of a public-key algorithm reusable contextMichael Brown2024-08-215-167/+205
| | | | | | | | | | | | | | | | | | | | | | | 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>
* [crypto] Pass asymmetric keys as ASN.1 cursorsMichael Brown2024-08-185-34/+16
| | | | | | | | | | | 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>
* [crypto] Generalise cms_signature to cms_messageMichael Brown2024-08-141-233/+282
| | | | | | | | | | | | | | | | | 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>
* [crypto] Add OID-identified algorithms for AES ciphersMichael Brown2024-08-143-0/+140
| | | | | | | Extend the definition of an ASN.1 OID-identified algorithm to include a potential cipher suite, and add identifiers for AES-CBC and AES-GCM. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Pass image as parameter to CMS functionsMichael Brown2024-08-131-15/+33
| | | | | | | | | | | | | 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>
* [crypto] Allow passing a NULL certificate store to x509_find() et alMichael Brown2024-08-132-32/+47
| | | | | | | | | | Allow passing a NULL value for the certificate list to all functions used for identifying an X.509 certificate from an existing set of certificates, and rename function parameters to indicate that this certificate list represents an unordered certificate store (rather than an ordered certificate chain). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Centralise mechanisms for identifying X.509 certificatesMichael Brown2024-08-123-82/+113
| | | | | | | | | Centralise all current mechanisms for identifying an X.509 certificate (by raw content, by subject, by issuer and serial number, and by matching public key), and remove the certstore-specific and CMS-specific variants of these functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Extend asn1_enter() to handle partial object cursorsMichael Brown2024-08-071-9/+37
| | | | | | | | | | | | | | | | | | | | | | | Handling large ASN.1 objects such as encrypted CMS files will require the ability to use the asn1_enter() and asn1_skip() family of functions on partial object cursors, where a defined additional length is known to exist after the end of the data buffer pointed to by the ASN.1 object cursor. We already have support for partial object cursors in the underlying asn1_start() operation used by both asn1_enter() and asn1_skip(), and this is used by the DER image probe routine to check that the potential DER file comprises a single ASN.1 SEQUENCE object. Add asn1_enter_partial() to formalise the process of entering an ASN.1 partial object, and refactor the DER image probe routine to use this instead of open-coding calls to the underlying asn1_start() operation. There is no need for an equivalent asn1_skip_partial() function, since only objects that are wholly contained within the partial cursor may be successfully skipped. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Clarify ASN.1 cursor invalidation behaviourMichael Brown2024-08-071-8/+21
| | | | | | | | | | | | | | | Calling asn1_skip_if_exists() on a malformed ASN.1 object may currently leave the cursor in a partially-updated state, where the tag byte and one of the length bytes have been stripped. The cursor is left with a valid data pointer and length and so no out-of-bounds access can arise, but the cursor no longer points to the start of an ASN.1 object. Ensure that each ASN.1 cursor manipulation code path leads to the cursor being either fully updated, left unmodified, or invalidated, and update the function descriptions to reflect this. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Do not return an error when skipping the final ASN.1 objectMichael Brown2024-08-071-5/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Successfully reaching the end of a well-formed ASN.1 object list is arguably not an error, but the current code (dating back to the original ASN.1 commit in 2007) will explicitly check for and report this as an error condition. Remove the explicit check for reaching the end of a well-formed ASN.1 object list, and instead return success along with a zero-length (and hence implicitly invalidated) cursor. Almost every existing caller of asn1_skip() or asn1_skip_if_exists() currently ignores the return value anyway. Skipped objects are (by definition) not of interest to the caller, and the invalidation behaviour of asn1_skip() ensures that any errors will be safely caught on a subsequent attempt to actually use the ASN.1 object content. Since these existing callers ignore the return value, they cannot be affected by this change. There is one existing caller of asn1_skip_if_exists() that does check the return value: in asn1_skip() itself, an error returned from asn1_skip_if_exists() will cause the cursor to be invalidated. In the case of an error indicating only that the cursor length is already zero, invalidation is a no-op, and so this change affects only the return value propagated from asn1_skip(). This leaves only a single call site within ocsp_request() where the return value from asn1_skip() is currently checked. The return status here is moot since there is no way for the code in question to fail (absent a bug in the ASN.1 construction or parsing code). There are therefore no callers of asn1_skip() or asn1_skip_if_exists() that rely on an error being returned for successfully reaching the end of a well-formed ASN.1 object list. Simplify the code by redefining this as a successful outcome. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [build] Fix build failures with random versions of gccgcmassertMichael Brown2024-03-271-11/+15
| | | | | | | | | | | | For unknown reasons, miscellaneous versions of gcc seem to struggle with the static assertions used to ensure the correct layout of the GCM structures. Adjust the assertions to use offsetof() rather than direct pointer comparison, on the basis that offsetof() must be a compile-time constant value. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add implementation of MS-CHAPv2 authenticationmschapv2Michael Brown2024-02-221-0/+363
| | | | | | | | 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>
* [crypto] Add x509_truncate() to truncate a certificate chainMichael Brown2024-02-141-9/+23
| | | | | | | | | | | 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>
* [build] Fix build failures with older versions of gcccentos7Michael Brown2024-02-101-6/+8
| | | | | | | | | | | | Some versions of gcc (observed with gcc 4.8.5 in CentOS 7) will report spurious build_assert() failures for some assertions about structure layouts. There is no clear pattern as to what causes these spurious failures, and the build assertion does succeed in that no unresolvable symbol reference is generated in the compiled code. Adjust the assertions to work around these apparent compiler issues. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add implementation of the DES cipherMichael Brown2024-02-071-0/+695
| | | | | | | | | | | | | | 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>
* [tls] Add ECDHE cipher suitesMichael Brown2024-01-3113-12/+253
| | | | | | | Add ECDHE variants of the existing cipher suites, and lower the priority of the non-ECDHE variants. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Make key exchange algorithms selectable via build configurationMichael Brown2024-01-308-90/+211
| | | | | | | | | Allow the choice of key exchange algorithms to be controlled via build configuration options in config/crypto.h, as is already done for the choices of public-key algorithms, cipher algorithms, and digest algorithms. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add X25519 OID-identified algorithm and TLS named curveMichael Brown2024-01-301-0/+45
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add an abstraction of an elliptic curveMichael Brown2024-01-301-0/+31
| | | | | | | Define an abstraction of an elliptic curve with a fixed generator and one supported operation (scalar multiplication of a curve point). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Check for all-zeros result from X25519 key exchangeMichael Brown2024-01-301-3/+8
| | | | | | | | | | | | | 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>
* [crypto] Add X25519 key exchange algorithmMichael Brown2024-01-191-0/+808
| | | | | | | | | | | | | | | | | 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>
* [crypto] Add bigint_swap() to conditionally swap big integersMichael Brown2024-01-191-0/+25
| | | | | | | 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>
* [libc] Replace linker_assert() with build_assert()Michael Brown2024-01-166-38/+38
| | | | | | | | | | | | | | | | | | | | | | | We currently implement build-time assertions via a mechanism that generates a call to an undefined external function that will cause the link to fail unless the compiler can prove that the asserted condition is true (and thereby eliminate the undefined function call). This assertion mechanism can be used for conditions that are not amenable to the use of static_assert(), since static_assert() will not allow for proofs via dead code elimination. Add __attribute__((error(...))) to the undefined external function, so that the error is raised at compile time rather than at link time. This allows us to provide a more meaningful error message (which will include the file name and line number, as with any other compile-time error), and avoids the need for the caller to specify a unique symbol name for the external function. Change the name from linker_assert() to build_assert(), since the assertion now takes place at compile time rather than at link time. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add support for PKCS#8 private key formatMichael Brown2023-06-022-1/+44
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [rng] Allow for entropy sources that fail during startup testsMichael Brown2023-02-201-122/+227
| | | | | | | | | Provide per-source state variables for the repetition count test and adaptive proportion test, to allow for the situation in which an entropy source can be enabled but then fails during the startup tests, thereby requiring an alternative entropy source to be used. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [rng] Allow entropy source to be selected at runtimeMichael Brown2023-02-172-229/+94
| | | | | | | | | | | | | | | | | | | | | | | | As noted in commit 3c83843 ("[rng] Check for several functioning RTC interrupts"), experimentation shows that Hyper-V cannot be trusted to reliably generate RTC interrupts. (As noted in commit f3ba0fb ("[hyperv] Provide timer based on the 10MHz time reference count MSR"), Hyper-V appears to suffer from a general problem in reliably generating any legacy interrupts.) An alternative entropy source is therefore required for an image that may be used in a Hyper-V Gen1 virtual machine. The x86 RDRAND instruction provides a suitable alternative entropy source, but may not be supported by all CPUs. We must therefore allow for multiple entropy sources to be compiled in, with the single active entropy source selected only at runtime. Restructure the internal entropy API to allow a working entropy source to be detected and chosen at runtime. Enable the RDRAND entropy source for all x86 builds, since it is likely to be substantially faster than any other source. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Add GCM cipher suitesMichael Brown2022-11-104-8/+128
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Support in-place decryption for GCM ciphersMichael Brown2022-11-101-34/+32
| | | | | | | | | | | | The hash calculation is currently performed incorrectly when decrypting in place, since the ciphertext will have been overwritten with the plaintext before being used to update the hash value. Restructure the code to allow for in-place encryption and decryption. Choose to optimise for the decryption case, since we are likely to decrypt much more data than we encrypt. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Ensure relevant GCM cipher state is cleared by cipher_setiv()Michael Brown2022-11-091-7/+13
| | | | | | | Reset the accumulated authentication state when cipher_setiv() is called, to allow the cipher to be reused without resetting the key. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Allow handshake digest algorithm to be specified by cipher suiteMichael Brown2022-11-092-0/+9
| | | | | | | | | | | | | | | | | | | All existing cipher suites use SHA-256 as the TLSv1.2 and above handshake digest algorithm (even when using SHA-1 as the MAC digest algorithm). Some GCM cipher suites use SHA-384 as the handshake digest algorithm. Allow the cipher suite to specify the handshake (and PRF) digest algorithm to be used for TLSv1.2 and above. This requires some restructuring to allow for the fact that the ClientHello message must be included within the handshake digest, even though the relevant digest algorithm is not yet known at the point that the ClientHello is sent. Fortunately, the ClientHello may be reproduced verbatim at the point of receiving the ServerHello, so we rely on reconstructing (rather than storing) this message. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Add MAC length as a cipher suite parameterMichael Brown2022-11-082-0/+8
| | | | | | | | | | | | | | | TLS stream and block ciphers use a MAC with a length equal to the output length of the digest algorithm in use. For AEAD ciphers there is no MAC, with the equivalent functionality provided by the cipher algorithm's authentication tag. Allow for the existence of AEAD cipher suites by making the MAC length a parameter of the cipher suite. Assume that the MAC key length is equal to the MAC length, since this is true for all currently supported cipher suites. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add concept of cipher alignment sizeMichael Brown2022-11-073-0/+3
| | | | | | | | | | | | | | | | | | | The GCM cipher mode of operation (in common with other counter-based modes of operation) has a notion of blocksize that does not neatly fall into our current abstraction: it does operate in 16-byte blocks but allows for an arbitrary overall data length (i.e. the final block may be incomplete). Model this by adding a concept of alignment size. Each call to encrypt() or decrypt() must begin at a multiple of the alignment size from the start of the data stream. This allows us to model GCM by using a block size of 1 byte and an alignment size of 16 bytes. As a side benefit, this same concept allows us to neatly model the fact that raw AES can encrypt only a single 16-byte block, by specifying an alignment size of zero on this cipher. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Formalise notions of fixed and record initialisation vectorsMichael Brown2022-11-072-0/+16
| | | | | | | | | | | | | | | | | | | | | TLS block ciphers always use CBC (as per RFC 5246 section 6.2.3.2) with a record initialisation vector length that is equal to the cipher block size, and no fixed initialisation vector. The initialisation vector for AEAD ciphers such as GCM is less straightforward, and requires both a fixed and per-record component. Extend the definition of a cipher suite to include fixed and record initialisation vector lengths, and generate the fixed portion (if any) as part of key expansion. Do not add explicit calls to cipher_setiv() in tls_assemble_block() and tls_split_block(), since the constraints imposed by RFC 5246 are specifically chosen to allow implementations to avoid doing so. (Instead, add a sanity check that the record initialisation vector length is equal to the cipher block size.) Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add block cipher Galois/Counter mode of operationMichael Brown2022-10-252-0/+536
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add concept of authentication tag to cipher algorithmsMichael Brown2022-10-253-0/+10
| | | | | | | | Some ciphers (such as GCM) support the concept of a tag that can be used to authenticate the encrypted data. Add a cipher method for generating an authentication tag. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Allow initialisation vector length to vary from cipher blocksizeMichael Brown2022-10-251-1/+2
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Expose null crypto algorithm methods for reuseMichael Brown2022-10-253-51/+31
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Add support for DHE variants of the existing cipher suitesMichael Brown2022-10-112-4/+52
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [tls] Add key exchange mechanism to definition of cipher suiteMichael Brown2022-10-112-0/+4
| | | | | | | Allow for the key exchange mechanism to vary depending upon the selected cipher suite. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add Ephemeral Diffie-Hellman key exchange algorithmMichael Brown2022-10-111-0/+133
| | | | | | | | Add an implementation of the Ephemeral Diffie-Hellman key exchange algorithm as defined in RFC2631, with test vectors taken from the NIST Cryptographic Toolkit. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Simplify internal HMAC APIMichael Brown2022-10-104-93/+54
| | | | | | | | | | | | Simplify the internal HMAC API so that the key is provided only at the point of calling hmac_init(), and the (potentially reduced) key is stored as part of the context for later use by hmac_final(). This simplifies the calling code, and avoids the need for callers such as TLS to allocate a potentially variable length block in order to retain a copy of the unmodified key. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [x509] Use case-insensitive comparison for certificate namesMichael Brown2021-05-181-1/+2
| | | | | | | | DNS names are case-insensitive, and RFC 5280 (unlike RFC 3280) mandates support for case-insensitive name comparison in X.509 certificates. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [x509] Clarify debug message for an untrusted X.509 issuerJosh McSavaney2020-12-281-1/+1
| | | | | | | | | | We surface this debugging information in cases where a cert actually lacks an issuer, but also in cases where it *has* an issuer, but we cannot trust it (e.g. due to issues in establishing a trust chain). Signed-off-by: Josh McSavaney <me@mcsau.cc> Modified-by: Michael Brown <mcb30@ipxe.org> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Allow private key to be specified as a TLS connection parameterMichael Brown2020-12-152-11/+28
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [x509] Make root of trust a reference-counted structureMichael Brown2020-12-092-11/+46
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [x509] Record root of trust used when validating a certificateMichael Brown2020-12-082-7/+22
| | | | | | | | | | | | | Record the root of trust used at the point that a certificate is validated, redefine validation as checking a certificate against a specific root of trust, and pass an explicit root of trust when creating a TLS connection. This allows a custom TLS connection to be used with a custom root of trust, without causing any validated certificates to be treated as valid for normal purposes. Signed-off-by: Michael Brown <mcb30@ipxe.org>