bumble 0.0.211__py3-none-any.whl → 0.0.212__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. bumble/_version.py +2 -2
  2. bumble/apps/bench.py +4 -2
  3. bumble/apps/console.py +2 -2
  4. bumble/apps/pair.py +185 -32
  5. bumble/att.py +13 -12
  6. bumble/avctp.py +2 -2
  7. bumble/avdtp.py +122 -68
  8. bumble/avrcp.py +11 -5
  9. bumble/core.py +13 -7
  10. bumble/{crypto.py → crypto/__init__.py} +11 -95
  11. bumble/crypto/builtin.py +652 -0
  12. bumble/crypto/cryptography.py +84 -0
  13. bumble/device.py +362 -185
  14. bumble/drivers/intel.py +3 -0
  15. bumble/gatt.py +3 -5
  16. bumble/gatt_client.py +5 -3
  17. bumble/gatt_server.py +8 -6
  18. bumble/hci.py +67 -2
  19. bumble/hfp.py +44 -20
  20. bumble/hid.py +24 -12
  21. bumble/host.py +24 -0
  22. bumble/keys.py +64 -48
  23. bumble/l2cap.py +19 -9
  24. bumble/pandora/host.py +11 -11
  25. bumble/pandora/l2cap.py +2 -2
  26. bumble/pandora/security.py +72 -56
  27. bumble/profiles/aics.py +3 -5
  28. bumble/profiles/ancs.py +3 -1
  29. bumble/profiles/ascs.py +11 -5
  30. bumble/profiles/asha.py +11 -6
  31. bumble/profiles/csip.py +1 -3
  32. bumble/profiles/gatt_service.py +1 -3
  33. bumble/profiles/hap.py +16 -33
  34. bumble/profiles/mcp.py +12 -9
  35. bumble/profiles/vcs.py +5 -5
  36. bumble/profiles/vocs.py +6 -9
  37. bumble/rfcomm.py +17 -8
  38. bumble/smp.py +14 -8
  39. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/METADATA +4 -4
  40. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/RECORD +44 -42
  41. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/WHEEL +1 -1
  42. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/entry_points.txt +0 -0
  43. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/licenses/LICENSE +0 -0
  44. {bumble-0.0.211.dist-info → bumble-0.0.212.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- # Copyright 2021-2022 Google LLC
1
+ # Copyright 2021-2025 Google LLC
2
2
  #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # Licensed under the Apache License, Version 2.0 (the "License")
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
@@ -12,12 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # -----------------------------------------------------------------------------
16
- # Crypto support
17
- #
18
- # See Bluetooth spec Vol 3, Part H - 2.2 CRYPTOGRAPHIC TOOLBOX
19
- # -----------------------------------------------------------------------------
20
-
21
15
  # -----------------------------------------------------------------------------
22
16
  # Imports
23
17
  # -----------------------------------------------------------------------------
@@ -25,19 +19,15 @@ from __future__ import annotations
25
19
 
26
20
  import logging
27
21
  import operator
28
-
29
22
  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
- EllipticCurvePrivateKey,
35
- EllipticCurvePublicNumbers,
36
- EllipticCurvePrivateNumbers,
37
- SECP256R1,
38
- )
39
- from cryptography.hazmat.primitives import cmac
40
- from typing import Tuple
23
+
24
+ try:
25
+ from bumble.crypto.cryptography import EccKey, e, aes_cmac
26
+ except ImportError:
27
+ logging.getLogger(__name__).debug(
28
+ "Unable to import cryptography, use built-in primitives."
29
+ )
30
+ from bumble.crypto.builtin import EccKey, e, aes_cmac # type: ignore[assignment]
41
31
 
42
32
 
43
33
  # -----------------------------------------------------------------------------
@@ -46,55 +36,6 @@ from typing import Tuple
46
36
  logger = logging.getLogger(__name__)
47
37
 
48
38
 
49
- # -----------------------------------------------------------------------------
50
- # Classes
51
- # -----------------------------------------------------------------------------
52
- class EccKey:
53
- def __init__(self, private_key: EllipticCurvePrivateKey) -> None:
54
- self.private_key = private_key
55
-
56
- @classmethod
57
- def generate(cls) -> EccKey:
58
- private_key = generate_private_key(SECP256R1())
59
- return cls(private_key)
60
-
61
- @classmethod
62
- def from_private_key_bytes(
63
- cls, d_bytes: bytes, x_bytes: bytes, y_bytes: bytes
64
- ) -> EccKey:
65
- d = int.from_bytes(d_bytes, byteorder='big', signed=False)
66
- x = int.from_bytes(x_bytes, byteorder='big', signed=False)
67
- y = int.from_bytes(y_bytes, byteorder='big', signed=False)
68
- private_key = EllipticCurvePrivateNumbers(
69
- d, EllipticCurvePublicNumbers(x, y, SECP256R1())
70
- ).private_key()
71
- return cls(private_key)
72
-
73
- @property
74
- def x(self) -> bytes:
75
- return (
76
- self.private_key.public_key()
77
- .public_numbers()
78
- .x.to_bytes(32, byteorder='big')
79
- )
80
-
81
- @property
82
- def y(self) -> bytes:
83
- return (
84
- self.private_key.public_key()
85
- .public_numbers()
86
- .y.to_bytes(32, byteorder='big')
87
- )
88
-
89
- def dh(self, public_key_x: bytes, public_key_y: bytes) -> bytes:
90
- x = int.from_bytes(public_key_x, byteorder='big', signed=False)
91
- y = int.from_bytes(public_key_y, byteorder='big', signed=False)
92
- public_key = EllipticCurvePublicNumbers(x, y, SECP256R1()).public_key()
93
- shared_key = self.private_key.exchange(ECDH(), public_key)
94
-
95
- return shared_key
96
-
97
-
98
39
  # -----------------------------------------------------------------------------
99
40
  # Functions
100
41
  # -----------------------------------------------------------------------------
@@ -132,19 +73,6 @@ def r() -> bytes:
132
73
  return secrets.token_bytes(16)
133
74
 
134
75
 
135
- # -----------------------------------------------------------------------------
136
- def e(key: bytes, data: bytes) -> bytes:
137
- '''
138
- AES-128 ECB, expecting byte-swapped inputs and producing a byte-swapped output.
139
-
140
- See Bluetooth spec Vol 3, Part H - 2.2.1 Security function e
141
- '''
142
-
143
- cipher = Cipher(algorithms.AES(reverse(key)), modes.ECB())
144
- encryptor = cipher.encryptor()
145
- return reverse(encryptor.update(reverse(data)))
146
-
147
-
148
76
  # -----------------------------------------------------------------------------
149
77
  def ah(k: bytes, r: bytes) -> bytes: # pylint: disable=redefined-outer-name
150
78
  '''
@@ -187,18 +115,6 @@ def s1(k: bytes, r1: bytes, r2: bytes) -> bytes:
187
115
  return e(k, r2[0:8] + r1[0:8])
188
116
 
189
117
 
190
- # -----------------------------------------------------------------------------
191
- def aes_cmac(m: bytes, k: bytes) -> bytes:
192
- '''
193
- See Bluetooth spec, Vol 3, Part H - 2.2.5 FunctionAES-CMAC
194
-
195
- NOTE: the input and output of this internal function are in big-endian byte order
196
- '''
197
- mac = cmac.CMAC(algorithms.AES(k))
198
- mac.update(m)
199
- return mac.finalize()
200
-
201
-
202
118
  # -----------------------------------------------------------------------------
203
119
  def f4(u: bytes, v: bytes, x: bytes, z: bytes) -> bytes:
204
120
  '''
@@ -209,7 +125,7 @@ def f4(u: bytes, v: bytes, x: bytes, z: bytes) -> bytes:
209
125
 
210
126
 
211
127
  # -----------------------------------------------------------------------------
212
- def f5(w: bytes, n1: bytes, n2: bytes, a1: bytes, a2: bytes) -> Tuple[bytes, bytes]:
128
+ def f5(w: bytes, n1: bytes, n2: bytes, a1: bytes, a2: bytes) -> tuple[bytes, bytes]:
213
129
  '''
214
130
  See Bluetooth spec, Vol 3, Part H - 2.2.7 LE Secure Connections Key Generation
215
131
  Function f5