Make sure we handle input NULL with length 0
[openssl.git] / providers / common / ciphers / cipher_common.c
index 34407879e60399176fde6b23cdbfb135397c405f..83c370793bf20ecbdd713a0cff9eff32bb926465 100644 (file)
@@ -12,8 +12,8 @@
  */
 
 #include "cipher_local.h"
-#include "internal/provider_ctx.h"
-#include "internal/providercommonerr.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommonerr.h"
 
 /*-
  * Generic cipher functions for OSSL_PARAM gettables and settables
@@ -68,17 +68,37 @@ int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
 CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic)
 CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
 
-static const OSSL_PARAM cipher_known_settable_ctx_params[] = {
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
-    OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL),
-    OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL),
-    OSSL_PARAM_END
-};
-const OSSL_PARAM *cipher_generic_settable_ctx_params(void)
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic)
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic)
+
+/*
+ * Variable key length cipher functions for OSSL_PARAM settables
+ */
+
+int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
-    return cipher_known_settable_ctx_params;
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    const OSSL_PARAM *p;
+
+    if (!cipher_generic_set_ctx_params(vctx, params))
+        return 0;
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL) {
+        size_t keylen;
+
+        if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ctx->keylen = keylen;
+    }
+    return 1;
 }
 
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen)
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen)
+
 /*-
  * AEAD cipher functions for OSSL_PARAM gettables and settables
  */
@@ -97,7 +117,6 @@ const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
 }
 
 static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
@@ -117,11 +136,8 @@ static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
     ctx->enc = enc ? 1 : 0;
 
     if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
-        if (ivlen != ctx->ivlen) {
-            ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+        if (!cipher_generic_initiv(ctx, iv, ivlen))
             return 0;
-        }
-        memcpy(ctx->iv, iv, ctx->ivlen);
     }
     if (key != NULL) {
         if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) {
@@ -191,6 +207,8 @@ int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
             ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
             return 0;
         }
+    }
+    if (nextblocks > 0) {
         if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
             ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
             return 0;
@@ -273,6 +291,11 @@ int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
 {
     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
 
+    if (inl == 0) {
+        *outl = 0;
+        return 1;
+    }
+
     if (outsize < inl) {
         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
         return 0;
@@ -330,8 +353,8 @@ int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
     }
     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
     if (p != NULL
-        && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)
-        && !OSSL_PARAM_set_octet_string(p, &ctx->iv, ctx->ivlen)) {
+        && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen)
+        && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) {
         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
         return 0;
     }
@@ -345,7 +368,6 @@ int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
         return 0;
     }
-
     return 1;
 }
 
@@ -374,16 +396,20 @@ int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
         }
         ctx->num = num;
     }
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL) {
-        size_t keylen;
+    return 1;
+}
 
-        if (!OSSL_PARAM_get_size_t(p, &keylen)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        ctx->keylen = keylen;
+int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv,
+                          size_t ivlen)
+{
+    if (ivlen != ctx->ivlen
+        || ivlen > sizeof(ctx->iv)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+        return 0;
     }
+    ctx->iv_set = 1;
+    memcpy(ctx->iv, iv, ivlen);
+    memcpy(ctx->oiv, iv, ivlen);
     return 1;
 }