]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl: add openssl_digest_size()
authorDan Streetman <ddstreet@ieee.org>
Wed, 5 Jul 2023 16:59:47 +0000 (12:59 -0400)
committerDan Streetman <ddstreet@ieee.org>
Thu, 28 Sep 2023 20:44:13 +0000 (16:44 -0400)
Add function to get digest hash size for provided digest name.

src/shared/openssl-util.c
src/shared/openssl-util.h
src/test/test-openssl.c

index 31a1a55df7963b7b9ac9f8b93e8e84195d4e0082..ab6ad26dcab2550f9771174c66be22710fdef510 100644 (file)
@@ -87,6 +87,37 @@ int openssl_hash(const EVP_MD *alg,
         return 0;
 }
 
+/* Returns the number of bytes generated by the specified digest algorithm. This can be used only for
+ * fixed-size algorithms, e.g. md5, sha1, sha256, etc. Do not use this for variable-sized digest algorithms,
+ * e.g. shake128. Returns 0 on success, -EOPNOTSUPP if the algorithm is not supported, or < 0 for any other
+ * error. */
+int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size) {
+        assert(digest_alg);
+        assert(ret_digest_size);
+
+#if OPENSSL_VERSION_MAJOR >= 3
+        _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
+#else
+        const EVP_MD *md = EVP_get_digestbyname(digest_alg);
+#endif
+        if (!md)
+                return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "Digest algorithm '%s' not supported.", digest_alg);
+
+        size_t digest_size;
+#if OPENSSL_VERSION_MAJOR >= 3
+        digest_size = EVP_MD_get_size(md);
+#else
+        digest_size = EVP_MD_size(md);
+#endif
+        if (digest_size == 0)
+                return log_openssl_errors("Failed to get Digest size");
+
+        *ret_digest_size = digest_size;
+
+        return 0;
+}
+
 int rsa_encrypt_bytes(
                 EVP_PKEY *pkey,
                 const void *decrypted_key,
index 4ea82b5f27c50283716e21e81668df107edfc958..742c2230b7e0617a50f569d5d119a2cacb1cee42 100644 (file)
@@ -39,6 +39,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
 #if OPENSSL_VERSION_MAJOR >= 3
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM*, OSSL_PARAM_free, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM_BLD*, OSSL_PARAM_BLD_free, NULL);
 #else
@@ -57,6 +58,8 @@ int openssl_pkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret);
 
 int openssl_hash(const EVP_MD *alg, const void *msg, size_t msg_len, uint8_t *ret_hash, size_t *ret_hash_len);
 
+int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size);
+
 int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size);
 
 int rsa_pkey_to_suitable_key_size(EVP_PKEY *pkey, size_t *ret_suitable_key_size);
index c46ecdcda8b66eb357a7aefc3d54b664bb4bf7fa..ae12f0768ad5cbc4d57394cb863a1b44220393be 100644 (file)
@@ -102,4 +102,55 @@ TEST(invalid) {
         assert_se(pkey == NULL);
 }
 
+static const struct {
+        const char *alg;
+        size_t size;
+} digest_size_table[] = {
+        /* SHA1 "family" */
+        { "sha1",     20, },
+#if OPENSSL_VERSION_MAJOR >= 3
+        { "sha-1",    20, },
+#endif
+        /* SHA2 family */
+        { "sha224",   28, },
+        { "sha256",   32, },
+        { "sha384",   48, },
+        { "sha512",   64, },
+#if OPENSSL_VERSION_MAJOR >= 3
+        { "sha-224",  28, },
+        { "sha2-224", 28, },
+        { "sha-256",  32, },
+        { "sha2-256", 32, },
+        { "sha-384",  48, },
+        { "sha2-384", 48, },
+        { "sha-512",  64, },
+        { "sha2-512", 64, },
+#endif
+        /* SHA3 family */
+        { "sha3-224", 28, },
+        { "sha3-256", 32, },
+        { "sha3-384", 48, },
+        { "sha3-512", 64, },
+        /* SM3 family */
+        { "sm3",      32, },
+        /* MD5 family */
+        { "md5",      16, },
+};
+
+TEST(digest_size) {
+        size_t size;
+
+        FOREACH_ARRAY(t, digest_size_table, ELEMENTSOF(digest_size_table)) {
+                assert(openssl_digest_size(t->alg, &size) >= 0);
+                assert_se(size == t->size);
+
+                _cleanup_free_ char *uppercase_alg = strdup(t->alg);
+                assert_se(uppercase_alg);
+                assert_se(openssl_digest_size(ascii_strupper(uppercase_alg), &size) >= 0);
+                assert_se(size == t->size);
+        }
+
+        assert_se(openssl_digest_size("invalid.alg", &size) == -EOPNOTSUPP);
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);