Merge pull request #287 from rayman42003:master

PiperOrigin-RevId: 282425118
diff --git a/java/src/main/java/com/google/crypto/tink/subtle/AesSiv.java b/java/src/main/java/com/google/crypto/tink/subtle/AesSiv.java
index 621883a..1487760 100644
--- a/java/src/main/java/com/google/crypto/tink/subtle/AesSiv.java
+++ b/java/src/main/java/com/google/crypto/tink/subtle/AesSiv.java
@@ -76,7 +76,13 @@
 
     byte[] result = cmacForS2V.computeMac(BLOCK_ZERO);
     for (int i = 0; i < s.length - 1; i++) {
-      result = Bytes.xor(AesUtil.dbl(result), cmacForS2V.computeMac(s[i]));
+      final byte[] currBlock;
+      if (s[i] == null) {
+        currBlock = new byte[0];
+      } else {
+        currBlock = s[i];
+      }
+      result = Bytes.xor(AesUtil.dbl(result), cmacForS2V.computeMac(currBlock));
     }
     byte[] lastBlock = s[s.length - 1];
     if (lastBlock.length >= 16) {
diff --git a/java/src/test/java/com/google/crypto/tink/subtle/AesSivTest.java b/java/src/test/java/com/google/crypto/tink/subtle/AesSivTest.java
index a0fc532..9ecb39b 100644
--- a/java/src/test/java/com/google/crypto/tink/subtle/AesSivTest.java
+++ b/java/src/test/java/com/google/crypto/tink/subtle/AesSivTest.java
@@ -144,6 +144,56 @@
   }
 
   @Test
+  public void testEncryptDecryptWithNullAssociatedData() throws GeneralSecurityException {
+    for (int keySize : keySizeInBytes) {
+      DeterministicAead dead = new AesSiv(Random.randBytes(keySize));
+      for (int triesPlaintext = 0; triesPlaintext < 100; triesPlaintext++) {
+        byte[] plaintext = Random.randBytes(Random.randInt(1024) + 1);
+        byte[] rebuiltPlaintext =
+            dead.decryptDeterministically(dead.encryptDeterministically(plaintext, null), null);
+        assertEquals(Hex.encode(plaintext), Hex.encode(rebuiltPlaintext));
+      }
+    }
+  }
+
+  @Test
+  public void testEncryptDecryptWithNullAndEmptyAssociatedDataEquivalent()
+      throws GeneralSecurityException {
+    for (int keySize : keySizeInBytes) {
+      DeterministicAead dead = new AesSiv(Random.randBytes(keySize));
+      for (int triesPlaintext = 0; triesPlaintext < 100; triesPlaintext++) {
+        byte[] plaintext = Random.randBytes(Random.randInt(1024) + 1);
+        byte[] emptyAad = new byte[0];
+        byte[] emptyAadCiphertext = dead.encryptDeterministically(plaintext, emptyAad);
+        byte[] emptyAadRebuiltPlaintext =
+                dead.decryptDeterministically(emptyAadCiphertext, emptyAad);
+
+        byte[] nullAadCipherText = dead.encryptDeterministically(plaintext, null);
+        byte[] nullAadRebuiltPlaintext =
+                dead.decryptDeterministically(nullAadCipherText, null);
+        
+        assertEquals(Hex.encode(plaintext), Hex.encode(emptyAadRebuiltPlaintext));
+        assertEquals(Hex.encode(plaintext), Hex.encode(nullAadRebuiltPlaintext));
+        assertEquals(Hex.encode(emptyAadCiphertext), Hex.encode(nullAadCipherText));
+      }
+    }
+  }
+
+  @Test
+  public void testEncryptDecryptWithEmptyPlaintextAndNullAssociatedData()
+      throws GeneralSecurityException {
+    for (int keySize : keySizeInBytes) {
+      DeterministicAead dead = new AesSiv(Random.randBytes(keySize));
+      for (int triesPlaintext = 0; triesPlaintext < 100; triesPlaintext++) {
+        byte[] plaintext = new byte[0];
+        byte[] rebuiltPlaintext =
+                dead.decryptDeterministically(dead.encryptDeterministically(plaintext, null), null);
+        assertEquals(Hex.encode(plaintext), Hex.encode(rebuiltPlaintext));
+      }
+    }
+  }
+
+  @Test
   public void testEncryptDecrypt() throws GeneralSecurityException {
     for (int keySize : keySizeInBytes) {
       DeterministicAead dead = new AesSiv(Random.randBytes(keySize));