/* * X.509 common functions for parsing and verification * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_USE_C) #include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include <stdio.h> #include <string.h> #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/asn1write.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) #include "mbedtls/platform_util.h" #include <time.h> #endif #define CHECK(code) … #define CHECK_RANGE(min, max, val) … /* * CertificateSerialNumber ::= INTEGER */ int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial) { … } /* Get an algorithm identifier without parameters (eg for signatures) * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg) { … } /* * Parse an algorithm identifier with (optional) parameters */ int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params) { … } /* * Convert md type to string */ #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) { … } #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) /* * HashAlgorithm ::= AlgorithmIdentifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * * For HashAlgorithm, parameters MUST be NULL or absent. */ static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) { … } /* * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] INTEGER DEFAULT 1 } * -- Note that the tags in this Sequence are explicit. * * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other * option. Enforce this at parsing time. */ 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 /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_get_attr_type_value(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { … } /* * Name ::= CHOICE { -- only one possibility for now -- * rdnSequence RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * The data structure is optimized for the common case where each RDN has only * one element, which is represented as a list of AttributeTypeAndValue. * For the general case we still use a flat list, but we mark elements of the * same set so that they are "merged" together in the functions that consume * this list, eg mbedtls_x509_dn_gets(). * * On success, this function may allocate a linked list starting at cur->next * that must later be free'd by the caller using mbedtls_free(). In error * cases, this function frees all allocated memory internally and the caller * has no freeing responsibilities. */ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { … } static int x509_date_is_valid(const mbedtls_x509_time *t) { … } static int x509_parse2_int(const unsigned char *p) { … } /* * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) * field. */ static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, size_t yearlen) { … } /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, mbedtls_x509_time *tm) { … } int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) { … } /* * Get signature algorithm from alg OID and optional parameters */ 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) { … } /* * X.509 Extensions (No parsing of extensions, pointer should * be either manually updated or extensions should be parsed!) */ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag) { … } static char nibble_to_hex_digit(int i) { … } /* * Store the name in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) { … } /* * Store the serial in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) { … } #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Helper for writing signature algorithms */ 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 /* MBEDTLS_X509_REMOVE_INFO */ /* * Helper for writing "RSA key size", "EC key size", etc */ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) { … } int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2) { … } #if defined(MBEDTLS_HAVE_TIME_DATE) int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) { … } static int x509_get_current_time(mbedtls_x509_time *now) { … } int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { … } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { … } #else /* MBEDTLS_HAVE_TIME_DATE */ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { ((void) to); return 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { ((void) from); return 0; } #endif /* MBEDTLS_HAVE_TIME_DATE */ /* Common functions for parsing CRT and CSR. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) /* * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * HardwareModuleName ::= SEQUENCE { * hwType OBJECT IDENTIFIER, * hwSerialNum OCTET STRING } * * NOTE: we currently only parse and use otherName of type HwModuleName, * as defined in RFC 4108. */ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, mbedtls_x509_san_other_name *other_name) { … } /* Check mbedtls_x509_get_subject_alt_name for detailed description. * * In some cases while parsing subject alternative names the sequence tag is optional * (e.g. CertSerialNumber). This function is designed to handle such case. */ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { … } /* * SubjectAltName ::= GeneralNames * * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER } * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } * * We list all types, but use the following GeneralName types from RFC 5280: * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" * of type "otherName", as defined in RFC 4108. */ int mbedtls_x509_get_subject_alt_name(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { … } int mbedtls_x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, unsigned char *ns_cert_type) { … } int mbedtls_x509_get_key_usage(unsigned char **p, const unsigned char *end, unsigned int *key_usage) { … } int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, mbedtls_x509_subject_alternative_name *san) { … } void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) { … } #if !defined(MBEDTLS_X509_REMOVE_INFO) int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, const mbedtls_x509_sequence *subject_alt_name, const char *prefix) { … } #define PRINT_ITEM(i) … #define CERT_TYPE(type, name) … int mbedtls_x509_info_cert_type(char **buf, size_t *size, unsigned char ns_cert_type) { … } #define KEY_USAGE(code, name) … int mbedtls_x509_info_key_usage(char **buf, size_t *size, unsigned int key_usage) { … } #endif /* MBEDTLS_X509_REMOVE_INFO */ #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ #endif /* MBEDTLS_X509_USE_C */