merge in mnc-release history after reset to mnc-dev
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index 479a2e6..af829e6 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -26,6 +26,7 @@
 
 #include "android_keymaster_test_utils.h"
 #include "keymaster0_engine.h"
+#include "openssl_utils.h"
 
 using std::ifstream;
 using std::istreambuf_iterator;
@@ -701,24 +702,12 @@
                                            .RsaSigningKey(256, 3)
                                            .Digest(KM_DIGEST_NONE)
                                            .Padding(KM_PAD_NONE)));
-    AuthorizationSet begin_params(client_params());
-    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
-    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
-    ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-
     string message = "1234567890123456789012345678901";
-    string result;
-    size_t input_consumed;
-    ASSERT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
-    EXPECT_EQ(0U, result.size());
-    EXPECT_EQ(31U, input_consumed);
-
     string signature;
-    ASSERT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
-    EXPECT_EQ(0U, signature.length());
+    SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
     if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
-        EXPECT_EQ(2, GetParam()->keymaster0_calls());
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) {
@@ -1897,20 +1886,18 @@
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
 
-    string message = "1234567890123456789012345678901";
+    string message = "1";
 
-    AuthorizationSet begin_params(client_params());
-    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
-    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
+    string ciphertext = EncryptMessage(message, KM_PAD_NONE);
+    EXPECT_EQ(256U / 8, ciphertext.size());
 
-    string result;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
-    EXPECT_EQ(0U, result.size());
+    string expected_plaintext = string(256 / 8 - 1, 0) + message;
+    string plaintext = DecryptMessage(ciphertext, KM_PAD_NONE);
+
+    EXPECT_EQ(expected_plaintext, plaintext);
 
     if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
-        EXPECT_EQ(2, GetParam()->keymaster0_calls());
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) {
@@ -1931,6 +1918,49 @@
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
+TEST_P(EncryptionOperationsTest, RsaNoPaddingLargerThanModulus) {
+    ASSERT_EQ(KM_ERROR_OK,
+              GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(256, 3).Padding(KM_PAD_NONE)));
+
+    string exported;
+    ASSERT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &exported));
+
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(exported.data());
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+        d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
+    unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(pkey.get()));
+
+    size_t modulus_len = BN_num_bytes(rsa->n);
+    ASSERT_EQ(256U / 8, modulus_len);
+    unique_ptr<uint8_t> modulus_buf(new uint8_t[modulus_len]);
+    BN_bn2bin(rsa->n, modulus_buf.get());
+
+    // The modulus is too big to encrypt.
+    string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
+
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
+
+    string result;
+    size_t input_consumed;
+    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
+    EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&result));
+
+    // One smaller than the modulus is okay.
+    BN_sub(rsa->n, rsa->n, BN_value_one());
+    modulus_len = BN_num_bytes(rsa->n);
+    ASSERT_EQ(256U / 8, modulus_len);
+    BN_bn2bin(rsa->n, modulus_buf.get());
+    message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
+    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
+
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+}
+
 TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
     size_t key_size = 768;
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
diff --git a/openssl_err.cpp b/openssl_err.cpp
index 2548d5c..51a29d9 100644
--- a/openssl_err.cpp
+++ b/openssl_err.cpp
@@ -151,6 +151,8 @@
     case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
     case RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:
         return KM_ERROR_INVALID_INPUT_LENGTH;
+    case RSA_R_DATA_TOO_LARGE_FOR_MODULUS:
+        return KM_ERROR_INVALID_ARGUMENT;
     default:
         return KM_ERROR_UNKNOWN_ERROR;
     };
diff --git a/rsa_operation.cpp b/rsa_operation.cpp
index 20ef45f..076f333 100644
--- a/rsa_operation.cpp
+++ b/rsa_operation.cpp
@@ -297,6 +297,21 @@
         return SignDigested(output);
 }
 
+static keymaster_error_t zero_pad_left(UniquePtr<uint8_t[]>* dest, size_t padded_len, Buffer& src) {
+    assert(padded_len > src.available_read());
+
+    dest->reset(new uint8_t[padded_len]);
+    if (!dest->get())
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    size_t padding_len = padded_len - src.available_read();
+    memset(dest->get(), 0, padding_len);
+    if (!src.read(dest->get() + padding_len, src.available_read()))
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    return KM_ERROR_OK;
+}
+
 keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
     UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
     if (!rsa.get())
@@ -305,16 +320,27 @@
     if (!output->Reinitialize(RSA_size(rsa.get())))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
+    size_t key_len = EVP_PKEY_size(rsa_key_);
     int bytes_encrypted;
     switch (padding_) {
-    case KM_PAD_NONE:
-        bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
-                                              output->peek_write(), rsa.get(), RSA_NO_PADDING);
+    case KM_PAD_NONE: {
+        const uint8_t* to_encrypt = data_.peek_read();
+        UniquePtr<uint8_t[]> zero_padded;
+        if (data_.available_read() > key_len) {
+            return KM_ERROR_INVALID_INPUT_LENGTH;
+        } else if (data_.available_read() < key_len) {
+            keymaster_error_t error = zero_pad_left(&zero_padded, key_len, data_);
+            if (error != KM_ERROR_OK)
+                return error;
+            to_encrypt = zero_padded.get();
+        }
+        bytes_encrypted = RSA_private_encrypt(key_len, to_encrypt, output->peek_write(), rsa.get(),
+                                              RSA_NO_PADDING);
         break;
+    }
     case KM_PAD_RSA_PKCS1_1_5_SIGN:
         // Does PKCS1 padding without digesting even make sense?  Dunno.  We'll support it.
-        if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead >
-            static_cast<size_t>(EVP_PKEY_size(rsa_key_))) {
+        if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
             LOG_E("Input too long: cannot sign %u-byte message with PKCS1 padding with %u-bit key",
                   data_.available_read(), EVP_PKEY_size(rsa_key_) * 8);
             return KM_ERROR_INVALID_INPUT_LENGTH;
@@ -322,6 +348,7 @@
         bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
                                               output->peek_write(), rsa.get(), RSA_PKCS1_PADDING);
         break;
+
     default:
         return KM_ERROR_UNSUPPORTED_PADDING_MODE;
     }
@@ -397,9 +424,9 @@
     int openssl_padding;
     switch (padding_) {
     case KM_PAD_NONE:
-        if (data_.available_read() != key_len)
+        if (data_.available_read() > key_len)
             return KM_ERROR_INVALID_INPUT_LENGTH;
-        if (data_.available_read() != signature.available_read())
+        if (key_len != signature.available_read())
             return KM_ERROR_VERIFICATION_FAILED;
         openssl_padding = RSA_NO_PADDING;
         break;
@@ -423,7 +450,19 @@
     if (bytes_decrypted < 0)
         return KM_ERROR_VERIFICATION_FAILED;
 
-    if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) != 0)
+    const uint8_t* compare_pos = decrypted_data.get();
+    size_t bytes_to_compare = bytes_decrypted;
+    uint8_t zero_check_result = 0;
+    if (padding_ == KM_PAD_NONE && data_.available_read() < bytes_to_compare) {
+        // If the data is short, for "unpadded" signing we zero-pad to the left.  So during
+        // verification we should have zeros on the left of the decrypted data.  Do a constant-time
+        // check.
+        const uint8_t* zero_end = compare_pos + bytes_to_compare - data_.available_read();
+        while (compare_pos < zero_end)
+            zero_check_result |= *compare_pos++;
+        bytes_to_compare = data_.available_read();
+    }
+    if (memcmp_s(compare_pos, data_.peek_read(), bytes_to_compare) != 0 || zero_check_result != 0)
         return KM_ERROR_VERIFICATION_FAILED;
     return KM_ERROR_OK;
 }
@@ -496,8 +535,18 @@
     if (!output->Reinitialize(outlen))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
-    if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, data_.peek_read(),
-                         data_.available_read()) <= 0)
+    const uint8_t* to_encrypt = data_.peek_read();
+    size_t to_encrypt_len = data_.available_read();
+    UniquePtr<uint8_t[]> zero_padded;
+    if (padding_ == KM_PAD_NONE && to_encrypt_len < outlen) {
+        keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
+        if (error != KM_ERROR_OK)
+            return error;
+        to_encrypt = zero_padded.get();
+        to_encrypt_len = outlen;
+    }
+
+    if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, to_encrypt, to_encrypt_len) <= 0)
         return TranslateLastOpenSslError();
     if (!output->advance_write(outlen))
         return KM_ERROR_UNKNOWN_ERROR;
@@ -534,8 +583,18 @@
     if (!output->Reinitialize(outlen))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
-    if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, data_.peek_read(),
-                         data_.available_read()) <= 0)
+    const uint8_t* to_decrypt = data_.peek_read();
+    size_t to_decrypt_len = data_.available_read();
+    UniquePtr<uint8_t[]> zero_padded;
+    if (padding_ == KM_PAD_NONE && to_decrypt_len < outlen) {
+        keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
+        if (error != KM_ERROR_OK)
+            return error;
+        to_decrypt = zero_padded.get();
+        to_decrypt_len = outlen;
+    }
+
+    if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, to_decrypt, to_decrypt_len) <= 0)
         return TranslateLastOpenSslError();
     if (!output->advance_write(outlen))
         return KM_ERROR_UNKNOWN_ERROR;