aboutsummaryrefslogtreecommitdiff
path: root/crypto/crmf
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/crmf')
-rw-r--r--crypto/crmf/build.info2
-rw-r--r--crypto/crmf/crmf_asn.c235
-rw-r--r--crypto/crmf/crmf_err.c74
-rw-r--r--crypto/crmf/crmf_lib.c715
-rw-r--r--crypto/crmf/crmf_local.h385
-rw-r--r--crypto/crmf/crmf_pbm.c233
6 files changed, 1644 insertions, 0 deletions
diff --git a/crypto/crmf/build.info b/crypto/crmf/build.info
new file mode 100644
index 000000000000..7cfa8ec2b076
--- /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 000000000000..3354b89736e9
--- /dev/null
+++ b/crypto/crmf/crmf_asn.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+#include <openssl/asn1t.h>
+
+#include "crmf_local.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),
+ 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)
+IMPLEMENT_ASN1_DUP_FUNCTION(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 000000000000..44b2f2757d2c
--- /dev/null
+++ b/crypto/crmf/crmf_err.c
@@ -0,0 +1,74 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/crmferr.h>
+#include "crypto/crmferr.h"
+
+#ifndef OPENSSL_NO_CRMF
+
+# ifndef OPENSSL_NO_ERR
+
+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_POPOSKINPUT_NOT_SUPPORTED),
+ "poposkinput not supported"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY),
+ "popo inconsistent public key"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY),
+ "popo missing public key"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT),
+ "popo missing subject"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED),
+ "popo raverified not accepted"},
+ {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_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"},
+ {0, NULL}
+};
+
+# endif
+
+int ossl_err_load_CRMF_strings(void)
+{
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(CRMF_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(CRMF_str_reasons);
+# endif
+ return 1;
+}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c
new file mode 100644
index 000000000000..3607fb0bf417
--- /dev/null
+++ b/crypto/crmf/crmf_lib.c
@@ -0,0 +1,715 @@
+/*-
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2018
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * 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_local.h"
+#include "internal/constant_time.h"
+#include "internal/sizes.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) \
+valt *OSSL_CRMF_MSG_get0_##ctrlinf##_##atyp(const OSSL_CRMF_MSG *msg) \
+{ \
+ int i; \
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls; \
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL; \
+ \
+ if (msg == NULL || msg->certReq == NULL) \
+ return NULL; \
+ controls = msg->certReq->controls; \
+ for (i = 0; i < sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_num(controls); i++) { \
+ atav = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_value(controls, i); \
+ if (OBJ_obj2nid(atav->type) == NID_id_##ctrlinf##_##atyp) \
+ return atav->value.atyp; \
+ } \
+ return NULL; \
+} \
+ \
+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) {
+ ERR_raise(ERR_LIB_CRMF, 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 err;
+ new = 1;
+ }
+ if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->certReq->controls, ctrl))
+ goto err;
+
+ return 1;
+ err:
+ 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) {
+ ERR_raise(ERR_LIB_CRMF, 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (pi->pubInfos == NULL)
+ pi->pubInfos = sk_OSSL_CRMF_SINGLEPUBINFO_new_null();
+ if (pi->pubInfos == NULL)
+ return 0;
+
+ return sk_OSSL_CRMF_SINGLEPUBINFO_push(pi->pubInfos, spi);
+}
+
+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) {
+ ERR_raise(ERR_LIB_CRMF, 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if ((cid = OSSL_CRMF_CERTID_new()) == NULL)
+ goto err;
+
+ if (!X509_NAME_set(&cid->issuer->d.directoryName, issuer))
+ goto err;
+ cid->issuer->type = GEN_DIRNAME;
+
+ ASN1_INTEGER_free(cid->serialNumber);
+ if ((cid->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+ goto err;
+
+ return cid;
+
+ err:
+ OSSL_CRMF_CERTID_free(cid);
+ return NULL;
+}
+
+/*
+ * id-regCtrl-protocolEncrKey Control (section 6.6)
+ */
+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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (crm->regInfo == NULL)
+ crm->regInfo = info = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
+ if (crm->regInfo == NULL)
+ goto err;
+ if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->regInfo, ri))
+ goto err;
+ return 1;
+
+ err:
+ 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return crm->certReq->certTemplate;
+}
+
+
+int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
+ ASN1_TIME *notBefore, ASN1_TIME *notAfter)
+{
+ OSSL_CRMF_OPTIONALVALIDITY *vld;
+ OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+ if (tmpl == NULL) { /* also crm == NULL implies this */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if ((vld = OSSL_CRMF_OPTIONALVALIDITY_new()) == NULL)
+ return 0;
+ vld->notBefore = notBefore;
+ vld->notAfter = notAfter;
+ tmpl->validity = vld;
+ return 1;
+}
+
+
+int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid)
+{
+ if (crm == NULL || crm->certReq == NULL || crm->certReq->certReqId == NULL) {
+ ERR_raise(ERR_LIB_CRMF, 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(const ASN1_INTEGER *a)
+{
+ int64_t res;
+
+ if (!ASN1_INTEGER_get_int64(&res, a)) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_INVALID_NUMBER);
+ return -1;
+ }
+ if (res < INT_MIN) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_SMALL);
+ return -1;
+ }
+ if (res > INT_MAX) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_LARGE);
+ return -1;
+ }
+ return (int)res;
+}
+
+int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm)
+{
+ if (crm == NULL || /* not really needed: */ crm->certReq == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return -1;
+ }
+ return crmf_asn1_get_int(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 */
+ ERR_raise(ERR_LIB_CRMF, 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,
+ 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 */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (tmpl->extensions == NULL) {
+ if ((tmpl->extensions = sk_X509_EXTENSION_new_null()) == NULL)
+ goto err;
+ new = 1;
+ }
+
+ if (!sk_X509_EXTENSION_push(tmpl->extensions, ext))
+ goto err;
+ return 1;
+ err:
+ if (new != 0) {
+ sk_X509_EXTENSION_free(tmpl->extensions);
+ tmpl->extensions = NULL;
+ }
+ return 0;
+}
+
+static int create_popo_signature(OSSL_CRMF_POPOSIGNINGKEY *ps,
+ const OSSL_CRMF_CERTREQUEST *cr,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ char name[80] = "";
+
+ if (ps == NULL || cr == NULL || pkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ps->poposkInput != NULL) {
+ /* We do not support cases 1+2 defined in RFC 4211, section 4.1 */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED);
+ return 0;
+ }
+
+ if (EVP_PKEY_get_default_digest_name(pkey, name, sizeof(name)) > 0
+ && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */
+ digest = NULL;
+
+ return ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
+ ps->algorithmIdentifier, NULL, ps->signature, cr,
+ NULL, pkey, digest, libctx, propq);
+}
+
+
+int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CRMF_POPO *pp = NULL;
+ ASN1_INTEGER *tag = NULL;
+
+ if (crm == NULL || (meth == OSSL_CRMF_POPO_SIGNATURE && pkey == NULL)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (meth == OSSL_CRMF_POPO_NONE)
+ goto end;
+ if ((pp = OSSL_CRMF_POPO_new()) == NULL)
+ goto err;
+ pp->type = meth;
+
+ switch (meth) {
+ case OSSL_CRMF_POPO_RAVERIFIED:
+ if ((pp->value.raVerified = ASN1_NULL_new()) == NULL)
+ goto err;
+ break;
+
+ case OSSL_CRMF_POPO_SIGNATURE:
+ {
+ OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
+
+ if (ps == NULL)
+ goto err;
+ if (!create_popo_signature(ps, crm->certReq, pkey, digest,
+ libctx, propq)) {
+ 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 err;
+ 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 err;
+ break;
+
+ default:
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
+ goto err;
+ }
+
+ end:
+ OSSL_CRMF_POPO_free(crm->popo);
+ crm->popo = pp;
+
+ return 1;
+ err:
+ OSSL_CRMF_POPO_free(pp);
+ return 0;
+}
+
+/* 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_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CRMF_MSG *req = NULL;
+ X509_PUBKEY *pubkey = NULL;
+ OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
+ const ASN1_ITEM *it;
+ void *asn;
+
+ if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (req->popo == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING);
+ return 0;
+ }
+
+ switch (req->popo->type) {
+ case OSSL_CRMF_POPO_RAVERIFIED:
+ if (!acceptRAVerified) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED);
+ return 0;
+ }
+ break;
+ case OSSL_CRMF_POPO_SIGNATURE:
+ pubkey = req->certReq->certTemplate->publicKey;
+ if (pubkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+ return 0;
+ }
+ 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 (sig->poposkInput->publicKey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+ return 0;
+ }
+ if (X509_PUBKEY_eq(pubkey, sig->poposkInput->publicKey) != 1) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY);
+ return 0;
+ }
+ it = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
+ asn = sig->poposkInput;
+ } else {
+ if (req->certReq->certTemplate->subject == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT);
+ return 0;
+ }
+ it = ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST);
+ asn = req->certReq;
+ }
+ if (ASN1_item_verify_ex(it, sig->algorithmIdentifier, sig->signature,
+ asn, NULL, X509_PUBKEY_get0(pubkey), libctx,
+ propq) < 1)
+ return 0;
+ break;
+ case OSSL_CRMF_POPO_KEYENC:
+ case OSSL_CRMF_POPO_KEYAGREE:
+ default:
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD);
+ return 0;
+ }
+ return 1;
+}
+
+/* retrieves the serialNumber of the given cert template or NULL on error */
+const ASN1_INTEGER
+*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->serialNumber : NULL;
+}
+
+const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->subject : NULL;
+}
+
+/* retrieves the issuer name of the given cert template or NULL on error */
+const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->issuer : NULL;
+}
+
+X509_EXTENSIONS
+ *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->extensions : NULL;
+}
+
+/* retrieves the issuer name of the given CertId or NULL on error */
+const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
+{
+ return cid != NULL && cid->issuer->type == GEN_DIRNAME ?
+ cid->issuer->d.directoryName : NULL;
+}
+
+/* retrieves the serialNumber of the given CertId or NULL on error */
+const ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid)
+{
+ return cid != NULL ? cid->serialNumber : 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject))
+ return 0;
+ if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer))
+ return 0;
+ if (serial != NULL) {
+ ASN1_INTEGER_free(tmpl->serialNumber);
+ if ((tmpl->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+ return 0;
+ }
+ if (pubkey != NULL && !X509_PUBKEY_set(&tmpl->publicKey, pubkey))
+ return 0;
+ return 1;
+}
+
+
+/*-
+ * Decrypts the certificate in the given encryptedValue using private key pkey.
+ * 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(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ 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 */
+ size_t eksize = 0; /* size of decrypted symmetric encryption key */
+ EVP_CIPHER *cipher = NULL; /* used cipher */
+ int cikeysize = 0; /* key size from 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 n, outlen = 0;
+ EVP_PKEY_CTX *pkctx = NULL; /* private key context */
+ char name[OSSL_MAX_NAME_SIZE];
+
+ if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
+ || ecert->encValue == NULL || pkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ /* select symmetric cipher based on algorithm given in message */
+ OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ cipher = EVP_CIPHER_fetch(NULL, name, NULL);
+
+ if (cipher == NULL)
+ cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
+
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER);
+ goto end;
+ }
+ (void)ERR_pop_to_mark();
+
+ cikeysize = EVP_CIPHER_get_key_length(cipher);
+ /* first the symmetric key needs to be decrypted */
+ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
+ if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx) > 0) {
+ ASN1_BIT_STRING *encKey = ecert->encSymmKey;
+ size_t failure;
+ int retval;
+
+ if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
+ encKey->data, encKey->length) <= 0
+ || (ek = OPENSSL_malloc(eksize)) == NULL)
+ goto end;
+ retval = EVP_PKEY_decrypt(pkctx, ek, &eksize,
+ encKey->data, encKey->length);
+ ERR_clear_error(); /* error state may have sensitive information */
+ failure = ~constant_time_is_zero_s(constant_time_msb(retval)
+ | constant_time_is_zero(retval));
+ failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize);
+ if (failure) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
+ goto end;
+ }
+ } else {
+ goto end;
+ }
+ if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
+ goto end;
+ if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
+ EVP_CIPHER_get_iv_length(cipher))
+ != EVP_CIPHER_get_iv_length(cipher)) {
+ ERR_raise(ERR_LIB_CRMF, 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_get_block_size(cipher))) == NULL
+ || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto end;
+ 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)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
+ goto end;
+ }
+ outlen += n;
+
+ /* convert decrypted certificate from DER to internal ASN.1 structure */
+ if ((cert = X509_new_ex(libctx, propq)) == NULL)
+ goto end;
+ if (d2i_X509(&cert, &p, outlen) == NULL)
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
+ end:
+ EVP_PKEY_CTX_free(pkctx);
+ OPENSSL_free(outbuf);
+ EVP_CIPHER_CTX_free(evp_ctx);
+ EVP_CIPHER_free(cipher);
+ OPENSSL_clear_free(ek, eksize);
+ OPENSSL_free(iv);
+ return cert;
+}
diff --git a/crypto/crmf/crmf_local.h b/crypto/crmf/crmf_local.h
new file mode 100644
index 000000000000..3b8c3701b54d
--- /dev/null
+++ b/crypto/crmf/crmf_local.h
@@ -0,0 +1,385 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+#ifndef OSSL_CRYPTO_CRMF_LOCAL_H
+# define OSSL_CRYPTO_CRMF_LOCAL_H
+
+# include <openssl/crmf.h>
+# include <openssl/err.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/types.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 */;
+
+/*-
+ * 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 */
+ 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;
+ ASN1_INTEGER *serialNumber; /* serialNumber MUST be omitted */
+ /* This field is assigned by the CA during certificate creation */
+ X509_ALGOR *signingAlg; /* signingAlg MUST be omitted */
+ /* This field is assigned by the CA during certificate creation */
+ const X509_NAME *issuer;
+ OSSL_CRMF_OPTIONALVALIDITY *validity;
+ const X509_NAME *subject;
+ X509_PUBKEY *publicKey;
+ ASN1_BIT_STRING *issuerUID; /* deprecated in version 2 */
+ /* According to rfc 3280: UniqueIdentifier ::= BIT STRING */
+ ASN1_BIT_STRING *subjectUID; /* deprecated in version 2 */
+ /* Could be X509_EXTENSION*S*, but that's only cosmetic */
+ STACK_OF(X509_EXTENSION) *extensions;
+} /* 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;
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls;
+} /* OSSL_CRMF_CERTREQUEST */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
+
+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 */;
+#endif
diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c
new file mode 100644
index 000000000000..88a8480cf73a
--- /dev/null
+++ b/crypto/crmf/crmf_pbm.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+
+#include <string.h>
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.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>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+
+#include "internal/sizes.h"
+
+#include "crmf_local.h"
+
+/*-
+ * creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4)
+ * |slen| SHOULD be at least 8 (16 is common)
+ * |owfnid| e.g., NID_sha256
+ * |itercnt| MUST be >= 100 (e.g., 500) and <= OSSL_CRMF_PBM_MAX_ITERATION_COUNT
+ * |macnid| e.g., NID_hmac_sha1
+ * returns pointer to OSSL_CRMF_PBMPARAMETER on success, NULL on error
+ */
+OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t slen,
+ int owfnid, size_t itercnt,
+ int macnid)
+{
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ unsigned char *salt = NULL;
+
+ if ((pbm = OSSL_CRMF_PBMPARAMETER_new()) == NULL)
+ 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)
+ goto err;
+ if (RAND_bytes_ex(libctx, salt, slen, 0) <= 0) {
+ ERR_raise(ERR_LIB_CRMF, 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)) {
+ ERR_raise(ERR_LIB_CRMF, 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ITERATIONCOUNT_BELOW_100);
+ goto err;
+ }
+ if (itercnt > OSSL_CRMF_PBM_MAX_ITERATION_COUNT) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT);
+ goto err;
+ }
+
+ if (!ASN1_INTEGER_set(pbm->iterationCount, itercnt)) {
+ ERR_raise(ERR_LIB_CRMF, 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)) {
+ ERR_raise(ERR_LIB_CRMF, 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
+ * |out| pointer to the computed mac, will be set on success
+ * |outlen| 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(OSSL_LIB_CTX *libctx, const char *propq,
+ const OSSL_CRMF_PBMPARAMETER *pbmp,
+ const unsigned char *msg, size_t msglen,
+ const unsigned char *sec, size_t seclen,
+ unsigned char **out, size_t *outlen)
+{
+ int mac_nid, hmac_md_nid = NID_undef;
+ char mdname[OSSL_MAX_NAME_SIZE];
+ char hmac_mdname[OSSL_MAX_NAME_SIZE];
+ EVP_MD *owf = 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;
+
+ if (out == NULL || pbmp == NULL || pbmp->mac == NULL
+ || pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ goto err;
+ }
+ if ((mac_res = OPENSSL_malloc(EVP_MAX_MD_SIZE)) == NULL)
+ 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.
+ */
+ OBJ_obj2txt(mdname, sizeof(mdname), pbmp->owf->algorithm, 0);
+ if ((owf = EVP_MD_fetch(libctx, mdname, propq)) == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL)
+ goto err;
+
+ /* compute the basekey of the salted secret */
+ if (!EVP_DigestInit_ex(ctx, owf, 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) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT);
+ goto err;
+ }
+
+ /* the first iteration was already done above */
+ while (--iterations > 0) {
+ if (!EVP_DigestInit_ex(ctx, owf, 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)
+ || OBJ_obj2txt(hmac_mdname, sizeof(hmac_mdname),
+ OBJ_nid2obj(hmac_md_nid), 0) <= 0) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+ if (EVP_Q_mac(libctx, "HMAC", propq, hmac_mdname, NULL, basekey, bklen,
+ msg, msglen, mac_res, EVP_MAX_MD_SIZE, outlen) == NULL)
+ goto err;
+
+ ok = 1;
+
+ err:
+ OPENSSL_cleanse(basekey, bklen);
+ EVP_MD_free(owf);
+ EVP_MD_CTX_free(ctx);
+
+ if (ok == 1) {
+ *out = 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;
+}