1/*
2 * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9{-
10use OpenSSL::paramnames qw(produce_param_decoder);
11-}
12
13/*
14 * low level APIs are deprecated for public use, but still ok for
15 * internal use.
16 */
17#include "internal/deprecated.h"
18
19#include <string.h>
20
21#include <openssl/core_dispatch.h>
22#include <openssl/core_names.h>
23#include <openssl/core_object.h>
24#include <openssl/crypto.h>
25#include <openssl/params.h>
26#include <openssl/err.h>
27#include <openssl/proverr.h>
28#include <openssl/pem.h>         /* For public PVK functions */
29#include <openssl/x509.h>
30#include "internal/cryptlib.h"
31#include "internal/passphrase.h"
32#include "internal/sizes.h"
33#include "crypto/pem.h"          /* For internal PVK and "blob" headers */
34#include "crypto/rsa.h"
35#include "prov/bio.h"
36#include "prov/implementations.h"
37#include "prov/endecoder_local.h"
38
39struct pvk2key_ctx_st;            /* Forward declaration */
40typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);
41typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);
42typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,
43                                   OSSL_LIB_CTX *libctx, const char *propq);
44typedef void free_key_fn(void *);
45struct keytype_desc_st {
46    int type;                 /* EVP key type */
47    const char *name;         /* Keytype */
48    const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
49
50    b2i_PVK_of_bio_pw_fn *read_private_key;
51    adjust_key_fn *adjust_key;
52    free_key_fn *free_key;
53};
54
55static OSSL_FUNC_decoder_freectx_fn pvk2key_freectx;
56static OSSL_FUNC_decoder_decode_fn pvk2key_decode;
57static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;
58static OSSL_FUNC_decoder_settable_ctx_params_fn pvk2key_settable_ctx_params;
59static OSSL_FUNC_decoder_set_ctx_params_fn pvk2key_set_ctx_params;
60
61/*
62 * Context used for DER to key decoding.
63 */
64struct pvk2key_ctx_st {
65    PROV_CTX *provctx;
66    char propq[OSSL_MAX_PROPQUERY_SIZE];
67    const struct keytype_desc_st *desc;
68    /* The selection that is passed to der2key_decode() */
69    int selection;
70};
71
72static struct pvk2key_ctx_st *
73pvk2key_newctx(void *provctx, const struct keytype_desc_st *desc)
74{
75    struct pvk2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
76
77    if (ctx != NULL) {
78        ctx->provctx = provctx;
79        ctx->desc = desc;
80    }
81    return ctx;
82}
83
84static void pvk2key_freectx(void *vctx)
85{
86    struct pvk2key_ctx_st *ctx = vctx;
87
88    OPENSSL_free(ctx);
89}
90
91{- produce_param_decoder('pvk2key_set_ctx_params',
92                         (['DECODER_PARAM_PROPERTIES', 'propq', 'utf8_string'],
93                         )); -}
94
95static const OSSL_PARAM *pvk2key_settable_ctx_params(ossl_unused void *provctx)
96{
97    return pvk2key_set_ctx_params_list;
98}
99
100static int pvk2key_set_ctx_params(void *vctx, const OSSL_PARAM params[])
101{
102    struct pvk2key_ctx_st *ctx = vctx;
103    struct pvk2key_set_ctx_params_st p;
104    char *str;
105
106    if (ctx == NULL || !pvk2key_set_ctx_params_decoder(params, &p))
107        return 0;
108
109    str = ctx->propq;
110    if (p.propq != NULL
111            && !OSSL_PARAM_get_utf8_string(p.propq, &str, sizeof(ctx->propq)))
112        return 0;
113
114    return 1;
115}
116
117static int pvk2key_does_selection(void *provctx, int selection)
118{
119    if (selection == 0)
120        return 1;
121
122    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY)  != 0)
123        return 1;
124
125    return 0;
126}
127
128static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
129                         OSSL_CALLBACK *data_cb, void *data_cbarg,
130                         OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
131{
132    struct pvk2key_ctx_st *ctx = vctx;
133    BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
134    void *key = NULL;
135    int ok = 0;
136
137    if (in == NULL)
138        return 0;
139
140    ctx->selection = selection;
141
142    if ((selection == 0
143         || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
144        && ctx->desc->read_private_key != NULL) {
145        struct ossl_passphrase_data_st pwdata;
146        int err, lib, reason;
147
148        memset(&pwdata, 0, sizeof(pwdata));
149        if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
150            goto end;
151
152        key = ctx->desc->read_private_key(in, ossl_pw_pvk_password, &pwdata,
153                                          PROV_LIBCTX_OF(ctx->provctx),
154                                          ctx->propq);
155
156        /*
157         * Because the PVK API doesn't have a separate decrypt call, we need
158         * to check the error queue for certain well known errors that are
159         * considered fatal and which we pass through, while the rest gets
160         * thrown away.
161         */
162        err = ERR_peek_last_error();
163        lib = ERR_GET_LIB(err);
164        reason = ERR_GET_REASON(err);
165        if (lib == ERR_LIB_PEM
166            && (reason == PEM_R_BAD_PASSWORD_READ
167                || reason == PEM_R_BAD_DECRYPT)) {
168            ERR_clear_last_mark();
169            goto end;
170        }
171
172        if (selection != 0 && key == NULL)
173            goto next;
174    }
175
176    if (key != NULL && ctx->desc->adjust_key != NULL)
177        ctx->desc->adjust_key(key, ctx);
178
179 next:
180    /*
181     * Indicated that we successfully decoded something, or not at all.
182     * Ending up "empty handed" is not an error.
183     */
184    ok = 1;
185
186    /*
187     * We free resources here so it's not held up during the callback, because
188     * we know the process is recursive and the allocated chunks of memory
189     * add up.
190     */
191    BIO_free(in);
192    in = NULL;
193
194    if (key != NULL) {
195        OSSL_PARAM params[4];
196        int object_type = OSSL_OBJECT_PKEY;
197
198        params[0] =
199            OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
200        params[1] =
201            OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
202                                             (char *)ctx->desc->name, 0);
203        /* The address of the key becomes the octet string */
204        params[2] =
205            OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
206                                              &key, sizeof(key));
207        params[3] = OSSL_PARAM_construct_end();
208
209        ok = data_cb(params, data_cbarg);
210    }
211
212 end:
213    BIO_free(in);
214    ctx->desc->free_key(key);
215
216    return ok;
217}
218
219static int pvk2key_export_object(void *vctx,
220                                const void *reference, size_t reference_sz,
221                                OSSL_CALLBACK *export_cb, void *export_cbarg)
222{
223    struct pvk2key_ctx_st *ctx = vctx;
224    OSSL_FUNC_keymgmt_export_fn *export =
225        ossl_prov_get_keymgmt_export(ctx->desc->fns);
226    void *keydata;
227
228    if (reference_sz == sizeof(keydata) && export != NULL) {
229        int selection = ctx->selection;
230
231        if (selection == 0)
232            selection = OSSL_KEYMGMT_SELECT_ALL;
233        /* The contents of the reference is the address to our object */
234        keydata = *(void **)reference;
235
236        return export(keydata, selection, export_cb, export_cbarg);
237    }
238    return 0;
239}
240
241/* ---------------------------------------------------------------------- */
242
243#define dsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex
244#define dsa_adjust              NULL
245#define dsa_free                (void (*)(void *))DSA_free
246
247/* ---------------------------------------------------------------------- */
248
249#define rsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex
250
251static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
252{
253    ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
254}
255
256#define rsa_free                (void (*)(void *))RSA_free
257
258/* ---------------------------------------------------------------------- */
259
260#define IMPLEMENT_MS(KEYTYPE, keytype)                                  \
261    static const struct keytype_desc_st                                 \
262    pvk2##keytype##_desc = {                                            \
263        EVP_PKEY_##KEYTYPE, #KEYTYPE,                                   \
264        ossl_##keytype##_keymgmt_functions,                             \
265        keytype##_private_key_bio,                                      \
266        keytype##_adjust,                                               \
267        keytype##_free                                                  \
268    };                                                                  \
269    static OSSL_FUNC_decoder_newctx_fn pvk2##keytype##_newctx;          \
270    static void *pvk2##keytype##_newctx(void *provctx)                  \
271    {                                                                   \
272        return pvk2key_newctx(provctx, &pvk2##keytype##_desc);          \
273    }                                                                   \
274    const OSSL_DISPATCH                                                 \
275    ossl_##pvk_to_##keytype##_decoder_functions[] = {                   \
276        { OSSL_FUNC_DECODER_NEWCTX,                                     \
277          (void (*)(void))pvk2##keytype##_newctx },                     \
278        { OSSL_FUNC_DECODER_FREECTX,                                    \
279          (void (*)(void))pvk2key_freectx },                            \
280        { OSSL_FUNC_DECODER_DOES_SELECTION,                             \
281          (void (*)(void))pvk2key_does_selection },                     \
282        { OSSL_FUNC_DECODER_DECODE,                                     \
283          (void (*)(void))pvk2key_decode },                             \
284        { OSSL_FUNC_DECODER_EXPORT_OBJECT,                              \
285          (void (*)(void))pvk2key_export_object },                      \
286        { OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS,                        \
287          (void (*)(void))pvk2key_settable_ctx_params },                \
288        { OSSL_FUNC_DECODER_SET_CTX_PARAMS,                             \
289          (void (*)(void))pvk2key_set_ctx_params },                     \
290        OSSL_DISPATCH_END                                               \
291    }
292
293#ifndef OPENSSL_NO_DSA
294IMPLEMENT_MS(DSA, dsa);
295#endif
296IMPLEMENT_MS(RSA, rsa);
297