Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL
authorDavid von Oheimb <David.von.Oheimb@siemens.com>
Wed, 17 Oct 2018 13:51:19 +0000 (15:51 +0200)
committerMatt Caswell <matt@openssl.org>
Tue, 12 Mar 2019 12:22:59 +0000 (12:22 +0000)
Also includes CRMF (RFC 4211) and HTTP transfer (RFC 6712)

CMP and CRMF API is added to libcrypto, and the "cmp" app to the openssl CLI.
Adds extensive man pages and tests.  Integration into build scripts.

Incremental pull request based on OpenSSL commit 1362190b1b78 of 2018-09-26

1st chunk: CRMF API (include/openssl/crmf.h) and its documentation (reviewed)

Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7328)

doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod [new file with mode: 0644]
doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod [new file with mode: 0644]
doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod [new file with mode: 0644]
doc/man3/OSSL_CRMF_MSG_set_validity.pod [new file with mode: 0644]
doc/man3/OSSL_CRMF_pbmp_new.pod [new file with mode: 0644]
doc/man3/X509_dup.pod
include/openssl/crmf.h [new file with mode: 0644]

diff --git a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
new file mode 100644 (file)
index 0000000..fbce702
--- /dev/null
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_get0_tmpl,
+OSSL_CRMF_CERTTEMPLATE_get0_serialNumber,
+OSSL_CRMF_CERTTEMPLATE_get0_issuer,
+OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert,
+OSSL_CRMF_MSG_get_certReqId
+- functions reading from CRMF CertReqMsg structures
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm);
+ ASN1_INTEGER
+     *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(OSSL_CRMF_CERTTEMPLATE *tmpl);
+ X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl);
+
+ X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+                                             EVP_PKEY *pkey);
+
+ int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm);
+
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_get0_tmpl() retrieves the certificate template of B<crm>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_serialNumber() retrieves the serialNumber of the
+given certificate template B<tmpl>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_issuer() retrieves the issuer name of the
+given certificate template B<tmpl>.
+
+OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert() decrypts the certificate in the given
+encryptedValue B<ecert>, using the private key B<pkey>.
+This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
+The function returns the decrypted certificate as a copy, leaving its ownership
+with the caller, who is responsible for freeing it.
+
+OSSL_CRMF_MSG_get_certReqId() retrieves the certReqId of B<crm>.
+
+
+=head1 RETURN VALUES
+
+OSSL_CRMF_MSG_get_certReqId() returns the certificate request ID as a
+non-negative integer or -1 on error.
+
+All other functions return a pointer with the intended result or NULL on error.
+
+=head1 SEE ALSO
+
+B<RFC 4211>
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod b/doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
new file mode 100644 (file)
index 0000000..1b80c72
--- /dev/null
@@ -0,0 +1,105 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_set1_regCtrl_regToken,
+OSSL_CRMF_MSG_set1_regCtrl_authenticator,
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo,
+OSSL_CRMF_MSG_set0_SinglePubInfo,
+OSSL_CRMF_MSG_set_PKIPublicationInfo_action,
+OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo,
+OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey,
+OSSL_CRMF_MSG_set1_regCtrl_oldCertID,
+OSSL_CRMF_CERTID_gen
+- functions setting CRMF Registration Controls
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
+                                         const ASN1_UTF8STRING *tok);
+ int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
+                                              const ASN1_UTF8STRING *auth);
+ int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
+                                  OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                  OSSL_CRMF_SINGLEPUBINFO *spi);
+ int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+                                      int method, GENERAL_NAME *nm);
+ int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
+                                  OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action);
+ int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
+                                        const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
+ int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
+                                                const X509_PUBKEY *pubkey);
+ int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
+                                          const OSSL_CRMF_CERTID *cid);
+ OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+                                        const ASN1_INTEGER *serial);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_set1_regCtrl_regToken() sets the regToken control in the given
+B<msg> copying the given B<tok> as value. See RFC 4211, section 6.1.
+
+OSSL_CRMF_MSG_set1_regCtrl_authenticator() sets the authenticator control in
+the given B<msg> copying the given B<auth> as value. See RFC 4211, section 6.2.
+
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo() pushes the given B<spi>
+to B<si>. Consumes the B<spi> pointer.
+
+OSSL_CRMF_MSG_set0_SinglePubInfo() sets given B<method> and PubLoction B<nm> to
+B<spi>.  PubLocation is optional, and therefore B<nm> may be NULL. Consumes the
+B<nm> pointer.
+Available methods are:
+ # define OSSL_CRMF_PUB_METHOD_DONTCARE 0
+ # define OSSL_CRMF_PUB_METHOD_X500     1
+ # define OSSL_CRMF_PUB_METHOD_WEB      2
+ # define OSSL_CRMF_PUB_METHOD_LDAP     3
+
+OSSL_CRMF_MSG_set_PKIPublicationInfo_action() sets the action in the given B<pi>
+using the given B<action> as value. See RFC 4211, section 6.3.
+Available actions are:
+ # define OSSL_CRMF_PUB_ACTION_DONTPUBLISH   0
+ # define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
+
+OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo() sets the pkiPulicationInfo
+control in the given B<msg> copying the given B<tok> as value. See RFC 4211,
+section 6.3.
+
+OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey() sets the protocolEncrKey control in
+the given B<msg> copying the given B<pubkey> as value. See RFC 4211, section 6.6.
+
+OSSL_CRMF_MSG_set1_regCtrl_oldCertID() sets the oldCertID control in the given
+B<msg> copying the given B<cid> as value. See RFC 4211, section 6.5.
+
+OSSL_CRMF_CERTID_gen produces an OSSL_CRMF_CERTID_gen structure copying the
+given B<issuer> name and B<serial> number.
+
+=head1 RETURN VALUES
+
+OSSL_CRMF_CERTID_gen returns a pointer to the resulting structure
+or NULL on error.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 NOTES
+
+A function OSSL_CRMF_MSG_set1_regCtrl_pkiArchiveOptions() for setting an
+Archive Options Control is not yet implemented due to missing features to
+create the needed OSSL_CRMF_PKIARCHIVEOPTINS content.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod b/doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
new file mode 100644 (file)
index 0000000..9e33a4a
--- /dev/null
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_set1_regInfo_utf8Pairs,
+OSSL_CRMF_MSG_set1_regInfo_certReq
+- functions setting CRMF Registration Info
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ int OSSL_CRMF_MSG_set1_regInfo_utf8Pairs(OSSL_CRMF_MSG *msg,
+                                          const ASN1_UTF8STRING *utf8pairs);
+ int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg,
+                                        const OSSL_CRMF_CERTREQUEST *cr);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_set1_regInfo_utf8Pairs() adds a copy of the given B<utf8pairs>
+value as utf8Pairs regInfo to the given B<msg>. See RFC 4211 section 7.1.
+
+OSSL_CRMF_MSG_set1_regInfo_certReq() adds a copy of the given B<cr> value
+as certReq regInfo to the given B<msg>. See RFC 4211 section 7.2.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 NOTES
+
+Calling these functions multiple times adds multiple instances of the respective
+control to the regInfo structure of the given B<msg>. While RFC 4211 expects
+multiple utf8Pairs in one regInfo structure, it does not allow multiple certReq.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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/man3/OSSL_CRMF_MSG_set_validity.pod b/doc/man3/OSSL_CRMF_MSG_set_validity.pod
new file mode 100644 (file)
index 0000000..a610337
--- /dev/null
@@ -0,0 +1,103 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_set_validity,
+OSSL_CRMF_MSG_set_certReqId,
+OSSL_CRMF_CERTTEMPLATE_fill,
+OSSL_CRMF_MSG_set0_extensions,
+OSSL_CRMF_MSG_push0_extension,
+OSSL_CRMF_MSG_create_popo,
+OSSL_CRMF_MSGS_verify_popo
+- functions populating and verifying CRMF CertReqMsg structures
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ int OSSL_CRMF_MSG_set_validity(OSSL_CRMF_MSG *crm, time_t from, time_t to);
+
+ int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, const int rid);
+
+ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+                                 const EVP_PKEY *pubkey,
+                                 const X509_NAME *subject,
+                                 const X509_NAME *issuer,
+                                 const ASN1_INTEGER *serial);
+
+ int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm,
+                                   X509_EXTENSIONS *exts);
+
+ int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm,
+                                   const X509_EXTENSION *ext);
+
+ int OSSL_CRMF_MSG_create_popo(OSSL_CRMF_MSG *crm, const EVP_PKEY *pkey,
+                               int dgst, int ppmtd);
+
+ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+                                int rid, int acceptRAVerified);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_set_validity() sets B<from> as notBefore and B<to> as notAfter
+as the validity in the certTemplate of B<crm>.
+
+OSSL_CRMF_MSG_set_certReqId() sets B<rid> as the certReqId of B<crm>.
+
+OSSL_CRMF_CERTTEMPLATE_fill() sets those fields of the certTemplate B<tmpl>
+for which non-NULL values are provided: B<pubkey>, B<subject>, B<issuer>,
+and/or B<serial>. The arguments are not consumed.
+
+OSSL_CRMF_MSG_set0_extensions() sets B<exts> as the extensions in the
+certTemplate of B<crm>. Consumes B<exts>.
+
+OSSL_CRMF_MSG_push0_extension() pushes the X509 extension B<ext> to the
+extensions in the certTemplate of B<crm>.  Consumes B<ext>.
+
+OSSL_CRMF_MSG_create_popo() creates and sets the Proof-of-Possession (POP)
+according to the method B<ppmtd> for B<pkey> to B<crm>. In case the method is
+OSSL_CRMF_POPO_SIGNATURE, POP is calculated using the B<dgst>.
+
+B<ppmtd> can be one of the following:
+
+=over 8
+
+=item * OSSL_CRMF_POPO_NONE       - RFC 4211, section 4, POP field omitted.
+CA/RA uses out-of-band method to verify POP. Note that servers may fail in this
+case, resulting for instance in HTTP error code 500 (Internal error).
+
+=item * OSSL_CRMF_POPO_RAVERIFIED - RFC 4211, section 4, explicit indication
+that the RA has already verified the POP.
+
+=item * OSSL_CRMF_POPO_SIGNATURE  - RFC 4211, section 4.1, only case 3 supported
+so far.
+
+=item * OSSL_CRMF_POPO_KEYENC     - RFC 4211, section 4.2, only indirect method
+(subsequentMessage/enccert) supported,
+challenge-response exchange (challengeResp) not yet supported.
+
+=item * OSSL_CRMF_POPO_KEYAGREE   - RFC 4211, section 4.3, not yet supported.
+
+=back
+
+OSSL_CRMF_MSGS_verify_popo verifies the Proof-of-Possession of the request with
+the given B<rid> in the list of B<reqs>. Optionally accepts RAVerified.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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/man3/OSSL_CRMF_pbmp_new.pod b/doc/man3/OSSL_CRMF_pbmp_new.pod
new file mode 100644 (file)
index 0000000..d386d2b
--- /dev/null
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_pbm_new,
+OSSL_CRMF_pbmp_new
+- functions for producing Password-Based MAC (PBM)
+
+=head1 SYNOPSIS
+
+  #include <openssl/crmf.h>
+
+  int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
+                        const unsigned char *msg, size_t msglen,
+                        const unsigned char *sec, size_t seclen,
+                        unsigned char **mac, unsigned int *maclen);
+
+  OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t saltlen, int owfnid,
+                                             int itercnt, int macnid);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_pbm_new() generates a PBM (Password-Based MAC) based on given PBM
+parameters B<pbmp>, message B<msg>, and secret B<sec>, along with the respective
+lengths B<msglen> and B<seclen>. Will write the adddress of the newly allocated
+MAC via the B<mac> reference parameter and the length via the B<maclen> reference
+parameter. Any previous pointer referred to by B<mac> will be freed if not NULL.
+
+The iteration count must be at least 100, as stipulated by RFC 4211, and is
+limited to at most 100000 to avoid DoS through manipulated or otherwise
+malformed input.
+
+OSSL_CRMF_pbmp_new() initializes and returns a new PBMParameter
+structure with new a random salt of given length B<saltlen>, OWF (one-way
+function) NID B<owfnid>, iteration count B<itercnt>, and MAC NID B<macnid>.
+
+=head1 NOTES
+
+The OWF (one-way function) and for the MAC (message authentication code) may be
+any with a NID defined in B<openssl/objects.h>,
+which also should include NID_hmac_sha1 which is specified by RFC 4210.
+
+RFC 4210 recommends that the salt SHOULD be at least 8 bytes (64 bits) long.
+
+=head1 RETURN VALUES
+
+OSSL_CRMF_pbm_new() returns 1 on success, 0 on error.
+
+OSSL_CRMF_pbmp_new() returns a new and initialized OSSL_CRMF_PBMPARAMETER
+structure, or NULL on error.
+
+=head1 EXAMPLE
+
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ unsigned char *msg = "Hello";
+ unsigend char *sec = "SeCrEt";
+ unsigend char *mac = NULL;
+ unsigend int maclen;
+
+ if ((pbm = OSSL_CRMF_pbmp_new(16, NID_sha256, 500, NID_hmac_sha1) == NULL))
+     goto err;
+ if (!OSSL_CRMF_pbm_new(pbm, msg, 5, sec, 6, &mac, &maclen))
+     goto err;
+
+=head1 SEE ALSO
+
+RFC 4211 section 4.4
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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
index 8ad7648e172f081aa898b8be5f9480f577ab13a9..2f51e4552c27fad0279ffce41872565d8d38b7fe 100644 (file)
@@ -116,6 +116,20 @@ OCSP_SIGNATURE_free,
 OCSP_SIGNATURE_new,
 OCSP_SINGLERESP_free,
 OCSP_SINGLERESP_new,
+OSSL_CRMF_CERTID_free,
+OSSL_CRMF_CERTID_new,
+OSSL_CRMF_CERTTEMPLATE_free,
+OSSL_CRMF_CERTTEMPLATE_new,
+OSSL_CRMF_ENCRYPTEDVALUE_free,
+OSSL_CRMF_ENCRYPTEDVALUE_new,
+OSSL_CRMF_MSG_free,
+OSSL_CRMF_MSG_new,
+OSSL_CRMF_PBMPARAMETER_free,
+OSSL_CRMF_PBMPARAMETER_new,
+OSSL_CRMF_PKIPUBLICATIONINFO_free,
+OSSL_CRMF_PKIPUBLICATIONINFO_new,
+OSSL_CRMF_MSGS_free,
+OSSL_CRMF_MSGS_new,
 OTHERNAME_free,
 OTHERNAME_new,
 PBE2PARAM_free,
diff --git a/include/openssl/crmf.h b/include/openssl/crmf.h
new file mode 100644 (file)
index 0000000..f88dd39
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2018
+ * Copyright Siemens AG 2015-2018
+ *
+ * Licensed under the OpenSSL license (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
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+#ifndef OSSL_HEADER_CRMF_H
+# define OSSL_HEADER_CRMF_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CRMF
+#  include <openssl/opensslv.h>
+#  include <openssl/safestack.h>
+#  include <openssl/crmferr.h>
+#  include <openssl/x509v3.h> /* for GENERAL_NAME etc. */
+
+/* explicit #includes not strictly needed since implied by the above: */
+#  include <openssl/ossl_typ.h>
+#  include <openssl/x509.h>
+
+#  ifdef  __cplusplus
+extern "C" {
+#  endif
+
+#  define OSSL_CRMF_POPOPRIVKEY_THISMESSAGE          0
+#  define OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE    1
+#  define OSSL_CRMF_POPOPRIVKEY_DHMAC                2
+#  define OSSL_CRMF_POPOPRIVKEY_AGREEMAC             3
+#  define OSSL_CRMF_POPOPRIVKEY_ENCRYPTEDKEY         4
+
+#  define OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT       0
+#  define OSSL_CRMF_SUBSEQUENTMESSAGE_CHALLENGERESP  1
+
+typedef struct OSSL_crmf_encrypetedvalue_st OSSL_CRMF_ENCRYPTEDVALUE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
+typedef struct OSSL_crmf_msg_st OSSL_CRMF_MSG;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
+DEFINE_STACK_OF(OSSL_CRMF_MSG)
+typedef struct OSSL_crmf_attributetypeandvalue_st OSSL_CRMF_ATTRIBUTETYPEANDVALUE;
+typedef struct OSSL_crmf_pbmparameter_st OSSL_CRMF_PBMPARAMETER;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
+typedef struct OSSL_crmf_poposigningkey_st OSSL_CRMF_POPOSIGNINGKEY;
+typedef struct OSSL_crmf_certrequest_st OSSL_CRMF_CERTREQUEST;
+typedef struct OSSL_crmf_certid_st OSSL_CRMF_CERTID;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTID)
+DEFINE_STACK_OF(OSSL_CRMF_CERTID)
+
+typedef struct OSSL_crmf_pkipublicationinfo_st OSSL_CRMF_PKIPUBLICATIONINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO)
+typedef struct OSSL_crmf_singlepubinfo_st OSSL_CRMF_SINGLEPUBINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
+typedef struct OSSL_crmf_certtemplate_st OSSL_CRMF_CERTTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+typedef STACK_OF(OSSL_CRMF_MSG) OSSL_CRMF_MSGS;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
+
+typedef struct OSSL_crmf_optionalvalidity_st OSSL_CRMF_OPTIONALVALIDITY;
+
+/* crmf_pbm.c */
+OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid,
+                                           int itercnt, int macnid);
+int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
+                      const unsigned char *msg, size_t msglen,
+                      const unsigned char *sec, size_t seclen,
+                      unsigned char **mac, unsigned int *maclen);
+
+/* crmf_lib.c */
+int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
+                                        const ASN1_UTF8STRING *tok);
+int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
+                                             const ASN1_UTF8STRING *auth);
+int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
+                                               OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                               OSSL_CRMF_SINGLEPUBINFO *spi);
+#  define OSSL_CRMF_PUB_METHOD_DONTCARE 0
+#  define OSSL_CRMF_PUB_METHOD_X500     1
+#  define OSSL_CRMF_PUB_METHOD_WEB      2
+#  define OSSL_CRMF_PUB_METHOD_LDAP     3
+int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+                                     int method, GENERAL_NAME *nm);
+#  define OSSL_CRMF_PUB_ACTION_DONTPUBLISH   0
+#  define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
+                                  OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action);
+int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
+                                        const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
+int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
+                                               const X509_PUBKEY *pubkey);
+int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
+                                         const OSSL_CRMF_CERTID *cid);
+OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+                                       const ASN1_INTEGER *serial);
+
+int OSSL_CRMF_MSG_set1_regInfo_utf8Pairs(OSSL_CRMF_MSG *msg,
+                                         const ASN1_UTF8STRING *utf8pairs);
+int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg,
+                                       const OSSL_CRMF_CERTREQUEST *cr);
+
+int OSSL_CRMF_MSG_set_validity(OSSL_CRMF_MSG *crm, time_t from, time_t to);
+int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid);
+int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm);
+int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
+
+int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, const X509_EXTENSION *ext);
+#  define OSSL_CRMF_POPO_NONE      -1
+#  define OSSL_CRMF_POPO_RAVERIFIED 0
+#  define OSSL_CRMF_POPO_SIGNATURE  1
+#  define OSSL_CRMF_POPO_KEYENC     2
+#  define OSSL_CRMF_POPO_KEYAGREE   3
+int OSSL_CRMF_MSG_create_popo(OSSL_CRMF_MSG *crm, const EVP_PKEY *pkey,
+                              int dgst, int ppmtd);
+int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+                               int rid, int acceptRAVerified);
+OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm);
+ASN1_INTEGER *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(OSSL_CRMF_CERTTEMPLATE *t);
+X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl);
+int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+                                const EVP_PKEY *pubkey,
+                                const X509_NAME *subject,
+                                const X509_NAME *issuer,
+                                const ASN1_INTEGER *serial);
+X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+                                            EVP_PKEY *pkey);
+
+#  ifdef __cplusplus
+}
+#  endif
+# endif /* !defined OPENSSL_NO_CRMF */
+#endif /* !defined OSSL_HEADER_CRMF_H */