diff --git a/ChangeLog.d/add_challenge_password.txt b/ChangeLog.d/add_challenge_password.txt new file mode 100644 index 00000000000..953fe1d8b53 --- /dev/null +++ b/ChangeLog.d/add_challenge_password.txt @@ -0,0 +1,6 @@ +API changes + * Added attributes to mbedtls_x509write_csr struct + * Added mbedtls_x509write_csr_set_attribute to set the attribute value + * Added helper function mbedtls_x509write_csr_set_challenge_password + will call mbedtls_x509write_csr_set_attribute + * Added mbedtls_x509_write_attributes to write the new attributes \ No newline at end of file diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h index fdc25ebf885..a4ae5f33586 100644 --- a/include/mbedtls/oid.h +++ b/include/mbedtls/oid.h @@ -340,6 +340,7 @@ /* * PKCS#8 OIDs */ +#define MBEDTLS_OID_PKCS9_CSR_CHAL_PW MBEDTLS_OID_PKCS9 "\x07" /**< challenge password OBJECT IDENTIFIER ::= {pkcs-9 7 } */ #define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ /* diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h index 6b104613d70..972cf2dde4d 100644 --- a/include/mbedtls/x509.h +++ b/include/mbedtls/x509.h @@ -196,6 +196,7 @@ #define MBEDTLS_X509_FORMAT_PEM 2 #define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ +#define MBEDTLS_X509_MAX_PKCS9_STR 255 /** pkcs-9-ub-pkcs9String INTEGER ::= 255 */ #ifdef __cplusplus extern "C" { diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h index c4bd7f12209..953a5236629 100644 --- a/include/mbedtls/x509_csr.h +++ b/include/mbedtls/x509_csr.h @@ -68,6 +68,7 @@ typedef struct mbedtls_x509write_csr { mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(attributes); } mbedtls_x509write_csr; @@ -323,6 +324,36 @@ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, int critical, const unsigned char *val, size_t val_len); +/** + * \brief Generic function to add to or replace an attribute in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * \param val_tag der tag of the value data + * + * \return 0 if successful, or a #PSA_ERROR_INSUFFICIENT_MEMORY + */ +int mbedtls_x509write_csr_set_attribute(mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len, const uint8_t val_tag); + +/** + * \brief Set a CSR challenge password + * + * \param ctx CSR context to use + * \param chal_pw challenge password OCTET STRING + * \param chal_pw_len length of the challenge password data + * \param printable tag as printable string (\c 1) or UTF8 string (\c 0) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_BAD_INPUT_DATA + */ +int mbedtls_x509write_csr_set_challenge_password(mbedtls_x509write_csr *ctx, + char *chal_pw, size_t chal_pw_len, + int printable); /** * \brief Free the contents of a CSR context * diff --git a/library/x509_create.c b/library/x509_create.c index 420e36b81b5..fe1f3ecb32b 100644 --- a/library/x509_create.c +++ b/library/x509_create.c @@ -401,6 +401,26 @@ int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, return 0; } +int mbedtls_x509_set_attribute(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len, const uint8_t val_tag) +{ + mbedtls_asn1_named_data *cur; + + if (val_len > (SIZE_MAX - 1)) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len, + val, val_len )) == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } + + memcpy(cur->val.p, val, val_len); + cur->val.tag = val_tag; + + return 0; +} + /* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue @@ -539,6 +559,33 @@ static int x509_write_extension(unsigned char **p, unsigned char *start, return (int) len; } +static int x509_write_attribute(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start, + ext->val.tag, + (const char *)ext->val.p, + ext->val.len)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, (const char *) ext->oid.p, + ext->oid.len)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} + /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, @@ -564,4 +611,18 @@ int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, return (int) len; } +int mbedtls_x509_write_attributes(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur_att = first; + + while (cur_att != NULL) { + MBEDTLS_ASN1_CHK_ADD(len, x509_write_attribute(p, start, cur_att)); + cur_att = cur_att->next; + } + + return (int) len; +} #endif /* MBEDTLS_X509_CREATE_C */ diff --git a/library/x509_internal.h b/library/x509_internal.h index 8a2d2ed0074..ad8bdd03d0c 100644 --- a/library/x509_internal.h +++ b/library/x509_internal.h @@ -51,8 +51,12 @@ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, 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_set_attribute(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len, const uint8_t val_tag); int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first); +int mbedtls_x509_write_attributes(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, diff --git a/library/x509write_csr.c b/library/x509write_csr.c index 75bd8f044e4..c13282d2137 100644 --- a/library/x509write_csr.c +++ b/library/x509write_csr.c @@ -49,6 +49,7 @@ void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->extensions); + mbedtls_asn1_free_named_data_list(&ctx->attributes); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); } @@ -78,6 +79,13 @@ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, critical, val, val_len); } +int mbedtls_x509write_csr_set_attribute(mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len, const uint8_t val_tag) +{ + return mbedtls_x509_set_attribute(&ctx->attributes, oid, oid_len, + val, val_len, val_tag); +} int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, const mbedtls_x509_san_list *san_list) @@ -132,6 +140,26 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, return 0; } +int mbedtls_x509write_csr_set_challenge_password(mbedtls_x509write_csr *ctx, + char *chal_pw, + size_t chal_pw_len, + int printable) +{ + if (chal_pw_len == 0 || chal_pw == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + /* pkcs-9-ub-challengePassword INTEGER ::= pkcs-9-ub-pkcs9String */ + if (chal_pw_len > MBEDTLS_X509_MAX_PKCS9_STR) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + mbedtls_x509write_csr_set_attribute(ctx, + MBEDTLS_OID_PKCS9_CSR_CHAL_PW, MBEDTLS_OID_SIZE ( MBEDTLS_OID_PKCS9_CSR_CHAL_PW ), + (unsigned char *)chal_pw, chal_pw_len, + (printable ? MBEDTLS_ASN1_PRINTABLE_STRING : MBEDTLS_ASN1_UTF8_STRING )); + return 0; +} static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, @@ -183,6 +211,9 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); } + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_attributes(&c, buf, + ctx->attributes)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 56af0ce8a87..e38f364d50d 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -1,30 +1,30 @@ Certificate Request check Server1 SHA1 depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha1":MBEDTLS_MD_SHA1:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha1":MBEDTLS_MD_SHA1:0:0:0:0:0:0:0 Certificate Request check Server1 SHA224 depends_on:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha224":MBEDTLS_MD_SHA224:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha224":MBEDTLS_MD_SHA224:0:0:0:0:0:0:0 Certificate Request check Server1 SHA256 depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha256":MBEDTLS_MD_SHA256:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha256":MBEDTLS_MD_SHA256:0:0:0:0:0:0:0 Certificate Request check Server1 SHA384 depends_on:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha384":MBEDTLS_MD_SHA384:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha384":MBEDTLS_MD_SHA384:0:0:0:0:0:0:0 Certificate Request check Server1 SHA512 depends_on:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha512":MBEDTLS_MD_SHA512:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha512":MBEDTLS_MD_SHA512:0:0:0:0:0:0:0 Certificate Request check Server1 MD5 depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.md5":MBEDTLS_MD_MD5:0:0:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.md5":MBEDTLS_MD_MD5:0:0:0:0:0:0:0 Certificate Request check Server1 key_usage depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.key_usage":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.key_usage":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0:0:0 Certificate Request check opaque Server1 key_usage depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 @@ -32,27 +32,31 @@ x509_csr_check_opaque:"../framework/data_files/server1.key":MBEDTLS_MD_SHA1:MBED Certificate Request check Server1 key_usage empty depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.key_usage_empty":MBEDTLS_MD_SHA1:0:1:0:0:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.key_usage_empty":MBEDTLS_MD_SHA1:0:1:0:0:0:0:0 Certificate Request check Server1 ns_cert_type depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.cert_type":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.cert_type":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:0:0 Certificate Request check Server1 ns_cert_type empty depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.cert_type_empty":MBEDTLS_MD_SHA1:0:0:0:1:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.cert_type_empty":MBEDTLS_MD_SHA1:0:0:0:1:0:0:0 Certificate Request check Server1 key_usage + ns_cert_type depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.ku-ct":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.ku-ct":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:0:0 Certificate Request check Server5 ECDSA, key_usage depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_HAVE_SECP256R1 -x509_csr_check:"../framework/data_files/server5.key":"../framework/data_files/server5.req.ku.sha1":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION:1:0:0:0 +x509_csr_check:"../framework/data_files/server5.key":"../framework/data_files/server5.req.ku.sha1":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION:1:0:0:0:0:0 Certificate Request check Server1, set_extension depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 -x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha256.ext":MBEDTLS_MD_SHA256:0:0:0:0:1 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.sha256.ext":MBEDTLS_MD_SHA256:0:0:0:0:1:0:0 + +Certificate Request check Server1, set_challenge_password +depends_on:PSA_WANT_ALG_SHA_256:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 +x509_csr_check:"../framework/data_files/server1.key":"../framework/data_files/server1.req.pw":MBEDTLS_MD_SHA256:0:0:0:0:0:1:abcde Certificate Request check opaque Server5 ECDSA, key_usage depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP256R1 diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index a22c486def4..b225885ed24 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -146,7 +146,8 @@ static int csr_set_extended_key_usage(mbedtls_x509write_csr *ctx, /* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C:MBEDTLS_X509_CSR_WRITE_C */ void x509_csr_check(char *key_file, char *cert_req_check_file, int md_type, int key_usage, int set_key_usage, int cert_type, - int set_cert_type, int set_extension) + int set_cert_type, int set_extension, + int chal_pw, char *set_chal_pw ) { mbedtls_pk_context key; mbedtls_x509write_csr req; @@ -221,6 +222,9 @@ void x509_csr_check(char *key_file, char *cert_req_check_file, int md_type, if (set_cert_type != 0) { TEST_ASSERT(mbedtls_x509write_csr_set_ns_cert_type(&req, cert_type) == 0); } + if (chal_pw != 0) { + TEST_ASSERT(mbedtls_x509write_csr_set_challenge_password(&req, set_chal_pw, strlen(set_chal_pw), 0 ) == 0); + } if (set_extension != 0) { TEST_ASSERT(csr_set_extended_key_usage(&req, MBEDTLS_OID_SERVER_AUTH, MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) == 0);