diff options
Diffstat (limited to 'crypto')
30 files changed, 2190 insertions, 2197 deletions
diff --git a/crypto/asn1/i2d_pr.c b/crypto/asn1/i2d_pr.c index 545300cbab..84513db5bf 100644 --- a/crypto/asn1/i2d_pr.c +++ b/crypto/asn1/i2d_pr.c @@ -10,7 +10,7 @@ #include <stdio.h> #include "internal/cryptlib.h" #include <openssl/evp.h> -#include <openssl/serializer.h> +#include <openssl/encoder.h> #include <openssl/buffer.h> #include <openssl/x509.h> #include "crypto/asn1.h" @@ -31,17 +31,17 @@ int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp) return ret; } if (a->keymgmt != NULL) { - const char *serprop = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ; - OSSL_SERIALIZER_CTX *ctx = - OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(a, serprop); + const char *encprop = OSSL_ENCODER_PrivateKey_TO_DER_PQ; + OSSL_ENCODER_CTX *ctx = + OSSL_ENCODER_CTX_new_by_EVP_PKEY(a, encprop); BIO *out = BIO_new(BIO_s_mem()); BUF_MEM *buf = NULL; int ret = -1; if (ctx != NULL && out != NULL - && OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL - && OSSL_SERIALIZER_to_bio(ctx, out) + && OSSL_ENCODER_CTX_get_encoder(ctx) != NULL + && OSSL_ENCODER_to_bio(ctx, out) && BIO_get_mem_ptr(out, &buf) > 0) { ret = buf->length; @@ -57,7 +57,7 @@ int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp) } } BIO_free(out); - OSSL_SERIALIZER_CTX_free(ctx); + OSSL_ENCODER_CTX_free(ctx); return ret; } ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); diff --git a/crypto/build.info b/crypto/build.info index 83625029c0..07e3dd526f 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \ md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ - err comp http ocsp cms ts srp cmac ct async ess crmf cmp serializer \ + err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \ ffc LIBS=../libcrypto diff --git a/crypto/encode_decode/build.info b/crypto/encode_decode/build.info new file mode 100644 index 0000000000..4686c4a19d --- /dev/null +++ b/crypto/encode_decode/build.info @@ -0,0 +1,8 @@ +SOURCE[../../libcrypto]=endecode_pass.c + +SOURCE[../../libcrypto]=encoder_meth.c encoder_lib.c encoder_pkey.c +SOURCE[../../libcrypto]=decoder_meth.c decoder_lib.c \ + decoder_pkey.c + +SOURCE[../../libcrypto]=encoder_err.c +SOURCE[../../libcrypto]=decoder_err.c diff --git a/crypto/serializer/deserializer_err.c b/crypto/encode_decode/decoder_err.c index 2cc245996f..984f7abeb9 100644 --- a/crypto/serializer/deserializer_err.c +++ b/crypto/encode_decode/decoder_err.c @@ -9,23 +9,23 @@ */ #include <openssl/err.h> -#include <openssl/deserializererr.h> +#include <openssl/decodererr.h> #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA OSSL_DESERIALIZER_str_reasons[] = { - {ERR_PACK(ERR_LIB_OSSL_DESERIALIZER, 0, OSSL_DESERIALIZER_R_MISSING_GET_PARAMS), - "missing get params"}, +static const ERR_STRING_DATA OSSL_DECODER_str_reasons[] = { + {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, OSSL_DECODER_R_MISSING_GET_PARAMS), + "missing get params"}, {0, NULL} }; #endif -int ERR_load_OSSL_DESERIALIZER_strings(void) +int ERR_load_OSSL_DECODER_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_reason_error_string(OSSL_DESERIALIZER_str_reasons[0].error) == NULL) - ERR_load_strings_const(OSSL_DESERIALIZER_str_reasons); + if (ERR_reason_error_string(OSSL_DECODER_str_reasons[0].error) == NULL) + ERR_load_strings_const(OSSL_DECODER_str_reasons); #endif return 1; } diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c new file mode 100644 index 0000000000..21b4703084 --- /dev/null +++ b/crypto/encode_decode/decoder_lib.c @@ -0,0 +1,483 @@ +/* + * Copyright 2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core_names.h> +#include <openssl/bio.h> +#include <openssl/params.h> +#include <openssl/provider.h> +#include "encoder_local.h" +#include "e_os.h" + +struct decoder_process_data_st { + OSSL_DECODER_CTX *ctx; + + /* Current BIO */ + BIO *bio; + + /* Index of the current decoder instance to be processed */ + size_t current_deser_inst_index; +}; + +static int decoder_process(const OSSL_PARAM params[], void *arg); + +int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in) +{ + struct decoder_process_data_st data; + int ok = 0; + + memset(&data, 0, sizeof(data)); + data.ctx = ctx; + data.bio = in; + + ok = decoder_process(NULL, &data); + + /* Clear any internally cached passphrase */ + if (!ctx->flag_user_passphrase) { + OSSL_DECODER_CTX_set_passphrase(ctx, NULL, 0); + ctx->flag_user_passphrase = 0; + } + return ok; +} + +#ifndef OPENSSL_NO_STDIO +static BIO *bio_from_file(FILE *fp) +{ + BIO *b; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB); + return NULL; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + return b; +} + +int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp) +{ + BIO *b = bio_from_file(fp); + int ret = 0; + + if (b != NULL) + ret = OSSL_DECODER_from_bio(ctx, b); + + BIO_free(b); + return ret; +} +#endif + +int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx, + const char *input_type) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* + * NULL is a valid starting input type, and means that the caller leaves + * it to code to discover what the starting input type is. + */ + ctx->start_input_type = input_type; + return 1; +} + +int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder) +{ + OSSL_DECODER_INSTANCE *decoder_inst = NULL; + const OSSL_PROVIDER *prov = NULL; + OSSL_PARAM params[2]; + void *provctx = NULL; + + if (!ossl_assert(ctx != NULL) || !ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (decoder->get_params == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, + OSSL_DECODER_R_MISSING_GET_PARAMS); + return 0; + } + + if (ctx->decoder_insts == NULL + && (ctx->decoder_insts = + sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + return 0; + } + if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!OSSL_DECODER_up_ref(decoder)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); + goto err; + } + decoder_inst->decoder = decoder; + + prov = OSSL_DECODER_provider(decoder_inst->decoder); + provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + + /* Cache the input type for this encoder */ + params[0] = + OSSL_PARAM_construct_utf8_ptr(OSSL_DECODER_PARAM_INPUT_TYPE, + (char **)&decoder_inst->input_type, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!decoder_inst->decoder->get_params(params) + || !OSSL_PARAM_modified(¶ms[0])) + goto err; + + if ((decoder_inst->deserctx = decoder_inst->decoder->newctx(provctx)) + == NULL) + goto err; + + if (sk_OSSL_DECODER_INSTANCE_push(ctx->decoder_insts, decoder_inst) <= 0) + goto err; + + return 1; + err: + if (decoder_inst != NULL) { + if (decoder_inst->decoder != NULL) + decoder_inst->decoder->freectx(decoder_inst->deserctx); + OSSL_DECODER_free(decoder_inst->decoder); + OPENSSL_free(decoder_inst); + } + return 0; +} + +int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, + OPENSSL_CTX *libctx, const char *propq) +{ + /* + * This function goes through existing decoder methods in + * |ctx->decoder_insts|, and tries to fetch new decoders that produce + * what the existing ones want as input, and push those newly fetched + * decoders on top of the same stack. + * Then it does the same again, but looping over the newly fetched + * decoders, until there are no more encoders to be fetched, or + * when we have done this 10 times. + * + * we do this with sliding windows on the stack by keeping track of indexes + * and of the end. + * + * +----------------+ + * | DER to RSA | <--- w_prev_start + * +----------------+ + * | DER to DSA | + * +----------------+ + * | DER to DH | + * +----------------+ + * | PEM to DER | <--- w_prev_end, w_new_start + * +----------------+ + * <--- w_new_end + */ + size_t w_prev_start, w_prev_end; /* "previous" decoders */ + size_t w_new_start, w_new_end; /* "new" decoders */ + size_t count = 0; /* Calculates how many were added in each iteration */ + size_t depth = 0; /* Counts the number of iterations */ + + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* + * If there is no stack of OSSL_DECODER_INSTANCE, we have nothing + * more to add. That's fine. + */ + if (ctx->decoder_insts == NULL) + return 1; + + w_prev_start = 0; + w_prev_end = sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts); + do { + size_t i; + + w_new_start = w_new_end = w_prev_end; + + for (i = w_prev_start; i < w_prev_end; i++) { + OSSL_DECODER_INSTANCE *decoder_inst = + sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); + const char *name = decoder_inst->input_type; + OSSL_DECODER *decoder = NULL; + + /* + * If the caller has specified what the initial input should be, + * and the decoder implementation we're looking at has that + * input type, there's no point adding on more implementations + * on top of this one, so we don't. + */ + if (ctx->start_input_type != NULL + && strcasecmp(ctx->start_input_type, + decoder_inst->input_type) != 0) + continue; + + ERR_set_mark(); + decoder = OSSL_DECODER_fetch(libctx, name, propq); + ERR_pop_to_mark(); + + if (decoder != NULL) { + size_t j; + + /* + * Check that we don't already have this decoder in our + * stack We only need to check among the newly added ones. + */ + for (j = w_new_start; j < w_new_end; j++) { + OSSL_DECODER_INSTANCE *check_inst = + sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, j); + + if (decoder == check_inst->decoder) { + /* We found it, so drop the new fetch */ + OSSL_DECODER_free(decoder); + decoder = NULL; + break; + } + } + } + + if (decoder == NULL) + continue; + + /* + * Apart from keeping w_new_end up to date, We don't care about + * errors here. If it doesn't collect, then it doesn't... + */ + if (OSSL_DECODER_CTX_add_decoder(ctx, decoder)) /* ref++ */ + w_new_end++; + OSSL_DECODER_free(decoder); /* ref-- */ + } + /* How many were added in this iteration */ + count = w_new_end - w_new_start; + + /* Slide the "previous decoder" windows */ + w_prev_start = w_new_start; + w_prev_end = w_new_end; + + depth++; + } while (count != 0 && depth <= 10); + + return 1; +} + +int OSSL_DECODER_CTX_num_decoders(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL || ctx->decoder_insts == NULL) + return 0; + return sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts); +} + +int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx, + OSSL_DECODER_CONSTRUCT *construct) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx->construct = construct; + return 1; +} + +int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx, + void *construct_data) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx->construct_data = construct_data; + return 1; +} + +int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx, + OSSL_DECODER_CLEANUP *cleanup) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx->cleanup = cleanup; + return 1; +} + +OSSL_DECODER_CONSTRUCT * +OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->construct; +} + +void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->construct_data; +} + +OSSL_DECODER_CLEANUP * +OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->cleanup; +} + +int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst, + void *reference, size_t reference_sz, + OSSL_CALLBACK *export_cb, void *export_cbarg) +{ + if (!(ossl_assert(decoder_inst != NULL) + && ossl_assert(reference != NULL) + && ossl_assert(export_cb != NULL) + && ossl_assert(export_cbarg != NULL))) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return decoder_inst->decoder->export_object(decoder_inst->deserctx, + reference, reference_sz, + export_cb, export_cbarg); +} + +OSSL_DECODER *OSSL_DECODER_INSTANCE_decoder(OSSL_DECODER_INSTANCE *decoder_inst) +{ + if (decoder_inst == NULL) + return NULL; + return decoder_inst->decoder; +} + +void *OSSL_DECODER_INSTANCE_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst) +{ + if (decoder_inst == NULL) + return NULL; + return decoder_inst->deserctx; +} + +static int decoder_process(const OSSL_PARAM params[], void *arg) +{ + struct decoder_process_data_st *data = arg; + OSSL_DECODER_CTX *ctx = data->ctx; + OSSL_DECODER_INSTANCE *decoder_inst = NULL; + OSSL_DECODER *decoder = NULL; + BIO *bio = data->bio; + long loc; + size_t i; + int ok = 0; + /* For recursions */ + struct decoder_process_data_st new_data; + + memset(&new_data, 0, sizeof(new_data)); + new_data.ctx = data->ctx; + + if (params == NULL) { + /* First iteration, where we prepare for what is to come */ + + data->current_deser_inst_index = + OSSL_DECODER_CTX_num_decoders(ctx); + + bio = data->bio; + } else { + const OSSL_PARAM *p; + + decoder_inst = + sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, + data->current_deser_inst_index); + decoder = OSSL_DECODER_INSTANCE_decoder(decoder_inst); + + if (ctx->construct != NULL + && ctx->construct(decoder_inst, params, ctx->construct_data)) { + ok = 1; + goto end; + } + + /* The constructor didn't return success */ + + /* + * so we try to use the object we got and feed it to any next + * decoder that will take it. Object references are not + * allowed for this. + * If this data isn't present, decoding has failed. + */ + + p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_DATA); + if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) + goto end; + new_data.bio = BIO_new_mem_buf(p->data, (int)p->data_size); + if (new_data.bio == NULL) + goto end; + bio = new_data.bio; + } + + /* + * If we have no more decoders to look through at this point, + * we failed + */ + if (data->current_deser_inst_index == 0) + goto end; + + if ((loc = BIO_tell(bio)) < 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB); + goto end; + } + + for (i = data->current_deser_inst_index; i-- > 0;) { + OSSL_DECODER_INSTANCE *new_deser_inst = + sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); + OSSL_DECODER *new_deser = + OSSL_DECODER_INSTANCE_decoder(new_deser_inst); + + /* + * If |decoder| is NULL, it means we've just started, and the caller + * may have specified what it expects the initial input to be. If + * that's the case, we do this extra check. + */ + if (decoder == NULL && ctx->start_input_type != NULL + && strcasecmp(ctx->start_input_type, + new_deser_inst->input_type) != 0) + continue; + + /* + * If we have a previous decoder, we check that the input type + * of the next to be used matches the type of this previous one. + * decoder_inst->input_type is a cache of the parameter "input-type" + * value for that decoder. + */ + if (decoder != NULL + && !OSSL_DECODER_is_a(decoder, new_deser_inst->input_type)) + continue; + + /* + * Checking the return value of BIO_reset() or BIO_seek() is unsafe. + * Furthermore, BIO_reset() is unsafe to use if the source BIO happens + * to be a BIO_s_mem(), because the earlier BIO_tell() gives us zero + * no matter where we are in the underlying buffer we're reading from. + * + * So, we simply do a BIO_seek(), and use BIO_tell() that we're back + * at the same position. This is a best effort attempt, but BIO_seek() + * and BIO_tell() should come as a pair... + */ + (void)BIO_seek(bio, loc); + if (BIO_tell(bio) != loc) + goto end; + + /* Recurse */ + new_data.current_deser_inst_index = i; + ok = new_deser->decode(new_deser_inst->deserctx, (OSSL_CORE_BIO *)bio, + decoder_process, &new_data, + ctx->passphrase_cb, new_data.ctx); + if (ok) + break; + } + + end: + BIO_free(new_data.bio); + return ok; +} diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c new file mode 100644 index 0000000000..2259c6348a --- /dev/null +++ b/crypto/encode_decode/decoder_meth.c @@ -0,0 +1,552 @@ +/* + * Copyright 2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core.h> +#include <openssl/core_dispatch.h> +#include <openssl/decoder.h> +#include <openssl/ui.h> +#include "internal/core.h" +#include "internal/namemap.h" +#include "internal/property.h" +#include "internal/provider.h" +#include "crypto/encoder.h" +#include "encoder_local.h" + +static void OSSL_DECODER_INSTANCE_free(OSSL_DECODER_INSTANCE *instance); + +/* + * Decoder can have multiple names, separated with colons in a name string + */ +#define NAME_SEPARATOR ':' + +/* Simple method structure constructor and destructor */ +static OSSL_DECODER *ossl_decoder_new(void) +{ + OSSL_DECODER *decoder = NULL; + + if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL + || (decoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { + OSSL_DECODER_free(decoder); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + decoder->base.refcnt = 1; + + return decoder; +} + +int OSSL_DECODER_up_ref(OSSL_DECODER *decoder) +{ + int ref = 0; + + CRYPTO_UP_REF(&decoder->base.refcnt, &ref, decoder->base.lock); + return 1; +} + +void OSSL_DECODER_free(OSSL_DECODER *decoder) +{ + int ref = 0; + + if (decoder == NULL) + return; + + CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref, decoder->base.lock); + if (ref > 0) + return; + ossl_provider_free(decoder->base.prov); + CRYPTO_THREAD_lock_free(decoder->base.lock); + OPENSSL_free(decoder); +} + +/* Permanent decoder method store, constructor and destructor */ +static void decoder_store_free(void *vstore) +{ + ossl_method_store_free(vstore); +} + +static void *decoder_store_new(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + + +static const OPENSSL_CTX_METHOD decoder_store_method = { + decoder_store_new, + decoder_store_free, +}; + +/* Data to be passed through ossl_method_construct() */ +struct decoder_data_st { + OPENSSL_CTX *libctx; + OSSL_METHOD_CONSTRUCT_METHOD *mcm; + int id; /* For get_decoder_from_store() */ + const char *names; /* For get_decoder_from_store() */ + const char *propquery; /* For get_decoder_from_store() */ +}; + +/* + * Generic routines to fetch / create DECODER methods with + * ossl_method_construct() + */ + +/* Temporary decoder method store, constructor and destructor */ +static void *alloc_tmp_decoder_store(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + +static void dealloc_tmp_decoder_store(void *store) +{ + if (store != NULL) + ossl_method_store_free(store); +} + +/* Get the permanent decoder store */ +static OSSL_METHOD_STORE *get_decoder_store(OPENSSL_CTX *libctx) +{ + return openssl_ctx_get_data(libctx, OPENSSL_CTX_DECODER_STORE_INDEX, + &decoder_store_method); +} + +/* Get decoder methods from a store, or put one in */ +static void *get_decoder_from_store(OPENSSL_CTX *libctx, void *store, + void *data) +{ + struct decoder_data_st *methdata = data; + void *method = NULL; + int id; + + if ((id = methdata->id) == 0) { + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + id = ossl_namemap_name2num(namemap, methdata->names); + } + + if (store == NULL + && (store = get_decoder_store(libctx)) == NULL) + return NULL; + + if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + return NULL; + return method; +} + +static int put_decoder_in_store(OPENSSL_CTX *libctx, void *store, + void *method, const OSSL_PROVIDER *prov, + int operation_id, const char *names, + const char *propdef, void *unused) +{ + OSSL_NAMEMAP *namemap; + int id; + + if ((namemap = ossl_namemap_stored(libctx)) == NULL + || (id = ossl_namemap_name2num(namemap, names)) == 0) + return 0; + + if (store == NULL && (store = get_decoder_store(libctx)) == NULL) + return 0; + + return ossl_method_store_add(store, prov, id, propdef, method, + (int (*)(void *))OSSL_DECODER_up_ref, + (void (*)(void *))OSSL_DECODER_free); +} + +/* Create and populate a decoder method */ +static void *decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov) +{ + OSSL_DECODER *decoder = NULL; + const OSSL_DISPATCH *fns = algodef->implementation; + + if ((decoder = ossl_decoder_new()) == NULL) + return NULL; + decoder->base.id = id; + decoder->base.propdef = algodef->property_definition; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_DECODER_NEWCTX: + if (decoder->newctx == NULL) + decoder->newctx = OSSL_FUNC_decoder_newctx(fns); + break; + case OSSL_FUNC_DECODER_FREECTX: + if (decoder->freectx == NULL) + decoder->freectx = OSSL_FUNC_decoder_freectx(fns); + break; + case OSSL_FUNC_DECODER_GET_PARAMS: + if (decoder->get_params == NULL) + decoder->get_params = + OSSL_FUNC_decoder_get_params(fns); + break; + case OSSL_FUNC_DECODER_GETTABLE_PARAMS: + if (decoder->gettable_params == NULL) + decoder->gettable_params = + OSSL_FUNC_decoder_gettable_params(fns); + break; + case OSSL_FUNC_DECODER_SET_CTX_PARAMS: + if (decoder->set_ctx_params == NULL) + decoder->set_ctx_params = + OSSL_FUNC_decoder_set_ctx_params(fns); + break; + case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS: + if (decoder->settable_ctx_params == NULL) + decoder->settable_ctx_params = + OSSL_FUNC_decoder_settable_ctx_params(fns); + break; + case OSSL_FUNC_DECODER_DECODE: + if (decoder->decode == NULL) + decoder->decode = OSSL_FUNC_decoder_decode(fns); + break; + case OSSL_FUNC_DECODER_EXPORT_OBJECT: + if (decoder->export_object == NULL) + decoder->export_object = OSSL_FUNC_decoder_export_object(fns); + break; + } + } + /* + * Try to check that the method is sensible. + * If you have a constructor, you must have a destructor and vice versa. + * You must have at least one of the encoding driver functions. + */ + if (!((decoder->newctx == NULL && decoder->freectx == NULL) + || (decoder->newctx != NULL && decoder->freectx != NULL)) + || (decoder->decode == NULL && decoder->export_object == NULL)) { + OSSL_DECODER_free(decoder); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); + return NULL; + } + + if (prov != NULL && !ossl_provider_up_ref(prov)) { + OSSL_DECODER_free(decoder); + return NULL; + } + + decoder->base.prov = prov; + return decoder; +} + + +/* + * The core fetching functionality passes the names of the implementation. + * This function is responsible to getting an identity number for them, + * then call decoder_from_dispatch() with that identity number. + */ +static void *construct_decoder(const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov, void *unused) +{ + /* + * This function is only called if get_decoder_from_store() returned + * NULL, so it's safe to say that of all the spots to create a new + * namemap entry, this is it. Should the name already exist there, we + * know that ossl_namemap_add() will return its corresponding number. + */ + OPENSSL_CTX *libctx = ossl_provider_library_context(prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *names = algodef->algorithm_names; + int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); + void *method = NULL; + + if (id != 0) + method = decoder_from_dispatch(id, algodef, prov); + + return method; +} + +/* Intermediary function to avoid ugly casts, used below */ +static void destruct_decoder(void *method, void *data) +{ + OSSL_DECODER_free(method); +} + +static int up_ref_decoder(void *method) +{ + return OSSL_DECODER_up_ref(method); +} + +static void free_decoder(void *method) +{ + OSSL_DECODER_free(method); +} + +/* Fetching support. Can fetch by numeric identity or by name */ +static OSSL_DECODER *inner_ossl_decoder_fetch(OPENSSL_CTX *libctx, int id, + const char *name, + const char *properties) +{ + OSSL_METHOD_STORE *store = get_decoder_store(libctx); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + void *method = NULL; + + if (store == NULL || namemap == NULL) + return NULL; + + /* + * If we have been passed neither a name_id or a name, we have an + * internal programming error. + */ + if (!ossl_assert(id != 0 || name != NULL)) + return NULL; + + if (id == 0) + id = ossl_namemap_name2num(namemap, name); + + if (id == 0 + || !ossl_method_store_cache_get(store, id, properties, &method)) { + OSSL_METHOD_CONSTRUCT_METHOD mcm = { + alloc_tmp_decoder_store, + dealloc_tmp_decoder_store, + get_decoder_from_store, + put_decoder_in_store, + construct_decoder, + destruct_decoder + }; + struct decoder_data_st mcmdata; + + mcmdata.libctx = libctx; + mcmdata.mcm = &mcm; + mcmdata.id = id; + mcmdata.names = name; + mcmdata.propquery = properties; + if ((method = ossl_method_construct(libctx, OSSL_OP_DECODER, + 0 /* !force_cache */, + &mcm, &mcmdata)) != NULL) { + /* + * If construction did create a method for us, we know that + * there is a correct name_id and meth_id, since those have + * already been calculated in get_decoder_from_store() and + * put_decoder_in_store() above. + */ + if (id == 0) + id = ossl_namemap_name2num(namemap, name); + ossl_method_store_cache_set(store, id, properties, method, + up_ref_decoder, free_decoder); + } + } + + return method; +} + +OSSL_DECODER *OSSL_DECODER_fetch(OPENSSL_CTX *libctx, const char *name, + const char *properties) +{ + return inner_ossl_decoder_fetch(libctx, 0, name, properties); +} + +OSSL_DECODER *ossl_decoder_fetch_by_number(OPENSSL_CTX *libctx, int id, + const char *properties) +{ + return inner_ossl_decoder_fetch(libctx, id, NULL, properties); +} + +/* + * Library of basic method functions + */ + +const OSSL_PROVIDER *OSSL_DECODER_provider(const OSSL_DECODER *decoder) +{ + if (!ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return decoder->base.prov; +} + +const char *OSSL_DECODER_properties(const OSSL_DECODER *decoder) +{ + if (!ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return decoder->base.propdef; +} + +int OSSL_DECODER_number(const OSSL_DECODER *decoder) +{ + if (!ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return decoder->base.id; +} + +int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name) +{ + if (decoder->base.prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(decoder->base.prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + return ossl_namemap_name2num(namemap, name) == decoder->base.id; + } + return 0; +} + +struct decoder_do_all_data_st { + void (*user_fn)(void *method, void *arg); + void *user_arg; +}; + +static void decoder_do_one(OSSL_PROVIDER *provider, + const OSSL_ALGORITHM *algodef, + int no_store, void *vdata) +{ + struct decoder_do_all_data_st *data = vdata; + OPENSSL_CTX *libctx = ossl_provider_library_context(provider); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *names = algodef->algorithm_names; + int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); + void *method = NULL; + + if (id != 0) + method = + decoder_from_dispatch(id, algodef, provider); + + if (method != NULL) { + data->user_fn(method, data->user_arg); + OSSL_DECODER_free(method); + } +} + +void OSSL_DECODER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_DECODER *decoder, void *arg), + void *arg) +{ + struct decoder_do_all_data_st data; + + data.user_fn = (void (*)(void *, void *))fn; + data.user_arg = arg; + ossl_algorithm_do_all(libctx, OSSL_OP_DECODER, NULL, + NULL, decoder_do_one, NULL, + &data); +} + +void OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder, + void (*fn)(const char *name, void *data), + void *data) +{ + if (decoder == NULL) + return; + + if (decoder->base.prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(decoder->base.prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + ossl_namemap_doall_names(namemap, decoder->base.id, fn, data); + } +} + +const OSSL_PARAM * +OSSL_DECODER_gettable_params(OSSL_DECODER *decoder) +{ + if (decoder != NULL && decoder->gettable_params != NULL) { + void *provctx = ossl_provider_ctx(OSSL_DECODER_provider(decoder)); + + return decoder->gettable_params(provctx); + } + return NULL; +} + +int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[]) +{ + if (decoder != NULL && decoder->get_params != NULL) + return decoder->get_params(params); + return 0; +} + +const OSSL_PARAM * +OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder) +{ + if (decoder != NULL && decoder->settable_ctx_params != NULL) { + void *provctx = ossl_provider_ctx(OSSL_DECODER_provider(decoder)); + + return decoder->settable_ctx_params(provctx); + } + return NULL; +} + +/* + * Decoder context support + */ + +/* + * |encoder| value NULL is valid, and signifies that there is no decoder. + * This is useful to provide fallback mechanisms. + * Functions that want to verify if there is a decoder can do so with + * OSSL_DECODER_CTX_get_decoder() + */ +OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void) +{ + OSSL_DECODER_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ctx->passphrase_cb = ossl_decoder_passphrase_in_cb; + return ctx; +} + +int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx, + const OSSL_PARAM params[]) +{ + size_t i; + size_t l; + + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx->decoder_insts == NULL) + return 1; + + l = (size_t)sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts); + for (i = 0; i < l; i++) { + OSSL_DECODER_INSTANCE *decoder_inst = + sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); + + if (decoder_inst->deserctx == NULL + || decoder_inst->decoder->set_ctx_params == NULL) + continue; + if (!decoder_inst->decoder->set_ctx_params(decoder_inst->deserctx, params)) + return 0; + } + return 1; +} + +static void +OSSL_DECODER_INSTANCE_free(OSSL_DECODER_INSTANCE *decoder_inst) +{ + if (decoder_inst != NULL) { + if (decoder_inst->decoder->freectx != NULL) + decoder_inst->decoder->freectx(decoder_inst->deserctx); + decoder_inst->deserctx = NULL; + OSSL_DECODER_free(decoder_inst->decoder); + decoder_inst->decoder = NULL; + OPENSSL_free(decoder_inst); + decoder_inst = NULL; + } +} + +void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx) +{ + if (ctx != NULL) { + if (ctx->cleanup != NULL) + ctx->cleanup(ctx->construct_data); + sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts, + OSSL_DECODER_INSTANCE_free); + OSSL_DECODER_CTX_set_passphrase_ui(ctx, NULL, NULL); + OSSL_DECODER_CTX_set_passphrase(ctx, NULL, 0); + OPENSSL_free(ctx); + } +} diff --git a/crypto/serializer/deserializer_pkey.c b/crypto/encode_decode/decoder_pkey.c index 6375a29e36..7f468c2476 100644 --- a/crypto/serializer/deserializer_pkey.c +++ b/crypto/encode_decode/decoder_pkey.c @@ -10,17 +10,17 @@ #include <openssl/core_names.h> #include <openssl/evp.h> #include <openssl/ui.h> -#include <openssl/deserializer.h> +#include <openssl/decoder.h> #include <openssl/safestack.h> #include "crypto/evp.h" -#include "serializer_local.h" +#include "encoder_local.h" -int OSSL_DESERIALIZER_CTX_set_passphrase(OSSL_DESERIALIZER_CTX *ctx, - const unsigned char *kstr, - size_t klen) +int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx, + const unsigned char *kstr, + size_t klen) { if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -36,7 +36,7 @@ int OSSL_DESERIALIZER_CTX_set_passphrase(OSSL_DESERIALIZER_CTX *ctx, ctx->cached_passphrase_len = klen; } if (ctx->cached_passphrase == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); return 0; } } @@ -44,7 +44,7 @@ int OSSL_DESERIALIZER_CTX_set_passphrase(OSSL_DESERIALIZER_CTX *ctx, return 1; } -static void deserializer_ctx_reset_passphrase_ui(OSSL_DESERIALIZER_CTX *ctx) +static void decoder_ctx_reset_passphrase_ui(OSSL_DECODER_CTX *ctx) { UI_destroy_method(ctx->allocated_ui_method); ctx->allocated_ui_method = NULL; @@ -52,28 +52,28 @@ static void deserializer_ctx_reset_passphrase_ui(OSSL_DESERIALIZER_CTX *ctx) ctx->ui_data = NULL; } -int OSSL_DESERIALIZER_CTX_set_passphrase_ui(OSSL_DESERIALIZER_CTX *ctx, - const UI_METHOD *ui_method, - void *ui_data) +int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx, + const UI_METHOD *ui_method, + void *ui_data) { if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } - deserializer_ctx_reset_passphrase_ui(ctx); + decoder_ctx_reset_passphrase_ui(ctx); ctx->ui_method = ui_method; ctx->ui_data = ui_data; return 1; } -int OSSL_DESERIALIZER_CTX_set_pem_password_cb(OSSL_DESERIALIZER_CTX *ctx, - pem_password_cb *cb, void *cbarg) +int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx, + pem_password_cb *cb, void *cbarg) { UI_METHOD *ui_method = NULL; if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -84,10 +84,10 @@ int OSSL_DESERIALIZER_CTX_set_pem_password_cb(OSSL_DESERIALIZER_CTX *ctx, */ if (cb == NULL || (ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0)) != NULL) { - deserializer_ctx_reset_passphrase_ui(ctx); + decoder_ctx_reset_passphrase_ui(ctx); ctx->ui_method = ctx->allocated_ui_method = ui_method; ctx->ui_data = cbarg; - ctx->passphrase_cb = ossl_deserializer_passphrase_in_cb; + ctx->passphrase_cb = ossl_decoder_passphrase_in_cb; return 1; } @@ -95,26 +95,26 @@ int OSSL_DESERIALIZER_CTX_set_pem_password_cb(OSSL_DESERIALIZER_CTX *ctx, } /* - * Support for OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY: + * Support for OSSL_DECODER_CTX_new_by_EVP_PKEY: * The construct data, and collecting keymgmt information for it */ DEFINE_STACK_OF(EVP_KEYMGMT) -struct deser_EVP_PKEY_data_st { +struct decoder_EVP_PKEY_data_st { char *object_type; /* recorded object data type, may be NULL */ void **object; /* Where the result should end up */ STACK_OF(EVP_KEYMGMT) *keymgmts; /* The EVP_KEYMGMTs we handle */ }; -static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, - const OSSL_PARAM *params, - void *construct_data) +static int decoder_construct_EVP_PKEY(OSSL_DECODER_INSTANCE *decoder_inst, + const OSSL_PARAM *params, + void *construct_data) { - struct deser_EVP_PKEY_data_st *data = construct_data; - OSSL_DESERIALIZER *deser = - OSSL_DESERIALIZER_INSTANCE_deserializer(deser_inst); - void *deserctx = OSSL_DESERIALIZER_INSTANCE_deserializer_ctx(deser_inst); + struct decoder_EVP_PKEY_data_st *data = construct_data; + OSSL_DECODER *decoder = + OSSL_DECODER_INSTANCE_decoder(decoder_inst); + void *deserctx = OSSL_DECODER_INSTANCE_decoder_ctx(decoder_inst); size_t i, end_i; /* * |object_ref| points to a provider reference to an object, its exact @@ -128,7 +128,7 @@ static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, size_t object_ref_sz = 0; const OSSL_PARAM *p; - p = OSSL_PARAM_locate_const(params, OSSL_DESERIALIZER_PARAM_DATA_TYPE); + p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_DATA_TYPE); if (p != NULL) { char *object_type = NULL; @@ -143,7 +143,7 @@ static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, * reference for the moment. This enforces that the key data itself * remains with the provider. */ - p = OSSL_PARAM_locate_const(params, OSSL_DESERIALIZER_PARAM_REFERENCE); + p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_REFERENCE); if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) return 0; object_ref = p->data; @@ -160,35 +160,35 @@ static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, * 1. If the object data type (recorded in |data->object_type|) * is defined, by checking it using EVP_KEYMGMT_is_a(). * 2. If the object data type is NOT defined, by comparing the - * EVP_KEYMGMT and OSSL_DESERIALIZER method numbers. Since - * EVP_KEYMGMT and OSSL_DESERIALIZE operate with the same + * EVP_KEYMGMT and OSSL_DECODER method numbers. Since + * EVP_KEYMGMT and OSSL_DECODE operate with the same * namemap, we know that the method numbers must match. * - * This allows individual deserializers to specify variants of keys, - * such as a DER to RSA deserializer finding a RSA-PSS key, without - * having to deserialize the exact same DER blob into the exact same + * This allows individual decoders to specify variants of keys, + * such as a DER to RSA decoder finding a RSA-PSS key, without + * having to decode the exact same DER blob into the exact same * internal structure twice. This is, of course, entirely at the - * discretion of the deserializer implementations. + * discretion of the decoder implementations. */ if (data->object_type != NULL ? EVP_KEYMGMT_is_a(keymgmt, data->object_type) - : EVP_KEYMGMT_number(keymgmt) == OSSL_DESERIALIZER_number(deser)) { + : EVP_KEYMGMT_number(keymgmt) == OSSL_DECODER_number(decoder)) { EVP_PKEY *pkey = NULL; void *keydata = NULL; const OSSL_PROVIDER *keymgmt_prov = EVP_KEYMGMT_provider(keymgmt); - const OSSL_PROVIDER *deser_prov = - OSSL_DESERIALIZER_provider(deser); + const OSSL_PROVIDER *decoder_prov = + OSSL_DECODER_provider(decoder); /* - * If the EVP_KEYMGMT and the OSSL_DESERIALIZER are from the + * If the EVP_KEYMGMT and the OSSL_DECODER are from the * same provider, we assume that the KEYMGMT has a key loading * function that can handle the provider reference we hold. * - * Otherwise, we export from the deserializer and import the + * Otherwise, we export from the decoder and import the * result in the keymgmt. */ - if (keymgmt_prov == deser_prov) { + if (keymgmt_prov == decoder_prov) { keydata = evp_keymgmt_load(keymgmt, object_ref, object_ref_sz); } else { struct evp_keymgmt_util_try_import_data_st import_data; @@ -201,9 +201,9 @@ static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, * No need to check for errors here, the value of * |import_data.keydata| is as much an indicator. */ - (void)deser->export_object(deserctx, object_ref, object_ref_sz, - &evp_keymgmt_util_try_import, - &import_data); + (void)decoder->export_object(deserctx, object_ref, object_ref_sz, + &evp_keymgmt_util_try_import, + &import_data); keydata = import_data.keydata; import_data.keydata = NULL; } @@ -225,9 +225,9 @@ static int deser_construct_EVP_PKEY(OSSL_DESERIALIZER_INSTANCE *deser_inst, return (*data->object != NULL); } -static void deser_clean_EVP_PKEY_construct_arg(void *construct_data) +static void decoder_clean_EVP_PKEY_construct_arg(void *construct_data) { - struct deser_EVP_PKEY_data_st *data = construct_data; + struct decoder_EVP_PKEY_data_st *data = construct_data; if (data != NULL) { sk_EVP_KEYMGMT_pop_free(data->keymgmts, EVP_KEYMGMT_free); @@ -239,9 +239,9 @@ static void deser_clean_EVP_PKEY_construct_arg(void *construct_data) DEFINE_STACK_OF_CSTRING() struct collected_data_st { - struct deser_EVP_PKEY_data_st *process_data; + struct decoder_EVP_PKEY_data_st *process_data; STACK_OF(OPENSSL_CSTRING) *names; - OSSL_DESERIALIZER_CTX *ctx; + OSSL_DECODER_CTX *ctx; unsigned int error_occured:1; }; @@ -280,7 +280,7 @@ static void collect_name(const char *name, void *arg) data->error_occured = 0; /* All is good now */ } -static void collect_deserializer(OSSL_DESERIALIZER *deser, void *arg) +static void collect_decoder(OSSL_DECODER *decoder, void *arg) { struct collected_data_st *data = arg; size_t i, end_i; @@ -294,37 +294,36 @@ static void collect_deserializer(OSSL_DESERIALIZER *deser, void *arg) for (i = 0; i < end_i; i++) { const char *name = sk_OPENSSL_CSTRING_value(data->names, i); - if (!OSSL_DESERIALIZER_is_a(deser, name)) + if (!OSSL_DECODER_is_a(decoder, name)) continue; - (void)OSSL_DESERIALIZER_CTX_add_deserializer(data->ctx, deser); + (void)OSSL_DECODER_CTX_add_decoder(data->ctx, decoder); } data->error_occured = 0; /* All is good now */ } -OSSL_DESERIALIZER_CTX * -OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey, - const char *input_type, - OPENSSL_CTX *libctx, - const char *propquery) +OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey, + const char *input_type, + OPENSSL_CTX *libctx, + const char *propquery) { - OSSL_DESERIALIZER_CTX *ctx = NULL; + OSSL_DECODER_CTX *ctx = NULL; struct collected_data_st *data = NULL; size_t i, end_i; - if ((ctx = OSSL_DESERIALIZER_CTX_new()) == NULL + if ((ctx = OSSL_DECODER_CTX_new()) == NULL || (data = OPENSSL_zalloc(sizeof(*data))) == NULL || (data->process_data = OPENSSL_zalloc(sizeof(*data->process_data))) == NULL || (data->process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL || (data->names = sk_OPENSSL_CSTRING_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); goto err; } data->process_data->object = (void **)pkey; data->ctx = ctx; - OSSL_DESERIALIZER_CTX_set_input_type(ctx, input_type); + OSSL_DECODER_CTX_set_input_type(ctx, input_type); /* First, find all keymgmts to form goals */ EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, data); @@ -345,30 +344,30 @@ OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey, } /* - * Finally, find all deserializers that have any keymgmt of the collected + * Finally, find all decoders that have any keymgmt of the collected * keymgmt names */ - OSSL_DESERIALIZER_do_all_provided(libctx, collect_deserializer, data); + OSSL_DECODER_do_all_provided(libctx, collect_decoder, data); if (data->error_occured) goto err; - /* If we found no deserializers to match the keymgmts, we err */ - if (OSSL_DESERIALIZER_CTX_num_deserializers(ctx) == 0) + /* If we found no decoders to match the keymgmts, we err */ + if (OSSL_DECODER_CTX_num_decoders(ctx) == 0) goto err; - /* Finally, collect extra deserializers based on what we already have */ - (void)OSSL_DESERIALIZER_CTX_add_extra(ctx, libctx, propquery); + /* Finally, collect extra decoders based on what we already have */ + (void)OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery); - if (!OSSL_DESERIALIZER_CTX_set_construct(ctx, deser_construct_EVP_PKEY) - || !OSSL_DESERIALIZER_CTX_set_construct_data(ctx, data->process_data) - || !OSSL_DESERIALIZER_CTX_set_cleanup - (ctx, deser_clean_EVP_PKEY_construct_arg)) + if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_EVP_PKEY) + || !OSSL_DECODER_CTX_set_construct_data(ctx, data->process_data) + || !OSSL_DECODER_CTX_set_cleanup(ctx, + decoder_clean_EVP_PKEY_construct_arg)) goto err; data->process_data = NULL; err: - deser_clean_EVP_PKEY_construct_arg(data->process_data); + decoder_clean_EVP_PKEY_construct_arg(data->process_data); sk_OPENSSL_CSTRING_free(data->names); OPENSSL_free(data); return ctx; diff --git a/crypto/encode_decode/encoder_err.c b/crypto/encode_decode/encoder_err.c new file mode 100644 index 0000000000..5416f8390e --- /dev/null +++ b/crypto/encode_decode/encoder_err.c @@ -0,0 +1,33 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/err.h> +#include <openssl/encodererr.h> + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OSSL_ENCODER_str_reasons[] = { + {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY), + "incorrect property query"}, + {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, OSSL_ENCODER_R_ENCODER_NOT_FOUND), + "encoder not found"}, + {0, NULL} +}; + +#endif + +int ERR_load_OSSL_ENCODER_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_reason_error_string(OSSL_ENCODER_str_reasons[0].error) == NULL) + ERR_load_strings_const(OSSL_ENCODER_str_reasons); +#endif + return 1; +} diff --git a/crypto/serializer/serializer_lib.c b/crypto/encode_decode/encoder_lib.c index 932ef1e3ae..b083fa2d4c 100644 --- a/crypto/serializer/serializer_lib.c +++ b/crypto/encode_decode/encoder_lib.c @@ -8,10 +8,10 @@ */ #include <openssl/bio.h> -#include <openssl/serializer.h> -#include "serializer_local.h" +#include <openssl/encoder.h> +#include "encoder_local.h" -int OSSL_SERIALIZER_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out) +int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out) { return ctx->do_output(ctx, out); } @@ -22,20 +22,20 @@ static BIO *bio_from_file(FILE *fp) BIO *b; if ((b = BIO_new(BIO_s_file())) == NULL) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_BUF_LIB); return NULL; } BIO_set_fp(b, fp, BIO_NOCLOSE); return b; } -int OSSL_SERIALIZER_to_fp(OSSL_SERIALIZER_CTX *ctx, FILE *fp) +int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp) { BIO *b = bio_from_file(fp); int ret = 0; if (b != NULL) - ret = OSSL_SERIALIZER_to_bio(ctx, b); + ret = OSSL_ENCODER_to_bio(ctx, b); BIO_free(b); return ret; diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h new file mode 100644 index 0000000000..34931d4e43 --- /dev/null +++ b/crypto/encode_decode/encoder_local.h @@ -0,0 +1,140 @@ +/* + * Copyright 2019-2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core_dispatch.h> +#include <openssl/types.h> +#include <openssl/safestack.h> +#include <openssl/encoder.h> +#include <openssl/decoder.h> +#include "internal/cryptlib.h" +#include "internal/refcount.h" + +struct ossl_serdes_base_st { + OSSL_PROVIDER *prov; + int id; + const char *propdef; + + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; +}; + +struct ossl_encoder_st { + struct ossl_serdes_base_st base; + OSSL_FUNC_encoder_newctx_fn *newctx; + OSSL_FUNC_encoder_freectx_fn *freectx; + OSSL_FUNC_encoder_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_encoder_settable_ctx_params_fn *settable_ctx_params; + OSSL_FUNC_encoder_encode_data_fn *encode_data; + OSSL_FUNC_encoder_encode_object_fn *encode_object; +}; + +struct ossl_decoder_st { + struct ossl_serdes_base_st base; + OSSL_FUNC_decoder_newctx_fn *newctx; + OSSL_FUNC_decoder_freectx_fn *freectx; + OSSL_FUNC_decoder_get_params_fn *get_params; + OSSL_FUNC_decoder_gettable_params_fn *gettable_params; + OSSL_FUNC_decoder_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_decoder_settable_ctx_params_fn *settable_ctx_params; + OSSL_FUNC_decoder_decode_fn *decode; + OSSL_FUNC_decoder_export_object_fn *export_object; +}; + +struct ossl_encoder_ctx_st { + OSSL_ENCODER *encoder; + void *serctx; + + int selection; + + /*- + * Output / encoding data, used by OSSL_ENCODER_to_{bio,fp} + * + * |object| is the libcrypto object to handle. + * |do_output| performs the actual encoding. + * + * |do_output| must have intimate knowledge of |object|. + */ + const void *object; + int (*do_output)(OSSL_ENCODER_CTX *ctx, BIO *out); + + /* For any function that needs a passphrase reader */ + const UI_METHOD *ui_method; + void *ui_data; + /* + * if caller used OSSL_ENCODER_CTX_set_passphrase_cb(), we need + * intermediary storage. + */ + UI_METHOD *allocated_ui_method; +}; + +struct ossl_decoder_instance_st { + OSSL_DECODER *decoder; /* Never NULL */ + void *deserctx; /* Never NULL */ + const char *input_type; /* Never NULL */ +}; + +DEFINE_STACK_OF(OSSL_DECODER_INSTANCE) + +struct ossl_decoder_ctx_st { + /* + * The caller may know the input type of the data they pass. If not, + * this will remain NULL and the decoding functionality will start + * with trying to decode with any desencoder in |decoder_insts|, + * regardless of their respective input type. + */ + const char *start_input_type; + + /* + * Decoders that are components of any current decoding path. + */ + STACK_OF(OSSL_DECODER_INSTANCE) *decoder_insts; + + /* + * The constructors of a decoding, and its caller argument. + */ + OSSL_DECODER_CONSTRUCT *construct; + OSSL_DECODER_CLEANUP *cleanup; + void *construct_data; + + /* For any function that needs a passphrase reader */ + OSSL_PASSPHRASE_CALLBACK *passphrase_cb; + const UI_METHOD *ui_method; + void *ui_data; + /* + * if caller used OSSL_ENCODER_CTX_set_pem_password_cb(), we need + * intermediary storage. + */ + UI_METHOD *allocated_ui_method; + /* + * Because the same input may pass through more than one decoder, + * we cache any passphrase passed to us. The desrializing processor + * must clear this at the end of a run. + */ + unsigned char *cached_passphrase; + size_t cached_passphrase_len; + + /* + * Flag section. Keep these together + */ + + /* + * The passphrase was passed to us by the user. In that case, it + * should only be freed when freeing this context. + */ + unsigned int flag_user_passphrase:1; +}; + +/* Passphrase callbacks, found in serdes_pass.c */ + +/* + * Encoders typically want to get an outgoing passphrase, while + * decoders typically want to get en incoming passphrase. + */ +OSSL_PASSPHRASE_CALLBACK ossl_encoder_passphrase_out_cb; +OSSL_PASSPHRASE_CALLBACK ossl_decoder_passphrase_in_cb; diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c new file mode 100644 index 0000000000..ef3c24433e --- /dev/null +++ b/crypto/encode_decode/encoder_meth.c @@ -0,0 +1,523 @@ +/* + * Copyright 2019-2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core.h> +#include <openssl/core_dispatch.h> +#include <openssl/encoder.h> +#include <openssl/ui.h> +#include "internal/core.h" +#include "internal/namemap.h" +#include "internal/property.h" +#include "internal/provider.h" +#include "crypto/encoder.h" +#include "encoder_local.h" + +/* + * Encoder can have multiple names, separated with colons in a name string + */ +#define NAME_SEPARATOR ':' + +/* Simple method structure constructor and destructor */ +static OSSL_ENCODER *ossl_encoder_new(void) +{ + OSSL_ENCODER *encoder = NULL; + + if ((encoder = OPENSSL_zalloc(sizeof(*encoder))) == NULL + || (encoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { + OSSL_ENCODER_free(encoder); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + encoder->base.refcnt = 1; + + return encoder; +} + +int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder) +{ + int ref = 0; + + CRYPTO_UP_REF(&encoder->base.refcnt, &ref, encoder->base.lock); + return 1; +} + +void OSSL_ENCODER_free(OSSL_ENCODER *encoder) +{ + int ref = 0; + + if (encoder == NULL) + return; + + CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref, encoder->base.lock); + if (ref > 0) + return; + ossl_provider_free(encoder->base.prov); + CRYPTO_THREAD_lock_free(encoder->base.lock); + OPENSSL_free(encoder); +} + +/* Permanent encoder method store, constructor and destructor */ +static void encoder_store_free(void *vstore) +{ + ossl_method_store_free(vstore); +} + +static void *encoder_store_new(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + + +static const OPENSSL_CTX_METHOD encoder_store_method = { + encoder_store_new, + encoder_store_free, +}; + +/* Data to be passed through ossl_method_construct() */ +struct encoder_data_st { + OPENSSL_CTX *libctx; + OSSL_METHOD_CONSTRUCT_METHOD *mcm; + int id; /* For get_encoder_from_store() */ + const char *names; /* For get_encoder_from_store() */ + const char *propquery; /* For get_encoder_from_store() */ +}; + +/* + * Generic routines to fetch / create ENCODER methods with + * ossl_method_construct() + */ + +/* Temporary encoder method store, constructor and destructor */ +static void *alloc_tmp_encoder_store(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + +static void dealloc_tmp_encoder_store(void *store) +{ + if (store != NULL) + ossl_method_store_free(store); +} + +/* Get the permanent encoder store */ +static OSSL_METHOD_STORE *get_encoder_store(OPENSSL_CTX *libctx) +{ + return openssl_ctx_get_data(libctx, OPENSSL_CTX_ENCODER_STORE_INDEX, + &encoder_store_method); +} + +/* Get encoder methods from a store, or put one in */ +static void *get_encoder_from_store(OPENSSL_CTX *libctx, void *store, + void *data) +{ + struct encoder_data_st *methdata = data; + void *method = NULL; + int id; + + if ((id = methdata->id) == 0) { + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + id = ossl_namemap_name2num(namemap, methdata->names); + } + + if (store == NULL + && (store = get_encoder_store(libctx)) == NULL) + return NULL; + + if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + return NULL; + return method; +} + +static int put_encoder_in_store(OPENSSL_CTX *libctx, void *store, + void *method, const OSSL_PROVIDER *prov, + int operation_id, const char *names, + const char *propdef, void *unused) +{ + OSSL_NAMEMAP *namemap; + int id; + + if ((namemap = ossl_namemap_stored(libctx)) == NULL + || (id = ossl_namemap_name2num(namemap, names)) == 0) + return 0; + + if (store == NULL && (store = get_encoder_store(libctx)) == NULL) + return 0; + + return ossl_method_store_add(store, prov, id, propdef, method, + (int (*)(void *))OSSL_ENCODER_up_ref, + (void (*)(void *))OSSL_ENCODER_free); +} + +/* Create and populate a encoder method */ +static void *encoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov) +{ + OSSL_ENCODER *encoder = NULL; + const OSSL_DISPATCH *fns = algodef->implementation; + + if ((encoder = ossl_encoder_new()) == NULL) + return NULL; + encoder->base.id = id; + encoder->base.propdef = algodef->property_definition; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_ENCODER_NEWCTX: + if (encoder->newctx == NULL) + encoder->newctx = + OSSL_FUNC_encoder_newctx(fns); + break; + case OSSL_FUNC_ENCODER_FREECTX: + if (encoder->freectx == NULL) + encoder->freectx = + OSSL_FUNC_encoder_freectx(fns); + break; + case OSSL_FUNC_ENCODER_SET_CTX_PARAMS: + if (encoder->set_ctx_params == NULL) + encoder->set_ctx_params = + OSSL_FUNC_encoder_set_ctx_params(fns); + break; + case OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS: + if (encoder->settable_ctx_params == NULL) + encoder->settable_ctx_params = + OSSL_FUNC_encoder_settable_ctx_params(fns); + break; + case OSSL_FUNC_ENCODER_ENCODE_DATA: + if (encoder->encode_data == NULL) + encoder->encode_data = + OSSL_FUNC_encoder_encode_data(fns); + break; + case OSSL_FUNC_ENCODER_ENCODE_OBJECT: + if (encoder->encode_object == NULL) + encoder->encode_object = + OSSL_FUNC_encoder_encode_object(fns); + break; + } + } + /* + * Try to check that the method is sensible. + * If you have a constructor, you must have a destructor and vice versa. + * You must have at least one of the encoding driver functions. + */ + if (!((encoder->newctx == NULL && encoder->freectx == NULL) + || (encoder->newctx != NULL && encoder->freectx != NULL)) + || (encoder->encode_data == NULL && encoder->encode_object == NULL)) { + OSSL_ENCODER_free(encoder); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); + return NULL; + } + + if (prov != NULL && !ossl_provider_up_ref(prov)) { + OSSL_ENCODER_free(encoder); + return NULL; + } + + encoder->base.prov = prov; + return encoder; +} + + +/* + * The core fetching functionality passes the names of the implementation. + * This function is responsible to getting an identity number for them, + * then call encoder_from_dispatch() with that identity number. + */ +static void *construct_encoder(const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov, void *unused) +{ + /* + * This function is only called if get_encoder_from_store() returned + * NULL, so it's safe to say that of all the spots to create a new + * namemap entry, this is it. Should the name already exist there, we + * know that ossl_namemap_add() will return its corresponding number. + */ + OPENSSL_CTX *libctx = ossl_provider_library_context(prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *names = algodef->algorithm_names; + int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); + void *method = NULL; + + if (id != 0) + method = encoder_from_dispatch(id, algodef, prov); + + return method; +} + +/* Intermediary function to avoid ugly casts, used below */ +static void destruct_encoder(void *method, void *data) +{ + OSSL_ENCODER_free(method); +} + +static int up_ref_encoder(void *method) +{ + return OSSL_ENCODER_up_ref(method); +} + +static void free_encoder(void *method) +{ + OSSL_ENCODER_free(method); +} + +/* Fetching support. Can fetch by numeric identity or by name */ +static OSSL_ENCODER *inner_ossl_encoder_fetch(OPENSSL_CTX *libctx, + int id, const char *name, + const char *properties) +{ + OSSL_METHOD_STORE *store = get_encoder_store(libctx); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + void *method = NULL; + + if (store == NULL || namemap == NULL) + return NULL; + + /* + * If we have been passed neither a name_id or a name, we have an + * internal programming error. + */ + if (!ossl_assert(id != 0 || name != NULL)) + return NULL; + + if (id == 0) + id = ossl_namemap_name2num(namemap, name); + + if (id == 0 + || !ossl_method_store_cache_get(store, id, properties, &method)) { + OSSL_METHOD_CONSTRUCT_METHOD mcm = { + alloc_tmp_encoder_store, + dealloc_tmp_encoder_store, + get_encoder_from_store, + put_encoder_in_store, + construct_encoder, + destruct_encoder + }; + struct encoder_data_st mcmdata; + + mcmdata.libctx = libctx; + mcmdata.mcm = &mcm; + mcmdata.id = id; + mcmdata.names = name; + mcmdata.propquery = properties; + if ((method = ossl_method_construct(libctx, OSSL_OP_ENCODER, + 0 /* !force_cache */, + &mcm, &mcmdata)) != NULL) { + /* + * If construction did create a method for us, we know that + * there is a correct name_id and meth_id, since those have + * already been calculated in get_encoder_from_store() and + * put_encoder_in_store() above. + */ + if (id == 0) + id = ossl_namemap_name2num(namemap, name); + ossl_method_store_cache_set(store, id, properties, method, + up_ref_encoder, free_encoder); + } + } + + return method; +} + +OSSL_ENCODER *OSSL_ENCODER_fetch(OPENSSL_CTX *libctx, const char *name, + const char *properties) +{ + return inner_ossl_encoder_fetch(libctx, 0, name, properties); +} + +OSSL_ENCODER *ossl_encoder_fetch_by_number(OPENSSL_CTX *libctx, int id, + const char *properties) +{ + return inner_ossl_encoder_fetch(libctx, id, NULL, properties); +} + +/* + * Library of basic method functions + */ + +const OSSL_PROVIDER *OSSL_ENCODER_provider(const OSSL_ENCODER *encoder) +{ + if (!ossl_assert(encoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return encoder->base.prov; +} + +const char *OSSL_ENCODER_properties(const OSSL_ENCODER *encoder) +{ + if (!ossl_assert(encoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return encoder->base.propdef; +} + +int OSSL_ENCODER_number(const OSSL_ENCODER *encoder) +{ + if (!ossl_assert(encoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return encoder->base.id; +} + +int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name) +{ + if (encoder->base.prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(encoder->base.prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + return ossl_namemap_name2num(namemap, name) == encoder->base.id; + } + return 0; +} + +struct encoder_do_all_data_st { + void (*user_fn)(void *method, void *arg); + void *user_arg; +}; + +static void encoder_do_one(OSSL_PROVIDER *provider, + const OSSL_ALGORITHM *algodef, + int no_store, void *vdata) +{ + struct encoder_do_all_data_st *data = vdata; + OPENSSL_CTX *libctx = ossl_provider_library_context(provider); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *names = algodef->algorithm_names; + int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); + void *method = NULL; + + if (id != 0) + method = + encoder_from_dispatch(id, algodef, provider); + + if (method != NULL) { + data->user_fn(method, data->user_arg); + OSSL_ENCODER_free(method); + } +} + +void OSSL_ENCODER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_ENCODER *encoder, void *arg), + void *arg) +{ + struct encoder_do_all_data_st data; + + data.user_fn = (void (*)(void *, void *))fn; + data.user_arg = arg; + + /* + * No pre- or post-condition for this call, as this only creates methods + * temporarly and then promptly destroys them. + */ + ossl_algorithm_do_all(libctx, OSSL_OP_ENCODER, NULL, NULL, + encoder_do_one, NULL, &data); +} + +void OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder, + void (*fn)(const char *name, void *data), + void *data) +{ + if (encoder == NULL) + return; + + if (encoder->base.prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(encoder->base.prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + ossl_namemap_doall_names(namemap, encoder->base.id, fn, data); + } +} + +const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder) +{ + if (encoder != NULL && encoder->settable_ctx_params != NULL) { + void *provctx = ossl_provider_ctx(OSSL_ENCODER_provider(encoder)); + + return encoder->settable_ctx_params(provctx); + } + return NULL; +} + +/* + * Encoder context support + */ + +/* + * |encoder| value NULL is valid, and signifies that there is no encoder. + * This is useful to provide fallback mechanisms. + * Functions that want to verify if there is a encoder can do so with + * OSSL_ENCODER_CTX_get_encoder() + */ +OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(OSSL_ENCODER *encoder) +{ + OSSL_ENCODER_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ctx->encoder = encoder; + if (encoder != NULL && encoder->newctx != NULL) { + const OSSL_PROVIDER *prov = OSSL_ENCODER_provider(encoder); + void *provctx = ossl_provider_ctx(prov); + + if (OSSL_ENCODER_up_ref(encoder)) { + ctx->serctx = encoder->newctx(provctx); + } else { + OSSL_ENCODER_free(encoder); + OPENSSL_free(ctx); + ctx = NULL; + } + } + + return ctx; +} + +const OSSL_ENCODER * +OSSL_ENCODER_CTX_get_encoder(OSSL_ENCODER_CTX *ctx) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ctx->encoder; +} + + +int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx, + const OSSL_PARAM params[]) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx->encoder != NULL && ctx->encoder->set_ctx_params != NULL) + return ctx->encoder->set_ctx_params(ctx->serctx, params); + return 0; +} + +void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx) +{ + if (ctx != NULL) { + if (ctx->encoder != NULL && ctx->encoder->freectx != NULL) + ctx->encoder->freectx(ctx->serctx); + OSSL_ENCODER_free(ctx->encoder); + UI_destroy_method(ctx->allocated_ui_method); + OPENSSL_free(ctx); + } +} diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c new file mode 100644 index 0000000000..dc776c023e --- /dev/null +++ b/crypto/encode_decode/encoder_pkey.c @@ -0,0 +1,276 @@ +/* + * Copyright 2019-2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/err.h> +#include <openssl/ui.h> +#include <openssl/params.h> +#include <openssl/encoder.h> +#include <openssl/core_names.h> +#include <openssl/safestack.h> +#include "internal/provider.h" +#include "internal/property.h" +#include "crypto/evp.h" +#include "encoder_local.h" + +DEFINE_STACK_OF_CSTRING() + +int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx, + const char *cipher_name, + const char *propquery) +{ + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_CIPHER, + (void *)cipher_name, 0); + params[1] = + OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, + (void *)propquery, 0); + + return OSSL_ENCODER_CTX_set_params(ctx, params); +} + +int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx, + const unsigned char *kstr, + size_t klen) +{ + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_ENCODER_PARAM_PASS, + (void *)kstr, klen); + + return OSSL_ENCODER_CTX_set_params(ctx, params); +} + +static void encoder_ctx_reset_passphrase_ui(OSSL_ENCODER_CTX *ctx) +{ + UI_destroy_method(ctx->allocated_ui_method); + ctx->allocated_ui_method = NULL; + ctx->ui_method = NULL; + ctx->ui_data = NULL; +} + +int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx, + const UI_METHOD *ui_method, + void *ui_data) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + encoder_ctx_reset_passphrase_ui(ctx); + ctx->ui_method = ui_method; + ctx->ui_data = ui_data; + return 1; +} + +int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx, + pem_password_cb *cb, void *cbarg) +{ + if (!ossl_assert(ctx != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + encoder_ctx_reset_passphrase_ui(ctx); + if (cb == NULL) + return 1; + ctx->ui_method = + ctx->allocated_ui_method = UI_UTIL_wrap_read_pem_callback(cb, 1); + ctx->ui_data = cbarg; + + return ctx->ui_method != NULL; +} + +/* + * Support for OSSL_ENCODER_CTX_new_by_TYPE: + * finding a suitable encoder + */ + +struct selected_encoder_st { + STACK_OF(OPENSSL_CSTRING) *names; + int error; +}; + +static void cache_encoders(const char *name, void *data) +{ + struct selected_encoder_st *d = data; + + if (sk_OPENSSL_CSTRING_push(d->names, name) <= 0) + d->error = 1; +} + +/* + * Support for OSSL_ENCODER_to_bio: + * writing callback for the OSSL_PARAM (the implementation doesn't have + * intimate knowledge of the provider side object) + */ + +struct encoder_write_data_st { + OSSL_ENCODER_CTX *ctx; + BIO *out; +}; + +static int encoder_write_cb(const OSSL_PARAM params[], void *arg) +{ + struct encoder_write_data_st *write_data = arg; + OSSL_ENCODER_CTX *ctx = write_data->ctx; + BIO *out = write_data->out; + + return ctx->encoder->encode_data(ctx->serctx, params, (OSSL_CORE_BIO *)out, + ossl_encoder_passphrase_out_cb, ctx); +} + +/* + * Support for OSSL_ENCODER_to_bio: + * Perform the actual output. + */ + +static int encoder_EVP_PKEY_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out) +{ + const EVP_PKEY *pkey = ctx->object; + void *keydata = pkey->keydata; + EVP_KEYMGMT *keymgmt = pkey->keymgmt; + + /* + * OSSL_ENCODER_CTX_new() creates a context, even when the + * encoder it's given is NULL. Callers can detect the lack + * of encoder with OSSL_ENCODER_CTX_get_encoder() and + * should take precautions, possibly call a fallback instead of + * OSSL_ENCODER_to_bio() / OSSL_ENCODER_to_fp(). If it's + * come this far, we return an error. + */ + if (ctx->encoder == NULL) + return 0; + + if (ctx->encoder->encode_object == NULL + || (OSSL_ENCODER_provider(ctx->encoder) + != EVP_KEYMGMT_provider(keymgmt))) { + struct encoder_write_data_st write_data; + + write_data.ctx = ctx; + write_data.out = out; + + return evp_keymgmt_export(keymgmt, keydata, ctx->selection, + &encoder_write_cb, &write_data); + } + + return ctx->encoder->encode_object(ctx->serctx, keydata, + (OSSL_CORE_BIO *)out, + ossl_encoder_passphrase_out_cb, ctx); +} + +/* + * OSSL_ENCODER_CTX_new_by_EVP_PKEY() returns a ctx with no encoder if + * it couldn't find a suitable encoder. This allows a caller to detect if + * a suitable encoder was found, with OSSL_ENCODER_CTX_get_encoder(), + * and to use fallback methods if the result is NULL. + */ +OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey, + const char *propquery) +{ + OSSL_ENCODER_CTX *ctx = NULL; + OSSL_ENCODER *encoder = NULL; + EVP_KEYMGMT *keymgmt = pkey->keymgmt; + int selection = OSSL_KEYMGMT_SELECT_ALL; + + if (!ossl_assert(pkey != NULL && propquery != NULL)) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (keymgmt != NULL) { + const OSSL_PROVIDER *desired_prov = EVP_KEYMGMT_provider(keymgmt); + OPENSSL_CTX *libctx = ossl_provider_library_context(desired_prov); + struct selected_encoder_st sel_data; + OSSL_ENCODER *first = NULL; + const char *name; + int i; + + /* + * Select the encoder in two steps. First, get the names of all of + * the encoders. Then determine which is the best one to use. + * This has to be broken because it isn't possible to fetch the + * serialisers inside EVP_KEYMGMT_names_do_all() due to locking + * order inversions with the store lock. + */ + sel_data.error = 0; + sel_data.names = sk_OPENSSL_CSTRING_new_null(); + if (sel_data.names == NULL) + return NULL; + EVP_KEYMGMT_names_do_all(keymgmt, cache_encoders, &sel_data); + /* + * Ignore memory allocation errors that are indicated in sel_data.error + * in case a suitable provider does get found regardless. + */ + + /* + * Encoders offer two functions, one that handles object data in + * the form of a OSSL_PARAM array, and one that directly handles a + * provider side object. The latter requires that the encoder + * is offered by the same provider that holds that object, but is + * more desirable because it usually provides faster encoding. + * + * When looking up possible encoders, we save the first that can + * handle an OSSL_PARAM array in |first| and use that if nothing + * better turns up. + */ + for (i = 0; i < sk_OPENSSL_CSTRING_num(sel_data.names); i++) { + name = sk_OPENSSL_CSTRING_value(sel_data.names, i); + encoder = OSSL_ENCODER_fetch(libctx, name, propquery); + if (encoder != NULL) { + if (OSSL_ENCODER_provider(encoder) == desired_prov + && encoder->encode_object != NULL) { + OSSL_ENCODER_free(first); + break; + } + if (first == NULL && encoder->encode_data != NULL) + first = encoder; + else + OSSL_ENCODER_free(encoder); + encoder = NULL; + } + } + sk_OPENSSL_CSTRING_free(sel_data.names); + if (encoder == NULL) + encoder = first; + + if (encoder != NULL) { + OSSL_PROPERTY_LIST *check = NULL, *current_props = NULL; + + check = ossl_parse_query(libctx, "type=parameters"); + current_props = + ossl_parse_property(libctx, OSSL_ENCODER_properties(encoder)); + if (ossl_property_match_count(check, current_props) > 0) + selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; + ossl_property_free(current_props); + ossl_property_free(check); + } else { + if (sel_data.error) + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + else + ERR_raise(ERR_LIB_OSSL_ENCODER, + OSSL_ENCODER_R_ENCODER_NOT_FOUND); + } + } + + ctx = OSSL_ENCODER_CTX_new(encoder); /* refcnt(encoder)++ */ + OSSL_ENCODER_free(encoder); /* refcnt(encoder)-- */ + + if (ctx != NULL) { + /* Setup for OSSL_ENCODE_to_bio() */ + ctx->selection = selection; + ctx->object = pkey; + ctx->do_output = encoder_EVP_PKEY_to_bio; + } + + return ctx; +} + diff --git a/crypto/serializer/serdes_pass.c b/crypto/encode_decode/endecode_pass.c index 75200955b5..113f5eeb84 100644 --- a/crypto/serializer/serdes_pass.c +++ b/crypto/encode_decode/endecode_pass.c @@ -11,7 +11,7 @@ #include <openssl/ui.h> #include <openssl/core_names.h> #include "internal/cryptlib.h" -#include "serializer_local.h" +#include "encoder_local.h" /* Passphrase callbacks for any who need it */ @@ -56,7 +56,7 @@ static int do_passphrase(char *pass, size_t pass_size, size_t *pass_len, /* Get an application constructed prompt */ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); - if (prompt == NULL) { + if (prompt == NULL) { ERR_raise(errlib, ERR_R_MALLOC_FAILURE); goto end; } @@ -107,33 +107,33 @@ static int do_passphrase(char *pass, size_t pass_size, size_t *pass_len, } /* - * Serializers typically want to get an outgoing passphrase, while - * deserializers typically want to get en incoming passphrase. + * Encoders typically want to get an outgoing passphrase, while + * decoders typically want to get en incoming passphrase. */ -int ossl_serializer_passphrase_out_cb(char *pass, size_t pass_size, - size_t *pass_len, - const OSSL_PARAM params[], void *arg) +int ossl_encoder_passphrase_out_cb(char *pass, size_t pass_size, + size_t *pass_len, + const OSSL_PARAM params[], void *arg) { - OSSL_SERIALIZER_CTX *ctx = arg; + OSSL_ENCODER_CTX *ctx = arg; if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } return do_passphrase(pass, pass_size, pass_len, params, arg, 1, ctx->ui_method, ctx->ui_data, - ERR_LIB_OSSL_SERIALIZER); + ERR_LIB_OSSL_ENCODER); } -int ossl_deserializer_passphrase_in_cb(char *pass, size_t pass_size, - size_t *pass_len, - const OSSL_PARAM params[], void *arg) +int ossl_decoder_passphrase_in_cb(char *pass, size_t pass_size, + size_t *pass_len, + const OSSL_PARAM params[], void *arg) { - OSSL_DESERIALIZER_CTX *ctx = arg; + OSSL_DECODER_CTX *ctx = arg; if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -147,13 +147,13 @@ int ossl_deserializer_passphrase_in_cb(char *pass, size_t pass_size, return 1; } else { if ((ctx->cached_passphrase = OPENSSL_zalloc(pass_size)) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); return 0; } } if (do_passphrase(pass, pass_size, pass_len, params, arg, 0, ctx->ui_method, ctx->ui_data, - ERR_LIB_OSSL_DESERIALIZER)) { + ERR_LIB_OSSL_DECODER)) { memcpy(ctx->cached_passphrase, pass, *pass_len); ctx->cached_passphrase_len = *pass_len; return 1; diff --git a/crypto/err/err.c b/crypto/err/err.c index e2d70d7a58..9098112d1c 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -75,8 +75,8 @@ static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"}, {ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"}, {ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"}, - {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, 0), "SERIALIZER routines"}, - {ERR_PACK(ERR_LIB_OSSL_DESERIALIZER, 0, 0), "DESERIALIZER routines"}, + {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, 0), "ENCODER routines"}, + {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, 0), "DECODER routines"}, {ERR_PACK(ERR_LIB_HTTP, 0, 0), "HTTP routines"}, {0, NULL}, }; diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index f1bed12795..037611d759 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -40,16 +40,16 @@ L OSSL_STORE include/openssl/store.h crypto/store/store_err.c L ESS include/openssl/ess.h crypto/ess/ess_err.c L PROP include/internal/property.h crypto/property/property_err.c L PROV providers/common/include/prov/providercommon.h providers/common/provider_err.c -L OSSL_SERIALIZER include/openssl/serializer.h crypto/serializer/serializer_err.c -L OSSL_DESERIALIZER include/openssl/deserializer.h crypto/serializer/deserializer_err.c +L OSSL_ENCODER include/openssl/encoder.h crypto/encoder/encoder_err.c +L OSSL_DECODER include/openssl/decoder.h crypto/encoder/decoder_err.c L HTTP include/openssl/http.h crypto/http/http_err.c # additional header files to be scanned for function names L NONE include/openssl/x509_vfy.h NONE -L NONE crypto/ec/ec_local.h NONE -L NONE crypto/cms/cms_local.h NONE -L NONE crypto/ct/ct_local.h NONE -L NONE ssl/ssl_local.h NONE +L NONE crypto/ec/ec_local.h NONE +L NONE crypto/cms/cms_local.h NONE +L NONE crypto/ct/ct_local.h NONE +L NONE ssl/ssl_local.h NONE # SSL/TLS alerts R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 10531ead7a..3a5a5b5692 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2702,9 +2702,9 @@ OCSP_R_STATUS_TOO_OLD:127:status too old OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest OCSP_R_UNKNOWN_NID:120:unknown nid OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type -OSSL_DESERIALIZER_R_MISSING_GET_PARAMS:100:missing get params -OSSL_SERIALIZER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query -OSSL_SERIALIZER_R_SERIALIZER_NOT_FOUND:101:serializer not found +OSSL_DECODER_R_MISSING_GET_PARAMS:100:missing get params +OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query +OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index bee6337a88..7a79816788 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -29,7 +29,7 @@ #include <openssl/engine.h> #include <openssl/params.h> #include <openssl/param_build.h> -#include <openssl/serializer.h> +#include <openssl/encoder.h> #include <openssl/core_names.h> #include "crypto/asn1.h" @@ -1143,23 +1143,23 @@ static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, } static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent, - const char *propquery /* For provided serialization */, + const char *propquery /* For provided encoding */, int (*legacy_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx), ASN1_PCTX *legacy_pctx /* For legacy print */) { int pop_f_prefix; long saved_indent; - OSSL_SERIALIZER_CTX *ctx = NULL; + OSSL_ENCODER_CTX *ctx = NULL; int ret = -2; /* default to unsupported */ if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent)) return 0; - ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, propquery); - if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL) - ret = OSSL_SERIALIZER_to_bio(ctx, out); - OSSL_SERIALIZER_CTX_free(ctx); + ctx = OSSL_ENCODER_CTX_new_by_EVP_PKEY(pkey, propquery); + if (OSSL_ENCODER_CTX_get_encoder(ctx) != NULL) + ret = OSSL_ENCODER_to_bio(ctx, out); + OSSL_ENCODER_CTX_free(ctx); if (ret != -2) goto end; @@ -1178,7 +1178,7 @@ static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent, int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ, + return print_pkey(pkey, out, indent, OSSL_ENCODER_PUBKEY_TO_TEXT_PQ, (pkey->ameth != NULL ? pkey->ameth->pub_print : NULL), pctx); } @@ -1186,7 +1186,7 @@ int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ, + return print_pkey(pkey, out, indent, OSSL_ENCODER_PrivateKey_TO_TEXT_PQ, (pkey->ameth != NULL ? pkey->ameth->priv_print : NULL), pctx); } @@ -1194,7 +1194,7 @@ int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - return print_pkey(pkey, out, indent, OSSL_SERIALIZER_Parameters_TO_TEXT_PQ, + return print_pkey(pkey, out, indent, OSSL_ENCODER_Parameters_TO_TEXT_PQ, (pkey->ameth != NULL ? pkey->ameth->param_print : NULL), pctx); } diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 1ab309329d..2f9346d998 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -27,7 +27,6 @@ /* TODO(3.0) remove when provider SM2 key generation is implemented */ #ifdef TMP_SM2_HACK # include <openssl/ec.h> -# include <openssl/serializer.h> # include "internal/sizes.h" #endif diff --git a/crypto/pem/pem_local.h b/crypto/pem/pem_local.h index 2fb1e6f4d5..81d1718e32 100644 --- a/crypto/pem/pem_local.h +++ b/crypto/pem/pem_local.h @@ -13,17 +13,17 @@ */ #include <openssl/pem.h> -#include <openssl/serializer.h> +#include <openssl/encoder.h> -/* Alternative IMPLEMENT macros for provided serializers */ +/* Alternative IMPLEMENT macros for provided encoders */ # define IMPLEMENT_PEM_provided_write_body_vars(type, asn1) \ int ret = 0; \ - const char *pq = OSSL_SERIALIZER_##asn1##_TO_PEM_PQ; \ - OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_##type(x, pq); \ + const char *pq = OSSL_ENCODER_##asn1##_TO_PEM_PQ; \ + OSSL_ENCODER_CTX *ctx = OSSL_ENCODER_CTX_new_by_##type(x, pq); \ \ - if (ctx != NULL && OSSL_SERIALIZER_CTX_get_serializer(ctx) == NULL) { \ - OSSL_SERIALIZER_CTX_free(ctx); \ + if (ctx != NULL && OSSL_ENCODER_CTX_get_encoder(ctx) == NULL) { \ + OSSL_ENCODER_CTX_free(ctx); \ goto legacy; \ } # define IMPLEMENT_PEM_provided_write_body_pass() \ @@ -38,31 +38,31 @@ } \ if (enc != NULL) { \ ret = 0; \ - if (OSSL_SERIALIZER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), \ - NULL)) { \ + if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), \ + NULL)) { \ ret = 1; \ if (kstr != NULL \ - && !OSSL_SERIALIZER_CTX_set_passphrase(ctx, kstr, klen)) \ + && !OSSL_ENCODER_CTX_set_passphrase(ctx, kstr, klen)) \ ret = 0; \ else if (cb != NULL \ - && !OSSL_SERIALIZER_CTX_set_passphrase_cb(ctx, \ - cb, u)) \ + && !OSSL_ENCODER_CTX_set_passphrase_cb(ctx, \ + cb, u)) \ ret = 0; \ } \ } \ if (!ret) { \ - OSSL_SERIALIZER_CTX_free(ctx); \ + OSSL_ENCODER_CTX_free(ctx); \ return 0; \ } # define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \ - ret = OSSL_SERIALIZER_to_##outtype(ctx, out); \ - OSSL_SERIALIZER_CTX_free(ctx); \ + ret = OSSL_ENCODER_to_##outtype(ctx, out); \ + OSSL_ENCODER_CTX_free(ctx); \ return ret # define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ writename) \ legacy: \ return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \ - x, NULL, NULL, 0, NULL, NULL) + x, NULL, NULL, 0, NULL, NULL) # define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \ writename) \ legacy: \ @@ -114,15 +114,15 @@ IMPLEMENT_PEM_provided_write_bio(name, type, str, asn1) \ IMPLEMENT_PEM_provided_write_fp(name, type, str, asn1) -# define IMPLEMENT_PEM_provided_write_cb(name, type, str, asn1) \ - IMPLEMENT_PEM_provided_write_cb_bio(name, type, str, asn1) \ +# define IMPLEMENT_PEM_provided_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb_bio(name, type, str, asn1) \ IMPLEMENT_PEM_provided_write_cb_fp(name, type, str, asn1) -# define IMPLEMENT_PEM_provided_rw(name, type, str, asn1) \ +# define IMPLEMENT_PEM_provided_rw(name, type, str, asn1) \ IMPLEMENT_PEM_read(name, type, str, asn1) \ IMPLEMENT_PEM_provided_write(name, type, str, asn1) -# define IMPLEMENT_PEM_provided_rw_cb(name, type, str, asn1) \ +# define IMPLEMENT_PEM_provided_rw_cb(name, type, str, asn1) \ IMPLEMENT_PEM_read(name, type, str, asn1) \ IMPLEMENT_PEM_provided_write_cb(name, type, str, asn1) diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c index 12a25b7a82..84d431820b 100644 --- a/crypto/pem/pem_pk8.c +++ b/crypto/pem/pem_pk8.c @@ -15,7 +15,7 @@ #include <openssl/x509.h> #include <openssl/pkcs12.h> #include <openssl/pem.h> -#include <openssl/serializer.h> +#include <openssl/encoder.h> static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, @@ -69,9 +69,9 @@ static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid, { int ret = 0; const char *pq = isder - ? OSSL_SERIALIZER_PrivateKey_TO_DER_PQ - : OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ; - OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(x, pq); + ? OSSL_ENCODER_PrivateKey_TO_DER_PQ + : OSSL_ENCODER_PrivateKey_TO_PEM_PQ; + OSSL_ENCODER_CTX *ctx = OSSL_ENCODER_CTX_new_by_EVP_PKEY(x, pq); if (ctx == NULL) return 0; @@ -90,12 +90,11 @@ static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid, } } - if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL) { + if (OSSL_ENCODER_CTX_get_encoder(ctx) != NULL) { ret = 1; if (enc != NULL) { ret = 0; - if (OSSL_SERIALIZER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), - NULL)) { + if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), NULL)) { const unsigned char *ukstr = (const unsigned char *)kstr; /* @@ -106,14 +105,14 @@ static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid, */ ret = 1; if (kstr != NULL - && !OSSL_SERIALIZER_CTX_set_passphrase(ctx, ukstr, klen)) + && !OSSL_ENCODER_CTX_set_passphrase(ctx, ukstr, klen)) ret = 0; else if (cb != NULL - && !OSSL_SERIALIZER_CTX_set_passphrase_cb(ctx, cb, u)) + && !OSSL_ENCODER_CTX_set_passphrase_cb(ctx, cb, u)) ret = 0; } } - ret = ret && OSSL_SERIALIZER_to_bio(ctx, bp); + ret = ret && OSSL_ENCODER_to_bio(ctx, bp); } else { X509_SIG *p8; PKCS8_PRIV_KEY_INFO *p8inf; @@ -153,7 +152,7 @@ static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid, legacy_end: PKCS8_PRIV_KEY_INFO_free(p8inf); } - OSSL_SERIALIZER_CTX_free(ctx); + OSSL_ENCODER_CTX_free(ctx); return ret; } @@ -261,4 +260,4 @@ IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, - PKCS8_PRIV_KEY_INFO) + PKCS8_PRIV_KEY_INFO) diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 4ee5bb7009..e355afe5f9 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -19,7 +19,6 @@ #include <openssl/dh.h> #include <openssl/store.h> #include <openssl/ui.h> -#include <openssl/serializer.h> #include "crypto/store.h" #include "crypto/asn1.h" #include "crypto/evp.h" diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c index 91b830c2e5..6d6ca9b266 100644 --- a/crypto/property/property_parse.c +++ b/crypto/property/property_parse.c @@ -596,9 +596,9 @@ int ossl_property_parse_init(OPENSSL_CTX *ctx) "provider", /* Name of provider (default, legacy, fips) */ "version", /* Version number of this provider */ "fips", /* FIPS validated or FIPS supporting algorithm */ - "format", /* output format for serializers */ - "type", /* output type for serializers */ - "input", /* input type for deserializers */ + "format", /* output format for encoders */ + "type", /* output type for encoders */ + "input", /* input type for decoders */ }; size_t i; diff --git a/crypto/serializer/build.info b/crypto/serializer/build.info deleted file mode 100644 index 11f8889b6b..0000000000 --- a/crypto/serializer/build.info +++ /dev/null @@ -1,8 +0,0 @@ -SOURCE[../../libcrypto]=serdes_pass.c - -SOURCE[../../libcrypto]=serializer_meth.c serializer_lib.c serializer_pkey.c -SOURCE[../../libcrypto]=deserializer_meth.c deserializer_lib.c \ - deserializer_pkey.c - -SOURCE[../../libcrypto]=serializer_err.c -SOURCE[../../libcrypto]=deserializer_err.c diff --git a/crypto/serializer/deserializer_lib.c b/crypto/serializer/deserializer_lib.c deleted file mode 100644 index aa3b552786..0000000000 --- a/crypto/serializer/deserializer_lib.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright 2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/core_names.h> -#include <openssl/bio.h> -#include <openssl/params.h> -#include <openssl/provider.h> -#include "serializer_local.h" -#include "e_os.h" - -struct deser_process_data_st { - OSSL_DESERIALIZER_CTX *ctx; - - /* Current BIO */ - BIO *bio; - - /* Index of the current deserializer instance to be processed */ - size_t current_deser_inst_index; -}; - -static int deser_process(const OSSL_PARAM params[], void *arg); - -int OSSL_DESERIALIZER_from_bio(OSSL_DESERIALIZER_CTX *ctx, BIO *in) -{ - struct deser_process_data_st data; - int ok = 0; - - memset(&data, 0, sizeof(data)); - data.ctx = ctx; - data.bio = in; - - ok = deser_process(NULL, &data); - - /* Clear any internally cached passphrase */ - if (!ctx->flag_user_passphrase) { - OSSL_DESERIALIZER_CTX_set_passphrase(ctx, NULL, 0); - ctx->flag_user_passphrase = 0; - } - return ok; -} - -#ifndef OPENSSL_NO_STDIO -static BIO *bio_from_file(FILE *fp) -{ - BIO *b; - - if ((b = BIO_new(BIO_s_file())) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_BIO_LIB); - return NULL; - } - BIO_set_fp(b, fp, BIO_NOCLOSE); - return b; -} - -int OSSL_DESERIALIZER_from_fp(OSSL_DESERIALIZER_CTX *ctx, FILE *fp) -{ - BIO *b = bio_from_file(fp); - int ret = 0; - - if (b != NULL) - ret = OSSL_DESERIALIZER_from_bio(ctx, b); - - BIO_free(b); - return ret; -} -#endif - -int OSSL_DESERIALIZER_CTX_set_input_type(OSSL_DESERIALIZER_CTX *ctx, - const char *input_type) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - /* - * NULL is a valid starting input type, and means that the caller leaves - * it to code to discover what the starting input type is. - */ - ctx->start_input_type = input_type; - return 1; -} - -int OSSL_DESERIALIZER_CTX_add_deserializer(OSSL_DESERIALIZER_CTX *ctx, - OSSL_DESERIALIZER *deser) -{ - OSSL_DESERIALIZER_INSTANCE *deser_inst = NULL; - const OSSL_PROVIDER *prov = NULL; - OSSL_PARAM params[2]; - void *provctx = NULL; - - if (!ossl_assert(ctx != NULL) || !ossl_assert(deser != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (deser->get_params == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, - OSSL_DESERIALIZER_R_MISSING_GET_PARAMS); - return 0; - } - - if (ctx->deser_insts == NULL - && (ctx->deser_insts = - sk_OSSL_DESERIALIZER_INSTANCE_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); - return 0; - } - if ((deser_inst = OPENSSL_zalloc(sizeof(*deser_inst))) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!OSSL_DESERIALIZER_up_ref(deser)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_INTERNAL_ERROR); - goto err; - } - deser_inst->deser = deser; - - prov = OSSL_DESERIALIZER_provider(deser_inst->deser); - provctx = OSSL_PROVIDER_get0_provider_ctx(prov); - - /* Cache the input type for this serializer */ - params[0] = - OSSL_PARAM_construct_utf8_ptr(OSSL_DESERIALIZER_PARAM_INPUT_TYPE, - (char **)&deser_inst->input_type, 0); - params[1] = OSSL_PARAM_construct_end(); - - if (!deser_inst->deser->get_params(params) - || !OSSL_PARAM_modified(¶ms[0])) - goto err; - - if ((deser_inst->deserctx = deser_inst->deser->newctx(provctx)) - == NULL) - goto err; - - if (sk_OSSL_DESERIALIZER_INSTANCE_push(ctx->deser_insts, deser_inst) <= 0) - goto err; - - return 1; - err: - if (deser_inst != NULL) { - if (deser_inst->deser != NULL) - deser_inst->deser->freectx(deser_inst->deserctx); - OSSL_DESERIALIZER_free(deser_inst->deser); - OPENSSL_free(deser_inst); - } - return 0; -} - -int OSSL_DESERIALIZER_CTX_add_extra(OSSL_DESERIALIZER_CTX *ctx, - OPENSSL_CTX *libctx, const char *propq) -{ - /* - * This function goes through existing deserializer methods in - * |ctx->deser_insts|, and tries to fetch new deserializers that produce - * what the existing ones want as input, and push those newly fetched - * deserializers on top of the same stack. - * Then it does the same again, but looping over the newly fetched - * deserializers, until there are no more serializers to be fetched, or - * when we have done this 10 times. - * - * we do this with sliding windows on the stack by keeping track of indexes - * and of the end. - * - * +----------------+ - * | DER to RSA | <--- w_prev_start - * +----------------+ - * | DER to DSA | - * +----------------+ - * | DER to DH | - * +----------------+ - * | PEM to DER | <--- w_prev_end, w_new_start - * +----------------+ - * <--- w_new_end - */ - size_t w_prev_start, w_prev_end; /* "previous" deserializers */ - size_t w_new_start, w_new_end; /* "new" deserializers */ - size_t count = 0; /* Calculates how many were added in each iteration */ - size_t depth = 0; /* Counts the number of iterations */ - - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - /* - * If there is no stack of OSSL_DESERIALIZER_INSTANCE, we have nothing - * more to add. That's fine. - */ - if (ctx->deser_insts == NULL) - return 1; - - w_prev_start = 0; - w_prev_end = sk_OSSL_DESERIALIZER_INSTANCE_num(ctx->deser_insts); - do { - size_t i; - - w_new_start = w_new_end = w_prev_end; - - for (i = w_prev_start; i < w_prev_end; i++) { - OSSL_DESERIALIZER_INSTANCE *deser_inst = - sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, i); - const char *name = deser_inst->input_type; - OSSL_DESERIALIZER *deser = NULL; - - /* - * If the caller has specified what the initial input should be, - * and the deserializer implementation we're looking at has that - * input type, there's no point adding on more implementations - * on top of this one, so we don't. - */ - if (ctx->start_input_type != NULL - && strcasecmp(ctx->start_input_type, - deser_inst->input_type) != 0) - continue; - - ERR_set_mark(); - deser = OSSL_DESERIALIZER_fetch(libctx, name, propq); - ERR_pop_to_mark(); - - if (deser != NULL) { - size_t j; - - /* - * Check that we don't already have this deserializer in our - * stack We only need to check among the newly added ones. - */ - for (j = w_new_start; j < w_new_end; j++) { - OSSL_DESERIALIZER_INSTANCE *check_inst = - sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, j); - - if (deser == check_inst->deser) { - /* We found it, so drop the new fetch */ - OSSL_DESERIALIZER_free(deser); - deser = NULL; - break; - } - } - } - - if (deser == NULL) - continue; - - /* - * Apart from keeping w_new_end up to date, We don't care about - * errors here. If it doesn't collect, then it doesn't... - */ - if (OSSL_DESERIALIZER_CTX_add_deserializer(ctx, deser)) /* ref++ */ - w_new_end++; - OSSL_DESERIALIZER_free(deser); /* ref-- */ - } - /* How many were added in this iteration */ - count = w_new_end - w_new_start; - - /* Slide the "previous deserializer" windows */ - w_prev_start = w_new_start; - w_prev_end = w_new_end; - - depth++; - } while (count != 0 && depth <= 10); - - return 1; -} - -int OSSL_DESERIALIZER_CTX_num_deserializers(OSSL_DESERIALIZER_CTX *ctx) -{ - if (ctx == NULL || ctx->deser_insts == NULL) - return 0; - return sk_OSSL_DESERIALIZER_INSTANCE_num(ctx->deser_insts); -} - -int OSSL_DESERIALIZER_CTX_set_construct(OSSL_DESERIALIZER_CTX *ctx, - OSSL_DESERIALIZER_CONSTRUCT *construct) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - ctx->construct = construct; - return 1; -} - -int OSSL_DESERIALIZER_CTX_set_construct_data(OSSL_DESERIALIZER_CTX *ctx, - void *construct_data) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - ctx->construct_data = construct_data; - return 1; -} - -int OSSL_DESERIALIZER_CTX_set_cleanup(OSSL_DESERIALIZER_CTX *ctx, - OSSL_DESERIALIZER_CLEANUP *cleanup) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - ctx->cleanup = cleanup; - return 1; -} - -OSSL_DESERIALIZER_CONSTRUCT * -OSSL_DESERIALIZER_CTX_get_construct(OSSL_DESERIALIZER_CTX *ctx) -{ - if (ctx == NULL) - return NULL; - return ctx->construct; -} - -void *OSSL_DESERIALIZER_CTX_get_construct_data(OSSL_DESERIALIZER_CTX *ctx) -{ - if (ctx == NULL) - return NULL; - return ctx->construct_data; -} - -OSSL_DESERIALIZER_CLEANUP * -OSSL_DESERIALIZER_CTX_get_cleanup(OSSL_DESERIALIZER_CTX *ctx) -{ - if (ctx == NULL) - return NULL; - return ctx->cleanup; -} - -int OSSL_DESERIALIZER_export(OSSL_DESERIALIZER_INSTANCE *deser_inst, - void *reference, size_t reference_sz, - OSSL_CALLBACK *export_cb, void *export_cbarg) -{ - if (!(ossl_assert(deser_inst != NULL) - && ossl_assert(reference != NULL) - && ossl_assert(export_cb != NULL) - && ossl_assert(export_cbarg != NULL))) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return deser_inst->deser->export_object(deser_inst->deserctx, - reference, reference_sz, - export_cb, export_cbarg); -} - -OSSL_DESERIALIZER *OSSL_DESERIALIZER_INSTANCE_deserializer - (OSSL_DESERIALIZER_INSTANCE *deser_inst) -{ - if (deser_inst == NULL) - return NULL; - return deser_inst->deser; -} - -void *OSSL_DESERIALIZER_INSTANCE_deserializer_ctx - (OSSL_DESERIALIZER_INSTANCE *deser_inst) -{ - if (deser_inst == NULL) - return NULL; - return deser_inst->deserctx; -} - -static int deser_process(const OSSL_PARAM params[], void *arg) -{ - struct deser_process_data_st *data = arg; - OSSL_DESERIALIZER_CTX *ctx = data->ctx; - OSSL_DESERIALIZER_INSTANCE *deser_inst = NULL; - OSSL_DESERIALIZER *deser = NULL; - BIO *bio = data->bio; - long loc; - size_t i; - int ok = 0; - /* For recursions */ - struct deser_process_data_st new_data; - - memset(&new_data, 0, sizeof(new_data)); - new_data.ctx = data->ctx; - - if (params == NULL) { - /* First iteration, where we prepare for what is to come */ - - data->current_deser_inst_index = - OSSL_DESERIALIZER_CTX_num_deserializers(ctx); - - bio = data->bio; - } else { - const OSSL_PARAM *p; - - deser_inst = - sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, - data->current_deser_inst_index); - deser = OSSL_DESERIALIZER_INSTANCE_deserializer(deser_inst); - - if (ctx->construct != NULL - && ctx->construct(deser_inst, params, ctx->construct_data)) { - ok = 1; - goto end; - } - - /* The constructor didn't return success */ - - /* - * so we try to use the object we got and feed it to any next - * deserializer that will take it. Object references are not - * allowed for this. - * If this data isn't present, deserialization has failed. - */ - - p = OSSL_PARAM_locate_const(params, OSSL_DESERIALIZER_PARAM_DATA); - if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) - goto end; - new_data.bio = BIO_new_mem_buf(p->data, (int)p->data_size); - if (new_data.bio == NULL) - goto end; - bio = new_data.bio; - } - - /* - * If we have no more deserializers to look through at this point, - * we failed - */ - if (data->current_deser_inst_index == 0) - goto end; - - if ((loc = BIO_tell(bio)) < 0) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_BIO_LIB); - goto end; - } - - for (i = data->current_deser_inst_index; i-- > 0;) { - OSSL_DESERIALIZER_INSTANCE *new_deser_inst = - sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, i); - OSSL_DESERIALIZER *new_deser = - OSSL_DESERIALIZER_INSTANCE_deserializer(new_deser_inst); - - /* - * If |deser| is NULL, it means we've just started, and the caller - * may have specified what it expects the initial input to be. If - * that's the case, we do this extra check. - */ - if (deser == NULL && ctx->start_input_type != NULL - && strcasecmp(ctx->start_input_type, - new_deser_inst->input_type) != 0) - continue; - - /* - * If we have a previous deserializer, we check that the input type - * of the next to be used matches the type of this previous one. - * deser_inst->input_type is a cache of the parameter "input-type" - * value for that deserializer. - */ - if (deser != NULL - && !OSSL_DESERIALIZER_is_a(deser, new_deser_inst->input_type)) - continue; - - /* - * Checking the return value of BIO_reset() or BIO_seek() is unsafe. - * Furthermore, BIO_reset() is unsafe to use if the source BIO happens - * to be a BIO_s_mem(), because the earlier BIO_tell() gives us zero - * no matter where we are in the underlying buffer we're reading from. - * - * So, we simply do a BIO_seek(), and use BIO_tell() that we're back - * at the same position. This is a best effort attempt, but BIO_seek() - * and BIO_tell() should come as a pair... - */ - (void)BIO_seek(bio, loc); - if (BIO_tell(bio) != loc) - goto end; - - /* Recurse */ - new_data.current_deser_inst_index = i; - ok = new_deser->deserialize(new_deser_inst->deserctx, - (OSSL_CORE_BIO *)bio, - deser_process, &new_data, - ctx->passphrase_cb, - new_data.ctx); - if (ok) - break; - } - - end: - BIO_free(new_data.bio); - return ok; -} diff --git a/crypto/serializer/deserializer_meth.c b/crypto/serializer/deserializer_meth.c deleted file mode 100644 index 69099f5e95..0000000000 --- a/crypto/serializer/deserializer_meth.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright 2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/core.h> -#include <openssl/core_dispatch.h> -#include <openssl/deserializer.h> -#include <openssl/ui.h> -#include "internal/core.h" -#include "internal/namemap.h" -#include "internal/property.h" -#include "internal/provider.h" -#include "crypto/serializer.h" -#include "serializer_local.h" - -static void OSSL_DESERIALIZER_INSTANCE_free(OSSL_DESERIALIZER_INSTANCE *instance); - -/* - * Deserializer can have multiple names, separated with colons in a name string - */ -#define NAME_SEPARATOR ':' - -/* Simple method structure constructor and destructor */ -static OSSL_DESERIALIZER *ossl_deserializer_new(void) -{ - OSSL_DESERIALIZER *deser = NULL; - - if ((deser = OPENSSL_zalloc(sizeof(*deser))) == NULL - || (deser->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { - OSSL_DESERIALIZER_free(deser); - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); - return NULL; - } - - deser->base.refcnt = 1; - - return deser; -} - -int OSSL_DESERIALIZER_up_ref(OSSL_DESERIALIZER *deser) -{ - int ref = 0; - - CRYPTO_UP_REF(&deser->base.refcnt, &ref, deser->base.lock); - return 1; -} - -void OSSL_DESERIALIZER_free(OSSL_DESERIALIZER *deser) -{ - int ref = 0; - - if (deser == NULL) - return; - - CRYPTO_DOWN_REF(&deser->base.refcnt, &ref, deser->base.lock); - if (ref > 0) - return; - ossl_provider_free(deser->base.prov); - CRYPTO_THREAD_lock_free(deser->base.lock); - OPENSSL_free(deser); -} - -/* Permanent deserializer method store, constructor and destructor */ -static void deserializer_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *deserializer_store_new(OPENSSL_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OPENSSL_CTX_METHOD deserializer_store_method = { - deserializer_store_new, - deserializer_store_free, -}; - -/* Data to be passed through ossl_method_construct() */ -struct deserializer_data_st { - OPENSSL_CTX *libctx; - OSSL_METHOD_CONSTRUCT_METHOD *mcm; - int id; /* For get_deserializer_from_store() */ - const char *names; /* For get_deserializer_from_store() */ - const char *propquery; /* For get_deserializer_from_store() */ -}; - -/* - * Generic routines to fetch / create DESERIALIZER methods with - * ossl_method_construct() - */ - -/* Temporary deserializer method store, constructor and destructor */ -static void *alloc_tmp_deserializer_store(OPENSSL_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - static void dealloc_tmp_deserializer_store(void *store) -{ - if (store != NULL) - ossl_method_store_free(store); -} - -/* Get the permanent deserializer store */ -static OSSL_METHOD_STORE *get_deserializer_store(OPENSSL_CTX *libctx) -{ - return openssl_ctx_get_data(libctx, OPENSSL_CTX_DESERIALIZER_STORE_INDEX, - &deserializer_store_method); -} - -/* Get deserializer methods from a store, or put one in */ -static void *get_deserializer_from_store(OPENSSL_CTX *libctx, void *store, - void *data) -{ - struct deserializer_data_st *methdata = data; - void *method = NULL; - int id; - - if ((id = methdata->id) == 0) { - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - id = ossl_namemap_name2num(namemap, methdata->names); - } - - if (store == NULL - && (store = get_deserializer_store(libctx)) == NULL) - return NULL; - - if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) - return NULL; - return method; -} - -static int put_deserializer_in_store(OPENSSL_CTX *libctx, void *store, - void *method, const OSSL_PROVIDER *prov, - int operation_id, const char *names, - const char *propdef, void *unused) -{ - OSSL_NAMEMAP *namemap; - int id; - - if ((namemap = ossl_namemap_stored(libctx)) == NULL - || (id = ossl_namemap_name2num(namemap, names)) == 0) - return 0; - - if (store == NULL && (store = get_deserializer_store(libctx)) == NULL) - return 0; - - return ossl_method_store_add(store, prov, id, propdef, method, - (int (*)(void *))OSSL_DESERIALIZER_up_ref, - (void (*)(void *))OSSL_DESERIALIZER_free); -} - -/* Create and populate a deserializer method */ -static void *deserializer_from_dispatch(int id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov) -{ - OSSL_DESERIALIZER *deser = NULL; - const OSSL_DISPATCH *fns = algodef->implementation; - - if ((deser = ossl_deserializer_new()) == NULL) - return NULL; - deser->base.id = id; - deser->base.propdef = algodef->property_definition; - - for (; fns->function_id != 0; fns++) { - switch (fns->function_id) { - case OSSL_FUNC_DESERIALIZER_NEWCTX: - if (deser->newctx == NULL) - deser->newctx = OSSL_FUNC_deserializer_newctx(fns); - break; - case OSSL_FUNC_DESERIALIZER_FREECTX: - if (deser->freectx == NULL) - deser->freectx = OSSL_FUNC_deserializer_freectx(fns); - break; - case OSSL_FUNC_DESERIALIZER_GET_PARAMS: - if (deser->get_params == NULL) - deser->get_params = - OSSL_FUNC_deserializer_get_params(fns); - break; - case OSSL_FUNC_DESERIALIZER_GETTABLE_PARAMS: - if (deser->gettable_params == NULL) - deser->gettable_params = - OSSL_FUNC_deserializer_gettable_params(fns); - break; - case OSSL_FUNC_DESERIALIZER_SET_CTX_PARAMS: - if (deser->set_ctx_params == NULL) - deser->set_ctx_params = - OSSL_FUNC_deserializer_set_ctx_params(fns); - break; - case OSSL_FUNC_DESERIALIZER_SETTABLE_CTX_PARAMS: - if (deser->settable_ctx_params == NULL) - deser->settable_ctx_params = - OSSL_FUNC_deserializer_settable_ctx_params(fns); - break; - case OSSL_FUNC_DESERIALIZER_DESERIALIZE: - if (deser->deserialize == NULL) - deser->deserialize = OSSL_FUNC_deserializer_deserialize(fns); - break; - case OSSL_FUNC_DESERIALIZER_EXPORT_OBJECT: - if (deser->export_object == NULL) - deser->export_object = OSSL_FUNC_deserializer_export_object(fns); - break; - } - } - /* - * Try to check that the method is sensible. - * If you have a constructor, you must have a destructor and vice versa. - * You must have at least one of the serializing driver functions. - */ - if (!((deser->newctx == NULL && deser->freectx == NULL) - || (deser->newctx != NULL && deser->freectx != NULL)) - || (deser->deserialize == NULL && deser->export_object == NULL)) { - OSSL_DESERIALIZER_free(deser); - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_INVALID_PROVIDER_FUNCTIONS); - return NULL; - } - - if (prov != NULL && !ossl_provider_up_ref(prov)) { - OSSL_DESERIALIZER_free(deser); - return NULL; - } - - deser->base.prov = prov; - return deser; -} - - -/* - * The core fetching functionality passes the names of the implementation. - * This function is responsible to getting an identity number for them, - * then call deserializer_from_dispatch() with that identity number. - */ -static void *construct_deserializer(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *unused) -{ - /* - * This function is only called if get_deserializer_from_store() returned - * NULL, so it's safe to say that of all the spots to create a new - * namemap entry, this is it. Should the name already exist there, we - * know that ossl_namemap_add() will return its corresponding number. - */ - OPENSSL_CTX *libctx = ossl_provider_library_context(prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - const char *names = algodef->algorithm_names; - int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); - void *method = NULL; - - if (id != 0) - method = deserializer_from_dispatch(id, algodef, prov); - - return method; -} - -/* Intermediary function to avoid ugly casts, used below */ -static void destruct_deserializer(void *method, void *data) -{ - OSSL_DESERIALIZER_free(method); -} - -static int up_ref_deserializer(void *method) -{ - return OSSL_DESERIALIZER_up_ref(method); -} - -static void free_deserializer(void *method) -{ - OSSL_DESERIALIZER_free(method); -} - -/* Fetching support. Can fetch by numeric identity or by name */ -static OSSL_DESERIALIZER *inner_ossl_deserializer_fetch(OPENSSL_CTX *libctx, - int id, - const char *name, - const char *properties) -{ - OSSL_METHOD_STORE *store = get_deserializer_store(libctx); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - void *method = NULL; - - if (store == NULL || namemap == NULL) - return NULL; - - /* - * If we have been passed neither a name_id or a name, we have an - * internal programming error. - */ - if (!ossl_assert(id != 0 || name != NULL)) - return NULL; - - if (id == 0) - id = ossl_namemap_name2num(namemap, name); - - if (id == 0 - || !ossl_method_store_cache_get(store, id, properties, &method)) { - OSSL_METHOD_CONSTRUCT_METHOD mcm = { - alloc_tmp_deserializer_store, - dealloc_tmp_deserializer_store, - get_deserializer_from_store, - put_deserializer_in_store, - construct_deserializer, - destruct_deserializer - }; - struct deserializer_data_st mcmdata; - - mcmdata.libctx = libctx; - mcmdata.mcm = &mcm; - mcmdata.id = id; - mcmdata.names = name; - mcmdata.propquery = properties; - if ((method = ossl_method_construct(libctx, OSSL_OP_DESERIALIZER, - 0 /* !force_cache */, - &mcm, &mcmdata)) != NULL) { - /* - * If construction did create a method for us, we know that - * there is a correct name_id and meth_id, since those have - * already been calculated in get_deserializer_from_store() and - * put_deserializer_in_store() above. - */ - if (id == 0) - id = ossl_namemap_name2num(namemap, name); - ossl_method_store_cache_set(store, id, properties, method, - up_ref_deserializer, free_deserializer); - } - } - - return method; -} - -OSSL_DESERIALIZER *OSSL_DESERIALIZER_fetch(OPENSSL_CTX *libctx, - const char *name, - const char *properties) -{ - return inner_ossl_deserializer_fetch(libctx, 0, name, properties); -} - -OSSL_DESERIALIZER *ossl_deserializer_fetch_by_number(OPENSSL_CTX *libctx, - int id, - const char *properties) -{ - return inner_ossl_deserializer_fetch(libctx, id, NULL, properties); -} - -/* - * Library of basic method functions - */ - -const OSSL_PROVIDER *OSSL_DESERIALIZER_provider(const OSSL_DESERIALIZER *deser) -{ - if (!ossl_assert(deser != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return deser->base.prov; -} - -const char *OSSL_DESERIALIZER_properties(const OSSL_DESERIALIZER *deser) -{ - if (!ossl_assert(deser != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return deser->base.propdef; -} - -int OSSL_DESERIALIZER_number(const OSSL_DESERIALIZER *deser) -{ - if (!ossl_assert(deser != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return deser->base.id; -} - -int OSSL_DESERIALIZER_is_a(const OSSL_DESERIALIZER *deser, const char *name) -{ - if (deser->base.prov != NULL) { - OPENSSL_CTX *libctx = ossl_provider_library_context(deser->base.prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - return ossl_namemap_name2num(namemap, name) == deser->base.id; - } - return 0; -} - -struct deserializer_do_all_data_st { - void (*user_fn)(void *method, void *arg); - void *user_arg; -}; - -static void deserializer_do_one(OSSL_PROVIDER *provider, - const OSSL_ALGORITHM *algodef, - int no_store, void *vdata) -{ - struct deserializer_do_all_data_st *data = vdata; - OPENSSL_CTX *libctx = ossl_provider_library_context(provider); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - const char *names = algodef->algorithm_names; - int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); - void *method = NULL; - - if (id != 0) - method = - deserializer_from_dispatch(id, algodef, provider); - - if (method != NULL) { - data->user_fn(method, data->user_arg); - OSSL_DESERIALIZER_free(method); - } -} - -void OSSL_DESERIALIZER_do_all_provided(OPENSSL_CTX *libctx, - void (*fn)(OSSL_DESERIALIZER *deser, - void *arg), - void *arg) -{ - struct deserializer_do_all_data_st data; - - data.user_fn = (void (*)(void *, void *))fn; - data.user_arg = arg; - ossl_algorithm_do_all(libctx, OSSL_OP_DESERIALIZER, NULL, - NULL, deserializer_do_one, NULL, - &data); -} - -void OSSL_DESERIALIZER_names_do_all(const OSSL_DESERIALIZER *deser, - void (*fn)(const char *name, void *data), - void *data) -{ - if (deser == NULL) - return; - - if (deser->base.prov != NULL) { - OPENSSL_CTX *libctx = ossl_provider_library_context(deser->base.prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - ossl_namemap_doall_names(namemap, deser->base.id, fn, data); - } -} - -const OSSL_PARAM * -OSSL_DESERIALIZER_gettable_params(OSSL_DESERIALIZER *deser) -{ - if (deser != NULL && deser->gettable_params != NULL) - return deser->gettable_params( - ossl_provider_ctx(OSSL_DESERIALIZER_provider(deser))); - return NULL; -} - -int OSSL_DESERIALIZER_get_params(OSSL_DESERIALIZER *deser, OSSL_PARAM params[]) -{ - if (deser != NULL && deser->get_params != NULL) - return deser->get_params(params); - return 0; -} - -const OSSL_PARAM * -OSSL_DESERIALIZER_settable_ctx_params(OSSL_DESERIALIZER *deser) -{ - if (deser != NULL && deser->settable_ctx_params != NULL) - return deser->settable_ctx_params( - ossl_provider_ctx(OSSL_DESERIALIZER_provider(deser))); - return NULL; -} - -/* - * Deserializer context support - */ - -/* - * |ser| value NULL is valid, and signifies that there is no deserializer. - * This is useful to provide fallback mechanisms. - * Functions that want to verify if there is a deserializer can do so with - * OSSL_DESERIALIZER_CTX_get_deserializer() - */ -OSSL_DESERIALIZER_CTX *OSSL_DESERIALIZER_CTX_new(void) -{ - OSSL_DESERIALIZER_CTX *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE); - return NULL; - } - - ctx->passphrase_cb = ossl_deserializer_passphrase_in_cb; - return ctx; -} - -int OSSL_DESERIALIZER_CTX_set_params(OSSL_DESERIALIZER_CTX *ctx, - const OSSL_PARAM params[]) -{ - size_t i; - size_t l; - - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (ctx->deser_insts == NULL) - return 1; - - l = (size_t)sk_OSSL_DESERIALIZER_INSTANCE_num(ctx->deser_insts); - for (i = 0; i < l; i++) { - OSSL_DESERIALIZER_INSTANCE *deser_inst = - sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, i); - - if (deser_inst->deserctx == NULL - || deser_inst->deser->set_ctx_params == NULL) - continue; - if (!deser_inst->deser->set_ctx_params(deser_inst->deserctx, params)) - return 0; - } - return 1; -} - -static void -OSSL_DESERIALIZER_INSTANCE_free(OSSL_DESERIALIZER_INSTANCE *deser_inst) -{ - if (deser_inst != NULL) { - if (deser_inst->deser->freectx != NULL) - deser_inst->deser->freectx(deser_inst->deserctx); - deser_inst->deserctx = NULL; - OSSL_DESERIALIZER_free(deser_inst->deser); - deser_inst->deser = NULL; - OPENSSL_free(deser_inst); - deser_inst = NULL; - } -} - -void OSSL_DESERIALIZER_CTX_free(OSSL_DESERIALIZER_CTX *ctx) -{ - if (ctx != NULL) { - if (ctx->cleanup != NULL) - ctx->cleanup(ctx->construct_data); - sk_OSSL_DESERIALIZER_INSTANCE_pop_free(ctx->deser_insts, - OSSL_DESERIALIZER_INSTANCE_free); - OSSL_DESERIALIZER_CTX_set_passphrase_ui(ctx, NULL, NULL); - OSSL_DESERIALIZER_CTX_set_passphrase(ctx, NULL, 0); - OPENSSL_free(ctx); - } -} diff --git a/crypto/serializer/serializer_err.c b/crypto/serializer/serializer_err.c deleted file mode 100644 index 2ea8b8bede..0000000000 --- a/crypto/serializer/serializer_err.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/err.h> -#include <openssl/serializererr.h> - -#ifndef OPENSSL_NO_ERR - -static const ERR_STRING_DATA OSSL_SERIALIZER_str_reasons[] = { - {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, OSSL_SERIALIZER_R_INCORRECT_PROPERTY_QUERY), - "incorrect property query"}, - {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, OSSL_SERIALIZER_R_SERIALIZER_NOT_FOUND), - "serializer not found"}, - {0, NULL} -}; - -#endif - -int ERR_load_OSSL_SERIALIZER_strings(void) -{ -#ifndef OPENSSL_NO_ERR - if (ERR_reason_error_string(OSSL_SERIALIZER_str_reasons[0].error) == NULL) - ERR_load_strings_const(OSSL_SERIALIZER_str_reasons); -#endif - return 1; -} diff --git a/crypto/serializer/serializer_local.h b/crypto/serializer/serializer_local.h deleted file mode 100644 index d139e402d7..0000000000 --- a/crypto/serializer/serializer_local.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2019-2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/core_dispatch.h> -#include <openssl/types.h> -#include <openssl/safestack.h> -#include <openssl/serializer.h> -#include <openssl/deserializer.h> -#include "internal/cryptlib.h" -#include "internal/refcount.h" - -struct ossl_serdes_base_st { - OSSL_PROVIDER *prov; - int id; - const char *propdef; - - CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; -}; - -struct ossl_serializer_st { - struct ossl_serdes_base_st base; - OSSL_FUNC_serializer_newctx_fn *newctx; - OSSL_FUNC_serializer_freectx_fn *freectx; - OSSL_FUNC_serializer_set_ctx_params_fn *set_ctx_params; - OSSL_FUNC_serializer_settable_ctx_params_fn *settable_ctx_params; - OSSL_FUNC_serializer_serialize_data_fn *serialize_data; - OSSL_FUNC_serializer_serialize_object_fn *serialize_object; -}; - -struct ossl_deserializer_st { - struct ossl_serdes_base_st base; - OSSL_FUNC_deserializer_newctx_fn *newctx; - OSSL_FUNC_deserializer_freectx_fn *freectx; - OSSL_FUNC_deserializer_get_params_fn *get_params; - OSSL_FUNC_deserializer_gettable_params_fn *gettable_params; - OSSL_FUNC_deserializer_set_ctx_params_fn *set_ctx_params; - OSSL_FUNC_deserializer_settable_ctx_params_fn *settable_ctx_params; - OSSL_FUNC_deserializer_deserialize_fn *deserialize; - OSSL_FUNC_deserializer_export_object_fn *export_object; -}; - -struct ossl_serializer_ctx_st { - OSSL_SERIALIZER *ser; - void *serctx; - - int selection; - - /*- - * Output / serializing data, used by OSSL_SERIALIZER_to_{bio,fp} - * - * |object| is the libcrypto object to handle. - * |do_output| performs the actual serialization. - * - * |do_output| must have intimate knowledge of |object|. - */ - const void *object; - int (*do_output)(OSSL_SERIALIZER_CTX *ctx, BIO *out); - - /* For any function that needs a passphrase reader */ - const UI_METHOD *ui_method; - void *ui_data; - /* - * if caller used OSSL_SERIALIZER_CTX_set_passphrase_cb(), we need - * intermediary storage. - */ - UI_METHOD *allocated_ui_method; -}; - -struct ossl_deserializer_instance_st { - OSSL_DESERIALIZER *deser; /* Never NULL */ - void *deserctx; /* Never NULL */ - const char *input_type; /* Never NULL */ -}; - -DEFINE_STACK_OF(OSSL_DESERIALIZER_INSTANCE) - -struct ossl_deserializer_ctx_st { - /* - * The caller may know the input type of the data they pass. If not, - * this will remain NULL and the deserializing functionality will start - * with trying to deserialize with any desserializer in |deser_insts|, - * regardless of their respective input type. - */ - const char *start_input_type; - - /* - * Deserializers that are components of any current deserialization path. - */ - STACK_OF(OSSL_DESERIALIZER_INSTANCE) *deser_insts; - - /* - * The constructors of a deserialization, and its caller argument. - */ - OSSL_DESERIALIZER_CONSTRUCT *construct; - OSSL_DESERIALIZER_CLEANUP *cleanup; - void *construct_data; - - /* For any function that needs a passphrase reader */ - OSSL_PASSPHRASE_CALLBACK *passphrase_cb; - const UI_METHOD *ui_method; - void *ui_data; - /* - * if caller used OSSL_SERIALIZER_CTX_set_pem_password_cb(), we need - * intermediary storage. - */ - UI_METHOD *allocated_ui_method; - /* - * Because the same input may pass through more than one deserializer, - * we cache any passphrase passed to us. The desrializing processor - * must clear this at the end of a run. - */ - unsigned char *cached_passphrase; - size_t cached_passphrase_len; - - /* - * Flag section. Keep these together - */ - - /* - * The passphrase was passed to us by the user. In that case, it - * should only be freed when freeing this context. - */ - unsigned int flag_user_passphrase:1; -}; - -/* Passphrase callbacks, found in serdes_pass.c */ - -/* - * Serializers typically want to get an outgoing passphrase, while - * deserializers typically want to get en incoming passphrase. - */ -OSSL_PASSPHRASE_CALLBACK ossl_serializer_passphrase_out_cb; -OSSL_PASSPHRASE_CALLBACK ossl_deserializer_passphrase_in_cb; diff --git a/crypto/serializer/serializer_meth.c b/crypto/serializer/serializer_meth.c deleted file mode 100644 index 1489fff890..0000000000 --- a/crypto/serializer/serializer_meth.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright 2019-2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/core.h> -#include <openssl/core_dispatch.h> -#include <openssl/serializer.h> -#include <openssl/ui.h> -#include "internal/core.h" -#include "internal/namemap.h" -#include "internal/property.h" -#include "internal/provider.h" -#include "crypto/serializer.h" -#include "serializer_local.h" - -/* - * Serializer can have multiple names, separated with colons in a name string - */ -#define NAME_SEPARATOR ':' - -/* Simple method structure constructor and destructor */ -static OSSL_SERIALIZER *ossl_serializer_new(void) -{ - OSSL_SERIALIZER *ser = NULL; - - if ((ser = OPENSSL_zalloc(sizeof(*ser))) == NULL - || (ser->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { - OSSL_SERIALIZER_free(ser); - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE); - return NULL; - } - - ser->base.refcnt = 1; - - return ser; -} - -int OSSL_SERIALIZER_up_ref(OSSL_SERIALIZER *ser) -{ - int ref = 0; - - CRYPTO_UP_REF(&ser->base.refcnt, &ref, ser->base.lock); - return 1; -} - -void OSSL_SERIALIZER_free(OSSL_SERIALIZER *ser) -{ - int ref = 0; - - if (ser == NULL) - return; - - CRYPTO_DOWN_REF(&ser->base.refcnt, &ref, ser->base.lock); - if (ref > 0) - return; - ossl_provider_free(ser->base.prov); - CRYPTO_THREAD_lock_free(ser->base.lock); - OPENSSL_free(ser); -} - -/* Permanent serializer method store, constructor and destructor */ -static void serializer_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *serializer_store_new(OPENSSL_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OPENSSL_CTX_METHOD serializer_store_method = { - serializer_store_new, - serializer_store_free, -}; - -/* Data to be passed through ossl_method_construct() */ -struct serializer_data_st { - OPENSSL_CTX *libctx; - OSSL_METHOD_CONSTRUCT_METHOD *mcm; - int id; /* For get_serializer_from_store() */ - const char *names; /* For get_serializer_from_store() */ - const char *propquery; /* For get_serializer_from_store() */ -}; - -/* - * Generic routines to fetch / create SERIALIZER methods with - * ossl_method_construct() - */ - -/* Temporary serializer method store, constructor and destructor */ -static void *alloc_tmp_serializer_store(OPENSSL_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - static void dealloc_tmp_serializer_store(void *store) -{ - if (store != NULL) - ossl_method_store_free(store); -} - -/* Get the permanent serializer store */ -static OSSL_METHOD_STORE *get_serializer_store(OPENSSL_CTX *libctx) -{ - return openssl_ctx_get_data(libctx, OPENSSL_CTX_SERIALIZER_STORE_INDEX, - &serializer_store_method); -} - -/* Get serializer methods from a store, or put one in */ -static void *get_serializer_from_store(OPENSSL_CTX *libctx, void *store, - void *data) -{ - struct serializer_data_st *methdata = data; - void *method = NULL; - int id; - - if ((id = methdata->id) == 0) { - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - id = ossl_namemap_name2num(namemap, methdata->names); - } - - if (store == NULL - && (store = get_serializer_store(libctx)) == NULL) - return NULL; - - if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) - return NULL; - return method; -} - -static int put_serializer_in_store(OPENSSL_CTX *libctx, void *store, - void *method, const OSSL_PROVIDER *prov, - int operation_id, const char *names, - const char *propdef, void *unused) -{ - OSSL_NAMEMAP *namemap; - int id; - - if ((namemap = ossl_namemap_stored(libctx)) == NULL - || (id = ossl_namemap_name2num(namemap, names)) == 0) - return 0; - - if (store == NULL && (store = get_serializer_store(libctx)) == NULL) - return 0; - - return ossl_method_store_add(store, prov, id, propdef, method, - (int (*)(void *))OSSL_SERIALIZER_up_ref, - (void (*)(void *))OSSL_SERIALIZER_free); -} - -/* Create and populate a serializer method */ -static void *serializer_from_dispatch(int id, const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov) -{ - OSSL_SERIALIZER *ser = NULL; - const OSSL_DISPATCH *fns = algodef->implementation; - - if ((ser = ossl_serializer_new()) == NULL) - return NULL; - ser->base.id = id; - ser->base.propdef = algodef->property_definition; - - for (; fns->function_id != 0; fns++) { - switch (fns->function_id) { - case OSSL_FUNC_SERIALIZER_NEWCTX: - if (ser->newctx == NULL) - ser->newctx = - OSSL_FUNC_serializer_newctx(fns); - break; - case OSSL_FUNC_SERIALIZER_FREECTX: - if (ser->freectx == NULL) - ser->freectx = - OSSL_FUNC_serializer_freectx(fns); - break; - case OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS: - if (ser->set_ctx_params == NULL) - ser->set_ctx_params = - OSSL_FUNC_serializer_set_ctx_params(fns); - break; - case OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS: - if (ser->settable_ctx_params == NULL) - ser->settable_ctx_params = - OSSL_FUNC_serializer_settable_ctx_params(fns); - break; - case OSSL_FUNC_SERIALIZER_SERIALIZE_DATA: - if (ser->serialize_data == NULL) - ser->serialize_data = - OSSL_FUNC_serializer_serialize_data(fns); - break; - case OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT: - if (ser->serialize_object == NULL) - ser->serialize_object = - OSSL_FUNC_serializer_serialize_object(fns); - break; - } - } - /* - * Try to check that the method is sensible. - * If you have a constructor, you must have a destructor and vice versa. - * You must have at least one of the serializing driver functions. - */ - if (!((ser->newctx == NULL && ser->freectx == NULL) - || (ser->newctx != NULL && ser->freectx != NULL)) - || (ser->serialize_data == NULL && ser->serialize_object == NULL)) { - OSSL_SERIALIZER_free(ser); - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_INVALID_PROVIDER_FUNCTIONS); - return NULL; - } - - if (prov != NULL && !ossl_provider_up_ref(prov)) { - OSSL_SERIALIZER_free(ser); - return NULL; - } - - ser->base.prov = prov; - return ser; -} - - -/* - * The core fetching functionality passes the names of the implementation. - * This function is responsible to getting an identity number for them, - * then call serializer_from_dispatch() with that identity number. - */ -static void *construct_serializer(const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov, void *unused) -{ - /* - * This function is only called if get_serializer_from_store() returned - * NULL, so it's safe to say that of all the spots to create a new - * namemap entry, this is it. Should the name already exist there, we - * know that ossl_namemap_add() will return its corresponding number. - */ - OPENSSL_CTX *libctx = ossl_provider_library_context(prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - const char *names = algodef->algorithm_names; - int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); - void *method = NULL; - - if (id != 0) - method = serializer_from_dispatch(id, algodef, prov); - - return method; -} - -/* Intermediary function to avoid ugly casts, used below */ -static void destruct_serializer(void *method, void *data) -{ - OSSL_SERIALIZER_free(method); -} - -static int up_ref_serializer(void *method) -{ - return OSSL_SERIALIZER_up_ref(method); -} - -static void free_serializer(void *method) -{ - OSSL_SERIALIZER_free(method); -} - -/* Fetching support. Can fetch by numeric identity or by name */ -static OSSL_SERIALIZER *inner_ossl_serializer_fetch(OPENSSL_CTX *libctx, - int id, const char *name, - const char *properties) -{ - OSSL_METHOD_STORE *store = get_serializer_store(libctx); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - void *method = NULL; - - if (store == NULL || namemap == NULL) - return NULL; - - /* - * If we have been passed neither a name_id or a name, we have an - * internal programming error. - */ - if (!ossl_assert(id != 0 || name != NULL)) - return NULL; - - if (id == 0) - id = ossl_namemap_name2num(namemap, name); - - if (id == 0 - || !ossl_method_store_cache_get(store, id, properties, &method)) { - OSSL_METHOD_CONSTRUCT_METHOD mcm = { - alloc_tmp_serializer_store, - dealloc_tmp_serializer_store, - get_serializer_from_store, - put_serializer_in_store, - construct_serializer, - destruct_serializer - }; - struct serializer_data_st mcmdata; - - mcmdata.libctx = libctx; - mcmdata.mcm = &mcm; - mcmdata.id = id; - mcmdata.names = name; - mcmdata.propquery = properties; - if ((method = ossl_method_construct(libctx, OSSL_OP_SERIALIZER, - 0 /* !force_cache */, - &mcm, &mcmdata)) != NULL) { - /* - * If construction did create a method for us, we know that - * there is a correct name_id and meth_id, since those have - * already been calculated in get_serializer_from_store() and - * put_serializer_in_store() above. - */ - if (id == 0) - id = ossl_namemap_name2num(namemap, name); - ossl_method_store_cache_set(store, id, properties, method, - up_ref_serializer, free_serializer); - } - } - - return method; -} - -OSSL_SERIALIZER *OSSL_SERIALIZER_fetch(OPENSSL_CTX *libctx, const char *name, - const char *properties) -{ - return inner_ossl_serializer_fetch(libctx, 0, name, properties); -} - -OSSL_SERIALIZER *ossl_serializer_fetch_by_number(OPENSSL_CTX *libctx, int id, - const char *properties) -{ - return inner_ossl_serializer_fetch(libctx, id, NULL, properties); -} - -/* - * Library of basic method functions - */ - -const OSSL_PROVIDER *OSSL_SERIALIZER_provider(const OSSL_SERIALIZER *ser) -{ - if (!ossl_assert(ser != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return ser->base.prov; -} - -const char *OSSL_SERIALIZER_properties(const OSSL_SERIALIZER *ser) -{ - if (!ossl_assert(ser != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return ser->base.propdef; -} - -int OSSL_SERIALIZER_number(const OSSL_SERIALIZER *ser) -{ - if (!ossl_assert(ser != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return ser->base.id; -} - -int OSSL_SERIALIZER_is_a(const OSSL_SERIALIZER *ser, const char *name) -{ - if (ser->base.prov != NULL) { - OPENSSL_CTX *libctx = ossl_provider_library_context(ser->base.prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - return ossl_namemap_name2num(namemap, name) == ser->base.id; - } - return 0; -} - -struct serializer_do_all_data_st { - void (*user_fn)(void *method, void *arg); - void *user_arg; -}; - -static void serializer_do_one(OSSL_PROVIDER *provider, - const OSSL_ALGORITHM *algodef, - int no_store, void *vdata) -{ - struct serializer_do_all_data_st *data = vdata; - OPENSSL_CTX *libctx = ossl_provider_library_context(provider); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - const char *names = algodef->algorithm_names; - int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); - void *method = NULL; - - if (id != 0) - method = - serializer_from_dispatch(id, algodef, provider); - - if (method != NULL) { - data->user_fn(method, data->user_arg); - OSSL_SERIALIZER_free(method); - } -} - -void OSSL_SERIALIZER_do_all_provided(OPENSSL_CTX *libctx, - void (*fn)(OSSL_SERIALIZER *ser, - void *arg), - void *arg) -{ - struct serializer_do_all_data_st data; - - data.user_fn = (void (*)(void *, void *))fn; - data.user_arg = arg; - - /* - * No pre- or post-condition for this call, as this only creates methods - * temporarly and then promptly destroys them. - */ - ossl_algorithm_do_all(libctx, OSSL_OP_SERIALIZER, NULL, NULL, - serializer_do_one, NULL, &data); -} - -void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *ser, - void (*fn)(const char *name, void *data), - void *data) -{ - if (ser == NULL) - return; - - if (ser->base.prov != NULL) { - OPENSSL_CTX *libctx = ossl_provider_library_context(ser->base.prov); - OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); - - ossl_namemap_doall_names(namemap, ser->base.id, fn, data); - } -} - -const OSSL_PARAM *OSSL_SERIALIZER_settable_ctx_params(OSSL_SERIALIZER *ser) -{ - if (ser != NULL && ser->settable_ctx_params != NULL) - return ser->settable_ctx_params( - ossl_provider_ctx(OSSL_SERIALIZER_provider(ser))); - return NULL; -} - -/* - * Serializer context support - */ - -/* - * |ser| value NULL is valid, and signifies that there is no serializer. - * This is useful to provide fallback mechanisms. - * Functions that want to verify if there is a serializer can do so with - * OSSL_SERIALIZER_CTX_get_serializer() - */ -OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new(OSSL_SERIALIZER *ser) -{ - OSSL_SERIALIZER_CTX *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE); - return NULL; - } - - ctx->ser = ser; - if (ser != NULL && ser->newctx != NULL) { - const OSSL_PROVIDER *prov = OSSL_SERIALIZER_provider(ser); - void *provctx = ossl_provider_ctx(prov); - - if (OSSL_SERIALIZER_up_ref(ser)) { - ctx->serctx = ser->newctx(provctx); - } else { - OSSL_SERIALIZER_free(ser); - OPENSSL_free(ctx); - ctx = NULL; - } - } - - return ctx; -} - -const OSSL_SERIALIZER * -OSSL_SERIALIZER_CTX_get_serializer(OSSL_SERIALIZER_CTX *ctx) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return ctx->ser; -} - - -int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx, - const OSSL_PARAM params[]) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (ctx->ser != NULL && ctx->ser->set_ctx_params != NULL) - return ctx->ser->set_ctx_params(ctx->serctx, params); - return 0; -} - -void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx) -{ - if (ctx != NULL) { - if (ctx->ser != NULL && ctx->ser->freectx != NULL) - ctx->ser->freectx(ctx->serctx); - OSSL_SERIALIZER_free(ctx->ser); - UI_destroy_method(ctx->allocated_ui_method); - OPENSSL_free(ctx); - } -} diff --git a/crypto/serializer/serializer_pkey.c b/crypto/serializer/serializer_pkey.c deleted file mode 100644 index d31b3cce8b..0000000000 --- a/crypto/serializer/serializer_pkey.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2019-2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/err.h> -#include <openssl/ui.h> -#include <openssl/params.h> -#include <openssl/serializer.h> -#include <openssl/core_names.h> -#include <openssl/safestack.h> -#include "internal/provider.h" -#include "internal/property.h" -#include "crypto/evp.h" -#include "serializer_local.h" - -DEFINE_STACK_OF_CSTRING() - -int OSSL_SERIALIZER_CTX_set_cipher(OSSL_SERIALIZER_CTX *ctx, - const char *cipher_name, - const char *propquery) -{ - OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; - - params[0] = - OSSL_PARAM_construct_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, - (void *)cipher_name, 0); - params[1] = - OSSL_PARAM_construct_utf8_string(OSSL_SERIALIZER_PARAM_PROPERTIES, - (void *)propquery, 0); - - return OSSL_SERIALIZER_CTX_set_params(ctx, params); -} - -int OSSL_SERIALIZER_CTX_set_passphrase(OSSL_SERIALIZER_CTX *ctx, - const unsigned char *kstr, - size_t klen) -{ - OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; - - params[0] = OSSL_PARAM_construct_octet_string(OSSL_SERIALIZER_PARAM_PASS, - (void *)kstr, klen); - - return OSSL_SERIALIZER_CTX_set_params(ctx, params); -} - -static void serializer_ctx_reset_passphrase_ui(OSSL_SERIALIZER_CTX *ctx) -{ - UI_destroy_method(ctx->allocated_ui_method); - ctx->allocated_ui_method = NULL; - ctx->ui_method = NULL; - ctx->ui_data = NULL; -} - -int OSSL_SERIALIZER_CTX_set_passphrase_ui(OSSL_SERIALIZER_CTX *ctx, - const UI_METHOD *ui_method, - void *ui_data) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - serializer_ctx_reset_passphrase_ui(ctx); - ctx->ui_method = ui_method; - ctx->ui_data = ui_data; - return 1; -} - -int OSSL_SERIALIZER_CTX_set_passphrase_cb(OSSL_SERIALIZER_CTX *ctx, - pem_password_cb *cb, void *cbarg) -{ - if (!ossl_assert(ctx != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - serializer_ctx_reset_passphrase_ui(ctx); - if (cb == NULL) - return 1; - ctx->ui_method = - ctx->allocated_ui_method = UI_UTIL_wrap_read_pem_callback(cb, 1); - ctx->ui_data = cbarg; - - return ctx->ui_method != NULL; -} - -/* - * Support for OSSL_SERIALIZER_CTX_new_by_TYPE: - * finding a suitable serializer - */ - -struct selected_serializer_st { - STACK_OF(OPENSSL_CSTRING) *names; - int error; -}; - -static void cache_serializers(const char *name, void *data) -{ - struct selected_serializer_st *d = data; - - if (sk_OPENSSL_CSTRING_push(d->names, name) <= 0) - d->error = 1; -} - -/* - * Support for OSSL_SERIALIZER_to_bio: - * writing callback for the OSSL_PARAM (the implementation doesn't have - * intimate knowledge of the provider side object) - */ - -struct serializer_write_data_st { - OSSL_SERIALIZER_CTX *ctx; - BIO *out; -}; - -static int serializer_write_cb(const OSSL_PARAM params[], void *arg) -{ - struct serializer_write_data_st *write_data = arg; - OSSL_SERIALIZER_CTX *ctx = write_data->ctx; - BIO *out = write_data->out; - - return ctx->ser->serialize_data(ctx->serctx, params, (OSSL_CORE_BIO *)out, - ossl_serializer_passphrase_out_cb, ctx); -} - -/* - * Support for OSSL_SERIALIZER_to_bio: - * Perform the actual output. - */ - -static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out) -{ - const EVP_PKEY *pkey = ctx->object; - void *keydata = pkey->keydata; - EVP_KEYMGMT *keymgmt = pkey->keymgmt; - - /* - * OSSL_SERIALIZER_CTX_new() creates a context, even when the - * serializer it's given is NULL. Callers can detect the lack - * of serializer with OSSL_SERIALIZER_CTX_get_serializer() and - * should take precautions, possibly call a fallback instead of - * OSSL_SERIALIZER_to_bio() / OSSL_SERIALIZER_to_fp(). If it's - * come this far, we return an error. - */ - if (ctx->ser == NULL) - return 0; - - if (ctx->ser->serialize_object == NULL - || OSSL_SERIALIZER_provider(ctx->ser) != EVP_KEYMGMT_provider(keymgmt)) { - struct serializer_write_data_st write_data; - - write_data.ctx = ctx; - write_data.out = out; - - return evp_keymgmt_export(keymgmt, keydata, ctx->selection, - &serializer_write_cb, &write_data); - } - - return ctx->ser->serialize_object(ctx->serctx, keydata, - (OSSL_CORE_BIO *)out, - ossl_serializer_passphrase_out_cb, ctx); -} - -/* - * OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() returns a ctx with no serializer if - * it couldn't find a suitable serializer. This allows a caller to detect if - * a suitable serializer was found, with OSSL_SERIALIZER_CTX_get_serializer(), - * and to use fallback methods if the result is NULL. - */ -OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey, - const char *propquery) -{ - OSSL_SERIALIZER_CTX *ctx = NULL; - OSSL_SERIALIZER *ser = NULL; - EVP_KEYMGMT *keymgmt = pkey->keymgmt; - int selection = OSSL_KEYMGMT_SELECT_ALL; - - if (!ossl_assert(pkey != NULL && propquery != NULL)) { - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER); - return NULL; - } - - if (keymgmt != NULL) { - const OSSL_PROVIDER *desired_prov = EVP_KEYMGMT_provider(keymgmt); - OPENSSL_CTX *libctx = ossl_provider_library_context(desired_prov); - struct selected_serializer_st sel_data; - OSSL_SERIALIZER *first = NULL; - const char *name; - int i; - - /* - * Select the serializer in two steps. First, get the names of all of - * the serializers. Then determine which is the best one to use. - * This has to be broken because it isn't possible to fetch the - * serialisers inside EVP_KEYMGMT_names_do_all() due to locking - * order inversions with the store lock. - */ - sel_data.error = 0; - sel_data.names = sk_OPENSSL_CSTRING_new_null(); - if (sel_data.names == NULL) - return NULL; - EVP_KEYMGMT_names_do_all(keymgmt, cache_serializers, &sel_data); - /* - * Ignore memory allocation errors that are indicated in sel_data.error - * in case a suitable provider does get found regardless. - */ - - /* - * Serializers offer two functions, one that handles object data in - * the form of a OSSL_PARAM array, and one that directly handles a - * provider side object. The latter requires that the serializer - * is offered by the same provider that holds that object, but is - * more desirable because it usually provides faster serialization. - * - * When looking up possible serializers, we save the first that can - * handle an OSSL_PARAM array in |first| and use that if nothing - * better turns up. - */ - for (i = 0; i < sk_OPENSSL_CSTRING_num(sel_data.names); i++) { - name = sk_OPENSSL_CSTRING_value(sel_data.names, i); - ser = OSSL_SERIALIZER_fetch(libctx, name, propquery); - if (ser != NULL) { - if (OSSL_SERIALIZER_provider(ser) == desired_prov - && ser->serialize_object != NULL) { - OSSL_SERIALIZER_free(first); - break; - } - if (first == NULL && ser->serialize_data != NULL) - first = ser; - else - OSSL_SERIALIZER_free(ser); - ser = NULL; - } - } - sk_OPENSSL_CSTRING_free(sel_data.names); - if (ser == NULL) - ser = first; - - if (ser != NULL) { - OSSL_PROPERTY_LIST *check = NULL, *current_props = NULL; - - check = ossl_parse_query(libctx, "type=parameters"); - current_props = - ossl_parse_property(libctx, OSSL_SERIALIZER_properties(ser)); - if (ossl_property_match_count(check, current_props) > 0) - selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; - ossl_property_free(current_props); - ossl_property_free(check); - } else { - if (sel_data.error) - ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE); - else - ERR_raise(ERR_LIB_OSSL_SERIALIZER, - OSSL_SERIALIZER_R_SERIALIZER_NOT_FOUND); - } - } - - ctx = OSSL_SERIALIZER_CTX_new(ser); /* refcnt(ser)++ */ - OSSL_SERIALIZER_free(ser); /* refcnt(ser)-- */ - - if (ctx != NULL) { - /* Setup for OSSL_SERIALIZE_to_bio() */ - ctx->selection = selection; - ctx->object = pkey; - ctx->do_output = serializer_EVP_PKEY_to_bio; - } - - return ctx; -} - diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 59f4a14895..cb47f917ad 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -22,7 +22,7 @@ #include "crypto/x509.h" #include <openssl/rsa.h> #include <openssl/dsa.h> -#include <openssl/serializer.h> +#include <openssl/encoder.h> struct X509_pubkey_st { X509_ALGOR *algor; @@ -97,18 +97,18 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) } } else if (pkey->keymgmt != NULL) { BIO *bmem = BIO_new(BIO_s_mem()); - const char *serprop = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ; - OSSL_SERIALIZER_CTX *sctx = - OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, serprop); + const char *encprop = OSSL_ENCODER_PUBKEY_TO_DER_PQ; + OSSL_ENCODER_CTX *ectx = + OSSL_ENCODER_CTX_new_by_EVP_PKEY(pkey, encprop); - if (OSSL_SERIALIZER_to_bio(sctx, bmem)) { + if (OSSL_ENCODER_to_bio(ectx, bmem)) { const unsigned char *der = NULL; long derlen = BIO_get_mem_data(bmem, (char **)&der); pk = d2i_X509_PUBKEY(NULL, &der, derlen); } - OSSL_SERIALIZER_CTX_free(sctx); + OSSL_ENCODER_CTX_free(ectx); BIO_free(bmem); } @@ -124,7 +124,7 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) /* * pk->pkey is NULL when using the legacy routine, but is non-NULL when - * going through the serializer, and for all intents and purposes, it's + * going through the encoder, and for all intents and purposes, it's * a perfect copy of |pkey|, just not the same instance. In that case, * we could simply return early, right here. * However, in the interest of being cautious leaning on paranoia, some @@ -303,16 +303,16 @@ int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp) } X509_PUBKEY_free(xpk); } else if (a->keymgmt != NULL) { - const char *serprop = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ; - OSSL_SERIALIZER_CTX *ctx = - OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(a, serprop); + const char *encprop = OSSL_ENCODER_PUBKEY_TO_DER_PQ; + OSSL_ENCODER_CTX *ctx = + OSSL_ENCODER_CTX_new_by_EVP_PKEY(a, encprop); BIO *out = BIO_new(BIO_s_mem()); BUF_MEM *buf = NULL; if (ctx != NULL && out != NULL - && OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL - && OSSL_SERIALIZER_to_bio(ctx, out) + && OSSL_ENCODER_CTX_get_encoder(ctx) != NULL + && OSSL_ENCODER_to_bio(ctx, out) && BIO_get_mem_ptr(out, &buf) > 0) { ret = buf->length; @@ -328,7 +328,7 @@ int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp) } } BIO_free(out); - OSSL_SERIALIZER_CTX_free(ctx); + OSSL_ENCODER_CTX_free(ctx); } return ret; |