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 15import os 16import random 17 18from absl.testing import absltest 19from absl.testing import parameterized 20import tink 21 22from tink.proto import common_pb2 23from tink.proto import hmac_pb2 24from tink.proto import tink_pb2 25import tink_config 26from util import testing_servers 27 28 29def setUpModule(): 30 tink.mac.register() 31 testing_servers.start('aes_ctr_hmac_streaming_key_test') 32 33 34def tearDownModule(): 35 testing_servers.stop() 36 37 38def to_keyset( 39 key: hmac_pb2.HmacKey, output_prefix_type: tink_pb2.OutputPrefixType 40) -> tink_pb2.Keyset: 41 """Embeds a HmacKey with the output_prefix_type in a keyset.""" 42 return tink_pb2.Keyset( 43 primary_key_id=1234, 44 key=[ 45 tink_pb2.Keyset.Key( 46 key_data=tink_pb2.KeyData( 47 type_url='type.googleapis.com/google.crypto.tink.HmacKey', 48 value=key.SerializeToString(), 49 key_material_type='SYMMETRIC', 50 ), 51 output_prefix_type=output_prefix_type, 52 status=tink_pb2.KeyStatusType.ENABLED, 53 key_id=1234, 54 ) 55 ], 56 ) 57 58 59def valid_keys(): 60 return [ 61 # Try SHA1 tag sizes 62 hmac_pb2.HmacKey( 63 version=0, 64 key_value=os.urandom(16), 65 params=hmac_pb2.HmacParams( 66 hash=common_pb2.HashType.SHA1, tag_size=10 67 ), 68 ), 69 hmac_pb2.HmacKey( 70 version=0, 71 key_value=os.urandom(16), 72 params=hmac_pb2.HmacParams( 73 hash=common_pb2.HashType.SHA1, tag_size=15 74 ), 75 ), 76 hmac_pb2.HmacKey( 77 version=0, 78 key_value=os.urandom(16), 79 params=hmac_pb2.HmacParams( 80 hash=common_pb2.HashType.SHA1, tag_size=20 81 ), 82 ), 83 # Try SHA1 key sizes 84 hmac_pb2.HmacKey( 85 version=0, 86 key_value=os.urandom(16), 87 params=hmac_pb2.HmacParams( 88 hash=common_pb2.HashType.SHA1, tag_size=10 89 ), 90 ), 91 hmac_pb2.HmacKey( 92 version=0, 93 key_value=os.urandom(17), 94 params=hmac_pb2.HmacParams( 95 hash=common_pb2.HashType.SHA1, tag_size=10 96 ), 97 ), 98 hmac_pb2.HmacKey( 99 version=0, 100 key_value=os.urandom(30), 101 params=hmac_pb2.HmacParams( 102 hash=common_pb2.HashType.SHA1, tag_size=10 103 ), 104 ), 105 # Very large key 106 hmac_pb2.HmacKey( 107 version=0, 108 key_value=os.urandom(1274), 109 params=hmac_pb2.HmacParams( 110 hash=common_pb2.HashType.SHA1, tag_size=10 111 ), 112 ), 113 # Different hash functions, min tag & key size. 114 hmac_pb2.HmacKey( 115 version=0, 116 key_value=os.urandom(16), 117 params=hmac_pb2.HmacParams( 118 hash=common_pb2.HashType.SHA224, tag_size=10 119 ), 120 ), 121 hmac_pb2.HmacKey( 122 version=0, 123 key_value=os.urandom(16), 124 params=hmac_pb2.HmacParams( 125 hash=common_pb2.HashType.SHA256, tag_size=10 126 ), 127 ), 128 hmac_pb2.HmacKey( 129 version=0, 130 key_value=os.urandom(16), 131 params=hmac_pb2.HmacParams( 132 hash=common_pb2.HashType.SHA384, tag_size=10 133 ), 134 ), 135 hmac_pb2.HmacKey( 136 version=0, 137 key_value=os.urandom(16), 138 params=hmac_pb2.HmacParams( 139 hash=common_pb2.HashType.SHA512, tag_size=10 140 ), 141 ), 142 ] 143 144 145def invalid_keys(): 146 return [ 147 # Short key size 148 hmac_pb2.HmacKey( 149 version=0, 150 key_value=os.urandom(9), 151 params=hmac_pb2.HmacParams( 152 hash=common_pb2.HashType.SHA1, tag_size=10 153 ), 154 ), 155 # Too short tag 156 hmac_pb2.HmacKey( 157 version=0, 158 key_value=os.urandom(16), 159 params=hmac_pb2.HmacParams( 160 hash=common_pb2.HashType.SHA1, tag_size=9 161 ), 162 ), 163 hmac_pb2.HmacKey( 164 version=0, 165 key_value=os.urandom(16), 166 params=hmac_pb2.HmacParams( 167 hash=common_pb2.HashType.SHA224, tag_size=9 168 ), 169 ), 170 hmac_pb2.HmacKey( 171 version=0, 172 key_value=os.urandom(16), 173 params=hmac_pb2.HmacParams( 174 hash=common_pb2.HashType.SHA256, tag_size=9 175 ), 176 ), 177 hmac_pb2.HmacKey( 178 version=0, 179 key_value=os.urandom(16), 180 params=hmac_pb2.HmacParams( 181 hash=common_pb2.HashType.SHA384, tag_size=9 182 ), 183 ), 184 hmac_pb2.HmacKey( 185 version=0, 186 key_value=os.urandom(16), 187 params=hmac_pb2.HmacParams( 188 hash=common_pb2.HashType.SHA512, tag_size=9 189 ), 190 ), 191 # Too long tag 192 hmac_pb2.HmacKey( 193 version=0, 194 key_value=os.urandom(16), 195 params=hmac_pb2.HmacParams( 196 hash=common_pb2.HashType.SHA1, tag_size=21 197 ), 198 ), 199 hmac_pb2.HmacKey( 200 version=0, 201 key_value=os.urandom(16), 202 params=hmac_pb2.HmacParams( 203 hash=common_pb2.HashType.SHA224, tag_size=29 204 ), 205 ), 206 hmac_pb2.HmacKey( 207 version=0, 208 key_value=os.urandom(16), 209 params=hmac_pb2.HmacParams( 210 hash=common_pb2.HashType.SHA256, tag_size=33 211 ), 212 ), 213 hmac_pb2.HmacKey( 214 version=0, 215 key_value=os.urandom(16), 216 params=hmac_pb2.HmacParams( 217 hash=common_pb2.HashType.SHA384, tag_size=49 218 ), 219 ), 220 hmac_pb2.HmacKey( 221 version=0, 222 key_value=os.urandom(16), 223 params=hmac_pb2.HmacParams( 224 hash=common_pb2.HashType.SHA512, tag_size=65 225 ), 226 ), 227 ] 228 229 230def valid_lang_and_key(): 231 for lang in tink_config.supported_languages_for_key_type('HmacKey'): 232 for key in valid_keys(): 233 yield (lang, key) 234 235 236def consistency_test_cases(): 237 for lang1 in tink_config.supported_languages_for_key_type('HmacKey'): 238 for lang2 in tink_config.supported_languages_for_key_type('HmacKey'): 239 for key in valid_keys(): 240 for output_prefix_type in [tink_pb2.OutputPrefixType.TINK, 241 tink_pb2.OutputPrefixType.LEGACY, 242 tink_pb2.OutputPrefixType.RAW, 243 tink_pb2.OutputPrefixType.CRUNCHY]: 244 yield (lang1, lang2, key, output_prefix_type) 245 246 247def invalid_lang_and_key(): 248 for lang in tink_config.supported_languages_for_key_type('HmacKey'): 249 for key in invalid_keys(): 250 yield (lang, key) 251 252 253class HmacKeyTest(parameterized.TestCase): 254 """Tests specific for keys of type HmacKey.""" 255 256 @parameterized.parameters(valid_lang_and_key()) 257 def test_create_mac( 258 self, lang: str, key: hmac_pb2.HmacKey 259 ): 260 keyset = to_keyset(key, tink_pb2.OutputPrefixType.TINK) 261 testing_servers.remote_primitive( 262 lang, keyset.SerializeToString(), tink.mac.Mac 263 ) 264 265 @parameterized.parameters(consistency_test_cases()) 266 def test_compute_mac_lang1_lang2( 267 self, 268 lang1: str, 269 lang2: str, 270 key: hmac_pb2.HmacKey, 271 output_prefix_type: tink_pb2.OutputPrefixType, 272 ): 273 keyset = to_keyset(key, output_prefix_type) 274 mac1 = testing_servers.remote_primitive( 275 lang1, keyset.SerializeToString(), tink.mac.Mac 276 ) 277 mac2 = testing_servers.remote_primitive( 278 lang2, keyset.SerializeToString(), tink.mac.Mac 279 ) 280 message = os.urandom(random.choice([0, 1, 17, 31, 1027])) 281 mac2.verify_mac(mac1.compute_mac(message), message) 282 283 284if __name__ == '__main__': 285 absltest.main() 286