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 <zephyr/device.h>
10 #include <zephyr/sys/crc.h>
11 #include <zephyr/logging/log.h>
12 
13 #ifdef CONFIG_OSDP_SC_ENABLED
14 #include <zephyr/crypto/crypto.h>
15 #include <zephyr/random/random.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_keyset_complete(struct osdp_pd * pd)44 void osdp_keyset_complete(struct osdp_pd *pd)
45 {
46 	cp_keyset_complete(pd);
47 }
48 
49 #ifdef CONFIG_OSDP_SC_ENABLED
50 
osdp_encrypt(uint8_t * key,uint8_t * iv,uint8_t * data,int len)51 void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len)
52 {
53 	const struct device *dev;
54 	struct cipher_ctx ctx = {
55 		.keylen = 16,
56 		.key.bit_stream = key,
57 		.flags = CAP_NO_IV_PREFIX
58 	};
59 	struct cipher_pkt encrypt = {
60 		.in_buf = data,
61 		.in_len = len,
62 		.out_buf = data,
63 		.out_len = len
64 	};
65 
66 	dev = device_get_binding(CONFIG_OSDP_CRYPTO_DRV_NAME);
67 	if (dev == NULL) {
68 		LOG_ERR("Failed to get crypto dev binding!");
69 		return;
70 	}
71 
72 	if (iv != NULL) {
73 		if (cipher_begin_session(dev, &ctx,
74 					 CRYPTO_CIPHER_ALGO_AES,
75 					 CRYPTO_CIPHER_MODE_CBC,
76 					 CRYPTO_CIPHER_OP_ENCRYPT)) {
77 			LOG_ERR("Failed at cipher_begin_session");
78 			return;
79 		}
80 		if (cipher_cbc_op(&ctx, &encrypt, iv)) {
81 			LOG_ERR("CBC ENCRYPT - Failed");
82 		}
83 	} else {
84 		if (cipher_begin_session(dev, &ctx,
85 					 CRYPTO_CIPHER_ALGO_AES,
86 					 CRYPTO_CIPHER_MODE_ECB,
87 					 CRYPTO_CIPHER_OP_ENCRYPT)) {
88 			LOG_ERR("Failed at cipher_begin_session");
89 			return;
90 		}
91 		if (cipher_block_op(&ctx, &encrypt)) {
92 			LOG_ERR("ECB ENCRYPT - Failed");
93 		}
94 	}
95 	cipher_free_session(dev, &ctx);
96 }
97 
osdp_decrypt(uint8_t * key,uint8_t * iv,uint8_t * data,int len)98 void osdp_decrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len)
99 {
100 	const struct device *dev;
101 	struct cipher_ctx ctx = {
102 		.keylen = 16,
103 		.key.bit_stream = key,
104 		.flags = CAP_NO_IV_PREFIX
105 	};
106 	struct cipher_pkt decrypt = {
107 		.in_buf = data,
108 		.in_len = len,
109 		.out_buf = data,
110 		.out_len = len
111 	};
112 
113 	dev = device_get_binding(CONFIG_OSDP_CRYPTO_DRV_NAME);
114 	if (dev == NULL) {
115 		LOG_ERR("Failed to get crypto dev binding!");
116 		return;
117 	}
118 
119 	if (iv != NULL) {
120 		if (cipher_begin_session(dev, &ctx,
121 					 CRYPTO_CIPHER_ALGO_AES,
122 					 CRYPTO_CIPHER_MODE_CBC,
123 					 CRYPTO_CIPHER_OP_DECRYPT)) {
124 			LOG_ERR("Failed at cipher_begin_session");
125 			return;
126 		}
127 		if (cipher_cbc_op(&ctx, &decrypt, iv)) {
128 			LOG_ERR("CBC DECRYPT - Failed");
129 		}
130 	} else {
131 		if (cipher_begin_session(dev, &ctx,
132 					 CRYPTO_CIPHER_ALGO_AES,
133 					 CRYPTO_CIPHER_MODE_ECB,
134 					 CRYPTO_CIPHER_OP_DECRYPT)) {
135 			LOG_ERR("Failed at cipher_begin_session");
136 			return;
137 		}
138 		if (cipher_block_op(&ctx, &decrypt)) {
139 			LOG_ERR("ECB DECRYPT - Failed");
140 		}
141 	}
142 	cipher_free_session(dev, &ctx);
143 }
144 
osdp_fill_random(uint8_t * buf,int len)145 void osdp_fill_random(uint8_t *buf, int len)
146 {
147 	sys_csrand_get(buf, len);
148 }
149 
osdp_get_sc_status_mask(void)150 uint32_t osdp_get_sc_status_mask(void)
151 {
152 	int i;
153 	uint32_t mask = 0;
154 	struct osdp_pd *pd;
155 	struct osdp *ctx = osdp_get_ctx();
156 
157 	for (i = 0; i < NUM_PD(ctx); i++) {
158 		pd = osdp_to_pd(ctx, i);
159 		if (ISSET_FLAG(pd, PD_FLAG_SC_ACTIVE)) {
160 			mask |= 1 << i;
161 		}
162 	}
163 	return mask;
164 }
165 
166 #endif /* CONFIG_OSDP_SC_ENABLED */
167