[openssl] master update

Matt Caswell matt at openssl.org
Tue Mar 12 12:30:47 UTC 2019


The branch master has been updated
       via  a61b7f2fa6de3bf8d5b1436e66c52d6bf7150ae4 (commit)
       via  2a3b52eacd098a74157f5d4cbbb34ad8f863f04e (commit)
      from  eef721b0d02c41cb5cebef33a9911db25523724a (commit)


- Log -----------------------------------------------------------------
commit a61b7f2fa6de3bf8d5b1436e66c52d6bf7150ae4
Author: David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Nov 16 14:05:31 2018 +0100

    2nd chunk: CRMF code (crypto/crmf/, ) and its integration
    in INSTALL, Configure, crypto/build.info, include/openssl/crmferr.h,
    crypto/err/, include/openssl/err.h, and (to be updated:) util/libcrypto.num
    
    Reviewed-by: Bernd Edlinger <bernd.edlinger at hotmail.de>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/7646)

commit 2a3b52eacd098a74157f5d4cbbb34ad8f863f04e
Author: David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Oct 17 15:51:19 2018 +0200

    Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL
    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 at hotmail.de>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/7328)

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

Summary of changes:
 Configure                                        |   1 +
 crypto/build.info                                |   2 +-
 crypto/crmf/build.info                           |   2 +
 crypto/crmf/crmf_asn.c                           | 240 ++++++++
 crypto/crmf/crmf_err.c                           | 104 ++++
 crypto/crmf/crmf_int.h                           | 394 ++++++++++++
 crypto/crmf/crmf_lib.c                           | 753 +++++++++++++++++++++++
 crypto/crmf/crmf_pbm.c                           | 231 +++++++
 crypto/err/err.c                                 |   1 +
 crypto/err/err_all.c                             |   4 +
 crypto/err/openssl.ec                            |   1 +
 crypto/err/openssl.txt                           |  41 ++
 doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod             |  66 ++
 doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod | 106 ++++
 doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod  |  49 ++
 doc/man3/OSSL_CRMF_MSG_set_validity.pod          | 105 ++++
 doc/man3/OSSL_CRMF_pbmp_new.pod                  |  78 +++
 doc/man3/X509_dup.pod                            |  14 +
 include/openssl/crmf.h                           | 137 +++++
 include/openssl/crmferr.h                        |  69 +++
 include/openssl/err.h                            |   2 +
 util/libcrypto.num                               |  82 +++
 22 files changed, 2481 insertions(+), 1 deletion(-)
 create mode 100644 crypto/crmf/build.info
 create mode 100644 crypto/crmf/crmf_asn.c
 create mode 100644 crypto/crmf/crmf_err.c
 create mode 100644 crypto/crmf/crmf_int.h
 create mode 100644 crypto/crmf/crmf_lib.c
 create mode 100644 crypto/crmf/crmf_pbm.c
 create mode 100644 doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
 create mode 100644 doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
 create mode 100644 doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
 create mode 100644 doc/man3/OSSL_CRMF_MSG_set_validity.pod
 create mode 100644 doc/man3/OSSL_CRMF_pbmp_new.pod
 create mode 100644 include/openssl/crmf.h
 create mode 100644 include/openssl/crmferr.h

diff --git a/Configure b/Configure
index b2410a2..8818d58 100755
--- a/Configure
+++ b/Configure
@@ -349,6 +349,7 @@ my @disablables = (
     "cmac",
     "cms",
     "comp",
+    "crmf",
     "crypto-mdebug",
     "crypto-mdebug-backtrace",
     "ct",
diff --git a/crypto/build.info b/crypto/build.info
index 0cca6ab..a1ccad4 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
         md2 md4 md5 sha mdc2 gmac hmac ripemd whrlpool poly1305 blake2 \
         siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
         seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
-        err comp ocsp cms ts srp cmac ct async kmac ess
+        err comp ocsp cms ts srp cmac ct async kmac ess crmf
 
 LIBS=../libcrypto
 # The Core
diff --git a/crypto/crmf/build.info b/crypto/crmf/build.info
new file mode 100644
index 0000000..7cfa8ec
--- /dev/null
+++ b/crypto/crmf/build.info
@@ -0,0 +1,2 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=crmf_asn.c crmf_err.c crmf_lib.c crmf_pbm.c
diff --git a/crypto/crmf/crmf_asn.c b/crypto/crmf/crmf_asn.c
new file mode 100644
index 0000000..d0ab6e9
--- /dev/null
+++ b/crypto/crmf/crmf_asn.c
@@ -0,0 +1,240 @@
+/*-
+ * 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.
+ */
+
+#include <openssl/asn1t.h>
+
+#include "crmf_int.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/crmf.h>
+
+ASN1_SEQUENCE(OSSL_CRMF_PRIVATEKEYINFO) = {
+    ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, version, ASN1_INTEGER),
+    ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, privateKeyAlgorithm, X509_ALGOR),
+    ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, privateKey, ASN1_OCTET_STRING),
+    ASN1_IMP_SET_OF_OPT(OSSL_CRMF_PRIVATEKEYINFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PRIVATEKEYINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PRIVATEKEYINFO)
+
+
+ASN1_CHOICE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER) = {
+    ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.string, ASN1_UTF8STRING),
+    ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.generalName, GENERAL_NAME)
+} ASN1_CHOICE_END(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ENCKEYWITHID) = {
+    ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID, privateKey, OSSL_CRMF_PRIVATEKEYINFO),
+    ASN1_OPT(OSSL_CRMF_ENCKEYWITHID, identifier,
+             OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ENCKEYWITHID)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTID) = {
+    ASN1_SIMPLE(OSSL_CRMF_CERTID, issuer, GENERAL_NAME),
+    ASN1_SIMPLE(OSSL_CRMF_CERTID, serialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTID)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTID)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = {
+    ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, intendedAlg, X509_ALGOR, 0),
+    ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, symmAlg, X509_ALGOR, 1),
+    ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, encSymmKey, ASN1_BIT_STRING, 2),
+    ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, keyAlg, X509_ALGOR, 3),
+    ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, valueHint, ASN1_OCTET_STRING, 4),
+    ASN1_SIMPLE(OSSL_CRMF_ENCRYPTEDVALUE, encValue, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ENCRYPTEDVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
+
+ASN1_SEQUENCE(OSSL_CRMF_SINGLEPUBINFO) = {
+    ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER),
+    ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME)
+} ASN1_SEQUENCE_END(OSSL_CRMF_SINGLEPUBINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PKIPUBLICATIONINFO) = {
+    ASN1_SIMPLE(OSSL_CRMF_PKIPUBLICATIONINFO, action, ASN1_INTEGER),
+    ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_PKIPUBLICATIONINFO, pubInfos,
+                         OSSL_CRMF_SINGLEPUBINFO)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_PKIPUBLICATIONINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PKMACVALUE) = {
+    ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, algId, X509_ALGOR),
+    ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, value, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PKMACVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPOPRIVKEY) = {
+    ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.thisMessage, ASN1_BIT_STRING, 0),
+    ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.subsequentMessage, ASN1_INTEGER, 1),
+    ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.dhMAC, ASN1_BIT_STRING, 2),
+    ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.agreeMAC, OSSL_CRMF_PKMACVALUE, 3),
+    /*
+     * TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be somehow
+     * taken from crypto/cms which exists now - this is not used anywhere so far
+     */
+    ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.encryptedKey, ASN1_NULL, 4),
+} ASN1_CHOICE_END(OSSL_CRMF_POPOPRIVKEY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PBMPARAMETER) = {
+    ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, salt, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, owf, X509_ALGOR),
+    ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, iterationCount, ASN1_INTEGER),
+    ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, mac, X509_ALGOR)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PBMPARAMETER)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) = {
+    ASN1_EXP(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.sender,
+             GENERAL_NAME, 0),
+    ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.publicKeyMAC,
+                OSSL_CRMF_PKMACVALUE)
+} ASN1_CHOICE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEYINPUT) = {
+    ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT, authInfo,
+                OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO),
+    ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT, publicKey, X509_PUBKEY)
+} ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEY) = {
+    ASN1_IMP_OPT(OSSL_CRMF_POPOSIGNINGKEY, poposkInput,
+                 OSSL_CRMF_POPOSIGNINGKEYINPUT, 0),
+    ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEY, algorithmIdentifier, X509_ALGOR),
+    ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEY, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEY)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPO) = {
+    ASN1_IMP(OSSL_CRMF_POPO, value.raVerified, ASN1_NULL, 0),
+    ASN1_IMP(OSSL_CRMF_POPO, value.signature, OSSL_CRMF_POPOSIGNINGKEY, 1),
+    ASN1_EXP(OSSL_CRMF_POPO, value.keyEncipherment, OSSL_CRMF_POPOPRIVKEY, 2),
+    ASN1_EXP(OSSL_CRMF_POPO, value.keyAgreement, OSSL_CRMF_POPOPRIVKEY, 3)
+} ASN1_CHOICE_END(OSSL_CRMF_POPO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPO)
+
+
+ASN1_ADB_TEMPLATE(attributetypeandvalue_default) = ASN1_OPT(
+        OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY);
+ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
+    ADB_ENTRY(NID_id_regCtrl_regToken,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.regToken, ASN1_UTF8STRING)),
+    ADB_ENTRY(NID_id_regCtrl_authenticator,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.authenticator, ASN1_UTF8STRING)),
+    ADB_ENTRY(NID_id_regCtrl_pkiPublicationInfo,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.pkiPublicationInfo,
+                          OSSL_CRMF_PKIPUBLICATIONINFO)),
+    ADB_ENTRY(NID_id_regCtrl_oldCertID,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.oldCertID, OSSL_CRMF_CERTID)),
+    ADB_ENTRY(NID_id_regCtrl_protocolEncrKey,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.protocolEncrKey, X509_PUBKEY)),
+    ADB_ENTRY(NID_id_regInfo_utf8Pairs,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.utf8Pairs, ASN1_UTF8STRING)),
+    ADB_ENTRY(NID_id_regInfo_certReq,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.certReq, OSSL_CRMF_CERTREQUEST)),
+} ASN1_ADB_END(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, 0, type, 0,
+               &attributetypeandvalue_default_tt, NULL);
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
+    ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, type, ASN1_OBJECT),
+    ASN1_ADB_OBJECT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_OPTIONALVALIDITY) = {
+    ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notBefore, ASN1_TIME, 0),
+    ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notAfter,  ASN1_TIME, 1)
+} ASN1_SEQUENCE_END(OSSL_CRMF_OPTIONALVALIDITY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = {
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, version,      ASN1_INTEGER, 0),
+    /*
+     * serialNumber MUST be omitted. This field is assigned by the CA
+     * during certificate creation.
+     */
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, serialNumber, ASN1_INTEGER, 1),
+    /*
+     * signingAlg MUST be omitted. This field is assigned by the CA
+     * during certificate creation.
+     */
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, signingAlg,   X509_ALGOR, 2),
+    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, issuer,       X509_NAME, 3),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, validity,
+                 OSSL_CRMF_OPTIONALVALIDITY, 4),
+    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, subject,      X509_NAME, 5),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, publicKey,    X509_PUBKEY, 6),
+    /* issuerUID is deprecated in version 2 */
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, issuerUID,    ASN1_BIT_STRING, 7),
+    /* subjectUID is deprecated in version 2 */
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, subjectUID,   ASN1_BIT_STRING, 8),
+    ASN1_IMP_SEQUENCE_OF_OPT(OSSL_CRMF_CERTTEMPLATE, extensions,
+                             X509_EXTENSION, 9),
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTTEMPLATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTREQUEST) = {
+    ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certReqId, ASN1_INTEGER),
+    ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certTemplate, OSSL_CRMF_CERTTEMPLATE),
+    ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_CERTREQUEST, controls,
+                         OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_MSG) = {
+    ASN1_SIMPLE(OSSL_CRMF_MSG, certReq, OSSL_CRMF_CERTREQUEST),
+    ASN1_OPT(OSSL_CRMF_MSG, popo, OSSL_CRMF_POPO),
+    ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_MSG, regInfo,
+                         OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_MSG)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
+
+
+ASN1_ITEM_TEMPLATE(OSSL_CRMF_MSGS) =
+    ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+                          OSSL_CRMF_MSGS, OSSL_CRMF_MSG)
+    ASN1_ITEM_TEMPLATE_END(OSSL_CRMF_MSGS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
+
diff --git a/crypto/crmf/crmf_err.c b/crypto/crmf/crmf_err.c
new file mode 100644
index 0000000..f3405b1
--- /dev/null
+++ b/crypto/crmf/crmf_err.c
@@ -0,0 +1,104 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2019 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/crmferr.h>
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA CRMF_str_functs[] = {
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_CRMF_POPOSIGNINGKEY_INIT, 0),
+     "CRMF_poposigningkey_init"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_CERTID_GEN, 0),
+     "OSSL_CRMF_CERTID_gen"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL, 0),
+     "OSSL_CRMF_CERTTEMPLATE_fill"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT, 0),
+     "OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO, 0),
+     "OSSL_CRMF_MSGS_verify_popo"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_CREATE_POPO, 0),
+     "OSSL_CRMF_MSG_create_popo"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_GET0_TMPL, 0),
+     "OSSL_CRMF_MSG_get0_tmpl"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID, 0),
+     "OSSL_CRMF_MSG_get_certReqId"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO, 0),
+     "OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_PUSH0_EXTENSION, 0),
+     "OSSL_CRMF_MSG_push0_extension"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL, 0),
+     "OSSL_CRMF_MSG_push0_regCtrl"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO, 0),
+     "OSSL_CRMF_MSG_push0_regInfo"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_SET0_EXTENSIONS, 0),
+     "OSSL_CRMF_MSG_set0_extensions"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_SET0_SINGLEPUBINFO, 0),
+     "OSSL_CRMF_MSG_set0_SinglePubInfo"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_SET_CERTREQID, 0),
+     "OSSL_CRMF_MSG_set_certReqId"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_SET_PKIPUBLICATIONINFO_ACTION, 0),
+     "OSSL_CRMF_MSG_set_PKIPublicationInfo_action"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY, 0),
+     "OSSL_CRMF_MSG_set_validity"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_PBMP_NEW, 0),
+     "OSSL_CRMF_pbmp_new"},
+    {ERR_PACK(ERR_LIB_CRMF, CRMF_F_OSSL_CRMF_PBM_NEW, 0), "OSSL_CRMF_pbm_new"},
+    {0, NULL}
+};
+
+static const ERR_STRING_DATA CRMF_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_BAD_PBM_ITERATIONCOUNT),
+    "bad pbm iterationcount"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CRMFERROR), "crmferror"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR), "error"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_CERTIFICATE),
+    "error decoding certificate"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_CERTIFICATE),
+    "error decrypting certificate"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY),
+    "error decrypting symmetric key"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_FAILURE_OBTAINING_RANDOM),
+    "failure obtaining random"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ITERATIONCOUNT_BELOW_100),
+    "iterationcount below 100"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE),
+    "setting mac algor failure"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE),
+    "setting owf algor failure"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_ALGORITHM),
+    "unsupported algorithm"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY),
+    "unsupported alg for popsigningkey"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_CIPHER),
+    "unsupported cipher"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO),
+    "unsupported method for creating popo"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD),
+    "unsupported popo method"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED),
+    "unsupported popo not accepted"},
+    {0, NULL}
+};
+
+#endif
+
+int ERR_load_CRMF_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+    if (ERR_func_error_string(CRMF_str_functs[0].error) == NULL) {
+        ERR_load_strings_const(CRMF_str_functs);
+        ERR_load_strings_const(CRMF_str_reasons);
+    }
+#endif
+    return 1;
+}
diff --git a/crypto/crmf/crmf_int.h b/crypto/crmf/crmf_int.h
new file mode 100644
index 0000000..db1547b
--- /dev/null
+++ b/crypto/crmf/crmf_int.h
@@ -0,0 +1,394 @@
+/*-
+ * 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_INT_H
+# define OSSL_HEADER_CRMF_INT_H
+
+# include <openssl/crmf.h>
+# include <openssl/err.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/ossl_typ.h>
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+
+/*-
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
+ *                  -- the intended algorithm for which the value will be used
+ * symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
+ *                  -- the symmetric algorithm used to encrypt the value
+ * encSymmKey    [2] BIT STRING           OPTIONAL,
+ *                  -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
+ *                  -- algorithm used to encrypt the symmetric key
+ * valueHint     [4] OCTET STRING         OPTIONAL,
+ *                  -- a brief description or identifier of the encValue content
+ *                  -- (may be meaningful only to the sending entity, and
+ *                  --  used only if EncryptedValue might be re-examined
+ *                  --  by the sending entity in the future)
+ * encValue      BIT STRING
+ *                  -- the encrypted value itself
+ * }
+ */
+struct OSSL_crmf_encryptedvalue_st {
+    X509_ALGOR *intendedAlg;      /* 0 */
+    X509_ALGOR *symmAlg;          /* 1 */
+    ASN1_BIT_STRING *encSymmKey;  /* 2 */
+    X509_ALGOR *keyAlg;           /* 3 */
+    ASN1_OCTET_STRING *valueHint; /* 4 */
+    ASN1_BIT_STRING *encValue;
+} /* OSSL_CRMF_ENCRYPTEDVALUE */;
+
+/*-
+ *  Attributes ::= SET OF Attribute
+ *  => X509_ATTRIBUTE
+ *
+ *  PrivateKeyInfo ::= SEQUENCE {
+ *     version                       INTEGER,
+ *     privateKeyAlgorithm           AlgorithmIdentifier,
+ *     privateKey                    OCTET STRING,
+ *     attributes                    [0] IMPLICIT Attributes OPTIONAL
+ *  }
+ */
+typedef struct OSSL_crmf_privatekeyinfo_st {
+    ASN1_INTEGER *version;
+    X509_ALGOR *privateKeyAlgorithm;
+    ASN1_OCTET_STRING *privateKey;
+    STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+} OSSL_CRMF_PRIVATEKEYINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PRIVATEKEYINFO)
+
+/*-
+ * section 4.2.1 Private Key Info Content Type
+ * id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ *
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey     PrivateKeyInfo,
+ * identifier     CHOICE {
+ *                      string         UTF8String,
+ *                      generalName    GeneralName
+ *                } OPTIONAL
+ * }
+ */
+typedef struct OSSL_crmf_enckeywithid_identifier_st {
+    int type;
+    union {
+        ASN1_UTF8STRING *string;
+        GENERAL_NAME *generalName;
+    } value;
+} OSSL_CRMF_ENCKEYWITHID_IDENTIFIER;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+
+typedef struct OSSL_crmf_enckeywithid_st {
+    OSSL_CRMF_PRIVATEKEYINFO *privateKey;
+    /* [0] */
+    OSSL_CRMF_ENCKEYWITHID_IDENTIFIER *identifier;
+} OSSL_CRMF_ENCKEYWITHID;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID)
+
+/*-
+ * CertId ::= SEQUENCE {
+ *      issuer           GeneralName,
+ *      serialNumber     INTEGER
+ * }
+ */
+struct OSSL_crmf_certid_st {
+    GENERAL_NAME *issuer;
+    ASN1_INTEGER *serialNumber;
+} /* OSSL_CRMF_CERTID */;
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
+
+/*-
+ * SinglePubInfo ::= SEQUENCE {
+ *  pubMethod        INTEGER {
+ *      dontCare        (0),
+ *      x500            (1),
+ *      web             (2),
+ *      ldap            (3) },
+ *  pubLocation  GeneralName OPTIONAL
+ * }
+ */
+struct OSSL_crmf_singlepubinfo_st {
+    ASN1_INTEGER *pubMethod;
+    GENERAL_NAME *pubLocation;
+} /* OSSL_CRMF_SINGLEPUBINFO */;
+DEFINE_STACK_OF(OSSL_CRMF_SINGLEPUBINFO)
+typedef STACK_OF(OSSL_CRMF_SINGLEPUBINFO) OSSL_CRMF_PUBINFOS;
+
+
+/*-
+ * PKIPublicationInfo ::= SEQUENCE {
+ *      action     INTEGER {
+ *                   dontPublish (0),
+ *                   pleasePublish (1) },
+ *      pubInfos   SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL
+ *      -- pubInfos MUST NOT be present if action is "dontPublish"
+ *      -- (if action is "pleasePublish" and pubInfos is omitted,
+ *      -- "dontCare" is assumed)
+ * }
+ */
+struct OSSL_crmf_pkipublicationinfo_st {
+    ASN1_INTEGER *action;
+    OSSL_CRMF_PUBINFOS *pubInfos;
+} /* OSSL_CRMF_PKIPUBLICATIONINFO */;
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_PKIPUBLICATIONINFO)
+
+/*-
+ * PKMACValue ::= SEQUENCE {
+ * algId  AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac {1 2 840 113533 7 66 13}
+ * -- parameter value is PBMParameter
+ * value  BIT STRING
+ * }
+ */
+typedef struct OSSL_crmf_pkmacvalue_st {
+    X509_ALGOR *algId;
+    ASN1_BIT_STRING *value;
+} OSSL_CRMF_PKMACVALUE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE)
+
+/*-
+ * SubsequentMessage ::= INTEGER {
+ * encrCert (0),
+ * -- requests that resulting certificate be encrypted for the
+ * -- end entity (following which, POP will be proven in a
+ * -- confirmation message)
+ * challengeResp (1)
+ * -- requests that CA engage in challenge-response exchange with
+ * -- end entity in order to prove private key possession
+ * }
+ *
+ * POPOPrivKey ::= CHOICE {
+ * thisMessage       [0] BIT STRING,                 -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC             [2] BIT STRING,                 -- Deprecated
+ * agreeMAC          [3] PKMACValue,
+ * encryptedKey      [4] EnvelopedData
+ * }
+ */
+
+typedef struct OSSL_crmf_popoprivkey_st {
+    int type;
+    union {
+        ASN1_BIT_STRING *thisMessage; /* 0 */     /* Deprecated */
+        ASN1_INTEGER *subsequentMessage; /* 1 */
+        ASN1_BIT_STRING *dhMAC; /* 2 */           /* Deprecated */
+        OSSL_CRMF_PKMACVALUE *agreeMAC; /* 3 */
+        /*
+         * TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be
+         * somehow taken from crypto/cms which exists now
+         * - this is not used anywhere so far
+         */
+        ASN1_NULL *encryptedKey; /* 4 */
+    } value;
+} OSSL_CRMF_POPOPRIVKEY;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY)
+
+/*-
+ * PBMParameter ::= SEQUENCE {
+ *    salt                    OCTET STRING,
+ *    owf                     AlgorithmIdentifier,
+ *    -- AlgId for a One-Way Function (SHA-1 recommended)
+ *    iterationCount          INTEGER,
+ *    -- number of times the OWF is applied
+ *    mac                     AlgorithmIdentifier
+ *    -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ *    -- or HMAC [HMAC, RFC2202])
+ * }
+ */
+struct OSSL_crmf_pbmparameter_st {
+    ASN1_OCTET_STRING *salt;
+    X509_ALGOR *owf;
+    ASN1_INTEGER *iterationCount;
+    X509_ALGOR *mac;
+} /* OSSL_CRMF_PBMPARAMETER */;
+#define OSSL_CRMF_PBM_MAX_ITERATION_COUNT 100000 /* if too large allows DoS */
+
+/*-
+ * POPOSigningKeyInput ::= SEQUENCE {
+ * authInfo       CHOICE {
+ *     sender                 [0] GeneralName,
+ *   -- used only if an authenticated identity has been
+ *   -- established for the sender (e.g., a DN from a
+ *   -- previously-issued and currently-valid certificate)
+ *     publicKeyMAC           PKMACValue },
+ *   -- used if no authenticated GeneralName currently exists for
+ *   -- the sender; publicKeyMAC contains a password-based MAC
+ *   -- on the DER-encoded value of publicKey
+ * publicKey      SubjectPublicKeyInfo  -- from CertTemplate
+ * }
+*/
+typedef struct OSSL_crmf_poposigningkeyinput_authinfo_st {
+    int type;
+    union {
+        /* 0 */ GENERAL_NAME *sender;
+        /* 1 */ OSSL_CRMF_PKMACVALUE *publicKeyMAC;
+    } value;
+} OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+typedef struct OSSL_crmf_poposigningkeyinput_st {
+    OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO *authInfo;
+    X509_PUBKEY *publicKey;
+} OSSL_CRMF_POPOSIGNINGKEYINPUT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+
+/*-
+ * POPOSigningKey ::= SEQUENCE {
+ *  poposkInput           [0] POPOSigningKeyInput OPTIONAL,
+ *  algorithmIdentifier   AlgorithmIdentifier,
+ *  signature             BIT STRING
+ * }
+ */
+struct OSSL_crmf_poposigningkey_st {
+    OSSL_CRMF_POPOSIGNINGKEYINPUT *poposkInput;
+    X509_ALGOR *algorithmIdentifier;
+    ASN1_BIT_STRING *signature;
+} /* OSSL_CRMF_POPOSIGNINGKEY */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEY)
+
+/*-
+ * ProofOfPossession ::= CHOICE {
+ *  raVerified        [0] NULL,
+ *  -- used if the RA has already verified that the requester is in
+ *  -- possession of the private key
+ *  signature         [1] POPOSigningKey,
+ *  keyEncipherment   [2] POPOPrivKey,
+ *  keyAgreement      [3] POPOPrivKey
+ * }
+ */
+typedef struct OSSL_crmf_popo_st {
+    int type;
+    union {
+        ASN1_NULL *raVerified; /* 0 */
+        OSSL_CRMF_POPOSIGNINGKEY *signature; /* 1 */
+        OSSL_CRMF_POPOPRIVKEY *keyEncipherment; /* 2 */
+        OSSL_CRMF_POPOPRIVKEY *keyAgreement; /* 3 */
+    } value;
+} OSSL_CRMF_POPO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPO)
+
+/*-
+ * OptionalValidity ::= SEQUENCE {
+ *  notBefore      [0] Time OPTIONAL,
+ *  notAfter       [1] Time OPTIONAL  -- at least one MUST be present
+ * }
+ */
+struct OSSL_crmf_optionalvalidity_st {
+    /* 0 */ ASN1_TIME *notBefore;
+    /* 1 */ ASN1_TIME *notAfter;
+} /* OSSL_CRMF_OPTIONALVALIDITY */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
+
+/*-
+ * CertTemplate ::= SEQUENCE {
+ * version          [0] Version                   OPTIONAL,
+ * serialNumber     [1] INTEGER                   OPTIONAL,
+ * signingAlg       [2] AlgorithmIdentifier       OPTIONAL,
+ * issuer           [3] Name                      OPTIONAL,
+ * validity         [4] OptionalValidity          OPTIONAL,
+ * subject          [5] Name                      OPTIONAL,
+ * publicKey        [6] SubjectPublicKeyInfo      OPTIONAL,
+ * issuerUID        [7] UniqueIdentifier          OPTIONAL,
+ * subjectUID       [8] UniqueIdentifier          OPTIONAL,
+ * extensions       [9] Extensions                OPTIONAL
+ * }
+ */
+struct OSSL_crmf_certtemplate_st {
+    ASN1_INTEGER *version;           /* 0 */
+    ASN1_INTEGER *serialNumber;      /* 1 */ /* serialNumber MUST be omitted  */
+             /* This field is assigned by the CA during certificate creation  */
+    X509_ALGOR *signingAlg;          /* 2 */  /* signingAlg MUST be omitted   */
+             /* This field is assigned by the CA during certificate creation  */
+    X509_NAME *issuer;               /* 3 */
+    OSSL_CRMF_OPTIONALVALIDITY *validity; /* 4 */
+    X509_NAME *subject;              /* 5 */
+    X509_PUBKEY *publicKey;          /* 6 */
+    ASN1_BIT_STRING *issuerUID;      /* 7 */  /* deprecated in version 2      */
+                  /* According to rfc 3280: UniqueIdentifier  ::=  BIT STRING */
+    ASN1_BIT_STRING *subjectUID;     /* 8 */  /* deprecated in version 2      */
+                      /* Could be X509_EXTENSION*S*, but that's only cosmetic */
+    STACK_OF(X509_EXTENSION) *extensions; /* 9 */
+} /* OSSL_CRMF_CERTTEMPLATE */;
+
+/*-
+ * CertRequest ::= SEQUENCE {
+ *  certReqId        INTEGER,          -- ID for matching request and reply
+ *  certTemplate     CertTemplate,     -- Selected fields of cert to be issued
+ *  controls         Controls OPTIONAL -- Attributes affecting issuance
+ * }
+ */
+struct OSSL_crmf_certrequest_st {
+    ASN1_INTEGER *certReqId;
+    OSSL_CRMF_CERTTEMPLATE *certTemplate;
+    /* TODO: make OSSL_CRMF_CONTROLS out of that - but only cosmetical */
+    STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls;
+} /* OSSL_CRMF_CERTREQUEST */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
+
+/* TODO: isn't there a better way to have this for ANY type? */
+struct OSSL_crmf_attributetypeandvalue_st {
+    ASN1_OBJECT *type;
+    union {
+        /* NID_id_regCtrl_regToken */
+        ASN1_UTF8STRING *regToken;
+
+        /* NID_id_regCtrl_authenticator */
+        ASN1_UTF8STRING *authenticator;
+
+        /* NID_id_regCtrl_pkiPublicationInfo */
+        OSSL_CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo;
+
+        /* NID_id_regCtrl_oldCertID */
+        OSSL_CRMF_CERTID *oldCertID;
+
+        /* NID_id_regCtrl_protocolEncrKey */
+        X509_PUBKEY *protocolEncrKey;
+
+        /* NID_id_regInfo_utf8Pairs */
+        ASN1_UTF8STRING *utf8Pairs;
+
+        /* NID_id_regInfo_certReq */
+        OSSL_CRMF_CERTREQUEST *certReq;
+
+        ASN1_TYPE *other;
+    } value;
+} /* OSSL_CRMF_ATTRIBUTETYPEANDVALUE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+DEFINE_STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+/*-
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ * CertReqMsg ::= SEQUENCE {
+ *  certReq        CertRequest,
+ *  popo           ProofOfPossession  OPTIONAL,
+ * -- content depends upon key type
+ *  regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL
+ * }
+ */
+struct OSSL_crmf_msg_st {
+    OSSL_CRMF_CERTREQUEST *certReq;
+    /* 0 */
+    OSSL_CRMF_POPO *popo;
+    /* 1 */
+    STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *regInfo;
+} /* OSSL_CRMF_MSG */;
+/* DEFINE_STACK_OF(OSSL_CRMF_MSG) */
+#endif
diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c
new file mode 100644
index 0000000..49deca7
--- /dev/null
+++ b/crypto/crmf/crmf_lib.c
@@ -0,0 +1,753 @@
+/*-
+ * 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.
+ */
+
+/*
+ * This file contains the functions that handle the individual items inside
+ * the CRMF structures
+ */
+
+/*
+ * NAMING
+ *
+ * The 0 functions use the supplied structure pointer directly in the parent and
+ * it will be freed up when the parent is freed.
+ *
+ * The 1 functions use a copy of the supplied structure pointer (or in some
+ * cases increases its link count) in the parent and so both should be freed up.
+ */
+
+#include <openssl/asn1t.h>
+
+#include "crmf_int.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+/*-
+ * atyp = Attribute Type
+ * valt = Value Type
+ * ctrlinf = "regCtrl" or "regInfo"
+ */
+#define IMPLEMENT_CRMF_CTRL_FUNC(atyp, valt, ctrlinf)                     \
+int OSSL_CRMF_MSG_set1_##ctrlinf##_##atyp(OSSL_CRMF_MSG *msg,             \
+                                          const valt *in)                 \
+{                                                                         \
+    OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL;                         \
+                                                                          \
+    if (msg == NULL || in  == NULL)                                       \
+        goto err;                                                         \
+    if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL)           \
+        goto err;                                                         \
+    if ((atav->type = OBJ_nid2obj(NID_id_##ctrlinf##_##atyp)) == NULL)    \
+        goto err;                                                         \
+    if ((atav->value.atyp = valt##_dup(in)) == NULL)                      \
+        goto err;                                                         \
+    if (!OSSL_CRMF_MSG_push0_##ctrlinf(msg, atav))                        \
+        goto err;                                                         \
+    return 1;                                                             \
+ err:                                                                     \
+    OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(atav);                           \
+    return 0;                                                             \
+}
+
+
+/*-
+ * Pushes the given control attribute into the controls stack of a CertRequest
+ * (section 6)
+ * returns 1 on success, 0 on error
+ */
+static int OSSL_CRMF_MSG_push0_regCtrl(OSSL_CRMF_MSG *crm,
+                                       OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ctrl)
+{
+    int new = 0;
+
+    if (crm == NULL || crm->certReq == NULL || ctrl == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (crm->certReq->controls == NULL) {
+        crm->certReq->controls = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
+        if (crm->certReq->controls == NULL)
+            goto oom;
+        new = 1;
+    }
+    if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->certReq->controls, ctrl))
+        goto oom;
+
+    return 1;
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL, ERR_R_MALLOC_FAILURE);
+
+    if (new != 0) {
+        sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(crm->certReq->controls);
+        crm->certReq->controls = NULL;
+    }
+    return 0;
+}
+
+ /* id-regCtrl-regToken Control (section 6.1) */
+IMPLEMENT_CRMF_CTRL_FUNC(regToken, ASN1_STRING, regCtrl)
+
+ /* id-regCtrl-authenticator Control (section 6.2) */
+#define ASN1_UTF8STRING_dup ASN1_STRING_dup
+IMPLEMENT_CRMF_CTRL_FUNC(authenticator, ASN1_UTF8STRING, regCtrl)
+
+int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+                                     int method, GENERAL_NAME *nm)
+{
+    if (spi == NULL
+            || method < OSSL_CRMF_PUB_METHOD_DONTCARE
+            || method > OSSL_CRMF_PUB_METHOD_LDAP) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET0_SINGLEPUBINFO,
+                ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+
+    if (!ASN1_INTEGER_set(spi->pubMethod, method))
+        return 0;
+    GENERAL_NAME_free(spi->pubLocation);
+    spi->pubLocation = nm;
+    return 1;
+}
+
+int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
+                                 OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                 OSSL_CRMF_SINGLEPUBINFO *spi)
+{
+    if (pi == NULL || spi == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO,
+                CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+    if (pi->pubInfos == NULL)
+        pi->pubInfos = sk_OSSL_CRMF_SINGLEPUBINFO_new_null();
+    if (pi->pubInfos == NULL)
+        goto oom;
+
+    if (!sk_OSSL_CRMF_SINGLEPUBINFO_push(pi->pubInfos, spi))
+        goto oom;
+    return 1;
+
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO,
+            ERR_R_MALLOC_FAILURE);
+    return 0;
+}
+
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
+                                 OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action)
+{
+    if (pi == NULL
+            || action < OSSL_CRMF_PUB_ACTION_DONTPUBLISH
+            || action > OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET_PKIPUBLICATIONINFO_ACTION,
+                ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+
+    return ASN1_INTEGER_set(pi->action, action);
+}
+
+ /* id-regCtrl-pkiPublicationInfo Control (section 6.3) */
+IMPLEMENT_CRMF_CTRL_FUNC(pkiPublicationInfo, OSSL_CRMF_PKIPUBLICATIONINFO,
+                         regCtrl)
+
+ /* id-regCtrl-oldCertID Control (section 6.5) from the given */
+IMPLEMENT_CRMF_CTRL_FUNC(oldCertID, OSSL_CRMF_CERTID, regCtrl)
+
+OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+                                       const ASN1_INTEGER *serial)
+{
+    OSSL_CRMF_CERTID *cid = NULL;
+
+    if (issuer == NULL || serial == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_CERTID_GEN, CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+
+    if ((cid = OSSL_CRMF_CERTID_new()) == NULL)
+        goto oom;
+
+    if (!X509_NAME_set(&cid->issuer->d.directoryName, issuer))
+        goto oom;
+    cid->issuer->type = GEN_DIRNAME;
+
+    ASN1_INTEGER_free(cid->serialNumber);
+    if ((cid->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+        goto oom;
+
+    return cid;
+
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_CERTID_GEN, ERR_R_MALLOC_FAILURE);
+    OSSL_CRMF_CERTID_free(cid);
+    return NULL;
+}
+
+ /*
+  * id-regCtrl-protocolEncrKey Control (section 6.6)
+  *
+  * For some reason X509_PUBKEY_dup() is not implemented in OpenSSL X509
+  * TODO: check whether that should go elsewhere
+  */
+static IMPLEMENT_ASN1_DUP_FUNCTION(X509_PUBKEY)
+IMPLEMENT_CRMF_CTRL_FUNC(protocolEncrKey, X509_PUBKEY, regCtrl)
+
+/*-
+ * Pushes the attribute given in regInfo in to the CertReqMsg->regInfo stack.
+ * (section 7)
+ * returns 1 on success, 0 on error
+ */
+static int OSSL_CRMF_MSG_push0_regInfo(OSSL_CRMF_MSG *crm,
+                                       OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ri)
+{
+    STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *info = NULL;
+
+    if (crm == NULL || ri == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (crm->regInfo == NULL)
+        crm->regInfo = info = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
+    if (crm->regInfo == NULL)
+        goto oom;
+    if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->regInfo, ri))
+        goto oom;
+    return 1;
+
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO, ERR_R_MALLOC_FAILURE);
+    if (info != NULL)
+        crm->regInfo = NULL;
+    sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(info);
+    return 0;
+}
+
+/* id-regInfo-utf8Pairs to regInfo (section 7.1) */
+IMPLEMENT_CRMF_CTRL_FUNC(utf8Pairs, ASN1_UTF8STRING, regInfo)
+
+/* id-regInfo-certReq to regInfo (section 7.2) */
+IMPLEMENT_CRMF_CTRL_FUNC(certReq, OSSL_CRMF_CERTREQUEST, regInfo)
+
+
+/* retrieves the certificate template of crm */
+OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm)
+{
+    if (crm == NULL || crm->certReq == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_GET0_TMPL, CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    return crm->certReq->certTemplate;
+}
+
+
+int OSSL_CRMF_MSG_set_validity(OSSL_CRMF_MSG *crm, time_t from, time_t to)
+{
+    OSSL_CRMF_OPTIONALVALIDITY *vld = NULL;
+    ASN1_TIME *from_asn = NULL;
+    ASN1_TIME *to_asn = NULL;
+    OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+    if (tmpl == NULL) { /* also crm == NULL implies this */
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (from != 0 && ((from_asn = ASN1_TIME_set(NULL, from)) == NULL))
+        goto oom;
+    if (to != 0 && ((to_asn = ASN1_TIME_set(NULL, to)) == NULL))
+        goto oom;
+    if ((vld = OSSL_CRMF_OPTIONALVALIDITY_new()) == NULL)
+        goto oom;
+
+    vld->notBefore = from_asn;
+    vld->notAfter = to_asn;
+
+    tmpl->validity = vld;
+
+    return 1;
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY, ERR_R_MALLOC_FAILURE);
+    ASN1_TIME_free(from_asn);
+    ASN1_TIME_free(to_asn);
+    return 0;
+}
+
+
+int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid)
+{
+    if (crm == NULL || crm->certReq == NULL || crm->certReq->certReqId == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET_CERTREQID, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    return ASN1_INTEGER_set(crm->certReq->certReqId, rid);
+}
+
+/* get ASN.1 encoded integer, return -1 on error */
+static int crmf_asn1_get_int(int func, const ASN1_INTEGER *a)
+{
+    int64_t res;
+
+    if (!ASN1_INTEGER_get_int64(&res, a)) {
+        CRMFerr(func, ASN1_R_INVALID_NUMBER);
+        return -1;
+    }
+    if (res < INT_MIN) {
+        CRMFerr(func, ASN1_R_TOO_SMALL);
+        return -1;
+    }
+    if (res > INT_MAX) {
+        CRMFerr(func, ASN1_R_TOO_LARGE);
+        return -1;
+    }
+    return (int)res;
+}
+
+int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm)
+{
+    if (crm == NULL || /* not really needed: */ crm->certReq == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID, CRMF_R_NULL_ARGUMENT);
+        return -1;
+    }
+    return crmf_asn1_get_int(CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID,
+                             crm->certReq->certReqId);
+}
+
+
+int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm,
+                                  X509_EXTENSIONS *exts)
+{
+    OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+    if (tmpl == NULL) { /* also crm == NULL implies this */
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_SET0_EXTENSIONS, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (sk_X509_EXTENSION_num(exts) == 0) {
+        sk_X509_EXTENSION_free(exts);
+        exts = NULL; /* do not include empty extensions list */
+    }
+
+    sk_X509_EXTENSION_pop_free(tmpl->extensions, X509_EXTENSION_free);
+    tmpl->extensions = exts;
+    return 1;
+}
+
+
+int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm,
+                                  const X509_EXTENSION *ext)
+{
+    int new = 0;
+    OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+    if (tmpl == NULL || ext == NULL) { /* also crm == NULL implies this */
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_EXTENSION, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (tmpl->extensions == NULL) {
+        if ((tmpl->extensions = sk_X509_EXTENSION_new_null()) == NULL)
+            goto oom;
+        new = 1;
+    }
+
+    if (!sk_X509_EXTENSION_push(tmpl->extensions, (X509_EXTENSION *)ext))
+        goto oom;
+    return 1;
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_PUSH0_EXTENSION, ERR_R_MALLOC_FAILURE);
+
+    if (new != 0) {
+        sk_X509_EXTENSION_free(tmpl->extensions);
+        tmpl->extensions = NULL;
+    }
+    return 0;
+}
+
+/* TODO: support cases 1+2 (besides case 3) defined in RFC 4211, section 4.1. */
+static int CRMF_poposigningkey_init(OSSL_CRMF_POPOSIGNINGKEY *ps,
+                                    OSSL_CRMF_CERTREQUEST *cr,
+                                    EVP_PKEY *pkey, int dgst)
+{
+    int len;
+    size_t crlen;
+    size_t siglen;
+    unsigned char *crder = NULL, *sig = NULL;
+    int alg_nid = 0;
+    int md_nid = 0;
+    const EVP_MD *alg = NULL;
+    EVP_MD_CTX *ctx = NULL;
+    int ret = 0;
+
+    if (ps == NULL || cr == NULL || pkey == NULL) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    /* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */
+    ps->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+    ps->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+    len = i2d_OSSL_CRMF_CERTREQUEST(cr, &crder);
+    if (len < 0 || crder == NULL) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
+        goto err;
+    }
+    crlen = (size_t)len;
+
+    if (!OBJ_find_sigid_by_algs(&alg_nid, dgst, EVP_PKEY_id(pkey))) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT,
+                CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY);
+        goto err;
+    }
+    if (!OBJ_find_sigid_algs(alg_nid, &md_nid, NULL)
+            || (alg = EVP_get_digestbynid(md_nid)) == NULL) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT,
+                CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY);
+        goto err;
+    }
+    if (!X509_ALGOR_set0(ps->algorithmIdentifier, OBJ_nid2obj(alg_nid),
+                         V_ASN1_NULL, NULL)
+            || (ctx = EVP_MD_CTX_new()) == NULL
+            || EVP_DigestSignInit(ctx, NULL, alg, NULL, pkey) <= 0
+            || EVP_DigestSignUpdate(ctx, crder, crlen) <= 0
+            || EVP_DigestSignFinal(ctx, NULL, &siglen) <= 0) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
+        goto err;
+    }
+    if ((sig = OPENSSL_malloc(siglen)) == NULL) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (EVP_DigestSignFinal(ctx, sig, &siglen) <= 0
+            || !ASN1_BIT_STRING_set(ps->signature, sig, siglen)) {
+        CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
+        goto err;
+    }
+    ret = 1;
+
+ err:
+    OPENSSL_free(crder);
+    EVP_MD_CTX_free(ctx);
+    OPENSSL_free(sig);
+    return ret;
+}
+
+
+int OSSL_CRMF_MSG_create_popo(OSSL_CRMF_MSG *crm, EVP_PKEY *pkey,
+                              int dgst, int ppmtd)
+{
+    OSSL_CRMF_POPO *pp = NULL;
+    ASN1_INTEGER *tag = NULL;
+
+    if (crm == NULL || (ppmtd == OSSL_CRMF_POPO_SIGNATURE && pkey == NULL)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_CREATE_POPO, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (ppmtd == OSSL_CRMF_POPO_NONE)
+        goto end;
+    if ((pp = OSSL_CRMF_POPO_new()) == NULL)
+        goto oom;
+    pp->type = ppmtd;
+
+    switch (ppmtd) {
+    case OSSL_CRMF_POPO_RAVERIFIED:
+        if ((pp->value.raVerified = ASN1_NULL_new()) == NULL)
+            goto oom;
+        break;
+
+    case OSSL_CRMF_POPO_SIGNATURE:
+        {
+            OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
+            if (ps == NULL
+                    || !CRMF_poposigningkey_init(ps, crm->certReq, pkey, dgst)){
+                OSSL_CRMF_POPOSIGNINGKEY_free(ps);
+                goto err;
+            }
+            pp->value.signature = ps;
+        }
+        break;
+
+    case OSSL_CRMF_POPO_KEYENC:
+        if ((pp->value.keyEncipherment = OSSL_CRMF_POPOPRIVKEY_new()) == NULL)
+            goto oom;
+        tag = ASN1_INTEGER_new();
+        pp->value.keyEncipherment->type =
+            OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE;
+        pp->value.keyEncipherment->value.subsequentMessage = tag;
+        if (tag == NULL
+                || !ASN1_INTEGER_set(tag, OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT))
+            goto oom;
+        break;
+
+    default:
+        CRMFerr(CRMF_F_OSSL_CRMF_MSG_CREATE_POPO,
+                CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
+        goto err;
+    }
+
+ end:
+    OSSL_CRMF_POPO_free(crm->popo);
+    crm->popo = pp;
+
+    return 1;
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_MSG_CREATE_POPO, ERR_R_MALLOC_FAILURE);
+ err:
+    OSSL_CRMF_POPO_free(pp);
+    return 0;
+}
+
+/* returns 0 for equal, -1 for a < b or error on a, 1 for a > b or error on b */
+static int X509_PUBKEY_cmp(X509_PUBKEY *a, X509_PUBKEY *b)
+{
+    X509_ALGOR *algA = NULL, *algB = NULL;
+    int res = 0;
+
+    if (a == b)
+        return 0;
+    if (a == NULL || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algA, a)
+            || algA == NULL)
+        return -1;
+    if (b == NULL || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algB, b)
+            || algB == NULL)
+        return 1;
+    if ((res = X509_ALGOR_cmp(algA, algB)) != 0)
+        return res;
+    return EVP_PKEY_cmp(X509_PUBKEY_get0(a), X509_PUBKEY_get0(b));
+}
+
+/* verifies the Proof-of-Possession of the request with the given rid in reqs */
+int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+                               int rid, int acceptRAVerified)
+{
+    OSSL_CRMF_MSG *req = NULL;
+    X509_PUBKEY *pubkey = NULL;
+    OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
+
+    if (reqs == NULL
+            || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL
+            || req->popo == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO,
+                CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    switch (req->popo->type) {
+    case OSSL_CRMF_POPO_RAVERIFIED:
+        if (acceptRAVerified)
+            return 1;
+        break;
+    case OSSL_CRMF_POPO_SIGNATURE:
+        pubkey = req->certReq->certTemplate->publicKey;
+        sig = req->popo->value.signature;
+        if (sig->poposkInput != NULL) {
+            /*
+             * According to RFC 4211: publicKey contains a copy of
+             * the public key from the certificate template. This MUST be
+             * exactly the same value as contained in the certificate template.
+             */
+            if (pubkey == NULL
+                    || sig->poposkInput->publicKey == NULL
+                    || X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey)
+                    || ASN1_item_verify(
+                           ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT),
+                           sig->algorithmIdentifier, sig->signature,
+                           sig->poposkInput, X509_PUBKEY_get0(pubkey)) < 1)
+                break;
+        } else {
+            if (pubkey == NULL
+                    || req->certReq->certTemplate->subject == NULL
+                    || ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
+                                    sig->algorithmIdentifier, sig->signature,
+                                    req->certReq,
+                                    X509_PUBKEY_get0(pubkey)) < 1)
+                break;
+        }
+        return 1;
+    case OSSL_CRMF_POPO_KEYENC:
+        /*
+         * TODO: when OSSL_CMP_certrep_new() supports encrypted certs,
+         * return 1 if the type of req->popo->value.keyEncipherment
+         * is OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE and
+         * its value.subsequentMessage == OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT
+        */
+    case OSSL_CRMF_POPO_KEYAGREE:
+    default:
+        CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO,
+                CRMF_R_UNSUPPORTED_POPO_METHOD);
+        return 0;
+    }
+    CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO,
+            CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED);
+    return 0;
+}
+
+/* retrieves the serialNumber of the given cert template or NULL on error */
+ASN1_INTEGER *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+    return tmpl != NULL ? tmpl->serialNumber : NULL;
+}
+
+/* retrieves the issuer name of the given cert template or NULL on error */
+X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+    return tmpl != NULL ? tmpl->issuer : NULL;
+}
+
+/*
+ * fill in certificate template.
+ * Any value argument that is NULL will leave the respective field unchanged.
+ */
+int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+                                EVP_PKEY *pubkey,
+                                const X509_NAME *subject,
+                                const X509_NAME *issuer,
+                                const ASN1_INTEGER *serial)
+{
+    if (tmpl == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL, CRMF_R_NULL_ARGUMENT);
+        return 0;
+    }
+    if (subject != NULL && !X509_NAME_set(&tmpl->subject, subject))
+        goto oom;
+    if (issuer != NULL && !X509_NAME_set(&tmpl->issuer, issuer))
+        goto oom;
+    if (serial != NULL) {
+        ASN1_INTEGER_free(tmpl->serialNumber);
+        if ((tmpl->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+            goto oom;
+    }
+    if (pubkey != NULL && !X509_PUBKEY_set(&tmpl->publicKey, pubkey))
+        goto oom;
+    return 1;
+
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL, ERR_R_MALLOC_FAILURE);
+    return 0;
+}
+
+
+/*-
+ * Decrypts the certificate in the given encryptedValue
+ * this is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2
+ *
+ * returns a pointer to the decrypted certificate
+ * returns NULL on error or if no certificate available
+ */
+X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+                                            EVP_PKEY *pkey)
+{
+    X509 *cert = NULL; /* decrypted certificate */
+    EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */
+    unsigned char *ek = NULL; /* decrypted symmetric encryption key */
+    const EVP_CIPHER *cipher = NULL; /* used cipher */
+    unsigned char *iv = NULL; /* initial vector for symmetric encryption */
+    unsigned char *outbuf = NULL; /* decryption output buffer */
+    const unsigned char *p = NULL; /* needed for decoding ASN1 */
+    int symmAlg = 0; /* NIDs for symmetric algorithm */
+    int n, outlen = 0;
+    EVP_PKEY_CTX *pkctx = NULL; /* private key context */
+
+    if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
+            || ecert->encValue == NULL || pkey == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    if ((symmAlg = OBJ_obj2nid(ecert->symmAlg->algorithm)) == 0) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_UNSUPPORTED_CIPHER);
+        return NULL;
+    }
+
+    /* first the symmetric key needs to be decrypted */
+    pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+    if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx)) {
+        ASN1_BIT_STRING *encKey = ecert->encSymmKey;
+        size_t eksize = 0;
+
+        if (EVP_PKEY_decrypt(pkctx, NULL, &eksize, encKey->data, encKey->length)
+                <= 0
+                || (ek = OPENSSL_malloc(eksize)) == NULL
+                || EVP_PKEY_decrypt(pkctx, ek, &eksize, encKey->data,
+                                    encKey->length) <= 0) {
+            CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                    CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
+            goto end;
+        }
+    } else {
+        goto oom;
+    }
+
+    /* select symmetric cipher based on algorithm given in message */
+    if ((cipher = EVP_get_cipherbynid(symmAlg)) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_UNSUPPORTED_CIPHER);
+        goto end;
+    }
+    if ((iv = OPENSSL_malloc(EVP_CIPHER_iv_length(cipher))) == NULL)
+        goto oom;
+    if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
+                                   EVP_CIPHER_iv_length(cipher))
+        != EVP_CIPHER_iv_length(cipher)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_MALFORMED_IV);
+        goto end;
+    }
+
+    /*
+     * d2i_X509 changes the given pointer, so use p for decoding the message and
+     * keep the original pointer in outbuf so the memory can be freed later
+     */
+    if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length +
+                                     EVP_CIPHER_block_size(cipher))) == NULL
+            || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
+        goto oom;
+    EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
+
+    if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
+            || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen,
+                                  ecert->encValue->data,
+                                  ecert->encValue->length)
+            || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
+        goto end;
+    }
+    outlen += n;
+
+    /* convert decrypted certificate from DER to internal ASN.1 structure */
+    if ((cert = d2i_X509(NULL, &p, outlen)) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT,
+                CRMF_R_ERROR_DECODING_CERTIFICATE);
+    }
+    goto end;
+
+ oom:
+    CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT, ERR_R_MALLOC_FAILURE);
+ end:
+    EVP_PKEY_CTX_free(pkctx);
+    OPENSSL_free(outbuf);
+    EVP_CIPHER_CTX_free(evp_ctx);
+    OPENSSL_free(ek);
+    OPENSSL_free(iv);
+    return cert;
+}
diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c
new file mode 100644
index 0000000..60d06d4
--- /dev/null
+++ b/crypto/crmf/crmf_pbm.c
@@ -0,0 +1,231 @@
+/*-
+ * 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.
+ */
+
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+
+#include "crmf_int.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+/*-
+ * creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4)
+ * |slen| SHOULD be > 8    (16 is common)
+ * |owfnid| e.g., NID_sha256
+ * |itercnt| MUST be > 100 (500 is common)
+ * |macnid| e.g., NID_hmac_sha1
+ * returns pointer to OSSL_CRMF_PBMPARAMETER on success, NULL on error
+ */
+OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid,
+                                           int itercnt, int macnid)
+{
+    OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+    unsigned char *salt = NULL;
+
+    if ((pbm = OSSL_CRMF_PBMPARAMETER_new()) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    /*
+     * salt contains a randomly generated value used in computing the key
+     * of the MAC process.  The salt SHOULD be at least 8 octets (64
+     * bits) long.
+     */
+    if ((salt = OPENSSL_malloc(slen)) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (RAND_bytes(salt, (int)slen) <= 0) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, CRMF_R_FAILURE_OBTAINING_RANDOM);
+        goto err;
+    }
+    if (!ASN1_OCTET_STRING_set(pbm->salt, salt, (int)slen))
+        goto err;
+
+    /*
+     * owf identifies the hash algorithm and associated parameters used to
+     * compute the key used in the MAC process.  All implementations MUST
+     * support SHA-1.
+     */
+    if (!X509_ALGOR_set0(pbm->owf, OBJ_nid2obj(owfnid), V_ASN1_UNDEF, NULL)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, CRMF_R_SETTING_OWF_ALGOR_FAILURE);
+        goto err;
+    }
+
+    /*
+     * iterationCount identifies the number of times the hash is applied
+     * during the key computation process.  The iterationCount MUST be a
+     * minimum of 100.      Many people suggest using values as high as 1000
+     * iterations as the minimum value.  The trade off here is between
+     * protection of the password from attacks and the time spent by the
+     * server processing all of the different iterations in deriving
+     * passwords.  Hashing is generally considered a cheap operation but
+     * this may not be true with all hash functions in the future.
+     */
+    if (itercnt < 100) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, CRMF_R_ITERATIONCOUNT_BELOW_100);
+        goto err;
+    }
+
+    if (!ASN1_INTEGER_set(pbm->iterationCount, itercnt)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, CRMF_R_CRMFERROR);
+        goto err;
+    }
+
+    /*
+     * mac identifies the algorithm and associated parameters of the MAC
+     * function to be used.  All implementations MUST support HMAC-SHA1 [HMAC].
+     * All implementations SHOULD support DES-MAC and Triple-DES-MAC [PKCS11].
+     */
+    if (!X509_ALGOR_set0(pbm->mac, OBJ_nid2obj(macnid), V_ASN1_UNDEF, NULL)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBMP_NEW, CRMF_R_SETTING_MAC_ALGOR_FAILURE);
+        goto err;
+    }
+
+    OPENSSL_free(salt);
+    return pbm;
+ err:
+    OPENSSL_free(salt);
+    OSSL_CRMF_PBMPARAMETER_free(pbm);
+    return NULL;
+}
+
+/*-
+ * calculates the PBM based on the settings of the given OSSL_CRMF_PBMPARAMETER
+ * |pbmp| identifies the algorithms, salt to use
+ * |msg| message to apply the PBM for
+ * |msglen| length of the message
+ * |sec| key to use
+ * |seclen| length of the key
+ * |mac| pointer to the computed mac, will be set on success
+ * |maclen| if not NULL, will set variable to the length of the mac on success
+ * returns 1 on success, 0 on error
+ */
+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, size_t *maclen)
+{
+    int mac_nid, hmac_md_nid = NID_undef;
+    const EVP_MD *m = NULL;
+    EVP_MD_CTX *ctx = NULL;
+    unsigned char basekey[EVP_MAX_MD_SIZE];
+    unsigned int bklen = EVP_MAX_MD_SIZE;
+    int64_t iterations;
+    unsigned char *mac_res = 0;
+    int ok = 0;
+    EVP_MAC_CTX *mctx = NULL;
+
+    if (mac == NULL || pbmp == NULL || pbmp->mac == NULL
+            || pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_NULL_ARGUMENT);
+        goto err;
+    }
+    if ((mac_res = OPENSSL_malloc(EVP_MAX_MD_SIZE)) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    /*
+     * owf identifies the hash algorithm and associated parameters used to
+     * compute the key used in the MAC process.  All implementations MUST
+     * support SHA-1.
+     */
+    if ((m = EVP_get_digestbyobj(pbmp->owf->algorithm)) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_UNSUPPORTED_ALGORITHM);
+        goto err;
+    }
+
+    if ((ctx = EVP_MD_CTX_new()) == NULL) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    /* compute the basekey of the salted secret */
+    if (!EVP_DigestInit_ex(ctx, m, NULL))
+        goto err;
+    /* first the secret */
+    if (!EVP_DigestUpdate(ctx, sec, seclen))
+        goto err;
+    /* then the salt */
+    if (!EVP_DigestUpdate(ctx, pbmp->salt->data, pbmp->salt->length))
+        goto err;
+    if (!EVP_DigestFinal_ex(ctx, basekey, &bklen))
+        goto err;
+    if (!ASN1_INTEGER_get_int64(&iterations, pbmp->iterationCount)
+            || iterations < 100 /* min from RFC */
+            || iterations > OSSL_CRMF_PBM_MAX_ITERATION_COUNT) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_BAD_PBM_ITERATIONCOUNT);
+        goto err;
+    }
+
+    /* the first iteration was already done above */
+    while (--iterations > 0) {
+        if (!EVP_DigestInit_ex(ctx, m, NULL))
+            goto err;
+        if (!EVP_DigestUpdate(ctx, basekey, bklen))
+            goto err;
+        if (!EVP_DigestFinal_ex(ctx, basekey, &bklen))
+            goto err;
+    }
+
+    /*
+     * mac identifies the algorithm and associated parameters of the MAC
+     * function to be used.  All implementations MUST support HMAC-SHA1 [HMAC].
+     * All implementations SHOULD support DES-MAC and Triple-DES-MAC [PKCS11].
+     */
+    mac_nid = OBJ_obj2nid(pbmp->mac->algorithm);
+
+    if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL)
+            || ((m = EVP_get_digestbynid(hmac_md_nid)) == NULL)) {
+        CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_UNSUPPORTED_ALGORITHM);
+        goto err;
+    }
+
+    if ((mctx = EVP_MAC_CTX_new(EVP_get_macbyname("HMAC"))) == NULL
+            || EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_MD, m) <= 0
+            || EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_KEY, basekey, bklen) <= 0
+            || !EVP_MAC_init(mctx)
+            || !EVP_MAC_update(mctx, msg, msglen)
+            || !EVP_MAC_final(mctx, mac_res, maclen))
+        goto err;
+
+    ok = 1;
+
+ err:
+    /* cleanup */
+    OPENSSL_cleanse(basekey, bklen);
+    EVP_MAC_CTX_free(mctx);
+    EVP_MD_CTX_free(ctx);
+
+    if (ok == 1) {
+        *mac = mac_res;
+        return 1;
+    }
+
+    OPENSSL_free(mac_res);
+
+    if (pbmp != NULL && pbmp->mac != NULL) {
+        char buf[128];
+
+        if (OBJ_obj2txt(buf, sizeof(buf), pbmp->mac->algorithm, 0))
+            ERR_add_error_data(1, buf);
+    }
+    return 0;
+}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 3aa3dae..63dcfc3 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -58,6 +58,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
     {ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"},
     {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
     {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, 0), "CRMF routines"},
     {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
     {ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
     {ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
index 4bf020c..1166b01 100644
--- a/crypto/err/err_all.c
+++ b/crypto/err/err_all.c
@@ -34,6 +34,7 @@
 #include <openssl/err.h>
 #include <openssl/tserr.h>
 #include <openssl/cmserr.h>
+#include <openssl/crmferr.h>
 #include <openssl/cterr.h>
 #include <openssl/asyncerr.h>
 #include <openssl/kdferr.h>
@@ -90,6 +91,9 @@ int err_load_crypto_strings_int(void)
 # ifndef OPENSSL_NO_CMS
         ERR_load_CMS_strings() == 0 ||
 # endif
+# ifndef OPENSSL_NO_CMP
+        ERR_load_CRMF_strings() == 0 ||
+# endif
 # ifndef OPENSSL_NO_CT
         ERR_load_CT_strings() == 0 ||
 # endif
diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec
index 901a847..a204434 100644
--- a/crypto/err/openssl.ec
+++ b/crypto/err/openssl.ec
@@ -29,6 +29,7 @@ L UI            include/openssl/ui.h            crypto/ui/ui_err.c
 L COMP          include/openssl/comp.h          crypto/comp/comp_err.c
 L TS            include/openssl/ts.h            crypto/ts/ts_err.c
 L CMS           include/openssl/cms.h           crypto/cms/cms_err.c
+L CRMF          include/openssl/crmf.h          crypto/crmf/crmf_err.c
 L CT            include/openssl/ct.h            crypto/ct/ct_err.c
 L ASYNC         include/openssl/async.h         crypto/async/async_err.c
 L KDF           include/openssl/kdf.h           crypto/kdf/kdf_err.c
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 8ae11ca..cb58f42 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -348,6 +348,28 @@ CONF_F_NCONF_NEW:111:NCONF_new
 CONF_F_PROCESS_INCLUDE:116:process_include
 CONF_F_SSL_MODULE_INIT:123:ssl_module_init
 CONF_F_STR_COPY:101:str_copy
+CRMF_F_CRMF_POPOSIGNINGKEY_INIT:100:CRMF_poposigningkey_init
+CRMF_F_OSSL_CRMF_CERTID_GEN:101:OSSL_CRMF_CERTID_gen
+CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL:102:OSSL_CRMF_CERTTEMPLATE_fill
+CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT:103:\
+	OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert
+CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO:104:OSSL_CRMF_MSGS_verify_popo
+CRMF_F_OSSL_CRMF_MSG_CREATE_POPO:105:OSSL_CRMF_MSG_create_popo
+CRMF_F_OSSL_CRMF_MSG_GET0_TMPL:106:OSSL_CRMF_MSG_get0_tmpl
+CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID:107:OSSL_CRMF_MSG_get_certReqId
+CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO:108:\
+	OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo
+CRMF_F_OSSL_CRMF_MSG_PUSH0_EXTENSION:109:OSSL_CRMF_MSG_push0_extension
+CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL:110:OSSL_CRMF_MSG_push0_regCtrl
+CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO:111:OSSL_CRMF_MSG_push0_regInfo
+CRMF_F_OSSL_CRMF_MSG_SET0_EXTENSIONS:112:OSSL_CRMF_MSG_set0_extensions
+CRMF_F_OSSL_CRMF_MSG_SET0_SINGLEPUBINFO:113:OSSL_CRMF_MSG_set0_SinglePubInfo
+CRMF_F_OSSL_CRMF_MSG_SET_CERTREQID:114:OSSL_CRMF_MSG_set_certReqId
+CRMF_F_OSSL_CRMF_MSG_SET_PKIPUBLICATIONINFO_ACTION:115:\
+	OSSL_CRMF_MSG_set_PKIPublicationInfo_action
+CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY:116:OSSL_CRMF_MSG_set_validity
+CRMF_F_OSSL_CRMF_PBMP_NEW:117:OSSL_CRMF_pbmp_new
+CRMF_F_OSSL_CRMF_PBM_NEW:118:OSSL_CRMF_pbm_new
 CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
 CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
 CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
@@ -2103,6 +2125,25 @@ CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section
 CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
 CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
 CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value
+CRMF_R_BAD_PBM_ITERATIONCOUNT:100:bad pbm iterationcount
+CRMF_R_MALFORMED_IV:101:malformed iv
+CRMF_R_CRMFERROR:102:crmferror
+CRMF_R_ERROR:103:error
+CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate
+CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate
+CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key
+CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
+CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
+CRMF_R_NULL_ARGUMENT:109:null argument
+CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
+CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
+CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm
+CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY:113:unsupported alg for popsigningkey
+CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher
+CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\
+	unsupported method for creating popo
+CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method
+CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted
 CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported
 CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit
 CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits
diff --git a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
new file mode 100644
index 0000000..fbce702
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
@@ -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
index 0000000..851bd13
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
@@ -0,0 +1,106 @@
+=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 in the given SinglePubInfo B<spi>
+the B<method> and publication location, in the form of a GeneralName, B<nm>.
+The publication location is optional, and therefore B<nm> may be NULL.
+The function consumes the B<nm> pointer if present.
+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 pkiPublicationInfo
+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
index 0000000..9e33a4a
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
@@ -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
index 0000000..b6ea32e
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set_validity.pod
@@ -0,0 +1,105 @@
+=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, int rid);
+
+ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+                                 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, 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>.
+On success the reference counter of the B<pubkey> (if given) is incremented,
+while the B<subject>, B<issuer>, and B<serial> structures (if given) are copied.
+
+OSSL_CRMF_MSG_set0_extensions() sets B<exts> as the extensions in the
+certTemplate of B<crm>. Frees any pre-existing ones and 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
index 0000000..a83209b
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_pbmp_new.pod
@@ -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, size_t *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>. On success writes the adddress of the newly
+allocated MAC via the B<mac> reference parameter and writes the length via the
+B<maclen> reference parameter unless it its 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 a new 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 algorithms for the OWF (one-way function) and for the MAC (message
+authentication code) may be any with a NID defined in B<openssl/objects.h>.
+As specified by RFC 4210, these should include NID_hmac_sha1.
+
+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";
+ unsigned char *sec = "SeCrEt";
+ unsigned char *mac = NULL;
+ size_t 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
diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
index 8ad7648..2f51e45 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -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
index 0000000..b4221a9
--- /dev/null
+++ b/include/openssl/crmf.h
@@ -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 (RFC 4211) implementation by M. Peylo, M. Viljanen, and D. von Oheimb.
+ */
+
+#ifndef OSSL_HEADER_CRMF_H
+# define OSSL_HEADER_CRMF_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CMP
+#  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_encryptedvalue_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, size_t *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, 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,
+                                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_CMP */
+#endif /* !defined OSSL_HEADER_CRMF_H */
diff --git a/include/openssl/crmferr.h b/include/openssl/crmferr.h
new file mode 100644
index 0000000..06f90fb
--- /dev/null
+++ b/include/openssl/crmferr.h
@@ -0,0 +1,69 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2019 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_CRMFERR_H
+# define HEADER_CRMFERR_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CMP
+
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+int ERR_load_CRMF_strings(void);
+
+/*
+ * CRMF function codes.
+ */
+#  define CRMF_F_CRMF_POPOSIGNINGKEY_INIT                  100
+#  define CRMF_F_OSSL_CRMF_CERTID_GEN                      101
+#  define CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL               102
+#  define CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT     103
+#  define CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO                104
+#  define CRMF_F_OSSL_CRMF_MSG_CREATE_POPO                 105
+#  define CRMF_F_OSSL_CRMF_MSG_GET0_TMPL                   106
+#  define CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID               107
+#  define CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO 108
+#  define CRMF_F_OSSL_CRMF_MSG_PUSH0_EXTENSION             109
+#  define CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL               110
+#  define CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO               111
+#  define CRMF_F_OSSL_CRMF_MSG_SET0_EXTENSIONS             112
+#  define CRMF_F_OSSL_CRMF_MSG_SET0_SINGLEPUBINFO          113
+#  define CRMF_F_OSSL_CRMF_MSG_SET_CERTREQID               114
+#  define CRMF_F_OSSL_CRMF_MSG_SET_PKIPUBLICATIONINFO_ACTION 115
+#  define CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY                116
+#  define CRMF_F_OSSL_CRMF_PBMP_NEW                        117
+#  define CRMF_F_OSSL_CRMF_PBM_NEW                         118
+
+/*
+ * CRMF reason codes.
+ */
+#  define CRMF_R_BAD_PBM_ITERATIONCOUNT                    100
+#  define CRMF_R_MALFORMED_IV                              101
+#  define CRMF_R_CRMFERROR                                 102
+#  define CRMF_R_ERROR                                     103
+#  define CRMF_R_ERROR_DECODING_CERTIFICATE                104
+#  define CRMF_R_ERROR_DECRYPTING_CERTIFICATE              105
+#  define CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY            106
+#  define CRMF_R_FAILURE_OBTAINING_RANDOM                  107
+#  define CRMF_R_ITERATIONCOUNT_BELOW_100                  108
+#  define CRMF_R_NULL_ARGUMENT                             109
+#  define CRMF_R_SETTING_MAC_ALGOR_FAILURE                 110
+#  define CRMF_R_SETTING_OWF_ALGOR_FAILURE                 111
+#  define CRMF_R_UNSUPPORTED_ALGORITHM                     112
+#  define CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY         113
+#  define CRMF_R_UNSUPPORTED_CIPHER                        114
+#  define CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO      115
+#  define CRMF_R_UNSUPPORTED_POPO_METHOD                   116
+#  define CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED             117
+
+# endif
+#endif
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 0d6956c..fded82c 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -96,6 +96,7 @@ typedef struct err_state_st {
 # define ERR_LIB_SM2             53
 # define ERR_LIB_ESS             54
 # define ERR_LIB_PROP            55
+# define ERR_LIB_CRMF            56
 
 # define ERR_LIB_USER            128
 
@@ -129,6 +130,7 @@ typedef struct err_state_st {
 # define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
+# define CRMFerr(f,r) ERR_PUT_error(ERR_LIB_CRMF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 4243593..974d918 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4660,3 +4660,85 @@ OSSL_PROVIDER_unload                    4615	3_0_0	EXIST::FUNCTION:
 OSSL_PROVIDER_add_builtin               4616	3_0_0	EXIST::FUNCTION:
 OSSL_PROVIDER_get_param_types           4617	3_0_0	EXIST::FUNCTION:
 OSSL_PROVIDER_get_params                4618	3_0_0	EXIST::FUNCTION:
+d2i_OSSL_CRMF_ENCRYPTEDVALUE            4619	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_ENCRYPTEDVALUE            4620	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_free           4621	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_new            4622	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_it             4623	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_it             4624	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_it             4624	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_MSG                       4625	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_MSG                       4626	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_free                      4627	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_new                       4628	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_it                        4629	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_MSG_it                        4630	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_MSG_it                        4630	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_PBMPARAMETER              4631	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_PBMPARAMETER              4632	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PBMPARAMETER_free             4633	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PBMPARAMETER_new              4634	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PBMPARAMETER_it               4635	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_PBMPARAMETER_it               4636	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_PBMPARAMETER_it               4636	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_CERTID                    4637	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_CERTID                    4638	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTID_free                   4639	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTID_new                    4640	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTID_it                     4641	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_CERTID_it                     4642	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_CERTID_it                     4642	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_PKIPUBLICATIONINFO        4643	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_PKIPUBLICATIONINFO        4644	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PKIPUBLICATIONINFO_free       4645	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PKIPUBLICATIONINFO_new        4646	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_PKIPUBLICATIONINFO_it         4647	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_PKIPUBLICATIONINFO_it         4648	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_PKIPUBLICATIONINFO_it         4648	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_SINGLEPUBINFO             4649	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_SINGLEPUBINFO             4650	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_SINGLEPUBINFO_free            4651	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_SINGLEPUBINFO_new             4652	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_SINGLEPUBINFO_it              4653	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_SINGLEPUBINFO_it              4654	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_SINGLEPUBINFO_it              4654	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_CERTTEMPLATE              4655	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_CERTTEMPLATE              4656	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_free             4657	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_new              4658	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_it               4659	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_CERTTEMPLATE_it               4660	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_CERTTEMPLATE_it               4660	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+d2i_OSSL_CRMF_MSGS                      4661	3_0_0	EXIST::FUNCTION:CMP
+i2d_OSSL_CRMF_MSGS                      4662	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSGS_free                     4663	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSGS_new                      4664	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSGS_it                       4665	3_0_0	NOEXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_MSGS_it                       4666	3_0_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMP
+OSSL_CRMF_MSGS_it                       4666	3_0_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMP
+OSSL_CRMF_pbmp_new                      4667	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_pbm_new                       4668	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regCtrl_regToken     4669	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regCtrl_authenticator 4670	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo 4671	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set0_SinglePubInfo        4672	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set_PKIPublicationInfo_action 4673	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo 4674	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey 4675	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regCtrl_oldCertID    4676	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTID_gen                    4677	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regInfo_utf8Pairs    4678	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set1_regInfo_certReq      4679	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set_validity              4680	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set_certReqId             4681	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_get_certReqId             4682	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_set0_extensions           4683	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_push0_extension           4684	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_create_popo               4685	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSGS_verify_popo              4686	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_MSG_get0_tmpl                 4687	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_get0_serialNumber 4688	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_get0_issuer      4689	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_CERTTEMPLATE_fill             4690	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert   4691	3_0_0	EXIST::FUNCTION:CMP
+ERR_load_CRMF_strings                   4692	3_0_0	EXIST::FUNCTION:CMP


More information about the openssl-commits mailing list