Add |PKCS12_verify_mac|.
This utility function is provided for API-compatibility and simply calls
|PKCS12_parse| internally.
BUG=536939
Change-Id: I86c548e5dfd64b6c473e497b95adfa5947fe9529
Reviewed-on: https://boringssl-review.googlesource.com/6008
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/pkcs8/pkcs12_test.cc b/crypto/pkcs8/pkcs12_test.cc
index 8b265cd..55006b4 100644
--- a/crypto/pkcs8/pkcs12_test.cc
+++ b/crypto/pkcs8/pkcs12_test.cc
@@ -681,6 +681,8 @@
0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
};
+static const char kPassword[] = "foo";
+
static bool Test(const char *name, const uint8_t *der, size_t der_len) {
ScopedX509Stack certs(sk_X509_new_null());
if (!certs) {
@@ -690,7 +692,7 @@
CBS pkcs12;
EVP_PKEY *key = nullptr;
CBS_init(&pkcs12, der, der_len);
- if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, "foo")) {
+ if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, kPassword)) {
fprintf(stderr, "PKCS12 failed on %s data.\n", name);
ERR_print_errors_fp(stderr);
return false;
@@ -718,10 +720,20 @@
return false;
}
+ if (PKCS12_verify_mac(p12.get(), "badpass", 7)) {
+ fprintf(stderr, "PKCS12_verify_mac accepted bad password.\n");
+ return false;
+ }
+
+ if (!PKCS12_verify_mac(p12.get(), kPassword, sizeof(kPassword) - 1)) {
+ fprintf(stderr, "PKCS12_verify_mac rejected good password.\n");
+ return false;
+ }
+
EVP_PKEY *key = nullptr;
X509 *cert = nullptr;
STACK_OF(X509) *ca_certs = nullptr;
- if (!PKCS12_parse(p12.get(), "foo", &key, &cert, &ca_certs)) {
+ if (!PKCS12_parse(p12.get(), kPassword, &key, &cert, &ca_certs)) {
fprintf(stderr, "PKCS12_parse failed.\n");
ERR_print_errors_fp(stderr);
return false;
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
index 8067c91..c097881 100644
--- a/crypto/pkcs8/pkcs8.c
+++ b/crypto/pkcs8/pkcs8.c
@@ -1176,6 +1176,31 @@
return 1;
}
+int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
+ int password_len) {
+ if (password == NULL) {
+ if (password_len != 0) {
+ return 0;
+ }
+ } else if (password_len != -1 &&
+ (password[password_len] != 0 ||
+ memchr(password, 0, password_len) != NULL)) {
+ return 0;
+ }
+
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) {
+ ERR_clear_error();
+ return 0;
+ }
+
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+
+ return 1;
+}
+
void PKCS12_free(PKCS12 *p12) {
OPENSSL_free(p12->ber_bytes);
OPENSSL_free(p12);
diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h
index a9b1a71..6b51f85 100644
--- a/include/openssl/pkcs8.h
+++ b/include/openssl/pkcs8.h
@@ -166,9 +166,21 @@
EVP_PKEY **out_pkey, X509 **out_cert,
STACK_OF(X509) **out_ca_certs);
+/* PKCS12_verify_mac returns one if |password| is a valid password for |p12|
+ * and zero otherwise. Since |PKCS12_parse| doesn't take a length parameter,
+ * it's not actually possible to use a non-NUL-terminated password to actually
+ * get anything from a |PKCS12|. Thus |password| and |password_len| may be
+ * |NULL| and zero, respectively, or else |password_len| may be -1, or else
+ * |password[password_len]| must be zero and no other NUL bytes may appear in
+ * |password|. If the |password_len| checks fail, zero is returned
+ * immediately. */
+OPENSSL_EXPORT int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
+ int password_len);
+
/* PKCS12_free frees |p12| and its contents. */
OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12);
+
#if defined(__cplusplus)
} /* extern C */
#endif