Coverage Report

Created: 2024-11-21 07:03

/src/openssl/providers/implementations/encode_decode/encode_key2blob.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2021-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
10
/*
11
 * Low level APIs are deprecated for public use, but still ok for internal use.
12
 */
13
#include "internal/deprecated.h"
14
15
#include <openssl/core.h>
16
#include <openssl/core_dispatch.h>
17
#include <openssl/core_names.h>
18
#include <openssl/params.h>
19
#include <openssl/err.h>
20
#include <openssl/evp.h>
21
#include <openssl/ec.h>
22
#include "internal/passphrase.h"
23
#include "internal/nelem.h"
24
#include "prov/implementations.h"
25
#include "prov/bio.h"
26
#include "prov/provider_ctx.h"
27
#include "endecoder_local.h"
28
29
static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
30
                      void *data, int len)
31
0
{
32
0
    BIO *out = ossl_bio_new_from_core_bio(provctx, cout);
33
0
    int ret;
34
35
0
    if (out == NULL)
36
0
        return 0;
37
0
    ret = BIO_write(out, data, len);
38
39
0
    BIO_free(out);
40
0
    return ret;
41
0
}
42
43
static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
44
static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
45
46
static void *key2blob_newctx(void *provctx)
47
0
{
48
0
    return provctx;
49
0
}
50
51
static void key2blob_freectx(void *vctx)
52
0
{
53
0
}
54
55
static int key2blob_check_selection(int selection, int selection_mask)
56
0
{
57
    /*
58
     * The selections are kinda sorta "levels", i.e. each selection given
59
     * here is assumed to include those following.
60
     */
61
0
    int checks[] = {
62
0
        OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
63
0
        OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
64
0
        OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
65
0
    };
66
0
    size_t i;
67
68
    /* The decoder implementations made here support guessing */
69
0
    if (selection == 0)
70
0
        return 1;
71
72
0
    for (i = 0; i < OSSL_NELEM(checks); i++) {
73
0
        int check1 = (selection & checks[i]) != 0;
74
0
        int check2 = (selection_mask & checks[i]) != 0;
75
76
        /*
77
         * If the caller asked for the currently checked bit(s), return
78
         * whether the decoder description says it's supported.
79
         */
80
0
        if (check1)
81
0
            return check2;
82
0
    }
83
84
    /* This should be dead code, but just to be safe... */
85
0
    return 0;
86
0
}
87
88
static int key2blob_encode(void *vctx, const void *key, int selection,
89
                           OSSL_CORE_BIO *cout)
90
0
{
91
0
    int pubkey_len = 0, ok = 0;
92
0
    unsigned char *pubkey = NULL;
93
94
0
    pubkey_len = i2o_ECPublicKey(key, &pubkey);
95
0
    if (pubkey_len > 0 && pubkey != NULL)
96
0
        ok = write_blob(vctx, cout, pubkey, pubkey_len);
97
0
    OPENSSL_free(pubkey);
98
0
    return ok;
99
0
}
100
101
/*
102
 * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
103
 * encoder
104
 *
105
 * impl:                The keytype to encode
106
 * type:                The C structure type holding the key data
107
 * selection_name:      The acceptable selections.  This translates into
108
 *                      the macro EVP_PKEY_##selection_name.
109
 *
110
 * The selection is understood as a "level" rather than an exact set of
111
 * requests from the caller.  The encoder has to decide what contents fit
112
 * the encoded format.  For example, the EC public key blob will only contain
113
 * the encoded public key itself, no matter if the selection bits include
114
 * OSSL_KEYMGMT_SELECT_PARAMETERS or not.  However, if the selection includes
115
 * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
116
 * cooperate, because it cannot output the private key.
117
 *
118
 * EVP_PKEY_##selection_name are convenience macros that combine "typical"
119
 * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
120
 */
121
#define MAKE_BLOB_ENCODER(impl, type, selection_name)                   \
122
    static OSSL_FUNC_encoder_import_object_fn                           \
123
    impl##2blob_import_object;                                          \
124
    static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object;    \
125
    static OSSL_FUNC_encoder_does_selection_fn                          \
126
    impl##2blob_does_selection;                                         \
127
    static OSSL_FUNC_encoder_encode_fn impl##2blob_encode;              \
128
                                                                        \
129
    static void *impl##2blob_import_object(void *ctx, int selection,    \
130
                                           const OSSL_PARAM params[])   \
131
0
    {                                                                   \
132
0
        return ossl_prov_import_key(ossl_##impl##_keymgmt_functions,    \
133
0
                                    ctx, selection, params);            \
134
0
    }                                                                   \
Unexecuted instantiation: encode_key2blob.c:ec2blob_import_object
Unexecuted instantiation: encode_key2blob.c:sm22blob_import_object
135
    static void impl##2blob_free_object(void *key)                      \
136
0
    {                                                                   \
137
0
        ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key);       \
138
0
    }                                                                   \
Unexecuted instantiation: encode_key2blob.c:ec2blob_free_object
Unexecuted instantiation: encode_key2blob.c:sm22blob_free_object
139
    static int impl##2blob_does_selection(void *ctx, int selection)     \
140
0
    {                                                                   \
141
0
        return key2blob_check_selection(selection,                      \
142
0
                                        EVP_PKEY_##selection_name);     \
143
0
    }                                                                   \
Unexecuted instantiation: encode_key2blob.c:ec2blob_does_selection
Unexecuted instantiation: encode_key2blob.c:sm22blob_does_selection
144
    static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout,      \
145
                                  const void *key,                      \
146
                                  const OSSL_PARAM key_abstract[],      \
147
                                  int selection,                        \
148
                                  OSSL_PASSPHRASE_CALLBACK *cb,         \
149
                                  void *cbarg)                          \
150
0
    {                                                                   \
151
0
        /* We don't deal with abstract objects */                       \
152
0
        if (key_abstract != NULL) {                                     \
153
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);     \
154
0
            return 0;                                                   \
155
0
        }                                                               \
156
0
        return key2blob_encode(vctx, key, selection, cout);             \
157
0
    }                                                                   \
Unexecuted instantiation: encode_key2blob.c:ec2blob_encode
Unexecuted instantiation: encode_key2blob.c:sm22blob_encode
158
    const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = {   \
159
        { OSSL_FUNC_ENCODER_NEWCTX,                                     \
160
          (void (*)(void))key2blob_newctx },                            \
161
        { OSSL_FUNC_ENCODER_FREECTX,                                    \
162
          (void (*)(void))key2blob_freectx },                           \
163
        { OSSL_FUNC_ENCODER_DOES_SELECTION,                             \
164
          (void (*)(void))impl##2blob_does_selection },                 \
165
        { OSSL_FUNC_ENCODER_IMPORT_OBJECT,                              \
166
          (void (*)(void))impl##2blob_import_object },                  \
167
        { OSSL_FUNC_ENCODER_FREE_OBJECT,                                \
168
          (void (*)(void))impl##2blob_free_object },                    \
169
        { OSSL_FUNC_ENCODER_ENCODE,                                     \
170
          (void (*)(void))impl##2blob_encode },                         \
171
        OSSL_DISPATCH_END                                               \
172
    }
173
174
#ifndef OPENSSL_NO_EC
175
MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
176
# ifndef OPENSSL_NO_SM2
177
MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
178
# endif
179
#endif