Commit Graph

4386 Commits

Author SHA1 Message Date
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
1421246d44 Update version_features.c 2019-06-25 09:07:16 +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
828a8c08b6 Add compile-guard for < TLS1.2 path in server-side ssl_pick_cert()
Minor code-size optimization along the way.
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
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
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
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