1 /*
2 * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef _OSDP_COMMON_H_
8 #define _OSDP_COMMON_H_
9
10 #include <zephyr/mgmt/osdp.h>
11 #include <zephyr/sys/__assert.h>
12
13 #define OSDP_RESP_TOUT_MS (200)
14 #define OSDP_ONLINE_RETRY_WAIT_MAX_MS (300 * 1000)
15 #define OSDP_PACKET_BUF_SIZE CONFIG_OSDP_UART_BUFFER_LENGTH
16 #define OSDP_PD_SC_TIMEOUT_MS (800)
17 #define OSDP_ONLINE_RETRY_WAIT_MAX_MS (300 * 1000)
18 #define OSDP_PD_MAX CONFIG_OSDP_NUM_CONNECTED_PD
19
20 #define OSDP_QUEUE_SLAB_SIZE \
21 (sizeof(union osdp_ephemeral_data) * CONFIG_OSDP_PD_COMMAND_QUEUE_SIZE)
22
23 #define ISSET_FLAG(p, f) (((p)->flags & (f)) == (f))
24 #define SET_FLAG(p, f) ((p)->flags |= (f))
25 #define CLEAR_FLAG(p, f) ((p)->flags &= ~(f))
26
27 #define BYTE_0(x) (uint8_t)(((x) >> 0) & 0xFF)
28 #define BYTE_1(x) (uint8_t)(((x) >> 8) & 0xFF)
29 #define BYTE_2(x) (uint8_t)(((x) >> 16) & 0xFF)
30 #define BYTE_3(x) (uint8_t)(((x) >> 24) & 0xFF)
31
32 #define GET_CURRENT_PD(p) ((p)->current_pd)
33 #define SET_CURRENT_PD(p, i) \
34 do { \
35 (p)->current_pd = osdp_to_pd(p, i); \
36 } while (0)
37 #define PD_MASK(ctx) \
38 (uint32_t)((1 << ((ctx)->num_pd)) - 1)
39 #define AES_PAD_LEN(x) ((x + 16 - 1) & (~(16 - 1)))
40 #define NUM_PD(ctx) ((ctx)->num_pd)
41
42 /**
43 * @brief OSDP reserved commands
44 */
45 #define CMD_POLL 0x60
46 #define CMD_ID 0x61
47 #define CMD_CAP 0x62
48 #define CMD_DIAG 0x63
49 #define CMD_LSTAT 0x64
50 #define CMD_ISTAT 0x65
51 #define CMD_OSTAT 0x66
52 #define CMD_RSTAT 0x67
53 #define CMD_OUT 0x68
54 #define CMD_LED 0x69
55 #define CMD_BUZ 0x6A
56 #define CMD_TEXT 0x6B
57 #define CMD_RMODE 0x6C
58 #define CMD_TDSET 0x6D
59 #define CMD_COMSET 0x6E
60 #define CMD_DATA 0x6F
61 #define CMD_XMIT 0x70
62 #define CMD_PROMPT 0x71
63 #define CMD_SPE 0x72
64 #define CMD_BIOREAD 0x73
65 #define CMD_BIOMATCH 0x74
66 #define CMD_KEYSET 0x75
67 #define CMD_CHLNG 0x76
68 #define CMD_SCRYPT 0x77
69 #define CMD_CONT 0x79
70 #define CMD_ABORT 0x7A
71 #define CMD_MAXREPLY 0x7B
72 #define CMD_MFG 0x80
73 #define CMD_SCDONE 0xA0
74 #define CMD_XWR 0xA1
75
76 /**
77 * @brief OSDP reserved responses
78 */
79 #define REPLY_ACK 0x40
80 #define REPLY_NAK 0x41
81 #define REPLY_PDID 0x45
82 #define REPLY_PDCAP 0x46
83 #define REPLY_LSTATR 0x48
84 #define REPLY_ISTATR 0x49
85 #define REPLY_OSTATR 0x4A
86 #define REPLY_RSTATR 0x4B
87 #define REPLY_RAW 0x50
88 #define REPLY_FMT 0x51
89 #define REPLY_PRES 0x52
90 #define REPLY_KEYPPAD 0x53
91 #define REPLY_COM 0x54
92 #define REPLY_SCREP 0x55
93 #define REPLY_SPER 0x56
94 #define REPLY_BIOREADR 0x57
95 #define REPLY_BIOMATCHR 0x58
96 #define REPLY_CCRYPT 0x76
97 #define REPLY_RMAC_I 0x78
98 #define REPLY_MFGREP 0x90
99 #define REPLY_BUSY 0x79
100 #define REPLY_XRD 0xB1
101
102 /**
103 * @brief secure block types
104 */
105 #define SCS_11 0x11 /* CP -> PD -- CMD_CHLNG */
106 #define SCS_12 0x12 /* PD -> CP -- REPLY_CCRYPT */
107 #define SCS_13 0x13 /* CP -> PD -- CMD_SCRYPT */
108 #define SCS_14 0x14 /* PD -> CP -- REPLY_RMAC_I */
109
110 #define SCS_15 0x15 /* CP -> PD -- packets w MAC w/o ENC */
111 #define SCS_16 0x16 /* PD -> CP -- packets w MAC w/o ENC */
112 #define SCS_17 0x17 /* CP -> PD -- packets w MAC w ENC*/
113 #define SCS_18 0x18 /* PD -> CP -- packets w MAC w ENC*/
114
115 /* PD Flags */
116 #define PD_FLAG_SC_CAPABLE 0x00000001 /* PD secure channel capable */
117 #define PD_FLAG_TAMPER 0x00000002 /* local tamper status */
118 #define PD_FLAG_POWER 0x00000004 /* local power status */
119 #define PD_FLAG_R_TAMPER 0x00000008 /* remote tamper status */
120 #define PD_FLAG_AWAIT_RESP 0x00000020 /* set after command is sent */
121 #define PD_FLAG_SKIP_SEQ_CHECK 0x00000040 /* disable seq checks (debug) */
122 #define PD_FLAG_SC_USE_SCBKD 0x00000080 /* in this SC attempt, use SCBKD */
123 #define PD_FLAG_SC_ACTIVE 0x00000100 /* secure channel is active */
124 #define PD_FLAG_SC_SCBKD_DONE 0x00000200 /* SCBKD check is done */
125 #define PD_FLAG_PKT_HAS_MARK 0x00000400 /* Packet has mark byte */
126 #define PD_FLAG_PKT_SKIP_MARK 0x00000800 /* CONFIG_OSDP_SKIP_MARK_BYTE */
127 #define PD_FLAG_HAS_SCBK 0x00001000 /* PD has a dedicated SCBK */
128 #define PD_FLAG_INSTALL_MODE 0x40000000 /* PD is in install mode */
129 #define PD_FLAG_PD_MODE 0x80000000 /* device is setup as PD */
130
131 enum osdp_pd_nak_code_e {
132 /**
133 * @brief Dummy
134 */
135 OSDP_PD_NAK_NONE,
136 /**
137 * @brief Message check character(s) error (bad cksum/crc)
138 */
139 OSDP_PD_NAK_MSG_CHK,
140 /**
141 * @brief Command length error
142 */
143 OSDP_PD_NAK_CMD_LEN,
144 /**
145 * @brief Unknown Command Code – Command not implemented by PD
146 */
147 OSDP_PD_NAK_CMD_UNKNOWN,
148 /**
149 * @brief Unexpected sequence number detected in the header
150 */
151 OSDP_PD_NAK_SEQ_NUM,
152 /**
153 * @brief Unexpected sequence number detected in the header
154 */
155 OSDP_PD_NAK_SC_UNSUP,
156 /**
157 * @brief unsupported security block or security conditions not met
158 */
159 OSDP_PD_NAK_SC_COND,
160 /**
161 * @brief BIO_TYPE not supported
162 */
163 OSDP_PD_NAK_BIO_TYPE,
164 /**
165 * @brief BIO_FORMAT not supported
166 */
167 OSDP_PD_NAK_BIO_FMT,
168 /**
169 * @brief Unable to process command record
170 */
171 OSDP_PD_NAK_RECORD,
172 /**
173 * @brief Dummy
174 */
175 OSDP_PD_NAK_SENTINEL
176 };
177
178 enum osdp_pd_state_e {
179 OSDP_PD_STATE_IDLE,
180 OSDP_PD_STATE_SEND_REPLY,
181 OSDP_PD_STATE_ERR,
182 };
183
184 enum osdp_cp_phy_state_e {
185 OSDP_CP_PHY_STATE_IDLE,
186 OSDP_CP_PHY_STATE_SEND_CMD,
187 OSDP_CP_PHY_STATE_REPLY_WAIT,
188 OSDP_CP_PHY_STATE_WAIT,
189 OSDP_CP_PHY_STATE_ERR,
190 };
191
192 enum osdp_cp_state_e {
193 OSDP_CP_STATE_INIT,
194 OSDP_CP_STATE_IDREQ,
195 OSDP_CP_STATE_CAPDET,
196 OSDP_CP_STATE_SC_INIT,
197 OSDP_CP_STATE_SC_CHLNG,
198 OSDP_CP_STATE_SC_SCRYPT,
199 OSDP_CP_STATE_SET_SCBK,
200 OSDP_CP_STATE_ONLINE,
201 OSDP_CP_STATE_OFFLINE
202 };
203
204 enum osdp_pkt_errors_e {
205 OSDP_ERR_PKT_NONE = 0,
206 /**
207 * Fatal packet formatting issues. The phy layer was unable to find a
208 * valid OSDP packet or the length of the packet was too long/incorrect.
209 */
210 OSDP_ERR_PKT_FMT = -1,
211 /**
212 * Not enough data in buffer; wait for more data (or timeout).
213 */
214 OSDP_ERR_PKT_WAIT = -2,
215 /**
216 * Message to/from an foreign device that can be safely ignored
217 * without altering the state of this PD.
218 */
219 OSDP_ERR_PKT_SKIP = -3,
220 /**
221 * Packet was valid but does not match some conditions. ie., only this
222 * packet is faulty, rest of the buffer may still be intact.
223 */
224 OSDP_ERR_PKT_CHECK = -4,
225 /**
226 * Discovered a busy packet. In CP mode, it should retry this command
227 * after some time.
228 */
229 OSDP_ERR_PKT_BUSY = -5,
230 /**
231 * Phy layer found a reason to send NACK to the CP that produced
232 * this packet; pd->reply_id is set REPLY_NAK and the reason code is
233 * also filled.
234 */
235 OSDP_ERR_PKT_NACK = -6,
236 };
237
238 /**
239 * @brief Various PD capability function codes.
240 */
241 enum osdp_pd_cap_function_code_e {
242 /**
243 * @brief Dummy.
244 */
245 OSDP_PD_CAP_UNUSED,
246
247 /**
248 * @brief This function indicates the ability to monitor the status of a
249 * switch using a two-wire electrical connection between the PD and the
250 * switch. The on/off position of the switch indicates the state of an
251 * external device.
252 *
253 * The PD may simply resolve all circuit states to an open/closed
254 * status, or it may implement supervision of the monitoring circuit.
255 * A supervised circuit is able to indicate circuit fault status in
256 * addition to open/closed status.
257 */
258 OSDP_PD_CAP_CONTACT_STATUS_MONITORING,
259
260 /**
261 * @brief This function provides a switched output, typically in the
262 * form of a relay. The Output has two states: active or inactive. The
263 * Control Panel (CP) can directly set the Output's state, or, if the PD
264 * supports timed operations, the CP can specify a time period for the
265 * activation of the Output.
266 */
267 OSDP_PD_CAP_OUTPUT_CONTROL,
268
269 /**
270 * @brief This capability indicates the form of the card data is
271 * presented to the Control Panel.
272 */
273 OSDP_PD_CAP_CARD_DATA_FORMAT,
274
275 /**
276 * @brief This capability indicates the presence of and type of LEDs.
277 */
278 OSDP_PD_CAP_READER_LED_CONTROL,
279
280 /**
281 * @brief This capability indicates the presence of and type of an
282 * Audible Annunciator (buzzer or similar tone generator)
283 */
284 OSDP_PD_CAP_READER_AUDIBLE_OUTPUT,
285
286 /**
287 * @brief This capability indicates that the PD supports a text display
288 * emulating character-based display terminals.
289 */
290 OSDP_PD_CAP_READER_TEXT_OUTPUT,
291
292 /**
293 * @brief This capability indicates that the type of date and time
294 * awareness or time keeping ability of the PD.
295 */
296 OSDP_PD_CAP_TIME_KEEPING,
297
298 /**
299 * @brief All PDs must be able to support the checksum mode. This
300 * capability indicates if the PD is capable of supporting CRC mode.
301 */
302 OSDP_PD_CAP_CHECK_CHARACTER_SUPPORT,
303
304 /**
305 * @brief This capability indicates the extent to which the PD supports
306 * communication security (Secure Channel Communication)
307 */
308 OSDP_PD_CAP_COMMUNICATION_SECURITY,
309
310 /**
311 * @brief This capability indicates the maximum size single message the
312 * PD can receive.
313 */
314 OSDP_PD_CAP_RECEIVE_BUFFERSIZE,
315
316 /**
317 * @brief This capability indicates the maximum size multi-part message
318 * which the PD can handle.
319 */
320 OSDP_PD_CAP_LARGEST_COMBINED_MESSAGE_SIZE,
321
322 /**
323 * @brief This capability indicates whether the PD supports the
324 * transparent mode used for communicating directly with a smart card.
325 */
326 OSDP_PD_CAP_SMART_CARD_SUPPORT,
327
328 /**
329 * @brief This capability indicates the number of credential reader
330 * devices present. Compliance levels are bit fields to be assigned as
331 * needed.
332 */
333 OSDP_PD_CAP_READERS,
334
335 /**
336 * @brief This capability indicates the ability of the reader to handle
337 * biometric input
338 */
339 OSDP_PD_CAP_BIOMETRICS,
340
341 /**
342 * @brief Capability Sentinel
343 */
344 OSDP_PD_CAP_SENTINEL
345 };
346
347 /* Unused type only to estimate ephemeral_data size */
348 union osdp_ephemeral_data {
349 struct osdp_cmd cmd;
350 struct osdp_event event;
351 };
352 #define OSDP_EPHEMERAL_DATA_MAX_LEN sizeof(union osdp_ephemeral_data)
353
354 /**
355 * @brief PD capability structure. Each PD capability has a 3 byte
356 * representation.
357 *
358 * @param function_code One of enum osdp_pd_cap_function_code_e.
359 * @param compliance_level A function_code dependent number that indicates what
360 * the PD can do with this capability.
361 * @param num_items Number of such capability entities in PD.
362 */
363 struct osdp_pd_cap {
364 uint8_t function_code;
365 uint8_t compliance_level;
366 uint8_t num_items;
367 };
368
369 /**
370 * @brief PD ID information advertised by the PD.
371 *
372 * @param version 3-bytes IEEE assigned OUI
373 * @param model 1-byte Manufacturer's model number
374 * @param vendor_code 1-Byte Manufacturer's version number
375 * @param serial_number 4-byte serial number for the PD
376 * @param firmware_version 3-byte version (major, minor, build)
377 */
378 struct osdp_pd_id {
379 int version;
380 int model;
381 uint32_t vendor_code;
382 uint32_t serial_number;
383 uint32_t firmware_version;
384 };
385
386 struct osdp_channel {
387 /**
388 * @brief pointer to a block of memory that will be passed to the
389 * send/receive method. This is optional and can be left empty.
390 */
391 void *data;
392
393 /**
394 * @brief pointer to function that copies received bytes into buffer
395 * @param data for use by underlying layers. channel_s::data is passed
396 * @param buf byte array copy incoming data
397 * @param len sizeof `buf`. Can copy utmost `len` bytes into `buf`
398 *
399 * @retval +ve: number of bytes copied on to `bug`. Must be <= `len`
400 * @retval -ve on errors
401 */
402 int (*recv)(void *data, uint8_t *buf, int maxlen);
403
404 /**
405 * @brief pointer to function that sends byte array into some channel
406 * @param data for use by underlying layers. channel_s::data is passed
407 * @param buf byte array to be sent
408 * @param len number of bytes in `buf`
409 *
410 * @retval +ve: number of bytes sent. must be <= `len`
411 * @retval -ve on errors
412 */
413 int (*send)(void *data, uint8_t *buf, int len);
414
415 /**
416 * @brief pointer to function that drops all bytes in TX/RX fifo
417 * @param data for use by underlying layers. channel_s::data is passed
418 */
419 void (*flush)(void *data);
420 };
421
422 struct osdp_queue {
423 sys_slist_t queue;
424 struct k_mem_slab slab;
425 uint8_t slab_buf[OSDP_QUEUE_SLAB_SIZE];
426 };
427
428 #ifdef CONFIG_OSDP_SC_ENABLED
429 struct osdp_secure_channel {
430 uint8_t scbk[16];
431 uint8_t s_enc[16];
432 uint8_t s_mac1[16];
433 uint8_t s_mac2[16];
434 uint8_t r_mac[16];
435 uint8_t c_mac[16];
436 uint8_t cp_random[8];
437 uint8_t pd_random[8];
438 uint8_t pd_client_uid[8];
439 uint8_t cp_cryptogram[16];
440 uint8_t pd_cryptogram[16];
441 };
442 #endif
443
444 struct osdp_pd {
445 void *osdp_ctx;
446 int idx;
447 uint32_t flags;
448
449 /* OSDP specified data */
450 int baud_rate;
451 int address;
452 int seq_number;
453 struct osdp_pd_cap cap[OSDP_PD_CAP_SENTINEL];
454 struct osdp_pd_id id;
455
456 /* PD state management */
457 #ifdef CONFIG_OSDP_MODE_PD
458 enum osdp_pd_state_e state;
459 #else
460 enum osdp_cp_state_e state;
461 enum osdp_cp_phy_state_e phy_state;
462 uint32_t wait_ms;
463 int64_t phy_tstamp;
464 #endif
465 int64_t tstamp;
466 uint8_t rx_buf[OSDP_PACKET_BUF_SIZE];
467 int rx_buf_len;
468
469 int cmd_id;
470 int reply_id;
471 uint8_t ephemeral_data[OSDP_EPHEMERAL_DATA_MAX_LEN];
472
473 struct osdp_channel channel;
474
475 union {
476 struct osdp_queue cmd; /* Command queue (CP Mode only) */
477 struct osdp_queue event; /* Command queue (PD Mode only) */
478 };
479
480 /* PD command callback to app with opaque arg pointer as passed by app */
481 void *command_callback_arg;
482 pd_command_callback_t command_callback;
483
484 #ifdef CONFIG_OSDP_SC_ENABLED
485 int64_t sc_tstamp;
486 struct osdp_secure_channel sc;
487 #endif
488 };
489
490 struct osdp {
491 int magic;
492 uint32_t flags;
493 int num_pd;
494 struct osdp_pd *current_pd; /* current operational pd's pointer */
495 struct osdp_pd *pd;
496 #ifdef CONFIG_OSDP_SC_ENABLED
497 uint8_t sc_master_key[16];
498 #endif
499 /* CP event callback to app with opaque arg pointer as passed by app */
500 void *event_callback_arg;
501 cp_event_callback_t event_callback;
502 };
503
504 #ifdef CONFIG_OSDP_MODE_PD
cp_keyset_complete(struct osdp_pd * pd)505 static inline void cp_keyset_complete(struct osdp_pd *pd) { }
506 #else
507 void cp_keyset_complete(struct osdp_pd *pd);
508 #endif
509
510 void osdp_keyset_complete(struct osdp_pd *pd);
511
512 /* from osdp_phy.c */
513 int osdp_phy_packet_init(struct osdp_pd *p, uint8_t *buf, int max_len);
514 int osdp_phy_packet_finalize(struct osdp_pd *p, uint8_t *buf,
515 int len, int max_len);
516 int osdp_phy_check_packet(struct osdp_pd *pd, uint8_t *buf, int len,
517 int *one_pkt_len);
518 int osdp_phy_decode_packet(struct osdp_pd *p, uint8_t *buf, int len,
519 uint8_t **pkt_start);
520 void osdp_phy_state_reset(struct osdp_pd *pd);
521 int osdp_phy_packet_get_data_offset(struct osdp_pd *p, const uint8_t *buf);
522 uint8_t *osdp_phy_packet_get_smb(struct osdp_pd *p, const uint8_t *buf);
523
524 /* from osdp_common.c */
525 int64_t osdp_millis_now(void);
526 int64_t osdp_millis_since(int64_t last);
527 void osdp_dump(const char *head, uint8_t *buf, int len);
528 uint16_t osdp_compute_crc16(const uint8_t *buf, size_t len);
529
530 /* from osdp.c */
531 struct osdp *osdp_get_ctx();
532
533 /* from osdp_cp.c */
534 #ifdef CONFIG_OSDP_MODE_CP
535 int osdp_extract_address(int *address);
536 #endif
537
538 #ifdef CONFIG_OSDP_SC_ENABLED
539 void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
540 void osdp_decrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
541 #endif
542
543 /* from osdp_sc.c */
544 void osdp_compute_scbk(struct osdp_pd *pd, uint8_t *master_key, uint8_t *scbk);
545 void osdp_compute_session_keys(struct osdp_pd *pd);
546 void osdp_compute_cp_cryptogram(struct osdp_pd *pd);
547 int osdp_verify_cp_cryptogram(struct osdp_pd *pd);
548 void osdp_compute_pd_cryptogram(struct osdp_pd *pd);
549 int osdp_verify_pd_cryptogram(struct osdp_pd *pd);
550 void osdp_compute_rmac_i(struct osdp_pd *pd);
551 int osdp_decrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
552 int osdp_encrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
553 int osdp_compute_mac(struct osdp_pd *pd, int is_cmd,
554 const uint8_t *data, int len);
555 void osdp_sc_setup(struct osdp_pd *pd);
556 void osdp_fill_random(uint8_t *buf, int len);
557
558 /* must be implemented by CP or PD */
559 int osdp_setup(struct osdp *ctx, uint8_t *key);
560 void osdp_update(struct osdp *ctx);
561
pd_to_osdp(struct osdp_pd * pd)562 static inline struct osdp *pd_to_osdp(struct osdp_pd *pd)
563 {
564 return pd->osdp_ctx;
565 }
566
osdp_to_pd(struct osdp * ctx,int pd_idx)567 static inline struct osdp_pd *osdp_to_pd(struct osdp *ctx, int pd_idx)
568 {
569 return ctx->pd + pd_idx;
570 }
571
is_pd_mode(struct osdp_pd * pd)572 static inline bool is_pd_mode(struct osdp_pd *pd)
573 {
574 return ISSET_FLAG(pd, PD_FLAG_PD_MODE);
575 }
576
is_cp_mode(struct osdp_pd * pd)577 static inline bool is_cp_mode(struct osdp_pd *pd)
578 {
579 return !ISSET_FLAG(pd, PD_FLAG_PD_MODE);
580 }
581
sc_is_capable(struct osdp_pd * pd)582 static inline bool sc_is_capable(struct osdp_pd *pd)
583 {
584 return ISSET_FLAG(pd, PD_FLAG_SC_CAPABLE);
585 }
586
sc_is_active(struct osdp_pd * pd)587 static inline bool sc_is_active(struct osdp_pd *pd)
588 {
589 return ISSET_FLAG(pd, PD_FLAG_SC_ACTIVE);
590 }
591
sc_activate(struct osdp_pd * pd)592 static inline void sc_activate(struct osdp_pd *pd)
593 {
594 SET_FLAG(pd, PD_FLAG_SC_ACTIVE);
595 }
596
sc_deactivate(struct osdp_pd * pd)597 static inline void sc_deactivate(struct osdp_pd *pd)
598 {
599 CLEAR_FLAG(pd, PD_FLAG_SC_ACTIVE);
600 }
601
602 #endif /* _OSDP_COMMON_H_ */
603