Merge changes I23a79eb5,I231079f3 into main
* changes:
Add debug display of Keystore metric info
Implement dump for IKeystoreMaintenance
diff --git a/keystore2/src/crypto/tests/certificate_utils_test.cpp b/keystore2/src/crypto/tests/certificate_utils_test.cpp
index a851798..e2f7cdb 100644
--- a/keystore2/src/crypto/tests/certificate_utils_test.cpp
+++ b/keystore2/src/crypto/tests/certificate_utils_test.cpp
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
-
#include "certificate_utils.h"
+#include <gtest/gtest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -231,6 +230,72 @@
return s.str();
}
+static std::optional<std::vector<uint8_t>> EncodeX509Algor(const X509_ALGOR* alg) {
+ uint8_t* der = nullptr;
+ int der_len = i2d_X509_ALGOR(alg, &der);
+ if (der_len < 0) {
+ return std::nullopt;
+ }
+ std::vector<uint8_t> ret(der, der + der_len);
+ OPENSSL_free(der);
+ return ret;
+}
+
+// `x509_verify` not working with RSA-PSS & SHA1/SHA224 digests. so, manually
+// verify the certificate with RSA-PSS & SHA1/SHA224 digests.
+// BoringSSL after https://boringssl-review.googlesource.com/c/boringssl/+/53865
+// does not support RSA-PSS with SHA1/SHA224 digests.
+static void verifyCertFieldsExplicitly(X509* cert, Digest digest) {
+ // RSA-PSS-SHA1 AlgorithmIdentifier DER encoded value
+ const std::vector<uint8_t> expected_rsa_pss_sha1 = {
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x00,
+ };
+ // RSA-PSS-SHA224 AlgorithmIdentifier DER encoded value
+ const std::vector<uint8_t> expected_rsa_pss_sha224 = {
+ 0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30,
+ 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
+ 0x02, 0x04, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x1c,
+ };
+ const X509_ALGOR* alg;
+ const ASN1_BIT_STRING* sig;
+ const EVP_MD* evp_digest;
+ X509_get0_signature(&sig, &alg, cert);
+ auto encoded = EncodeX509Algor(alg);
+ ASSERT_TRUE(encoded);
+
+ // Check the AlgorithmIdentifiers.
+ if (digest == Digest::SHA1) {
+ evp_digest = EVP_sha1();
+ EXPECT_EQ(encoded.value(), expected_rsa_pss_sha1);
+ } else if (digest == Digest::SHA224) {
+ evp_digest = EVP_sha224();
+ EXPECT_EQ(encoded.value(), expected_rsa_pss_sha224);
+ } else {
+ GTEST_FAIL()
+ << "Error: This is expected to be used only for RSA-PSS with SHA1/SHA224 as digests";
+ }
+
+ // Check the signature.
+ EVP_PKEY_Ptr pubkey(X509_get_pubkey(cert));
+ ASSERT_TRUE(pubkey);
+
+ uint8_t* tbs = nullptr;
+ int tbs_len = i2d_X509_tbs(cert, &tbs);
+ ASSERT_GT(tbs_len, 0);
+
+ size_t sig_len;
+ ASSERT_TRUE(ASN1_BIT_STRING_num_bytes(sig, &sig_len));
+ EVP_PKEY_CTX* pctx;
+ bssl::ScopedEVP_MD_CTX ctx;
+ ASSERT_TRUE(EVP_DigestVerifyInit(ctx.get(), &pctx, evp_digest, nullptr, pubkey.get()));
+ ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING));
+ // The salt length should match the digest length.
+ ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1));
+ EXPECT_TRUE(EVP_DigestVerify(ctx.get(), ASN1_STRING_get0_data(sig), sig_len, tbs, tbs_len));
+}
+
INSTANTIATE_TEST_SUITE_P(CertSigningWithCallbackRsa, CertificateUtilsWithRsa,
testing::Combine(testing::ValuesIn(rsa_key_sizes),
testing::ValuesIn(rsa_paddings),
@@ -315,10 +380,10 @@
EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
if ((padding == Padding::PSS) && (digest == Digest::SHA1 || digest == Digest::SHA224)) {
// BoringSSL after https://boringssl-review.googlesource.com/c/boringssl/+/53865
- // does not support these PSS combinations, so skip certificate verification for them
- // and just check _something_ was returned.
+ // does not support these PSS combinations, so verify these certificates manually.
EXPECT_NE(decoded_cert.get(), nullptr);
EXPECT_NE(decoded_pkey.get(), nullptr);
+ verifyCertFieldsExplicitly(decoded_cert.get(), digest);
} else {
ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
}
diff --git a/prng_seeder/Android.bp b/prng_seeder/Android.bp
index 4f9b7e1..b56a405 100644
--- a/prng_seeder/Android.bp
+++ b/prng_seeder/Android.bp
@@ -19,19 +19,6 @@
default_applicable_licenses: ["system_security_license"],
}
-rust_bindgen {
- name: "libcutils_socket_bindgen",
- crate_name: "cutils_socket_bindgen",
- wrapper_src: "cutils_wrapper.h",
- source_stem: "bindings",
- bindgen_flags: [
- "--allowlist-function=android_get_control_socket",
- ],
- shared_libs: [
- "libcutils",
- ],
-}
-
rust_defaults {
name: "prng_seeder_defaults",
edition: "2021",
@@ -39,10 +26,10 @@
"libanyhow",
"libbssl_sys",
"libclap",
- "libcutils_socket_bindgen",
"liblogger",
"liblog_rust",
"libnix",
+ "librustutils",
"libtokio",
],
@@ -73,10 +60,10 @@
"libanyhow",
"libbssl_sys",
"libclap",
- "libcutils_socket_bindgen",
"liblogger",
"liblog_rust",
"libnix",
+ "librustutils",
"libtokio",
],
test_suites: ["general-tests"],
diff --git a/prng_seeder/cutils_wrapper.h b/prng_seeder/cutils_wrapper.h
deleted file mode 100644
index 9c1fe56..0000000
--- a/prng_seeder/cutils_wrapper.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <cutils/sockets.h>
diff --git a/prng_seeder/src/cutils_socket.rs b/prng_seeder/src/cutils_socket.rs
deleted file mode 100644
index b408be6..0000000
--- a/prng_seeder/src/cutils_socket.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::ffi::CString;
-use std::os::unix::{net::UnixListener, prelude::FromRawFd};
-
-use anyhow::{ensure, Result};
-
-pub fn android_get_control_socket(name: &str) -> Result<UnixListener> {
- let name = CString::new(name)?;
- // SAFETY: name is a valid C string, and android_get_control_socket doesn't retain it after it
- // returns.
- let fd = unsafe { cutils_socket_bindgen::android_get_control_socket(name.as_ptr()) };
- ensure!(fd >= 0, "android_get_control_socket failed");
- // SAFETY: android_get_control_socket either returns a valid and open FD or -1, and we checked
- // that it's not -1.
- Ok(unsafe { UnixListener::from_raw_fd(fd) })
-}
diff --git a/prng_seeder/src/main.rs b/prng_seeder/src/main.rs
index cb7f38d..d112d61 100644
--- a/prng_seeder/src/main.rs
+++ b/prng_seeder/src/main.rs
@@ -18,7 +18,6 @@
//! by init.
mod conditioner;
-mod cutils_socket;
mod drbg;
use std::{
@@ -70,6 +69,9 @@
}
fn setup() -> Result<(ConditionerBuilder, UnixListener)> {
+ // SAFETY: nobody has taken ownership of the inherited FDs yet.
+ unsafe { rustutils::inherited_fd::init_once() }
+ .context("In setup, failed to own inherited FDs")?;
configure_logging()?;
let cli = Cli::try_parse()?;
// SAFETY: Nothing else sets the signal handler, so either it was set here or it is the default.
@@ -78,8 +80,9 @@
let listener = match cli.socket {
Some(path) => get_socket(path.as_path())?,
- None => cutils_socket::android_get_control_socket("prng_seeder")
- .context("In setup, calling android_get_control_socket")?,
+ None => rustutils::sockets::android_get_control_socket("prng_seeder")
+ .context("In setup, calling android_get_control_socket")?
+ .into(),
};
let hwrng = std::fs::File::open(&cli.source)
.with_context(|| format!("Unable to open hwrng {}", cli.source.display()))?;