ECIES: implement KM_MODE_CTR. This implementation is rand counter-mode.
When encrypting, if the caller doesn't specify the IV, Keymaster will
randomly generate a 16-byte IV.

Change-Id: I9096b83ca38be161b60b398271c99bc11e804b52
diff --git a/aes_operation.cpp b/aes_operation.cpp
index 79ba248..aab185c 100644
--- a/aes_operation.cpp
+++ b/aes_operation.cpp
@@ -87,6 +87,12 @@
     case KM_MODE_ECB:
     case KM_MODE_CBC:
         return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
+    case KM_MODE_CTR:
+        if (padding != KM_PAD_NONE) {
+            *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
+            return NULL;
+        }
+        return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
     default:
         *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
         return NULL;
@@ -145,7 +151,7 @@
 }
 
 static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_OCB, KM_MODE_ECB,
-                                                               KM_MODE_CBC};
+                                                               KM_MODE_CBC, KM_MODE_CTR};
 
 const keymaster_block_mode_t*
 AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
@@ -276,6 +282,21 @@
             return KM_ERROR_UNSUPPORTED_KEY_SIZE;
         }
         break;
+    case KM_MODE_CTR:
+        switch (key_size_) {
+        case 16:
+            cipher = EVP_aes_128_ctr();
+            break;
+        case 24:
+            cipher = EVP_aes_192_ctr();
+            break;
+        case 32:
+            cipher = EVP_aes_256_ctr();
+            break;
+        default:
+            return KM_ERROR_UNSUPPORTED_KEY_SIZE;
+        }
+        break;
     default:
         return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
     }
@@ -303,6 +324,7 @@
 bool AesEvpOperation::need_iv() const {
     switch (block_mode_) {
     case KM_MODE_CBC:
+    case KM_MODE_CTR:
         return true;
     case KM_MODE_ECB:
         return false;
@@ -359,7 +381,7 @@
     if (iv_blob.data_length != AES_BLOCK_SIZE) {
         LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
               iv_blob.data_length);
-        return KM_ERROR_INVALID_ARGUMENT;
+        return KM_ERROR_INVALID_NONCE;
     }
     iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
     if (!iv_.get())
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 154ad11..7284377 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -103,7 +103,7 @@
 
     EXPECT_EQ(KM_ERROR_OK, device()->get_supported_block_modes(device(), KM_ALGORITHM_AES,
                                                                KM_PURPOSE_ENCRYPT, &modes, &len));
-    EXPECT_TRUE(ResponseContains({KM_MODE_OCB, KM_MODE_ECB, KM_MODE_CBC}, modes, len));
+    EXPECT_TRUE(ResponseContains({KM_MODE_OCB, KM_MODE_ECB, KM_MODE_CBC, KM_MODE_CTR}, modes, len));
     free(modes);
 }
 
@@ -1853,6 +1853,130 @@
     EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&plaintext));
 }
 
+TEST_F(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
+    ASSERT_EQ(KM_ERROR_OK,
+              GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128).Authorization(
+                  TAG_BLOCK_MODE, KM_MODE_CTR)));
+    string message = "123";
+    string iv1;
+    string ciphertext1 = EncryptMessage(message, &iv1);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+    EXPECT_EQ(16, iv1.size());
+
+    string iv2;
+    string ciphertext2 = EncryptMessage(message, &iv2);
+    EXPECT_EQ(message.size(), ciphertext2.size());
+    EXPECT_EQ(16, iv2.size());
+
+    // IVs should be random, so ciphertexts should differ.
+    EXPECT_NE(iv1, iv2);
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    string plaintext = DecryptMessage(ciphertext1, iv1);
+    EXPECT_EQ(message, plaintext);
+}
+
+TEST_F(EncryptionOperationsTest, AesCtrIncremental) {
+    ASSERT_EQ(KM_ERROR_OK,
+              GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128).Authorization(
+                  TAG_BLOCK_MODE, KM_MODE_CTR)));
+
+    int increment = 15;
+    string message(239, 'a');
+    AuthorizationSet input_params;
+    AuthorizationSet output_params;
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
+
+    string ciphertext;
+    size_t input_consumed;
+    for (size_t i = 0; i < message.size(); i += increment)
+        EXPECT_EQ(KM_ERROR_OK,
+                  UpdateOperation(message.substr(i, increment), &ciphertext, &input_consumed));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(&ciphertext));
+    EXPECT_EQ(message.size(), ciphertext.size());
+
+    // Move TAG_NONCE into input_params
+    input_params.Reinitialize(output_params);
+    output_params.Clear();
+
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, input_params, &output_params));
+    string plaintext;
+    for (size_t i = 0; i < ciphertext.size(); i += increment)
+        EXPECT_EQ(KM_ERROR_OK,
+                  UpdateOperation(ciphertext.substr(i, increment), &plaintext, &input_consumed));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
+    EXPECT_EQ(ciphertext.size(), plaintext.size());
+    EXPECT_EQ(message, plaintext);
+}
+
+struct AesCtrSp80038aTestVector {
+    const char* key;
+    const char* nonce;
+    const char* plaintext;
+    const char* ciphertext;
+};
+
+// These test vectors are taken from
+// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section F.5.
+static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = {
+    // AES-128
+    {
+        "2b7e151628aed2a6abf7158809cf4f3c", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"
+        "5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee",
+    },
+    // AES-192
+    {
+        "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94"
+        "1e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050",
+    },
+    // AES-256
+    {
+        "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
+        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5"
+        "2b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6",
+    },
+};
+
+TEST_F(EncryptionOperationsTest, AesCtrSp80038aTestVector) {
+    for (size_t i = 0; i < 3; i++) {
+        const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]);
+        const string key = hex2str(test.key);
+        const string nonce = hex2str(test.nonce);
+        const string plaintext = hex2str(test.plaintext);
+        const string ciphertext = hex2str(test.ciphertext);
+        CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
+    }
+}
+
+TEST_F(EncryptionOperationsTest, AesCtrInvalidPaddingMode) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .AesEncryptionKey(128)
+                                           .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
+                                           .Authorization(TAG_PADDING, KM_PAD_PKCS7)));
+
+    EXPECT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_ENCRYPT));
+}
+
+TEST_F(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .AesEncryptionKey(128)
+                                           .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
+                                           .Authorization(TAG_CALLER_NONCE)));
+
+    AuthorizationSet input_params;
+    input_params.push_back(TAG_NONCE, "123", 3);
+    EXPECT_EQ(KM_ERROR_INVALID_NONCE, BeginOperation(KM_PURPOSE_ENCRYPT, input_params));
+}
+
 TEST_F(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128).Authorization(
diff --git a/google_keymaster_test_utils.cpp b/google_keymaster_test_utils.cpp
index 664e020..7f39478 100644
--- a/google_keymaster_test_utils.cpp
+++ b/google_keymaster_test_utils.cpp
@@ -100,27 +100,22 @@
 }
 
 static char hex_value[256] = {
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  1,  2,  3,  4,  5,  6, 7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 1,  2,  3,  4,  5,  6,  7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'
     0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'A'..'F'
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'a'..'f'
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0,
+    0, 0,  0,  0,  0,  0,  0,  0,  // 'a'..'f'
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,
+    0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0};
 
 string hex2str(string a) {
     string b;
-    size_t num = a.size()/2;
+    size_t num = a.size() / 2;
     b.resize(num);
     for (size_t i = 0; i < num; i++) {
         b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
@@ -458,6 +453,22 @@
     EXPECT_EQ(expected_ciphertext, ciphertext);
 }
 
+void Keymaster1Test::CheckAesCtrTestVector(const string& key, const string& nonce,
+                                           const string& message,
+                                           const string& expected_ciphertext) {
+    ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
+                                         .AesEncryptionKey(key.size() * 8)
+                                         .Authorization(TAG_BLOCK_MODE, KM_MODE_CTR)
+                                         .Authorization(TAG_CALLER_NONCE),
+                                     KM_KEY_FORMAT_RAW, key));
+
+    AuthorizationSet begin_params, update_params, output_params;
+    begin_params.push_back(TAG_NONCE, nonce.data(), nonce.size());
+    string ciphertext =
+        EncryptMessageWithParams(message, begin_params, update_params, &output_params);
+    EXPECT_EQ(expected_ciphertext, ciphertext);
+}
+
 AuthorizationSet Keymaster1Test::hw_enforced() {
     EXPECT_TRUE(characteristics_ != NULL);
     return AuthorizationSet(characteristics_->hw_enforced);
diff --git a/google_keymaster_test_utils.h b/google_keymaster_test_utils.h
index 97c90dc..6e2444f 100644
--- a/google_keymaster_test_utils.h
+++ b/google_keymaster_test_utils.h
@@ -215,7 +215,8 @@
     void CheckAesOcbTestVector(const std::string& key, const std::string& nonce,
                                const std::string& associated_data, const std::string& message,
                                const std::string& expected_ciphertext);
-
+    void CheckAesCtrTestVector(const std::string& key, const std::string& nonce,
+                               const std::string& message, const std::string& expected_ciphertext);
     AuthorizationSet UserAuthParams();
     AuthorizationSet ClientParams();