ENCODER: Refactor the OSSL_ENCODER API to be more like OSSL_DECODER
[openssl.git] / crypto / encode_decode / encoder_meth.c
index 62342f511a79ebd220c05252201fbd87072afc07..93929b5360d52266285e48a349db65ae40437671 100644 (file)
@@ -180,6 +180,16 @@ static void *encoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
                 encoder->freectx =
                     OSSL_FUNC_encoder_freectx(fns);
             break;
+        case OSSL_FUNC_ENCODER_GET_PARAMS:
+            if (encoder->get_params == NULL)
+                encoder->get_params =
+                    OSSL_FUNC_encoder_get_params(fns);
+            break;
+        case OSSL_FUNC_ENCODER_GETTABLE_PARAMS:
+            if (encoder->gettable_params == NULL)
+                encoder->gettable_params =
+                    OSSL_FUNC_encoder_gettable_params(fns);
+            break;
         case OSSL_FUNC_ENCODER_SET_CTX_PARAMS:
             if (encoder->set_ctx_params == NULL)
                 encoder->set_ctx_params =
@@ -190,26 +200,34 @@ static void *encoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
                 encoder->settable_ctx_params =
                     OSSL_FUNC_encoder_settable_ctx_params(fns);
             break;
-        case OSSL_FUNC_ENCODER_ENCODE_DATA:
-            if (encoder->encode_data == NULL)
-                encoder->encode_data =
-                    OSSL_FUNC_encoder_encode_data(fns);
+        case OSSL_FUNC_ENCODER_ENCODE:
+            if (encoder->encode == NULL)
+                encoder->encode = OSSL_FUNC_encoder_encode(fns);
+            break;
+        case OSSL_FUNC_ENCODER_IMPORT_OBJECT:
+            if (encoder->import_object == NULL)
+                encoder->import_object =
+                    OSSL_FUNC_encoder_import_object(fns);
             break;
-        case OSSL_FUNC_ENCODER_ENCODE_OBJECT:
-            if (encoder->encode_object == NULL)
-                encoder->encode_object =
-                    OSSL_FUNC_encoder_encode_object(fns);
+        case OSSL_FUNC_ENCODER_FREE_OBJECT:
+            if (encoder->free_object == NULL)
+                encoder->free_object =
+                    OSSL_FUNC_encoder_free_object(fns);
             break;
         }
     }
     /*
      * Try to check that the method is sensible.
      * If you have a constructor, you must have a destructor and vice versa.
-     * You must have at least one of the encoding driver functions.
+     * You must have the encoding driver functions.
      */
     if (!((encoder->newctx == NULL && encoder->freectx == NULL)
-          || (encoder->newctx != NULL && encoder->freectx != NULL))
-        || (encoder->encode_data == NULL && encoder->encode_object == NULL)) {
+          || (encoder->newctx != NULL && encoder->freectx != NULL)
+          || (encoder->import_object != NULL && encoder->free_object != NULL)
+          || (encoder->import_object == NULL && encoder->free_object == NULL))
+        || encoder->encode == NULL
+        || encoder->gettable_params == NULL
+        || encoder->get_params == NULL) {
         OSSL_ENCODER_free(encoder);
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
@@ -440,6 +458,24 @@ void OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
     }
 }
 
+const OSSL_PARAM *
+OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder)
+{
+    if (encoder != NULL && encoder->gettable_params != NULL) {
+        void *provctx = ossl_provider_ctx(OSSL_ENCODER_provider(encoder));
+
+        return encoder->gettable_params(provctx);
+    }
+    return NULL;
+}
+
+int OSSL_ENCODER_get_params(OSSL_ENCODER *encoder, OSSL_PARAM params[])
+{
+    if (encoder != NULL && encoder->get_params != NULL)
+        return encoder->get_params(params);
+    return 0;
+}
+
 const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder)
 {
     if (encoder != NULL && encoder->settable_ctx_params != NULL) {
@@ -454,69 +490,51 @@ const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder)
  * Encoder context support
  */
 
-/*
- * |encoder| value NULL is valid, and signifies that there is no encoder.
- * This is useful to provide fallback mechanisms.
- *  Functions that want to verify if there is a encoder can do so with
- * OSSL_ENCODER_CTX_get_encoder()
- */
-OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(OSSL_ENCODER *encoder)
+OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(void)
 {
     OSSL_ENCODER_CTX *ctx;
 
-    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    ctx->encoder = encoder;
-    if (encoder != NULL && encoder->newctx != NULL) {
-        const OSSL_PROVIDER *prov = OSSL_ENCODER_provider(encoder);
-        void *provctx = ossl_provider_ctx(prov);
-
-        if (OSSL_ENCODER_up_ref(encoder)) {
-            ctx->encoderctx = encoder->newctx(provctx);
-        } else {
-            OSSL_ENCODER_free(encoder);
-            OPENSSL_free(ctx);
-            ctx = NULL;
-        }
-    }
 
     return ctx;
 }
 
-const OSSL_ENCODER *
-OSSL_ENCODER_CTX_get_encoder(OSSL_ENCODER_CTX *ctx)
+int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
+                                const OSSL_PARAM params[])
 {
+    size_t i;
+    size_t l;
+
     if (!ossl_assert(ctx != NULL)) {
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
 
-    return ctx->encoder;
-}
+    if (ctx->encoder_insts == NULL)
+        return 1;
 
+    l = OSSL_ENCODER_CTX_get_num_encoders(ctx);
+    for (i = 0; i < l; i++) {
+        OSSL_ENCODER_INSTANCE *encoder_inst =
+            sk_OSSL_ENCODER_INSTANCE_value(ctx->encoder_insts, i);
+        OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
+        void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst);
 
-int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
-                                const OSSL_PARAM params[])
-{
-    if (!ossl_assert(ctx != NULL)) {
-        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
+        if (encoderctx == NULL || encoder->set_ctx_params == NULL)
+            continue;
+        if (!encoder->set_ctx_params(encoderctx, params))
+            return 0;
     }
-
-    if (ctx->encoder != NULL && ctx->encoder->set_ctx_params != NULL)
-        return ctx->encoder->set_ctx_params(ctx->encoderctx, params);
-    return 0;
+    return 1;
 }
 
 void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx)
 {
     if (ctx != NULL) {
-        if (ctx->encoder != NULL && ctx->encoder->freectx != NULL)
-            ctx->encoder->freectx(ctx->encoderctx);
-        OSSL_ENCODER_free(ctx->encoder);
+        sk_OSSL_ENCODER_INSTANCE_pop_free(ctx->encoder_insts,
+                                          ossl_encoder_instance_free);
+        OPENSSL_free(ctx->construct_data);
         ossl_pw_clear_passphrase_data(&ctx->pwdata);
         OPENSSL_free(ctx);
     }