[openssl] master update

Richard Levitte levitte at openssl.org
Mon Oct 12 06:34:52 UTC 2020


The branch master has been updated
       via  8ebd88950d9d0a94037e4962daa6e80a464bea06 (commit)
       via  d406f0fe679a571af3f2cfd48b4d830b3d743694 (commit)
       via  3ad9c478642d6edf5964c8c890845d93b40cb9a0 (commit)
       via  895419b7d13bd9ba68718e6a25c92e52fd6fec7f (commit)
       via  053730c5b7e9f4d0e97108e01d0fce472f300edd (commit)
       via  77c30753cdcf4da182953b3b169296c6612089ef (commit)
       via  f044964e7a8b731d1452bbaf5028311db329a45b (commit)
       via  6fbb89fb12b6a5ca9838b357ca6c810c57f474e4 (commit)
       via  abd9d035a727648f4fd77fda464bd1ee5e9cf9c2 (commit)
      from  71abae18f5a27656302cb0fc076b0cd98df9e9f0 (commit)


- Log -----------------------------------------------------------------
commit 8ebd88950d9d0a94037e4962daa6e80a464bea06
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Oct 6 16:11:17 2020 +0200

    Document how deprecation should be done
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit d406f0fe679a571af3f2cfd48b4d830b3d743694
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Oct 5 07:55:14 2020 +0200

    OpenSSL::ParseC: handle OSSL_CORE_MAKE_FUNC
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit 3ad9c478642d6edf5964c8c890845d93b40cb9a0
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Oct 4 12:51:42 2020 +0200

    Add PEM declaration macros that take attributes
    
    This makes it possible to easily deprecated selections of PEM
    functions.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit 895419b7d13bd9ba68718e6a25c92e52fd6fec7f
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Oct 4 12:20:17 2020 +0200

    Add ASN1 declaration macros that take attributes
    
    This makes it possible to easily deprecated selections of ASN1
    functions.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit 053730c5b7e9f4d0e97108e01d0fce472f300edd
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Oct 4 11:51:20 2020 +0200

    Make OpenSSL::ParseC and OpenSSL::Ordinals treat deprecation consistently
    
    The triggering macro that decides if a symbol is to be considered
    deprecated is OPENSSL_NO_DEPRECATEDIN_x_y[_z].  OpenSSL::ParseC
    renames any OPENSSL_NO_DEPRECATED_x_y[_z] by inserting "IN".
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit 77c30753cdcf4da182953b3b169296c6612089ef
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Oct 4 11:13:28 2020 +0200

    Add convenience macros OSSL_DEPRECATEDIN_{major}_{minor}
    
    As opposed to DEPRECATEDIN_{major}_{minor}(), any use of these macros must
    be guarded with a corresponding OPENSSL_NO_DEPRECATED_{major}_{minor}:
    
        #ifndef OPENSSL_NO_DEPRECATED_3_0
        OSSL_DEPRECATEDIN_3_0 int RSA_size(const RSA *rsa);
        #endif
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit f044964e7a8b731d1452bbaf5028311db329a45b
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Oct 3 09:45:24 2020 +0200

    Add definitions of OSSL_DEPRECATED[_FOR] for Microsoft VC
    
    It turns out that they have __declspec(deprecated) that correspond
    pretty much to GCC's __attribute__((deprecated)), including for
    messages.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit 6fbb89fb12b6a5ca9838b357ca6c810c57f474e4
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Oct 3 09:33:32 2020 +0200

    Change OSSL_DEPRECATED to take a version argument
    
    The macro value is changed to use deprecation messages where whose are
    supported.
    
    We also add the macro OSSL_DEPRECATED_FOR(), to be used whenever an
    additional message text is desirable, for example to tell the user
    what the deprecated is replaced with.  Example:
    
        OSSL_DEPRECATED_FOR(3.0,"use EVP_PKEY and EVP_PKEY_size() instead")
        int RSA_size(const RSA *rsa);
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

commit abd9d035a727648f4fd77fda464bd1ee5e9cf9c2
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Oct 3 09:26:36 2020 +0200

    Add a macro OSSL_DEPRECATED for compiler dependent deprecation attributes
    
    The diverse DEPRECATEDIN_x_y_z macros are rewritten in terms of this macro.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/13074)

-----------------------------------------------------------------------

Summary of changes:
 doc/internal/man7/deprecation.pod   | 225 ++++++++++++++++++++++++++++++++++++
 doc/man7/openssl_user_macros.pod.in |   3 +-
 include/openssl/asn1.h.in           | 111 +++++++++++-------
 include/openssl/macros.h            | 136 ++++++++++++++++------
 include/openssl/pem.h               | 122 ++++++++++++-------
 util/missingmacro.txt               |  11 ++
 util/perl/OpenSSL/Ordinals.pm       |   1 -
 util/perl/OpenSSL/ParseC.pm         |  64 ++++++++--
 8 files changed, 547 insertions(+), 126 deletions(-)
 create mode 100644 doc/internal/man7/deprecation.pod

diff --git a/doc/internal/man7/deprecation.pod b/doc/internal/man7/deprecation.pod
new file mode 100644
index 0000000000..e55da1ffe4
--- /dev/null
+++ b/doc/internal/man7/deprecation.pod
@@ -0,0 +1,225 @@
+=pod
+
+=head1 NAME
+
+deprecation - Macros used for deprecating symbols and simulate removal
+
+=head1 SYNOPSIS
+
+ #include <openssl/macros.h>
+
+ OSSL_DEPRECATED(since)
+ OSSL_DEPRECATED_FOR(since, msg)
+
+ OPENSSL_NO_DEPRECATED_3_0
+ OSSL_DEPRECATEDIN_3_0
+ OSSL_DEPRECATEDIN_3_0_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_1_1_1
+ OSSL_DEPRECATEDIN_1_1_1
+ OSSL_DEPRECATEDIN_1_1_1_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_1_1_0
+ OSSL_DEPRECATEDIN_1_1_0
+ OSSL_DEPRECATEDIN_1_1_0_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_1_0_2
+ OSSL_DEPRECATEDIN_1_0_2
+ OSSL_DEPRECATEDIN_1_0_2_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_1_0_1
+ OSSL_DEPRECATEDIN_1_0_1
+ OSSL_DEPRECATEDIN_1_0_1_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_1_0_0
+ OSSL_DEPRECATEDIN_1_0_0
+ OSSL_DEPRECATEDIN_1_0_0_FOR(msg)
+
+ OPENSSL_NO_DEPRECATED_0_9_8
+ OSSL_DEPRECATEDIN_0_9_8
+ OSSL_DEPRECATEDIN_0_9_8_FOR(msg)
+
+=head1 DESCRIPTION
+
+Deprecation of a symbol is adding an attribute to the declaration of that
+symbol (function, type, variable, but we currently only do that for
+functions in our F<< <openssl/*.h> >> header files).
+
+Removal of a symbol is not the same thing as deprecation, as it actually
+removes the symbol from public view.
+
+OpenSSL configuration supports deprecation as well as simulating removal of
+symbols from public view, and also supports doing this in terms of a
+specified OpenSSL version.
+
+Deprecation is done using attribute macros having names starting with
+B<OSSL_DEPRECATED>, used with any declaration it applies to.
+
+Simulating removal is done with guard macros having names starting with
+L<OPENSSL_NO_DEPRECATED(7)>.
+
+The implementation of a deprecated symbol is kept for two reasons:
+
+=over 4
+
+=item Kept as legacy for the deprecation period
+
+It's implemented only to have it available as long as the symbol isn't
+removed entirely (be it by explicitly removing it when it's judged that it
+has been deprecated long enough, or because the removal is simulated).
+These need to be guarded appropriately, as shown in the L</Implementations
+kept as legacy>.
+
+=item Kept for internal purposes
+
+The implementation doesn't need to change or be guarded.  However, it's
+necessary to ensure that the declaration remains available for the
+translation unit where the implementation is located, even when the symbol
+is publicly unavailable through simulated removal.  That's done by including
+an internal header file very early in the translation unit.  See
+L</Implementations kept for internal purposes>.
+
+In a future cleanup, the declaration should be explicitly moved to an
+internal header file, with the deprecation attribute removed, and the
+translation unit should adjust its header inclusions accordingly.
+
+=back
+
+=head2 General macros
+
+I<Note: none of these macros should be used directly, please use the version
+specific macros instead>
+
+OSSL_DEPRECATED() implements the deprecated attribute if the compiler
+supports it, otherwise it expands to nothing.  It takes one argument
+I<since> that should be set to the OpenSSL version where the symbol was
+deprecated, and will be displayed with the deprecation warning message,
+for compilers that support user specified deprecation messages.
+
+OSSL_DEPRECATED_FOR() does the same as OSSL_DEPRECATED(), but also takes a
+second argument I<msg>, which is an additional text messages to be displayed
+with the deprecation warning along with the OpenSSL version number, for
+compilers that support user specified deprecation messages.
+
+B<OPENSSL_NO_DEPRECATED> is a macro that's generated by OpenSSL
+configuration in response to the C<no-deprecated> configuration option.
+This macro suppresses the definition of deprecated symbols.
+
+=head2 Version specific macros
+
+OSSL_DEPRECATEDIN_I<major>_I<minor>() macros that are defined to
+OSSL_DEPRECATED() with that version number as I<since>, for any version up
+to and including the one expressed with L<OPENSSL_API_COMPAT(7)>.  For any
+known version above the version expressed with L<OPENSSL_API_COMPAT(7)>,
+The are defined to nothing.
+
+OSSL_DEPRECATEDIN_I<major>_I<minor>_FOR() macros that are defined to
+OSSL_DEPRECATED() with that version number as I<since>, under the same
+conditions as OSSL_DEPRECATEDIN_I<major>_I<minor>().
+
+B<OPENSSL_NO_DEPRECATED_I<major>_I<minor>> macros should be used as
+guards around declarations that will eventually disappear from the public
+header files (F<< <openssl/*.h> >>).
+
+Any set of symbols deprecated with a B<OSSL_DEPRECATEDIN_I<major>_I<minor>>
+attribute macro B<must> be wrapped with a guard using the corresponding
+B<OPENSSL_NO_DEPRECATED_I<major>_I<minor>> macro, see L</Header files>
+example below.  This not only affects what the user of the header file will
+have available, it's also used to determine the conditions for exporting the
+symbol in the shared libraries.
+
+=head1 EXAMPLES
+
+=head2 Header files
+
+In public header files (F<< <openssl/*.h> >>), a deprecated symbol will
+always be wrapped with a negative test of the guard:
+
+ # ifndef OPENSSL_NO_DEPRECATED_1_1_0
+ /* ... */
+ OSSL_DEPRECATEDIN_1_1_0 __owur int
+ HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md);
+ /* ... */
+ # endif
+
+=head2 Implementations of deprecated symbols
+
+At least for the period of deprecation for any symbol, its implementation
+needs to be kept, and for symbols that are kept internally, for longer than
+that.  There are two things to deal with:
+
+=over 4
+
+=item Deprecation warnings
+
+To remedy deprecation warnings, simply define the macro
+B<OPENSSL_SUPPRESS_DEPRECATED> at the beginning of the translation unit.
+
+=item Simulated removal
+
+=over 4
+
+=item *
+
+For symbols that are kept as legacy, the simulated removal should be
+enforced, by guarding the implementation the exact same way as the
+declaration in the public header file.
+
+=item *
+
+For symbols that are planned to be kept internally beyond their deprecation
+period, the translation units that implement them must ensure that the
+public header files they include to that declare the symbols don't remove
+the symbols, even when removal is otherwise simulated.
+
+=back
+
+=back
+
+=head3 Implementations kept as legacy
+
+For a deprecated function that we plan to simply remove, for example
+RSA_new_method(), the following should be found very early (before including
+any OpenSSL header file) in the translation unit:
+
+ /*
+  * Suppress deprecation warnings for RSA low level implementations that are
+  * kept until removal.
+  */
+ #define OPENSSL_SUPPRESS_DEPRECATED
+
+And RSA_new_method() implementation itself should be guarded like this:
+
+ #ifndef OPENSSL_NO_DEPRECATED_3_0
+ RSA *RSA_new_method(ENGINE *engine)
+ {
+     /* ... */
+ }
+ #endif
+
+=head3 Implementations kept for internal purposes
+
+For a deprecated function that we plan to keep internally, for example
+RSA_size(), the following should be found very early (before including any
+other OpenSSL header file) in the translation unit:
+
+ /*
+  * RSA low level APIs are deprecated for public use, but are kept for
+  * internal use.
+  */
+ #include "internal/deprecated.h"
+
+=head1 SEE ALSO
+
+L<openssl_user_macros(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 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
diff --git a/doc/man7/openssl_user_macros.pod.in b/doc/man7/openssl_user_macros.pod.in
index 8e9d116e17..33969e2476 100644
--- a/doc/man7/openssl_user_macros.pod.in
+++ b/doc/man7/openssl_user_macros.pod.in
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-openssl_user_macros, OPENSSL_API_COMPAT - User defined macros
+openssl_user_macros, OPENSSL_API_COMPAT, OPENSSL_NO_DEPRECATED
+- User defined macros
 
 =head1 DESCRIPTION
 
diff --git a/include/openssl/asn1.h.in b/include/openssl/asn1.h.in
index 9b141dba4c..878c7e43f2 100644
--- a/include/openssl/asn1.h.in
+++ b/include/openssl/asn1.h.in
@@ -230,45 +230,76 @@ typedef struct ASN1_VALUE_st ASN1_VALUE;
 
 /* Declare ASN1 functions: the implement macro in in asn1t.h */
 
-# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
-
-# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
-        DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
-
-# define DECLARE_ASN1_FUNCTIONS_name(type, name) \
-        DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
-        DECLARE_ASN1_ENCODE_FUNCTIONS_name(type, name)
-
-# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
-        DECLARE_ASN1_ENCODE_FUNCTIONS_only(type, name) \
-        DECLARE_ASN1_ITEM(itname)
+/*
+ * The mysterious 'extern' that's passed to some macros is innocuous,
+ * and is there to quiet pre-C99 compilers that may complain about empty
+ * arguments in macro calls.
+ */
 
+# define DECLARE_ASN1_FUNCTIONS_attr(attr, type)                            \
+    DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, type)
+# define DECLARE_ASN1_FUNCTIONS(type)                                       \
+    DECLARE_ASN1_FUNCTIONS_attr(extern, type)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_attr(attr, type)                      \
+    DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, type)
+# define DECLARE_ASN1_ALLOC_FUNCTIONS(type)                                 \
+    DECLARE_ASN1_ALLOC_FUNCTIONS_attr(extern, type)
+
+# define DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, name)                 \
+    DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name)                \
+    DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name)
+# define DECLARE_ASN1_FUNCTIONS_name(type, name)                            \
+    DECLARE_ASN1_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, itname, name)       \
+    DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name)               \
+    DECLARE_ASN1_ITEM_attr(attr, itname)
+# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)                  \
+    DECLARE_ASN1_ENCODE_FUNCTIONS_attr(extern, type, itname, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name)          \
+    DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, name, name)
 # define DECLARE_ASN1_ENCODE_FUNCTIONS_name(type, name) \
-         DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
-
-# define DECLARE_ASN1_ENCODE_FUNCTIONS_only(type, name) \
-        type *d2i_##name(type **a, const unsigned char **in, long len); \
-        int i2d_##name(const type *a, unsigned char **out);
-
-# define DECLARE_ASN1_NDEF_FUNCTION(name) \
-        int i2d_##name##_NDEF(const name *a, unsigned char **out);
-
-# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
-        type *name##_new(void); \
-        void name##_free(type *a);
-
-# define DECLARE_ASN1_DUP_FUNCTION(type) \
-        DECLARE_ASN1_DUP_FUNCTION_name(type, type)
-
-# define DECLARE_ASN1_DUP_FUNCTION_name(type, name) \
-        type *name##_dup(const type *a);
-
-# define DECLARE_ASN1_PRINT_FUNCTION(stname) \
-        DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname)
-
-# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
-        int fname##_print_ctx(BIO *out, const stname *x, int indent, \
-                                         const ASN1_PCTX *pctx);
+    DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name)          \
+    attr type *d2i_##name(type **a, const unsigned char **in, long len);    \
+    attr int i2d_##name(const type *a, unsigned char **out);
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_only(type, name)                     \
+    DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(extern, type, name)
+
+# define DECLARE_ASN1_NDEF_FUNCTION_attr(attr, name)                        \
+    attr int i2d_##name##_NDEF(const name *a, unsigned char **out);
+# define DECLARE_ASN1_NDEF_FUNCTION(name)                                   \
+    DECLARE_ASN1_NDEF_FUNCTION_attr(extern, name)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name)           \
+    attr type *name##_new(void);                                            \
+    attr void name##_free(type *a);
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name)                      \
+    DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_DUP_FUNCTION_attr(attr, type)                         \
+    DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, type)
+# define DECLARE_ASN1_DUP_FUNCTION(type)                                    \
+    DECLARE_ASN1_DUP_FUNCTION_attr(extern, type)
+
+# define DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, name)              \
+    attr type *name##_dup(const type *a);
+# define DECLARE_ASN1_DUP_FUNCTION_name(type, name)                         \
+    DECLARE_ASN1_DUP_FUNCTION_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_PRINT_FUNCTION_attr(attr, stname)                     \
+    DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, stname)
+# define DECLARE_ASN1_PRINT_FUNCTION(stname)                                \
+    DECLARE_ASN1_PRINT_FUNCTION_attr(extern, stname)
+
+# define DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, fname)        \
+    attr int fname##_print_ctx(BIO *out, const stname *x, int indent,       \
+                               const ASN1_PCTX *pctx);
+# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname)                   \
+    DECLARE_ASN1_PRINT_FUNCTION_fname_attr(extern, stname, fname)
 
 # define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
 # define I2D_OF(type) int (*)(const type *,unsigned char **)
@@ -344,8 +375,10 @@ typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
 
 # define ASN1_ITEM_rptr(ref) (ref##_it())
 
-# define DECLARE_ASN1_ITEM(name) \
-        const ASN1_ITEM * name##_it(void);
+# define DECLARE_ASN1_ITEM_attr(attr, name)                                 \
+    attr const ASN1_ITEM * name##_it(void);
+# define DECLARE_ASN1_ITEM(name)                                            \
+    DECLARE_ASN1_ITEM_attr(extern, name)
 
 /* Parameters used by ASN1_STRING_print_ex() */
 
diff --git a/include/openssl/macros.h b/include/openssl/macros.h
index 2ed8fcf002..24fad673bd 100644
--- a/include/openssl/macros.h
+++ b/include/openssl/macros.h
@@ -25,27 +25,56 @@
 
 /*
  * Generic deprecation macro
-  *
-  * If OPENSSL_SUPPRESS_DEPRECATED is defined, then DECLARE_DEPRECATED
-  * becomes a no-op
+ *
+ * If OPENSSL_SUPPRESS_DEPRECATED is defined, then OSSL_DEPRECATED and
+ * OSSL_DEPRECATED_FOR become no-ops
  */
-# ifndef DECLARE_DEPRECATED
-#  define DECLARE_DEPRECATED(f)   f;
+# ifndef OSSL_DEPRECATED
+#  undef OSSL_DEPRECATED_FOR
 #  ifndef OPENSSL_SUPPRESS_DEPRECATED
-#   ifdef __GNUC__
-#    if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
-#     undef DECLARE_DEPRECATED
-#     define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
+#   if defined(_MSC_VER)
+     /*
+      * MSVC supports __declspec(deprecated) since MSVC 2003 (13.10),
+      * and __declspec(deprecated(message)) since MSVC 2005 (14.00)
+      */
+#    if _MSC_VER >= 1400
+#     define OSSL_DEPRECATED(since) \
+          __declspec(deprecated("Since OpenSSL " # since))
+#     define OSSL_DEPRECATED_FOR(since, message) \
+          __declspec(deprecated("Since OpenSSL " # since ";" message))
+#    elif _MSC_VER >= 1310
+#     define OSSL_DEPRECATED(since) __declspec(deprecated)
+#     define OSSL_DEPRECATED_FOR(since, message) __declspec(deprecated)
+#    endif
+#   elif defined(__GNUC__)
+     /*
+      * According to GCC documentation, deprecations with message appeared in
+      * GCC 4.5.0
+      */
+#    if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#     define OSSL_DEPRECATED(since) \
+          __attribute__((deprecated("Since OpenSSL " # since)))
+#     define OSSL_DEPRECATED_FOR(since, message) \
+          __attribute__((deprecated("Since OpenSSL " # since ";" message)))
+#    elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
+#     define OSSL_DEPRECATED(since) __attribute__((deprecated))
+#     define OSSL_DEPRECATED_FOR(since, message) __attribute__((deprecated))
 #    endif
 #   elif defined(__SUNPRO_C)
 #    if (__SUNPRO_C >= 0x5130)
-#     undef DECLARE_DEPRECATED
-#     define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
+#     define OSSL_DEPRECATED(since) __attribute__ ((deprecated))
+#     define OSSL_DEPRECATED_FOR(since, message) __attribute__ ((deprecated))
 #    endif
 #   endif
 #  endif
 # endif
 
+/* Still not defined?  Then define empty macros */
+# ifndef OSSL_DEPRECATED
+#  define OSSL_DEPRECATED(since)
+#  define OSSL_DEPRECATED_FOR(since, message)
+# endif
+
 /*
  * Applications should use -DOPENSSL_API_COMPAT=<version> to suppress the
  * declarations of functions deprecated in or before <version>.  If this is
@@ -122,10 +151,17 @@
 # endif
 
 /*
- * Define macros for deprecation purposes.  We always define the macros
- * DEPERECATEDIN_{major}_{minor}() for all OpenSSL versions we care for,
- * and OPENSSL_NO_DEPRECATED_{major}_{minor} to be used to check if
- * removal of deprecated functions applies on that particular version.
+ * Define macros for deprecation and simulated removal purposes.
+ *
+ * The macros OSSL_DEPRECATED_{major}_{minor} are always defined for
+ * all OpenSSL versions we care for.  They can be used as attributes
+ * in function declarations where appropriate.
+ *
+ * The macros OPENSSL_NO_DEPRECATED_{major}_{minor} are defined for
+ * all OpenSSL versions up to or equal to the version given with
+ * OPENSSL_API_COMPAT.  They are used as guards around anything that's
+ * deprecated up to that version, as an effect of the developer option
+ * 'no-deprecated'.
  */
 
 # undef OPENSSL_NO_DEPRECATED_3_0
@@ -138,73 +174,101 @@
 
 # if OPENSSL_API_LEVEL >= 30000
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_3_0(f)       DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_3_0                OSSL_DEPRECATED(3.0)
+#   define OSSL_DEPRECATEDIN_3_0_FOR(msg)       OSSL_DEPRECATED_FOR(3.0, msg)
+#   define DEPRECATEDIN_3_0(f)                  OSSL_DEPRECATEDIN_3_0 f;
 #  else
-#   define DEPRECATEDIN_3_0(f)
 #   define OPENSSL_NO_DEPRECATED_3_0
+#   define DEPRECATEDIN_3_0(f)
 #  endif
 # else
-#  define DEPRECATEDIN_3_0(f)        f;
+#  define OSSL_DEPRECATEDIN_3_0
+#  define OSSL_DEPRECATEDIN_3_0_FOR(msg)
+#  define DEPRECATEDIN_3_0(f)                   f;
 # endif
 # if OPENSSL_API_LEVEL >= 10101
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_1_1_1(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_1_1_1              OSSL_DEPRECATED(1.1.1)
+#   define OSSL_DEPRECATEDIN_1_1_1_FOR(msg)     OSSL_DEPRECATED_FOR(1.1.1, msg)
+#   define DEPRECATEDIN_1_1_1(f)                OSSL_DEPRECATEDIN_1_1_1 f;
 #  else
-#   define DEPRECATEDIN_1_1_1(f)
 #   define OPENSSL_NO_DEPRECATED_1_1_1
+#   define DEPRECATEDIN_1_1_1(f)
 #  endif
 # else
-#  define DEPRECATEDIN_1_1_1(f)      f;
+#  define OSSL_DEPRECATEDIN_1_1_1
+#  define OSSL_DEPRECATEDIN_1_1_1_FOR(msg)
+#  define DEPRECATEDIN_1_1_1(f)                 f;
 # endif
 # if OPENSSL_API_LEVEL >= 10100
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_1_1_0(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_1_1_0              OSSL_DEPRECATED(1.1.0)
+#   define OSSL_DEPRECATEDIN_1_1_0_FOR(msg)     OSSL_DEPRECATED_FOR(1.1.0, msg)
+#   define DEPRECATEDIN_1_1_0(f)                OSSL_DEPRECATEDIN_1_1_0 f;
 #  else
-#   define DEPRECATEDIN_1_1_0(f)
 #   define OPENSSL_NO_DEPRECATED_1_1_0
+#   define DEPRECATEDIN_1_1_0(f)
 #  endif
 # else
-#  define DEPRECATEDIN_1_1_0(f)      f;
+#  define OSSL_DEPRECATEDIN_1_1_0
+#  define OSSL_DEPRECATEDIN_1_1_0_FOR(msg)
+#  define DEPRECATEDIN_1_1_0(f)                 f;
 # endif
 # if OPENSSL_API_LEVEL >= 10002
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_1_0_2(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_1_0_2              OSSL_DEPRECATED(1.0.2)
+#   define OSSL_DEPRECATEDIN_1_0_2_FOR(msg)     OSSL_DEPRECATED_FOR(1.0.2, msg)
+#   define DEPRECATEDIN_1_0_2(f)                OSSL_DEPRECATEDIN_1_0_2 f;
 #  else
-#   define DEPRECATEDIN_1_0_2(f)
 #   define OPENSSL_NO_DEPRECATED_1_0_2
+#   define DEPRECATEDIN_1_0_2(f)
 #  endif
 # else
-#  define DEPRECATEDIN_1_0_2(f)      f;
+#  define OSSL_DEPRECATEDIN_1_0_2
+#  define OSSL_DEPRECATEDIN_1_0_2_FOR(msg)
+#  define DEPRECATEDIN_1_0_2(f)                 f;
 # endif
 # if OPENSSL_API_LEVEL >= 10001
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_1_0_1(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_1_0_1              OSSL_DEPRECATED(1.0.1)
+#   define OSSL_DEPRECATEDIN_1_0_1_FOR(msg)     OSSL_DEPRECATED_FOR(1.0.1, msg)
+#   define DEPRECATEDIN_1_0_1(f)                OSSL_DEPRECATEDIN_1_0_1 f;
 #  else
-#   define DEPRECATEDIN_1_0_1(f)
 #   define OPENSSL_NO_DEPRECATED_1_0_1
+#   define DEPRECATEDIN_1_0_1(f)
 #  endif
 # else
-#  define DEPRECATEDIN_1_0_1(f)      f;
+#  define OSSL_DEPRECATEDIN_1_0_1
+#  define OSSL_DEPRECATEDIN_1_0_1_FOR(msg)
+#  define DEPRECATEDIN_1_0_1(f)                 f;
 # endif
 # if OPENSSL_API_LEVEL >= 10000
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_1_0_0(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_1_0_0              OSSL_DEPRECATED(1.0.0)
+#   define OSSL_DEPRECATEDIN_1_0_0_FOR(msg)     OSSL_DEPRECATED_FOR(1.0.0, msg)
+#   define DEPRECATEDIN_1_0_0(f)                OSSL_DEPRECATEDIN_1_0_0 f;
 #  else
-#   define DEPRECATEDIN_1_0_0(f)
 #   define OPENSSL_NO_DEPRECATED_1_0_0
+#   define DEPRECATEDIN_1_0_0(f)
 #  endif
 # else
-#  define DEPRECATEDIN_1_0_0(f)      f;
+#  define OSSL_DEPRECATEDIN_1_0_0
+#  define OSSL_DEPRECATEDIN_1_0_0_FOR(msg)
+#  define DEPRECATEDIN_1_0_0(f)                 f;
 # endif
 # if OPENSSL_API_LEVEL >= 908
 #  ifndef OPENSSL_NO_DEPRECATED
-#   define DEPRECATEDIN_0_9_8(f)     DECLARE_DEPRECATED(f)
+#   define OSSL_DEPRECATEDIN_0_9_8              OSSL_DEPRECATED(0.9.8)
+#   define OSSL_DEPRECATEDIN_0_9_8_FOR(msg)     OSSL_DEPRECATED_FOR(0.9.8, msg)
+#   define DEPRECATEDIN_0_9_8(f)                OSSL_DEPRECATEDIN_0_9_8 f;
 #  else
-#   define DEPRECATEDIN_0_9_8(f)
 #   define OPENSSL_NO_DEPRECATED_0_9_8
+#   define DEPRECATEDIN_0_9_8(f)
 #  endif
 # else
-#  define DEPRECATEDIN_0_9_8(f)      f;
+#  define OSSL_DEPRECATEDIN_0_9_8
+#  define OSSL_DEPRECATEDIN_0_9_8_FOR(msg)
+#  define DEPRECATEDIN_0_9_8(f)                 f;
 # endif
 
 /*
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index 9247922574..a5e0077715 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -191,72 +191,110 @@ extern "C" {
 
 /* These are the same except they are for the declarations */
 
+/*
+ * The mysterious 'extern' that's passed to some macros is innocuous,
+ * and is there to quiet pre-C99 compilers that may complain about empty
+ * arguments in macro calls.
+ */
 # if defined(OPENSSL_NO_STDIO)
 
-#  define DECLARE_PEM_read_fp(name, type) /**/
-#  define DECLARE_PEM_write_fp(name, type) /**/
+#  define DECLARE_PEM_read_fp_attr(attr, name, type) /**/
+#  define DECLARE_PEM_write_fp_attr(attr, name, type) /**/
+#  define DECLARE_PEM_write_fp_attr(attr, name, type) /**/
 #  ifndef OPENSSL_NO_DEPRECATED_3_0
-#   define DECLARE_PEM_write_fp_const(name, type) /**/
+#   define DECLARE_PEM_write_fp_const_attr(attr, name, type) /**/
 #  endif
-#  define DECLARE_PEM_write_cb_fp(name, type) /**/
-# else
+#  define DECLARE_PEM_write_cb_fp_attr(attr, name, type) /**/
 
-#  define DECLARE_PEM_read_fp(name, type)                               \
-    type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
-
-#  define DECLARE_PEM_write_fp(name, type)              \
-    PEM_write_fnsig(name, type, FILE, write);
+# else
 
+#  define DECLARE_PEM_read_fp_attr(attr, name, type)                        \
+    attr type *PEM_read_##name(FILE *fp, type **x,                          \
+                               pem_password_cb *cb, void *u);
+#  define DECLARE_PEM_write_fp_attr(attr, name, type)                       \
+    attr PEM_write_fnsig(name, type, FILE, write);
 #  ifndef OPENSSL_NO_DEPRECATED_3_0
-#   define DECLARE_PEM_write_fp_const(name, type)       \
-    PEM_write_fnsig(name, type, FILE, write);
+#   define DECLARE_PEM_write_fp_const_attr(attr, name, type)                \
+    attr PEM_write_fnsig(name, type, FILE, write);
 #  endif
+#  define DECLARE_PEM_write_cb_fp_attr(attr, name, type)                    \
+    attr PEM_write_cb_fnsig(name, type, FILE, write);
 
-#  define DECLARE_PEM_write_cb_fp(name, type)           \
-    PEM_write_cb_fnsig(name, type, FILE, write);
+# endif
 
+# define DECLARE_PEM_read_fp(name, type)                                   \
+    DECLARE_PEM_read_fp_attr(extern, name, type)
+# define DECLARE_PEM_write_fp(name, type)                                  \
+    DECLARE_PEM_write_fp_attr(extern, name, type)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+#   define DECLARE_PEM_write_fp_const(name, type)                           \
+    DECLARE_PEM_write_fp_const_attr(extern, name, type)
 # endif
+# define DECLARE_PEM_write_cb_fp(name, type)                               \
+    DECLARE_PEM_write_cb_fp_attr(extern, name, type)
 
-#  define DECLARE_PEM_read_bio(name, type)                      \
-    type *PEM_read_bio_##name(BIO *bp, type **x,                \
-                              pem_password_cb *cb, void *u);
+# define DECLARE_PEM_read_bio_attr(attr, name, type)                        \
+    attr type *PEM_read_bio_##name(BIO *bp, type **x,                       \
+                                   pem_password_cb *cb, void *u);
+# define DECLARE_PEM_read_bio(name, type)                                   \
+    DECLARE_PEM_read_bio_attr(extern, name, type)
 
-#  define DECLARE_PEM_write_bio(name, type)             \
-    PEM_write_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_bio_attr(attr, name, type)                       \
+    attr PEM_write_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_bio(name, type)                                  \
+    DECLARE_PEM_write_bio_attr(extern, name, type)
 
-#  ifndef OPENSSL_NO_DEPRECATED_3_0
-#   define DECLARE_PEM_write_bio_const(name, type)      \
-    PEM_write_fnsig(name, type, BIO, write_bio);
-#  endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+#  define DECLARE_PEM_write_bio_const_attr(attr, name, type)                \
+    attr PEM_write_fnsig(name, type, BIO, write_bio);
+#  define DECLARE_PEM_write_bio_const(name, type)      \
+    DECLARE_PEM_write_bio_const_attr(extern, name, type)
+# endif
 
-#  define DECLARE_PEM_write_cb_bio(name, type)          \
-    PEM_write_cb_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_cb_bio_attr(attr, name, type)                    \
+    attr PEM_write_cb_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_cb_bio(name, type)                               \
+    DECLARE_PEM_write_cb_bio_attr(extern, name, type)
 
+# define DECLARE_PEM_write_attr(attr, name, type)                           \
+    DECLARE_PEM_write_bio_attr(attr, name, type)                            \
+    DECLARE_PEM_write_fp_attr(attr, name, type)
 # define DECLARE_PEM_write(name, type) \
-        DECLARE_PEM_write_bio(name, type) \
-        DECLARE_PEM_write_fp(name, type)
+    DECLARE_PEM_write_attr(extern, name, type)
 # ifndef OPENSSL_NO_DEPRECATED_3_0
-#  define DECLARE_PEM_write_const(name, type) \
-        DECLARE_PEM_write_bio_const(name, type) \
-        DECLARE_PEM_write_fp_const(name, type)
+#  define DECLARE_PEM_write_const_attr(attr, name, type)                    \
+    DECLARE_PEM_write_bio_const_attr(attr, name, type)                      \
+    DECLARE_PEM_write_fp_const_attr(attr, name, type)
+#  define DECLARE_PEM_write_const(name, type)                               \
+    DECLARE_PEM_write_const_attr(extern, name, type)
 # endif
-# define DECLARE_PEM_write_cb(name, type) \
-        DECLARE_PEM_write_cb_bio(name, type) \
-        DECLARE_PEM_write_cb_fp(name, type)
-# define DECLARE_PEM_read(name, type) \
-        DECLARE_PEM_read_bio(name, type) \
-        DECLARE_PEM_read_fp(name, type)
+# define DECLARE_PEM_write_cb_attr(attr, name, type)                        \
+    DECLARE_PEM_write_cb_bio_attr(attr, name, type)                         \
+    DECLARE_PEM_write_cb_fp_attr(attr, name, type)
+# define DECLARE_PEM_write_cb(name, type)                                   \
+    DECLARE_PEM_write_cb_attr(extern, name, type)
+# define DECLARE_PEM_read_attr(attr, name, type)                            \
+    DECLARE_PEM_read_bio_attr(attr, name, type)                             \
+    DECLARE_PEM_read_fp_attr(attr, name, type)
+# define DECLARE_PEM_read(name, type)                                       \
+    DECLARE_PEM_read_attr(extern, name, type)
+# define DECLARE_PEM_rw_attr(attr, name, type)                              \
+    DECLARE_PEM_read_attr(attr, name, type)                                 \
+    DECLARE_PEM_write_attr(attr, name, type)
 # define DECLARE_PEM_rw(name, type) \
-        DECLARE_PEM_read(name, type) \
-        DECLARE_PEM_write(name, type)
+    DECLARE_PEM_rw_attr(extern, name, type)
 # ifndef OPENSSL_NO_DEPRECATED_3_0
+#  define DECLARE_PEM_rw_const_attr(attr, name, type)                       \
+    DECLARE_PEM_read_attr(attr, name, type)                                 \
+    DECLARE_PEM_write_const_attr(attr, name, type)
 #  define DECLARE_PEM_rw_const(name, type) \
-        DECLARE_PEM_read(name, type) \
-        DECLARE_PEM_write_const(name, type)
+    DECLARE_PEM_rw_const_attr(extern, name, type)
 # endif
+# define DECLARE_PEM_rw_cb_attr(attr, name, type)                           \
+    DECLARE_PEM_read_attr(attr, name, type)                                 \
+    DECLARE_PEM_write_cb_attr(attr, name, type)
 # define DECLARE_PEM_rw_cb(name, type) \
-        DECLARE_PEM_read(name, type) \
-        DECLARE_PEM_write_cb(name, type)
+    DECLARE_PEM_rw_cb_attr(extern, name, type)
 
 int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
 int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len,
diff --git a/util/missingmacro.txt b/util/missingmacro.txt
index 2b02fef5f5..109bb0870f 100644
--- a/util/missingmacro.txt
+++ b/util/missingmacro.txt
@@ -176,3 +176,14 @@ X509V3_set_ctx_test(3)
 X509V3_set_ctx_nodb(3)
 EXT_BITSTRING(3)
 EXT_IA5STRING(3)
+
+# These are documented internally, in doc/internal/man7/deprecation.pod
+OSSL_DEPRECATED(3)
+OSSL_DEPRECATED_FOR(3)
+OSSL_DEPRECATEDIN_3_0_FOR(3)
+OSSL_DEPRECATEDIN_1_1_1_FOR(3)
+OSSL_DEPRECATEDIN_1_1_0_FOR(3)
+OSSL_DEPRECATEDIN_1_0_2_FOR(3)
+OSSL_DEPRECATEDIN_1_0_1_FOR(3)
+OSSL_DEPRECATEDIN_1_0_0_FOR(3)
+OSSL_DEPRECATEDIN_0_9_8_FOR(3)
diff --git a/util/perl/OpenSSL/Ordinals.pm b/util/perl/OpenSSL/Ordinals.pm
index 7008ebf536..8f113fb8f6 100644
--- a/util/perl/OpenSSL/Ordinals.pm
+++ b/util/perl/OpenSSL/Ordinals.pm
@@ -407,7 +407,6 @@ sub _parse_features {
         if ($def =~ m{^ZLIB$})                      { $features{$&} =  $op; }
         if ($def =~ m{^OPENSSL_USE_})               { $features{$'} =  $op; }
         if ($def =~ m{^OPENSSL_NO_})                { $features{$'} = !$op; }
-        if ($def =~ m{^DEPRECATEDIN_(.*)$})         { $features{$&} = !$op; }
     }
 
     return %features;
diff --git a/util/perl/OpenSSL/ParseC.pm b/util/perl/OpenSSL/ParseC.pm
index 7e6377dd17..5cc5f28bf3 100644
--- a/util/perl/OpenSSL/ParseC.pm
+++ b/util/perl/OpenSSL/ParseC.pm
@@ -75,7 +75,7 @@ my @opensslcpphandlers = (
 #if$1 OPENSSL_NO_DEPRECATEDIN_$2
 EOF
       }
-   }
+    }
 );
 my @cpphandlers = (
     ##################################################################
@@ -262,17 +262,40 @@ my @opensslchandlers = (
     # Deprecated stuff, by OpenSSL release.
 
     # We trick the parser by pretending that the declaration is wrapped in a
-    # check if the DEPRECATEDIN macro is defined or not.  Callers of parse()
-    # will have to decide what to do with it.
+    # check if the OPENSSL_NO_DEPRECATEDIN_x_y[_z] macro is defined or not.
+    # Callers of parse() will have to decide what to do with it.
     { regexp   => qr/(DEPRECATEDIN_\d+_\d+(?:_\d+)?)<<<\((.*)\)>>>/,
       massager => sub { return (<<"EOF");
-#ifndef $1
+#ifndef OPENSSL_NO_$1
 $2;
 #endif
 EOF
       },
     },
 
+    # OSSL_DEPRECATEDIN_x_y[_z] is simply ignored.  Such declarations are
+    # supposed to be guarded with an '#ifdef OPENSSL_NO_DEPRECATED_x_y[_z]'
+    { regexp   => qr/OSSL_DEPRECATEDIN_\d+_\d+(?:_\d+)?\s+(.*)/,
+      massager => sub { return $1; },
+    },
+    { regexp   => qr/(.*?)\s+OSSL_DEPRECATEDIN_\d+_\d+(?:_\d+)?\s+(.*)/,
+      massager => sub { return "$1 $2"; },
+    },
+
+    #####
+    # Core stuff
+
+    # OSSL_CORE_MAKE_FUNC is a macro to create the necessary data and inline
+    # function the libcrypto<->provider interface
+    { regexp   => qr/OSSL_CORE_MAKE_FUNC<<<\((.*?),(.*?),(.*?)\)>>>/,
+      massager => sub {
+          return (<<"EOF");
+typedef $1 OSSL_FUNC_$2_fn$3;
+static ossl_inline OSSL_FUNC_$2_fn *OSSL_FUNC_$2(const OSSL_DISPATCH *opf);
+EOF
+      },
+    },
+
     #####
     # LHASH stuff
 
@@ -498,9 +521,27 @@ int $2_dup(void);
 EOF
       }
     },
+    # Universal translator of attributed PEM declarators
+    { regexp   => qr/
+          DECLARE_ASN1
+          (_ENCODE_FUNCTIONS_only|_ENCODE_FUNCTIONS|_ENCODE_FUNCTIONS_name
+           |_ALLOC_FUNCTIONS_name|_ALLOC_FUNCTIONS|_FUNCTIONS_name|_FUNCTIONS
+           |_NDEF_FUNCTION|_PRINT_FUNCTION|_PRINT_FUNCTION_name
+           |_DUP_FUNCTION|_DUP_FUNCTION_name)
+          _attr
+          <<<\(\s*OSSL_DEPRECATEDIN_(.*?)\s*,(.*?)\)>>>
+      /x,
+      massager => sub { return (<<"EOF");
+DECLARE_ASN1$1($3)
+EOF
+      },
+    },
     { regexp   => qr/DECLARE_PKCS12_SET_OF<<<\((.*)\)>>>/,
       massager => sub { return (); }
     },
+
+    #####
+    # PEM stuff
     { regexp   => qr/DECLARE_PEM(?|_rw|_rw_cb|_rw_const)<<<\((.*?),.*\)>>>/,
       massager => sub { return (<<"EOF");
 #ifndef OPENSSL_NO_STDIO
@@ -512,9 +553,6 @@ int PEM_write_bio_$1(void);
 EOF
       },
     },
-
-    #####
-    # PEM stuff
     { regexp   => qr/DECLARE_PEM(?|_write|_write_cb|_write_const)<<<\((.*?),.*\)>>>/,
       massager => sub { return (<<"EOF");
 #ifndef OPENSSL_NO_STDIO
@@ -530,6 +568,18 @@ EOF
 int PEM_read_$1(void);
 #endif
 int PEM_read_bio_$1(void);
+EOF
+      },
+    },
+    # Universal translator of attributed PEM declarators
+    { regexp   => qr/
+          DECLARE_PEM
+          (_rw|_rw_cb|_rw_const|_write|_write_cb|_write_const|_read|_read_cb)
+          _attr
+          <<<\(\s*OSSL_DEPRECATEDIN_(.*?)\s*,(.*?)\)>>>
+      /x,
+      massager => sub { return (<<"EOF");
+DECLARE_PEM$1($3)
 EOF
       },
     },


More information about the openssl-commits mailing list