EVP: Only use the engine when one is defined, in pkey_mac_ctrl()
[openssl.git] / crypto / evp / pkey_mac.c
index 07421183eabb573062b136174f77a944dc8ec161..3503aac6d306855e22ca7f610da93c67b8cd02d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -13,8 +13,8 @@
 #include <openssl/engine.h>
 #include <openssl/params.h>
 #include <openssl/core_names.h>
-#include "internal/evp_int.h"
-#include "evp_locl.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
 
 /* MAC PKEY context structure */
 
@@ -51,17 +51,31 @@ static int pkey_mac_init(EVP_PKEY_CTX *ctx)
     MAC_PKEY_CTX *hctx;
     /* We're being smart and using the same base NIDs for PKEY and for MAC */
     int nid = ctx->pmeth->pkey_id;
-    EVP_MAC *mac = EVP_MAC_fetch(NULL, OBJ_nid2sn(nid), NULL);
+    EVP_MAC *mac;
+
+    ERR_set_mark();
+    mac = EVP_MAC_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propquery);
+    ERR_pop_to_mark();
+
+    /*
+     * mac == NULL may actually be ok in some situations. In an
+     * EVP_PKEY_new_mac_key() call a temporary EVP_PKEY_CTX is created with
+     * default libctx. We don't actually need the underlying MAC to be present
+     * to successfully set the key in that case. The resulting EVP_PKEY could
+     * then be used in some other libctx where the MAC *is* present
+     */
 
     if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
         EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
-    hctx->ctx = EVP_MAC_CTX_new(mac);
-    if (hctx->ctx == NULL) {
-        OPENSSL_free(hctx);
-        return 0;
+    if (mac != NULL) {
+        hctx->ctx = EVP_MAC_CTX_new(mac);
+        if (hctx->ctx == NULL) {
+            OPENSSL_free(hctx);
+            return 0;
+        }
     }
 
     if (nid == EVP_PKEY_CMAC) {
@@ -83,6 +97,13 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
     MAC_PKEY_CTX *sctx, *dctx;
 
     sctx = EVP_PKEY_CTX_get_data(src);
+
+    if (sctx->ctx == NULL) {
+        /* This actually means the fetch failed during the init call */
+        EVPerr(0, EVP_R_FETCH_FAILED);
+        return 0;
+    }
+
     if (sctx->ctx->data == NULL)
         return 0;
 
@@ -142,7 +163,7 @@ static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
     MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx);
 
     if (hctx != NULL) {
-        EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
+        EVP_MAC *mac = hctx->ctx != NULL ? EVP_MAC_CTX_mac(hctx->ctx) : NULL;
 
         switch (hctx->type) {
         case MAC_TYPE_RAW:
@@ -177,8 +198,15 @@ static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         break;
     case MAC_TYPE_MAC:
         {
-            EVP_MAC_CTX *cmkey = EVP_MAC_CTX_dup(hctx->ctx);
+            EVP_MAC_CTX *cmkey;
+
+            if (hctx->ctx == NULL) {
+                /* This actually means the fetch failed during the init call */
+                EVPerr(0, EVP_R_FETCH_FAILED);
+                return 0;
+            }
 
+            cmkey = EVP_MAC_CTX_dup(hctx->ctx);
             if (cmkey == NULL)
                 return 0;
             if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx)))
@@ -220,9 +248,15 @@ static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
         hctx->type == MAC_TYPE_RAW
         && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
 
+    if (hctx->ctx == NULL) {
+        /* This actually means the fetch failed during the init call */
+        EVPerr(0, EVP_R_FETCH_FAILED);
+        return 0;
+    }
+
     if (set_key) {
-        if (strcmp(OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))),
-                   EVP_MAC_name(EVP_MAC_CTX_mac(hctx->ctx))) != 0)
+        if (!EVP_MAC_is_a(EVP_MAC_CTX_mac(hctx->ctx),
+                          OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)))))
             return 0;
         key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
         if (key == NULL)
@@ -274,18 +308,28 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                 OSSL_PARAM params[3];
                 size_t params_n = 0;
                 char *ciphname = (char *)OBJ_nid2sn(EVP_CIPHER_nid(p2));
-                char *engineid = (char *)ENGINE_get_id(ctx->engine);
 
+#ifndef OPENSSL_NO_ENGINE
+                if (ctx->engine != NULL) {
+                    char *engid = (char *)ENGINE_get_id(ctx->engine);
+
+                    params[params_n++] =
+                        OSSL_PARAM_construct_utf8_string("engine", engid, 0);
+                }
+#endif
                 params[params_n++] =
-                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
-                                                     engineid,
-                                                     strlen(engineid) + 1);
-                params[params_n++] =
-                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
-                                                     ciphname,
-                                                     strlen(ciphname) + 1);
+                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
+                                                     ciphname, 0);
                 params[params_n] = OSSL_PARAM_construct_end();
 
+                if (hctx->ctx == NULL) {
+                    /*
+                     * This actually means the fetch failed during the init call
+                     */
+                    EVPerr(0, EVP_R_FETCH_FAILED);
+                    return 0;
+                }
+
                 if (!EVP_MAC_CTX_set_params(hctx->ctx, params)
                     || !EVP_MAC_init(hctx->ctx))
                     return 0;
@@ -307,8 +351,7 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 
                 if (ctx->pkey == NULL)
                     return 0;
-                new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey
-                                              ->pkey.ptr);
+                new_mac_ctx = EVP_MAC_CTX_dup(ctx->pkey->pkey.ptr);
                 if (new_mac_ctx == NULL)
                     return 0;
                 EVP_MAC_CTX_free(hctx->ctx);
@@ -336,13 +379,21 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
              */
 
             params[0] =
-                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, &size);
+                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size);
+
+            if (hctx->ctx == NULL) {
+                /*
+                 * This actually means the fetch failed during the init call
+                 */
+                EVPerr(0, EVP_R_FETCH_FAILED);
+                return 0;
+            }
 
             if (!EVP_MAC_CTX_set_params(hctx->ctx, params))
                 return 0;
 
             params[0] =
-                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, &verify);
+                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &verify);
 
             if (!EVP_MAC_CTX_get_params(hctx->ctx, params))
                 return 0;
@@ -374,6 +425,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                                                       p2, p1);
                 params[params_n] = OSSL_PARAM_construct_end();
 
+                if (hctx->ctx == NULL) {
+                    /*
+                     * This actually means the fetch failed during the init call
+                     */
+                    EVPerr(0, EVP_R_FETCH_FAILED);
+                    return 0;
+                }
+
                 return EVP_MAC_CTX_set_params(hctx->ctx, params);
             }
             break;
@@ -386,6 +445,12 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
     case EVP_PKEY_CTRL_DIGESTINIT:
         switch (hctx->type) {
         case MAC_TYPE_RAW:
+            if (hctx->ctx == NULL) {
+                /* This actually means the fetch failed during the init call */
+                EVPerr(0, EVP_R_FETCH_FAILED);
+                return 0;
+            }
+
             /* Ensure that we have attached the implementation */
             if (!EVP_MAC_init(hctx->ctx))
                 return 0;
@@ -396,20 +461,18 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                 size_t params_n = 0;
                 char *mdname =
                     (char *)OBJ_nid2sn(EVP_MD_nid(hctx->raw_data.md));
-                char *engineid = ctx->engine == NULL
-                    ? NULL : (char *)ENGINE_get_id(ctx->engine);
 
-                if (engineid != NULL) {
-                    size_t engineid_l = strlen(engineid) + 1;
+#ifndef OPENSSL_NO_ENGINE
+                if (ctx->engine != NULL) {
+                    char *engid = (char *)ENGINE_get_id(ctx->engine);
+
                     params[params_n++] =
-                        OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
-                                                         engineid,
-                                                         engineid_l);
+                        OSSL_PARAM_construct_utf8_string("engine", engid, 0);
                 }
+#endif
                 params[params_n++] =
-                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
-                                                     mdname,
-                                                     strlen(mdname) + 1);
+                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+                                                     mdname, 0);
                 params[params_n++] =
                     OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
                                                       key->data, key->length);
@@ -434,24 +497,50 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 }
 
 static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
-                              const char *type, const char *value)
+                             const char *type, const char *value)
 {
     MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
-    const EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
+    const EVP_MAC *mac;
     OSSL_PARAM params[2];
     int ok = 0;
 
+    if (hctx == NULL) {
+        EVPerr(0, EVP_R_NULL_MAC_PKEY_CTX);
+        return 0;
+    }
+    if (hctx->ctx == NULL) {
+        /* This actually means the fetch failed during the init call */
+        EVPerr(0, EVP_R_FETCH_FAILED);
+        return 0;
+    }
+    mac = EVP_MAC_CTX_mac(hctx->ctx);
+
+    /*
+     * Translation of some control names that are equivalent to a single
+     * parameter name.
+     *
+     * "md" and "digest" are the same thing, we use the single "digest"
+     *
+     * "digestsize" was a setting control in siphash, but naming wise,
+     * it's really the same as "size".
+     */
+    if (strcmp(type, "md") == 0)
+        type = OSSL_MAC_PARAM_DIGEST;
+    else if (strcmp(type, "digestsize") == 0)
+        type = OSSL_MAC_PARAM_SIZE;
+
     if (!OSSL_PARAM_allocate_from_text(&params[0],
-                                       EVP_MAC_CTX_settable_params(mac),
-                                       type, value, strlen(value) + 1))
+                                       EVP_MAC_settable_ctx_params(mac),
+                                       type, value, strlen(value) + 1, NULL))
         return 0;
     params[1] = OSSL_PARAM_construct_end();
+
     ok = EVP_MAC_CTX_set_params(hctx->ctx, params);
     OPENSSL_free(params[0].data);
     return ok;
 }
 
-const EVP_PKEY_METHOD cmac_pkey_meth = {
+static const EVP_PKEY_METHOD cmac_pkey_meth = {
     EVP_PKEY_CMAC,
     EVP_PKEY_FLAG_SIGCTX_CUSTOM,
     pkey_mac_init,
@@ -484,7 +573,12 @@ const EVP_PKEY_METHOD cmac_pkey_meth = {
     pkey_mac_ctrl_str
 };
 
-const EVP_PKEY_METHOD hmac_pkey_meth = {
+const EVP_PKEY_METHOD *cmac_pkey_method(void)
+{
+    return &cmac_pkey_meth;
+}
+
+static const EVP_PKEY_METHOD hmac_pkey_meth = {
     EVP_PKEY_HMAC,
     0,
     pkey_mac_init,
@@ -517,7 +611,12 @@ const EVP_PKEY_METHOD hmac_pkey_meth = {
     pkey_mac_ctrl_str
 };
 
-const EVP_PKEY_METHOD siphash_pkey_meth = {
+const EVP_PKEY_METHOD *hmac_pkey_method(void)
+{
+    return &hmac_pkey_meth;
+}
+
+static const EVP_PKEY_METHOD siphash_pkey_meth = {
     EVP_PKEY_SIPHASH,
     EVP_PKEY_FLAG_SIGCTX_CUSTOM,
     pkey_mac_init,
@@ -550,7 +649,12 @@ const EVP_PKEY_METHOD siphash_pkey_meth = {
     pkey_mac_ctrl_str
 };
 
-const EVP_PKEY_METHOD poly1305_pkey_meth = {
+const EVP_PKEY_METHOD *siphash_pkey_method(void)
+{
+    return &siphash_pkey_meth;
+}
+
+static const EVP_PKEY_METHOD poly1305_pkey_meth = {
     EVP_PKEY_POLY1305,
     EVP_PKEY_FLAG_SIGCTX_CUSTOM,
     pkey_mac_init,
@@ -582,3 +686,8 @@ const EVP_PKEY_METHOD poly1305_pkey_meth = {
     pkey_mac_ctrl,
     pkey_mac_ctrl_str
 };
+
+const EVP_PKEY_METHOD *poly1305_pkey_method(void)
+{
+    return &poly1305_pkey_meth;
+}