xref: /btstack/test/mesh/mesh_crypto.py (revision 1d0ba3a50937e585ebce27d37145291505fe56a8)
1#!/usr/bin/env python3
2# BlueKitchen GmbH (c) 2019
3
4# pip3 install pycryptodomex
5
6# implementation of the Bluetooth SIG Mesh crypto functions using pycryptodomex
7
8from Cryptodome.Cipher import AES
9from Cryptodome.Hash   import CMAC
10
11def aes_cmac(k, n):
12    cobj = CMAC.new(k, ciphermod=AES)
13    cobj.update(n)
14    return cobj.digest()
15
16def aes_ccm_encrypt(key, nonce, message, additional_data, mac_len):
17    cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=mac_len)
18    cipher.update(additional_data)
19    ciphertext, tag = cipher.encrypt_and_digest(message)
20    return ciphertext, tag
21
22def aes_ccm_decrypt(key, nonce, message, additional_data, mac_len, mac_tag):
23    cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=mac_len)
24    cipher.update(additional_data)
25    try:
26        ciphertext = cipher.decrypt_and_verify(message, mac_tag)
27        return ciphertext
28    except ValueError:
29        return None
30
31def s1(m):
32    # s1(M) = AES-CMACZERO (M)
33    zero_key = bytes(16)
34    return aes_cmac(zero_key, m)
35
36def k1(n, salt, p):
37    # T = AES-CMACSALT (N)
38    t = aes_cmac(salt, n)
39    # k1(N, SALT, P) = AES-CMACT (P)
40    return aes_cmac(t, p)
41
42def k2(n, p):
43    # SALT = s1(“smk2”)
44    salt = s1(b'smk2')
45    # T = AES-CMACSALT (N)
46    t = aes_cmac(salt, n)
47    # T0 = empty string (zero length)
48    t0 = b''
49    # T1 = AES-CMACT (T0 || P || 0x01)
50    t1 = aes_cmac(t, t0 + p + b'\x01')
51    # T2 = AES-CMACT (T1 || P || 0x02)
52    t2 = aes_cmac(t, t1 + p + b'\x02')
53    # T3 = AES-CMACT (T2 || P || 0x03)
54    t3 = aes_cmac(t, t2 + p + b'\x03')
55    nid = t1[15] & 0x7f
56    encryption_key = t2
57    privacy_key = t3
58    return (nid, encryption_key, privacy_key)
59
60def k3(n):
61    # SALT = s1(“smk3”)
62    salt = s1(b'smk3')
63    # T = AES-CMACSALT (N)
64    t = aes_cmac(salt, n)
65    return aes_cmac(t, b'id64' + b'\x01')[8:]
66
67def k4(n):
68    # SALT = s1(“smk4”)
69    salt = s1(b'smk4')
70    # T = AES-CMACSALT (N)
71    t = aes_cmac(salt, n)
72    return aes_cmac(t, b'id6' + b'\x01')[15] & 0x3f
73
74