1 // Copyright 2023 Google LLC 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 import static org.junit.Assume.assumeTrue; 22 23 import com.google.crypto.tink.Mac; 24 import com.google.crypto.tink.config.TinkFips; 25 import com.google.crypto.tink.config.internal.TinkFipsUtil; 26 import com.google.crypto.tink.mac.internal.AesCmacTestUtil; 27 import com.google.crypto.tink.mac.internal.AesCmacTestUtil.AesCmacTestVector; 28 import com.google.crypto.tink.mac.internal.HmacTestUtil; 29 import com.google.crypto.tink.mac.internal.HmacTestUtil.HmacTestVector; 30 import java.security.GeneralSecurityException; 31 import java.security.Security; 32 import java.util.Arrays; 33 import org.conscrypt.Conscrypt; 34 import org.junit.Assume; 35 import org.junit.BeforeClass; 36 import org.junit.experimental.theories.DataPoints; 37 import org.junit.experimental.theories.FromDataPoints; 38 import org.junit.experimental.theories.Theories; 39 import org.junit.experimental.theories.Theory; 40 import org.junit.runner.RunWith; 41 42 @RunWith(Theories.class) 43 public class PrfMacTest { 44 @BeforeClass setUp()45 public static void setUp() throws Exception { 46 // If Tink is built in FIPS-only mode, register Conscrypt for the tests. 47 if (TinkFips.useOnlyFips()) { 48 try { 49 Conscrypt.checkAvailability(); 50 Security.addProvider(Conscrypt.newProvider()); 51 } catch (Throwable cause) { 52 throw new IllegalStateException( 53 "Cannot test HMAC in FIPS-mode without Conscrypt Provider", cause); 54 } 55 } 56 57 hmacImplementationTestVectors = 58 Arrays.copyOf( 59 HmacTestUtil.HMAC_TEST_VECTORS, 60 HmacTestUtil.HMAC_TEST_VECTORS.length + HmacTestUtil.PREFIXED_KEY_TYPES.length); 61 System.arraycopy( 62 HmacTestUtil.PREFIXED_KEY_TYPES, 63 0, 64 hmacImplementationTestVectors, 65 HmacTestUtil.HMAC_TEST_VECTORS.length, 66 HmacTestUtil.PREFIXED_KEY_TYPES.length); 67 } 68 69 @DataPoints("allAesCmacTestVectors") 70 public static final AesCmacTestVector[] CMAC_IMPLEMENTATION_TEST_VECTORS = 71 new AesCmacTestVector[] { 72 AesCmacTestUtil.RFC_TEST_VECTOR_0, 73 AesCmacTestUtil.RFC_TEST_VECTOR_1, 74 AesCmacTestUtil.RFC_TEST_VECTOR_2, 75 AesCmacTestUtil.NOT_OVERFLOWING_INTERNAL_STATE, 76 AesCmacTestUtil.FILL_UP_EXACTLY_INTERNAL_STATE, 77 AesCmacTestUtil.FILL_UP_EXACTLY_INTERNAL_STATE_TWICE, 78 AesCmacTestUtil.OVERFLOW_INTERNAL_STATE_ONCE, 79 AesCmacTestUtil.OVERFLOW_INTERNAL_STATE_TWICE, 80 AesCmacTestUtil.SHORTER_TAG, 81 AesCmacTestUtil.TAG_WITH_KEY_PREFIX_TYPE_LEGACY, 82 AesCmacTestUtil.TAG_WITH_KEY_PREFIX_TYPE_TINK, 83 AesCmacTestUtil.LONG_KEY_TEST_VECTOR, 84 }; 85 86 @DataPoints("failingAesCmacTestVectors") 87 public static final AesCmacTestVector[] CMAC_FAILING_TEST_VECTORS = 88 new AesCmacTestVector[] { 89 AesCmacTestUtil.WRONG_PREFIX_TAG_LEGACY, 90 AesCmacTestUtil.WRONG_PREFIX_TAG_TINK, 91 AesCmacTestUtil.TAG_TOO_SHORT 92 }; 93 94 @DataPoints("failingHmacTestVectors") 95 public static final HmacTestVector[] HMAC_FAILING_TEST_VECTORS = 96 HmacTestUtil.CREATE_VERIFICATION_FAILS_FAST; 97 98 @DataPoints("allHmacTestVectors") 99 public static HmacTestVector[] hmacImplementationTestVectors; 100 101 @Theory computeAesCmac_isCorrect(@romDataPoints"allAesCmacTestVectors") AesCmacTestVector t)102 public void computeAesCmac_isCorrect(@FromDataPoints("allAesCmacTestVectors") AesCmacTestVector t) 103 throws Exception { 104 Assume.assumeFalse(TinkFips.useOnlyFips()); 105 106 Mac aesCmac = PrfMac.create(t.key); 107 108 assertThat(aesCmac.computeMac(t.message)).isEqualTo(t.tag); 109 } 110 111 @Theory verifyAesCmac_isCorrect(@romDataPoints"allAesCmacTestVectors") AesCmacTestVector t)112 public void verifyAesCmac_isCorrect(@FromDataPoints("allAesCmacTestVectors") AesCmacTestVector t) 113 throws Exception { 114 Assume.assumeFalse(TinkFips.useOnlyFips()); 115 116 Mac aesCmac = PrfMac.create(t.key); 117 118 aesCmac.verifyMac(t.tag, t.message); 119 } 120 121 @Theory verifyAesCmac_throwsOnWrongTag( @romDataPoints"failingAesCmacTestVectors") AesCmacTestVector t)122 public void verifyAesCmac_throwsOnWrongTag( 123 @FromDataPoints("failingAesCmacTestVectors") AesCmacTestVector t) throws Exception { 124 Assume.assumeFalse(TinkFips.useOnlyFips()); 125 126 Mac aesCmac = PrfMac.create(t.key); 127 128 assertThrows(GeneralSecurityException.class, () -> aesCmac.verifyMac(t.tag, t.message)); 129 } 130 131 @Theory computeHmac_isCorrect(@romDataPoints"allHmacTestVectors") HmacTestVector t)132 public void computeHmac_isCorrect(@FromDataPoints("allHmacTestVectors") HmacTestVector t) 133 throws Exception { 134 assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable()); 135 136 Mac hmac = PrfMac.create(t.key); 137 138 assertThat(hmac.computeMac(t.message)).isEqualTo(t.tag); 139 } 140 141 @Theory verifyHmac_isCorrect(@romDataPoints"allHmacTestVectors") HmacTestVector t)142 public void verifyHmac_isCorrect(@FromDataPoints("allHmacTestVectors") HmacTestVector t) 143 throws Exception { 144 assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable()); 145 146 Mac hmac = PrfMac.create(t.key); 147 148 hmac.verifyMac(t.tag, t.message); 149 } 150 151 @Theory verifyHmac_throwsOnWrongTag( @romDataPoints"failingHmacTestVectors") HmacTestVector t)152 public void verifyHmac_throwsOnWrongTag( 153 @FromDataPoints("failingHmacTestVectors") HmacTestVector t) throws Exception { 154 assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable()); 155 156 Mac hmac = PrfMac.create(t.key); 157 158 assertThrows(GeneralSecurityException.class, () -> hmac.verifyMac(t.tag, t.message)); 159 } 160 } 161