xref: /btstack/test/mesh/mesh_message_test.py (revision af7c3ae6cd1e2bcfd24e6d0654508ecf775c9e5d)
1#!/usr/bin/env python3
2# BlueKitchen GmbH (c) 2019
3
4# pip3 install pycryptodomex
5
6from mesh_crypto import *
7
8try:
9    from Cryptodome.Cipher import AES
10    from Cryptodome.Hash import CMAC
11except ImportError:
12    # fallback: try to import PyCryptodome as (an almost drop-in) replacement for the PyCrypto library
13    try:
14        from Crypto.Cipher import AES
15        from Crypto.Hash import CMAC
16    except ImportError:
17        print("\n[!] PyCryptodome required but not installed (using random value instead)")
18        print("[!] Please install PyCryptodome, e.g. 'pip3 install pycryptodomex' or 'pip3 install pycryptodome'\n")
19
20# S1('test') = b73cefbd641ef2ea598c2b6efb62f79c
21s1_input  = b'test'
22s1_actual = s1(s1_input)
23
24s1_expected = bytes.fromhex('b73cefbd641ef2ea598c2b6efb62f79c')
25if s1_actual != s1_expected:
26    print("s1: expected " + s1_expected.hex + ", but got " + s1_actual.hex())
27
28# K1(3216d1509884b533248541792b877f98, 2ba14ffa0df84a2831938d57d276cab4, 5a09d60797eeb4478aada59db3352a0d) = f6ed15a8934afbe7d83e8dcb57fcf5d7
29k1_n        = bytes.fromhex("3216d1509884b533248541792b877f98")
30k1_salt     = bytes.fromhex("2ba14ffa0df84a2831938d57d276cab4")
31k1_p        = bytes.fromhex("5a09d60797eeb4478aada59db3352a0d")
32k1_actual = k1(k1_n, k1_salt, k1_p)
33
34k1_expected = bytes.fromhex("f6ed15a8934afbe7d83e8dcb57fcf5d7")
35if k1_actual != k1_expected:
36    print("k1: expected " + k1_expected.hex() + ", but got " + k1_actual.hex())
37
38# k2 test
39k2_n                       = bytes.fromhex('7dd7364cd842ad18c17c2b820c84c3d6')
40k2_p                       = bytes.fromhex('00')
41(k2_nid, k2_encryption_key, k2_privacy_key) = k2(k2_n, k2_p)
42
43k2_nid_expected            = 0x68
44k2_encryption_key_expected = bytes.fromhex('0953fa93e7caac9638f58820220a398e')
45k2_privacy_key_expected    = bytes.fromhex('8b84eedec100067d670971dd2aa700cf')
46if k2_nid_expected != k2_nid:
47    print("k2: nid expected " + hex(k2_nid_expected) + ", but got " + hex(k2_nid))
48if k2_encryption_key_expected != k2_encryption_key:
49    print("k2: encryption key expected " + k2_encryption_key_expected.hex() + ", but got " + k2_encryption_key.hex())
50if k2_privacy_key_expected != k2_privacy_key:
51    print("k2: privacy key expected " + k2_privacy_key_expected.hex() + ", but got " + k2_privacy_key.hex())
52
53# k3 test
54k3_n = bytes.fromhex('f7a2a44f8e8a8029064f173ddc1e2b00')
55k3_actual = k3(k3_n)
56
57k3_expected = bytes.fromhex('ff046958233db014')
58if k3_actual != k3_expected:
59    print("k3: expected " + k3_expected.hex() + ", but got " + k3_actual.hex())
60
61# k4 test
62k4_n = bytes.fromhex('3216d1509884b533248541792b877f98')
63k4_actual = k4(k4_n)
64
65k4_expected = 0x38
66if k4_actual != k4_expected:
67    print("k4: expected " + hex(k4_expected) + ", but got " + hex(k4_actual))
68
69# aes-ccm-encrypt test
70message_1_network_nonce     = bytes.fromhex('00800000011201000012345678')
71message_1_network_plaintext = bytes.fromhex('fffd' + '034b50057e400000010000')
72message_1_encryption_key    = bytes.fromhex('0953fa93e7caac9638f58820220a398e')
73(message_1_ciphertext, message_1_mic) = aes_ccm_encrypt(message_1_encryption_key, message_1_network_nonce, message_1_network_plaintext, b'', 8)
74
75message_1_ciphertext_expected = bytes.fromhex('b5e5bfdacbaf6cb7fb6bff871f')
76message_1_mic_expected        = bytes.fromhex('035444ce83a670df')
77if message_1_ciphertext_expected != message_1_ciphertext:
78    print("aes_ccm_encrypt: ciphertext expected " + hex(message_1_ciphertext_expected) + ", but got " + hex(message_1_ciphertext))
79if message_1_mic_expected != message_1_mic:
80    print("aes_ccm_encrypt: encryption key expected " + message_1_mic_expected.hex() + ", but got " + message_1_mic.hex())
81
82# aes-ccm-decrypt test
83message_1_network_nonce       = bytes.fromhex('00800000011201000012345678')
84message_1_ciphertext_expected = bytes.fromhex('b5e5bfdacbaf6cb7fb6bff871f')
85message_1_mic_expected        = bytes.fromhex('035444ce83a670df')
86message_1_plaintext_decrypted = aes_ccm_decrypt(message_1_encryption_key, message_1_network_nonce, message_1_ciphertext_expected, b'', 8, message_1_mic_expected)
87
88message_1_network_plaintext   = bytes.fromhex('fffd' + '034b50057e400000010000')
89if message_1_plaintext_decrypted == None:
90    print("aes_ccm_decrypt: digest validation failed")
91elif message_1_network_plaintext != message_1_plaintext_decrypted:
92    print("aes_ccm: plaintext expected " + hex(message_1_network_plaintext) + ", but got " + hex(message_1_plaintext_decrypted))
93
94# aes128 encrypt
95aes_key = bytes(16)
96aes_n   = bytes(16)
97aes_actual = aes128(aes_key, aes_n)
98
99aes_expected = bytes.fromhex('66E94BD4EF8A2C3B884CFA59CA342B2E')
100if aes_expected != aes_actual:
101    print("aes128: expected " + aes_expected.hex() + ", but got " + aes_actual.hex())
102
103# network PECB
104iv_index = bytes.fromhex('12345678')
105privacy_key = bytes.fromhex('8b84eedec100067d670971dd2aa700cf')
106message_1_network_pdu = bytes.fromhex('68eca487516765b5e5bfdacbaf6cb7fb6bff871f035444ce83a670df')
107privacy_random = message_1_network_pdu[7:14]
108message_1_pecb = network_pecb(privacy_random, iv_index, privacy_key)
109
110message_1_pecb_expected = bytes.fromhex('6ca487507564')
111if message_1_pecb_expected != message_1_pecb:
112    print("network_pecb: expected " + message_1_pecb_expected.hex() + ", but got " + message_1_pecb.hex())
113
114# message 1
115iv_index                 = bytes.fromhex('12345678')
116privacy_key              = bytes.fromhex('8b84eedec100067d670971dd2aa700cf')
117message_1_network_pdu    = bytes.fromhex('68eca487516765b5e5bfdacbaf6cb7fb6bff871f035444ce83a670df')
118message_1_encryption_key = bytes.fromhex('0953fa93e7caac9638f58820220a398e')
119message_1_decrypted      = network_decrypt(message_1_network_pdu, iv_index, message_1_encryption_key, privacy_key)
120
121message_1_decrypted_expected = bytes.fromhex('68800000011201fffd034b50057e400000010000')
122if message_1_decrypted_expected != message_1_decrypted:
123    print("network_pdu: encrypt expected " + message_1_decrypted_expected.hex() + ", but got " + message_1_decrypted.hex())
124
125# message x decrypt
126iv_index                 = bytes.fromhex('00000001')
127privacy_key              = bytes.fromhex('035efaafbbd84f898b95190cc3cac36b')
128encryption_key           = bytes.fromhex('9ba46b86afbe8b7f0b63db597372babe')
129message_1_network_pdu    = bytes.fromhex('B10000520D001C000155555555555555555555555555555555')
130message_1_encrypted      = network_encrypt(message_1_network_pdu, iv_index, encryption_key, privacy_key)
131
132message_1_expected       = bytes.fromhex('b12a7492504b03fa604d6d2f298ad31233fe1d568175b2f1104e23380b')
133if message_1_expected != message_1_encrypted:
134    print("network_pdu: decrypt expected " + message_1_expected.hex() + ", but got " + message_1_encrypted.hex())
135