Welcome to mirror list, hosted at ThFree Co, Russian Federation.

zigbee.security.h « include « stack « zigbee « STM32_WPAN « ST « Middlewares - github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5a76db58b46a4416ac8f96e527691156bcfd2b4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/**
 * @file zigbee.security.h
 * @brief Zigbee security header file
 * @author Exegin Technologies
 * @copyright Copyright [2009 - 2020] Exegin Technologies Limited. All rights reserved.
 */

#ifndef ZIGBEE_SECURITY_H
#define ZIGBEE_SECURITY_H

#include <stdint.h>
#include <stdbool.h>

struct ZigBeeT;

/* Security Install Code Max Length (including CRC) */
#define ZB_SEC_INSTALL_CODE_MAX_LENGTH      18U

/* Key and Cipher strengths used by ZigBee. */
#define ZB_SEC_BLOCKSIZE                    16U
#define ZB_SEC_KEYSIZE                      ZB_SEC_BLOCKSIZE

/* ZB_SEC_KEYSTR_SIZE is a helper to know how much to allocate
 * for ascii string buffer. */
#define ZB_SEC_KEYSTR_SIZE      ((ZB_SEC_KEYSIZE * 2U) + ZB_SEC_KEYSIZE /* separators */ + 1U /* NULL */)

/*
 * +-----------------------------------------------------------------------------+
 * | Security      Security       Security       Data         Frame Integrity    |
 * | level         Level Sub-     Attributes     Encryption   (length M of MIC,  |
 * | identifier    Field                                      in number of       |
 * |               (Figure 18)                                octets)            |
 * +-----------------------------------------------------------------------------+
 * | 0x00          000          None           OFF           NO (M = 0)        |
 * | 0x01          001          MIC-32         OFF          YES (M=4)          |
 * | 0x02          010          MIC-64         OFF          YES (M=8)          |
 * | 0x03          011          MIC-128        OFF          YES (M=16)         |
 * | 0x04          100          ENC            ON            NO (M = 0)        |
 * | 0x05          101          ENC-MIC-32     ON           YES (M=4)          |
 * | 0x06          110          ENC-MIC-64     ON           YES (M=8)          |
 * | 0x07          111          ENC-MIC-128    ON           YES (M=16)         |
 * +-----------------------------------------------------------------------------+
 */
#define ZB_SEC_LEVEL_NONE                   0x00U
#define ZB_SEC_LEVEL_MIC32                  0x01U
#define ZB_SEC_LEVEL_MIC64                  0x02U
#define ZB_SEC_LEVEL_MIC128                 0x03U
#define ZB_SEC_LEVEL_ENC                    0x04U
#define ZB_SEC_LEVEL_ENC_MIC32              (uint8_t)(ZB_SEC_LEVEL_ENC | ZB_SEC_LEVEL_MIC32)
#define ZB_SEC_LEVEL_ENC_MIC64              (uint8_t)(ZB_SEC_LEVEL_ENC | ZB_SEC_LEVEL_MIC64)
#define ZB_SEC_LEVEL_ENC_MIC128             (uint8_t)(ZB_SEC_LEVEL_ENC | ZB_SEC_LEVEL_MIC128)

/* Macro checks security level if encryption is enabled */
#define ZB_SEC_ENCRYPTED(level)             ((level & ZB_SEC_LEVEL_ENC) != 0U)

/* Macro returns the length of the MIC, can be computed
 * as 4bytes * Floor((2 ^ (level - 1))), or:
 * 4 * 2 ^ (level - 1) rounded down to the nearest 4 bytes.
 *
 * See right-most column in table above.
 */
#define ZB_SEC_MIC_LENGTH(level)            ((2U << ((level) & 0x3U)) & ~0x3U)
#define ZB_SEC_MIC_LENGTH_5                 4U

/* The maximum possible MIC length. */
#define ZB_SEC_MAX_MIC_LENGTH               16U

/* The length of the CCM* nonce. */
#define ZB_SEC_NONCE_LENGTH                 13U

/* The maximum size of the auxilliary header. */
#define ZB_SEC_MAX_HEADER_SIZE              14U

/* Masks for the Security control header fields. (section 4.5.1)*/
#define ZB_SEC_SECCTRL_MASK_LEVEL           (uint8_t)0x07U /* Bits 0-2 */
#define ZB_SEC_SECCTRL_MASK_KEYID           (uint8_t)0x18U /* Bits 3-4 */
#define ZB_SEC_SECCTRL_MASK_EXTNONCE        (uint8_t)0x20U /* Bits 5 */
#define ZB_SEC_SECCTRL_MASK_RESERVED        (uint8_t)0x60U /* Bits 6-7 */

/* Offsets of the Security control header fields. */
#define ZB_SEC_SECCTRL_OFFSET_LEVEL         0U
#define ZB_SEC_SECCTRL_OFFSET_KEYID         3U
#define ZB_SEC_SECCTRL_OFFSET_EXTNONCE      5U

/* Key Ids (Frame Control Field). */
enum ZbSecHdrKeyIdT {
    ZB_SEC_KEYID_LINK = 0x00,
    ZB_SEC_KEYID_NETWORK = 0x01,
    ZB_SEC_KEYID_TRANSPORT = 0x02,
    ZB_SEC_KEYID_KEYLOAD = 0x03,
    /* Exegin add-on - not for over-the-air */
    ZB_SEC_KEYID_BOTH_LINK_NETWORK = 0xfe, /* For Update Device (send two) */
    ZB_SEC_KEYID_DEFAULT = 0xff
};

/* Maximum value for a frame counter. */
#define ZB_SEC_MAX_FRAME_COUNTER            0xffffffffU

/* Frame Counter Resets are controlled much like a lollipop counter, and require
 * the 'new' value to be near zero to guard against replay attacks. */
#define ZB_FRAME_COUNTER_RESET_MAX          256U

/* Key Type Enumerations (Primitives and over-the-air). */
enum ZbSecKeyTypeT {
    /* Reserved -- was Trust-Center master key */
    ZB_SEC_KEYTYPE_STANDARD_NWK = 0x01, /* Standard network key */
    /* 0x02 -- Reserved -- was Application master key */
    ZB_SEC_KEYTYPE_APP_LINK = 0x03, /* Application link key */
    ZB_SEC_KEYTYPE_TC_LINK = 0x04 /* Trust-Center link key */
        /* 0x05 -- Reserved -- was High security network key */
};

/*---------------------------------------------------------------
 * Flags to indicate encryption used. Loosely based on enum ZbSecKeyTypeT.
 *---------------------------------------------------------------
 */
#define ZB_SEC_ENCRYPT_TYPE_LINK_FLAG       0x80U

enum ZbSecEncryptT {
    /* No encryption used */
    ZB_SEC_ENCRYPT_TYPE_NONE = 0x00,
    /* Encrypted with standard network key */
    ZB_SEC_ENCRYPT_TYPE_STANDARD_NWK = 0x01,
    /* Link keys */
    /* ZB_SEC_ENCRYPT_TYPE_LINK_FLAG = ZB_SEC_ENCRYPT_TYPE_LINK_FLAG, */
    /* Application link key */
    ZB_SEC_ENCRYPT_TYPE_APP_LINK = 0x83, /* ZB_SEC_ENCRYPT_TYPE_LINK_FLAG | 0x03U */
    /* Trust-Center link key */
    ZB_SEC_ENCRYPT_TYPE_TC_LINK = 0x84, /* ZB_SEC_ENCRYPT_TYPE_LINK_FLAG | 0x04U */
    /* Preconfigured Global Trust-Center link key */
    ZB_SEC_ENCRYPT_TYPE_GLOBAL_TC_LINK = 0x90, /* ZB_SEC_ENCRYPT_TYPE_LINK_FLAG | 0x10U */
    /* Distributed Global Trust-Center link key */
    ZB_SEC_ENCRYPT_TYPE_DISTRIB_TC_LINK = 0xa0 /* ZB_SEC_ENCRYPT_TYPE_LINK_FLAG | 0x20U */
};

/*---------------------------------------------------------------
 * CBKE Certificate Formats
 *---------------------------------------------------------------
 */
/* Field sizes for the elliptic curve (NIST-K163, aka SECT-163K1) */
#define CBKE_PRIVATE_KEY_SIZE               21U /* sizeof(2^163) */
#define CBKE_COMPRESSED_PUBLIC_KEY_SIZE     (CBKE_PRIVATE_KEY_SIZE + 1U)
#define CBKE_UNCOMPRESSED_PUBLIC_KEY_SIZE   (2 * CBKE_PRIVATE_KEY_SIZE + 1U)
#define CBKE_SHARED_SECRET_SIZE             CBKE_PRIVATE_KEY_SIZE

/* Field sizes for the elliptic curve (NIST-K283, aka SECT-283K1) */
#define CBKE2_PRIVATE_KEY_SIZE              36U /* sizeof(2^283) */
#define CBKE2_COMPRESSED_PUBLIC_KEY_SIZE    (CBKE2_PRIVATE_KEY_SIZE + 1U)
#define CBKE2_UNCOMPRESSED_PUBLIC_KEY_SIZE  (2U * CBKE2_PRIVATE_KEY_SIZE + 1U)
#define CBKE2_SHARED_SECRET_SIZE            CBKE2_PRIVATE_KEY_SIZE

/* Size and layout of the CBKE certificate. */
#define CBKE_CERT_SUBJECT_OFFSET            CBKE_COMPRESSED_PUBLIC_KEY_SIZE
#define CBKE_CERT_SUBJECT_SIZE              8U
#define CBKE_CERT_ISSUER_OFFSET             (CBKE_CERT_SUBJECT_OFFSET + CBKE_CERT_SUBJECT_SIZE)
#define CBKE_CERT_ISSUER_SIZE               8U
#define CBKE_CERT_DATA_OFFSET               (CBKE_CERT_ISSUER_OFFSET + CBKE_CERT_ISSUER_SIZE)
#define CBKE_CERT_DATA_SIZE                 10U
#define CBKE_CERTIFICATE_SIZE               (CBKE_CERT_DATA_OFFSET + CBKE_CERT_DATA_SIZE)

/* Size and layout of the CBKE2 certificate. */
#define CBKE2_CERT_TYPE_OFFSET              0U
#define CBKE2_CERT_TYPE_SIZE                1U
#define CBKE2_CERT_TYPE                     0x00U
#define CBKE2_CERT_SERIAL_OFFSET            (CBKE2_CERT_TYPE_SIZE)
#define CBKE2_CERT_SERIAL_SIZE              8U
#define CBKE2_CERT_CURVE_OFFSET             (CBKE2_CERT_SERIAL_OFFSET + CBKE2_CERT_SERIAL_SIZE)
#define CBKE2_CERT_CURVE_SIZE               1U
#define CBKE2_CERT_CURVE                    CURVE_IDENTIFIER_SECT283K1
#define CBKE2_CERT_HASH_OFFSET              (CBKE2_CERT_CURVE_OFFSET + CBKE2_CERT_CURVE_SIZE)
#define CBKE2_CERT_HASH_SIZE                1U
#define CBKE2_CERT_HASH                     HASH_IDENTIFIER_AES_MMO
#define CBKE2_CERT_ISSUER_OFFSET            (CBKE2_CERT_HASH_OFFSET + CBKE2_CERT_HASH_SIZE)
#define CBKE2_CERT_ISSUER_SIZE              8U
#define CBKE2_CERT_VALID_FROM_OFFSET        (CBKE2_CERT_ISSUER_OFFSET + CBKE2_CERT_ISSUER_SIZE)
#define CBKE2_CERT_VALID_FROM_SIZE          5U
#define CBKE2_CERT_VALID_TO_OFFSET          (CBKE2_CERT_VALID_FROM_OFFSET + CBKE2_CERT_VALID_FROM_SIZE)
#define CBKE2_CERT_VALID_TO_SIZE            4U
#define CBKE2_CERT_SUBJECT_OFFSET           (CBKE2_CERT_VALID_TO_OFFSET + CBKE2_CERT_VALID_TO_SIZE)
#define CBKE2_CERT_SUBJECT_SIZE             8U
#define CBKE2_CERT_KEY_USAGE_OFFSET         (CBKE2_CERT_SUBJECT_OFFSET + CBKE2_CERT_SUBJECT_SIZE)
#define CBKE2_CERT_KEY_USAGE_SIZE           1U
#define CBKE2_CERT_KEY_USAGE                KEY_USAGE_AGREEMENT
#define CBKE2_CERT_PUBLIC_KEY_OFFSET        (CBKE2_CERT_KEY_USAGE_OFFSET + CBKE2_CERT_KEY_USAGE_SIZE)
#define CBKE2_CERT_PUBLIC_KEY_SIZE          37U
#define CBKE2_CERTIFICATE_SIZE              (CBKE2_CERT_PUBLIC_KEY_OFFSET + CBKE2_CERT_PUBLIC_KEY_SIZE)

struct ZbZclCbkePrivateT {
    uint8_t privateKey[CBKE_PRIVATE_KEY_SIZE];
    uint8_t publicCaKey[CBKE_COMPRESSED_PUBLIC_KEY_SIZE];
};

struct ZbZclCbkeInfoT {
    struct ZbZclCbkePrivateT keys;
    uint8_t cert[CBKE_CERTIFICATE_SIZE];
    uint8_t ephemeralTime; /* In seconds. If 0, CBKE_V1_EPHEMERAL_DEFAULT_TIME is used */
    uint8_t confirmTime; /* In seconds. If 0, CBKE_V1_CONFIRM_DEFAULT_TIME is used */
};

struct ZbZclCbke2PrivateT {
    uint8_t privateKey[CBKE2_PRIVATE_KEY_SIZE];
    uint8_t publicCaKey[CBKE2_COMPRESSED_PUBLIC_KEY_SIZE];
};

struct ZbZclCbke2InfoT {
    struct ZbZclCbke2PrivateT keys;
    uint8_t cert[CBKE2_CERTIFICATE_SIZE];
    uint8_t ephemeralTime; /* In seconds. If 0, CBKE_V2_EPHEMERAL_DEFAULT_TIME is used */
    uint8_t confirmTime; /* In seconds. If 0, CBKE_V2_CONFIRM_DEFAULT_TIME is used */
};

/*---------------------------------------------------------------
 * Auxiliary Frame Functions
 *---------------------------------------------------------------
 */
/* Security Control Field of the Auxilliary Header */
struct ZbSecAuxHdrCtrlT {
    uint8_t secLevel;
    enum ZbSecHdrKeyIdT keyId;
    bool extNonce;
};

/* Structure containing the fields stored in the Aux Header */
struct ZbSecAuxHdrT {
    struct ZbSecAuxHdrCtrlT securityCtrl;
    uint32_t frameCounter;
    uint64_t srcExtAddr; /* Present if securityCtrl.extNonce */
    uint8_t keySeqno; /* Present if securityCtrl.keyId = 1 (Network Key) */
};

/**
 * Parses the auxiliary header into the provided structure.
 * @param data Packet buffer
 * @param dataLen Packet length
 * @param auxHdrPtr Pointer to ZbSecAuxHdrT structure to parse data into.
 * @return Number of bytes in the header, or <0 on error.
 */
int ZbSecParseAuxHdr(const uint8_t *data, unsigned int dataLen, struct ZbSecAuxHdrT *auxHdrPtr);

/**
 * Append an auxillary security header to a packet
 * @param data Packet buffer
 * @param dataLen Packet length
 * @param auxHdrPtr auxillary header struct to use
 * @return Number of bytes written, or <0 on error.
 */
int ZbSecAppendAuxHdr(uint8_t *data, unsigned int dataLen, struct ZbSecAuxHdrT *auxHdrPtr);

/**
 * Builds the CCM* nonce from the source address, frame counter and security control bits.
 * The nonce buffer must be at least ZB_SEC_NONCE_LENGTH in size.
 * @param nonce Nonce buffer (output)
 * @param extAddr Source extended addres
 * @param frameCounter Frame counter
 * @param secCtrl Security control field
 * @return None
 */
void ZbSecMakeNonce(uint8_t *nonce, uint64_t extAddr, uint32_t frameCounter, uint8_t secCtrl);

/*---------------------------------------------------------------
 * Security Transformations
 *---------------------------------------------------------------
 */

/**
 * Performs an AES MMO hash on the selected data
 * @param zb Zigbee stack instance
 * @param data data to hash
 * @param length length of data to hash
 * @param digest hash must be AES_BLOCK_SIZE in size!
 * @return
 */
bool ZbAesMmoHash(struct ZigBeeT *zb, uint8_t const *data, const unsigned int length, uint8_t *digest);

/**
 * Performs the Keyed Hash function for Message Authentication. The HMAC operation described
 * in section B.1.4, and specified by FIPS pub 198. This is used to trasmute the link keys into
 * key-load and key-transport keys.
 * @param key encryption key to use
 * @param input input data
 * @param keyOut output buffer
 * @return
 */
void ZbSecKeyTransform(uint8_t *key, uint8_t input, uint8_t *keyOut);

/* Add a device-key-pair. NOTE: May not be supported by all platforms. */
uint8_t ZbSecAddDeviceLinkKeyByKey(struct ZigBeeT *zb, uint64_t extAddr, uint8_t *key);
uint8_t ZbSecAddDeviceLinkKeyByKeyStr(struct ZigBeeT *zb, uint64_t extAddr, char *str);

/*---------------------------------------------------------------
 * Extras: Install Code Helpers (Optional, may not be included in all builds)
 *---------------------------------------------------------------
 */
/* Performs redundancy checks on a ZSE installation code and optionally converts the code
 * into an application link key. */
bool ZbSecInstallCodeCheck(struct ZigBeeT *zb, const void *installCode, unsigned int codeLen, void *keyOut);

/* Computes the 2-byte CRC of the input Install Code */
void ZbSecInstallCodeCrc(const uint8_t *ic_in, uint8_t ic_len, uint8_t *crc_out);

/* Add a device-key-pair using an Install Code (includes trailing 2-octet CRC). */
uint8_t ZbSecAddDeviceLinkKeyByInstallCode(struct ZigBeeT *zb, uint64_t extAddr, uint8_t *ic, unsigned int len);

/*---------------------------------------------------------------
 * ECDSA Signature Validation
 *---------------------------------------------------------------
 */
enum ZbSecEcdsaSigType {
    ZB_SEC_ECDSA_SIG_SUITE_1,
    ZB_SEC_ECDSA_SIG_SUITE_2
};

#define ZB_SEC_CRYPTO_SUITE_V2_CERT_LEN             74U
#define ZB_SEC_CRYPTO_SUITE_V2_SIG_LEN              80U /* IEEE[8] r[36] s[36] */

/**
 * Description
 * @param zb
 * @param sig_type
 * @param ca_pub_key_array
 * @param ca_pub_key_len
 * @param certificate Length must be ZB_SEC_CRYPTO_SUITE_V2_CERT_LEN (74 bytes)
 * @param signature Length must be ZB_SEC_CRYPTO_SUITE_V2_SIG_LEN (80 bytes)
 * @param image_digest Length is AES_BLOCK_SIZE (16 bytes)
 * @param cert_digest Length is AES_BLOCK_SIZE (16 bytes)
 * @return
 */
enum ZbStatusCodeT ZbSecEcdsaValidate(struct ZigBeeT *zb, enum ZbSecEcdsaSigType sig_type,
    const uint8_t *ca_pub_key_array, unsigned int ca_pub_key_len,
    const uint8_t *certificate, const uint8_t *signature,
    const uint8_t *image_digest, const uint8_t *cert_digest);

#endif /* ZIGBEE_SECURITY_H */