• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2021-2022 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#      https://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# Imports
17# -----------------------------------------------------------------------------
18
19from bumble.crypto import EccKey, aes_cmac, ah, c1, f4, f5, f6, g2, h6, h7, s1
20
21# -----------------------------------------------------------------------------
22# pylint: disable=invalid-name
23# -----------------------------------------------------------------------------
24
25# -----------------------------------------------------------------------------
26def reversed_hex(hex_str):
27    return bytes(reversed(bytes.fromhex(hex_str)))
28
29
30# -----------------------------------------------------------------------------
31def test_ecc():
32    key = EccKey.generate()
33    x = key.x
34    y = key.y
35
36    assert len(x) == 32
37    assert len(y) == 32
38
39    # Test DH with test vectors from the spec
40    private_A = (
41        '3f49f6d4 a3c55f38 74c9b3e3 d2103f50 4aff607b eb40b799 5899b8a6 cd3c1abd'
42    )
43    private_B = (
44        '55188b3d 32f6bb9a 900afcfb eed4e72a 59cb9ac2 f19d7cfb 6b4fdd49 f47fc5fd'
45    )
46    public_A_x = (
47        '20b003d2 f297be2c 5e2c83a7 e9f9a5b9 eff49111 acf4fddb cc030148 0e359de6'
48    )
49    public_A_y = (
50        'dc809c49 652aeb6d 63329abf 5a52155c 766345c2 8fed3024 741c8ed0 1589d28b'
51    )
52    public_B_x = (
53        '1ea1f0f0 1faf1d96 09592284 f19e4c00 47b58afd 8615a69f 559077b2 2faaa190'
54    )
55    public_B_y = (
56        '4c55f33e 429dad37 7356703a 9ab85160 472d1130 e28e3676 5f89aff9 15b1214a'
57    )
58    dhkey = 'ec0234a3 57c8ad05 341010a6 0a397d9b 99796b13 b4f866f1 868d34f3 73bfa698'
59
60    key_a = EccKey.from_private_key_bytes(
61        bytes.fromhex(private_A), bytes.fromhex(public_A_x), bytes.fromhex(public_A_y)
62    )
63    shared_key = key_a.dh(bytes.fromhex(public_B_x), bytes.fromhex(public_B_y))
64    assert shared_key == bytes.fromhex(dhkey)
65
66    key_b = EccKey.from_private_key_bytes(
67        bytes.fromhex(private_B), bytes.fromhex(public_B_x), bytes.fromhex(public_B_y)
68    )
69    shared_key = key_b.dh(bytes.fromhex(public_A_x), bytes.fromhex(public_A_y))
70    assert shared_key == bytes.fromhex(dhkey)
71
72
73# -----------------------------------------------------------------------------
74def test_c1():
75    k = bytes(16)
76    r = reversed_hex('5783D52156AD6F0E6388274EC6702EE0')
77    pres = reversed_hex('05000800000302')
78    preq = reversed_hex('07071000000101')
79    iat = 1
80    ia = reversed_hex('A1A2A3A4A5A6')
81    rat = 0
82    ra = reversed_hex('B1B2B3B4B5B6')
83    result = c1(k, r, preq, pres, iat, rat, ia, ra)
84    assert result == reversed_hex('1e1e3fef878988ead2a74dc5bef13b86')
85
86
87# -----------------------------------------------------------------------------
88def test_s1():
89    k = bytes(16)
90    r1 = reversed_hex('000F0E0D0C0B0A091122334455667788')
91    r2 = reversed_hex('010203040506070899AABBCCDDEEFF00')
92    result = s1(k, r1, r2)
93    assert result == reversed_hex('9a1fe1f0e8b0f49b5b4216ae796da062')
94
95
96# -----------------------------------------------------------------------------
97def test_aes_cmac():
98    m = b''
99    k = bytes.fromhex('2b7e1516 28aed2a6 abf71588 09cf4f3c')
100    cmac = aes_cmac(m, k)
101    assert cmac == bytes.fromhex('bb1d6929 e9593728 7fa37d12 9b756746')
102
103    m = bytes.fromhex('6bc1bee2 2e409f96 e93d7e11 7393172a')
104    cmac = aes_cmac(m, k)
105    assert cmac == bytes.fromhex('070a16b4 6b4d4144 f79bdd9d d04a287c')
106
107    m = bytes.fromhex(
108        '6bc1bee2 2e409f96 e93d7e11 7393172a'
109        + 'ae2d8a57 1e03ac9c 9eb76fac 45af8e51'
110        + '30c81c46 a35ce411'
111    )
112    cmac = aes_cmac(m, k)
113    assert cmac == bytes.fromhex('dfa66747 de9ae630 30ca3261 1497c827')
114
115    m = bytes.fromhex(
116        '6bc1bee2 2e409f96 e93d7e11 7393172a'
117        + 'ae2d8a57 1e03ac9c 9eb76fac 45af8e51'
118        + '30c81c46 a35ce411 e5fbc119 1a0a52ef'
119        + 'f69f2445 df4f9b17 ad2b417b e66c3710'
120    )
121    cmac = aes_cmac(m, k)
122    assert cmac == bytes.fromhex('51f0bebf 7e3b9d92 fc497417 79363cfe')
123
124
125# -----------------------------------------------------------------------------
126def test_f4():
127    u = bytes(
128        reversed(
129            bytes.fromhex(
130                '20b003d2 f297be2c 5e2c83a7 e9f9a5b9'
131                + 'eff49111 acf4fddb cc030148 0e359de6'
132            )
133        )
134    )
135    v = bytes(
136        reversed(
137            bytes.fromhex(
138                '55188b3d 32f6bb9a 900afcfb eed4e72a'
139                + '59cb9ac2 f19d7cfb 6b4fdd49 f47fc5fd'
140            )
141        )
142    )
143    x = bytes(reversed(bytes.fromhex('d5cb8454 d177733e ffffb2ec 712baeab')))
144    z = bytes([0])
145    value = f4(u, v, x, z)
146    assert bytes(reversed(value)) == bytes.fromhex(
147        'f2c916f1 07a9bd1c f1eda1be a974872d'
148    )
149
150
151# -----------------------------------------------------------------------------
152def test_f5():
153    w = bytes(
154        reversed(
155            bytes.fromhex(
156                'ec0234a3 57c8ad05 341010a6 0a397d9b'
157                + '99796b13 b4f866f1 868d34f3 73bfa698'
158            )
159        )
160    )
161    n1 = bytes(reversed(bytes.fromhex('d5cb8454 d177733e ffffb2ec 712baeab')))
162    n2 = bytes(reversed(bytes.fromhex('a6e8e7cc 25a75f6e 216583f7 ff3dc4cf')))
163    a1 = bytes(reversed(bytes.fromhex('00561237 37bfce')))
164    a2 = bytes(reversed(bytes.fromhex('00a71370 2dcfc1')))
165    value = f5(w, n1, n2, a1, a2)
166    assert bytes(reversed(value[0])) == bytes.fromhex(
167        '2965f176 a1084a02 fd3f6a20 ce636e20'
168    )
169    assert bytes(reversed(value[1])) == bytes.fromhex(
170        '69867911 69d7cd23 980522b5 94750a38'
171    )
172
173
174# -----------------------------------------------------------------------------
175def test_f6():
176    n1 = bytes(reversed(bytes.fromhex('d5cb8454 d177733e ffffb2ec 712baeab')))
177    n2 = bytes(reversed(bytes.fromhex('a6e8e7cc 25a75f6e 216583f7 ff3dc4cf')))
178    mac_key = bytes(reversed(bytes.fromhex('2965f176 a1084a02 fd3f6a20 ce636e20')))
179    r = bytes(reversed(bytes.fromhex('12a3343b b453bb54 08da42d2 0c2d0fc8')))
180    io_cap = bytes(reversed(bytes.fromhex('010102')))
181    a1 = bytes(reversed(bytes.fromhex('00561237 37bfce')))
182    a2 = bytes(reversed(bytes.fromhex('00a71370 2dcfc1')))
183    value = f6(mac_key, n1, n2, r, io_cap, a1, a2)
184    assert bytes(reversed(value)) == bytes.fromhex(
185        'e3c47398 9cd0e8c5 d26c0b09 da958f61'
186    )
187
188
189# -----------------------------------------------------------------------------
190def test_g2():
191    u = bytes(
192        reversed(
193            bytes.fromhex(
194                '20b003d2 f297be2c 5e2c83a7 e9f9a5b9'
195                + 'eff49111 acf4fddb cc030148 0e359de6'
196            )
197        )
198    )
199    v = bytes(
200        reversed(
201            bytes.fromhex(
202                '55188b3d 32f6bb9a 900afcfb eed4e72a'
203                + '59cb9ac2 f19d7cfb 6b4fdd49 f47fc5fd'
204            )
205        )
206    )
207    x = bytes(reversed(bytes.fromhex('d5cb8454 d177733e ffffb2ec 712baeab')))
208    y = bytes(reversed(bytes.fromhex('a6e8e7cc 25a75f6e 216583f7 ff3dc4cf')))
209    value = g2(u, v, x, y)
210    assert value == 0x2F9ED5BA
211
212
213# -----------------------------------------------------------------------------
214def test_h6():
215    KEY = bytes.fromhex('ec0234a3 57c8ad05 341010a6 0a397d9b')
216    KEY_ID = bytes.fromhex('6c656272')
217    assert h6(KEY, KEY_ID) == bytes.fromhex('2d9ae102 e76dc91c e8d3a9e2 80b16399')
218
219
220# -----------------------------------------------------------------------------
221def test_h7():
222    KEY = bytes.fromhex('ec0234a3 57c8ad05 341010a6 0a397d9b')
223    SALT = bytes.fromhex('00000000 00000000 00000000 746D7031')
224    assert h7(SALT, KEY) == bytes.fromhex('fb173597 c6a3c0ec d2998c2a 75a57011')
225
226
227# -----------------------------------------------------------------------------
228def test_ah():
229    irk = bytes(reversed(bytes.fromhex('ec0234a3 57c8ad05 341010a6 0a397d9b')))
230    prand = bytes(reversed(bytes.fromhex('708194')))
231    value = ah(irk, prand)
232    expected = bytes(reversed(bytes.fromhex('0dfbaa')))
233    assert value == expected
234
235
236# -----------------------------------------------------------------------------
237if __name__ == '__main__':
238    test_ecc()
239    test_c1()
240    test_s1()
241    test_aes_cmac()
242    test_f4()
243    test_f5()
244    test_f6()
245    test_g2()
246    test_h6()
247    test_h7()
248    test_ah()
249