diff --git a/0124-PBMAC1-PKCS12-FIPS-support.patch b/0124-PBMAC1-PKCS12-FIPS-support.patch
new file mode 100644
index 0000000..b8d4403
--- /dev/null
+++ b/0124-PBMAC1-PKCS12-FIPS-support.patch
@@ -0,0 +1,1463 @@
+From d959252c47af0eb0dd55bc032606901fedaf029b Mon Sep 17 00:00:00 2001
+From: Dmitry Belyavskiy <beldmit@gmail.com>
+Date: Fri, 7 Jun 2024 14:37:57 +0200
+Subject: [PATCH 1/4] Implementation of the RFC 9579, PBMAC1 in PKCS#12
+
+---
+ apps/pkcs12.c               |  63 ++++++--
+ crypto/asn1/p5_pbev2.c      |   7 +
+ crypto/evp/digest.c         |  54 +++++++
+ crypto/pkcs12/p12_mutl.c    | 296 ++++++++++++++++++++++++++++++++----
+ include/crypto/evp.h        |   3 +
+ include/openssl/pkcs12.h.in |   3 +
+ include/openssl/x509.h.in   |  15 +-
+ 7 files changed, 394 insertions(+), 47 deletions(-)
+
+diff --git a/apps/pkcs12.c b/apps/pkcs12.c
+index 54323a9713393..cbe133742a8be 100644
+--- a/apps/pkcs12.c
++++ b/apps/pkcs12.c
+@@ -70,7 +70,7 @@ typedef enum OPTION_choice {
+     OPT_NAME, OPT_CSP, OPT_CANAME,
+     OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
+     OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
+-    OPT_R_ENUM, OPT_PROV_ENUM, OPT_JDKTRUST,
++    OPT_R_ENUM, OPT_PROV_ENUM, OPT_JDKTRUST, OPT_PBMAC1_PBKDF2, OPT_PBMAC1_PBKDF2_MD,
+ #ifndef OPENSSL_NO_DES
+     OPT_LEGACY_ALG
+ #endif
+@@ -147,6 +147,8 @@ const OPTIONS pkcs12_options[] = {
+ #endif
+     {"macalg", OPT_MACALG, 's',
+      "Digest algorithm to use in MAC (default SHA256)"},
++    {"pbmac1_pbkdf2", OPT_PBMAC1_PBKDF2, '-', "Use PBMAC1 with PBKDF2 instead of MAC"},
++    {"pbmac1_pbkdf2_md", OPT_PBMAC1_PBKDF2_MD, 's', "Digest to use for PBMAC1 KDF (default SHA256)"},
+     {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
+     {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
+     {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"},
+@@ -170,14 +172,14 @@ int pkcs12_main(int argc, char **argv)
+     int use_legacy = 0;
+ #endif
+     /* use library defaults for the iter, maciter, cert, and key PBE */
+-    int iter = 0, maciter = 0;
++    int iter = 0, maciter = 0, pbmac1_pbkdf2 = 0;
+     int macsaltlen = PKCS12_SALT_LEN;
+     int cert_pbe = NID_undef;
+     int key_pbe = NID_undef;
+     int ret = 1, macver = 1, add_lmk = 0, private = 0;
+     int noprompt = 0;
+     char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
+-    char *passin = NULL, *passout = NULL, *macalg = NULL;
++    char *passin = NULL, *passout = NULL, *macalg = NULL, *pbmac1_pbkdf2_md = NULL;
+     char *cpass = NULL, *mpass = NULL, *badpass = NULL;
+     const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog;
+     int noCApath = 0, noCAfile = 0, noCAstore = 0;
+@@ -283,6 +285,12 @@ int pkcs12_main(int argc, char **argv)
+         case OPT_MACALG:
+             macalg = opt_arg();
+             break;
++        case OPT_PBMAC1_PBKDF2:
++            pbmac1_pbkdf2 = 1;
++            break;
++        case OPT_PBMAC1_PBKDF2_MD:
++            pbmac1_pbkdf2_md = opt_arg();
++            break;
+         case OPT_CERTPBE:
+             if (!set_pbe(&cert_pbe, opt_arg()))
+                 goto opthelp;
+@@ -700,10 +708,20 @@ int pkcs12_main(int argc, char **argv)
+         }
+ 
+         if (maciter != -1) {
+-            if (!PKCS12_set_mac(p12, mpass, -1, NULL, macsaltlen, maciter, macmd)) {
+-                BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
+-                BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n");
+-                goto export_end;
++            if (pbmac1_pbkdf2 == 1) {
++                if (!PKCS12_set_pbmac1_pbkdf2(p12, mpass, -1, NULL,
++                                              macsaltlen, maciter,
++                                              macmd, pbmac1_pbkdf2_md)) {
++                    BIO_printf(bio_err, "Error creating PBMAC1\n");
++                    goto export_end;
++                }
++            } else {
++                if (!PKCS12_set_mac(p12, mpass, -1, NULL, macsaltlen, maciter, macmd)) {
++                    BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
++                    BIO_printf(bio_err,
++                               "Use -nomac or -pbmac1_pbkdf2 if PKCS12KDF support not available\n");
++                    goto export_end;
++                }
+             }
+         }
+         assert(private);
+@@ -774,11 +792,32 @@ int pkcs12_main(int argc, char **argv)
+         X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
+         BIO_puts(bio_err, "MAC: ");
+         i2a_ASN1_OBJECT(bio_err, macobj);
+-        BIO_printf(bio_err, ", Iteration %ld\n",
+-                   tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
+-        BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
+-                   tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
+-                   tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
++        if (OBJ_obj2nid(macobj) == NID_pbmac1) {
++            PBKDF2PARAM *pbkdf2_param = PBMAC1_get1_pbkdf2_param(macalgid);
++
++            if (pbkdf2_param == NULL) {
++                BIO_printf(bio_err, ", Unsupported KDF or params for PBMAC1\n");
++            } else {
++                const ASN1_OBJECT *prfobj;
++
++                BIO_printf(bio_err, " using PBKDF2, Iteration %ld\n",
++                           ASN1_INTEGER_get(pbkdf2_param->iter));
++                BIO_printf(bio_err, "Key length: %ld, Salt length: %d\n",
++                           ASN1_INTEGER_get(pbkdf2_param->keylength),
++                           ASN1_STRING_length(pbkdf2_param->salt->value.octet_string));
++                X509_ALGOR_get0(&prfobj, NULL, NULL, pbkdf2_param->prf);
++                BIO_printf(bio_err, "PBKDF2 PRF: ");
++                i2a_ASN1_OBJECT(bio_err, prfobj);
++                BIO_printf(bio_err, "\n");
++            }
++            PBKDF2PARAM_free(pbkdf2_param);
++        } else {
++            BIO_printf(bio_err, ", Iteration %ld\n",
++                       tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
++            BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
++                       tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
++                       tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
++        }
+     }
+     if (macver) {
+         EVP_KDF *pkcs12kdf;
+diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
+index 8575d05bf6d5a..c22cc6b77075d 100644
+--- a/crypto/asn1/p5_pbev2.c
++++ b/crypto/asn1/p5_pbev2.c
+@@ -35,6 +35,13 @@ ASN1_SEQUENCE(PBKDF2PARAM) = {
+ 
+ IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
+ 
++ASN1_SEQUENCE(PBMAC1PARAM) = {
++    ASN1_SIMPLE(PBMAC1PARAM, keyDerivationFunc, X509_ALGOR),
++    ASN1_SIMPLE(PBMAC1PARAM, messageAuthScheme, X509_ALGOR)
++} ASN1_SEQUENCE_END(PBMAC1PARAM)
++
++IMPLEMENT_ASN1_FUNCTIONS(PBMAC1PARAM)
++
+ /*
+  * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know
+  * this is horrible! Extended version to allow application supplied PRF NID
+diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
+index 18a64329b7a35..a74e2fa42c5bb 100644
+--- a/crypto/evp/digest.c
++++ b/crypto/evp/digest.c
+@@ -20,6 +20,7 @@
+ #include <openssl/params.h>
+ #include <openssl/core_names.h>
+ #include "internal/cryptlib.h"
++#include "internal/nelem.h"
+ #include "internal/provider.h"
+ #include "internal/core.h"
+ #include "crypto/evp.h"
+@@ -1185,3 +1186,56 @@ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
+                        (void (*)(void *, void *))fn, arg,
+                        evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
+ }
++
++typedef struct {
++    int md_nid;
++    int hmac_nid;
++} ossl_hmacmd_pair;
++
++static const ossl_hmacmd_pair ossl_hmacmd_pairs[] = {
++    {NID_sha1, NID_hmacWithSHA1},
++    {NID_md5, NID_hmacWithMD5},
++    {NID_sha224, NID_hmacWithSHA224},
++    {NID_sha256, NID_hmacWithSHA256},
++    {NID_sha384, NID_hmacWithSHA384},
++    {NID_sha512, NID_hmacWithSHA512},
++    {NID_id_GostR3411_94, NID_id_HMACGostR3411_94},
++    {NID_id_GostR3411_2012_256, NID_id_tc26_hmac_gost_3411_2012_256},
++    {NID_id_GostR3411_2012_512, NID_id_tc26_hmac_gost_3411_2012_512},
++    {NID_sha3_224, NID_hmac_sha3_224},
++    {NID_sha3_256, NID_hmac_sha3_256},
++    {NID_sha3_384, NID_hmac_sha3_384},
++    {NID_sha3_512, NID_hmac_sha3_512},
++    {NID_sha512_224, NID_hmacWithSHA512_224},
++    {NID_sha512_256, NID_hmacWithSHA512_256}
++};
++
++int ossl_hmac2mdnid(int hmac_nid)
++{
++    int md_nid = NID_undef;
++    size_t i;
++
++    for (i = 0; i < OSSL_NELEM(ossl_hmacmd_pairs); i++) {
++        if (ossl_hmacmd_pairs[i].hmac_nid == hmac_nid) {
++            md_nid = ossl_hmacmd_pairs[i].md_nid;
++            break;
++        }
++    }
++
++    return md_nid;
++}
++
++int ossl_md2hmacnid(int md_nid)
++{
++    int hmac_nid = NID_undef;
++    size_t i;
++
++    for (i = 0; i < OSSL_NELEM(ossl_hmacmd_pairs); i++) {
++        if (ossl_hmacmd_pairs[i].md_nid == md_nid) {
++            hmac_nid = ossl_hmacmd_pairs[i].hmac_nid;
++            break;
++        }
++    }
++
++    return hmac_nid;
++}
+diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
+index 4091e61d9dd06..d410978a49e1e 100644
+--- a/crypto/pkcs12/p12_mutl.c
++++ b/crypto/pkcs12/p12_mutl.c
+@@ -15,12 +15,19 @@
+ 
+ #include <stdio.h>
+ #include "internal/cryptlib.h"
++#include "crypto/evp.h"
+ #include <openssl/crypto.h>
+ #include <openssl/hmac.h>
+ #include <openssl/rand.h>
+ #include <openssl/pkcs12.h>
+ #include "p12_local.h"
+ 
++static int pkcs12_pbmac1_pbkdf2_key_gen(const char *pass, int passlen,
++                                        unsigned char *salt, int saltlen,
++                                        int id, int iter, int keylen,
++                                        unsigned char *out,
++                                        const EVP_MD *md_type);
++
+ int PKCS12_mac_present(const PKCS12 *p12)
+ {
+     return p12->mac ? 1 : 0;
+@@ -72,9 +79,76 @@ static int pkcs12_gen_gost_mac_key(const char *pass, int passlen,
+     return 1;
+ }
+ 
+-/* Generate a MAC */
++PBKDF2PARAM *PBMAC1_get1_pbkdf2_param(const X509_ALGOR *macalg)
++{
++    PBMAC1PARAM *param = NULL;
++    PBKDF2PARAM *pbkdf2_param = NULL;
++    const ASN1_OBJECT *kdf_oid;
++
++    param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), macalg->parameter);
++    if (param == NULL) {
++        ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_INVALID_ARGUMENT);
++        return NULL;
++    }
++
++    X509_ALGOR_get0(&kdf_oid, NULL, NULL, param->keyDerivationFunc);
++    if (OBJ_obj2nid(kdf_oid) != NID_id_pbkdf2) {
++        ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_INVALID_ARGUMENT);
++        PBMAC1PARAM_free(param);
++        return NULL;
++    }
++
++    pbkdf2_param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM),
++                                             param->keyDerivationFunc->parameter);
++    PBMAC1PARAM_free(param);
++
++    return pbkdf2_param;
++}
++
++static int PBMAC1_PBKDF2_HMAC(OSSL_LIB_CTX *ctx, const char *propq,
++                              const char *pass, int passlen,
++                              const X509_ALGOR *macalg, unsigned char *key)
++{
++    PBKDF2PARAM *pbkdf2_param = NULL;
++    const ASN1_OBJECT *kdf_hmac_oid;
++    int ret = -1;
++    int keylen = 0;
++    EVP_MD *kdf_md = NULL;
++    const ASN1_OCTET_STRING *pbkdf2_salt = NULL;
++
++    pbkdf2_param = PBMAC1_get1_pbkdf2_param(macalg);
++    if (pbkdf2_param == NULL) {
++        ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED);
++        goto err;
++    }
++    keylen = ASN1_INTEGER_get(pbkdf2_param->keylength);
++    pbkdf2_salt = pbkdf2_param->salt->value.octet_string;
++    X509_ALGOR_get0(&kdf_hmac_oid, NULL, NULL, pbkdf2_param->prf);
++
++    kdf_md = EVP_MD_fetch(ctx, OBJ_nid2sn(ossl_hmac2mdnid(OBJ_obj2nid(kdf_hmac_oid))), propq);
++    if (kdf_md == NULL) {
++        ERR_raise(ERR_LIB_PKCS12, ERR_R_FETCH_FAILED);
++        goto err;
++    }
++
++    if (PKCS5_PBKDF2_HMAC(pass, passlen, pbkdf2_salt->data, pbkdf2_salt->length,
++                          ASN1_INTEGER_get(pbkdf2_param->iter), kdf_md, keylen, key) <= 0) {
++        ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
++        goto err;
++    }
++    ret = keylen;
++
++ err:
++    EVP_MD_free(kdf_md);
++    PBKDF2PARAM_free(pbkdf2_param);
++
++    return ret;
++}
++
++/* Generate a MAC, also used for verification */
+ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+                           unsigned char *mac, unsigned int *maclen,
++                          int pbmac1_md_nid, int pbmac1_kdf_nid,
+                           int (*pkcs12_key_gen)(const char *pass, int passlen,
+                                                 unsigned char *salt, int slen,
+                                                 int id, int iter, int n,
+@@ -88,8 +162,8 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+     unsigned char key[EVP_MAX_MD_SIZE], *salt;
+     int saltlen, iter;
+     char md_name[80];
+-    int md_size = 0;
+-    int md_nid;
++    int keylen = 0;
++    int md_nid = NID_undef;
+     const X509_ALGOR *macalg;
+     const ASN1_OBJECT *macoid;
+ 
+@@ -111,9 +185,13 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+         iter = ASN1_INTEGER_get(p12->mac->iter);
+     X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
+     X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
+-    if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0)
+-        return 0;
+-
++    if (OBJ_obj2nid(macoid) == NID_pbmac1) {
++        if (OBJ_obj2txt(md_name, sizeof(md_name), OBJ_nid2obj(pbmac1_md_nid), 0) < 0)
++            return 0;
++    } else {
++        if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0)
++            return 0;
++    }
+     (void)ERR_set_mark();
+     md = md_fetch = EVP_MD_fetch(p12->authsafes->ctx.libctx, md_name,
+                                  p12->authsafes->ctx.propq);
+@@ -127,40 +205,61 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+     }
+     (void)ERR_pop_to_mark();
+ 
+-    md_size = EVP_MD_get_size(md);
++    keylen = EVP_MD_get_size(md);
+     md_nid = EVP_MD_get_type(md);
+-    if (md_size < 0)
++    if (keylen < 0)
+         goto err;
+-    if ((md_nid == NID_id_GostR3411_94
+-         || md_nid == NID_id_GostR3411_2012_256
+-         || md_nid == NID_id_GostR3411_2012_512)
+-        && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
+-        md_size = TK26_MAC_KEY_LEN;
++
++    /* For PBMAC1 we use a special keygen callback if not provided (e.g. on verification) */
++    if (pbmac1_md_nid != NID_undef && pkcs12_key_gen == NULL) {
++        keylen = PBMAC1_PBKDF2_HMAC(p12->authsafes->ctx.libctx, p12->authsafes->ctx.propq,
++                                    pass, passlen, macalg, key);
++        if (keylen < 0)
++            goto err;
++    } else if ((md_nid == NID_id_GostR3411_94
++                || md_nid == NID_id_GostR3411_2012_256
++                || md_nid == NID_id_GostR3411_2012_512)
++               && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
++        keylen = TK26_MAC_KEY_LEN;
+         if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter,
+-                                     md_size, key, md)) {
++                                     keylen, key, md)) {
+             ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+             goto err;
+         }
+     } else {
++        EVP_MD *hmac_md = (EVP_MD *)md;
++        int fetched = 0;
++
++        if (pbmac1_kdf_nid != NID_undef) {
++            char hmac_md_name[128];
++
++            if (OBJ_obj2txt(hmac_md_name, sizeof(hmac_md_name), OBJ_nid2obj(pbmac1_kdf_nid), 0) < 0)
++                goto err;
++            hmac_md = EVP_MD_fetch(NULL, hmac_md_name, NULL);
++            fetched = 1;
++        }
+         if (pkcs12_key_gen != NULL) {
+-            if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+-                                   iter, md_size, key, md)) {
++            int res = (*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
++                                        iter, keylen, key, hmac_md);
++
++            if (fetched)
++                EVP_MD_free(hmac_md);
++            if (res != 1) {
+                 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+                 goto err;
+             }
+         } else {
+             /* Default to UTF-8 password */
+             if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+-                                       iter, md_size, key, md,
+-                                       p12->authsafes->ctx.libctx,
+-                                       p12->authsafes->ctx.propq)) {
++                                        iter, keylen, key, md,
++                                        p12->authsafes->ctx.libctx, p12->authsafes->ctx.propq)) {
+                 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+                 goto err;
+             }
+         }
+     }
+     if ((hmac = HMAC_CTX_new()) == NULL
+-        || !HMAC_Init_ex(hmac, key, md_size, md, NULL)
++        || !HMAC_Init_ex(hmac, key, keylen, md, NULL)
+         || !HMAC_Update(hmac, p12->authsafes->d.data->data,
+                         p12->authsafes->d.data->length)
+         || !HMAC_Final(hmac, mac, maclen)) {
+@@ -178,7 +277,7 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+ int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+                    unsigned char *mac, unsigned int *maclen)
+ {
+-    return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NULL);
++    return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NID_undef, NID_undef, NULL);
+ }
+ 
+ /* Verify the mac */
+@@ -187,14 +286,40 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
+     unsigned char mac[EVP_MAX_MD_SIZE];
+     unsigned int maclen;
+     const ASN1_OCTET_STRING *macoct;
++    const X509_ALGOR *macalg;
++    const ASN1_OBJECT *macoid;
+ 
+     if (p12->mac == NULL) {
+         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT);
+         return 0;
+     }
+-    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
+-        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
+-        return 0;
++
++    X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
++    X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
++    if (OBJ_obj2nid(macoid) == NID_pbmac1) {
++        PBMAC1PARAM *param = NULL;
++        const ASN1_OBJECT *hmac_oid;
++        int md_nid = NID_undef;
++
++        param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), macalg->parameter);
++        if (param == NULL) {
++            ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED);
++            return 0;
++        }
++        X509_ALGOR_get0(&hmac_oid, NULL, NULL, param->messageAuthScheme);
++        md_nid = ossl_hmac2mdnid(OBJ_obj2nid(hmac_oid));
++
++        if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, md_nid, NID_undef, NULL)) {
++            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
++            PBMAC1PARAM_free(param);
++            return 0;
++        }
++        PBMAC1PARAM_free(param);
++    } else {
++        if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NID_undef, NID_undef, NULL)) {
++            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
++            return 0;
++        }
+     }
+     X509_SIG_get0(p12->mac->dinfo, NULL, &macoct);
+     if ((maclen != (unsigned int)ASN1_STRING_length(macoct))
+@@ -205,7 +330,6 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
+ }
+ 
+ /* Set a mac */
+-
+ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+                    unsigned char *salt, int saltlen, int iter,
+                    const EVP_MD *md_type)
+@@ -226,7 +350,7 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+     /*
+      * Note that output mac is forced to UTF-8...
+      */
+-    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
++    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NID_undef, NID_undef, NULL)) {
+         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
+         return 0;
+     }
+@@ -238,9 +362,18 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+     return 1;
+ }
+ 
+-/* Set up a mac structure */
+-int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
+-                     const EVP_MD *md_type)
++static int pkcs12_pbmac1_pbkdf2_key_gen(const char *pass, int passlen,
++                                        unsigned char *salt, int saltlen,
++                                        int id, int iter, int keylen,
++                                        unsigned char *out,
++                                        const EVP_MD *md_type)
++{
++    return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter,
++                             md_type, keylen, out);
++}
++
++static int pkcs12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
++                            int nid)
+ {
+     X509_ALGOR *macalg;
+ 
+@@ -274,11 +407,112 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
+         memcpy(p12->mac->salt->data, salt, saltlen);
+     }
+     X509_SIG_getm(p12->mac->dinfo, &macalg, NULL);
+-    if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_get_type(md_type)),
+-                         V_ASN1_NULL, NULL)) {
++    if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(nid), V_ASN1_NULL, NULL)) {
+         ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB);
+         return 0;
+     }
+ 
+     return 1;
+ }
++
++/* Set up a mac structure */
++int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
++                     const EVP_MD *md_type)
++{
++    return pkcs12_setup_mac(p12, iter, salt, saltlen, EVP_MD_get_type(md_type));
++}
++
++int PKCS12_set_pbmac1_pbkdf2(PKCS12 *p12, const char *pass, int passlen,
++                             unsigned char *salt, int saltlen, int iter,
++                             const EVP_MD *md_type, const char *prf_md_name)
++{
++    unsigned char mac[EVP_MAX_MD_SIZE];
++    unsigned int maclen;
++    ASN1_OCTET_STRING *macoct;
++    X509_ALGOR *alg = NULL;
++    int ret = 0;
++    int prf_md_nid = NID_undef, prf_nid = NID_undef, hmac_nid;
++    unsigned char *known_salt = NULL;
++    int keylen = 0;
++    PBMAC1PARAM *param = NULL;
++    X509_ALGOR  *hmac_alg = NULL, *macalg = NULL;
++
++    if (md_type == NULL)
++        /* No need to do a fetch as the md_type is used only to get a NID */
++        md_type = EVP_sha256();
++
++    if (prf_md_name == NULL)
++        prf_md_nid = EVP_MD_get_type(md_type);
++    else
++        prf_md_nid = OBJ_txt2nid(prf_md_name);
++
++    if (iter == 0)
++        iter = PKCS12_DEFAULT_ITER;
++
++    keylen = EVP_MD_get_size(md_type);
++
++    prf_nid  = ossl_md2hmacnid(prf_md_nid);
++    hmac_nid = ossl_md2hmacnid(EVP_MD_get_type(md_type));
++
++    if (prf_nid == NID_undef || hmac_nid == NID_undef) {
++        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
++        goto err;
++    }
++
++    if (salt == NULL) {
++        known_salt = OPENSSL_malloc(saltlen);
++        if (known_salt == NULL)
++            goto err;
++
++        if (RAND_bytes_ex(NULL, known_salt, saltlen, 0) <= 0) {
++            ERR_raise(ERR_LIB_PKCS12, ERR_R_RAND_LIB);
++            goto err;
++        }
++    }
++
++    param = PBMAC1PARAM_new();
++    hmac_alg = X509_ALGOR_new();
++    alg = PKCS5_pbkdf2_set(iter, salt ? salt : known_salt, saltlen, prf_nid, keylen);
++    if (param == NULL || hmac_alg == NULL || alg == NULL)
++        goto err;
++
++    if (pkcs12_setup_mac(p12, iter, salt ? salt : known_salt, saltlen,
++                         NID_pbmac1) == PKCS12_ERROR) {
++        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR);
++        goto err;
++    }
++
++    if (!X509_ALGOR_set0(hmac_alg, OBJ_nid2obj(hmac_nid), V_ASN1_NULL, NULL)) {
++        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR);
++        goto err;
++    }
++
++    X509_ALGOR_free(param->keyDerivationFunc);
++    X509_ALGOR_free(param->messageAuthScheme);
++    param->keyDerivationFunc = alg;
++    param->messageAuthScheme = hmac_alg;
++
++    X509_SIG_getm(p12->mac->dinfo, &macalg, &macoct);
++    if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), param, &macalg->parameter))
++        goto err;
++
++    /*
++     * Note that output mac is forced to UTF-8...
++     */
++    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
++                        EVP_MD_get_type(md_type), prf_md_nid,
++                        pkcs12_pbmac1_pbkdf2_key_gen)) {
++        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
++        goto err;
++    }
++    if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) {
++        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR);
++        goto err;
++    }
++    ret = 1;
++
++ err:
++    PBMAC1PARAM_free(param);
++    OPENSSL_free(known_salt);
++    return ret;
++}
+diff --git a/include/crypto/evp.h b/include/crypto/evp.h
+index 32c60f223c78c..72d9995e8f0f4 100644
+--- a/include/crypto/evp.h
++++ b/include/crypto/evp.h
+@@ -964,4 +964,7 @@ int evp_pkey_decrypt_alloc(EVP_PKEY_CTX *ctx, unsigned char **outp,
+                            size_t *outlenp, size_t expected_outlen,
+                            const unsigned char *in, size_t inlen);
+ 
++int ossl_md2hmacnid(int mdnid);
++int ossl_hmac2mdnid(int hmac_nid);
++
+ #endif /* OSSL_CRYPTO_EVP_H */
+diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in
+index 35759d4deadc3..ab62207e49b55 100644
+--- a/include/openssl/pkcs12.h.in
++++ b/include/openssl/pkcs12.h.in
+@@ -269,6 +269,9 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+                    unsigned char *salt, int saltlen, int iter,
+                    const EVP_MD *md_type);
++int PKCS12_set_pbmac1_pbkdf2(PKCS12 *p12, const char *pass, int passlen,
++                             unsigned char *salt, int saltlen, int iter,
++                             const EVP_MD *md_type, const char *prf_md_name);
+ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+                      int saltlen, const EVP_MD *md_type);
+ unsigned char *OPENSSL_asc2uni(const char *asc, int asclen,
+diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
+index 99bc4aab29133..b7f080a5360db 100644
+--- a/include/openssl/x509.h.in
++++ b/include/openssl/x509.h.in
+@@ -279,7 +279,12 @@ typedef struct PBKDF2PARAM_st {
+     X509_ALGOR *prf;
+ } PBKDF2PARAM;
+ 
+-#ifndef OPENSSL_NO_SCRYPT
++typedef struct {
++    X509_ALGOR *keyDerivationFunc;
++    X509_ALGOR *messageAuthScheme;
++} PBMAC1PARAM;
++
++# ifndef OPENSSL_NO_SCRYPT
+ typedef struct SCRYPT_PARAMS_st {
+     ASN1_OCTET_STRING *salt;
+     ASN1_INTEGER *costParameter;
+@@ -287,7 +292,7 @@ typedef struct SCRYPT_PARAMS_st {
+     ASN1_INTEGER *parallelizationParameter;
+     ASN1_INTEGER *keyLength;
+ } SCRYPT_PARAMS;
+-#endif
++# endif
+ 
+ #ifdef  __cplusplus
+ }
+@@ -1023,9 +1028,10 @@ X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name);
+ DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+ DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+ DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+-#ifndef OPENSSL_NO_SCRYPT
++DECLARE_ASN1_FUNCTIONS(PBMAC1PARAM)
++# ifndef OPENSSL_NO_SCRYPT
+ DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS)
+-#endif
++# endif
+ 
+ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+                          const unsigned char *salt, int saltlen);
+@@ -1062,6 +1068,7 @@ X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+                                 int prf_nid, int keylen,
+                                 OSSL_LIB_CTX *libctx);
+ 
++PBKDF2PARAM *PBMAC1_get1_pbkdf2_param(const X509_ALGOR *macalg);
+ /* PKCS#8 utilities */
+ 
+ DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+From 29d98a8287d217b2232344056934d3cd2c6f44a3 Mon Sep 17 00:00:00 2001
+From: Dmitry Belyavskiy <beldmit@gmail.com>
+Date: Fri, 7 Jun 2024 14:38:40 +0200
+Subject: [PATCH 2/4] Implementation of the RFC 9579, PBMAC1 in PKCS#12 -
+ documentation
+
+---
+ doc/man1/openssl-pkcs12.pod.in        | 11 +++++++
+ doc/man3/PBMAC1_get1_pbkdf2_param.pod | 46 +++++++++++++++++++++++++++
+ doc/man3/PKCS12_gen_mac.pod           | 37 ++++++++++++++++-----
+ doc/man3/X509_dup.pod                 |  3 ++
+ doc/man3/d2i_X509.pod                 |  2 ++
+ util/missingcrypto.txt                |  1 -
+ util/missingcrypto111.txt             |  1 -
+ 7 files changed, 91 insertions(+), 10 deletions(-)
+ create mode 100644 doc/man3/PBMAC1_get1_pbkdf2_param.pod
+
+diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in
+index 665b22bb644ac..020543cd5c895 100644
+--- a/doc/man1/openssl-pkcs12.pod.in
++++ b/doc/man1/openssl-pkcs12.pod.in
+@@ -62,6 +62,8 @@ PKCS#12 output (export) options:
+ [B<-certpbe> I<cipher>]
+ [B<-descert>]
+ [B<-macalg> I<digest>]
++[B<-pbmac1_pbkdf2>]
++[B<-pbmac1_pbkdf2_md> I<digest>]
+ [B<-iter> I<count>]
+ [B<-noiter>]
+ [B<-nomaciter>]
+@@ -345,6 +347,15 @@ then both, the private key and the certificates are encrypted using triple DES.
+ 
+ Specify the MAC digest algorithm. If not included SHA256 will be used.
+ 
++=item B<-pbmac1_pbkdf2>
++
++Use PBMAC1 with PBKDF2 for MAC protection of the PKCS#12 file.
++
++=item B<-pbmac1_pbkdf2_md> I<digest>
++
++Specify the PBKDF2 KDF digest algorithm. If not specified, SHA256 will be used.
++Unless C<-pbmac1_pbkdf2> is specified, this parameter is ignored.
++
+ =item B<-iter> I<count>
+ 
+ This option specifies the iteration count for the encryption key and MAC. The
+diff --git a/doc/man3/PBMAC1_get1_pbkdf2_param.pod b/doc/man3/PBMAC1_get1_pbkdf2_param.pod
+new file mode 100644
+index 0000000000000..415c3cd214a2e
+--- /dev/null
++++ b/doc/man3/PBMAC1_get1_pbkdf2_param.pod
+@@ -0,0 +1,46 @@
++=pod
++
++=head1 NAME
++
++PBMAC1_get1_pbkdf2_param - Function to manipulate a PBMAC1
++MAC structure
++
++=head1 SYNOPSIS
++
++ #include <openssl/x509.h>
++
++ PBKDF2PARAM *PBMAC1_get1_pbkdf2_param(const X509_ALGOR *macalg);
++
++=head1 DESCRIPTION
++
++PBMAC1_get1_pbkdf2_param() retrieves a B<PBKDF2PARAM> structure from an
++I<X509_ALGOR> structure.
++
++=head1 RETURN VALUES
++
++PBMAC1_get1_pbkdf2_param() returns NULL in case when PBMAC1 uses an algorithm
++apart from B<PBKDF2> or when passed incorrect parameters and a pointer to
++B<PBKDF2PARAM> structure otherwise.
++
++=head1 CONFORMING TO
++
++IETF RFC 9579 (L<https://tools.ietf.org/html/rfc9579>)
++
++=head1 SEE ALSO
++
++L<openssl-pkcs12(1)>
++
++=head1 HISTORY
++
++The I<PBMAC1_get1_pbkdf2_param> function was added in OpenSSL 3.4.
++
++=head1 COPYRIGHT
++
++Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
++
++Licensed under the Apache License 2.0 (the "License").  You may not use
++this file except in compliance with the License.  You can obtain a copy
++in the file LICENSE in the source distribution or at
++L<https://www.openssl.org/source/license.html>.
++
++=cut
+diff --git a/doc/man3/PKCS12_gen_mac.pod b/doc/man3/PKCS12_gen_mac.pod
+index a72df145fedd7..ebeee98f04e68 100644
+--- a/doc/man3/PKCS12_gen_mac.pod
++++ b/doc/man3/PKCS12_gen_mac.pod
+@@ -3,7 +3,8 @@
+ =head1 NAME
+ 
+ PKCS12_gen_mac, PKCS12_setup_mac, PKCS12_set_mac,
+-PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure
++PKCS12_set_pbmac1_pbkdf2, PKCS12_verify_mac, PKCS12_get0_mac -
++Functions to create and manipulate a PKCS#12 MAC structure
+ 
+ =head1 SYNOPSIS
+ 
+@@ -15,9 +16,19 @@ PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure
+  int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+                     unsigned char *salt, int saltlen, int iter,
+                     const EVP_MD *md_type);
++ int PKCS12_set_pbmac1_pbkdf2(PKCS12 *p12, const char *pass, int passlen,
++                                   unsigned char *salt, int saltlen, int iter,
++                                   const EVP_MD *md_type,
++                                   const char *prf_md_name);
+  int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+                       int saltlen, const EVP_MD *md_type);
+ 
++ void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac,
++                      const X509_ALGOR **pmacalg,
++                      const ASN1_OCTET_STRING **psalt,
++                      const ASN1_INTEGER **piter,
++                      const PKCS12 *p12);
++
+ =head1 DESCRIPTION
+ 
+ PKCS12_gen_mac() generates an HMAC over the entire PKCS#12 object using the
+@@ -31,10 +42,15 @@ PKCS12_setup_mac() sets the MAC part of the PKCS#12 structure with the supplied
+ parameters.
+ 
+ PKCS12_set_mac() sets the MAC and MAC parameters into the PKCS#12 object.
++PKCS12_set_pbmac1_pbkdf2() sets the MAC and MAC parameters into the PKCS#12
++object when B<PBMAC1> with PBKDF2 is used for protection of the PKCS#12 object.
+ 
+ I<pass> is the passphrase to use in the HMAC. I<salt> is the salt value to use,
+-I<iter> is the iteration count and I<md_type> is the message digest
+-function to use.
++I<iter> is the iteration count and I<md_type> is the message digest function to
++use. I<prf_md_name> specifies the digest used for the PBKDF2 in PBMAC1 KDF.
++
++PKCS12_get0_mac() retrieves any included MAC value, B<X509_ALGOR> object,
++I<salt>, and I<iter> count from the PKCS12 object.
+ 
+ =head1 NOTES
+ 
+@@ -43,17 +59,18 @@ If I<salt> is NULL then a suitable salt will be generated and used.
+ If I<iter> is 1 then an iteration count will be omitted from the PKCS#12
+ structure.
+ 
+-PKCS12_gen_mac(), PKCS12_verify_mac() and PKCS12_set_mac() make assumptions
+-regarding the encoding of the given passphrase. See L<passphrase-encoding(7)>
+-for more information.
++PKCS12_gen_mac(), PKCS12_verify_mac(), PKCS12_set_mac() and
++PKCS12_set_pbmac1_pbkdf2() make assumptions regarding the encoding of the
++given passphrase. See L<passphrase-encoding(7)> for more information.
+ 
+ =head1 RETURN VALUES
+ 
+-All functions return 1 on success and 0 if an error occurred.
++All functions returning an integer return 1 on success and 0 if an error occurred.
+ 
+ =head1 CONFORMING TO
+ 
+ IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
++IETF RFC 9579 (L<https://tools.ietf.org/html/rfc9579>)
+ 
+ =head1 SEE ALSO
+ 
+@@ -62,9 +79,13 @@ L<EVP_KDF-PKCS12KDF(7)>,
+ L<PKCS12_create(3)>,
+ L<passphrase-encoding(7)>
+ 
++=head1 HISTORY
++
++The I<PKCS12_set_pbmac1_pbkdf2> function was added in OpenSSL 3.4.
++
+ =head1 COPYRIGHT
+ 
+-Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
++Copyright 2021-2024 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
+diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
+index fc93494a76617..81ea2275d7414 100644
+--- a/doc/man3/X509_dup.pod
++++ b/doc/man3/X509_dup.pod
+@@ -218,6 +218,9 @@ PBEPARAM_free,
+ PBEPARAM_new,
+ PBKDF2PARAM_free,
+ PBKDF2PARAM_new,
++PBMAC1PARAM_free,
++PBMAC1PARAM_it,
++PBMAC1PARAM_new,
+ PKCS12_BAGS_free,
+ PKCS12_BAGS_new,
+ PKCS12_MAC_DATA_free,
+diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod
+index 75b37e5544396..3615bcaafe7c0 100644
+--- a/doc/man3/d2i_X509.pod
++++ b/doc/man3/d2i_X509.pod
+@@ -115,6 +115,7 @@ d2i_OTHERNAME,
+ d2i_PBE2PARAM,
+ d2i_PBEPARAM,
+ d2i_PBKDF2PARAM,
++d2i_PBMAC1PARAM,
+ d2i_PKCS12,
+ d2i_PKCS12_BAGS,
+ d2i_PKCS12_MAC_DATA,
+@@ -300,6 +301,7 @@ i2d_OTHERNAME,
+ i2d_PBE2PARAM,
+ i2d_PBEPARAM,
+ i2d_PBKDF2PARAM,
++i2d_PBMAC1PARAM,
+ i2d_PKCS12,
+ i2d_PKCS12_BAGS,
+ i2d_PKCS12_MAC_DATA,
+diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
+index b7d5091b31912..a56491d0f8b94 100644
+--- a/util/missingcrypto.txt
++++ b/util/missingcrypto.txt
+@@ -749,7 +749,6 @@ PKCS12_MAC_DATA_it(3)
+ PKCS12_PBE_add(3)
+ PKCS12_SAFEBAGS_it(3)
+ PKCS12_SAFEBAG_it(3)
+-PKCS12_get0_mac(3)
+ PKCS12_get_attr(3)
+ PKCS12_it(3)
+ PKCS12_item_pack_safebag(3)
+diff --git a/util/missingcrypto111.txt b/util/missingcrypto111.txt
+index 0386701ad1e32..f3402ada7e60f 100644
+--- a/util/missingcrypto111.txt
++++ b/util/missingcrypto111.txt
+@@ -1027,7 +1027,6 @@ PKCS12_add_safe(3)
+ PKCS12_add_safes(3)
+ PKCS12_decrypt_skey(3)
+ PKCS12_gen_mac(3)
+-PKCS12_get0_mac(3)
+ PKCS12_get_attr(3)
+ PKCS12_get_attr_gen(3)
+ PKCS12_get_friendlyname(3)
+
+From 7257898633703d5841aefa7fb4f9d192430fdad8 Mon Sep 17 00:00:00 2001
+From: Dmitry Belyavskiy <beldmit@gmail.com>
+Date: Thu, 6 Jun 2024 13:07:48 +0200
+Subject: [PATCH 3/4] Make update
+
+---
+ doc/build.info     | 6 ++++++
+ util/libcrypto.num | 7 +++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/doc/build.info b/doc/build.info
+index d47371e88aa9f..60a5d9b86bd5c 100644
+--- a/doc/build.info
++++ b/doc/build.info
+@@ -1847,6 +1847,10 @@ DEPEND[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
+ GENERATE[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
+ DEPEND[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
+ GENERATE[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
++DEPEND[html/man3/PBMAC1_get1_pbkdf2_param.html]=man3/PBMAC1_get1_pbkdf2_param.pod
++GENERATE[html/man3/PBMAC1_get1_pbkdf2_param.html]=man3/PBMAC1_get1_pbkdf2_param.pod
++DEPEND[man/man3/PBMAC1_get1_pbkdf2_param.3]=man3/PBMAC1_get1_pbkdf2_param.pod
++GENERATE[man/man3/PBMAC1_get1_pbkdf2_param.3]=man3/PBMAC1_get1_pbkdf2_param.pod
+ DEPEND[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
+ GENERATE[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
+ DEPEND[man/man3/PEM_X509_INFO_read_bio_ex.3]=man3/PEM_X509_INFO_read_bio_ex.pod
+@@ -3453,6 +3457,7 @@ html/man3/OSSL_trace_get_category_num.html \
+ html/man3/OSSL_trace_set_channel.html \
+ html/man3/OpenSSL_add_all_algorithms.html \
+ html/man3/OpenSSL_version.html \
++html/man3/PBMAC1_get1_pbkdf2_param.html \
+ html/man3/PEM_X509_INFO_read_bio_ex.html \
+ html/man3/PEM_bytes_read_bio.html \
+ html/man3/PEM_read.html \
+@@ -4113,6 +4118,7 @@ man/man3/OSSL_trace_get_category_num.3 \
+ man/man3/OSSL_trace_set_channel.3 \
+ man/man3/OpenSSL_add_all_algorithms.3 \
+ man/man3/OpenSSL_version.3 \
++man/man3/PBMAC1_get1_pbkdf2_param.3 \
+ man/man3/PEM_X509_INFO_read_bio_ex.3 \
+ man/man3/PEM_bytes_read_bio.3 \
+ man/man3/PEM_read.3 \
+diff --git a/util/libcrypto.num b/util/libcrypto.num
+index 7f958a4fa31db..ef11c0302e396 100644
+--- a/util/libcrypto.num
++++ b/util/libcrypto.num
+@@ -5664,3 +5664,10 @@ OSSL_IETF_ATTR_SYNTAX_get_value_num     ?	3_4_0	EXIST::FUNCTION:
+ OPENSSL_strncasecmp                     ? 	3_0_1	EXIST::FUNCTION:
+ ossl_ctx_legacy_digest_signatures_allowed ?	3_0_1	EXIST::FUNCTION:
+ ossl_ctx_legacy_digest_signatures_allowed_set ?	3_0_1	EXIST::FUNCTION:
++PKCS12_set_pbmac1_pbkdf2                ?	3_4_0	EXIST::FUNCTION:
++PBMAC1_get1_pbkdf2_param                ?	3_4_0	EXIST::FUNCTION:
++d2i_PBMAC1PARAM                         ?	3_4_0	EXIST::FUNCTION:
++i2d_PBMAC1PARAM                         ?	3_4_0	EXIST::FUNCTION:
++PBMAC1PARAM_free                        ?	3_4_0	EXIST::FUNCTION:
++PBMAC1PARAM_new                         ?	3_4_0	EXIST::FUNCTION:
++PBMAC1PARAM_it                          ?	3_4_0	EXIST::FUNCTION:
+
+From 97fbb9437163fb5114da40250b7ace83748a2e81 Mon Sep 17 00:00:00 2001
+From: Dmitry Belyavskiy <beldmit@gmail.com>
+Date: Thu, 6 Jun 2024 17:01:45 +0200
+Subject: [PATCH 4/4] Test vectors from rfc9579 and creation tests
+
+---
+ test/recipes/80-test_pkcs12.t                 |  55 +++++++++++++++++-
+ .../pbmac1_256_256.bad-iter.p12               | Bin 0 -> 2703 bytes
+ .../pbmac1_256_256.bad-salt.p12               | Bin 0 -> 2702 bytes
+ .../pbmac1_256_256.good.p12                   | Bin 0 -> 2702 bytes
+ .../pbmac1_256_256.no-len.p12                 | Bin 0 -> 2700 bytes
+ .../pbmac1_512_256.good.p12                   | Bin 0 -> 2702 bytes
+ .../pbmac1_512_512.good.p12                   | Bin 0 -> 2736 bytes
+ 7 files changed, 54 insertions(+), 1 deletion(-)
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-iter.p12
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-salt.p12
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_256_256.good.p12
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_256_256.no-len.p12
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_512_256.good.p12
+ create mode 100644 test/recipes/80-test_pkcs12_data/pbmac1_512_512.good.p12
+
+diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t
+index 999129a03074d..c14ef94998cde 100644
+--- a/test/recipes/80-test_pkcs12.t
++++ b/test/recipes/80-test_pkcs12.t
+@@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) {
+ }
+ $ENV{OPENSSL_WIN32_UTF8}=1;
+ 
+-plan tests => 31;
++plan tests => 45;
+ 
+ # Test different PKCS#12 formats
+ ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats");
+@@ -170,6 +170,59 @@ ok(grep(/Trusted key usage (Oracle)/, @pkcs12info) == 0,
+     ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty");
+ }
+ 
++my %pbmac1_tests = (
++    pbmac1_defaults => {args => [], lookup => "hmacWithSHA256"},
++    pbmac1_nondefaults => {args => ["-pbmac1_pbkdf2_md", "sha512", "-macalg", "sha384"], lookup => "hmacWithSHA512"},
++);
++
++for my $instance (sort keys %pbmac1_tests) {
++    my $extra_args = $pbmac1_tests{$instance}{args};
++    my $lookup     = $pbmac1_tests{$instance}{lookup};
++    # Test export of PEM file with both cert and key, with password.
++    {
++        my $pbmac1_id = $instance;
++        ok(run(app(["openssl", "pkcs12", "-export", "-pbmac1_pbkdf2",
++                "-inkey", srctop_file(@path, "cert-key-cert.pem"),
++                "-in", srctop_file(@path, "cert-key-cert.pem"),
++                "-passout", "pass:1234",
++		@$extra_args,
++                "-out", "$pbmac1_id.p12"], stderr => "${pbmac1_id}_err.txt")),
++        "test_export_pkcs12_${pbmac1_id}");
++        open DATA, "${pbmac1_id}_err.txt";
++        my @match = grep /:error:/, <DATA>;
++        close DATA;
++        ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_${pbmac1_id}_err.empty");
++
++        ok(run(app(["openssl", "pkcs12", "-in", "$pbmac1_id.p12", "-info", "-noout",
++                "-passin", "pass:1234"], stderr => "${pbmac1_id}_info.txt")),
++        "test_export_pkcs12_${pbmac1_id}_info");
++        open DATA, "${pbmac1_id}_info.txt";
++        my @match = grep /$lookup/, <DATA>;
++        close DATA;
++        ok(scalar @match > 0 ? 1 : 0, "test_export_pkcs12_${pbmac1_id}_info");
++    }
++}
++
++# Test pbmac1 pkcs12 good files, RFC 9579
++for my $file ("pbmac1_256_256.good.p12", "pbmac1_512_256.good.p12", "pbmac1_512_512.good.p12")
++{
++    my $path = srctop_file("test", "recipes", "80-test_pkcs12_data", $file);
++    ok(run(app(["openssl", "pkcs12", "-in", $path, "-password", "pass:1234", "-noenc"])),
++      "test pbmac1 pkcs12 file $file");
++}
++
++# Test pbmac1 pkcs12 bad files, RFC 9579
++for my $file ("pbmac1_256_256.bad-iter.p12", "pbmac1_256_256.bad-salt.p12", "pbmac1_256_256.no-len.p12")
++{
++    my $path = srctop_file("test", "recipes", "80-test_pkcs12_data", $file);
++    with({ exit_checker => sub { return shift == 1; } },
++        sub {
++            ok(run(app(["openssl", "pkcs12", "-in", $path, "-password", "pass:1234", "-noenc"])),
++            "test pbmac1 pkcs12 bad file $file");
++            }
++        );
++}
++
+ # Test some bad pkcs12 files
+ my $bad1 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad1.p12");
+ my $bad2 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad2.p12");
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-iter.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-iter.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..9957d473c433bc9fb9572ecf51332a7f325fe36f
+GIT binary patch
+literal 2703
+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
+QZf;>CWNWRj_YbE31}omyrT_o{
+
+literal 0
+HcmV?d00001
+
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-salt.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_256_256.bad-salt.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..fef1e51f71c94240b8d5e375b3e5273a7cb54be5
+GIT binary patch
+literal 2702
+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
+QJitKh*G5^nATS8@Hz^a=n*aa+
+
+literal 0
+HcmV?d00001
+
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_256_256.good.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_256_256.good.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..b8c8c2d7759c66db30d791389a498418fd9cf2bd
+GIT binary patch
+literal 2702
+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
+Ob8A5xD?ME>2=q5e$<~_y
+
+literal 0
+HcmV?d00001
+
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_256_256.no-len.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_256_256.no-len.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..35ebe05d177f7d745251e2fce3ebb4f23e0ebd09
+GIT binary patch
+literal 2700
+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
+
+literal 0
+HcmV?d00001
+
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_512_256.good.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_512_256.good.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..e8d4899691bfec94614bf1614c0e9d45b902cf24
+GIT binary patch
+literal 2702
+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
+VW!Nl&SdEOYi{CK0av2B!{0(@<()a)X
+
+literal 0
+HcmV?d00001
+
+diff --git a/test/recipes/80-test_pkcs12_data/pbmac1_512_512.good.p12 b/test/recipes/80-test_pkcs12_data/pbmac1_512_512.good.p12
+new file mode 100644
+index 0000000000000000000000000000000000000000..64e14341a10d04e7e98cf83dbb2b6409ae1fd72f
+GIT binary patch
+literal 2736
+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
+D?Q7k<
+
+literal 0
+HcmV?d00001
+
diff --git a/openssl.spec b/openssl.spec
index 333a425..f58bd8c 100644
--- a/openssl.spec
+++ b/openssl.spec
@@ -29,7 +29,7 @@ print(string.sub(hash, 0, 16))
 Summary: Utilities from the general purpose cryptography library with TLS implementation
 Name: openssl
 Version: 3.2.2
-Release: 7%{?dist}
+Release: 8%{?dist}
 Epoch: 1
 Source: openssl-%{version}.tar.gz
 Source2: Makefile.certificate
@@ -158,6 +158,8 @@ Patch117: 0117-ignore-unknown-sigalgorithms-groups.patch
 Patch121: 0121-FIPS-cms-defaults.patch
 # HKDF regression with older provider implementations
 Patch122: 0123-kdf-Preserve-backward-compatibility-with-older-provi.patch
+# https://github.com/openssl/openssl/issues/24577
+Patch124: 0124-PBMAC1-PKCS12-FIPS-support.patch
 
 License: Apache-2.0
 URL: http://www.openssl.org/
@@ -503,6 +505,10 @@ ln -s /etc/crypto-policies/back-ends/openssl_fips.config $RPM_BUILD_ROOT%{_sysco
 %ldconfig_scriptlets libs
 
 %changelog
+* Wed Aug 07 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.2.2-8
+- An interface to create PKCS #12 files in FIPS compliant way
+  Resolves: RHEL-36659
+
 * Wed Jul 10 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.2.2-7
 - Disallow SHA1 at SECLEVEL2 in OpenSSL
   Resolves: RHEL-39962