mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
PROV: Implement an EC key -> blob encoder, to get the public key
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/14291)
This commit is contained in:
parent
8ab9c4ddc4
commit
c8182743a7
@ -104,12 +104,15 @@ ENCODER_w_structure("DSA", dsa, yes, der, type_specific),
|
||||
ENCODER_w_structure("DSA", dsa, yes, pem, type_specific),
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
/* EC only supports keypair and parameters output. */
|
||||
/* EC only supports keypair and parameters DER and PEM output. */
|
||||
ENCODER_w_structure("EC", ec, yes, der, type_specific_no_pub),
|
||||
ENCODER_w_structure("EC", ec, yes, pem, type_specific_no_pub),
|
||||
/* EC supports blob output for the public key */
|
||||
ENCODER("EC", ec, yes, blob),
|
||||
# ifndef OPENSSL_NO_SM2
|
||||
ENCODER_w_structure("SM2", sm2, yes, der, type_specific_no_pub),
|
||||
ENCODER_w_structure("SM2", sm2, yes, pem, type_specific_no_pub),
|
||||
ENCODER("SM2", sm2, yes, blob),
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -15,4 +15,10 @@ SOURCE[$ENCODER_GOAL]=endecoder_common.c
|
||||
SOURCE[$DECODER_GOAL]=decode_der2key.c decode_pem2der.c decode_ms2key.c
|
||||
|
||||
SOURCE[$ENCODER_GOAL]=encode_key2any.c encode_key2text.c encode_key2ms.c
|
||||
# encode_key2blob.c is only being included when EC is enabled, because we
|
||||
# currently only define a "blob" output type for EC public keys. This may
|
||||
# change in the future.
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ENCODER_GOAL]=encode_key2blob.c
|
||||
ENDIF
|
||||
DEPEND[encode_key2any.o]=../../common/include/prov/der_rsa.h
|
||||
|
202
providers/implementations/encode_decode/encode_key2blob.c
Normal file
202
providers/implementations/encode_decode/encode_key2blob.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2021 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Low level APIs are deprecated for public use, but still ok for internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core.h>
|
||||
#include <openssl/core_dispatch.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include "internal/passphrase.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/bio.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "endecoder_local.h"
|
||||
|
||||
static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
|
||||
void *data, int len)
|
||||
{
|
||||
BIO *out = bio_new_from_core_bio(provctx, cout);
|
||||
int ret = BIO_write(out, data, len);
|
||||
|
||||
BIO_free(out);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
|
||||
static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
|
||||
static OSSL_FUNC_encoder_gettable_params_fn key2blob_gettable_params;
|
||||
static OSSL_FUNC_encoder_get_params_fn key2blob_get_params;
|
||||
|
||||
static void *key2blob_newctx(void *provctx)
|
||||
{
|
||||
return provctx;
|
||||
}
|
||||
|
||||
static void key2blob_freectx(void *vctx)
|
||||
{
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *key2blob_gettable_params(ossl_unused void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM gettables[] = {
|
||||
{ OSSL_ENCODER_PARAM_OUTPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
|
||||
OSSL_PARAM_END,
|
||||
};
|
||||
|
||||
return gettables;
|
||||
}
|
||||
|
||||
static int key2blob_get_params(OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_ENCODER_PARAM_OUTPUT_TYPE);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "blob"))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int key2blob_check_selection(int selection, int selection_mask)
|
||||
{
|
||||
/*
|
||||
* The selections are kinda sorta "levels", i.e. each selection given
|
||||
* here is assumed to include those following.
|
||||
*/
|
||||
int checks[] = {
|
||||
OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
|
||||
OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
|
||||
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
|
||||
};
|
||||
size_t i;
|
||||
|
||||
/* The decoder implementations made here support guessing */
|
||||
if (selection == 0)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(checks); i++) {
|
||||
int check1 = (selection & checks[i]) != 0;
|
||||
int check2 = (selection_mask & checks[i]) != 0;
|
||||
|
||||
/*
|
||||
* If the caller asked for the currently checked bit(s), return
|
||||
* whether the decoder description says it's supported.
|
||||
*/
|
||||
if (check1)
|
||||
return check2;
|
||||
}
|
||||
|
||||
/* This should be dead code, but just to be safe... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int key2blob_encode(void *vctx, const void *key, int selection,
|
||||
OSSL_CORE_BIO *cout)
|
||||
{
|
||||
int pubkey_len = 0, ok = 0;
|
||||
unsigned char *pubkey = NULL;
|
||||
|
||||
pubkey_len = i2o_ECPublicKey(key, &pubkey);
|
||||
if (pubkey_len > 0 && pubkey != NULL)
|
||||
ok = write_blob(vctx, cout, pubkey, pubkey_len);
|
||||
OPENSSL_free(pubkey);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
|
||||
* encoder
|
||||
*
|
||||
* impl: The keytype to encode
|
||||
* type: The C structure type holding the key data
|
||||
* selection_name: The acceptable selections. This translates into
|
||||
* the macro EVP_PKEY_##selection_name.
|
||||
*
|
||||
* The selection is understood as a "level" rather than an exact set of
|
||||
* requests from the caller. The encoder has to decide what contents fit
|
||||
* the encoded format. For example, the EC public key blob will only contain
|
||||
* the encoded public key itself, no matter if the selection bits include
|
||||
* OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes
|
||||
* OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
|
||||
* cooperate, because it cannot output the private key.
|
||||
*
|
||||
* EVP_PKEY_##selection_name are convenience macros that combine "typical"
|
||||
* OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
|
||||
*/
|
||||
#define MAKE_BLOB_ENCODER(impl, type, selection_name) \
|
||||
static OSSL_FUNC_encoder_import_object_fn \
|
||||
impl##2blob_import_object; \
|
||||
static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \
|
||||
static OSSL_FUNC_encoder_does_selection_fn \
|
||||
impl##2blob_does_selection; \
|
||||
static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \
|
||||
\
|
||||
static void *impl##2blob_import_object(void *ctx, int selection, \
|
||||
const OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
|
||||
ctx, selection, params); \
|
||||
} \
|
||||
static void impl##2blob_free_object(void *key) \
|
||||
{ \
|
||||
ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
|
||||
} \
|
||||
static int impl##2blob_does_selection(void *ctx, int selection) \
|
||||
{ \
|
||||
return key2blob_check_selection(selection, \
|
||||
EVP_PKEY_##selection_name); \
|
||||
} \
|
||||
static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \
|
||||
const void *key, \
|
||||
const OSSL_PARAM key_abstract[], \
|
||||
int selection, \
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, \
|
||||
void *cbarg) \
|
||||
{ \
|
||||
/* We don't deal with abstract objects */ \
|
||||
if (key_abstract != NULL) { \
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
|
||||
return 0; \
|
||||
} \
|
||||
return key2blob_encode(vctx, key, selection, cout); \
|
||||
} \
|
||||
const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \
|
||||
{ OSSL_FUNC_ENCODER_NEWCTX, \
|
||||
(void (*)(void))key2blob_newctx }, \
|
||||
{ OSSL_FUNC_ENCODER_FREECTX, \
|
||||
(void (*)(void))key2blob_freectx }, \
|
||||
{ OSSL_FUNC_ENCODER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))key2blob_gettable_params }, \
|
||||
{ OSSL_FUNC_ENCODER_GET_PARAMS, \
|
||||
(void (*)(void))key2blob_get_params }, \
|
||||
{ OSSL_FUNC_ENCODER_DOES_SELECTION, \
|
||||
(void (*)(void))impl##2blob_does_selection }, \
|
||||
{ OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
|
||||
(void (*)(void))impl##2blob_import_object }, \
|
||||
{ OSSL_FUNC_ENCODER_FREE_OBJECT, \
|
||||
(void (*)(void))impl##2blob_free_object }, \
|
||||
{ OSSL_FUNC_ENCODER_ENCODE, \
|
||||
(void (*)(void))impl##2blob_encode }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
|
||||
# ifndef OPENSSL_NO_SM2
|
||||
MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
|
||||
# endif
|
||||
#endif
|
@ -380,6 +380,7 @@ extern const OSSL_DISPATCH ossl_dsa_to_text_encoder_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH ossl_ec_to_EC_der_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ec_to_EC_pem_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ec_to_blob_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ec_to_PKCS8_der_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ec_to_PKCS8_pem_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ec_to_SubjectPublicKeyInfo_der_encoder_functions[];
|
||||
@ -393,6 +394,7 @@ extern const OSSL_DISPATCH ossl_ec_to_text_encoder_functions[];
|
||||
#ifndef OPENSSL_NO_SM2
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_SM2_der_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_SM2_pem_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_blob_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_PKCS8_der_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_PKCS8_pem_encoder_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_to_SubjectPublicKeyInfo_der_encoder_functions[];
|
||||
|
Loading…
Reference in New Issue
Block a user