Russian standard body has changed the way MAC key is calculated for
PKCS12 files. Generate proper keys depending on the digest type used for
MAC generation.

Sponsored by ROSA Linux

Signed-off-by: Dmitry Baryshkov <dbarysh...@gmail.com>
---
 src/lib/libcrypto/pkcs12/p12_key.c  | 18 ++++++++++++++++++
 src/lib/libcrypto/pkcs12/p12_mutl.c | 28 +++++++++++++++++++++-------
 src/lib/libcrypto/pkcs12/pkcs12.h   |  5 +++++
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/src/lib/libcrypto/pkcs12/p12_key.c 
b/src/lib/libcrypto/pkcs12/p12_key.c
index d419a9d83598..9a5297a23131 100644
--- a/src/lib/libcrypto/pkcs12/p12_key.c
+++ b/src/lib/libcrypto/pkcs12/p12_key.c
@@ -195,3 +195,21 @@ end:
        EVP_MD_CTX_cleanup(&ctx);
        return ret;
 }
+
+int
+PKCS12_key_gen_gost(const char *pass, int passlen, unsigned char *salt,
+    int saltlen, int iter, int n, unsigned char *out,
+    const EVP_MD *md_type)
+{
+       unsigned char buf[96];
+
+       if (n != PKCS12_GOST_KEY_LEN)
+               return 0;
+
+       if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, md_type, 
sizeof(buf), buf))
+               return 0;
+
+       memcpy(out, buf + sizeof(buf) - PKCS12_GOST_KEY_LEN, 
PKCS12_GOST_KEY_LEN);
+
+       return 1;
+}
diff --git a/src/lib/libcrypto/pkcs12/p12_mutl.c 
b/src/lib/libcrypto/pkcs12/p12_mutl.c
index f3132ec75f68..023bbbd92db1 100644
--- a/src/lib/libcrypto/pkcs12/p12_mutl.c
+++ b/src/lib/libcrypto/pkcs12/p12_mutl.c
@@ -74,6 +74,7 @@ PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
     unsigned char *mac, unsigned int *maclen)
 {
        const EVP_MD *md_type;
+       int md_type_nid;
        HMAC_CTX hmac;
        unsigned char key[EVP_MAX_MD_SIZE], *salt;
        int saltlen, iter;
@@ -97,13 +98,26 @@ PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
                PKCS12error(PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
                return 0;
        }
-       md_size = EVP_MD_size(md_type);
-       if (md_size < 0)
-               return 0;
-       if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
-           md_size, key, md_type)) {
-               PKCS12error(PKCS12_R_KEY_GEN_ERROR);
-               return 0;
+       md_type_nid = EVP_MD_type(md_type);
+       if ((md_type_nid == NID_id_GostR3411_94 ||
+            md_type_nid == NID_id_tc26_gost3411_2012_256 ||
+            md_type_nid == NID_id_tc26_gost3411_2012_512) &&
+           getenv("LEGACY_GOST_PKCS12") == NULL) {
+               md_size = PKCS12_GOST_KEY_LEN;
+               if (!PKCS12_key_gen_gost(pass, passlen, salt, saltlen, iter,
+                   md_size, key, md_type)) {
+                       PKCS12error(PKCS12_R_KEY_GEN_ERROR);
+                       return 0;
+               }
+       } else {
+               md_size = EVP_MD_size(md_type);
+               if (md_size < 0)
+                       return 0;
+               if (!PKCS12_key_gen(pass, passlen, salt, saltlen, 
PKCS12_MAC_ID, iter,
+                   md_size, key, md_type)) {
+                       PKCS12error(PKCS12_R_KEY_GEN_ERROR);
+                       return 0;
+               }
        }
        HMAC_CTX_init(&hmac);
        if (!HMAC_Init_ex(&hmac, key, md_size, md_type, NULL) ||
diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h 
b/src/lib/libcrypto/pkcs12/pkcs12.h
index 56635f9d7e0a..4dab109bbc3a 100644
--- a/src/lib/libcrypto/pkcs12/pkcs12.h
+++ b/src/lib/libcrypto/pkcs12/pkcs12.h
@@ -91,6 +91,11 @@ extern "C" {
 #define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc
 #endif
 
+#define PKCS12_GOST_KEY_LEN 32
+int PKCS12_key_gen_gost(const char *pass, int passlen, unsigned char *salt,
+    int saltlen, int iter, int n, unsigned char *out,
+    const EVP_MD *md_type);
+
 /* MS key usage constants */
 
 #define KEY_EX 0x10
-- 
2.27.0

Reply via email to