Home | History | Annotate | Line # | Download | only in encode_decode
      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 
     10 /*
     11  * low level APIs are deprecated for public use, but still ok for
     12  * internal use.
     13  */
     14 #include "internal/deprecated.h"
     15 
     16 #include <string.h>
     17 
     18 #include <openssl/core_dispatch.h>
     19 #include <openssl/core_names.h>
     20 #include <openssl/core_object.h>
     21 #include <openssl/crypto.h>
     22 #include <openssl/params.h>
     23 #include <openssl/pem.h> /* For public PVK functions */
     24 #include <openssl/x509.h>
     25 #include <openssl/err.h>
     26 #include "internal/passphrase.h"
     27 #include "crypto/pem.h" /* For internal PVK and "blob" headers */
     28 #include "crypto/rsa.h"
     29 #include "prov/bio.h"
     30 #include "prov/implementations.h"
     31 #include "endecoder_local.h"
     32 
     33 struct msblob2key_ctx_st; /* Forward declaration */
     34 typedef void *b2i_of_void_fn(const unsigned char **in, unsigned int bitlen,
     35     int ispub);
     36 typedef void adjust_key_fn(void *, struct msblob2key_ctx_st *ctx);
     37 typedef void free_key_fn(void *);
     38 struct keytype_desc_st {
     39     int type; /* EVP key type */
     40     const char *name; /* Keytype */
     41     const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
     42 
     43     b2i_of_void_fn *read_private_key;
     44     b2i_of_void_fn *read_public_key;
     45     adjust_key_fn *adjust_key;
     46     free_key_fn *free_key;
     47 };
     48 
     49 static OSSL_FUNC_decoder_freectx_fn msblob2key_freectx;
     50 static OSSL_FUNC_decoder_decode_fn msblob2key_decode;
     51 static OSSL_FUNC_decoder_export_object_fn msblob2key_export_object;
     52 
     53 /*
     54  * Context used for DER to key decoding.
     55  */
     56 struct msblob2key_ctx_st {
     57     PROV_CTX *provctx;
     58     const struct keytype_desc_st *desc;
     59     /* The selection that is passed to msblob2key_decode() */
     60     int selection;
     61 };
     62 
     63 static struct msblob2key_ctx_st *
     64 msblob2key_newctx(void *provctx, const struct keytype_desc_st *desc)
     65 {
     66     struct msblob2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
     67 
     68     if (ctx != NULL) {
     69         ctx->provctx = provctx;
     70         ctx->desc = desc;
     71     }
     72     return ctx;
     73 }
     74 
     75 static void msblob2key_freectx(void *vctx)
     76 {
     77     struct msblob2key_ctx_st *ctx = vctx;
     78 
     79     OPENSSL_free(ctx);
     80 }
     81 
     82 static int msblob2key_does_selection(void *provctx, int selection)
     83 {
     84     if (selection == 0)
     85         return 1;
     86 
     87     if ((selection & (OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) != 0)
     88         return 1;
     89 
     90     return 0;
     91 }
     92 
     93 static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
     94     OSSL_CALLBACK *data_cb, void *data_cbarg,
     95     OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
     96 {
     97     struct msblob2key_ctx_st *ctx = vctx;
     98     BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
     99     const unsigned char *p;
    100     unsigned char hdr_buf[16], *buf = NULL;
    101     unsigned int bitlen, magic, length;
    102     int isdss = -1;
    103     int ispub = -1;
    104     void *key = NULL;
    105     int ok = 0;
    106 
    107     if (in == NULL)
    108         return 0;
    109 
    110     if (BIO_read(in, hdr_buf, 16) != 16) {
    111         ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
    112         goto next;
    113     }
    114     ERR_set_mark();
    115     p = hdr_buf;
    116     ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;
    117     ERR_pop_to_mark();
    118     if (!ok)
    119         goto next;
    120 
    121     ctx->selection = selection;
    122     ok = 0; /* Assume that we fail */
    123 
    124     if ((isdss && ctx->desc->type != EVP_PKEY_DSA)
    125         || (!isdss && ctx->desc->type != EVP_PKEY_RSA))
    126         goto next;
    127 
    128     length = ossl_blob_length(bitlen, isdss, ispub);
    129     if (length > BLOB_MAX_LENGTH) {
    130         ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);
    131         goto next;
    132     }
    133     buf = OPENSSL_malloc(length);
    134     if (buf == NULL)
    135         goto end;
    136     p = buf;
    137     if (BIO_read(in, buf, length) != (int)length) {
    138         ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
    139         goto next;
    140     }
    141 
    142     if ((selection == 0
    143             || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
    144         && !ispub
    145         && ctx->desc->read_private_key != NULL) {
    146         struct ossl_passphrase_data_st pwdata;
    147 
    148         memset(&pwdata, 0, sizeof(pwdata));
    149         if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
    150             goto end;
    151         p = buf;
    152         key = ctx->desc->read_private_key(&p, bitlen, ispub);
    153         if (selection != 0 && key == NULL)
    154             goto next;
    155     }
    156     if (key == NULL && (selection == 0 || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
    157         && ispub
    158         && ctx->desc->read_public_key != NULL) {
    159         p = buf;
    160         key = ctx->desc->read_public_key(&p, bitlen, ispub);
    161         if (selection != 0 && key == NULL)
    162             goto next;
    163     }
    164 
    165     if (key != NULL && ctx->desc->adjust_key != NULL)
    166         ctx->desc->adjust_key(key, ctx);
    167 
    168 next:
    169     /*
    170      * Indicated that we successfully decoded something, or not at all.
    171      * Ending up "empty handed" is not an error.
    172      */
    173     ok = 1;
    174 
    175     /*
    176      * We free resources here so it's not held up during the callback, because
    177      * we know the process is recursive and the allocated chunks of memory
    178      * add up.
    179      */
    180     OPENSSL_free(buf);
    181     BIO_free(in);
    182     buf = NULL;
    183     in = NULL;
    184 
    185     if (key != NULL) {
    186         OSSL_PARAM params[4];
    187         int object_type = OSSL_OBJECT_PKEY;
    188 
    189         params[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
    190         params[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
    191             (char *)ctx->desc->name, 0);
    192         /* The address of the key becomes the octet string */
    193         params[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
    194             &key, sizeof(key));
    195         params[3] = OSSL_PARAM_construct_end();
    196 
    197         ok = data_cb(params, data_cbarg);
    198     }
    199 
    200 end:
    201     BIO_free(in);
    202     OPENSSL_free(buf);
    203     ctx->desc->free_key(key);
    204 
    205     return ok;
    206 }
    207 
    208 static int
    209 msblob2key_export_object(void *vctx,
    210     const void *reference, size_t reference_sz,
    211     OSSL_CALLBACK *export_cb, void *export_cbarg)
    212 {
    213     struct msblob2key_ctx_st *ctx = vctx;
    214     OSSL_FUNC_keymgmt_export_fn *export = ossl_prov_get_keymgmt_export(ctx->desc->fns);
    215     void *keydata;
    216 
    217     if (reference_sz == sizeof(keydata) && export != NULL) {
    218         int selection = ctx->selection;
    219 
    220         if (selection == 0)
    221             selection = OSSL_KEYMGMT_SELECT_ALL;
    222         /* The contents of the reference is the address to our object */
    223         keydata = *(void **)reference;
    224 
    225         return export(keydata, selection, export_cb, export_cbarg);
    226     }
    227     return 0;
    228 }
    229 
    230 /* ---------------------------------------------------------------------- */
    231 
    232 #define dsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header
    233 #define dsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header
    234 #define dsa_adjust NULL
    235 #define dsa_free (void (*)(void *)) DSA_free
    236 
    237 /* ---------------------------------------------------------------------- */
    238 
    239 #define rsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header
    240 #define rsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header
    241 
    242 static void rsa_adjust(void *key, struct msblob2key_ctx_st *ctx)
    243 {
    244     ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
    245 }
    246 
    247 #define rsa_free (void (*)(void *)) RSA_free
    248 
    249 /* ---------------------------------------------------------------------- */
    250 
    251 #define IMPLEMENT_MSBLOB(KEYTYPE, keytype)                             \
    252     static const struct keytype_desc_st mstype##2##keytype##_desc = {  \
    253         EVP_PKEY_##KEYTYPE, #KEYTYPE,                                  \
    254         ossl_##keytype##_keymgmt_functions,                            \
    255         keytype##_decode_private_key,                                  \
    256         keytype##_decode_public_key,                                   \
    257         keytype##_adjust,                                              \
    258         keytype##_free                                                 \
    259     };                                                                 \
    260     static OSSL_FUNC_decoder_newctx_fn msblob2##keytype##_newctx;      \
    261     static void *msblob2##keytype##_newctx(void *provctx)              \
    262     {                                                                  \
    263         return msblob2key_newctx(provctx, &mstype##2##keytype##_desc); \
    264     }                                                                  \
    265     const OSSL_DISPATCH                                                \
    266         ossl_msblob_to_##keytype##_decoder_functions[]                 \
    267         = {                                                            \
    268               { OSSL_FUNC_DECODER_NEWCTX,                              \
    269                   (void (*)(void))msblob2##keytype##_newctx },         \
    270               { OSSL_FUNC_DECODER_FREECTX,                             \
    271                   (void (*)(void))msblob2key_freectx },                \
    272               { OSSL_FUNC_DECODER_DOES_SELECTION,                      \
    273                   (void (*)(void))msblob2key_does_selection },         \
    274               { OSSL_FUNC_DECODER_DECODE,                              \
    275                   (void (*)(void))msblob2key_decode },                 \
    276               { OSSL_FUNC_DECODER_EXPORT_OBJECT,                       \
    277                   (void (*)(void))msblob2key_export_object },          \
    278               OSSL_DISPATCH_END                                        \
    279           }
    280 
    281 #ifndef OPENSSL_NO_DSA
    282 IMPLEMENT_MSBLOB(DSA, dsa);
    283 #endif
    284 IMPLEMENT_MSBLOB(RSA, rsa);
    285