#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
+#include "pem_local.h"
#ifndef OPENSSL_NO_RSA
static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa);
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)
--- /dev/null
+/*
+ * 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 <openssl/pem.h>
+#include <openssl/serializer.h>
+
+/* 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)
+
#include <openssl/dh.h>
#include <openssl/store.h>
#include <openssl/ui.h>
+#include <openssl/serializer.h>
#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);
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,
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
* 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) /**/
}
# 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); \
}
# 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); \
}
}
# 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); \
}
# 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); \
}
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
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) \