Replaced '{ 0, NULL }' with OSSL_DISPATCH_END in OSSL_DISPATCH arrays
[openssl.git] / providers / implementations / encode_decode / decode_pvk2key.c
index 3f2c80abdc8dc5aeb7bed7245eda7219da7ceedb..6624773d9bf0370bc88bbb9cc338d91b44a1df0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2022 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
@@ -20,6 +20,7 @@
 #include <openssl/core_object.h>
 #include <openssl/crypto.h>
 #include <openssl/params.h>
+#include <openssl/err.h>
 #include <openssl/pem.h>         /* For public PVK functions */
 #include <openssl/x509.h>
 #include "internal/passphrase.h"
@@ -32,7 +33,8 @@
 struct pvk2key_ctx_st;            /* Forward declaration */
 typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);
 typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);
-typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u);
+typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,
+                                   OSSL_LIB_CTX *libctx, const char *propq);
 typedef void free_key_fn(void *);
 struct keytype_desc_st {
     int type;                 /* EVP key type */
@@ -45,8 +47,6 @@ struct keytype_desc_st {
 };
 
 static OSSL_FUNC_decoder_freectx_fn pvk2key_freectx;
-static OSSL_FUNC_decoder_gettable_params_fn pvk2key_gettable_params;
-static OSSL_FUNC_decoder_get_params_fn pvk2key_get_params;
 static OSSL_FUNC_decoder_decode_fn pvk2key_decode;
 static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;
 
@@ -56,6 +56,8 @@ static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;
 struct pvk2key_ctx_st {
     PROV_CTX *provctx;
     const struct keytype_desc_st *desc;
+    /* The selection that is passed to der2key_decode() */
+    int selection;
 };
 
 static struct pvk2key_ctx_st *
@@ -77,27 +79,6 @@ static void pvk2key_freectx(void *vctx)
     OPENSSL_free(ctx);
 }
 
-static const OSSL_PARAM *pvk2key_gettable_params(ossl_unused void *provctx)
-{
-    static const OSSL_PARAM gettables[] = {
-        { OSSL_DECODER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
-        OSSL_PARAM_END,
-    };
-
-    return gettables;
-}
-
-static int pvk2key_get_params(OSSL_PARAM params[])
-{
-    OSSL_PARAM *p;
-
-    p = OSSL_PARAM_locate(params, OSSL_DECODER_PARAM_INPUT_TYPE);
-    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "PVK"))
-        return 0;
-
-    return 1;
-}
-
 static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                          OSSL_CALLBACK *data_cb, void *data_cbarg,
                          OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
@@ -107,15 +88,40 @@ static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
     void *key = NULL;
     int ok = 0;
 
+    if (in == NULL)
+        return 0;
+
+    ctx->selection = selection;
+
     if ((selection == 0
          || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
         && ctx->desc->read_private_key != NULL) {
         struct ossl_passphrase_data_st pwdata;
+        int err, lib, reason;
 
         memset(&pwdata, 0, sizeof(pwdata));
         if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
             goto end;
-        key = ctx->desc->read_private_key(in, ossl_pw_pem_password, &pwdata);
+
+        key = ctx->desc->read_private_key(in, ossl_pw_pvk_password, &pwdata,
+                                          PROV_LIBCTX_OF(ctx->provctx), NULL);
+
+        /*
+         * Because the PVK API doesn't have a separate decrypt call, we need
+         * to check the error queue for certain well known errors that are
+         * considered fatal and which we pass through, while the rest gets
+         * thrown away.
+         */
+        err = ERR_peek_last_error();
+        lib = ERR_GET_LIB(err);
+        reason = ERR_GET_REASON(err);
+        if (lib == ERR_LIB_PEM
+            && (reason == PEM_R_BAD_PASSWORD_READ
+                || reason == PEM_R_BAD_DECRYPT)) {
+            ERR_clear_last_mark();
+            goto end;
+        }
+
         if (selection != 0 && key == NULL)
             goto next;
     }
@@ -124,6 +130,12 @@ static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
         ctx->desc->adjust_key(key, ctx);
 
  next:
+    /*
+     * Indicated that we successfully decoded something, or not at all.
+     * Ending up "empty handed" is not an error.
+     */
+    ok = 1;
+
     /*
      * We free resources here so it's not held up during the callback, because
      * we know the process is recursive and the allocated chunks of memory
@@ -170,21 +182,20 @@ static int pvk2key_export_object(void *vctx,
         /* The contents of the reference is the address to our object */
         keydata = *(void **)reference;
 
-        return export(keydata, OSSL_KEYMGMT_SELECT_ALL,
-                      export_cb, export_cbarg);
+        return export(keydata, ctx->selection, export_cb, export_cbarg);
     }
     return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-#define dsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio
+#define dsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex
 #define dsa_adjust              NULL
 #define dsa_free                (void (*)(void *))DSA_free
 
 /* ---------------------------------------------------------------------- */
 
-#define rsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio
+#define rsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex
 
 static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
 {
@@ -215,15 +226,11 @@ static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
           (void (*)(void))pvk2##keytype##_newctx },                     \
         { OSSL_FUNC_DECODER_FREECTX,                                    \
           (void (*)(void))pvk2key_freectx },                            \
-        { OSSL_FUNC_DECODER_GETTABLE_PARAMS,                            \
-          (void (*)(void))pvk2key_gettable_params },                    \
-        { OSSL_FUNC_DECODER_GET_PARAMS,                                 \
-          (void (*)(void))pvk2key_get_params },                         \
         { OSSL_FUNC_DECODER_DECODE,                                     \
           (void (*)(void))pvk2key_decode },                             \
         { OSSL_FUNC_DECODER_EXPORT_OBJECT,                              \
           (void (*)(void))pvk2key_export_object },                      \
-        { 0, NULL }                                                     \
+        OSSL_DISPATCH_END                                               \
     }
 
 #ifndef OPENSSL_NO_DSA