• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/hmdfs/comm/crypto.c
4  *
5  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6  */
7 
8 #include "crypto.h"
9 
10 #include <crypto/aead.h>
11 #include <crypto/hash.h>
12 #include <linux/tcp.h>
13 #include <net/inet_connection_sock.h>
14 #include <net/tcp_states.h>
15 #include <net/tls.h>
16 
17 #include "hmdfs.h"
18 
tls_crypto_set_key(struct connection * conn_impl,int tx)19 static void tls_crypto_set_key(struct connection *conn_impl, int tx)
20 {
21 	int rc = 0;
22 	struct tcp_handle *tcp = conn_impl->connect_handle;
23 	struct tls_context *ctx = tls_get_ctx(tcp->sock->sk);
24 	struct cipher_context *cctx = NULL;
25 	struct tls_sw_context_tx *sw_ctx_tx = NULL;
26 	struct tls_sw_context_rx *sw_ctx_rx = NULL;
27 	struct crypto_aead **aead = NULL;
28 	struct tls12_crypto_info_aes_gcm_128 *crypto_info = NULL;
29 
30 	if (tx) {
31 		crypto_info = &conn_impl->send_crypto_info;
32 		cctx = &ctx->tx;
33 		sw_ctx_tx = tls_sw_ctx_tx(ctx);
34 		aead = &sw_ctx_tx->aead_send;
35 	} else {
36 		crypto_info = &conn_impl->recv_crypto_info;
37 		cctx = &ctx->rx;
38 		sw_ctx_rx = tls_sw_ctx_rx(ctx);
39 		aead = &sw_ctx_rx->aead_recv;
40 	}
41 
42 	memcpy(cctx->iv, crypto_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
43 	memcpy(cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, crypto_info->iv,
44 	       TLS_CIPHER_AES_GCM_128_IV_SIZE);
45 	memcpy(cctx->rec_seq, crypto_info->rec_seq,
46 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
47 	rc = crypto_aead_setkey(*aead, crypto_info->key,
48 				TLS_CIPHER_AES_GCM_128_KEY_SIZE);
49 	if (rc)
50 		hmdfs_err("crypto set key error");
51 }
52 
tls_crypto_info_init(struct connection * conn_impl)53 int tls_crypto_info_init(struct connection *conn_impl)
54 {
55 	int ret = 0;
56 	u8 key_meterial[HMDFS_KEY_SIZE];
57 	struct tcp_handle *tcp =
58 		(struct tcp_handle *)(conn_impl->connect_handle);
59 	if (conn_impl->node->version < DFS_2_0 || !tcp)
60 		return -EINVAL;
61 	// send
62 	update_key(conn_impl->send_key, key_meterial, HKDF_TYPE_IV);
63 	ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TCP, TCP_ULP,
64 							KERNEL_SOCKPTR("tls"), sizeof("tls"));
65 	if (ret)
66 		hmdfs_err("set tls error %d", ret);
67 	tcp->connect->send_crypto_info.info.version = TLS_1_2_VERSION;
68 	tcp->connect->send_crypto_info.info.cipher_type =
69 		TLS_CIPHER_AES_GCM_128;
70 
71 	memcpy(tcp->connect->send_crypto_info.key, tcp->connect->send_key,
72 	       TLS_CIPHER_AES_GCM_128_KEY_SIZE);
73 	memcpy(tcp->connect->send_crypto_info.iv,
74 	       key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE);
75 	memcpy(tcp->connect->send_crypto_info.salt,
76 	       key_meterial + CRYPTO_SALT_OFFSET,
77 	       TLS_CIPHER_AES_GCM_128_SALT_SIZE);
78 	memcpy(tcp->connect->send_crypto_info.rec_seq,
79 	       key_meterial + CRYPTO_SEQ_OFFSET,
80 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
81 
82 	ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TLS, TLS_TX,
83 				KERNEL_SOCKPTR(&(tcp->connect->send_crypto_info)),
84 				sizeof(tcp->connect->send_crypto_info));
85 	if (ret)
86 		hmdfs_err("set tls send_crypto_info error %d", ret);
87 
88 	// recv
89 	update_key(tcp->connect->recv_key, key_meterial, HKDF_TYPE_IV);
90 	tcp->connect->recv_crypto_info.info.version = TLS_1_2_VERSION;
91 	tcp->connect->recv_crypto_info.info.cipher_type =
92 		TLS_CIPHER_AES_GCM_128;
93 
94 	memcpy(tcp->connect->recv_crypto_info.key, tcp->connect->recv_key,
95 	       TLS_CIPHER_AES_GCM_128_KEY_SIZE);
96 	memcpy(tcp->connect->recv_crypto_info.iv,
97 	       key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE);
98 	memcpy(tcp->connect->recv_crypto_info.salt,
99 	       key_meterial + CRYPTO_SALT_OFFSET,
100 	       TLS_CIPHER_AES_GCM_128_SALT_SIZE);
101 	memcpy(tcp->connect->recv_crypto_info.rec_seq,
102 	       key_meterial + CRYPTO_SEQ_OFFSET,
103 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
104 	memset(key_meterial, 0, HMDFS_KEY_SIZE);
105 
106 	ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TLS, TLS_RX,
107 				KERNEL_SOCKPTR(&(tcp->connect->recv_crypto_info)),
108 				sizeof(tcp->connect->recv_crypto_info));
109 	if (ret)
110 		hmdfs_err("set tls recv_crypto_info error %d", ret);
111 	return ret;
112 }
113 
tls_set_tx(struct tcp_handle * tcp)114 static int tls_set_tx(struct tcp_handle *tcp)
115 {
116 	int ret = 0;
117 	u8 new_key[HMDFS_KEY_SIZE];
118 	u8 key_meterial[HMDFS_KEY_SIZE];
119 
120 	ret = update_key(tcp->connect->send_key, new_key, HKDF_TYPE_REKEY);
121 	if (ret < 0)
122 		return ret;
123 	memcpy(tcp->connect->send_key, new_key, HMDFS_KEY_SIZE);
124 	ret = update_key(tcp->connect->send_key, key_meterial, HKDF_TYPE_IV);
125 	if (ret < 0)
126 		return ret;
127 
128 	memcpy(tcp->connect->send_crypto_info.key, tcp->connect->send_key,
129 	       TLS_CIPHER_AES_GCM_128_KEY_SIZE);
130 	memcpy(tcp->connect->send_crypto_info.iv,
131 	       key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE);
132 	memcpy(tcp->connect->send_crypto_info.salt,
133 	       key_meterial + CRYPTO_SALT_OFFSET,
134 	       TLS_CIPHER_AES_GCM_128_SALT_SIZE);
135 	memcpy(tcp->connect->send_crypto_info.rec_seq,
136 	       key_meterial + CRYPTO_SEQ_OFFSET,
137 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
138 	memset(new_key, 0, HMDFS_KEY_SIZE);
139 	memset(key_meterial, 0, HMDFS_KEY_SIZE);
140 
141 	tls_crypto_set_key(tcp->connect, 1);
142 	return 0;
143 }
144 
tls_set_rx(struct tcp_handle * tcp)145 static int tls_set_rx(struct tcp_handle *tcp)
146 {
147 	int ret = 0;
148 	u8 new_key[HMDFS_KEY_SIZE];
149 	u8 key_meterial[HMDFS_KEY_SIZE];
150 
151 	ret = update_key(tcp->connect->recv_key, new_key, HKDF_TYPE_REKEY);
152 	if (ret < 0)
153 		return ret;
154 	memcpy(tcp->connect->recv_key, new_key, HMDFS_KEY_SIZE);
155 	ret = update_key(tcp->connect->recv_key, key_meterial, HKDF_TYPE_IV);
156 	if (ret < 0)
157 		return ret;
158 
159 	memcpy(tcp->connect->recv_crypto_info.key, tcp->connect->recv_key,
160 	       TLS_CIPHER_AES_GCM_128_KEY_SIZE);
161 	memcpy(tcp->connect->recv_crypto_info.iv,
162 	       key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE);
163 	memcpy(tcp->connect->recv_crypto_info.salt,
164 	       key_meterial + CRYPTO_SALT_OFFSET,
165 	       TLS_CIPHER_AES_GCM_128_SALT_SIZE);
166 	memcpy(tcp->connect->recv_crypto_info.rec_seq,
167 	       key_meterial + CRYPTO_SEQ_OFFSET,
168 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
169 	memset(new_key, 0, HMDFS_KEY_SIZE);
170 	memset(key_meterial, 0, HMDFS_KEY_SIZE);
171 	tls_crypto_set_key(tcp->connect, 0);
172 	return 0;
173 }
174 
set_crypto_info(struct connection * conn_impl,int set_type)175 int set_crypto_info(struct connection *conn_impl, int set_type)
176 {
177 	int ret = 0;
178 	__u8 version = conn_impl->node->version;
179 	struct tcp_handle *tcp =
180 		(struct tcp_handle *)(conn_impl->connect_handle);
181 	if (version < DFS_2_0 || !tcp)
182 		return -EINVAL;
183 
184 	if (set_type == SET_CRYPTO_SEND) {
185 		ret = tls_set_tx(tcp);
186 		if (ret) {
187 			hmdfs_err("tls set tx fail");
188 			return ret;
189 		}
190 	}
191 	if (set_type == SET_CRYPTO_RECV) {
192 		ret = tls_set_rx(tcp);
193 		if (ret) {
194 			hmdfs_err("tls set rx fail");
195 			return ret;
196 		}
197 	}
198 	hmdfs_info("KTLS setting success");
199 	return ret;
200 }
201 
hmac_sha256(u8 * key,u8 key_len,char * info,u8 info_len,u8 * output)202 static int hmac_sha256(u8 *key, u8 key_len, char *info, u8 info_len, u8 *output)
203 {
204 	struct crypto_shash *tfm = NULL;
205 	struct shash_desc *shash = NULL;
206 	int ret = 0;
207 
208 	if (!key)
209 		return -EINVAL;
210 
211 	tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
212 	if (IS_ERR(tfm)) {
213 		hmdfs_err("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
214 		return PTR_ERR(tfm);
215 	}
216 
217 	ret = crypto_shash_setkey(tfm, key, key_len);
218 	if (ret) {
219 		hmdfs_err("crypto_ahash_setkey failed: err %d", ret);
220 		goto failed;
221 	}
222 
223 	shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
224 			GFP_KERNEL);
225 	if (!shash) {
226 		ret = -ENOMEM;
227 		goto failed;
228 	}
229 
230 	shash->tfm = tfm;
231 
232 	ret = crypto_shash_digest(shash, info, info_len, output);
233 
234 	kfree(shash);
235 
236 failed:
237 	crypto_free_shash(tfm);
238 	return ret;
239 }
240 
241 static const char *const g_key_lable[] = { "ktls key initiator",
242 					   "ktls key accepter",
243 					   "ktls key update", "ktls iv&salt" };
244 static const int g_key_lable_len[] = { 18, 17, 15, 12 };
245 
update_key(__u8 * old_key,__u8 * new_key,int type)246 int update_key(__u8 *old_key, __u8 *new_key, int type)
247 {
248 	int ret = 0;
249 	char lable[MAX_LABLE_SIZE];
250 	u8 lable_size;
251 
252 	lable_size = g_key_lable_len[type] + sizeof(u16) + sizeof(char);
253 	*((u16 *)lable) = HMDFS_KEY_SIZE;
254 	memcpy(lable + sizeof(u16), g_key_lable[type], g_key_lable_len[type]);
255 	*(lable + sizeof(u16) + g_key_lable_len[type]) = 0x01;
256 	ret = hmac_sha256(old_key, HMDFS_KEY_SIZE, lable, lable_size, new_key);
257 	if (ret < 0)
258 		hmdfs_err("hmac sha256 error");
259 	return ret;
260 }
261