Move common functions for crt/csr parsing to x509.c
Signed-off-by: Przemek Stekiel <przemyslaw.stekiel@mobica.com>
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index abd36b8..aa1cd08 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -250,6 +250,56 @@
}
mbedtls_x509_time;
+/**
+ * From RFC 5280 section 4.2.1.6:
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * Future versions of the library may add new fields to this structure or
+ * to its embedded union and structure.
+ */
+typedef struct mbedtls_x509_san_other_name {
+ /**
+ * The type_id is an OID as defined in RFC 5280.
+ * To check the value of the type id, you should use
+ * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
+ */
+ mbedtls_x509_buf type_id; /**< The type id. */
+ union {
+ /**
+ * From RFC 4108 section 5:
+ * HardwareModuleName ::= SEQUENCE {
+ * hwType OBJECT IDENTIFIER,
+ * hwSerialNum OCTET STRING }
+ */
+ struct {
+ mbedtls_x509_buf oid; /**< The object identifier. */
+ mbedtls_x509_buf val; /**< The named value. */
+ }
+ hardware_module_name;
+ }
+ value;
+}
+mbedtls_x509_san_other_name;
+
+/**
+ * A structure for holding the parsed Subject Alternative Name,
+ * according to type.
+ *
+ * Future versions of the library may add new fields to this structure or
+ * to its embedded union and structure.
+ */
+typedef struct mbedtls_x509_subject_alternative_name {
+ int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
+ union {
+ mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
+ mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
+ }
+ san; /**< A union of the supported SAN types */
+}
+mbedtls_x509_subject_alternative_name;
+
/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
/**
@@ -326,6 +376,36 @@
*/
int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
+/**
+ * \brief This function parses an item in the SubjectAlternativeNames
+ * extension.
+ *
+ * \param san_buf The buffer holding the raw data item of the subject
+ * alternative name.
+ * \param san The target structure to populate with the parsed presentation
+ * of the subject alternative name encoded in \p san_raw.
+ *
+ * \note Only "dnsName" and "otherName" of type hardware_module_name
+ * as defined in RFC 4180 is supported.
+ *
+ * \note This function should be called on a single raw data of
+ * subject alternative name. For example, after successful
+ * certificate parsing, one must iterate on every item in the
+ * \p crt->subject_alt_names sequence, and pass it to
+ * this function.
+ *
+ * \warning The target structure contains pointers to the raw data of the
+ * parsed certificate, and its lifetime is restricted by the
+ * lifetime of the certificate.
+ *
+ * \return \c 0 on success
+ * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
+ * SAN type.
+ * \return Another negative value for any other failure.
+ */
+int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
+ mbedtls_x509_subject_alternative_name *san);
+
/** \} addtogroup x509_module */
/*
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 661f8aa..2060835 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -103,56 +103,6 @@
mbedtls_x509_crt;
/**
- * From RFC 5280 section 4.2.1.6:
- * OtherName ::= SEQUENCE {
- * type-id OBJECT IDENTIFIER,
- * value [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * Future versions of the library may add new fields to this structure or
- * to its embedded union and structure.
- */
-typedef struct mbedtls_x509_san_other_name {
- /**
- * The type_id is an OID as defined in RFC 5280.
- * To check the value of the type id, you should use
- * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
- */
- mbedtls_x509_buf type_id; /**< The type id. */
- union {
- /**
- * From RFC 4108 section 5:
- * HardwareModuleName ::= SEQUENCE {
- * hwType OBJECT IDENTIFIER,
- * hwSerialNum OCTET STRING }
- */
- struct {
- mbedtls_x509_buf oid; /**< The object identifier. */
- mbedtls_x509_buf val; /**< The named value. */
- }
- hardware_module_name;
- }
- value;
-}
-mbedtls_x509_san_other_name;
-
-/**
- * A structure for holding the parsed Subject Alternative Name,
- * according to type.
- *
- * Future versions of the library may add new fields to this structure or
- * to its embedded union and structure.
- */
-typedef struct mbedtls_x509_subject_alternative_name {
- int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
- union {
- mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
- mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
- }
- san; /**< A union of the supported SAN types */
-}
-mbedtls_x509_subject_alternative_name;
-
-/**
* Build flag from an algorithm/curve identifier (pk, md, ecp)
* Since 0 is always XXX_NONE, ignore it.
*/
@@ -589,36 +539,6 @@
int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path);
#endif /* MBEDTLS_FS_IO */
-/**
- * \brief This function parses an item in the SubjectAlternativeNames
- * extension.
- *
- * \param san_buf The buffer holding the raw data item of the subject
- * alternative name.
- * \param san The target structure to populate with the parsed presentation
- * of the subject alternative name encoded in \p san_raw.
- *
- * \note Only "dnsName" and "otherName" of type hardware_module_name
- * as defined in RFC 4180 is supported.
- *
- * \note This function should be called on a single raw data of
- * subject alternative name. For example, after successful
- * certificate parsing, one must iterate on every item in the
- * \p crt->subject_alt_names sequence, and pass it to
- * this function.
- *
- * \warning The target structure contains pointers to the raw data of the
- * parsed certificate, and its lifetime is restricted by the
- * lifetime of the certificate.
- *
- * \return \c 0 on success
- * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
- * SAN type.
- * \return Another negative value for any other failure.
- */
-int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
- mbedtls_x509_subject_alternative_name *san);
-
#if !defined(MBEDTLS_X509_REMOVE_INFO)
/**
* \brief Returns an informational string about the
diff --git a/library/x509.c b/library/x509.c
index 1b3701c..9869b05 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -1107,4 +1107,490 @@
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)
+{
+ int ret = 0;
+ size_t len;
+ unsigned char *p = subject_alt_name->p;
+ const unsigned char *end = p + subject_alt_name->len;
+ mbedtls_x509_buf cur_oid;
+
+ if ((subject_alt_name->tag &
+ (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
+ (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
+ /*
+ * The given subject alternative name is not of type "othername".
+ */
+ return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+ }
+
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_OID)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ cur_oid.tag = MBEDTLS_ASN1_OID;
+ cur_oid.p = p;
+ cur_oid.len = len;
+
+ /*
+ * Only HwModuleName is currently supported.
+ */
+ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
+ return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+ }
+
+ if (p + len >= end) {
+ mbedtls_platform_zeroize(other_name, sizeof(*other_name));
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+ p += len;
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
+ 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
+ other_name->value.hardware_module_name.oid.p = p;
+ other_name->value.hardware_module_name.oid.len = len;
+
+ if (p + len >= end) {
+ mbedtls_platform_zeroize(other_name, sizeof(*other_name));
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+ p += len;
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
+ other_name->value.hardware_module_name.val.p = p;
+ other_name->value.hardware_module_name.val.len = len;
+ p += len;
+ if (p != end) {
+ mbedtls_platform_zeroize(other_name,
+ sizeof(*other_name));
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+ return 0;
+}
+
+/*
+ * 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 }
+ *
+ * NOTE: we list all types, but only use dNSName and otherName
+ * of type HwModuleName, as defined in RFC 4108, at this point.
+ */
+int mbedtls_x509_get_subject_alt_name(unsigned char **p,
+ const unsigned char *end,
+ mbedtls_x509_sequence *subject_alt_name)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len, tag_len;
+ mbedtls_asn1_buf *buf;
+ unsigned char tag;
+ mbedtls_asn1_sequence *cur = subject_alt_name;
+
+ /* Get main sequence tag */
+ if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if (*p + len != end) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+
+ while (*p < end) {
+ mbedtls_x509_subject_alternative_name dummy_san_buf;
+ memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
+
+ tag = **p;
+ (*p)++;
+ if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
+ MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+ }
+
+ /*
+ * Check that the SAN is structured correctly.
+ */
+ ret = mbedtls_x509_parse_subject_alt_name(&(cur->buf), &dummy_san_buf);
+ /*
+ * In case the extension is malformed, return an error,
+ * and clear the allocated sequences.
+ */
+ if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
+ mbedtls_asn1_sequence_free(subject_alt_name->next);
+ subject_alt_name->next = NULL;
+ return ret;
+ }
+
+ /* Allocate and assign next pointer */
+ if (cur->buf.p != NULL) {
+ if (cur->next != NULL) {
+ return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+ }
+
+ cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
+
+ if (cur->next == NULL) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_ALLOC_FAILED);
+ }
+
+ cur = cur->next;
+ }
+
+ buf = &(cur->buf);
+ buf->tag = tag;
+ buf->p = *p;
+ buf->len = tag_len;
+ *p += buf->len;
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if (*p != end) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+
+ return 0;
+}
+
+int mbedtls_x509_get_ns_cert_type(unsigned char **p,
+ const unsigned char *end,
+ unsigned char *ns_cert_type)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_x509_bitstring bs = { 0, 0, NULL };
+
+ if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if (bs.len == 0) {
+ *ns_cert_type = 0;
+ return 0;
+ }
+
+ if (bs.len != 1) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+ }
+
+ /* Get actual bitstring */
+ *ns_cert_type = *bs.p;
+ return 0;
+}
+
+int mbedtls_x509_get_key_usage(unsigned char **p,
+ const unsigned char *end,
+ unsigned int *key_usage)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t i;
+ mbedtls_x509_bitstring bs = { 0, 0, NULL };
+
+ if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+ }
+
+ if (bs.len == 0) {
+ *key_usage = 0;
+ return 0;
+ }
+
+ if (bs.len < 1) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+ MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+ }
+
+ /* Get actual bitstring */
+ *key_usage = 0;
+ for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
+ *key_usage |= (unsigned int) bs.p[i] << (8*i);
+ }
+
+ return 0;
+}
+
+int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
+ mbedtls_x509_subject_alternative_name *san)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ switch (san_buf->tag &
+ (MBEDTLS_ASN1_TAG_CLASS_MASK |
+ MBEDTLS_ASN1_TAG_VALUE_MASK)) {
+ /*
+ * otherName
+ */
+ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
+ {
+ mbedtls_x509_san_other_name other_name;
+
+ ret = x509_get_other_name(san_buf, &other_name);
+ if (ret != 0) {
+ return ret;
+ }
+
+ memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+ san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+ memcpy(&san->san.other_name,
+ &other_name, sizeof(other_name));
+
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
+ {
+ memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+ san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+ memcpy(&san->san.unstructured_name,
+ san_buf, sizeof(*san_buf));
+
+ }
+ break;
+
+ /*
+ * Type not supported
+ */
+ default:
+ return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+ }
+ return 0;
+}
+
+#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)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t i;
+ size_t n = *size;
+ char *p = *buf;
+ const mbedtls_x509_sequence *cur = subject_alt_name;
+ mbedtls_x509_subject_alternative_name san;
+ int parse_ret;
+
+ while (cur != NULL) {
+ memset(&san, 0, sizeof(san));
+ parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
+ if (parse_ret != 0) {
+ if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
+ ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ } else {
+ ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ }
+ cur = cur->next;
+ continue;
+ }
+
+ switch (san.type) {
+ /*
+ * otherName
+ */
+ case MBEDTLS_X509_SAN_OTHER_NAME:
+ {
+ mbedtls_x509_san_other_name *other_name = &san.san.other_name;
+
+ ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
+ &other_name->value.hardware_module_name.oid) != 0) {
+ ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ ret =
+ mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret = mbedtls_oid_get_numeric_string(p,
+ n,
+ &other_name->value.hardware_module_name.oid);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret =
+ mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
+ ret = mbedtls_snprintf(p,
+ n,
+ "%02X",
+ other_name->value.hardware_module_name.val.p[i]);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ }
+ }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case MBEDTLS_X509_SAN_DNS_NAME:
+ {
+ ret = mbedtls_snprintf(p, n, "\n%s dNSName : ", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ if (san.san.unstructured_name.len >= n) {
+ *p = '\0';
+ return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+ }
+
+ memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
+ p += san.san.unstructured_name.len;
+ n -= san.san.unstructured_name.len;
+ }
+ break;
+
+ /*
+ * Type not supported, skip item.
+ */
+ default:
+ ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ break;
+ }
+
+ cur = cur->next;
+ }
+
+ *p = '\0';
+
+ *size = n;
+ *buf = p;
+
+ return 0;
+}
+
+#define PRINT_ITEM(i) \
+ { \
+ ret = mbedtls_snprintf(p, n, "%s" i, sep); \
+ MBEDTLS_X509_SAFE_SNPRINTF; \
+ sep = ", "; \
+ }
+
+#define CERT_TYPE(type, name) \
+ if (ns_cert_type & (type)) \
+ PRINT_ITEM(name);
+
+int mbedtls_x509_info_cert_type(char **buf, size_t *size,
+ unsigned char ns_cert_type)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t n = *size;
+ char *p = *buf;
+ const char *sep = "";
+
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA");
+ CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA");
+
+ *size = n;
+ *buf = p;
+
+ return 0;
+}
+
+#define KEY_USAGE(code, name) \
+ if (key_usage & (code)) \
+ PRINT_ITEM(name);
+
+int mbedtls_x509_info_key_usage(char **buf, size_t *size,
+ unsigned int key_usage)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t n = *size;
+ char *p = *buf;
+ const char *sep = "";
+
+ KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature");
+ KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation");
+ KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment");
+ KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment");
+ KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement");
+ KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign");
+ KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign");
+ KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only");
+ KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only");
+
+ *size = n;
+ *buf = p;
+
+ return 0;
+}
+#endif /* MBEDTLS_X509_REMOVE_INFO */
+#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
#endif /* MBEDTLS_X509_USE_C */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index f77991e..5997c87 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -562,63 +562,6 @@
return 0;
}
-int mbedtls_x509_get_ns_cert_type(unsigned char **p,
- const unsigned char *end,
- unsigned char *ns_cert_type)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- mbedtls_x509_bitstring bs = { 0, 0, NULL };
-
- if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if (bs.len == 0) {
- *ns_cert_type = 0;
- return 0;
- }
-
- if (bs.len != 1) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_INVALID_LENGTH);
- }
-
- /* Get actual bitstring */
- *ns_cert_type = *bs.p;
- return 0;
-}
-
-int mbedtls_x509_get_key_usage(unsigned char **p,
- const unsigned char *end,
- unsigned int *key_usage)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t i;
- mbedtls_x509_bitstring bs = { 0, 0, NULL };
-
- if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if (bs.len == 0) {
- *key_usage = 0;
- return 0;
- }
-
- if (bs.len < 1) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_INVALID_LENGTH);
- }
-
- /* Get actual bitstring */
- *key_usage = 0;
- for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
- *key_usage |= (unsigned int) bs.p[i] << (8*i);
- }
-
- return 0;
-}
-
/*
* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
*
@@ -644,118 +587,6 @@
}
/*
- * 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 }
- *
- * NOTE: we list all types, but only use dNSName and otherName
- * of type HwModuleName, as defined in RFC 4108, at this point.
- */
-int mbedtls_x509_get_subject_alt_name(unsigned char **p,
- const unsigned char *end,
- mbedtls_x509_sequence *subject_alt_name)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len, tag_len;
- mbedtls_asn1_buf *buf;
- unsigned char tag;
- mbedtls_asn1_sequence *cur = subject_alt_name;
-
- /* Get main sequence tag */
- if ((ret = mbedtls_asn1_get_tag(p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if (*p + len != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- while (*p < end) {
- mbedtls_x509_subject_alternative_name dummy_san_buf;
- memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
-
- tag = **p;
- (*p)++;
- if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
- MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
- }
-
- /*
- * Check that the SAN is structured correctly.
- */
- ret = mbedtls_x509_parse_subject_alt_name(&(cur->buf), &dummy_san_buf);
- /*
- * In case the extension is malformed, return an error,
- * and clear the allocated sequences.
- */
- if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
- mbedtls_asn1_sequence_free(subject_alt_name->next);
- subject_alt_name->next = NULL;
- return ret;
- }
-
- /* Allocate and assign next pointer */
- if (cur->buf.p != NULL) {
- if (cur->next != NULL) {
- return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
- }
-
- cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
-
- if (cur->next == NULL) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_ALLOC_FAILED);
- }
-
- cur = cur->next;
- }
-
- buf = &(cur->buf);
- buf->tag = tag;
- buf->p = *p;
- buf->len = tag_len;
- *p += buf->len;
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if (*p != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- return 0;
-}
-
-/*
* id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
*
* anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
@@ -1713,319 +1544,7 @@
}
#endif /* MBEDTLS_FS_IO */
-/*
- * 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)
-{
- int ret = 0;
- size_t len;
- unsigned char *p = subject_alt_name->p;
- const unsigned char *end = p + subject_alt_name->len;
- mbedtls_x509_buf cur_oid;
-
- if ((subject_alt_name->tag &
- (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
- (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
- /*
- * The given subject alternative name is not of type "othername".
- */
- return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
- }
-
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_OID)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- cur_oid.tag = MBEDTLS_ASN1_OID;
- cur_oid.p = p;
- cur_oid.len = len;
-
- /*
- * Only HwModuleName is currently supported.
- */
- if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
- return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
- }
-
- if (p + len >= end) {
- mbedtls_platform_zeroize(other_name, sizeof(*other_name));
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
- p += len;
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
- 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
- other_name->value.hardware_module_name.oid.p = p;
- other_name->value.hardware_module_name.oid.len = len;
-
- if (p + len >= end) {
- mbedtls_platform_zeroize(other_name, sizeof(*other_name));
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
- p += len;
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_OCTET_STRING)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
- }
-
- other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
- other_name->value.hardware_module_name.val.p = p;
- other_name->value.hardware_module_name.val.len = len;
- p += len;
- if (p != end) {
- mbedtls_platform_zeroize(other_name,
- sizeof(*other_name));
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
- return 0;
-}
-
-int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
- mbedtls_x509_subject_alternative_name *san)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- switch (san_buf->tag &
- (MBEDTLS_ASN1_TAG_CLASS_MASK |
- MBEDTLS_ASN1_TAG_VALUE_MASK)) {
- /*
- * otherName
- */
- case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
- {
- mbedtls_x509_san_other_name other_name;
-
- ret = x509_get_other_name(san_buf, &other_name);
- if (ret != 0) {
- return ret;
- }
-
- memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
- san->type = MBEDTLS_X509_SAN_OTHER_NAME;
- memcpy(&san->san.other_name,
- &other_name, sizeof(other_name));
-
- }
- break;
-
- /*
- * dNSName
- */
- case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
- {
- memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
- san->type = MBEDTLS_X509_SAN_DNS_NAME;
-
- memcpy(&san->san.unstructured_name,
- san_buf, sizeof(*san_buf));
-
- }
- break;
-
- /*
- * Type not supported
- */
- default:
- return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
- }
- return 0;
-}
-
#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)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t i;
- size_t n = *size;
- char *p = *buf;
- const mbedtls_x509_sequence *cur = subject_alt_name;
- mbedtls_x509_subject_alternative_name san;
- int parse_ret;
-
- while (cur != NULL) {
- memset(&san, 0, sizeof(san));
- parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
- if (parse_ret != 0) {
- if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
- ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
- } else {
- ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
- }
- cur = cur->next;
- continue;
- }
-
- switch (san.type) {
- /*
- * otherName
- */
- case MBEDTLS_X509_SAN_OTHER_NAME:
- {
- mbedtls_x509_san_other_name *other_name = &san.san.other_name;
-
- ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
-
- if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
- &other_name->value.hardware_module_name.oid) != 0) {
- ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
- ret =
- mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
-
- ret = mbedtls_oid_get_numeric_string(p,
- n,
- &other_name->value.hardware_module_name.oid);
- MBEDTLS_X509_SAFE_SNPRINTF;
-
- ret =
- mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
-
- for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
- ret = mbedtls_snprintf(p,
- n,
- "%02X",
- other_name->value.hardware_module_name.val.p[i]);
- MBEDTLS_X509_SAFE_SNPRINTF;
- }
- }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
- }
- break;
-
- /*
- * dNSName
- */
- case MBEDTLS_X509_SAN_DNS_NAME:
- {
- ret = mbedtls_snprintf(p, n, "\n%s dNSName : ", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
- if (san.san.unstructured_name.len >= n) {
- *p = '\0';
- return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
- }
-
- memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
- p += san.san.unstructured_name.len;
- n -= san.san.unstructured_name.len;
- }
- break;
-
- /*
- * Type not supported, skip item.
- */
- default:
- ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
- MBEDTLS_X509_SAFE_SNPRINTF;
- break;
- }
-
- cur = cur->next;
- }
-
- *p = '\0';
-
- *size = n;
- *buf = p;
-
- return 0;
-}
-
-#define PRINT_ITEM(i) \
- { \
- ret = mbedtls_snprintf(p, n, "%s" i, sep); \
- MBEDTLS_X509_SAFE_SNPRINTF; \
- sep = ", "; \
- }
-
-#define CERT_TYPE(type, name) \
- if (ns_cert_type & (type)) \
- PRINT_ITEM(name);
-
-int mbedtls_x509_info_cert_type(char **buf, size_t *size,
- unsigned char ns_cert_type)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n = *size;
- char *p = *buf;
- const char *sep = "";
-
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA");
- CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA");
-
- *size = n;
- *buf = p;
-
- return 0;
-}
-
-#define KEY_USAGE(code, name) \
- if (key_usage & (code)) \
- PRINT_ITEM(name);
-
-int mbedtls_x509_info_key_usage(char **buf, size_t *size,
- unsigned int key_usage)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n = *size;
- char *p = *buf;
- const char *sep = "";
-
- KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature");
- KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation");
- KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment");
- KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment");
- KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement");
- KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign");
- KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign");
- KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only");
- KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only");
-
- *size = n;
- *buf = p;
-
- return 0;
-}
-
static int x509_info_ext_key_usage(char **buf, size_t *size,
const mbedtls_x509_sequence *extended_key_usage)
{