1 /*
2 * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <ctype.h>
8
9 #include <device.h>
10 #include <sys/crc.h>
11 #include <logging/log.h>
12
13 #ifdef CONFIG_OSDP_SC_ENABLED
14 #include <crypto/cipher.h>
15 #include <random/rand32.h>
16 #endif
17
18 #include "osdp_common.h"
19
20 LOG_MODULE_DECLARE(osdp, CONFIG_OSDP_LOG_LEVEL);
21
osdp_dump(const char * head,uint8_t * buf,int len)22 void osdp_dump(const char *head, uint8_t *buf, int len)
23 {
24 LOG_HEXDUMP_DBG(buf, len, head);
25 }
26
osdp_compute_crc16(const uint8_t * buf,size_t len)27 uint16_t osdp_compute_crc16(const uint8_t *buf, size_t len)
28 {
29 return crc16_itu_t(0x1D0F, buf, len);
30 }
31
osdp_millis_now(void)32 int64_t osdp_millis_now(void)
33 {
34 return (int64_t) k_uptime_get();
35 }
36
osdp_millis_since(int64_t last)37 int64_t osdp_millis_since(int64_t last)
38 {
39 int64_t tmp = last;
40
41 return (int64_t) k_uptime_delta(&tmp);
42 }
43
osdp_cmd_alloc(struct osdp_pd * pd)44 struct osdp_cmd *osdp_cmd_alloc(struct osdp_pd *pd)
45 {
46 struct osdp_cmd *cmd = NULL;
47
48 if (k_mem_slab_alloc(&pd->cmd.slab, (void **)&cmd, K_MSEC(100))) {
49 LOG_ERR("Memory allocation time-out");
50 return NULL;
51 }
52 return cmd;
53 }
54
osdp_cmd_free(struct osdp_pd * pd,struct osdp_cmd * cmd)55 void osdp_cmd_free(struct osdp_pd *pd, struct osdp_cmd *cmd)
56 {
57 k_mem_slab_free(&pd->cmd.slab, (void **)&cmd);
58 }
59
osdp_cmd_enqueue(struct osdp_pd * pd,struct osdp_cmd * cmd)60 void osdp_cmd_enqueue(struct osdp_pd *pd, struct osdp_cmd *cmd)
61 {
62 sys_slist_append(&pd->cmd.queue, &cmd->node);
63 }
64
osdp_cmd_dequeue(struct osdp_pd * pd,struct osdp_cmd ** cmd)65 int osdp_cmd_dequeue(struct osdp_pd *pd, struct osdp_cmd **cmd)
66 {
67 sys_snode_t *node;
68
69 node = sys_slist_peek_head(&pd->cmd.queue);
70 if (node == NULL) {
71 return -1;
72 }
73 sys_slist_remove(&pd->cmd.queue, NULL, node);
74 *cmd = CONTAINER_OF(node, struct osdp_cmd, node);
75 return 0;
76 }
77
osdp_cmd_get_last(struct osdp_pd * pd)78 struct osdp_cmd *osdp_cmd_get_last(struct osdp_pd *pd)
79 {
80 return (struct osdp_cmd *)sys_slist_peek_tail(&pd->cmd.queue);
81 }
82
83 #ifdef CONFIG_OSDP_SC_ENABLED
84
osdp_encrypt(uint8_t * key,uint8_t * iv,uint8_t * data,int len)85 void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len)
86 {
87 const struct device *dev;
88 struct cipher_ctx ctx = {
89 .keylen = 16,
90 .key.bit_stream = key,
91 .flags = CAP_NO_IV_PREFIX
92 };
93 struct cipher_pkt encrypt = {
94 .in_buf = data,
95 .in_len = len,
96 .out_buf = data,
97 .out_len = len
98 };
99
100 dev = device_get_binding(CONFIG_OSDP_CRYPTO_DRV_NAME);
101 if (dev == NULL) {
102 LOG_ERR("Failed to get crypto dev binding!");
103 return;
104 }
105
106 if (iv != NULL) {
107 if (cipher_begin_session(dev, &ctx,
108 CRYPTO_CIPHER_ALGO_AES,
109 CRYPTO_CIPHER_MODE_CBC,
110 CRYPTO_CIPHER_OP_ENCRYPT)) {
111 LOG_ERR("Failed at cipher_begin_session");
112 return;
113 }
114 if (cipher_cbc_op(&ctx, &encrypt, iv)) {
115 LOG_ERR("CBC ENCRYPT - Failed");
116 }
117 } else {
118 if (cipher_begin_session(dev, &ctx,
119 CRYPTO_CIPHER_ALGO_AES,
120 CRYPTO_CIPHER_MODE_ECB,
121 CRYPTO_CIPHER_OP_ENCRYPT)) {
122 LOG_ERR("Failed at cipher_begin_session");
123 return;
124 }
125 if (cipher_block_op(&ctx, &encrypt)) {
126 LOG_ERR("ECB ENCRYPT - Failed");
127 }
128 }
129 cipher_free_session(dev, &ctx);
130 }
131
osdp_decrypt(uint8_t * key,uint8_t * iv,uint8_t * data,int len)132 void osdp_decrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len)
133 {
134 const struct device *dev;
135 struct cipher_ctx ctx = {
136 .keylen = 16,
137 .key.bit_stream = key,
138 .flags = CAP_NO_IV_PREFIX
139 };
140 struct cipher_pkt decrypt = {
141 .in_buf = data,
142 .in_len = len,
143 .out_buf = data,
144 .out_len = len
145 };
146
147 dev = device_get_binding(CONFIG_OSDP_CRYPTO_DRV_NAME);
148 if (dev == NULL) {
149 LOG_ERR("Failed to get crypto dev binding!");
150 return;
151 }
152
153 if (iv != NULL) {
154 if (cipher_begin_session(dev, &ctx,
155 CRYPTO_CIPHER_ALGO_AES,
156 CRYPTO_CIPHER_MODE_CBC,
157 CRYPTO_CIPHER_OP_DECRYPT)) {
158 LOG_ERR("Failed at cipher_begin_session");
159 return;
160 }
161 if (cipher_cbc_op(&ctx, &decrypt, iv)) {
162 LOG_ERR("CBC DECRYPT - Failed");
163 }
164 } else {
165 if (cipher_begin_session(dev, &ctx,
166 CRYPTO_CIPHER_ALGO_AES,
167 CRYPTO_CIPHER_MODE_ECB,
168 CRYPTO_CIPHER_OP_DECRYPT)) {
169 LOG_ERR("Failed at cipher_begin_session");
170 return;
171 }
172 if (cipher_block_op(&ctx, &decrypt)) {
173 LOG_ERR("ECB DECRYPT - Failed");
174 }
175 }
176 cipher_free_session(dev, &ctx);
177 }
178
osdp_fill_random(uint8_t * buf,int len)179 void osdp_fill_random(uint8_t *buf, int len)
180 {
181 sys_csrand_get(buf, len);
182 }
183
osdp_get_sc_status_mask(void)184 uint32_t osdp_get_sc_status_mask(void)
185 {
186 int i;
187 uint32_t mask = 0;
188 struct osdp_pd *pd;
189 struct osdp *ctx = osdp_get_ctx();
190
191 for (i = 0; i < NUM_PD(ctx); i++) {
192 pd = TO_PD(ctx, i);
193 if (ISSET_FLAG(pd, PD_FLAG_SC_ACTIVE)) {
194 mask |= 1 << i;
195 }
196 }
197 return mask;
198 }
199
200 #endif /* CONFIG_OSDP_SC_ENABLED */
201