]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
feat: Implement EVP_CIPHER_CTX_{set,get}_algor_params() and EVP_CIPHER_CTX_get_algor()
authorRichard Levitte <levitte@openssl.org>
Thu, 25 Jul 2024 10:34:06 +0000 (12:34 +0200)
committerRichard Levitte <levitte@openssl.org>
Tue, 27 Aug 2024 11:56:28 +0000 (13:56 +0200)
EVP_CIPHER_CTX_set_algor_params() and EVP_CIPHER_CTX_set_algor_params() can
be used instead of EVP_CIPHER_asn1_to_param() and EVP_CIPHER_param_to_asn1().

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25000)

crypto/err/openssl.txt
crypto/evp/evp_err.c
crypto/evp/evp_lib.c
include/openssl/evp.h
include/openssl/evperr.h
util/libcrypto.num

index 88830a3cd2bae52367f9c32c0ed1f03835affc36..007db19b768d26abfbc959017616ce3f9a22588a 100644 (file)
@@ -739,6 +739,8 @@ EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
 EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
 EVP_R_FINAL_ERROR:188:final error
 EVP_R_GENERATE_ERROR:214:generate error
+EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED:229:\
+       getting AlgorithmIdentifier not supported
 EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
 EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
 EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
index ffac813db2525a3c7887f5d0221d92ae4344b827..48ec7ae15e00b5e4685fc1651153a08ed6024961 100644 (file)
@@ -71,6 +71,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "expecting a siphash key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GENERATE_ERROR), "generate error"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED),
+    "getting AlgorithmIdentifier not supported"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
     "illegal scrypt parameters"},
index e80c2ba681268a71f3336bf412224e0f2dd64320..9ae4afd42a036d5f12de814cd18f5db08f8feee3 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
+#include <openssl/x509.h>
 #include <openssl/objects.h>
 #include <openssl/params.h>
 #include <openssl/core_names.h>
@@ -127,37 +128,13 @@ int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
             ret = EVP_CIPHER_set_asn1_iv(c, type);
         }
     } else if (cipher->prov != NULL) {
-        OSSL_PARAM params[3], *p = params;
-        unsigned char *der = NULL, *derp;
+        /* We cheat, there's no need for an object ID for this use */
+        X509_ALGOR alg;
 
-        /*
-         * We make two passes, the first to get the appropriate buffer size,
-         * and the second to get the actual value.
-         */
-        *p++ = OSSL_PARAM_construct_octet_string(
-                       OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS,
-                       NULL, 0);
-        *p = OSSL_PARAM_construct_end();
-
-        if (!EVP_CIPHER_CTX_get_params(c, params))
-            goto err;
-
-        /* ... but, we should get a return size too! */
-        if (OSSL_PARAM_modified(params)
-            && params[0].return_size != 0
-            && (der = OPENSSL_malloc(params[0].return_size)) != NULL) {
-            params[0].data = der;
-            params[0].data_size = params[0].return_size;
-            OSSL_PARAM_set_all_unmodified(params);
-            derp = der;
-            if (EVP_CIPHER_CTX_get_params(c, params)
-                && OSSL_PARAM_modified(params)
-                && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp,
-                                 params[0].return_size) != NULL) {
-                ret = 1;
-            }
-            OPENSSL_free(der);
-        }
+        alg.algorithm = NULL;
+        alg.parameter = type;
+
+        ret = EVP_CIPHER_CTX_get_algor_params(c, &alg);
     } else {
         ret = -2;
     }
@@ -220,20 +197,13 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
             ret = EVP_CIPHER_get_asn1_iv(c, type) >= 0 ? 1 : -1;
         }
     } else if (cipher->prov != NULL) {
-        OSSL_PARAM params[3], *p = params;
-        unsigned char *der = NULL;
-        int derl = -1;
-
-        if ((derl = i2d_ASN1_TYPE(type, &der)) >= 0) {
-            *p++ =
-                OSSL_PARAM_construct_octet_string(
-                        OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS,
-                        der, (size_t)derl);
-            *p = OSSL_PARAM_construct_end();
-            if (EVP_CIPHER_CTX_set_params(c, params))
-                ret = 1;
-            OPENSSL_free(der);
-        }
+        /* We cheat, there's no need for an object ID for this use */
+        X509_ALGOR alg;
+
+        alg.algorithm = NULL;
+        alg.parameter = type;
+
+        ret = EVP_CIPHER_CTX_set_algor_params(c, &alg);
     } else {
         ret = -2;
     }
@@ -1248,4 +1218,130 @@ EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq,
     return ret;
 }
 
+int EVP_CIPHER_CTX_set_algor_params(EVP_CIPHER_CTX *ctx, const X509_ALGOR *alg)
+{
+    int ret = -1;                /* Assume the worst */
+    unsigned char *der = NULL;
+    int derl = -1;
+
+    if ((derl = i2d_ASN1_TYPE(alg->parameter, &der)) >= 0) {
+        const char *k_old = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS_OLD;
+        const char *k_new = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS;
+        OSSL_PARAM params[3];
+
+        /*
+         * Passing the same data with both the old (deprecated) and the
+         * new AlgID parameters OSSL_PARAM key.
+         */
+        params[0] = OSSL_PARAM_construct_octet_string(k_old, der, (size_t)derl);
+        params[1] = OSSL_PARAM_construct_octet_string(k_new, der, (size_t)derl);
+        params[2] = OSSL_PARAM_construct_end();
+        ret = EVP_CIPHER_CTX_set_params(ctx, params);
+    }
+    OPENSSL_free(der);
+    return ret;
+}
+
+int EVP_CIPHER_CTX_get_algor_params(EVP_CIPHER_CTX *ctx, X509_ALGOR *alg)
+{
+    int ret = -1;                /* Assume the worst */
+    unsigned char *der = NULL;
+    size_t derl;
+    ASN1_TYPE *type = NULL;
+    int i = -1;
+    const char *k_old = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS_OLD;
+    const char *k_new = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS;
+    const char *derk;
+    OSSL_PARAM params[3];
+
+    /*
+     * We make two passes, the first to get the appropriate buffer size,
+     * and the second to get the actual value.
+     * Also, using both the old (deprecated) and the new AlgID parameters
+     * OSSL_PARAM key, and using whichever the provider responds to.
+     * Should the provider respond on both, the new key takes priority.
+     */
+    params[0] = OSSL_PARAM_construct_octet_string(k_old, NULL, 0);
+    params[1] = OSSL_PARAM_construct_octet_string(k_new, NULL, 0);
+    params[2] = OSSL_PARAM_construct_end();
+
+    if (!EVP_CIPHER_CTX_get_params(ctx, params))
+        goto err;
+
+    /* ... but, we should get a return size too! */
+    if (OSSL_PARAM_modified(&params[0]) && params[0].return_size != 0)
+        i = 0;
+    if (OSSL_PARAM_modified(&params[1]) && params[1].return_size != 0)
+        i = 1;
+
+    /*
+     * If alg->parameter is non-NULL, it will be changed by d2i_ASN1_TYPE()
+     * below.  If it is NULL, the d2i_ASN1_TYPE() call will allocate new
+     * space for it.  Either way, alg->parameter can be safely assigned
+     * with type after the d2i_ASN1_TYPE() call, with the safety that it
+     * will be ok.
+     */
+    type = alg->parameter;
+
+    derk = params[i].key;
+    derl = params[i].return_size;
+    if (i >= 0 && (der = OPENSSL_malloc(derl)) != NULL) {
+        unsigned char *derp = der;
+
+        params[i] = OSSL_PARAM_construct_octet_string(derk, der, derl);
+        if (EVP_CIPHER_CTX_get_params(ctx, params)
+            && OSSL_PARAM_modified(&params[i])
+            && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp,
+                             (int)derl) != NULL) {
+            /*
+             * Don't free alg->parameter, see comment further up.
+             * Worst case, alg->parameter gets assigned its own value.
+             */
+            alg->parameter = type;
+            ret = 1;
+        }
+    }
+ err:
+    OPENSSL_free(der);
+    return ret;
+}
+
+int EVP_CIPHER_CTX_get_algor(EVP_CIPHER_CTX *ctx, X509_ALGOR **alg)
+{
+    int ret = -1;                /* Assume the worst */
+    OSSL_PARAM params[2];
+    size_t aid_len = 0;
+    const char *k_aid = OSSL_SIGNATURE_PARAM_ALGORITHM_ID;
+
+    params[0] = OSSL_PARAM_construct_octet_string(k_aid, NULL, 0);
+    params[1] = OSSL_PARAM_construct_end();
+
+    if (EVP_CIPHER_CTX_get_params(ctx, params) <= 0)
+        goto err;
+
+    if (OSSL_PARAM_modified(&params[0]))
+        aid_len = params[0].return_size;
+    if (aid_len == 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED);
+        ret = -2;
+        goto err;
+    }
+    if (alg != NULL) {
+        unsigned char *aid = NULL;
+        const unsigned char *pp = NULL;
+
+        if ((aid = OPENSSL_malloc(aid_len)) != NULL) {
+            params[0] = OSSL_PARAM_construct_octet_string(k_aid, aid, aid_len);
+            pp = aid;
+            if (EVP_CIPHER_CTX_get_params(ctx, params)
+                && OSSL_PARAM_modified(&params[0])
+                && d2i_X509_ALGOR(alg, &pp, aid_len) != NULL)
+                ret = 1;
+        }
+        OPENSSL_free(aid);
+    }
+ err:
+    return ret;
+}
+
 #endif /* !defined(FIPS_MODULE) */
index 97ca2a08319750bfaeaaf0a4148b0bf2d6a6389e..5ca10346b245ad11d6dbd4e453ebfee7a992b1fd 100644 (file)
@@ -895,6 +895,10 @@ const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher);
 const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *ctx);
 const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *ctx);
 
+int EVP_CIPHER_CTX_set_algor_params(EVP_CIPHER_CTX *ctx, const X509_ALGOR *alg);
+int EVP_CIPHER_CTX_get_algor_params(EVP_CIPHER_CTX *ctx, X509_ALGOR *alg);
+int EVP_CIPHER_CTX_get_algor(EVP_CIPHER_CTX *ctx, X509_ALGOR **alg);
+
 const BIO_METHOD *BIO_f_md(void);
 const BIO_METHOD *BIO_f_base64(void);
 const BIO_METHOD *BIO_f_cipher(void);
index 2d879342242e50f6570d5fddfe55ed91506c97ef..0a991f735a0cb74bc4c3e5e74290ce79cb4bc816 100644 (file)
@@ -54,6 +54,7 @@
 # define EVP_R_EXPECTING_A_SIPHASH_KEY                    175
 # define EVP_R_FINAL_ERROR                                188
 # define EVP_R_GENERATE_ERROR                             214
+# define EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED  229
 # define EVP_R_GET_RAW_KEY_FAILED                         182
 # define EVP_R_ILLEGAL_SCRYPT_PARAMETERS                  171
 # define EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS             204
index 57c1e4686cd29049ca6f2b357d7b897415e65044..351df4de982f15d7473d6f18326bf5ca1477512e 100644 (file)
@@ -5726,3 +5726,6 @@ EVP_PKEY_verify_message_init            ? 3_4_0   EXIST::FUNCTION:
 EVP_PKEY_verify_message_update          ?      3_4_0   EXIST::FUNCTION:
 EVP_PKEY_verify_message_final           ?      3_4_0   EXIST::FUNCTION:
 EVP_PKEY_verify_recover_init_ex2        ?      3_4_0   EXIST::FUNCTION:
+EVP_CIPHER_CTX_set_algor_params         ?      3_4_0   EXIST::FUNCTION:
+EVP_CIPHER_CTX_get_algor_params         ?      3_4_0   EXIST::FUNCTION:
+EVP_CIPHER_CTX_get_algor                ?      3_4_0   EXIST::FUNCTION: