providers/implementations/exchange/kdf_exch.c: Fix kdf_derive()
authorRichard Levitte <levitte@openssl.org>
Sat, 11 Jun 2022 05:40:40 +0000 (07:40 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 15 Jun 2022 13:20:36 +0000 (15:20 +0200)
kdf_derive() calls EVP_KDF_derive(), but didn't do enough to adapt its input
buffer length arguments to fit the requirements to call EVP_KDF_derive().

Fixes #18517

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18533)

(cherry picked from commit e906eab8d863ac7bdadc671e8d0686fead88c4bf)

providers/implementations/exchange/kdf_exch.c

index 38631b45d16de3db84f7e96ccdc2b366aa65b3e8..bb18da9eba9cd9f329f5bf6b05a4e3bf3b3a94fb 100644 (file)
@@ -11,6 +11,8 @@
 #include <openssl/kdf.h>
 #include <openssl/core_dispatch.h>
 #include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
 #include <openssl/params.h>
 #include "prov/implementations.h"
 #include "prov/provider_ctx.h"
@@ -92,16 +94,33 @@ static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
                       size_t outlen)
 {
     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+    size_t kdfsize;
+    int ret;
 
     if (!ossl_prov_is_running())
         return 0;
 
+    kdfsize = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx);
+
     if (secret == NULL) {
-        *secretlen = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx);
+        *secretlen = kdfsize;
         return 1;
     }
 
-    return EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL);
+    if (kdfsize != SIZE_MAX) {
+        if (outlen < kdfsize) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        outlen = kdfsize;
+    }
+
+    ret = EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL);
+    if (ret <= 0)
+        return 0;
+
+    *secretlen = outlen;
+    return 1;
 }
 
 static void kdf_freectx(void *vpkdfctx)