return "PEM";
case FORMAT_ASN1:
return "DER";
+ case FORMAT_PVK:
+ return "PVK";
+ case FORMAT_MSBLOB:
+ return "MSBLOB";
}
return NULL;
}
return 1;
}
+OSSL_DECODER_INSTANCE *
+ossl_decoder_instance_new_forprov(OSSL_DECODER *decoder, void *provctx,
+ const char *input_structure)
+{
+ void *decoderctx;
+
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ decoderctx = decoder->newctx(provctx);
+ if (decoderctx == NULL)
+ return 0;
+ if (input_structure != NULL && decoder->set_ctx_params != NULL) {
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+ (char *)input_structure, 0);
+ if (!decoder->set_ctx_params(decoderctx, params)) {
+ decoder->freectx(decoderctx);
+ return 0;
+ }
+ }
+ return ossl_decoder_instance_new(decoder, decoderctx);
+}
+
OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
void *decoderctx)
{
if ((decoderctx = decoder->newctx(provctx)) == NULL)
return;
- if (data->ctx->input_structure != NULL) {
+ if (decoder->set_ctx_params != NULL
+ && data->ctx->input_structure != NULL) {
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
const char *str = data->ctx->input_structure;
params[0] =
OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
(char *)str, 0);
- if (decoder->set_ctx_params != NULL
- && !decoder->set_ctx_params(decoderctx, params)) {
+ if (!decoder->set_ctx_params(decoderctx, params)) {
decoder->freectx(decoderctx);
return;
}
sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
OSSL_DECODER *new_decoder =
OSSL_DECODER_INSTANCE_get_decoder(new_decoder_inst);
+ const char *new_decoder_name = NULL;
void *new_decoderctx =
OSSL_DECODER_INSTANCE_get_decoder_ctx(new_decoder_inst);
const char *new_input_type =
&n_i_s_was_set);
OSSL_TRACE_BEGIN(DECODER) {
+ new_decoder_name = OSSL_DECODER_get0_name(new_decoder);
BIO_printf(trc_out,
"(ctx %p) %s [%u] Considering decoder instance %p (decoder %p):\n"
" %s with %s\n",
(void *)new_data.ctx, LEVEL, (unsigned int)i,
(void *)new_decoder_inst, (void *)new_decoder,
- OSSL_DECODER_get0_name(new_decoder),
+ new_decoder_name,
OSSL_DECODER_get0_properties(new_decoder));
} OSSL_TRACE_END(DECODER);
/* Recurse */
OSSL_TRACE_BEGIN(DECODER) {
BIO_printf(trc_out,
- "(ctx %p) %s [%u] Running decoder instance %p\n",
+ "(ctx %p) %s [%u] Running decoder instance %s (%p)\n",
(void *)new_data.ctx, LEVEL, (unsigned int)i,
- (void *)new_decoder_inst);
+ new_decoder_name, (void *)new_decoder_inst);
} OSSL_TRACE_END(DECODER);
/*
OSSL_TRACE_BEGIN(DECODER) {
BIO_printf(trc_out,
- "(ctx %p) %s [%u] Running decoder instance %p => %d"
+ "(ctx %p) %s [%u] Running decoder instance %s (%p) => %d"
" (recursed further: %s, construct called: %s)\n",
(void *)new_data.ctx, LEVEL, (unsigned int)i,
- (void *)new_decoder_inst, ok,
+ new_decoder_name, (void *)new_decoder_inst, ok,
new_data.flag_next_level_called ? "yes" : "no",
new_data.flag_construct_called ? "yes" : "no");
} OSSL_TRACE_END(DECODER);
return;
}
+ /*
+ * Input types must be compatible, but we must accept DER encoders when the
+ * start input type is "PEM".
+ */
+ if (data->ctx->start_input_type != NULL
+ && di->input_type != NULL
+ && OPENSSL_strcasecmp(di->input_type, data->ctx->start_input_type) != 0
+ && (OPENSSL_strcasecmp(di->input_type, "DER") != 0
+ || OPENSSL_strcasecmp(data->ctx->start_input_type, "PEM") != 0)) {
+ /* Mismatch is not an error, continue. */
+ ossl_decoder_instance_free(di);
+ return;
+ }
+
OSSL_TRACE_BEGIN(DECODER) {
BIO_printf(trc_out,
"(ctx %p) Checking out decoder %p:\n"
PEM_R_UNSUPPORTED_ENCRYPTION:114:unsupported encryption
PEM_R_UNSUPPORTED_KEY_COMPONENTS:126:unsupported key components
PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE:110:unsupported public key type
+PEM_R_UNSUPPORTED_PVK_KEY_TYPE:133:unsupported pvk key type
PKCS12_R_CALLBACK_FAILED:115:callback failed
PKCS12_R_CANT_PACK_STRUCTURE:100:can't pack structure
PKCS12_R_CONTENT_TYPE_NOT_DATA:121:content type not data
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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
"unsupported key components"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE),
"unsupported public key type"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_PVK_KEY_TYPE),
+ "unsupported pvk key type"},
{0, NULL}
};
}
int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
- int skip_magic,
+ int skip_magic, int *isdss,
unsigned int *psaltlen, unsigned int *pkeylen)
{
const unsigned char *p = *in;
}
/* Skip reserved */
p += 4;
- /*
- * keytype =
- */ read_ledword(&p);
+ /* Check the key type */
+ switch (read_ledword(&p)) {
+ case MS_KEYTYPE_KEYX:
+ if (*isdss == 1) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB);
+ return 0;
+ }
+ *isdss = 0;
+ break;
+ case MS_KEYTYPE_SIGN:
+ if (*isdss == 0) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB);
+ return 0;
+ }
+ *isdss = 1;
+ break;
+ default:
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PVK_KEY_TYPE);
+ return 0;
+ }
is_encrypted = read_ledword(&p);
*psaltlen = read_ledword(&p);
*pkeylen = read_ledword(&p);
}
p = pvk_hdr;
- if (!ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen))
+ if (!ossl_do_PVK_header(&p, 24, 0, isdss, &saltlen, &keylen))
return 0;
buflen = (int)keylen + saltlen;
buf = OPENSSL_malloc(buflen);
struct extracted_param_data_st {
int object_type;
const char *data_type;
+ const char *input_type;
const char *data_structure;
const char *utf8_data;
const void *octet_data;
if (p != NULL
&& !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure))
return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_INPUT_TYPE);
+ if (p != NULL
+ && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.input_type))
+ return 0;
p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE);
if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref,
&helper_data.ref_size))
}
decoderctx =
- OSSL_DECODER_CTX_new_for_pkey(&pk, NULL, data->data_structure,
+ OSSL_DECODER_CTX_new_for_pkey(&pk, data->input_type, data->data_structure,
data->data_type, selection, libctx,
propq);
(void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg);
{
unsigned int saltlen = 0, keylen = 0;
+ int isdss = -1;
unsigned char peekbuf[24] = { 0, };
const unsigned char *p = peekbuf;
if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
return 0;
- if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &saltlen, &keylen))
+ if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &isdss, &saltlen, &keylen))
return 0;
}
OSSL_PROVIDER *prov);
OSSL_DECODER_INSTANCE *
+ossl_decoder_instance_new_forprov(OSSL_DECODER *decoder, void *provctx,
+ const char *input_structure);
+OSSL_DECODER_INSTANCE *
ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx);
void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst);
int ossl_decoder_ctx_get_harderr(const OSSL_DECODER_CTX *ctx);
int *pisdss, int *pispub);
unsigned int ossl_blob_length(unsigned bitlen, int isdss, int ispub);
int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
- int skip_magic,
+ int skip_magic, int *isdss,
unsigned int *psaltlen, unsigned int *pkeylen);
# ifndef OPENSSL_NO_DEPRECATED_3_0
# ifndef OPENSSL_NO_DSA
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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
# define PEM_R_UNSUPPORTED_ENCRYPTION 114
# define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126
# define PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE 110
+# define PEM_R_UNSUPPORTED_PVK_KEY_TYPE 133
#endif
{
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 */
*/
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;
}
* 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;
}
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
*/
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)) {
#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"
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.
int ok = 1;
if (mem != NULL) {
- OSSL_PARAM params[3];
-
- 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();
+ OSSL_PARAM params[6], *p = params;
+
+ 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);
}
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;
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;
}
/* 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:
}
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;
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;
}
/* 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:
{ 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 \
}
{
const unsigned char *in = data;
unsigned int saltlen = 0, keylen = 0;
- int ok = ossl_do_PVK_header(&in, data_len, 0, &saltlen, &keylen);
+ int isdss = -1;
- return ok;
+ return ossl_do_PVK_header(&in, data_len, 0, &isdss, &saltlen, &keylen);
}
static int test_unprotected_via_PVK(const char *type, EVP_PKEY *key)