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 <mgmt/osdp.h>
11 #include <sys/__assert.h>
12 
13 #define OSDP_RESP_TOUT_MS              (200)
14 
15 #define OSDP_CMD_SLAB_BUF_SIZE \
16 	(sizeof(struct osdp_cmd) * CONFIG_OSDP_PD_COMMAND_QUEUE_SIZE)
17 
18 #define ISSET_FLAG(p, f)               (((p)->flags & (f)) == (f))
19 #define SET_FLAG(p, f)                 ((p)->flags |= (f))
20 #define CLEAR_FLAG(p, f)               ((p)->flags &= ~(f))
21 
22 #define BYTE_0(x)                      (uint8_t)(((x) >>  0) & 0xFF)
23 #define BYTE_1(x)                      (uint8_t)(((x) >>  8) & 0xFF)
24 #define BYTE_2(x)                      (uint8_t)(((x) >> 16) & 0xFF)
25 #define BYTE_3(x)                      (uint8_t)(((x) >> 24) & 0xFF)
26 
27 /* casting helpers */
28 #define TO_OSDP(p)                     ((struct osdp *)p)
29 #define TO_CP(p)                       (((struct osdp *)(p))->cp)
30 #define TO_PD(p, i)                    (((struct osdp *)(p))->pd + i)
31 #define TO_CTX(p)                      ((struct osdp *)p->__parent)
32 
33 #define GET_CURRENT_PD(p)              (TO_CP(p)->current_pd)
34 #define SET_CURRENT_PD(p, i)                                    \
35 	do {                                                    \
36 		TO_CP(p)->current_pd = TO_PD(p, i);             \
37 		TO_CP(p)->pd_offset = i;                        \
38 	} while (0)
39 #define PD_MASK(ctx) \
40 	(uint32_t)((1 << (TO_CP(ctx)->num_pd)) - 1)
41 #define AES_PAD_LEN(x)                 ((x + 16 - 1) & (~(16 - 1)))
42 #define NUM_PD(ctx)                    (TO_CP(ctx)->num_pd)
43 #define OSDP_COMMAND_DATA_MAX_LEN      sizeof(struct osdp_cmd)
44 
45 /**
46  * @brief OSDP reserved commands
47  */
48 #define CMD_POLL                0x60
49 #define CMD_ID                  0x61
50 #define CMD_CAP                 0x62
51 #define CMD_DIAG                0x63
52 #define CMD_LSTAT               0x64
53 #define CMD_ISTAT               0x65
54 #define CMD_OSTAT               0x66
55 #define CMD_RSTAT               0x67
56 #define CMD_OUT                 0x68
57 #define CMD_LED                 0x69
58 #define CMD_BUZ                 0x6A
59 #define CMD_TEXT                0x6B
60 #define CMD_RMODE               0x6C
61 #define CMD_TDSET               0x6D
62 #define CMD_COMSET              0x6E
63 #define CMD_DATA                0x6F
64 #define CMD_XMIT                0x70
65 #define CMD_PROMPT              0x71
66 #define CMD_SPE                 0x72
67 #define CMD_BIOREAD             0x73
68 #define CMD_BIOMATCH            0x74
69 #define CMD_KEYSET              0x75
70 #define CMD_CHLNG               0x76
71 #define CMD_SCRYPT              0x77
72 #define CMD_CONT                0x79
73 #define CMD_ABORT               0x7A
74 #define CMD_MAXREPLY            0x7B
75 #define CMD_MFG                 0x80
76 #define CMD_SCDONE              0xA0
77 #define CMD_XWR                 0xA1
78 
79 /**
80  * @brief OSDP reserved responses
81  */
82 #define REPLY_ACK               0x40
83 #define REPLY_NAK               0x41
84 #define REPLY_PDID              0x45
85 #define REPLY_PDCAP             0x46
86 #define REPLY_LSTATR            0x48
87 #define REPLY_ISTATR            0x49
88 #define REPLY_OSTATR            0x4A
89 #define REPLY_RSTATR            0x4B
90 #define REPLY_RAW               0x50
91 #define REPLY_FMT               0x51
92 #define REPLY_PRES              0x52
93 #define REPLY_KEYPPAD           0x53
94 #define REPLY_COM               0x54
95 #define REPLY_SCREP             0x55
96 #define REPLY_SPER              0x56
97 #define REPLY_BIOREADR          0x57
98 #define REPLY_BIOMATCHR         0x58
99 #define REPLY_CCRYPT            0x76
100 #define REPLY_RMAC_I            0x78
101 #define REPLY_MFGREP            0x90
102 #define REPLY_BUSY              0x79
103 #define REPLY_XRD               0xB1
104 
105 /**
106  * @brief secure block types
107  */
108 #define SCS_11                  0x11    /* CP -> PD -- CMD_CHLNG */
109 #define SCS_12                  0x12    /* PD -> CP -- REPLY_CCRYPT */
110 #define SCS_13                  0x13    /* CP -> PD -- CMD_SCRYPT */
111 #define SCS_14                  0x14    /* PD -> CP -- REPLY_RMAC_I */
112 
113 #define SCS_15                  0x15    /* CP -> PD -- packets w MAC w/o ENC */
114 #define SCS_16                  0x16    /* PD -> CP -- packets w MAC w/o ENC */
115 #define SCS_17                  0x17    /* CP -> PD -- packets w MAC w ENC*/
116 #define SCS_18                  0x18    /* PD -> CP -- packets w MAC w ENC*/
117 
118 /* PD Flags */
119 #define PD_FLAG_SC_CAPABLE      0x00000001 /* PD secure channel capable */
120 #define PD_FLAG_TAMPER          0x00000002 /* local tamper status */
121 #define PD_FLAG_POWER           0x00000004 /* local power status */
122 #define PD_FLAG_R_TAMPER        0x00000008 /* remote tamper status */
123 #define PD_FLAG_AWAIT_RESP      0x00000020 /* set after command is sent */
124 #define PD_FLAG_SKIP_SEQ_CHECK  0x00000040 /* disable seq checks (debug) */
125 #define PD_FLAG_SC_USE_SCBKD    0x00000080 /* in this SC attempt, use SCBKD */
126 #define PD_FLAG_SC_ACTIVE       0x00000100 /* secure channel is active */
127 #define PD_FLAG_SC_SCBKD_DONE   0x00000200 /* SCBKD check is done */
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 	OSDP_CP_PHY_STATE_ERR_WAIT,
191 	OSDP_CP_PHY_STATE_CLEANUP,
192 };
193 
194 enum osdp_cp_state_e {
195 	OSDP_CP_STATE_INIT,
196 	OSDP_CP_STATE_IDREQ,
197 	OSDP_CP_STATE_CAPDET,
198 	OSDP_CP_STATE_SC_INIT,
199 	OSDP_CP_STATE_SC_CHLNG,
200 	OSDP_CP_STATE_SC_SCRYPT,
201 	OSDP_CP_STATE_SET_SCBK,
202 	OSDP_CP_STATE_ONLINE,
203 	OSDP_CP_STATE_OFFLINE
204 };
205 
206 enum osdp_pkt_errors_e {
207 	OSDP_ERR_PKT_FMT   = -1,
208 	OSDP_ERR_PKT_WAIT  = -2,
209 	OSDP_ERR_PKT_SKIP  = -3
210 };
211 
212 /**
213  * @brief Various PD capability function codes.
214  */
215 enum osdp_pd_cap_function_code_e {
216 	/**
217 	 * @brief Dummy.
218 	 */
219 	OSDP_PD_CAP_UNUSED,
220 
221 	/**
222 	 * @brief This function indicates the ability to monitor the status of a
223 	 * switch using a two-wire electrical connection between the PD and the
224 	 * switch. The on/off position of the switch indicates the state of an
225 	 * external device.
226 	 *
227 	 * The PD may simply resolve all circuit states to an open/closed
228 	 * status, or it may implement supervision of the monitoring circuit.
229 	 * A supervised circuit is able to indicate circuit fault status in
230 	 * addition to open/closed status.
231 	 */
232 	OSDP_PD_CAP_CONTACT_STATUS_MONITORING,
233 
234 	/**
235 	 * @brief This function provides a switched output, typically in the
236 	 * form of a relay. The Output has two states: active or inactive. The
237 	 * Control Panel (CP) can directly set the Output's state, or, if the PD
238 	 * supports timed operations, the CP can specify a time period for the
239 	 * activation of the Output.
240 	 */
241 	OSDP_PD_CAP_OUTPUT_CONTROL,
242 
243 	/**
244 	 * @brief This capability indicates the form of the card data is
245 	 * presented to the Control Panel.
246 	 */
247 	OSDP_PD_CAP_CARD_DATA_FORMAT,
248 
249 	/**
250 	 * @brief This capability indicates the presence of and type of LEDs.
251 	 */
252 	OSDP_PD_CAP_READER_LED_CONTROL,
253 
254 	/**
255 	 * @brief This capability indicates the presence of and type of an
256 	 * Audible Annunciator (buzzer or similar tone generator)
257 	 */
258 	OSDP_PD_CAP_READER_AUDIBLE_OUTPUT,
259 
260 	/**
261 	 * @brief This capability indicates that the PD supports a text display
262 	 * emulating character-based display terminals.
263 	 */
264 	OSDP_PD_CAP_READER_TEXT_OUTPUT,
265 
266 	/**
267 	 * @brief This capability indicates that the type of date and time
268 	 * awareness or time keeping ability of the PD.
269 	 */
270 	OSDP_PD_CAP_TIME_KEEPING,
271 
272 	/**
273 	 * @brief All PDs must be able to support the checksum mode. This
274 	 * capability indicates if the PD is capable of supporting CRC mode.
275 	 */
276 	OSDP_PD_CAP_CHECK_CHARACTER_SUPPORT,
277 
278 	/**
279 	 * @brief This capability indicates the extent to which the PD supports
280 	 * communication security (Secure Channel Communication)
281 	 */
282 	OSDP_PD_CAP_COMMUNICATION_SECURITY,
283 
284 	/**
285 	 * @brief This capability indicates the maximum size single message the
286 	 * PD can receive.
287 	 */
288 	OSDP_PD_CAP_RECEIVE_BUFFERSIZE,
289 
290 	/**
291 	 * @brief This capability indicates the maximum size multi-part message
292 	 * which the PD can handle.
293 	 */
294 	OSDP_PD_CAP_LARGEST_COMBINED_MESSAGE_SIZE,
295 
296 	/**
297 	 * @brief This capability indicates whether the PD supports the
298 	 * transparent mode used for communicating directly with a smart card.
299 	 */
300 	OSDP_PD_CAP_SMART_CARD_SUPPORT,
301 
302 	/**
303 	 * @brief This capability indicates the number of credential reader
304 	 * devices present. Compliance levels are bit fields to be assigned as
305 	 * needed.
306 	 */
307 	OSDP_PD_CAP_READERS,
308 
309 	/**
310 	 * @brief This capability indicates the ability of the reader to handle
311 	 * biometric input
312 	 */
313 	OSDP_PD_CAP_BIOMETRICS,
314 
315 	/**
316 	 * @brief Capability Sentinel
317 	 */
318 	OSDP_PD_CAP_SENTINEL
319 };
320 
321 /**
322  * @brief PD capability structure. Each PD capability has a 3 byte
323  * representation.
324  *
325  * @param function_code One of enum osdp_pd_cap_function_code_e.
326  * @param compliance_level A function_code dependent number that indicates what
327  *                         the PD can do with this capability.
328  * @param num_items Number of such capability entities in PD.
329  */
330 struct osdp_pd_cap {
331 	uint8_t function_code;
332 	uint8_t compliance_level;
333 	uint8_t num_items;
334 };
335 
336 /**
337  * @brief PD ID information advertised by the PD.
338  *
339  * @param version 3-bytes IEEE assigned OUI
340  * @param model 1-byte Manufacturer's model number
341  * @param vendor_code 1-Byte Manufacturer's version number
342  * @param serial_number 4-byte serial number for the PD
343  * @param firmware_version 3-byte version (major, minor, build)
344  */
345 struct osdp_pd_id {
346 	int version;
347 	int model;
348 	uint32_t vendor_code;
349 	uint32_t serial_number;
350 	uint32_t firmware_version;
351 };
352 
353 struct osdp_channel {
354 	/**
355 	 * @brief pointer to a block of memory that will be passed to the
356 	 * send/receive method. This is optional and can be left empty.
357 	 */
358 	void *data;
359 
360 	/**
361 	 * @brief pointer to function that copies received bytes into buffer
362 	 * @param data for use by underlying layers. channel_s::data is passed
363 	 * @param buf byte array copy incoming data
364 	 * @param len sizeof `buf`. Can copy utmost `len` bytes into `buf`
365 	 *
366 	 * @retval +ve: number of bytes copied on to `bug`. Must be <= `len`
367 	 * @retval -ve on errors
368 	 */
369 	int (*recv)(void *data, uint8_t *buf, int maxlen);
370 
371 	/**
372 	 * @brief pointer to function that sends byte array into some channel
373 	 * @param data for use by underlying layers. channel_s::data is passed
374 	 * @param buf byte array to be sent
375 	 * @param len number of bytes in `buf`
376 	 *
377 	 * @retval +ve: number of bytes sent. must be <= `len`
378 	 * @retval -ve on errors
379 	 */
380 	int (*send)(void *data, uint8_t *buf, int len);
381 
382 	/**
383 	 * @brief pointer to function that drops all bytes in TX/RX fifo
384 	 * @param data for use by underlying layers. channel_s::data is passed
385 	 */
386 	void (*flush)(void *data);
387 };
388 
389 struct osdp_cmd_queue {
390 	sys_slist_t queue;
391 	struct k_mem_slab slab;
392 	uint8_t slab_buf[OSDP_CMD_SLAB_BUF_SIZE];
393 };
394 
395 struct osdp_notifiers {
396 	int (*keypress)(int address, uint8_t key);
397 	int (*cardread)(int address, int format, uint8_t *data, int len);
398 };
399 
400 #ifdef CONFIG_OSDP_SC_ENABLED
401 struct osdp_secure_channel {
402 	uint8_t scbk[16];
403 	uint8_t s_enc[16];
404 	uint8_t s_mac1[16];
405 	uint8_t s_mac2[16];
406 	uint8_t r_mac[16];
407 	uint8_t c_mac[16];
408 	uint8_t cp_random[8];
409 	uint8_t pd_random[8];
410 	uint8_t pd_client_uid[8];
411 	uint8_t cp_cryptogram[16];
412 	uint8_t pd_cryptogram[16];
413 };
414 #endif
415 
416 struct osdp_pd {
417 	void *__parent;
418 	int offset;
419 	uint32_t flags;
420 
421 	/* OSDP specified data */
422 	int baud_rate;
423 	int address;
424 	int seq_number;
425 	struct osdp_pd_cap cap[OSDP_PD_CAP_SENTINEL];
426 	struct osdp_pd_id id;
427 
428 	/* PD state management */
429 #ifdef CONFIG_OSDP_MODE_PD
430 	enum osdp_pd_state_e state;
431 #else
432 	enum osdp_cp_state_e state;
433 	enum osdp_cp_phy_state_e phy_state;
434 	int64_t phy_tstamp;
435 #endif
436 	int64_t tstamp;
437 	uint8_t rx_buf[CONFIG_OSDP_UART_BUFFER_LENGTH];
438 	int rx_buf_len;
439 
440 	int cmd_id;
441 	int reply_id;
442 	uint8_t cmd_data[OSDP_COMMAND_DATA_MAX_LEN];
443 
444 	struct osdp_channel channel;
445 	struct osdp_cmd_queue cmd;
446 #ifdef CONFIG_OSDP_SC_ENABLED
447 	int64_t sc_tstamp;
448 	struct osdp_secure_channel sc;
449 #endif
450 };
451 
452 struct osdp_cp {
453 	void *__parent;
454 	uint32_t flags;
455 	int num_pd;
456 	struct osdp_pd *current_pd;	/* current operational pd's pointer */
457 	int pd_offset;			/* current pd's offset into ctx->pd */
458 	struct osdp_notifiers notifier;
459 };
460 
461 struct osdp {
462 	int magic;
463 	uint32_t flags;
464 	struct osdp_cp *cp;
465 	struct osdp_pd *pd;
466 #ifdef CONFIG_OSDP_SC_ENABLED
467 	uint8_t sc_master_key[16];
468 #endif
469 };
470 
471 /* from osdp_phy.c */
472 int osdp_phy_packet_init(struct osdp_pd *p, uint8_t *buf, int max_len);
473 int osdp_phy_packet_finalize(struct osdp_pd *p, uint8_t *buf,
474 			       int len, int max_len);
475 int osdp_phy_decode_packet(struct osdp_pd *p, uint8_t *buf, int len);
476 void osdp_phy_state_reset(struct osdp_pd *pd);
477 int osdp_phy_packet_get_data_offset(struct osdp_pd *p, const uint8_t *buf);
478 uint8_t *osdp_phy_packet_get_smb(struct osdp_pd *p, const uint8_t *buf);
479 
480 /* from osdp_common.c */
481 int64_t osdp_millis_now(void);
482 int64_t osdp_millis_since(int64_t last);
483 void osdp_dump(const char *head, uint8_t *buf, int len);
484 uint16_t osdp_compute_crc16(const uint8_t *buf, size_t len);
485 struct osdp_cmd *osdp_cmd_alloc(struct osdp_pd *pd);
486 void osdp_cmd_free(struct osdp_pd *pd, struct osdp_cmd *cmd);
487 void osdp_cmd_enqueue(struct osdp_pd *pd, struct osdp_cmd *cmd);
488 int osdp_cmd_dequeue(struct osdp_pd *pd, struct osdp_cmd **cmd);
489 struct osdp_cmd *osdp_cmd_get_last(struct osdp_pd *pd);
490 
491 /* from osdp.c */
492 struct osdp *osdp_get_ctx();
493 
494 /* from osdp_cp.c */
495 #ifdef CONFIG_OSDP_MODE_CP
496 int osdp_extract_address(int *address);
497 #endif
498 
499 #ifdef CONFIG_OSDP_SC_ENABLED
500 void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
501 void osdp_decrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
502 #endif
503 
504 /* from osdp_sc.c */
505 void osdp_compute_scbk(struct osdp_pd *pd, uint8_t *scbk);
506 void osdp_compute_session_keys(struct osdp *ctx);
507 void osdp_compute_cp_cryptogram(struct osdp_pd *pd);
508 int osdp_verify_cp_cryptogram(struct osdp_pd *pd);
509 void osdp_compute_pd_cryptogram(struct osdp_pd *pd);
510 int osdp_verify_pd_cryptogram(struct osdp_pd *pd);
511 void osdp_compute_rmac_i(struct osdp_pd *pd);
512 int osdp_decrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
513 int osdp_encrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
514 int osdp_compute_mac(struct osdp_pd *pd, int is_cmd,
515 		     const uint8_t *data, int len);
516 void osdp_sc_init(struct osdp_pd *pd);
517 void osdp_fill_random(uint8_t *buf, int len);
518 
519 /* must be implemented by CP or PD */
520 int osdp_setup(struct osdp *ctx, uint8_t *key);
521 void osdp_update(struct osdp *ctx);
522 
523 #endif	/* _OSDP_COMMON_H_ */
524