Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/providers/implementations/encode_decode/decode_pvk2key.c
Line
Count
Source
1
/*
2
 * Copyright 2020-2025 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
/* clang-format off */
10
11
/* clang-format on */
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
39
struct pvk2key_ctx_st; /* Forward declaration */
40
typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);
41
typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);
42
typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,
43
    OSSL_LIB_CTX *libctx, const char *propq);
44
typedef void free_key_fn(void *);
45
struct 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
55
static OSSL_FUNC_decoder_freectx_fn pvk2key_freectx;
56
static OSSL_FUNC_decoder_decode_fn pvk2key_decode;
57
static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;
58
static OSSL_FUNC_decoder_settable_ctx_params_fn pvk2key_settable_ctx_params;
59
static OSSL_FUNC_decoder_set_ctx_params_fn pvk2key_set_ctx_params;
60
61
/*
62
 * Context used for DER to key decoding.
63
 */
64
struct 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
72
static struct pvk2key_ctx_st *
73
pvk2key_newctx(void *provctx, const struct keytype_desc_st *desc)
74
311k
{
75
311k
    struct pvk2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
76
77
311k
    if (ctx != NULL) {
78
311k
        ctx->provctx = provctx;
79
311k
        ctx->desc = desc;
80
311k
    }
81
311k
    return ctx;
82
311k
}
83
84
static void pvk2key_freectx(void *vctx)
85
311k
{
86
311k
    struct pvk2key_ctx_st *ctx = vctx;
87
88
311k
    OPENSSL_free(ctx);
89
311k
}
90
91
/* clang-format off */
92
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
93
#ifndef pvk2key_set_ctx_params_list
94
static const OSSL_PARAM pvk2key_set_ctx_params_list[] = {
95
    OSSL_PARAM_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, NULL, 0),
96
    OSSL_PARAM_END
97
};
98
#endif
99
100
#ifndef pvk2key_set_ctx_params_st
101
struct pvk2key_set_ctx_params_st {
102
    OSSL_PARAM *propq;
103
};
104
#endif
105
106
#ifndef pvk2key_set_ctx_params_decoder
107
static int pvk2key_set_ctx_params_decoder
108
    (const OSSL_PARAM *p, struct pvk2key_set_ctx_params_st *r)
109
0
{
110
0
    const char *s;
111
112
0
    memset(r, 0, sizeof(*r));
113
0
    if (p != NULL)
114
0
        for (; (s = p->key) != NULL; p++)
115
0
            if (ossl_likely(strcmp("properties", s + 0) == 0)) {
116
                /* OSSL_DECODER_PARAM_PROPERTIES */
117
0
                if (ossl_unlikely(r->propq != NULL)) {
118
0
                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
119
0
                                   "param %s is repeated", s);
120
0
                    return 0;
121
0
                }
122
0
                r->propq = (OSSL_PARAM *)p;
123
0
            }
124
0
    return 1;
125
0
}
126
#endif
127
/* End of machine generated */
128
/* clang-format on */
129
130
static const OSSL_PARAM *pvk2key_settable_ctx_params(ossl_unused void *provctx)
131
0
{
132
0
    return pvk2key_set_ctx_params_list;
133
0
}
134
135
static int pvk2key_set_ctx_params(void *vctx, const OSSL_PARAM params[])
136
0
{
137
0
    struct pvk2key_ctx_st *ctx = vctx;
138
0
    struct pvk2key_set_ctx_params_st p;
139
0
    char *str;
140
141
0
    if (ctx == NULL || !pvk2key_set_ctx_params_decoder(params, &p))
142
0
        return 0;
143
144
0
    str = ctx->propq;
145
0
    if (p.propq != NULL
146
0
        && !OSSL_PARAM_get_utf8_string(p.propq, &str, sizeof(ctx->propq)))
147
0
        return 0;
148
149
0
    return 1;
150
0
}
151
152
static int pvk2key_does_selection(void *provctx, int selection)
153
556k
{
154
556k
    if (selection == 0)
155
10
        return 1;
156
157
556k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
158
90.5k
        return 1;
159
160
466k
    return 0;
161
556k
}
162
163
static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
164
    OSSL_CALLBACK *data_cb, void *data_cbarg,
165
    OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
166
43.6k
{
167
43.6k
    struct pvk2key_ctx_st *ctx = vctx;
168
43.6k
    BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
169
43.6k
    void *key = NULL;
170
43.6k
    int ok = 0;
171
172
43.6k
    if (in == NULL)
173
0
        return 0;
174
175
43.6k
    ctx->selection = selection;
176
177
43.6k
    if ((selection == 0
178
0
            || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
179
43.6k
        && ctx->desc->read_private_key != NULL) {
180
43.6k
        struct ossl_passphrase_data_st pwdata;
181
43.6k
        int err, lib, reason;
182
183
43.6k
        memset(&pwdata, 0, sizeof(pwdata));
184
43.6k
        if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
185
0
            goto end;
186
187
43.6k
        key = ctx->desc->read_private_key(in, ossl_pw_pvk_password, &pwdata,
188
43.6k
            PROV_LIBCTX_OF(ctx->provctx),
189
43.6k
            ctx->propq);
190
191
        /*
192
         * Because the PVK API doesn't have a separate decrypt call, we need
193
         * to check the error queue for certain well known errors that are
194
         * considered fatal and which we pass through, while the rest gets
195
         * thrown away.
196
         */
197
43.6k
        err = ERR_peek_last_error();
198
43.6k
        lib = ERR_GET_LIB(err);
199
43.6k
        reason = ERR_GET_REASON(err);
200
43.6k
        if (lib == ERR_LIB_PEM
201
43.3k
            && (reason == PEM_R_BAD_PASSWORD_READ
202
43.2k
                || reason == PEM_R_BAD_DECRYPT)) {
203
21
            ERR_clear_last_mark();
204
21
            goto end;
205
21
        }
206
207
43.6k
        if (selection != 0 && key == NULL)
208
0
            goto next;
209
43.6k
    }
210
211
43.6k
    if (key != NULL && ctx->desc->adjust_key != NULL)
212
12
        ctx->desc->adjust_key(key, ctx);
213
214
43.6k
next:
215
    /*
216
     * Indicated that we successfully decoded something, or not at all.
217
     * Ending up "empty handed" is not an error.
218
     */
219
43.6k
    ok = 1;
220
221
    /*
222
     * We free resources here so it's not held up during the callback, because
223
     * we know the process is recursive and the allocated chunks of memory
224
     * add up.
225
     */
226
43.6k
    BIO_free(in);
227
43.6k
    in = NULL;
228
229
43.6k
    if (key != NULL) {
230
16
        OSSL_PARAM params[4];
231
16
        int object_type = OSSL_OBJECT_PKEY;
232
233
16
        params[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
234
16
        params[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
235
16
            (char *)ctx->desc->name, 0);
236
        /* The address of the key becomes the octet string */
237
16
        params[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
238
16
            &key, sizeof(key));
239
16
        params[3] = OSSL_PARAM_construct_end();
240
241
16
        ok = data_cb(params, data_cbarg);
242
16
    }
243
244
43.6k
end:
245
43.6k
    BIO_free(in);
246
43.6k
    ctx->desc->free_key(key);
247
248
43.6k
    return ok;
249
43.6k
}
250
251
static int pvk2key_export_object(void *vctx,
252
    const void *reference, size_t reference_sz,
253
    OSSL_CALLBACK *export_cb, void *export_cbarg)
254
0
{
255
0
    struct pvk2key_ctx_st *ctx = vctx;
256
0
    OSSL_FUNC_keymgmt_export_fn *export = ossl_prov_get_keymgmt_export(ctx->desc->fns);
257
0
    void *keydata;
258
259
0
    if (reference_sz == sizeof(keydata) && export != NULL) {
260
0
        int selection = ctx->selection;
261
262
0
        if (selection == 0)
263
0
            selection = OSSL_KEYMGMT_SELECT_ALL;
264
        /* The contents of the reference is the address to our object */
265
0
        keydata = *(void **)reference;
266
267
0
        return export(keydata, selection, export_cb, export_cbarg);
268
0
    }
269
0
    return 0;
270
0
}
271
272
/* ---------------------------------------------------------------------- */
273
274
#define dsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex
275
#define dsa_adjust NULL
276
#define dsa_free (void (*)(void *)) DSA_free
277
278
/* ---------------------------------------------------------------------- */
279
280
#define rsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex
281
282
static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
283
12
{
284
12
    ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
285
12
}
286
287
#define rsa_free (void (*)(void *)) RSA_free
288
289
/* ---------------------------------------------------------------------- */
290
291
#define IMPLEMENT_MS(KEYTYPE, keytype)                           \
292
    static const struct keytype_desc_st                          \
293
        pvk2##keytype##_desc                                     \
294
        = {                                                      \
295
              EVP_PKEY_##KEYTYPE, #KEYTYPE,                      \
296
              ossl_##keytype##_keymgmt_functions,                \
297
              keytype##_private_key_bio,                         \
298
              keytype##_adjust,                                  \
299
              keytype##_free                                     \
300
          };                                                     \
301
    static OSSL_FUNC_decoder_newctx_fn pvk2##keytype##_newctx;   \
302
    static void *pvk2##keytype##_newctx(void *provctx)           \
303
311k
    {                                                            \
304
311k
        return pvk2key_newctx(provctx, &pvk2##keytype##_desc);   \
305
311k
    }                                                            \
decode_pvk2key.c:pvk2dsa_newctx
Line
Count
Source
303
156k
    {                                                            \
304
156k
        return pvk2key_newctx(provctx, &pvk2##keytype##_desc);   \
305
156k
    }                                                            \
decode_pvk2key.c:pvk2rsa_newctx
Line
Count
Source
303
155k
    {                                                            \
304
155k
        return pvk2key_newctx(provctx, &pvk2##keytype##_desc);   \
305
155k
    }                                                            \
306
    const OSSL_DISPATCH                                          \
307
        ossl_##pvk_to_##keytype##_decoder_functions[]            \
308
        = {                                                      \
309
              { OSSL_FUNC_DECODER_NEWCTX,                        \
310
                  (void (*)(void))pvk2##keytype##_newctx },      \
311
              { OSSL_FUNC_DECODER_FREECTX,                       \
312
                  (void (*)(void))pvk2key_freectx },             \
313
              { OSSL_FUNC_DECODER_DOES_SELECTION,                \
314
                  (void (*)(void))pvk2key_does_selection },      \
315
              { OSSL_FUNC_DECODER_DECODE,                        \
316
                  (void (*)(void))pvk2key_decode },              \
317
              { OSSL_FUNC_DECODER_EXPORT_OBJECT,                 \
318
                  (void (*)(void))pvk2key_export_object },       \
319
              { OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS,           \
320
                  (void (*)(void))pvk2key_settable_ctx_params }, \
321
              { OSSL_FUNC_DECODER_SET_CTX_PARAMS,                \
322
                  (void (*)(void))pvk2key_set_ctx_params },      \
323
              OSSL_DISPATCH_END                                  \
324
          }
325
326
#ifndef OPENSSL_NO_DSA
327
IMPLEMENT_MS(DSA, dsa);
328
#endif
329
IMPLEMENT_MS(RSA, rsa);