• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.subtle;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.prf.Prf;
24 import com.google.crypto.tink.prf.internal.AesCmacPrfTestUtil;
25 import com.google.crypto.tink.prf.internal.AesCmacPrfWycheproofTestUtil;
26 import java.security.InvalidAlgorithmParameterException;
27 import java.util.Arrays;
28 import java.util.List;
29 import org.junit.experimental.theories.DataPoints;
30 import org.junit.experimental.theories.FromDataPoints;
31 import org.junit.experimental.theories.Theories;
32 import org.junit.experimental.theories.Theory;
33 import org.junit.runner.RunWith;
34 
35 /** Unit tests for {@link PrfAesCmac}. */
36 @RunWith(Theories.class)
37 public class PrfAesCmacTest {
38 
39   private static final int KEY_SIZE = 16;
40 
41   @DataPoints("AesCmacPrfTestVectors")
42   public static final List<AesCmacPrfTestUtil.TestVector> testVectors =
43       AesCmacPrfTestUtil.creatTestVectors();
44 
45   @DataPoints("WycheproofTestVectors")
46   public static final List<AesCmacPrfTestUtil.TestVector> wycheproofTestVectors =
47       AesCmacPrfWycheproofTestUtil.readTestVectors();
48 
49   @Theory
calcN_returnsNumberOfAesBlocks()50   public void calcN_returnsNumberOfAesBlocks() throws Exception {
51     // AES block size is 16 bytes.
52     assertThat(PrfAesCmac.calcN(0)).isEqualTo(1);
53     assertThat(PrfAesCmac.calcN(1)).isEqualTo(1);
54     assertThat(PrfAesCmac.calcN(16)).isEqualTo(1);
55     assertThat(PrfAesCmac.calcN(17)).isEqualTo(2);
56     assertThat(PrfAesCmac.calcN(32)).isEqualTo(2);
57     assertThat(PrfAesCmac.calcN(33)).isEqualTo(3);
58     assertThat(PrfAesCmac.calcN(48)).isEqualTo(3);
59     assertThat(PrfAesCmac.calcN(49)).isEqualTo(4);
60     assertThat(PrfAesCmac.calcN(0x7FFFFFF0)).isEqualTo(0x07FFFFFF);
61     assertThat(PrfAesCmac.calcN(0x7FFFFFF1)).isEqualTo(0x08000000);
62     assertThat(PrfAesCmac.calcN(Integer.MAX_VALUE)).isEqualTo(0x08000000);
63   }
64 
65   @Theory
compute_isCorrect( @romDataPoints"AesCmacPrfTestVectors") AesCmacPrfTestUtil.TestVector testVector)66   public void compute_isCorrect(
67       @FromDataPoints("AesCmacPrfTestVectors") AesCmacPrfTestUtil.TestVector testVector)
68       throws Exception {
69     Prf prf =
70         new PrfAesCmac(testVector.key().getKeyBytes().toByteArray(InsecureSecretKeyAccess.get()));
71 
72     assertThat(prf.compute(testVector.data(), testVector.outputLength())).isEqualTo(testVector.output());
73   }
74 
75   @Theory
createWithAesCmacPrfKey_compute_isCorrect( @romDataPoints"AesCmacPrfTestVectors") AesCmacPrfTestUtil.TestVector testVector)76   public void createWithAesCmacPrfKey_compute_isCorrect(
77       @FromDataPoints("AesCmacPrfTestVectors") AesCmacPrfTestUtil.TestVector testVector)
78       throws Exception {
79     Prf prf = PrfAesCmac.create(testVector.key());
80 
81     assertThat(prf.compute(testVector.data(), testVector.outputLength())).isEqualTo(testVector.output());
82   }
83 
84   @Theory
wycheproofTestVectors_compute_isCorrect( @romDataPoints"WycheproofTestVectors") AesCmacPrfTestUtil.TestVector testVector)85   public void wycheproofTestVectors_compute_isCorrect(
86       @FromDataPoints("WycheproofTestVectors") AesCmacPrfTestUtil.TestVector testVector)
87       throws Exception {
88     Prf prf = PrfAesCmac.create(testVector.key());
89 
90     assertThat(prf.compute(testVector.data(), testVector.outputLength()))
91         .isEqualTo(testVector.output());
92   }
93 
94   @Theory
compute_outputLengthTooLarge_throws()95   public void compute_outputLengthTooLarge_throws() throws Exception {
96     Prf prf = new PrfAesCmac(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c"));
97     byte[] message = new byte[0];
98 
99     assertThrows(InvalidAlgorithmParameterException.class, () -> prf.compute(message, 17));
100   }
101 
102   @Theory
compute_bitFlipInMessage_outputIsDifferent()103   public void compute_bitFlipInMessage_outputIsDifferent() throws Exception {
104     byte[] key = Random.randBytes(KEY_SIZE);
105     Prf prf = new PrfAesCmac(key);
106     byte[] message = Random.randBytes(20);
107     int outputLength = 16;
108 
109     byte[] output = prf.compute(message, outputLength);
110 
111     for (int b = 0; b < message.length; b++) {
112       for (int bit = 0; bit < 8; bit++) {
113         byte[] modifiedMessage = Arrays.copyOf(message, message.length);
114         modifiedMessage[b] = (byte) (modifiedMessage[b] ^ (1 << bit));
115 
116         byte[] outputOfModifiedMessage = prf.compute(modifiedMessage, outputLength);
117 
118         assertThat(outputOfModifiedMessage).isNotEqualTo(output);
119       }
120     }
121   }
122 }
123