Commit graph

9212 commits

Author SHA1 Message Date
Hanno Becker 180f7bf60b Add compile-time option to remove legacy CRT fields 2019-06-25 09:06:26 +01:00
Hanno Becker b6c39fca5c Add parsing cache to mbedtls_x509_crt
This commit replaces the dummy implementation of the CRT acquire/release
framework by a cache-based implementation which remembers frame and PK
associated to a CRT across multiple `acquire/release` pairs.
2019-06-25 09:06:26 +01:00
Hanno Becker 73cd8d8adc Make use of acquire/release in ssl_parse_certificate_verify() 2019-06-25 09:06:26 +01:00
Hanno Becker 2fefa4845d Make use of acquire/release in ssl_parse_server_key_exchange() 2019-06-25 09:06:26 +01:00
Hanno Becker 39ae65cf73 Make use of acquire/release in ssl_get_ecdh_params_from_cert() 2019-06-25 09:06:26 +01:00
Hanno Becker 0c1681685c Make use of acquire/release in client-side ssl_write_encrypted_pms() 2019-06-25 09:06:26 +01:00
Hanno Becker 232f8faf00 Make use of CRT acquire/release in ssl_write_certificate_request() 2019-06-25 09:06:26 +01:00
Hanno Becker 30649f7a17 Make use of CRT acquire/release in server-side ssl_pick_cert() 2019-06-25 09:06:26 +01:00
Hanno Becker 8c13ee615f Make use of CRT acquire/release in ssl_parse_certificate_verify()
Access the peer's PK through the PK acquire/release API only.

Care has to be taken not to accidentally overwrite the return
value `ret` from the CRT chain verification.
2019-06-25 09:06:26 +01:00
Hanno Becker 6cb5f86dac Make use of CRT acquire/release in mbedtls_debug_print_crt() 2019-06-25 09:06:26 +01:00
Hanno Becker 5c03058bbc Make use of CRT acquire/release in test_suite_x509parse suite 2019-06-25 09:06:26 +01:00
Hanno Becker 8723336831 Make use of CRT acquire/release in x509_crt_verify_restartable 2019-06-25 09:06:26 +01:00
Hanno Becker 082435c011 Make use of CRT acquire/release in x509_crt_verify_name()
This commit modifies the static function `x509_crt_verify_name()` to
use the acquire/release API to access the given CRTs `subject` field.

This function is solely called from the beginning of the CRT chain
verification routine, which also needs to access the child's CRT frame.
It should therefore be considered - for a later commit - to collapse
the two acquire/release pairs to one, thereby saving some code.
2019-06-25 09:06:26 +01:00
Hanno Becker 58c35646df Make use of CRT acquire/release in CRT chain verification #2 2019-06-25 09:06:26 +01:00
Hanno Becker bb26613d32 Make use of CRT acquire/release in x509_crt_verifycrl() 2019-06-25 09:06:26 +01:00
Hanno Becker 79ae5b68e7 Make use of CRT acquire/release in x509_serial_is_revoked() 2019-06-25 09:06:26 +01:00
Hanno Becker e9718b451a Make use of CRT acquire/release in ExtKeyUsage checking 2019-06-25 09:06:26 +01:00
Hanno Becker 371e0e4573 Determine whether CRT is initialized or not through raw data pointer
Previously, `mbedtls_x509_crt_der_internal()` used the `version` field
(which is `0` after initialization but strictly greater than 0 once a
CRT has successfully been parsed) to determine whether an
`mbedtls_x509_crt` instance had already been setup.

Preparating for the removal of `version` from the structure, this
commit modifies the code to instead peek at the raw data pointer,
which is NULL as long as the CRT structure hasn't been setup with a CRT,
and will be kept in the new CRT structure.
2019-06-25 09:06:26 +01:00
Hanno Becker 4f869eda64 Make use of CRT acquire/release in mbedtls_x509_crt_info()
This commit adapts `mbedtls_x509_crt_info()` to no longer access
structure fields from `mbedtls_x509_crt` directly, but to instead
query for a `mbedtls_x509_crt_frame` and `mbedtls_pk_context` and
use these to extract the required CRT information.
2019-06-25 09:06:26 +01:00
Hanno Becker 343fec08ad Add version of MBEDTLS_X509_SAFE_SNPRINTF supporting cleanup section
This will be needed in debugging functions that maintain heap
allocated state, and which hence needs to be freed in case an
`snprintf()` call fails.
2019-06-25 09:06:26 +01:00
Hanno Becker 45eedf1ace Make use of CRT acquire/release in mbedtls_x509_crt_check_key_usage 2019-06-25 09:06:26 +01:00
Hanno Becker 43bf900018 Make use of CRT acquire/release searching for issuer in CRT verif.
This commit continues rewriting the CRT chain verification to use
the new acquire/release framework for CRTs. Specifically, it replaces
all member accesses of the current _parent_ CRT by accesses to the
respective frame.
2019-06-25 09:06:26 +01:00
Hanno Becker e449e2d846 Make use of CRT acquire/release for X.509 CRT signature checking 2019-06-25 09:06:26 +01:00
Hanno Becker 5299cf87d4 Add structure holding X.509 CRT signature information
This commit introduces an internal structure `mbedtls_x509_crt_sig_info`
containing all information that has to be kept from a child CRT when searching
for a potential parent:
- The issuer name
- The signature type
- The signature
- The hash of the CRT

The structure can be obtained from a CRT frame via `x509_crt_get_sig_info()`
and freed via `x509_crt_free_sig_info()`.

The purpose of this is to reduce the amount of RAM used during CRT
chain verification; once we've extracted the signature info structure
from the current child CRT, we can free all cached data for that CRT
(frame and PK) before searching for a suitable parent. This way, there
will ultimately not be more than one frame needed at a single point
during the verification.
2019-06-25 09:06:26 +01:00
Hanno Becker a788cab46d Check validity of potential parent before checking signature
The function `x509_crt_find_parent_in()` traverses a list of CRTs
to find a potential parent to a given CRT. So far, the logic was
the following: For each candidate,
- check basic parenting skills (mostly name match)
- verify signature
- verify validity
This order is insuitable for the new acquire/release layer of
indirection when dealing with CRTs, because we either have to
query the candidate's CRT frame twice, or query frame and PK
simultaneously.

This commit moves the validity check to the beginning of the
routine to allow querying for the frame and then for the PK.

The entry point for restartable ECC needs to be moved for that
to not forget the validity-flag while pausing ECC computations.
2019-06-25 09:06:26 +01:00
Hanno Becker 1e0677acc1 Make use of CRT acquire/release for child in CRT chain verification
During CRT verification, `x509_crt_check_signature()` checks whether a
candidate parent CRT correctly signs the current child CRT.

This commit rewrites this function to use the new acquire/release
framework for using CRTs.
2019-06-25 09:06:26 +01:00
Hanno Becker 337088aa2d Add internal API for acquire/release of CRT frames and PKs
The goal of the subsequent commits is to remove all direct uses
of the existing `mbedtls_x509_crt` apart from the `raw` buffer
and the linked list `next` pointer.

The approach is the following: Whenever a code-path needs to inspect
a CRT, it can request a frame for the CRT through the API
`x509_crt_frame_acquire()`. On success, this function returns a pointer
to a frame structure for the CRT (the origin of which is flexible and
need not concern the caller) that can be used to inspect the desired
fields. Once done, the caller hands back the frame through an explicit
call to `x509_crt_frame_release()`.

This commit also adds an inefficient dummy implementation for
`x509_crt_frame_acquire()` which always allocates a new
`mbedtls_x509_crt_frame` structure on the heap and parses it
from the raw data underlying the CRT. This will change in subsequent
commits, but it constitutes a valid implementation to test against.

Ultimately, `x509_crt_frame_acquire()` is to compute a frame for the
given CRT only once, and cache it for subsequent calls.

The need for `x509_crt_frame_release()` is the following: When
implementing `x509_crt_frame_acquire()` through a flushable cache
as indicated above, it must be ensured that no thread destroys
a cached frame structure for the time it is needed by another
thread. The `acquire/release` pair allows to explicitly delimit
the lifetime requirements for the returned frame structure.
The frame pointer must not be used after the `release` call anymore;
and in fact, the dummy implementation shows that it would
immediately lead to a memory failure.

Analogously to `x509_crt_frame_{acquire|release}()`, there's also
`x509_crt_pk_{acquire|release}()` which allows to acquire/release
a PK context setup from the public key contained within the CRT.
2019-06-25 09:06:26 +01:00
Hanno Becker 21f5567571 Introduce X.509 CRT frame structure
This commit restructures the parsing of X.509 CRTs in the following way:

First, it introduces a 'frame' structure `mbedtls_x509_crt_frame`, which
contains pointers to some structured fields of a CRT as well as copies of
primitive fields. For example, there's a pointer-length pair delimiting the raw
public key data in the CRT, but there's a C-uint8 to store the CRT version
(not a pointer-length pair delimiting the ASN.1 structure holding the version).

Setting up a frame from a raw CRT buffer does not require any memory outside
of the frame structure itself; it's just attaches a 'template' to the buffer
that allows to inspect the structured parts of the CRT afterwards.

Note that the frame structure does not correspond to a particular ASN.1
structure; for example, it contains pointers to delimit the three parts
of a CRT (TBS, SignatureAlgorithm, Signature), but also pointers to the
fields of the TBS, and pointers into the Extensions substructure of the TBS.

Further, the commit introduces an internal function `x509_crt_parse_frame()`
which sets up a frame from a raw CRT buffer, as well as several small helper
functions which help setting up the more complex structures (Subject, Issuer, PK)
from the frame.

These functions are then put to use to rewrite the existing parsing function
`mbedtls_x509_crt_parse_der_core()` by setting up a CRT frame from the input
buffer, residing on the stack, and afterwards copying the respective fields
to the actual `mbedtls_x509_crt` structure and performing the deeper parsing
through the various helper functions.
2019-06-25 09:06:26 +01:00
Hanno Becker c6573a27a1 Convert X.509 name buffer to linked list via name traversal callback 2019-06-25 09:06:26 +01:00
Hanno Becker 6b37812a45 Add next_merged field to X.509 name comparison abort callback 2019-06-25 09:06:26 +01:00
Hanno Becker 10e6b9b2b5 Move point of re-entry for restartable X.509 verification 2019-06-25 09:06:26 +01:00
Hanno Becker b59d3f1692 Add single function to parse ASN.1 AlgorithmIdentifier to x509.c 2019-06-25 09:06:26 +01:00
Hanno Becker 1898b68f09 Allow NULL pointer in mbedtls_x509_get_sig_alg if params not needed
Also, set `sig_opts` pointer to `NULL` if no signature algorithm
parameters are given (to reflect exactly that).
2019-06-25 09:06:26 +01:00
Hanno Becker c84fd1cd95 Check whether CRT is revoked by passing its serial number only
CRLs reference revoked CRTs through their serial number only.
2019-06-25 09:06:26 +01:00
Hanno Becker b3def1d341 Move length check into mbedtls_x509_memcasecmp()
At every occasion where we're using `mbedtls_x509_memcasecmp()` we're
checking that the two buffer lengths coincide before making the call.

This commit saves a few bytes of code by moving this length check
to `mbedtls_x509_memcasecmp()`.
2019-06-25 09:06:26 +01:00
Hanno Becker f1b39bf18c Implement v3 Extension parsing through ASN.1 SEQUENCE OF traversal
This commit rewrites the v3 ext parsing routine `x509_crt_get_ext_cb()`
in terms of the generic ASN.1 SEQUENCE traversal routine.
2019-06-25 09:06:26 +01:00
Hanno Becker c7c638eddd Implement ExtKeyUsage traversal via ASN.1 SEQUENCE OF traversal
This commit re-implements the `ExtendedKeyUsage` traversal
routine in terms of the generic ASN.1 SEQUENCE traversal routine.
2019-06-25 09:06:26 +01:00
Hanno Becker 90b9408dd0 Implement SubjectAltName traversal via ASN.1 SEQUENCE OF traversal
This commit re-implements the `SubjectAlternativeName` traversal
routine in terms of the generic ASN.1 SEQUENCE traversal routine.
2019-06-25 09:06:26 +01:00
Hanno Becker 8730610ae0 Introduce ASN.1 API for traversing ASN.1 SEQUENCEs
This commit adds a new function `mbedtls_asn1_traverse_sequence_of()`
which traverses an ASN.1 SEQUENCE and calls a user-provided callback
for each entry.

It allows to put the following constraints on the tags allowed
in the SEQUENCE:
- A tag mask and mandatory tag value w.r.t. that mask.
  A non-matching tag leads to an MBEDTLS_ERR_ASN1_UNEXPECTED_TAG error.
  For example, it the mask if 0xFF, this means that only
  a single tag will be allowed in the SEQUENCE.
- A tag mask and optional tag value w.r.t. that mask.
  A non-matching tag is silently ignored.

The main use for this flexibility is the traversal of the
`SubjectAlternativeNames` extension, where some parts of the
tag are fixed but some are flexible to indicate which type
of name the entry describes.
2019-06-25 09:06:26 +01:00
Hanno Becker 5984d30f4b Make use of cb to build linked list presentation of SubjectAltName 2019-06-25 09:06:26 +01:00
Hanno Becker ad46219a88 Add cb to build dynamic linked list representation of SubjectAltName
This commit adds a callback for use with `x509_subject_alt_name_traverse()`
which builds the legacy dynamically allocated linked list presentation
of the `SubjectAlternativeNames` extension while traversing the raw data.
2019-06-25 09:06:26 +01:00
Hanno Becker da410828f4 Add callback to search through SubjectAltNames extension
The current CN name verification x509_crt_verify_name() traverses
the dynamically allocated linked list presentation of the subject
alternative name extension, searching for an alternative name that
matches the desired hostname configured by the application.

Eventually, we want to remove this dynamically allocated linked list
for the benefit of reduced code size and RAM usage, and hence need to
rewrite x509_crt_verify_name() in a way that builds on the raw ASN.1
buffer holding the SubjectAlternativeNames extension.

This commit does this by using the existing SubjectAlternativeNames
traversal routine x509_subject_alt_name_traverse(), passing to it a
callback which compares the current alternative name component to the
desired hostname configured by the application.
2019-06-25 09:06:26 +01:00
Hanno Becker 2c6cc045c2 Add function to traverse raw SubjectAltName extension
This commit adds a new function `x509_subject_alt_name_traverse()`
which allows to traverse the raw ASN.1 data of a `SubjectAlternativeNames`
extension.

The `SubjectAlternativeNames` extension needs to be traversed
in the following situations:
1 Initial traversal to check well-formedness of ASN.1 data
2 Traversal to check for a particular name component
3 Building the legacy linked list presentation

Analogously to how multiple tasks related to X.509 name comparison
are implemented through the workhorse `mbedtlS_x509_name_cmp_raw()`,
the new function `x509_subject_alt_name_traverse()` allows to pass
an arbitrary callback which is called on any component of the
`SubjectAlternativeNames` extension found. This way, the above
three tasks can be implemented by passing
1 a NULL callback,
2 a name comparison callback
3 a linked list building callback.
2019-06-25 09:06:26 +01:00
Hanno Becker 2492622289 Pass raw data to x509_check_wildcard() and x509_crt_check_cn()
In preparation for rewriting the `SubjectAlternativeName` search routine
to use raw ASN.1 data, this commit changes `x509_check_wildcard()` and
`x509_check_cn()`, responsible for checking whether a name matches a
wildcard pattern, to take a raw buffer pointer and length as parameters
instead of an `mbedtls_x509_buf` instance.
2019-06-25 09:06:26 +01:00
Hanno Becker ded167e18c Add raw buffer holding SubjectAlternativeName ext to CRT structure
This is analogous to a previous commit for the `ExtendedKeyUsage`
extension: We aim at not using dynamically allocated linked lists
to represent the components of the `SubjectAlternativeName` extension,
but to traverse the raw ASN.1 data when needed.

This commit adds a field to `mbedtls_x509_crt` containing the raw
ASN.1 buffer bounds of the `SubjectAlternativeNames` extension.
2019-06-25 09:06:26 +01:00
Hanno Becker e1956af057 Check for extended key usage by traversing raw extension data
This commit re-implements `mbedtls_x509_crt_check_extended_key_usage()`
to not use the dynamically allocated linked list presentation of the
`ExtendedKeyUsage` but to search for the required usage by traversing
the raw ASN.1 data.
2019-06-25 09:06:26 +01:00
Hanno Becker 7ec9c368f1 Add buffer holding raw ExtKeyUsage extension data to CRT struct
The previous commits replace the use of dynamically allocated linked lists
for X.509 name inspection. This commit is the first in a series which attempts
the same for the `ExtendedKeyUsage` extension. So far, when a CRT is parsed,
the extension is traversed and converted into a dynamically allocated linked
list, which is then search through whenever the usage of a CRT needs to be
checked through `mbedtls_x509_check_extended_key_usage()`.

As a first step, this commit introduces a raw buffer holding the bounds
of the `ExtendedKeyUsage` extension to the `mbedtls_x509_crt` structure.
2019-06-25 09:06:26 +01:00
Hanno Becker 8b543b3ca8 Make use of abort condition callback in CN comparison
The previous CN name comparison function x509_crt_verify_name()
traversed the dynamically allocated linked list presentation of
the CRT's subject, comparing each entry to the desired hostname
configured by the application code.

Eventually, we want to get rid of the linked list presentation of
the CRT's subject to save both code and RAM usage, and hence need
to rewrite the CN verification routine in a way that builds on the
raw ASN.1 subject data only.

In order to avoid duplicating the code for the parsing of the nested
ASN.1 name structure, this commit performs the name search by using
the existing name traversal function mbedtls_x509_name_cmp_raw(),
passing to it a callback which checks whether the current name
component matches the desired hostname.
2019-06-25 09:06:26 +01:00
Hanno Becker 67284cce00 Add abort condition callback to mbedtls_x509_name_cmp_raw()
There are three operations that need to be performed on an X.509 name:
1 Initial traversal to check well-formedness of the ASN.1 structure.
2 Comparison between two X.509 name sequences.
3 Checking whether an X.509 name matches a client's ServerName request.

Each of these tasks involves traversing the nested ASN.1 structure,
In the interest of saving code, we aim to provide a single function
which can perform all of the above tasks.

The existing comparison function is already suitable not only for task 2,
but also for 1: One can simply pass two equal ASN.1 name buffers, in which
case the function will succeed if and only if that buffer is a well-formed
ASN.1 name.

This commit further adds a callback to `mbedtls_x509_name_cmp_raw()` which
is called after each successful step in the simultaneous name traversal and
comparison; it may perform any operation on the current name and potentially
signal that the comparison should be aborted.

With that, task 3 can be implemented by passing equal names and a callback
which aborts as soon as it finds the desired name component.
2019-06-25 09:06:26 +01:00
Hanno Becker 7dee12a38c Make use of raw comparison function in CRT verification
This commit replaces the previous calls to `mbedtls_x509_name_cmp()`
during CRT verification (to match child and parent, to check whether
a CRT is self-issued, and to match CRLs and CAs) by calls to the new
`mbedtls_x509_name_cmp_raw()` using the raw ASN.1 data; it passes the
raw buffers introduced in the last commits.

The previous name comparison function mbedtls_x509_name_cmp() is now
both unused and unneeded, and is removed.
2019-06-25 09:06:26 +01:00