summaryrefslogtreecommitdiffstats
path: root/keymaster0_engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'keymaster0_engine.cpp')
-rw-r--r--keymaster0_engine.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/keymaster0_engine.cpp b/keymaster0_engine.cpp
index 995bc0b..70987f9 100644
--- a/keymaster0_engine.cpp
+++ b/keymaster0_engine.cpp
@@ -295,6 +295,15 @@ EVP_PKEY* Keymaster0Engine::GetKeymaster0PublicKey(const KeymasterKeyBlob& blob)
return d2i_PUBKEY(nullptr /* allocate new struct */, &p, pub_key_data_length);
}
+static bool data_too_large_for_public_modulus(const uint8_t* data, size_t len, const RSA* rsa) {
+ unique_ptr<BIGNUM, BIGNUM_Delete> input_as_bn(
+ BN_bin2bn(data, len, nullptr /* allocate result */));
+ return input_as_bn && BN_ucmp(input_as_bn.get(), rsa->n) >= 0;
+}
+
+#define USER_F_private_transform 100
+#define USER_F_ecdsa_sign 101
+
int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in,
size_t len) const {
const keymaster_key_blob_t* key_blob = RsaKeyToBlob(rsa);
@@ -306,8 +315,16 @@ int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t*
keymaster_rsa_sign_params_t sign_params = {DIGEST_NONE, PADDING_NONE};
unique_ptr<uint8_t[], Malloc_Delete> signature;
size_t signature_length;
- if (!Keymaster0Sign(&sign_params, *key_blob, in, len, &signature, &signature_length))
+ if (!Keymaster0Sign(&sign_params, *key_blob, in, len, &signature, &signature_length)) {
+ if (data_too_large_for_public_modulus(in, len, rsa)) {
+ ALOGE("Keymaster0 signing failed because data is too large.");
+ OPENSSL_PUT_ERROR(RSA, private_transform, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ } else {
+ // We don't know what error code is correct; force an "unknown error" return
+ OPENSSL_PUT_ERROR(USER, private_transform, KM_ERROR_UNKNOWN_ERROR);
+ }
return 0;
+ }
Eraser eraser(signature.get(), signature_length);
if (signature_length > len) {
@@ -347,8 +364,12 @@ int Keymaster0Engine::EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_
keymaster_ec_sign_params_t sign_params = {DIGEST_NONE};
unique_ptr<uint8_t[], Malloc_Delete> signature;
size_t signature_length;
- if (!Keymaster0Sign(&sign_params, *key_blob, digest, digest_len, &signature, &signature_length))
+ if (!Keymaster0Sign(&sign_params, *key_blob, digest, digest_len, &signature,
+ &signature_length)) {
+ // We don't know what error code is correct; force an "unknown error" return
+ OPENSSL_PUT_ERROR(USER, ecdsa_sign, KM_ERROR_UNKNOWN_ERROR);
return 0;
+ }
Eraser eraser(signature.get(), signature_length);
if (signature_length == 0) {