Commit graph

328 commits

Author SHA1 Message Date
Hanno Becker ed05888195 x509_crt.c: Add blank line to increase readability 2019-06-28 14:48:31 +01:00
Hanno Becker 08d341211d Move signature-info extraction out of MBEDTLS_X509_REMOVE_INFO
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.
2019-06-25 10:41:31 +01:00
Hanno Becker 040c564888 Fix certificate validity checking logic to work with !TIME_DATE
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.
2019-06-25 09:11:11 +01:00
Hanno Becker 97aa4363e1 Simplify X.509 CRT version check in UID parsing
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.
2019-06-25 09:11:11 +01:00
Hanno Becker e908412a35 Simplify logic for issuer/subject ID parsing 2019-06-25 09:11:11 +01:00
Hanno Becker fd64f14ef9 Remove redundant CRT version check during CRT parsing 2019-06-25 09:11:11 +01:00
Hanno Becker b36a245654 Add comment to #endif indicating which condition was guarded 2019-06-25 09:10:57 +01:00
Hanno Becker 484caf0abc Consistently use (type *) instead of (type*) for pointer conversion 2019-06-25 09:10:57 +01:00
Hanno Becker 2ba9fbdfe9 Allow multiple concurrent readers for X.509 CRT frame and PK context
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.
2019-06-25 09:10:57 +01:00
Hanno Becker 5f268b3cf6 Don't allow change of CRT frame returned by x509_crt_frame_acquire() 2019-06-25 09:10:57 +01:00
Hanno Becker 1250623ad1 Mark CRT frame argument to mbedtls_x509_xxx_from_frame() constant 2019-06-25 09:10:57 +01:00
Hanno Becker fd5c185ed6 Use uint16_t to store key usage field in X.509 CRT
Also, reorder the fields to avoid padding, thereby reducing the size of
mbedtls_x509_crt_frame by 2 Bytes.
2019-06-25 09:10:57 +01:00
Hanno Becker 54f1c2cb20 Rename MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR to _WITH_CLEANUP 2019-06-25 09:10:57 +01:00
Hanno Becker 7b8e11e724 Avoid allocating empty buffers when handling length-0 CRTs 2019-06-25 09:10:57 +01:00
Hanno Becker 529f25d119 Don't use mbedtls_asn1_get_sequence_of() in x509_crt.c
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.
2019-06-25 09:10:57 +01:00
Hanno Becker 15b73b4066 Correct placement of comment on X.509 SAN parsing 2019-06-25 09:10:57 +01:00
Hanno Becker f6bc8886c7 Move declarations of internal X.509 functions to separate header
This makes it easier to distinguish public from internal functions;
for us, for users, and for automated API compatibility checkers.
2019-06-25 09:10:57 +01:00
Hanno Becker 76428359b3 Move existence check for pk/frame to mbedtls_x509_crt_provide_xxx() 2019-06-25 09:07:16 +01:00
Hanno Becker bc685199d9 Implement MBEDTLS_X509_ALWAYS_FLUSH 2019-06-25 09:07:16 +01:00
Hanno Becker c6d1c3ed1c Remove frame/pk parameter from mbedtls_x509_crt_xxx_release() 2019-06-25 09:07:16 +01:00
Hanno Becker 38f0cb487c Introduce helpers for conversion between X.509 buffer structs
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).
2019-06-25 09:07:16 +01:00
Hanno Becker 1e11f217d4 Solely use raw X.509 name data references including SEQUENCE header
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.
2019-06-25 09:07:16 +01:00
Hanno Becker 4e021c8f50 Remove raw SubjectAltNames and ExtKeyUsage from legacy CRT struct 2019-06-25 09:07:16 +01:00
Hanno Becker ea32d8ba2a Provide direct way of setting up a CRT frame from legacy CRT struct
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.
2019-06-25 09:07:16 +01:00
Hanno Becker 5226c53e13 Modify mbedtls_x509_crt_info() to use getter API 2019-06-25 09:06:26 +01:00
Hanno Becker 7a4de9cdab Flush CRT cache after parsing
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.
2019-06-25 09:06:26 +01:00
Hanno Becker 2bcc7640f8 Give x509_{sequence|name}_free() external linkage
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.
2019-06-25 09:06:26 +01:00
Hanno Becker ab6c8ea8bc Add public API to query SubjectAltNames and ExtKeyUsage extensions 2019-06-25 09:06:26 +01:00
Hanno Becker 63e6998dd7 Add public API to query subject and issuer from CRT
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()`.
2019-06-25 09:06:26 +01:00
Hanno Becker 823efad6e8 Add public API to query for CRT frame and PK
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.
2019-06-25 09:06:26 +01:00
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 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 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 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