• 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# Crypto support
17#
18# See Bluetooth spec Vol 3, Part H - 2.2 CRYPTOGRAPHIC TOOLBOX
19# -----------------------------------------------------------------------------
20
21# -----------------------------------------------------------------------------
22# Imports
23# -----------------------------------------------------------------------------
24import logging
25import operator
26import platform
27
28if platform.system() != 'Emscripten':
29    import secrets
30    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
31    from cryptography.hazmat.primitives.asymmetric.ec import (
32        generate_private_key,
33        ECDH,
34        EllipticCurvePublicNumbers,
35        EllipticCurvePrivateNumbers,
36        SECP256R1,
37    )
38    from cryptography.hazmat.primitives import cmac
39else:
40    # TODO: implement stubs
41    pass
42
43# -----------------------------------------------------------------------------
44# Logging
45# -----------------------------------------------------------------------------
46logger = logging.getLogger(__name__)
47
48
49# -----------------------------------------------------------------------------
50# Classes
51# -----------------------------------------------------------------------------
52class EccKey:
53    def __init__(self, private_key):
54        self.private_key = private_key
55
56    @classmethod
57    def generate(cls):
58        private_key = generate_private_key(SECP256R1())
59        return cls(private_key)
60
61    @classmethod
62    def from_private_key_bytes(cls, d_bytes, x_bytes, y_bytes):
63        d = int.from_bytes(d_bytes, byteorder='big', signed=False)
64        x = int.from_bytes(x_bytes, byteorder='big', signed=False)
65        y = int.from_bytes(y_bytes, byteorder='big', signed=False)
66        private_key = EllipticCurvePrivateNumbers(
67            d, EllipticCurvePublicNumbers(x, y, SECP256R1())
68        ).private_key()
69        return cls(private_key)
70
71    @property
72    def x(self):
73        return (
74            self.private_key.public_key()
75            .public_numbers()
76            .x.to_bytes(32, byteorder='big')
77        )
78
79    @property
80    def y(self):
81        return (
82            self.private_key.public_key()
83            .public_numbers()
84            .y.to_bytes(32, byteorder='big')
85        )
86
87    def dh(self, public_key_x, public_key_y):
88        x = int.from_bytes(public_key_x, byteorder='big', signed=False)
89        y = int.from_bytes(public_key_y, byteorder='big', signed=False)
90        public_key = EllipticCurvePublicNumbers(x, y, SECP256R1()).public_key()
91        shared_key = self.private_key.exchange(ECDH(), public_key)
92
93        return shared_key
94
95
96# -----------------------------------------------------------------------------
97# Functions
98# -----------------------------------------------------------------------------
99
100# -----------------------------------------------------------------------------
101def xor(x, y):
102    assert len(x) == len(y)
103    return bytes(map(operator.xor, x, y))
104
105
106# -----------------------------------------------------------------------------
107def r():
108    '''
109    Generate 16 bytes of random data
110    '''
111    return secrets.token_bytes(16)
112
113
114# -----------------------------------------------------------------------------
115def e(key, data):
116    '''
117    AES-128 ECB, expecting byte-swapped inputs and producing a byte-swapped output.
118
119    See Bluetooth spec Vol 3, Part H - 2.2.1 Security function e
120    '''
121
122    cipher = Cipher(algorithms.AES(bytes(reversed(key))), modes.ECB())
123    encryptor = cipher.encryptor()
124    return bytes(reversed(encryptor.update(bytes(reversed(data)))))
125
126
127# -----------------------------------------------------------------------------
128def ah(k, r):  # pylint: disable=redefined-outer-name
129    '''
130    See Bluetooth spec Vol 3, Part H - 2.2.2 Random Address Hash function ah
131    '''
132
133    padding = bytes(13)
134    r_prime = r + padding
135    return e(k, r_prime)[0:3]
136
137
138# -----------------------------------------------------------------------------
139def c1(k, r, preq, pres, iat, rat, ia, ra):  # pylint: disable=redefined-outer-name
140    '''
141    See Bluetooth spec, Vol 3, Part H - 2.2.3 Confirm value generation function c1 for
142    LE Legacy Pairing
143    '''
144
145    p1 = bytes([iat, rat]) + preq + pres
146    p2 = ra + ia + bytes([0, 0, 0, 0])
147    return e(k, xor(e(k, xor(r, p1)), p2))
148
149
150# -----------------------------------------------------------------------------
151def s1(k, r1, r2):
152    '''
153    See Bluetooth spec, Vol 3, Part H - 2.2.4 Key generation function s1 for LE Legacy
154    Pairing
155    '''
156
157    return e(k, r2[0:8] + r1[0:8])
158
159
160# -----------------------------------------------------------------------------
161def aes_cmac(m, k):
162    '''
163    See Bluetooth spec, Vol 3, Part H - 2.2.5 FunctionAES-CMAC
164
165    NOTE: the input and output of this internal function are in big-endian byte order
166    '''
167    mac = cmac.CMAC(algorithms.AES(k))
168    mac.update(m)
169    return mac.finalize()
170
171
172# -----------------------------------------------------------------------------
173def f4(u, v, x, z):
174    '''
175    See Bluetooth spec, Vol 3, Part H - 2.2.6 LE Secure Connections Confirm Value
176    Generation Function f4
177    '''
178    return bytes(
179        reversed(
180            aes_cmac(bytes(reversed(u)) + bytes(reversed(v)) + z, bytes(reversed(x)))
181        )
182    )
183
184
185# -----------------------------------------------------------------------------
186def f5(w, n1, n2, a1, a2):
187    '''
188    See Bluetooth spec, Vol 3, Part H - 2.2.7 LE Secure Connections Key Generation
189    Function f5
190
191    NOTE: this returns a tuple: (MacKey, LTK) in little-endian byte order
192    '''
193    salt = bytes.fromhex('6C888391AAF5A53860370BDB5A6083BE')
194    t = aes_cmac(bytes(reversed(w)), salt)
195    key_id = bytes([0x62, 0x74, 0x6C, 0x65])
196    return (
197        bytes(
198            reversed(
199                aes_cmac(
200                    bytes([0])
201                    + key_id
202                    + bytes(reversed(n1))
203                    + bytes(reversed(n2))
204                    + bytes(reversed(a1))
205                    + bytes(reversed(a2))
206                    + bytes([1, 0]),
207                    t,
208                )
209            )
210        ),
211        bytes(
212            reversed(
213                aes_cmac(
214                    bytes([1])
215                    + key_id
216                    + bytes(reversed(n1))
217                    + bytes(reversed(n2))
218                    + bytes(reversed(a1))
219                    + bytes(reversed(a2))
220                    + bytes([1, 0]),
221                    t,
222                )
223            )
224        ),
225    )
226
227
228# -----------------------------------------------------------------------------
229def f6(w, n1, n2, r, io_cap, a1, a2):  # pylint: disable=redefined-outer-name
230    '''
231    See Bluetooth spec, Vol 3, Part H - 2.2.8 LE Secure Connections Check Value
232    Generation Function f6
233    '''
234    return bytes(
235        reversed(
236            aes_cmac(
237                bytes(reversed(n1))
238                + bytes(reversed(n2))
239                + bytes(reversed(r))
240                + bytes(reversed(io_cap))
241                + bytes(reversed(a1))
242                + bytes(reversed(a2)),
243                bytes(reversed(w)),
244            )
245        )
246    )
247
248
249# -----------------------------------------------------------------------------
250def g2(u, v, x, y):
251    '''
252    See Bluetooth spec, Vol 3, Part H - 2.2.9 LE Secure Connections Numeric Comparison
253    Value Generation Function g2
254    '''
255    return int.from_bytes(
256        aes_cmac(
257            bytes(reversed(u)) + bytes(reversed(v)) + bytes(reversed(y)),
258            bytes(reversed(x)),
259        )[-4:],
260        byteorder='big',
261    )
262
263
264# -----------------------------------------------------------------------------
265def h6(w, key_id):
266    '''
267    See Bluetooth spec, Vol 3, Part H - 2.2.10 Link key conversion function h6
268    '''
269    return aes_cmac(key_id, w)
270
271
272# -----------------------------------------------------------------------------
273def h7(salt, w):
274    '''
275    See Bluetooth spec, Vol 3, Part H - 2.2.11 Link key conversion function h7
276    '''
277    return aes_cmac(w, salt)
278