Further decoder tuning possibly better perf

- The decoder should consider fewer options based on
  more precise tracking of the desired input type
  (DER, PVK, MSBLOB), algorithm (RSA, EC, ...),
  input structure (SPKI, P8, ...).

How much this affects actual use-cases is harder to estimate, we'll just
have to run before/after perf tests.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26927)
This commit is contained in:
Viktor Dukhovni 2025-02-28 04:17:08 +11:00 committed by Geert
parent 89dbc6a62c
commit 31b5f3f382
14 changed files with 198 additions and 46 deletions

View file

@ -416,6 +416,7 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
{
OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx);
const OSSL_ALGORITHM *to_algo = NULL;
const char *input_structure = NULL;
int ok = 0;
/* Setup for this session, so only if not already done */
@ -440,8 +441,9 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
*/
switch (ctx->expected_type) {
case OSSL_STORE_INFO_PUBKEY:
input_structure = "SubjectPublicKeyInfo";
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"SubjectPublicKeyInfo")) {
input_structure)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
@ -456,22 +458,25 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
* might then get a password prompt for a key when reading only
* certs from a file.
*/
input_structure = "EncryptedPrivateKeyInfo";
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"EncryptedPrivateKeyInfo")) {
input_structure)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
break;
case OSSL_STORE_INFO_CERT:
input_structure = "Certificate";
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"Certificate")) {
input_structure)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
break;
case OSSL_STORE_INFO_CRL:
input_structure = "CertificateList";
if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
"CertificateList")) {
input_structure)) {
ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
goto err;
}
@ -485,6 +490,7 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
to_algo++) {
OSSL_DECODER *to_obj = NULL;
OSSL_DECODER_INSTANCE *to_obj_inst = NULL;
const char *input_type;
/*
* Create the internal last resort decoder implementation
@ -494,10 +500,25 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
*/
to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL);
if (to_obj != NULL)
to_obj_inst = ossl_decoder_instance_new(to_obj, ctx->provctx);
to_obj_inst =
ossl_decoder_instance_new_forprov(to_obj, ctx->provctx,
input_structure);
OSSL_DECODER_free(to_obj);
if (to_obj_inst == NULL)
goto err;
/*
* The input type has to match unless, the input type is PEM
* and the decoder input type is DER, in which case we'll pick
* up additional decoders.
*/
input_type = OSSL_DECODER_INSTANCE_get_input_type(to_obj_inst);
if (ctx->_.file.input_type != NULL
&& OPENSSL_strcasecmp(input_type, ctx->_.file.input_type) != 0
&& (OPENSSL_strcasecmp(ctx->_.file.input_type, "PEM") != 0
|| OPENSSL_strcasecmp(input_type, "der") != 0)) {
ossl_decoder_instance_free(to_obj_inst);
continue;
}
if (!ossl_decoder_ctx_add_decoder_inst(ctx->_.file.decoderctx,
to_obj_inst)) {

View file

@ -32,6 +32,7 @@
#include <openssl/asn1err.h>
#include <openssl/params.h>
#include "internal/asn1.h"
#include "internal/sizes.h"
#include "crypto/pem.h" /* For internal PVK and "blob" headers */
#include "prov/bio.h"
#include "file_store_local.h"
@ -45,18 +46,54 @@
static OSSL_FUNC_decoder_newctx_fn any2obj_newctx;
static OSSL_FUNC_decoder_freectx_fn any2obj_freectx;
struct any2obj_ctx_st {
PROV_CTX *provctx;
char data_structure[OSSL_MAX_CODEC_STRUCT_SIZE];
};
static void *any2obj_newctx(void *provctx)
{
return provctx;
struct any2obj_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ctx->provctx = provctx;
return ctx;
}
static void any2obj_freectx(void *vctx)
static void any2obj_freectx(void *ctx)
{
OPENSSL_free(ctx);
}
static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem,
static int any2obj_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
struct any2obj_ctx_st *ctx = vctx;
const OSSL_PARAM *p;
char *str;
p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
str = ctx->data_structure;
if (p != NULL
&& !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->data_structure)))
return 0;
return 1;
}
static const OSSL_PARAM *any2obj_settable_ctx_params(ossl_unused void *provctx)
{
static const OSSL_PARAM settables[] = {
OSSL_PARAM_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, NULL, 0),
OSSL_PARAM_END
};
return settables;
}
static int any2obj_decode_final(void *vctx, int objtype, const char *input_type,
const char *data_type, BUF_MEM *mem,
OSSL_CALLBACK *data_cb, void *data_cbarg)
{
struct any2obj_ctx_st *ctx = vctx;
/*
* 1 indicates that we successfully decoded something, or not at all.
* Ending up "empty handed" is not an error.
@ -64,14 +101,21 @@ static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem,
int ok = 1;
if (mem != NULL) {
OSSL_PARAM params[3];
OSSL_PARAM params[6], *p = params;
params[0] =
OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
params[1] =
OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
mem->data, mem->length);
params[2] = OSSL_PARAM_construct_end();
if (data_type != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
(char *)data_type, 0);
if (input_type != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_INPUT_TYPE,
(char *)input_type, 0);
if (*ctx->data_structure != '\0')
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
(char *)ctx->data_structure, 0);
*p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
mem->data, mem->length);
*p = OSSL_PARAM_construct_end();
ok = data_cb(params, data_cbarg);
BUF_MEM_free(mem);
@ -80,11 +124,12 @@ static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem,
}
static OSSL_FUNC_decoder_decode_fn der2obj_decode;
static int der2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
static int der2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
OSSL_CALLBACK *data_cb, void *data_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
struct any2obj_ctx_st *ctx = vctx;
BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
BUF_MEM *mem = NULL;
int ok;
@ -101,16 +146,17 @@ static int der2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
BIO_free(in);
/* any2obj_decode_final() frees |mem| for us */
return any2obj_decode_final(provctx, OSSL_OBJECT_UNKNOWN, mem,
return any2obj_decode_final(ctx, OSSL_OBJECT_UNKNOWN, NULL, NULL, mem,
data_cb, data_cbarg);
}
static OSSL_FUNC_decoder_decode_fn msblob2obj_decode;
static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
static int msblob2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
OSSL_CALLBACK *data_cb, void *data_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
struct any2obj_ctx_st *ctx = vctx;
BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
BUF_MEM *mem = NULL;
size_t mem_len = 0, mem_want;
const unsigned char *p;
@ -165,7 +211,8 @@ static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
}
/* any2obj_decode_final() frees |mem| for us */
return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
return any2obj_decode_final(ctx, OSSL_OBJECT_PKEY, "msblob",
isdss ? "DSA" : "RSA", mem,
data_cb, data_cbarg);
err:
@ -175,16 +222,17 @@ static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
}
static OSSL_FUNC_decoder_decode_fn pvk2obj_decode;
static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
static int pvk2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
OSSL_CALLBACK *data_cb, void *data_cbarg,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
struct any2obj_ctx_st *ctx = vctx;
BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
BUF_MEM *mem = NULL;
size_t mem_len = 0, mem_want;
const unsigned char *p;
unsigned int saltlen, keylen;
int ok = 0;
int ok = 0, isdss = -1;
if (in == NULL)
goto err;
@ -206,7 +254,7 @@ static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
ERR_set_mark();
p = (unsigned char *)&mem->data[0];
ok = ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen) > 0;
ok = ossl_do_PVK_header(&p, 24, 0, &isdss, &saltlen, &keylen) > 0;
ERR_pop_to_mark();
if (!ok)
goto next;
@ -232,7 +280,8 @@ static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
}
/* any2obj_decode_final() frees |mem| for us */
return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
return any2obj_decode_final(ctx, OSSL_OBJECT_PKEY, "pvk",
ok ? (isdss ? "DSA" : "RSA") : NULL, mem,
data_cb, data_cbarg);
err:
@ -246,6 +295,10 @@ static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
{ OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))any2obj_newctx }, \
{ OSSL_FUNC_DECODER_FREECTX, (void (*)(void))any2obj_freectx }, \
{ OSSL_FUNC_DECODER_DECODE, (void (*)(void))fromtype##2obj_decode }, \
{ OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, \
(void (*)(void))any2obj_settable_ctx_params }, \
{ OSSL_FUNC_DECODER_SET_CTX_PARAMS, \
(void (*)(void))any2obj_set_ctx_params }, \
OSSL_DISPATCH_END \
}