From f864a9396a690958d26c87827ba6f26e7b010caf Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 18 Nov 2019 01:44:23 +0100 Subject: [PATCH] SERIALIZER: add hooks in PEM_write_bio_ and PEM_write_fp_ routines Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10394) --- crypto/pem/pem_all.c | 4 +- crypto/pem/pem_local.h | 128 +++++++++++++++++++++++++++++++++++++++++ crypto/pem/pem_pkey.c | 26 ++++++--- include/openssl/pem.h | 56 +++++++++--------- 4 files changed, 175 insertions(+), 39 deletions(-) create mode 100644 crypto/pem/pem_local.h diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c index 975e62e9f7..2e8eb2e183 100644 --- a/crypto/pem/pem_all.c +++ b/crypto/pem/pem_all.c @@ -17,6 +17,7 @@ #include #include #include +#include "pem_local.h" #ifndef OPENSSL_NO_RSA static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa); @@ -172,4 +173,5 @@ EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb, IMPLEMENT_PEM_write(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) IMPLEMENT_PEM_write(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams) #endif -IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) +IMPLEMENT_PEM_provided_write(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) +IMPLEMENT_PEM_read(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/crypto/pem/pem_local.h b/crypto/pem/pem_local.h new file mode 100644 index 0000000000..3b501abde7 --- /dev/null +++ b/crypto/pem/pem_local.h @@ -0,0 +1,128 @@ +/* + * 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 + */ + +/* + * TODO(v3.0): the IMPLEMENT macros in include/openssl/pem.h should be + * moved here. + */ + +#include +#include + +/* Alternative IMPLEMENT macros for provided serializers */ + +# define IMPLEMENT_PEM_provided_write_body_vars(type, asn1) \ + int ret = 0; \ + const char *pq = OSSL_SERIALIZER_##asn1##_TO_PEM_PQ; \ + OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_##type(x, pq); \ + \ + if (ctx != NULL && OSSL_SERIALIZER_CTX_get_serializer(ctx) == NULL) { \ + OSSL_SERIALIZER_CTX_free(ctx); \ + goto legacy; \ + } +# define IMPLEMENT_PEM_provided_write_body_pass() \ + ret = 1; \ + if (kstr == NULL && cb == NULL) { \ + if (u != NULL) { \ + kstr = u; \ + klen = strlen(u); \ + } else { \ + cb = PEM_def_callback; \ + } \ + } \ + if (enc != NULL) { \ + ret = 0; \ + if (OSSL_SERIALIZER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), \ + NULL)) { \ + ret = 1; \ + if (kstr != NULL \ + && !OSSL_SERIALIZER_CTX_set_passphrase(ctx, kstr, klen)) \ + ret = 0; \ + else if (cb != NULL \ + && !OSSL_SERIALIZER_CTX_set_passphrase_cb(ctx, 1, \ + cb, u)) \ + ret = 0; \ + } \ + } \ + if (!ret) { \ + OSSL_SERIALIZER_CTX_free(ctx); \ + return 0; \ + } +# define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \ + ret = OSSL_SERIALIZER_to_##outtype(ctx, out); \ + OSSL_SERIALIZER_CTX_free(ctx); \ + return ret +# define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ + writename) \ + legacy: \ + return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \ + x, NULL, NULL, 0, NULL, NULL) +# define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \ + writename) \ + legacy: \ + return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \ + x, enc, kstr, klen, cb, u) + +# define IMPLEMENT_PEM_provided_write_to(name, type, str, asn1, \ + OUTTYPE, outtype, writename) \ + PEM_write_fnsig(name, type, OUTTYPE, writename) \ + { \ + IMPLEMENT_PEM_provided_write_body_vars(type, asn1); \ + IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ + IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ + writename); \ + } + + +# define IMPLEMENT_PEM_provided_write_cb_to(name, type, str, asn1, \ + OUTTYPE, outtype, writename) \ + PEM_write_cb_fnsig(name, type, OUTTYPE, writename) \ + { \ + IMPLEMENT_PEM_provided_write_body_vars(type, asn1); \ + IMPLEMENT_PEM_provided_write_body_pass(); \ + IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ + IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \ + writename); \ + } + +# ifdef OPENSSL_NO_STDIO + +# define IMPLEMENT_PEM_provided_write_fp(name, type, str, asn1) +# define IMPLEMENT_PEM_provided_write_cb_fp(name, type, str, asn1) + +# else + +# define IMPLEMENT_PEM_provided_write_fp(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_to(name, type, str, asn1, FILE, fp, write) +# define IMPLEMENT_PEM_provided_write_cb_fp(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb_to(name, type, str, asn1, FILE, fp, write) + +# endif + +# define IMPLEMENT_PEM_provided_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_to(name, type, str, asn1, BIO, bio, write_bio) +# define IMPLEMENT_PEM_provided_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb_to(name, type, str, asn1, BIO, bio, write_bio) + +# define IMPLEMENT_PEM_provided_write(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_provided_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_provided_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write(name, type, str, asn1) + +# define IMPLEMENT_PEM_provided_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_provided_write_cb(name, type, str, asn1) + diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 6f89759f1e..c619cc11b4 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -19,9 +19,11 @@ #include #include #include +#include #include "crypto/store.h" #include "crypto/asn1.h" #include "crypto/evp.h" +#include "pem_local.h" int pem_check_suffix(const char *pem_str, const char *suffix); @@ -64,15 +66,18 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, return ret; } -int PEM_write_bio_PrivateKey(BIO *bp, const EVP_PKEY *x, - const EVP_CIPHER *enc, - const unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) +PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) { + IMPLEMENT_PEM_provided_write_body_vars(EVP_PKEY, PrivateKey); + + IMPLEMENT_PEM_provided_write_body_pass(); + IMPLEMENT_PEM_provided_write_body_main(EVP_PKEY, bio); + + legacy: if (x->ameth == NULL || x->ameth->priv_encode != NULL) - return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, + return PEM_write_bio_PKCS8PrivateKey(out, x, enc, (const char *)kstr, klen, cb, u); - return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, u); + return PEM_write_bio_PrivateKey_traditional(out, x, enc, kstr, klen, cb, u); } int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x, @@ -112,15 +117,20 @@ EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) return ret; } -int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x) +PEM_write_fnsig(Parameters, EVP_PKEY, BIO, write_bio) { char pem_str[80]; + IMPLEMENT_PEM_provided_write_body_vars(EVP_PKEY, Parameters); + + IMPLEMENT_PEM_provided_write_body_main(EVP_PKEY, bio); + + legacy: if (!x->ameth || !x->ameth->param_encode) return 0; BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str); return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode, - pem_str, bp, x, NULL, NULL, 0, 0, NULL); + pem_str, out, x, NULL, NULL, 0, 0, NULL); } #ifndef OPENSSL_NO_STDIO diff --git a/include/openssl/pem.h b/include/openssl/pem.h index 35d01544ba..c90bec8eac 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h @@ -66,6 +66,14 @@ extern "C" { * IMPLEMENT_PEM_rw_cb(...) */ +# define PEM_write_fnsig(name, type, OUTTYPE, writename) \ + int PEM_##writename##_##name(OUTTYPE *out, const type *x) +# define PEM_write_cb_fnsig(name, type, OUTTYPE, writename) \ + int PEM_##writename##_##name(OUTTYPE *out, const type *x, \ + const EVP_CIPHER *enc, \ + const unsigned char *kstr, int klen, \ + pem_password_cb *cb, void *u) + # ifdef OPENSSL_NO_STDIO # define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ @@ -87,9 +95,9 @@ extern "C" { } # define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ - int PEM_write_##name(FILE *fp, const type *x) \ + PEM_write_fnsig(name, type, FILE, write) \ { \ - return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, fp, \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, out, \ x, NULL, NULL, 0, NULL, NULL); \ } @@ -99,12 +107,9 @@ extern "C" { # endif # define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ - int PEM_write_##name(FILE *fp, const type *x, \ - const EVP_CIPHER *enc, \ - const unsigned char *kstr, int klen, \ - pem_password_cb *cb, void *u) \ + PEM_write_cb_fnsig(name, type, FILE, write) \ { \ - return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, fp, \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, out, \ x, enc, kstr, klen, cb, u); \ } @@ -123,9 +128,9 @@ extern "C" { } # define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ - int PEM_write_bio_##name(BIO *bp, const type *x) \ + PEM_write_fnsig(name, type, BIO, write_bio) \ { \ - return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, bp, \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, out, \ x, NULL,NULL,0,NULL,NULL); \ } @@ -135,12 +140,9 @@ extern "C" { # endif # define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ - int PEM_write_bio_##name(BIO *bp, const type *x, \ - const EVP_CIPHER *enc, \ - const unsigned char *kstr, int klen, \ - pem_password_cb *cb, void *u) \ + PEM_write_cb_fnsig(name, type, BIO, write_bio) \ { \ - return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, bp, \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, out, \ x, enc, kstr, klen, cb, u); \ } @@ -203,18 +205,15 @@ extern "C" { type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); # define DECLARE_PEM_write_fp(name, type) \ - int PEM_write_##name(FILE *fp, const type *x); + PEM_write_fnsig(name, type, FILE, write); # ifndef OPENSSL_NO_DEPRECATED_3_0 -# define DECLARE_PEM_write_fp_const(name, type) \ - DECLARE_PEM_write_fp(name, type) +# define DECLARE_PEM_write_fp_const(name, type) \ + PEM_write_fnsig(name, type, FILE, write); # endif -# define DECLARE_PEM_write_cb_fp(name, type) \ - int PEM_write_##name(FILE *fp, const type *x, \ - const EVP_CIPHER *enc, \ - const unsigned char *kstr, int klen, \ - pem_password_cb *cb, void *u); +# define DECLARE_PEM_write_cb_fp(name, type) \ + PEM_write_cb_fnsig(name, type, FILE, write); # endif @@ -223,18 +222,15 @@ extern "C" { pem_password_cb *cb, void *u); # define DECLARE_PEM_write_bio(name, type) \ - int PEM_write_bio_##name(BIO *bp, const type *x); + PEM_write_fnsig(name, type, BIO, write_bio); # ifndef OPENSSL_NO_DEPRECATED_3_0 -# define DECLARE_PEM_write_bio_const(name, type) \ - DECLARE_PEM_write_bio(name, type) +# define DECLARE_PEM_write_bio_const(name, type) \ + PEM_write_fnsig(name, type, BIO, write_bio); # endif -# define DECLARE_PEM_write_cb_bio(name, type) \ - int PEM_write_bio_##name(BIO *bp, const type *x, \ - const EVP_CIPHER *enc, \ - const unsigned char *kstr, int klen, \ - pem_password_cb *cb, void *u); +# define DECLARE_PEM_write_cb_bio(name, type) \ + PEM_write_cb_fnsig(name, type, BIO, write_bio); # define DECLARE_PEM_write(name, type) \ DECLARE_PEM_write_bio(name, type) \ -- 2.25.1