SERIALIZER: add support for serializing EVP_PKEYs

The following public functions is added:

- OSSL_SERIALIZER_CTX_new_by_EVP_PKEY()
- OSSL_SERIALIZER_CTX_set_cipher()
- OSSL_SERIALIZER_CTX_set_passphrase()
- OSSL_SERIALIZER_CTX_set_passphrase_cb()
- OSSL_SERIALIZER_CTX_set_passphrase_ui()

OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() selects a suitable serializer
for the given EVP_PKEY, and sets up the OSSL_SERIALIZER_CTX to
function together with OSSL_SERIALIZER_to_bio() and
OSSL_SERIALIZER_to_fp().

OSSL_SERIALIZER_CTX_set_cipher() indicates what cipher should be used
to produce an encrypted serialization of the EVP_PKEY.  This is passed
directly to the provider using OSSL_SERIALIZER_CTX_set_params().

OSSL_SERIALIZER_CTX_set_passphrase() can be used to set a pass phrase
to be used for the encryption.  This is passed directly to the
provider using OSSL_SERIALIZER_CTX_set_params().

OSSL_SERIALIZER_CTX_set_passphrase_cb() and
OSSL_SERIALIZER_CTX_set_passphrase_ui() sets up a callback to be used
to prompt for a passphrase.  This is stored in the context, and is
called via an internal intermediary at the time of serialization.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10394)
This commit is contained in:
Richard Levitte 2019-11-18 01:34:26 +01:00
parent 1793d270f3
commit 866234ac35
17 changed files with 710 additions and 2 deletions

View File

@ -113,6 +113,7 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_INIT_FAIL, "init fail"},
{ERR_R_OPERATION_FAIL, "operation fail"},
{ERR_R_INVALID_PROVIDER_FUNCTIONS, "invalid provider functions"},
{ERR_R_INTERRUPTED_OR_CANCELLED, "interrupted or cancelled"},
{0, NULL},
};

View File

@ -2550,6 +2550,7 @@ 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_SERIALIZER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query
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

View File

@ -1 +1,2 @@
SOURCE[../../libcrypto]=serializer_meth.c serializer_lib.c
SOURCE[../../libcrypto]=serializer_meth.c serializer_lib.c serializer_pkey.c \
serializer_err.c

View File

@ -0,0 +1,31 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 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"},
{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;
}

View File

@ -38,4 +38,13 @@ struct ossl_serializer_ctx_st {
*/
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;
};

View File

@ -10,6 +10,7 @@
#include <openssl/core.h>
#include <openssl/core_numbers.h>
#include <openssl/serializer.h>
#include <openssl/ui.h>
#include "internal/core.h"
#include "internal/namemap.h"
#include "internal/property.h"
@ -509,6 +510,7 @@ void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx)
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);
}
}

View File

@ -0,0 +1,386 @@
/*
* Copyright 2019 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 "internal/provider.h"
#include "internal/property.h"
#include "crypto/evp.h"
#include "serializer_local.h"
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, int enc,
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, enc);
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 {
OPENSSL_CTX *libctx;
const OSSL_PROVIDER *desired_provider;
const char *propquery;
/*
* When selecting serializers, we need to check the intended use.
* This is governed by the |domainparams| flag in the EVP_PKEY,
* we must just make sure to filter on 'type=domainparams' accordingly.
*/
int want_domainparams;
/*
* 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 the first that can
* handle a provider side object in |desired|.
*/
OSSL_SERIALIZER *first;
OSSL_SERIALIZER *desired;
};
static void select_serializer(const char *name, void *data)
{
struct selected_serializer_st *d = data;
OSSL_SERIALIZER *s = NULL;
OSSL_PROPERTY_LIST *check =
d->want_domainparams
? ossl_parse_query(d->libctx, "type=domainparams")
: NULL;
/* No need to look further if we already have the more desirable option */
if (d->desired != NULL)
return;
if ((s = OSSL_SERIALIZER_fetch(d->libctx, name, d->propquery)) != NULL) {
/*
* Extra check if domain parameters are explicitly specified:
* only accept serializers that have the "type=domainparams"
* property.
*
* For data that isn't marked as domain parameters, a domain
* parameters serializer is still acceptable, because a key
* may hold domain parameters too.
*/
if (d->want_domainparams) {
OSSL_PROPERTY_LIST *current_props =
ossl_parse_property(d->libctx, OSSL_SERIALIZER_properties(s));
int check_cnt = ossl_property_match_count(check, current_props);
if (check_cnt == 0) {
OSSL_SERIALIZER_free(s);
return;
}
}
if (d->first == NULL && s->serialize_data != NULL) {
d->first = s;
} else if (OSSL_SERIALIZER_provider(s) == d->desired_provider
&& s->serialize_object != NULL) {
OSSL_SERIALIZER_free(d->first);
d->first = NULL;
d->desired = s;
} else {
OSSL_SERIALIZER_free(s);
}
}
}
/*
* Support for OSSL_SERIALIZER_CTX_new_by_TYPE and OSSL_SERIALIZER_to_bio:
* Passphrase callbacks
*/
/*
* First, we define the generic passphrase function that supports both
* outgoing (with passphrase verify) and incoming (without passphrase verify)
* passphrase reading.
*/
static int serializer_passphrase(char *pass, size_t pass_size,
size_t *pass_len, int verify,
const OSSL_PARAM params[], void *arg)
{
OSSL_SERIALIZER_CTX *ctx = arg;
const OSSL_PARAM *p;
const char *prompt_info = NULL;
char *prompt = NULL, *vpass = NULL;
int prompt_idx = -1, verify_idx = -1;
UI *ui = NULL;
int ret = 0;
if (!ossl_assert(ctx != NULL && pass != NULL
&& pass_size != 0 && pass_len != NULL)) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((p = OSSL_PARAM_locate_const(params,
OSSL_PASSPHRASE_PARAM_INFO)) != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
prompt_info = p->data;
}
if ((ui = UI_new()) == NULL) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
return 0;
}
UI_set_method(ui, ctx->ui_method);
UI_add_user_data(ui, ctx->ui_data);
/* Get an application constructed prompt */
prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
if (prompt == NULL) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
goto end;
}
prompt_idx = UI_add_input_string(ui, prompt,
UI_INPUT_FLAG_DEFAULT_PWD,
pass, 0, pass_size - 1) - 1;
if (prompt_idx < 0) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_UI_LIB);
goto end;
}
if (verify) {
/* Get a buffer for verification prompt */
vpass = OPENSSL_zalloc(pass_size);
if (vpass == NULL) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
goto end;
}
verify_idx = UI_add_verify_string(ui, prompt,
UI_INPUT_FLAG_DEFAULT_PWD,
vpass, 0, pass_size - 1,
pass) - 1;
if (verify_idx < 0) {
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_UI_LIB);
goto end;
}
}
switch (UI_process(ui)) {
case -2:
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_INTERRUPTED_OR_CANCELLED);
break;
case -1:
ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_UI_LIB);
break;
default:
*pass_len = (size_t)UI_get_result_length(ui, prompt_idx);
ret = 1;
break;
}
end:
OPENSSL_free(vpass);
OPENSSL_free(prompt);
UI_free(ui);
return ret;
}
/* Ensure correct function definition for outgoing passphrase reader */
static OSSL_PASSPHRASE_CALLBACK serializer_passphrase_out_cb;
static int serializer_passphrase_out_cb(char *pass, size_t pass_size,
size_t *pass_len,
const OSSL_PARAM params[], void *arg)
{
return serializer_passphrase(pass, pass_size, pass_len, 1, params, arg);
}
/*
* 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, out,
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 *provdata = pkey->pkeys[0].provdata;
int domainparams = pkey->pkeys[0].domainparams;
EVP_KEYMGMT *keymgmt = pkey->pkeys[0].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) {
struct serializer_write_data_st write_data;
write_data.ctx = ctx;
write_data.out = out;
if (domainparams)
return evp_keymgmt_exportdomparams(keymgmt, provdata,
serializer_write_cb,
&write_data);
return evp_keymgmt_exportkey(keymgmt, provdata,
serializer_write_cb, &write_data);
}
return ctx->ser->serialize_object(ctx->serctx, provdata, out,
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->pkeys[0].keymgmt;
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;
memset(&sel_data, 0, sizeof(sel_data));
sel_data.libctx = libctx;
sel_data.desired_provider = desired_prov;
sel_data.propquery = propquery;
sel_data.want_domainparams = pkey->pkeys[0].domainparams;
EVP_KEYMGMT_names_do_all(keymgmt, select_serializer, &sel_data);
if (sel_data.desired != NULL) {
ser = sel_data.desired;
sel_data.desired = NULL;
} else if (sel_data.first != NULL) {
ser = sel_data.first;
sel_data.first = NULL;
}
OSSL_SERIALIZER_free(sel_data.first);
OSSL_SERIALIZER_free(sel_data.desired);
}
ctx = OSSL_SERIALIZER_CTX_new(ser); /* refcnt(ser)++ */
OSSL_SERIALIZER_free(ser); /* refcnt(ser)-- */
if (ctx != NULL) {
/* Setup for OSSL_SERIALIZE_to_bio() */
ctx->object = pkey;
ctx->do_output = serializer_EVP_PKEY_to_bio;
}
return ctx;
}

View File

@ -111,7 +111,7 @@ OSSL_SERIALIZER_number() returns an integer.
=head1 SEE ALSO
L<provider(7)>, L<OSSL_SERIALIZER_CTX(3)>, L<OSSL_SERIALIZER_to_bio(3)>,
L<OPENSSL_CTX(3)>
L<OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(3)>, L<OPENSSL_CTX(3)>
=head1 HISTORY

View File

@ -0,0 +1,134 @@
=pod
=head1 NAME
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY,
OSSL_SERIALIZER_CTX_set_cipher,
OSSL_SERIALIZER_CTX_set_passphrase,
OSSL_SERIALIZER_CTX_set_passphrase_cb,
OSSL_SERIALIZER_CTX_set_passphrase_ui,
OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ,
OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
OSSL_SERIALIZER_Parameters_TO_PEM_PQ,
OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ,
OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ,
OSSL_SERIALIZER_Parameters_TO_TEXT_PQ
- Serializer routines to serialize EVP_PKEYs
=head1 SYNOPSIS
#include <openssl/serializer.h>
OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
const char *propquery);
int OSSL_SERIALIZER_CTX_set_cipher(OSSL_SERIALIZER_CTX *ctx,
const char *cipher_name,
const char *propquery);
int OSSL_SERIALIZER_CTX_set_passphrase(OSSL_SERIALIZER_CTX *ctx,
const unsigned char *kstr,
size_t klen);
int OSSL_SERIALIZER_CTX_set_passphrase_cb(OSSL_SERIALIZER_CTX *ctx, int enc,
pem_password_cb *cb, void *cbarg);
int OSSL_SERIALIZER_CTX_set_passphrase_ui(OSSL_SERIALIZER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data);
#define OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ "format=pem,type=public"
#define OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ "format=pem,type=private"
#define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=domainparams"
#define OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ "format=text,type=public"
#define OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ "format=text,type=private"
#define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=domainparams"
=head1 DESCRIPTION
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() creates a B<OSSL_SERIALIZER_CTX>
with a suitable attached output routine for B<EVP_PKEY>s. It will
search for a serializer implementation that matches the algorithm of
the B<EVP_PKEY> and the property query given with I<propquery>. It
will prefer to find a serializer from the same provider as the key
data of the B<EVP_PKEY> itself, but failing that, it will choose the
first serializer that supplies a generic serializing function.
If no suitable serializer was found, OSSL_SERIALIZER_CTX_new_by_EVP_PKEY()
still creates a B<OSSL_SERIALIZER_CTX>, but with no associated
serializer (L<OSSL_SERIALIZER_CTX_get_serializer(3)> returns NULL).
This helps the caller distinguish between an error when creating
the B<OSSL_SERIALIZER_CTX>, and the lack the serializer support and
act accordingly.
OSSL_SERIALIZER_CTX_set_cipher() tells the implementation what cipher
should be used to encrypt serialized keys. The cipher is given by
name I<cipher_name>. The interpretation of that I<cipher_name> is
implementation dependent. The implementation may implement the digest
directly itself or by other implementations, or it may choose to fetch
it. If the implementation supports fetching the cipher, then it may
use I<propquery> as properties to be queried for when fetching.
I<cipher_name> may also be NULL, which will result in unencrypted
serialization.
OSSL_SERIALIZER_CTX_set_passphrase() gives the implementation a
pass phrase to use when encrypting the serialized private key.
Alternatively, a pass phrase callback may be specified with the
following functions.
OSSL_SERIALIZER_CTX_set_passphrase_cb() and
OSSL_SERIALIZER_CTX_set_passphrase_ui() sets up a callback method that
the implementation can use to prompt for a pass phrase.
=for comment Note that the callback method is called indirectly,
through an internal B<OSSL_PASSPHRASE_CALLBACK> function.
The macros B<OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ>,
B<OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ>,
B<OSSL_SERIALIZER_Parameters_TO_PEM_PQ>,
B<OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ>,
B<OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ>,
B<OSSL_SERIALIZER_Parameters_TO_TEXT_PQ> are convenience macros with
property queries to serialize the B<EVP_PKEY> as a public key, private
key or parameters to B<PEM>, or to text.
=head1 RETURN VALUES
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() returns a pointer to a
B<OSSL_SERIALIZER_CTX>, or NULL if it couldn't be created.
OSSL_SERIALIZER_CTX_set_cipher(),
OSSL_SERIALIZER_CTX_set_passphrase(),
OSSL_SERIALIZER_CTX_set_passphrase_cb(), and
OSSL_SERIALIZER_CTX_set_passphrase_ui() all return 1 on success, or 0
on failure.
=head1 NOTES
Parts of the function and macro names are made to match already
existing OpenSSL names.
B<EVP_PKEY> in OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() matches the type
name, thus making for the naming pattern
B<OSSL_SERIALIZER_CTX_new_by_I<TYPE>>() when new types are handled.
B<PUBKEY>, B<PrivateKey> and B<Parameters> in the macro names match
the B<I<TYPE>> part of of B<PEM_write_bio_I<TYPE>> functions as well
as B<i2d_I<TYPE>_bio> functions.
=head1 SEE ALSO
L<provider(7)>, L<OSSL_SERIALIZER(3)>, L<OSSL_SERIALIZER_CTX(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2019 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
L<https://www.openssl.org/source/license.html>.
=cut

View File

@ -193,6 +193,55 @@ Both serialization functions also take an B<OSSL_PASSPHRASE_CALLBACK>
function pointer along with a pointer to application data I<cbarg>,
which should be used when a pass phrase prompt is needed.
=head2 Serializer parameters
Parameters currently recognised by built-in serializers are as
follows:
=over 4
=item "cipher" (B<OSSL_SERIALIZER_PARAM_CIPHER>) <UTF8 string>
The name of the encryption cipher to be used when generating encrypted
serialization. This is used when serializing private keys, as well as
other objects that need protection.
If this name is invalid for the serialization implementation, the
implementation should refuse to perform the serialization, i.e.
OP_serializer_serialize_data() and OP_serializer_serialize_object()
should return an error.
=item "properties" (B<OSSL_SERIALIZER_PARAM_PROPERTIES>) <UTF8 string>
The properties to be queried when trying to fetch the algorithm given
with the "cipher" parameter.
This must be given together with the "cipher" parameter to be
considered valid.
The serialization implementation isn't obligated to use this value.
However, it is recommended that implementations that do not handle
property strings return an error on receiving this parameter unless
its value NULL or the empty string.
=item "passphrase" (B<OSSL_SERIALIZER_PARAM_PASS>) <octet string>
A pass phrase provided by the application. When this is given, the
built-in serializers will not attempt to use the passphrase callback.
=back
Parameters currently recognised by the built-in pass phrase callback:
=over 4
=item "info" (B<OSSL_PASSPHRASE_PARAM_INFO>) <UTF8 string>
A string of information that will become part of the pass phrase
prompt. This could be used to give the user information on what kind
of object it's being prompted for.
=back
=head1 RETURN VALUES
OP_serializer_newctx() returns a pointer to a context, or NULL on

View File

@ -202,6 +202,17 @@ extern "C" {
#define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL "oaep-label"
#define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN "oaep-label-len"
/*
* Serializer parameters
*/
/* The passphrase may be passed as a utf8 string or an octet string */
#define OSSL_SERIALIZER_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
#define OSSL_SERIALIZER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
#define OSSL_SERIALIZER_PARAM_PASS "passphrase"
/* Passphrase callback parameters */
#define OSSL_PASSPHRASE_PARAM_INFO "info"
# ifdef __cplusplus
}
# endif

View File

@ -233,6 +233,7 @@ struct err_state_st {
# define ERR_R_PASSED_INVALID_ARGUMENT (7)
# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL)
# define ERR_R_INVALID_PROVIDER_FUNCTIONS (9|ERR_R_FATAL)
# define ERR_R_INTERRUPTED_OR_CANCELLED (10)
/*
* 99 is the maximum possible ERR_R_... code, higher values are reserved for

View File

@ -18,6 +18,7 @@
# endif
# include <stdarg.h>
# include <stddef.h>
# include <openssl/serializererr.h>
# include <openssl/types.h>
# include <openssl/core.h>
@ -53,12 +54,46 @@ int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx,
const OSSL_PARAM params[]);
void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx);
/* Utilities that help set specific parameters */
int OSSL_SERIALIZER_CTX_set_cipher(OSSL_SERIALIZER_CTX *ctx,
const char *cipher_name,
const char *propquery);
int OSSL_SERIALIZER_CTX_set_passphrase(OSSL_SERIALIZER_CTX *ctx,
const unsigned char *kstr,
size_t klen);
int OSSL_SERIALIZER_CTX_set_passphrase_cb(OSSL_SERIALIZER_CTX *ctx, int enc,
pem_password_cb *cb, void *cbarg);
int OSSL_SERIALIZER_CTX_set_passphrase_ui(OSSL_SERIALIZER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data);
/* Utilities to output the object to serialize */
int OSSL_SERIALIZER_to_bio(OSSL_SERIALIZER_CTX *ctx, BIO *out);
#ifndef OPENSSL_NO_STDIO
int OSSL_SERIALIZER_to_fp(OSSL_SERIALIZER_CTX *ctx, FILE *fp);
#endif
/*
* Create the OSSL_SERIALIZER_CTX with an associated type. This will perform
* an implicit OSSL_SERIALIZER_fetch(), suitable for the object of that type.
* This is more useful than calling OSSL_SERIALIZER_CTX_new().
*/
OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
const char *propquery);
/*
* These macros define the last argument to pass to
* OSSL_SERIALIZER_CTX_new_by_TYPE().
*/
# define OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ "format=pem,type=public"
# define OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ "format=pem,type=private"
# define OSSL_SERIALIZER_Parameters_TO_PEM_PQ "format=pem,type=domainparams"
/* Corresponding macros for text output */
# define OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ "format=text,type=public"
# define OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ "format=text,type=private"
# define OSSL_SERIALIZER_Parameters_TO_TEXT_PQ "format=text,type=domainparams"
# ifdef __cplusplus
}
# endif

View File

@ -0,0 +1,34 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 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
*/
#ifndef OPENSSL_OSSL_SERIALIZERERR_H
# define OPENSSL_OSSL_SERIALIZERERR_H
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C"
# endif
int ERR_load_OSSL_SERIALIZER_strings(void);
/*
* OSSL_SERIALIZER function codes.
*/
# ifndef OPENSSL_NO_DEPRECATED_3_0
# endif
/*
* OSSL_SERIALIZER reason codes.
*/
# define OSSL_SERIALIZER_R_INCORRECT_PROPERTY_QUERY 100
#endif

View File

@ -4894,3 +4894,9 @@ OSSL_SERIALIZER_CTX_free ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_properties ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_to_bio ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_to_fp ? 3_0_0 EXIST::FUNCTION:STDIO
OSSL_SERIALIZER_CTX_new_by_EVP_PKEY ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_CTX_set_cipher ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_CTX_set_passphrase ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_CTX_set_passphrase_cb ? 3_0_0 EXIST::FUNCTION:
OSSL_SERIALIZER_CTX_set_passphrase_ui ? 3_0_0 EXIST::FUNCTION:
ERR_load_OSSL_SERIALIZER_strings ? 3_0_0 EXIST::FUNCTION:

View File

@ -455,6 +455,7 @@ ERR_load_PKCS12_strings
ERR_load_PKCS7_strings
ERR_load_RAND_strings
ERR_load_RSA_strings
ERR_load_OSSL_SERIALIZER_strings
ERR_load_TS_strings
ERR_load_UI_strings
ERR_load_X509V3_strings

View File

@ -370,6 +370,12 @@ OSSL_PARAM_utf8_string define
OSSL_PARAM_get_TYPE generic
OSSL_PARAM_END define
OSSL_PARAM_set_TYPE generic
OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ define
OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ define
OSSL_SERIALIZER_Parameters_TO_PEM_PQ define
OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ define
OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ define
OSSL_SERIALIZER_Parameters_TO_TEXT_PQ define
PEM_FLAG_EAY_COMPATIBLE define
PEM_FLAG_ONLY_B64 define
PEM_FLAG_SECURE define