Merge remote-tracking branch 'restricted/pr/584' into baremetal-proposed

* restricted/pr/584: (140 commits)
  Remove superfluous new line in x509.c
  Add comment about X.509 name comparison of buffer with itself
  [Fixup] Add missing PK release call in Cert Verify parsing
  Fix guard controlling whether nested acquire calls are allowed
  Add X.509 CRT test for nested calls for CRT frame / PK acquire
  Don't return threading error on release()-without-acquire() calls
  Don't allow nested CRT acquire()-calls if MBEDTLS_X509_ALWAYS_FLUSH
  Make X.509 CRT cache reference counting unconditional
  Remove memory buffer alloc from i386 test in all.sh
  Don't mention pk_sign() in the context of public-key contexts
  Don't use assertion for failures of mbedtls_x509_crt_x_acquire()
  Fix copy pasta in x509_crt.h
  Reference copy-less versions of X.509 CRT frame/PK getters
  x509_crt.c: Add blank line to increase readability
  [FIXUP] Fix bug in ASN.1 traversal of silently ignored tag
  [FIXUP] Fix typo in declaration of mbedtls_x509_memcasecmp()
  Move signature-info extraction out of MBEDTLS_X509_REMOVE_INFO
  Fix certificate validity checking logic to work with !TIME_DATE
  Simplify X.509 CRT version check in UID parsing
  Remove unused variable warning in on-demand X.509 parsing
  ...
This commit is contained in:
Manuel Pégourié-Gonnard
2019-07-03 10:03:45 +02:00
37 changed files with 3518 additions and 1120 deletions

View File

@@ -89,6 +89,18 @@
#define MBEDTLS_ASN1_CONSTRUCTED 0x20
#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80
/* Slightly smaller way to check if tag is a string tag
* compared to canonical implementation. */
#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \
( ( tag ) < 32u && ( \
( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \
( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \
( 1u << MBEDTLS_ASN1_T61_STRING ) | \
( 1u << MBEDTLS_ASN1_IA5_STRING ) | \
( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \
( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \
( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) )
/*
* Bit masks for each of the components of an ASN.1 tag as specified in
* ITU X.690 (08/2015), section 8.1 "General rules for encoding",
@@ -119,6 +131,10 @@
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \
memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \
memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 )
#ifdef __cplusplus
extern "C" {
#endif
@@ -260,20 +276,97 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end
size_t *len );
/**
* \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>"
* Updated the pointer to immediately behind the full sequence tag.
* \brief Free a heap-allocated linked list presentation of
* an ASN.1 sequence, including the first element.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param cur First variable in the chain to fill
* \param tag Type of sequence
* \param seq The address of the first sequence component. This may
* be \c NULL, in which case this functions returns
* immediately.
*/
void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq );
/**
* \brief This function parses and splits an ASN.1 "SEQUENCE OF <tag>"
* and updates the source buffer pointer to immediately behind
* the full sequence.
*
* \param p The address of the pointer to the beginning of the
* ASN.1 SEQUENCE OF structure, including ASN.1 tag+length header.
* On success, `*p` is advanced to point to the first byte
* following the parsed ASN.1 sequence.
* \param end The end of the ASN.1 input buffer starting at \p p. This is
* used for bounds checking.
* \param cur The address at which to store the first entry in the parsed
* sequence. Further entries are heap-allocated and referenced
* from \p cur.
* \param tag The common tag of the entries in the ASN.1 sequence.
*
* \note Ownership for the heap-allocated elements \c cur->next,
* \c cur->next->next, ..., is passed to the caller. It
* is hence the caller's responsibility to free them when
* no longer needed, and mbedtls_asn1_sequence_free() can
* be used for that, passing \c cur->next as the \c seq
* argument (or \p cur if \p cur itself was heap-allocated
* by the caller).
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int mbedtls_asn1_get_sequence_of( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_sequence *cur,
int tag);
int tag );
/**
* \brief Traverse an ASN.1 SEQUENCE container and
* call a callback for each entry.
*
* \warning This function is still experimental and may change
* at any time.
*
* \param p The address of the pointer to the beginning of
* the ASN.1 SEQUENCE header. This is updated to
* point to the end of the ASN.1 SEQUENCE container
* on a successful invocation.
* \param end The end of the ASN.1 SEQUENCE container.
* \param tag_must_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_must_value.
* \param tag_must_val The required value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_must_mask.
* Mismatching tags lead to an error.
* For example, a value of \c 0 for both \p tag_must_mask
* and \p tag_must_val means that every tag is allowed,
* while a value of \c 0xFF for \p tag_must_mask means
* that \p tag_must_val is the only allowed tag.
* \param tag_may_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_may_value.
* \param tag_may_val The desired value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_may_mask.
* Mismatching tags will be silently ignored.
* For example, a value of \c 0 for \p tag_may_mask and
* \p tag_may_val means that any tag will be considered,
* while a value of \c 0xFF for \p tag_may_mask means
* that all tags with value different from \p tag_may_val
* will be ignored.
* \param cb The callback to trigger for each component
* in the ASN.1 SEQUENCE. If the callback returns
* a non-zero value, the function stops immediately,
* forwarding the callback's return value.
* \param ctx The context to be passed to the callback \p cb.
*
* \return \c 0 if successful the entire ASN.1 SEQUENCE
* was traversed without parsing or callback errors.
* \return A negative ASN.1 error code on a parsing failure.
* \return A non-zero error code forwarded from the callback
* \p cb in case the latter returns a non-zero value.
*/
int mbedtls_asn1_traverse_sequence_of(
unsigned char **p,
const unsigned char *end,
uint8_t tag_must_mask, uint8_t tag_must_val,
uint8_t tag_may_mask, uint8_t tag_may_val,
int (*cb)( void *ctx, int tag,
unsigned char* start, size_t len ),
void *ctx );
#if defined(MBEDTLS_BIGNUM_C)
/**

View File

@@ -1757,6 +1757,54 @@
*/
#define MBEDTLS_VERSION_FEATURES
/**
* \def MBEDTLS_X509_ON_DEMAND_PARSING
*
* Save RAM by reducing mbedtls_x509_crt to a pointer
* to the raw CRT data and parsing CRTs on demand only.
*
* \warning This option changes the API by removing most of
* the structure fields of mbedtls_x509_crt.
*
* \warning This option and its corresponding X.509 API are currently
* under development and may change at any time.
*
* Regardless of whether this option is enabled or not, direct access of
* structure fields of `mbedtls_x509_crt` should be replaced by calls to
* one of the following functions:
* - mbedtls_x509_crt_get_frame(), to obtain a CRT frame giving
* access to several basic CRT fields (such as the CRT version),
* as well as pointers to the raw ASN.1 data of more complex fields
* (such as the issuer).
* - mbedtls_x509_crt_get_pk(), to obtain a public key context
* for the public key contained in the certificate.
* - mbedtls_x509_crt_get_issuer(), to obtain the issuer name.
* - mbedtls_x509_crt_get_subject(), to obtain the subject name.
* - mbedtls_x509_crt_get_subject_alt_names(), to obtain the
* alternative names from the subject alternative names extension.
* - mbedtls_x509_crt_get_ext_key_usage(), to obtain the state of
* the extended key usage extension.
*
* Uncomment this to enable on-demand CRT parsing to save RAM.
*/
//#define MBEDTLS_X509_ON_DEMAND_PARSING
/**
* \def MBEDTLS_X509_ALWAYS_FLUSH
*
* Save RAM by having Mbed TLS always flush caches for parsed X.509
* structures after use: This means, firstly, that caches of X.509
* structures used by an API call are flushed when the call returns,
* but it also encompasses immediate flushing of caches when Mbed TLS uses
* multiple structures in succession, thereby reducing the peak RAM usage.
* Setting this option leads to minimal RAM usage of the X.509 module at
* the cost of performance penalties when using X.509 structures multiple
* times (such as trusted CRTs on systems serving many connections).
*
* Uncomment this to always flush caches for unused X.509 structures.
*/
#define MBEDTLS_X509_ALWAYS_FLUSH
/**
* \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
*

View File

@@ -183,6 +183,15 @@ extern "C" {
* \{
*/
/**
* Basic length-value buffer structure
*/
typedef struct mbedtls_x509_buf_raw
{
unsigned char *p; /*!< The address of the first byte in the buffer. */
size_t len; /*!< The number of Bytes in the buffer. */
} mbedtls_x509_buf_raw;
/**
* Type-length-value structure that allows for ASN1 using DER.
*/
@@ -269,6 +278,29 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to );
*/
int mbedtls_x509_time_is_future( const mbedtls_x509_time *from );
/**
* \brief Free a dynamic linked list presentation of an X.509 name
* as returned e.g. by mbedtls_x509_crt_get_subject().
*
* \param name The address of the first name component. This may
* be \c NULL, in which case this functions returns
* immediately.
*/
void mbedtls_x509_name_free( mbedtls_x509_name *name );
/**
* \brief Free a dynamic linked list presentation of an X.509 sequence
* as returned e.g. by mbedtls_x509_crt_get_subject_alt_name().
*
* \param seq The address of the first sequence component. This may
* be \c NULL, in which case this functions returns
* immediately.
*/
static inline void mbedtls_x509_sequence_free( mbedtls_x509_sequence *seq )
{
mbedtls_asn1_sequence_free( (mbedtls_asn1_sequence*) seq );
}
#if defined(MBEDTLS_SELF_TEST)
/**
@@ -280,49 +312,6 @@ int mbedtls_x509_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
/*
* Internal module functions. You probably do not want to use these unless you
* know you do.
*/
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur );
int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg );
int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg, mbedtls_x509_buf *params );
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
int *salt_len );
#endif
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig );
int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
void **sig_opts );
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
mbedtls_x509_time *t );
int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *serial );
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *ext, int tag );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
const void *sig_opts );
#endif
int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name );
int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name );
int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
int critical, const unsigned char *val,
size_t val_len );
int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first );
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first );
int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len,
unsigned char *sig, size_t size );
#define MBEDTLS_X509_SAFE_SNPRINTF \
do { \
if( ret < 0 || (size_t) ret >= n ) \
@@ -332,6 +321,18 @@ int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
p += (size_t) ret; \
} while( 0 )
#define MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP \
do { \
if( ret < 0 || (size_t) ret >= n ) \
{ \
ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; \
goto cleanup; \
} \
\
n -= (size_t) ret; \
p += (size_t) ret; \
} while( 0 )
#ifdef __cplusplus
}
#endif

View File

@@ -75,7 +75,7 @@ typedef struct mbedtls_x509_crl
int version; /**< CRL version (1=v1, 2=v2) */
mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */
mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */
mbedtls_x509_buf_raw issuer_raw; /**< The raw issuer data (DER). */
mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */

View File

@@ -32,6 +32,7 @@
#include "x509.h"
#include "x509_crl.h"
#include "x509_internal.h"
/**
* \addtogroup x509_module
@@ -47,14 +48,69 @@ extern "C" {
* \{
*/
typedef struct mbedtls_x509_crt_frame
{
/* Keep these 8-bit fields at the front of the structure to allow them to
* be fetched in a single instruction on Thumb2; putting them at the back
* requires an intermediate address calculation. */
uint8_t version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
uint8_t ca_istrue; /**< Optional Basic Constraint extension value:
* 1 if this certificate belongs to a CA, 0 otherwise. */
uint8_t max_pathlen; /**< Optional Basic Constraint extension value:
* The maximum path length to the root certificate.
* Path length is 1 higher than RFC 5280 'meaning', so 1+ */
uint8_t ns_cert_type; /**< Optional Netscape certificate type extension value:
* See the values in x509.h */
mbedtls_md_type_t sig_md; /**< The hash algorithm used to hash CRT before signing. */
mbedtls_pk_type_t sig_pk; /**< The signature algorithm used to sign the CRT hash. */
uint16_t key_usage; /**< Optional key usage extension value: See the values in x509.h */
uint32_t ext_types; /**< Bitfield indicating which extensions are present.
* See the values in x509.h. */
mbedtls_x509_time valid_from; /**< The start time of certificate validity. */
mbedtls_x509_time valid_to; /**< The end time of certificate validity. */
mbedtls_x509_buf_raw raw; /**< The raw certificate data in DER. */
mbedtls_x509_buf_raw tbs; /**< The part of the CRT that is [T]o [B]e [S]igned. */
mbedtls_x509_buf_raw serial; /**< The unique ID for certificate issued by a specific CA. */
mbedtls_x509_buf_raw pubkey_raw; /**< The raw public key data (DER). */
mbedtls_x509_buf_raw issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */
mbedtls_x509_buf_raw issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */
mbedtls_x509_buf_raw subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */
mbedtls_x509_buf_raw subject_raw; /**< The raw subject data (DER). Used for quick comparison. */
mbedtls_x509_buf_raw sig; /**< Signature: hash of the tbs part signed with the private key. */
mbedtls_x509_buf_raw sig_alg; /**< The signature algorithm used for \p sig. */
mbedtls_x509_buf_raw v3_ext; /**< The raw data for the extension list in the certificate.
* Might be useful for manual inspection of extensions that
* Mbed TLS doesn't yet support. */
mbedtls_x509_buf_raw subject_alt_raw; /**< The raw data for the SubjectAlternativeNames extension. */
mbedtls_x509_buf_raw ext_key_usage_raw; /**< The raw data for the ExtendedKeyUsage extension. */
} mbedtls_x509_crt_frame;
/**
* Container for an X.509 certificate. The certificate may be chained.
*/
typedef struct mbedtls_x509_crt
{
int own_buffer; /**< Indicates if \c raw is owned
* by the structure or not. */
mbedtls_x509_buf raw; /**< The raw certificate data (DER). */
* by the structure or not. */
mbedtls_x509_buf raw; /**< The raw certificate data (DER). */
mbedtls_x509_crt_cache *cache; /**< Internal parsing cache. */
struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */
/* Legacy fields */
#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
@@ -84,7 +140,7 @@ typedef struct mbedtls_x509_crt
unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */
mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
@@ -92,8 +148,7 @@ typedef struct mbedtls_x509_crt
mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */
mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */
#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
}
mbedtls_x509_crt;
@@ -586,6 +641,366 @@ void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx );
*/
void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/**
* \brief Request CRT frame giving access to basic CRT fields
* and raw ASN.1 data of complex fields.
*
* \param crt The CRT to use. This must be initialized and set up.
* \param dst The address of the destination frame structure.
* This need not be initialized.
*
* \note ::mbedtls_x509_crt_frame does not contain pointers to
* dynamically allocated memory, and hence need not be freed.
* Users may e.g. allocate an instance of
* ::mbedtls_x509_crt_frame on the stack and call this function
* on it, in which case no allocation/freeing has to be done.
*
* \note You may also use mbedtls_x509_crt_frame_acquire() and
* mbedtls_x509_crt_frame_release() for copy-less variants
* of this function.
*
* \return \c 0 on success. In this case, \p dst is updated
* to hold the frame for the given CRT.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_frame( mbedtls_x509_crt const *crt,
mbedtls_x509_crt_frame *dst );
/**
* \brief Set up a PK context with the public key in a certificate.
*
* \param crt The certificate to use. This must be initialized and set up.
* \param pk The address of the destination PK context to fill.
* This must be initialized via mbedtls_pk_init().
*
* \note You may also use mbedtls_x509_crt_pk_acquire() and
* mbedtls_x509_crt_pk_release() for copy-less variants
* of this function.
*
* \return \c 0 on success. In this case, the user takes ownership
* of the destination PK context, and is responsible for
* calling mbedtls_pk_free() on it once it's no longer needed.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_pk( mbedtls_x509_crt const *crt,
mbedtls_pk_context *pk );
/**
* \brief Request the subject name of a CRT, presented
* as a dynamically allocated linked list.
*
* \param crt The CRT to use. This must be initialized and set up.
* \param subject The address at which to store the address of the
* first entry of the generated linked list holding
* the subject name.
*
* \note Depending on your use case, consider using the raw ASN.1
* describing the subject name instead of the heap-allocated
* linked list generated by this call. The pointers to the
* raw ASN.1 data are part of the CRT frame that can be queried
* via mbedtls_x509_crt_get_frame(), and they can be traversed
* via mbedtls_asn1_traverse_sequence_of().
*
* \return \c 0 on success. In this case, the user takes ownership
* of the name context, and is responsible for freeing it
* through a call to mbedtls_x509_name_free() once it's no
* longer needed.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
mbedtls_x509_name **subject );
/**
* \brief Request the subject name of a CRT, presented
* as a dynamically allocated linked list.
*
* \param crt The CRT to use. This must be initialized and set up.
* \param issuer The address at which to store the address of the
* first entry of the generated linked list holding
* the subject name.
*
* \note Depending on your use case, consider using the raw ASN.1
* describing the issuer name instead of the heap-allocated
* linked list generated by this call. The pointers to the
* raw ASN.1 data are part of the CRT frame that can be queried
* via mbedtls_x509_crt_get_frame(), and they can be traversed
* via mbedtls_asn1_traverse_sequence_of().
*
* \return \c 0 on success. In this case, the user takes ownership
* of the name context, and is responsible for freeing it
* through a call to mbedtls_x509_name_free() once it's no
* longer needed.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_issuer( mbedtls_x509_crt const *crt,
mbedtls_x509_name **issuer );
/**
* \brief Request the subject alternative name of a CRT, presented
* as a dynamically allocated linked list.
*
* \param crt The CRT to use. This must be initialized and set up.
* \param subj_alt The address at which to store the address of the
* first component of the subject alternative names list.
*
* \note Depending in your use case, consider using the raw ASN.1
* describing the subject alternative names extension
* instead of the heap-allocated linked list generated by this
* call. The pointers to the raw ASN.1 data are part of the CRT
* frame that can be queried via mbedtls_x509_crt_get_frame(),
* and mbedtls_asn1_traverse_sequence_of() can be used to
* traverse the list of subject alternative names.
*
* \return \c 0 on success. In this case, the user takes ownership
* of the name context, and is responsible for freeing it
* through a call to mbedtls_x509_sequence_free() once it's
* no longer needed.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
mbedtls_x509_sequence **subj_alt );
/**
* \brief Request the ExtendedKeyUsage extension of a CRT,
* presented as a dynamically allocated linked list.
*
* \param crt The CRT to use. This must be initialized and set up.
* \param ext_key_usage The address at which to store the address of the
* first entry of the ExtendedKeyUsage extension.
*
* \note Depending in your use case, consider using the raw ASN.1
* describing the extended key usage extension instead of
* the heap-allocated linked list generated by this call.
* The pointers to the raw ASN.1 data are part of the CRT
* frame that can be queried via mbedtls_x509_crt_get_frame(),
* and mbedtls_asn1_traverse_sequence_of() can be used to
* traverse the entries in the extended key usage extension.
*
* \return \c 0 on success. In this case, the user takes ownership
* of the name context, and is responsible for freeing it
* through a call to mbedtls_x509_sequence_free() once it's
* no longer needed.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
mbedtls_x509_sequence **ext_key_usage );
/**
* \brief Flush internal X.509 CRT parsing cache, if present.
*
* \param crt The CRT structure whose cache to flush.
*
* \note Calling this function frequently reduces RAM usage
* at the cost of performance.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt );
/**
* \brief Request temporary read-access to a certificate frame
* for a given certificate.
*
* Once no longer needed, the frame must be released
* through a call to mbedtls_x509_crt_frame_release().
*
* This is a copy-less version of mbedtls_x509_crt_get_frame().
* See there for more information.
*
* \param crt The certificate to use. This must be initialized and set up.
* \param dst The address at which to store the address of a readable
* certificate frame for the input certificate \p crt which the
* caller can use until calling mbedtls_x509_crt_frame_release().
*
* \note The certificate frame `**frame_ptr` returned by this function
* is owned by the X.509 module and must not be freed or modified
* by the caller. The X.509 module guarantees its validity as long
* as \p crt is valid and mbedtls_x509_crt_frame_release() hasn't
* been issued.
*
* \note In a single-threaded application using
* MBEDTLS_X509_ALWAYS_FLUSH, nested calls to this function
* are not allowed and will fail gracefully with
* MBEDTLS_ERR_X509_FATAL_ERROR.
*
* \return \c 0 on success. In this case, `*frame_ptr` is updated
* to hold the address of a frame for the given CRT.
* \return A negative error code on failure.
*/
static inline int mbedtls_x509_crt_frame_acquire( mbedtls_x509_crt const *crt,
mbedtls_x509_crt_frame const **dst )
{
int ret = 0;
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->frame_readers == 0 )
#endif
ret = mbedtls_x509_crt_cache_provide_frame( crt );
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->frame_readers == MBEDTLS_X509_CACHE_FRAME_READERS_MAX )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
crt->cache->frame_readers++;
#endif
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
*dst = crt->cache->frame;
return( ret );
}
/**
* \brief Release access to a certificate frame acquired
* through a prior call to mbedtls_x509_crt_frame_acquire().
*
* \param crt The certificate for which a certificate frame has
* previously been acquired.
*/
static inline int mbedtls_x509_crt_frame_release( mbedtls_x509_crt const *crt )
{
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->frame_readers == 0 )
return( MBEDTLS_ERR_X509_FATAL_ERROR );
crt->cache->frame_readers--;
#endif
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock( &crt->cache->frame_mutex );
#endif /* MBEDTLS_THREADING_C */
#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
(void) mbedtls_x509_crt_flush_cache_frame( crt );
#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
!defined(MBEDTLS_THREADING_C)
((void) crt);
#endif
return( 0 );
}
/**
* \brief Request temporary access to a public key context
* for a given certificate.
*
* Once no longer needed, the frame must be released
* through a call to mbedtls_x509_crt_pk_release().
*
* This is a copy-less version of mbedtls_x509_crt_get_pk().
* See there for more information.
*
* \param crt The certificate to use. This must be initialized and set up.
* \param dst The address at which to store the address of a public key
* context for the public key in the input certificate \p crt.
*
* \warning The public key context `**pk_ptr` returned by this function
* is owned by the X.509 module and must be used by the caller
* in a thread-safe way. In particular, the caller must only
* use the context with functions which are `const` on the input
* context, or those which are known to be thread-safe. The latter
* for example includes mbedtls_pk_verify() for ECC or RSA public
* key contexts.
*
* \note In a single-threaded application using
* MBEDTLS_X509_ALWAYS_FLUSH, nested calls to this function
* are not allowed and will fail gracefully with
* MBEDTLS_ERR_X509_FATAL_ERROR.
*
* \return \c 0 on success. In this case, `*pk_ptr` is updated
* to hold the address of a public key context for the given
* certificate.
* \return A negative error code on failure.
*/
static inline int mbedtls_x509_crt_pk_acquire( mbedtls_x509_crt const *crt,
mbedtls_pk_context **dst )
{
int ret = 0;
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->pk_readers == 0 )
#endif
ret = mbedtls_x509_crt_cache_provide_pk( crt );
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->pk_readers == MBEDTLS_X509_CACHE_PK_READERS_MAX )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
crt->cache->pk_readers++;
#endif
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
*dst = crt->cache->pk;
return( ret );
}
/**
* \brief Release access to a public key context acquired
* through a prior call to mbedtls_x509_crt_frame_acquire().
*
* \param crt The certificate for which a certificate frame has
* previously been acquired.
*/
static inline int mbedtls_x509_crt_pk_release( mbedtls_x509_crt const *crt )
{
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif /* MBEDTLS_THREADING_C */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
if( crt->cache->pk_readers == 0 )
return( MBEDTLS_ERR_X509_FATAL_ERROR );
crt->cache->pk_readers--;
#endif
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock( &crt->cache->pk_mutex );
#endif /* MBEDTLS_THREADING_C */
#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
(void) mbedtls_x509_crt_flush_cache_pk( crt );
#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
!defined(MBEDTLS_THREADING_C)
((void) crt);
#endif
return( 0 );
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/* \} name */

View File

@@ -0,0 +1,117 @@
/**
* \file x509_internal.h
*
* \brief Internal X.509 functions
*/
/*
* Copyright (C) 2006-2019, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*
*/
#ifndef MBEDTLS_X509_INTERNAL_H
#define MBEDTLS_X509_INTERNAL_H
#include "x509.h"
#include "threading.h"
/* Internal structure used for caching parsed data from an X.509 CRT. */
struct mbedtls_x509_crt;
struct mbedtls_pk_context;
struct mbedtls_x509_crt_frame;
#define MBEDTLS_X509_CACHE_PK_READERS_MAX ((uint32_t) -1)
#define MBEDTLS_X509_CACHE_FRAME_READERS_MAX ((uint32_t) -1)
typedef struct mbedtls_x509_crt_cache
{
#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
defined(MBEDTLS_THREADING_C)
uint32_t frame_readers;
uint32_t pk_readers;
#endif /* !MBEDTLS_X509_ALWAYS_FLUSH || MBEDTLS_THREADING_C */
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t frame_mutex;
mbedtls_threading_mutex_t pk_mutex;
#endif
mbedtls_x509_buf_raw pk_raw;
struct mbedtls_x509_crt_frame *frame;
struct mbedtls_pk_context *pk;
} mbedtls_x509_crt_cache;
/* Internal X.509 CRT cache handling functions. */
int mbedtls_x509_crt_flush_cache_frame( struct mbedtls_x509_crt const *crt );
int mbedtls_x509_crt_flush_cache_pk( struct mbedtls_x509_crt const *crt );
int mbedtls_x509_crt_cache_provide_frame( struct mbedtls_x509_crt const *crt );
int mbedtls_x509_crt_cache_provide_pk( struct mbedtls_x509_crt const *crt );
/* Uncategorized internal X.509 functions */
int mbedtls_x509_get_name( unsigned char *p, size_t len,
mbedtls_x509_name *cur );
int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg );
int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg, mbedtls_x509_buf *params );
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
int *salt_len );
#endif
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig );
int mbedtls_x509_get_sig_alg_raw( unsigned char **p, unsigned char const *end,
mbedtls_md_type_t *md_alg,
mbedtls_pk_type_t *pk_alg,
void **sig_opts );
int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
void **sig_opts );
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
mbedtls_x509_time *t );
int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *serial );
int mbedtls_x509_name_cmp_raw( mbedtls_x509_buf_raw const *a,
mbedtls_x509_buf_raw const *b,
int (*check)( void *ctx,
mbedtls_x509_buf *oid,
mbedtls_x509_buf *val,
int next_merged ),
void *check_ctx );
int mbedtls_x509_memcasecmp( const void *s1, const void *s2,
size_t len1, size_t len2 );
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *ext, int tag );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
int mbedtls_x509_sig_alg_gets( char *buf, size_t size,
mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
const void *sig_opts );
#endif
int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name );
int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name );
int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
int critical, const unsigned char *val,
size_t val_len );
int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first );
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first );
int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len,
unsigned char *sig, size_t size );
#endif /* MBEDTLS_X509_INTERNAL_H */