diff --git a/doc/api_ref/ffi.rst b/doc/api_ref/ffi.rst index f797b0d6e15..30ee56fc970 100644 --- a/doc/api_ref/ffi.rst +++ b/doc/api_ref/ffi.rst @@ -1737,13 +1737,27 @@ X.509 Certificates const char* key, size_t index, \ uint8_t out[], size_t* out_len) - Get a value from the issuer DN field. + Get a value from the issuer DN field. If the index is out of range, + :cpp:enumerator:`BOTAN_FFI_ERROR_BAD_PARAMETER` is returned for historical + reasons. + +.. cpp:function:: int botan_x509_cert_get_issuer_dn_count(botan_x509_cert_t cert, \ + const char* key, size_t* count) + + Get the number of values for a given key in the issuer DN field. .. cpp:function:: int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert, \ const char* key, size_t index, \ uint8_t out[], size_t* out_len) - Get a value from the subject DN field. + Get a value from the subject DN field. If the index is out of range, + :cpp:enumerator:`BOTAN_FFI_ERROR_BAD_PARAMETER` is returned for historical + reasons. + +.. cpp:function:: int botan_x509_cert_get_subject_dn_count(botan_x509_cert_t cert, \ + const char* key, size_t* count) + + Get the number of values for a given key in the subject DN field. .. cpp:function:: int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 0fa22566799..e70b2208a16 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -2182,15 +2182,30 @@ BOTAN_FFI_EXPORT(3, 11) int botan_x509_cert_is_ca(botan_x509_cert_t cert); */ BOTAN_FFI_EXPORT(3, 11) int botan_x509_cert_get_path_length_constraint(botan_x509_cert_t cert, size_t* path_limit); -/* TODO(Botan4) this should use char for the out param */ +/** + * Enumerates the names of the given @p key in the issuer DN. If @p index is + * out of bounds, BOTAN_FFI_ERROR_BAD_PARAMETER is returned. + * + * TODO(Botan4) use BOTAN_FFI_ERROR_OUT_OF_RANGE instead of BAD_PARAMETER + * TODO(Botan4) this should use char for the out param + */ BOTAN_FFI_EXPORT(2, 0) int botan_x509_cert_get_issuer_dn( botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len); +BOTAN_FFI_EXPORT(3, 11) int botan_x509_cert_get_issuer_dn_count(botan_x509_cert_t cert, const char* key, size_t* count); -/* TODO(Botan4) this should use char for the out param */ +/** + * Enumerates the names of the given @p key in the subject DN. If @p index is + * out of bounds, BOTAN_FFI_ERROR_BAD_PARAMETER is returned. + * + * TODO(Botan4) use BOTAN_FFI_ERROR_OUT_OF_RANGE instead of BAD_PARAMETER + * TODO(Botan4) this should use char for the out param + */ BOTAN_FFI_EXPORT(2, 0) int botan_x509_cert_get_subject_dn( botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len); +BOTAN_FFI_EXPORT(3, 11) +int botan_x509_cert_get_subject_dn_count(botan_x509_cert_t cert, const char* key, size_t* count); BOTAN_FFI_EXPORT(2, 0) int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len); diff --git a/src/lib/ffi/ffi_cert.cpp b/src/lib/ffi/ffi_cert.cpp index 7709ab04334..763f868a827 100644 --- a/src/lib/ffi/ffi_cert.cpp +++ b/src/lib/ffi/ffi_cert.cpp @@ -137,7 +137,7 @@ int botan_x509_cert_get_issuer_dn( // TODO(Botan4) change the type of out and remove this cast return write_str_output(reinterpret_cast(out), out_len, c.issuer_info(key).at(index)); } else { - return BOTAN_FFI_ERROR_BAD_PARAMETER; + return BOTAN_FFI_ERROR_BAD_PARAMETER; // TODO(Botan4): use BOTAN_FFI_ERROR_OUT_OF_RANGE } }); #else @@ -146,6 +146,22 @@ int botan_x509_cert_get_issuer_dn( #endif } +int botan_x509_cert_get_issuer_dn_count(botan_x509_cert_t cert, const char* key, size_t* count) { +#if defined(BOTAN_HAS_X509_CERTIFICATES) + return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int { + if(Botan::any_null_pointers(count)) { + return BOTAN_FFI_ERROR_NULL_POINTER; + } + + *count = c.issuer_info(key).size(); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(cert, key, count); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif +} + int botan_x509_cert_get_subject_dn( botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) { #if defined(BOTAN_HAS_X509_CERTIFICATES) @@ -155,7 +171,7 @@ int botan_x509_cert_get_subject_dn( // TODO(Botan4) change the type of out and remove this cast return write_str_output(reinterpret_cast(out), out_len, c.subject_info(key).at(index)); } else { - return BOTAN_FFI_ERROR_BAD_PARAMETER; + return BOTAN_FFI_ERROR_BAD_PARAMETER; // TODO(Botan4): use BOTAN_FFI_ERROR_OUT_OF_RANGE } }); #else @@ -164,6 +180,22 @@ int botan_x509_cert_get_subject_dn( #endif } +int botan_x509_cert_get_subject_dn_count(botan_x509_cert_t cert, const char* key, size_t* count) { +#if defined(BOTAN_HAS_X509_CERTIFICATES) + return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int { + if(Botan::any_null_pointers(count)) { + return BOTAN_FFI_ERROR_NULL_POINTER; + } + + *count = c.subject_info(key).size(); + return BOTAN_FFI_SUCCESS; + }); +#else + BOTAN_UNUSED(cert, key, count); + return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; +#endif +} + int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) { return copy_view_str(reinterpret_cast(out), out_len, botan_x509_cert_view_as_string, cert); } diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 0ad8bf206eb..9dfd50b1d24 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -968,6 +968,12 @@ class FFI_ECDSA_Certificate_Test final : public FFI_Test { } #endif + size_t rdn_count; + TEST_FFI_OK(botan_x509_cert_get_issuer_dn_count, (cert, "Name", &rdn_count)); + result.test_eq("issuer DN 'name' count", rdn_count, 1); + TEST_FFI_OK(botan_x509_cert_get_issuer_dn_count, (cert, "Organizational Unit", &rdn_count)); + result.test_eq("issuer DN 'organizational unit' count", rdn_count, 0); + size_t dn_len = 0; TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_issuer_dn, @@ -977,6 +983,11 @@ class FFI_ECDSA_Certificate_Test final : public FFI_Test { TEST_FFI_OK(botan_x509_cert_get_issuer_dn, (cert, "Name", 0, dn.data(), &dn_len)); result.test_eq("issuer dn", reinterpret_cast(dn.data()), "ISRG Root X2"); + TEST_FFI_OK(botan_x509_cert_get_subject_dn_count, (cert, "Name", &rdn_count)); + result.test_eq("subject DN 'name' count", rdn_count, 1); + TEST_FFI_OK(botan_x509_cert_get_subject_dn_count, (cert, "Organizational Unit", &rdn_count)); + result.test_eq("subject DN 'organizational unit' count", rdn_count, 0); + dn_len = 0; TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, botan_x509_cert_get_subject_dn,