From: Richard Levitte Date: Mon, 18 Nov 2019 00:56:22 +0000 (+0100) Subject: PROV SERIALIZER: add support for writing RSA keys X-Git-Tag: openssl-3.0.0-alpha1~877 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=677add38003b37cab06ebc59260c8d28745bb948;p=oweals%2Fopenssl.git PROV SERIALIZER: add support for writing RSA keys This also adds the missing accessor RSA_get0_pss_params(), so those parameters can be included in the PKCS#8 data structure without needing to know the inside of the RSA structure. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10394) --- diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 71e4b78306..bf47540b45 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -584,6 +584,11 @@ const BIGNUM *RSA_get0_iqmp(const RSA *r) return r->iqmp; } +const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r) +{ + return r->pss; +} + void RSA_clear_flags(RSA *r, int flags) { r->flags &= ~flags; diff --git a/doc/man3/RSA_get0_key.pod b/doc/man3/RSA_get0_key.pod index 8515f6edfb..a947c39643 100644 --- a/doc/man3/RSA_get0_key.pod +++ b/doc/man3/RSA_get0_key.pod @@ -5,7 +5,7 @@ RSA_set0_key, RSA_set0_factors, RSA_set0_crt_params, RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_get0_n, RSA_get0_e, RSA_get0_d, RSA_get0_p, RSA_get0_q, -RSA_get0_dmp1, RSA_get0_dmq1, RSA_get0_iqmp, +RSA_get0_dmp1, RSA_get0_dmq1, RSA_get0_iqmp, RSA_get0_pss_params, RSA_clear_flags, RSA_test_flags, RSA_set_flags, RSA_get0_engine, RSA_get_multi_prime_extra_count, RSA_get0_multi_prime_factors, RSA_get0_multi_prime_crt_params, @@ -33,6 +33,7 @@ RSA_set0_multi_prime_params, RSA_get_version const BIGNUM *RSA_get0_dmp1(const RSA *r); const BIGNUM *RSA_get0_dmq1(const RSA *r); const BIGNUM *RSA_get0_iqmp(const RSA *r); + const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r); void RSA_clear_flags(RSA *r, int flags); int RSA_test_flags(const RSA *r, int flags); void RSA_set_flags(RSA *r, int flags); @@ -98,6 +99,8 @@ retrieved separately by the corresponding function RSA_get0_n(), RSA_get0_e(), RSA_get0_d(), RSA_get0_p(), RSA_get0_q(), RSA_get0_dmp1(), RSA_get0_dmq1(), and RSA_get0_iqmp(), respectively. +RSA_get0_pss_params() is used to retrieve the RSA-PSS parameters. + RSA_set_flags() sets the flags in the B parameter on the RSA object. Multiple flags can be passed in one go (bitwise ORed together). Any flags that are already set are left set. RSA_test_flags() tests to @@ -136,6 +139,9 @@ RSA_get0_n(), RSA_get0_e(), RSA_get0_d(), RSA_get0_p(), RSA_get0_q(), RSA_get0_dmp1(), RSA_get0_dmq1(), and RSA_get0_iqmp() return the respective value. +RSA_get0_pss_params() returns a B pointer, or NULL if +there is none. + RSA_get0_multi_prime_factors() and RSA_get0_multi_prime_crt_params() return 1 on success or 0 on failure. diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 852981dfcf..02a02160b3 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -224,6 +224,7 @@ const BIGNUM *RSA_get0_q(const RSA *d); const BIGNUM *RSA_get0_dmp1(const RSA *r); const BIGNUM *RSA_get0_dmq1(const RSA *r); const BIGNUM *RSA_get0_iqmp(const RSA *r); +const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r); void RSA_clear_flags(RSA *r, int flags); int RSA_test_flags(const RSA *r, int flags); void RSA_set_flags(RSA *r, int flags); @@ -279,14 +280,14 @@ int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2); DECLARE_ASN1_ENCODE_FUNCTIONS_name(RSA, RSAPublicKey) DECLARE_ASN1_ENCODE_FUNCTIONS_name(RSA, RSAPrivateKey) -typedef struct rsa_pss_params_st { +struct rsa_pss_params_st { X509_ALGOR *hashAlgorithm; X509_ALGOR *maskGenAlgorithm; ASN1_INTEGER *saltLength; ASN1_INTEGER *trailerField; /* Decoded hash algorithm from maskGenAlgorithm */ X509_ALGOR *maskHash; -} RSA_PSS_PARAMS; +}; DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS) diff --git a/include/openssl/types.h b/include/openssl/types.h index b8450ce709..9ac8549062 100644 --- a/include/openssl/types.h +++ b/include/openssl/types.h @@ -130,6 +130,7 @@ typedef struct dsa_method DSA_METHOD; typedef struct rsa_st RSA; typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_pss_params_st RSA_PSS_PARAMS; typedef struct ec_key_st EC_KEY; typedef struct ec_key_method_st EC_KEY_METHOD; diff --git a/providers/defltprov.c b/providers/defltprov.c index 51d3d52ee9..84e580366d 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -385,6 +385,23 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = { { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM deflt_serializer[] = { + { "RSA", "default=yes,format=text,type=private", + rsa_priv_text_serializer_functions }, + { "RSA", "default=yes,format=text,type=public", + rsa_pub_text_serializer_functions }, + { "RSA", "default=yes,format=der,type=private", + rsa_priv_der_serializer_functions }, + { "RSA", "default=yes,format=der,type=public", + rsa_pub_der_serializer_functions }, + { "RSA", "default=yes,format=pem,type=private", + rsa_priv_pem_serializer_functions }, + { "RSA", "default=yes,format=pem,type=public", + rsa_pub_pem_serializer_functions }, + + { NULL, NULL, NULL } +}; + static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov, int operation_id, int *no_cache) @@ -407,6 +424,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov, return deflt_signature; case OSSL_OP_ASYM_CIPHER: return deflt_asym_cipher; + case OSSL_OP_SERIALIZER: + return deflt_serializer; } return NULL; } diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 490843c544..438f9a25fa 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -261,3 +261,11 @@ extern const OSSL_DISPATCH dsa_signature_functions[]; /* Asym Cipher */ extern const OSSL_DISPATCH rsa_asym_cipher_functions[]; + +/* Serializers */ +extern const OSSL_DISPATCH rsa_priv_text_serializer_functions[]; +extern const OSSL_DISPATCH rsa_pub_text_serializer_functions[]; +extern const OSSL_DISPATCH rsa_priv_der_serializer_functions[]; +extern const OSSL_DISPATCH rsa_pub_der_serializer_functions[]; +extern const OSSL_DISPATCH rsa_priv_pem_serializer_functions[]; +extern const OSSL_DISPATCH rsa_pub_pem_serializer_functions[]; diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info index 9d063e4c32..8dc5376183 100644 --- a/providers/implementations/serializers/build.info +++ b/providers/implementations/serializers/build.info @@ -2,5 +2,7 @@ # switch each to the Legacy provider when needed. $SERIALIZER_GOAL=../../libimplementations.a +$RSA_GOAL=../../libimplementations.a SOURCE[$SERIALIZER_GOAL]=serializer_common.c +SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h index dca7a4e217..47d025c0c3 100644 --- a/providers/implementations/serializers/serializer_local.h +++ b/providers/implementations/serializers/serializer_local.h @@ -32,14 +32,11 @@ struct pkcs8_encrypt_ctx_st { OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_importkey(const OSSL_DISPATCH *fns); +OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_rsa_importkey(void); + int ossl_prov_print_labeled_bignum(BIO *out, const char *label, const BIGNUM *n); - -enum dh_print_type { - dh_print_priv, - dh_print_pub, - dh_print_params -}; +int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv); int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid, int (*p2s)(const void *obj, int nid, diff --git a/providers/implementations/serializers/serializer_rsa.c b/providers/implementations/serializers/serializer_rsa.c new file mode 100644 index 0000000000..ac8e4a2bbe --- /dev/null +++ b/providers/implementations/serializers/serializer_rsa.c @@ -0,0 +1,103 @@ +/* + * 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 "crypto/rsa.h" /* rsa_get0_all_params() */ +#include "prov/bio.h" /* ossl_prov_bio_printf() */ +#include "prov/implementations.h" /* rsa_keymgmt_functions */ +#include "serializer_local.h" + +DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) + +OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_rsa_importkey(void) +{ + return ossl_prov_get_importkey(rsa_keymgmt_functions); +} + +int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv) +{ + const char *modulus_label; + const char *exponent_label; + const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; + STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); + int ret = 0; + + if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL) + goto err; + + RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); + rsa_get0_all_params(rsa, factors, exps, coeffs); + + if (priv && rsa_d != NULL) { + if (ossl_prov_bio_printf(out, "Private-Key: (%d bit, %d primes)\n", + BN_num_bits(rsa_n), + sk_BIGNUM_const_num(factors)) <= 0) + goto err; + modulus_label = "modulus:"; + exponent_label = "publicExponent:"; + } else { + if (ossl_prov_bio_printf(out, "Public-Key: (%d bit)\n", + BN_num_bits(rsa_n)) <= 0) + goto err; + modulus_label = "Modulus:"; + exponent_label = "Exponent:"; + } + if (!ossl_prov_print_labeled_bignum(out, modulus_label, rsa_n)) + goto err; + if (!ossl_prov_print_labeled_bignum(out, exponent_label, rsa_e)) + goto err; + if (priv) { + int i; + + if (!ossl_prov_print_labeled_bignum(out, "privateExponent:", rsa_d)) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "prime1:", + sk_BIGNUM_const_value(factors, 0))) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "prime2:", + sk_BIGNUM_const_value(factors, 1))) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "exponent1:", + sk_BIGNUM_const_value(exps, 0))) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "exponent2:", + sk_BIGNUM_const_value(exps, 1))) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "coefficient:", + sk_BIGNUM_const_value(coeffs, 0))) + goto err; + for (i = 2; i < sk_BIGNUM_const_num(factors); i++) { + if (ossl_prov_bio_printf(out, "prime%d:", i + 1) <= 0) + goto err; + if (!ossl_prov_print_labeled_bignum(out, NULL, + sk_BIGNUM_const_value(factors, + i))) + goto err; + if (ossl_prov_bio_printf(out, "exponent%d:", i + 1) <= 0) + goto err; + if (!ossl_prov_print_labeled_bignum(out, NULL, + sk_BIGNUM_const_value(exps, i))) + goto err; + if (ossl_prov_bio_printf(out, "coefficient%d:", i + 1) <= 0) + goto err; + if (!ossl_prov_print_labeled_bignum(out, NULL, + sk_BIGNUM_const_value(coeffs, + i - 1))) + goto err; + } + } + ret = 1; + err: + sk_BIGNUM_const_free(factors); + sk_BIGNUM_const_free(exps); + sk_BIGNUM_const_free(coeffs); + return ret; +} + diff --git a/providers/implementations/serializers/serializer_rsa_priv.c b/providers/implementations/serializers/serializer_rsa_priv.c new file mode 100644 index 0000000000..05d9316ba1 --- /dev/null +++ b/providers/implementations/serializers/serializer_rsa_priv.c @@ -0,0 +1,279 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "prov/providercommonerr.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn rsa_priv_newctx; +static OSSL_OP_serializer_freectx_fn rsa_priv_freectx; +static OSSL_OP_serializer_set_ctx_params_fn rsa_priv_set_ctx_params; +static OSSL_OP_serializer_settable_ctx_params_fn rsa_priv_settable_ctx_params; +static OSSL_OP_serializer_serialize_data_fn rsa_priv_der_data; +static OSSL_OP_serializer_serialize_object_fn rsa_priv_der; +static OSSL_OP_serializer_serialize_data_fn rsa_pem_priv_data; +static OSSL_OP_serializer_serialize_object_fn rsa_pem_priv; + +static OSSL_OP_serializer_newctx_fn rsa_print_newctx; +static OSSL_OP_serializer_freectx_fn rsa_print_freectx; +static OSSL_OP_serializer_serialize_data_fn rsa_priv_print_data; +static OSSL_OP_serializer_serialize_object_fn rsa_priv_print; + + /* + * Context used for private key serialization. + */ +struct rsa_priv_ctx_st { + void *provctx; + + struct pkcs8_encrypt_ctx_st sc; +}; + +/* Helper functions to prepare RSA-PSS params for serialization */ + +static int prepare_rsa_params(const void *rsa, int nid, + ASN1_STRING **pstr, int *pstrtype) +{ + const RSA_PSS_PARAMS *pss = RSA_get0_pss_params(rsa); + *pstr = NULL; + + /* If RSA it's just NULL type */ + if (nid != EVP_PKEY_RSA_PSS) { + *pstrtype = V_ASN1_NULL; + return 1; + } + /* If no PSS parameters we omit parameters entirely */ + if (pss == NULL) { + *pstrtype = V_ASN1_UNDEF; + return 1; + } + /* Encode PSS parameters */ + if (ASN1_item_pack((void *)pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr) + == NULL) + return 0; + + *pstrtype = V_ASN1_SEQUENCE; + return 1; +} + +/* Private key : context */ +static void *rsa_priv_newctx(void *provctx) +{ + struct rsa_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) { + ctx->provctx = provctx; + } + + /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */ + ctx->sc.pbe_nid = -1; + + return ctx; +} + +static void rsa_priv_freectx(void *vctx) +{ + struct rsa_priv_ctx_st *ctx = vctx; + + EVP_CIPHER_free(ctx->sc.cipher); + OPENSSL_free(ctx->sc.cipher_pass); + OPENSSL_free(ctx); +} + +static const OSSL_PARAM *rsa_priv_settable_ctx_params(void) +{ + static const OSSL_PARAM settables[] = { + OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0), + OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0), + OSSL_PARAM_END, + }; + + return settables; +} + +static int rsa_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + struct rsa_priv_ctx_st *ctx = vctx; + const OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER)) + != NULL) { + const OSSL_PARAM *propsp = + OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES); + const char *props = NULL; + + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + props = (propsp != NULL ? propsp->data : NULL); + + EVP_CIPHER_free(ctx->sc.cipher); + ctx->sc.cipher_intent = p->data != NULL; + if (p->data != NULL + && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props)) + == NULL)) + return 0; + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS)) + != NULL) { + OPENSSL_free(ctx->sc.cipher_pass); + ctx->sc.cipher_pass = NULL; + if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0, + &ctx->sc.cipher_pass_length)) + return 0; + } + return 1; +} + +/* Private key : DER */ +static int rsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct rsa_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(ctx->provctx, params); + + ok = rsa_priv_der(vctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_priv_der(void *vctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct rsa_priv_ctx_st *ctx = vctx; + int ret; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + ret = ossl_prov_write_priv_der_from_obj(out, rsa, EVP_PKEY_RSA, + prepare_rsa_params, + (i2d_of_void *)i2d_RSAPrivateKey, + &ctx->sc); + + return ret; +} + +/* Private key : PEM */ +static int rsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct rsa_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(ctx, params); + + ok = rsa_pem_priv(vctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_pem_priv(void *vctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct rsa_priv_ctx_st *ctx = vctx; + int ret; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + ret = ossl_prov_write_priv_pem_from_obj(out, rsa, EVP_PKEY_RSA, + prepare_rsa_params, + (i2d_of_void *)i2d_RSAPrivateKey, + &ctx->sc); + + return ret; +} + +/* + * There's no specific print context, so we use the provider context + */ +static void *rsa_print_newctx(void *provctx) +{ + return provctx; +} + +static void rsa_print_freectx(void *ctx) +{ +} + +static int rsa_priv_print_data(void *provctx, const OSSL_PARAM params[], + BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(provctx, params); /* ctx == provctx */ + + ok = rsa_priv_print(provctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_priv_print(void *ctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_rsa(out, rsa, 1); +} + +const OSSL_DISPATCH rsa_priv_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))rsa_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))rsa_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_priv_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_priv_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH rsa_priv_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))rsa_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))rsa_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_pem_priv_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_pem_priv }, + { 0, NULL } +}; + +const OSSL_DISPATCH rsa_priv_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_print_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_print_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_priv_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))rsa_priv_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_rsa_pub.c b/providers/implementations/serializers/serializer_rsa_pub.c new file mode 100644 index 0000000000..c975499d7c --- /dev/null +++ b/providers/implementations/serializers/serializer_rsa_pub.c @@ -0,0 +1,135 @@ +/* + * 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 +#include +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "prov/providercommonerr.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn rsa_pub_newctx; +static OSSL_OP_serializer_freectx_fn rsa_pub_freectx; +static OSSL_OP_serializer_serialize_data_fn rsa_pub_der_data; +static OSSL_OP_serializer_serialize_object_fn rsa_pub_der; +static OSSL_OP_serializer_serialize_data_fn rsa_pub_pem_data; +static OSSL_OP_serializer_serialize_object_fn rsa_pub_pem; + +static OSSL_OP_serializer_serialize_data_fn rsa_pub_print_data; +static OSSL_OP_serializer_serialize_object_fn rsa_pub_print; + +/* Public key : context */ + +/* + * There's no specific implementation context, so we use the provider context + */ +static void *rsa_pub_newctx(void *provctx) +{ + return provctx; +} + +static void rsa_pub_freectx(void *ctx) +{ +} + +/* Public key : DER */ +static int rsa_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */ + + ok = rsa_pub_der(ctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_pub_der(void *ctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return i2d_RSA_PUBKEY_bio(out, rsa); +} + +/* Public key : PEM */ +static int rsa_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */ + + ok = rsa_pub_pem(ctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_pub_pem(void *ctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return PEM_write_bio_RSA_PUBKEY(out, rsa); +} + +static int rsa_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *rsa_importkey = + ossl_prov_get_rsa_importkey(); + int ok = 0; + + if (rsa_importkey != NULL) { + RSA *rsa = rsa_importkey(ctx, params); /* ctx == provctx */ + + ok = rsa_pub_print(ctx, rsa, out, cb, cbarg); + RSA_free(rsa); + } + return ok; +} + +static int rsa_pub_print(void *ctx, void *rsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_rsa(out, rsa, 0); +} + +const OSSL_DISPATCH rsa_pub_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_pub_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_pub_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH rsa_pub_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_pub_pem_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_pub_pem }, + { 0, NULL } +}; + +const OSSL_DISPATCH rsa_pub_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_pub_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))rsa_pub_print_data }, + { 0, NULL } +}; diff --git a/util/libcrypto.num b/util/libcrypto.num index 28db5054af..32b502147c 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4900,7 +4900,6 @@ 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: -RSA_get0_pss_params ? 3_0_0 EXIST::FUNCTION:RSA PEM_read_X509_PUBKEY ? 3_0_0 EXIST::FUNCTION:STDIO PEM_write_X509_PUBKEY ? 3_0_0 EXIST::FUNCTION:STDIO PEM_read_bio_X509_PUBKEY ? 3_0_0 EXIST::FUNCTION: @@ -4909,3 +4908,4 @@ d2i_X509_PUBKEY_fp ? 3_0_0 EXIST::FUNCTION:STDIO i2d_X509_PUBKEY_fp ? 3_0_0 EXIST::FUNCTION:STDIO d2i_X509_PUBKEY_bio ? 3_0_0 EXIST::FUNCTION: i2d_X509_PUBKEY_bio ? 3_0_0 EXIST::FUNCTION: +RSA_get0_pss_params ? 3_0_0 EXIST::FUNCTION:RSA