summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/openssl/ossl_pkcs12.c43
-rw-r--r--test/openssl/test_pkcs12.rb42
2 files changed, 85 insertions, 0 deletions
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index ea7d14e782..bda90aec3e 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -251,6 +251,48 @@ ossl_pkcs12_to_der(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * pkcs12.set_mac(pass, salt = nil, iter = nil, md_type = nil)
+ *
+ * Sets MAC parameters and generates MAC over the PKCS #12 structure.
+ *
+ * This method uses HMAC and the PKCS #12 specific password-based KDF as
+ * specified in the original PKCS #12.
+ *
+ * See also the man page PKCS12_set_mac(3).
+ *
+ * Added in version 3.3.0.
+ */
+static VALUE
+pkcs12_set_mac(int argc, VALUE *argv, VALUE self)
+{
+ PKCS12 *p12;
+ VALUE pass, salt, iter, md_name;
+ int iter_i = 0;
+ const EVP_MD *md_type = NULL;
+
+ rb_scan_args(argc, argv, "13", &pass, &salt, &iter, &md_name);
+ rb_check_frozen(self);
+ GetPKCS12(self, p12);
+
+ StringValue(pass);
+ if (!NIL_P(salt))
+ StringValue(salt);
+ if (!NIL_P(iter))
+ iter_i = NUM2INT(iter);
+ if (!NIL_P(md_name))
+ md_type = ossl_evp_get_digestbyname(md_name);
+
+ if (!PKCS12_set_mac(p12, RSTRING_PTR(pass), RSTRING_LENINT(pass),
+ !NIL_P(salt) ? (unsigned char *)RSTRING_PTR(salt) : NULL,
+ !NIL_P(salt) ? RSTRING_LENINT(salt) : 0,
+ iter_i, md_type))
+ ossl_raise(ePKCS12Error, "PKCS12_set_mac");
+
+ return Qnil;
+}
+
void
Init_ossl_pkcs12(void)
{
@@ -276,6 +318,7 @@ Init_ossl_pkcs12(void)
rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+ rb_define_method(cPKCS12, "set_mac", pkcs12_set_mac, -1);
/* MSIE specific PKCS12 key usage extensions */
rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX));
diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb
index faf26c9e3e..68a23b28c0 100644
--- a/test/openssl/test_pkcs12.rb
+++ b/test/openssl/test_pkcs12.rb
@@ -337,6 +337,48 @@ BC8fv38mue8LZVcbHQQIUNrWKEnskCoCAggA
)
assert_equal p12.to_der, p12.dup.to_der
end
+
+ def test_set_mac_pkcs12kdf
+ p12 = OpenSSL::PKCS12.create(
+ "pass",
+ "name",
+ @mykey,
+ @mycert,
+ nil,
+ nil,
+ nil,
+ nil,
+ 1234, # mac_iter
+ nil,
+ )
+ macdata = macdata(p12)
+ # Depends on the OpenSSL version: SHA256 in OpenSSL >= 3.0
+ assert_include ["SHA1", "SHA256"], macdata[:mac_algo]
+ assert_equal 1234, macdata[:iter]
+
+ p12.set_mac("pass", "macsalt", 2345, "SHA384")
+ macdata = macdata(p12)
+ assert_equal "SHA384", macdata[:mac_algo]
+ assert_equal "macsalt", macdata[:salt]
+ assert_equal 2345, macdata[:iter]
+ assert_equal @mykey.to_der, OpenSSL::PKCS12.new(p12.to_der, "pass").key.to_der
+ end
+
+ private
+
+ def macdata(p12)
+ # See RFC 7292
+ asn1 = OpenSSL::ASN1.decode(p12.to_der)
+ macdata = asn1.value[2]
+ mac = macdata.value[0]
+ mac_algo = mac.value[0].value[0].value
+ _mac_params = mac.value[0].value[1]
+ {
+ mac_algo: mac_algo,
+ salt: macdata.value[1].value,
+ iter: macdata.value[2]&.value,
+ }
+ end
end
end