mbedtls_ssl_read() can fail non-fatally, in which case
ssl_parse_certificate_verify() returned immediately without
calling mbedtls_x509_crt_pk_release(), which in turn lead
to a fatal error because of nested acquire calls in the
next call to the function.
Resource counting as a safe-guard against nested acquire calls
is implemented if and only if MBEDTLS_X509_ALWAYS_FLUSH is disabled
_or_ MBEDTLS_THREADING_C is enabled.
Forbidding nested calls to acquire() allows to remove the reference
counting logic and hence saving some bytes of code. This is valuable
because MBEDTLS_X509_ALWAYS_FLUSH is likely to be used on constrained
systems where code-size is limited.
Previously, reference counting for the CRT frames and PK contexts
handed out by mbedtls_x509_crt_{frame|pk}_acquire() was implemented
only in case threading support was enabled, which leaves the door
open for a potential use-after-free should a single-threaded application
use nested calls to mbedtls_x509_crt_acquire().
Since Mbed TLS itself does not use such nested calls, it might be
preferred long-term to forbid nesting of acquire calls on the API
level, and hence get rid of reference counting in the interest of
code-size benefits. However, this can be considered as an optimization
of X.509 on demand parsing, and for now this commit introduces
reference counting unconditionally to have a safe version of
on demand parsing to build further optimizations upon.
During rebase, the definition of ::mbedtls_x509_crt_sig_info
as well as x509_crt_free_sig_info() and x509_crt_get_sig_info()
were accidentally guarded by !MBEDTLS_X509_REMOVE_INFO.
This commit moves their definition outside of that guard.
If MBEDTLS_HAVE_TIME_DATE is undefined, the functions
`mbedtls_x509_time_is_past()` and `mbedtls_x509_time_is_future()`
are still defined but return `0` (that is, no time is seen to in
the past or future). To maintain functional correctness, this
means that these functions have to be called in a way where
the condition being checked for is the erroneous one: Concretely,
one shouldn't check that a CRT's `validFrom` is in the past,
or that its `validTo` is in the future, because that would
fail if !MBEDTLS_HAVE_TIME_DATE. Instead, one should check
that `validFrom` is NOT in the future, and `validTo` is NOT
in the past. That was the logic previously, but an uncautious
change during transition to X.509 on-demand parsing has
changed it. This commit fixes this.
WHen parsing the CRT version, we already check that
version is either 1, 2, or 3, so checking whether
version == 2 or version == 3 is equivalent to
version != 1.
Previously, only one thread could access the parsing cache of an X.509 CRT
at a time. Firstly, this leads to significant performance penalties on
systems running many concurrent threads which share CRT structures --
for example, server threads sharing an SSL configuration containing the
server CRT. Secondly, the locking should be logically unnecessary, because
the threads are supposed to access the CRT frame and PK in a read-only,
or at least thread-safe manner.
This commit modifies the X.509 CRT cache implementation by allowing an
arbitrary number of concurrent readers, locking only the path of setting
up and clearing the cache.
This commit modifies the implementation of x509_get_ext_key_usage()
to not rely on mbedtls_asn1_get_sequence_of() but to instead use
mbedtls_asn1_traverse_sequence_of() with the same sequence-building
callback that also x509_get_subject_alt_name() uses, and which agrees
with the callback used by mbedtls_asn1_get_sequence_of().
The reason for this is that with this change, Mbed TLS itself isn't
using mbedtls_asn1_get_sequence_of() anymore, but only the more powerful
mbedtls_asn1_traverse_sequence_of(), so that unless application code
makes use of mbedtls_asn1_get_sequence_of(), its implementation
-- including the underlying sequence building callback -- will be
removed by link time garbage collection.
This commit introduces two static helpers
- `x509_buf_to_buf_raw()`
- `x509_buf_raw_to_buf()`
which convert to/from the old `mbedtls_x509_buf` and
the new `mbedtls_x509_buf_raw` (the latter omitting the
ASN.1 tag field).
So far, the CRT frame structure `mbedtls_x509_crt_frame` used
as `issuer_raw` and `subject_raw` the _content_ of the ASN.1
name structure for issuer resp. subject. This was in contrast
to the fields `issuer_raw` and `subject_raw` from the legacy
`mbedtls_x509_crt` structure, and caused some information
duplication by having both variants `xxx_no_hdr` and `xxx_with_hdr`
in `mbedtls_x509_crt` and `mbedtls_x509_crt_frame`.
This commit removes this mismatch by solely using the legacy
form of `issuer_raw` and `subject_raw`, i.e. those _including_
the ASN.1 name header.
Previously, `mbedtls_x509_crt_cache_provide_frame()` provided the requested
CRT frame by always parsing the raw data underlying the CRT. That's inefficient
in legacy mode, where the CRTs fields are permanently accessible through the
legacy `mbedtls_x509_crt` structure.
This commit modifies `mbedtls_x509_crt_cache_provide_frame()` in legacy mode
(that is, !MBEDTLS_X509_ON_DEMAND_PARSING) to setup the CRT frame by copying
fields from the legacy CRT structure.
This commit modifies the CRT parsing routine to flush
the CRT cache after parsing. More specifically, the
frame cache is flushed before the PK is parsed, to
avoid storing the PK and frame in RAM at the same time.
With the introduction of `mbedtls_x509_crt_get_{issuer|name}()`,
users need an easy way of freeing the dynamic name structures these
functions return.
To that end, this commit renames `x509_{sequence|name}_free()`
to `mbedtls_x509_{sequence|name}_free()` and gives them external linkage.
The legacy `mbedtls_x509_crt` contains fields `issuer/subject`
which are dynamically allocated linked list presentations of the
CRTs issuer and subject names, respectively.
The new CRT frame structure `mbedtls_x509_crt_frame`, however,
only provides pointers to the raw ASN.1 buffers for the issuer
and subject, for reasons of memory usage.
For convenience to users that previously used the `issuer`/`subject`
fields of `mbedtls_x509_crt`, this commit adds two public API functions
`mbedtls_x509_crt_get_subject()` and `mbedtls_x509_crt_get_issuer()`
which allow to request the legacy linked list presentation of the
CRTs subject / issuer names.
Similar to `mbedtls_x509_crt_get_pk()`, the returned names are owned
by the user, and must be freed through a call to `mbedtls_x509_name_free()`.
This commit unconditionally adds two convenience API functions:
- mbedtls_x509_crt_get_frame()
- mbedtls_x509_crt_get_pk()
which allow users to extract a CRT frame or PK context
from a certificate.
The difference with the existing acquire/release API for frame and PK
contexts is that in contrast to the latter, the structures returned by
the new API are owned by the user (and, in case of the PK context, need
to be freed by him). This makes the API easier to use, but comes at the
cost of additional memory overhead.
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.