18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/hmdfs/comm/crypto.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "crypto.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <crypto/aead.h> 118c2ecf20Sopenharmony_ci#include <crypto/hash.h> 128c2ecf20Sopenharmony_ci#include <linux/tcp.h> 138c2ecf20Sopenharmony_ci#include <net/inet_connection_sock.h> 148c2ecf20Sopenharmony_ci#include <net/tcp_states.h> 158c2ecf20Sopenharmony_ci#include <net/tls.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "hmdfs.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void tls_crypto_set_key(struct connection *conn_impl, int tx) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci int rc = 0; 228c2ecf20Sopenharmony_ci struct tcp_handle *tcp = conn_impl->connect_handle; 238c2ecf20Sopenharmony_ci struct tls_context *ctx = NULL; 248c2ecf20Sopenharmony_ci struct cipher_context *cctx = NULL; 258c2ecf20Sopenharmony_ci struct tls_sw_context_tx *sw_ctx_tx = NULL; 268c2ecf20Sopenharmony_ci struct tls_sw_context_rx *sw_ctx_rx = NULL; 278c2ecf20Sopenharmony_ci struct crypto_aead **aead = NULL; 288c2ecf20Sopenharmony_ci struct tls12_crypto_info_aes_gcm_128 *crypto_info = NULL; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci lock_sock(tcp->sock->sk); 318c2ecf20Sopenharmony_ci ctx = tls_get_ctx(tcp->sock->sk); 328c2ecf20Sopenharmony_ci if (tx) { 338c2ecf20Sopenharmony_ci crypto_info = &conn_impl->send_crypto_info; 348c2ecf20Sopenharmony_ci cctx = &ctx->tx; 358c2ecf20Sopenharmony_ci sw_ctx_tx = tls_sw_ctx_tx(ctx); 368c2ecf20Sopenharmony_ci aead = &sw_ctx_tx->aead_send; 378c2ecf20Sopenharmony_ci } else { 388c2ecf20Sopenharmony_ci crypto_info = &conn_impl->recv_crypto_info; 398c2ecf20Sopenharmony_ci cctx = &ctx->rx; 408c2ecf20Sopenharmony_ci sw_ctx_rx = tls_sw_ctx_rx(ctx); 418c2ecf20Sopenharmony_ci aead = &sw_ctx_rx->aead_recv; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci memcpy(cctx->iv, crypto_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE); 458c2ecf20Sopenharmony_ci memcpy(cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, crypto_info->iv, 468c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_IV_SIZE); 478c2ecf20Sopenharmony_ci memcpy(cctx->rec_seq, crypto_info->rec_seq, 488c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); 498c2ecf20Sopenharmony_ci rc = crypto_aead_setkey(*aead, crypto_info->key, 508c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_KEY_SIZE); 518c2ecf20Sopenharmony_ci if (rc) 528c2ecf20Sopenharmony_ci hmdfs_err("crypto set key error"); 538c2ecf20Sopenharmony_ci release_sock(tcp->sock->sk); 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint tls_crypto_info_init(struct connection *conn_impl) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int ret = 0; 598c2ecf20Sopenharmony_ci u8 key_meterial[HMDFS_KEY_SIZE]; 608c2ecf20Sopenharmony_ci struct tcp_handle *tcp = 618c2ecf20Sopenharmony_ci (struct tcp_handle *)(conn_impl->connect_handle); 628c2ecf20Sopenharmony_ci if (!tcp) 638c2ecf20Sopenharmony_ci return -EINVAL; 648c2ecf20Sopenharmony_ci // send 658c2ecf20Sopenharmony_ci update_key(conn_impl->send_key, key_meterial, HKDF_TYPE_IV); 668c2ecf20Sopenharmony_ci ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TCP, TCP_ULP, 678c2ecf20Sopenharmony_ci KERNEL_SOCKPTR("tls"), sizeof("tls")); 688c2ecf20Sopenharmony_ci if (ret) 698c2ecf20Sopenharmony_ci hmdfs_err("set tls error %d", ret); 708c2ecf20Sopenharmony_ci tcp->connect->send_crypto_info.info.version = TLS_1_2_VERSION; 718c2ecf20Sopenharmony_ci tcp->connect->send_crypto_info.info.cipher_type = 728c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.key, tcp->connect->send_key, 758c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_KEY_SIZE); 768c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.iv, 778c2ecf20Sopenharmony_ci key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE); 788c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.salt, 798c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SALT_OFFSET, 808c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_SALT_SIZE); 818c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.rec_seq, 828c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SEQ_OFFSET, 838c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TLS, TLS_TX, 868c2ecf20Sopenharmony_ci KERNEL_SOCKPTR(&(tcp->connect->send_crypto_info)), 878c2ecf20Sopenharmony_ci sizeof(tcp->connect->send_crypto_info)); 888c2ecf20Sopenharmony_ci if (ret) 898c2ecf20Sopenharmony_ci hmdfs_err("set tls send_crypto_info error %d", ret); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci // recv 928c2ecf20Sopenharmony_ci update_key(tcp->connect->recv_key, key_meterial, HKDF_TYPE_IV); 938c2ecf20Sopenharmony_ci tcp->connect->recv_crypto_info.info.version = TLS_1_2_VERSION; 948c2ecf20Sopenharmony_ci tcp->connect->recv_crypto_info.info.cipher_type = 958c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.key, tcp->connect->recv_key, 988c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_KEY_SIZE); 998c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.iv, 1008c2ecf20Sopenharmony_ci key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE); 1018c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.salt, 1028c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SALT_OFFSET, 1038c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_SALT_SIZE); 1048c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.rec_seq, 1058c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SEQ_OFFSET, 1068c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); 1078c2ecf20Sopenharmony_ci memset(key_meterial, 0, HMDFS_KEY_SIZE); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci ret = tcp->sock->ops->setsockopt(tcp->sock, SOL_TLS, TLS_RX, 1108c2ecf20Sopenharmony_ci KERNEL_SOCKPTR(&(tcp->connect->recv_crypto_info)), 1118c2ecf20Sopenharmony_ci sizeof(tcp->connect->recv_crypto_info)); 1128c2ecf20Sopenharmony_ci if (ret) 1138c2ecf20Sopenharmony_ci hmdfs_err("set tls recv_crypto_info error %d", ret); 1148c2ecf20Sopenharmony_ci return ret; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int tls_set_tx(struct tcp_handle *tcp) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci int ret = 0; 1208c2ecf20Sopenharmony_ci u8 new_key[HMDFS_KEY_SIZE]; 1218c2ecf20Sopenharmony_ci u8 key_meterial[HMDFS_KEY_SIZE]; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci ret = update_key(tcp->connect->send_key, new_key, HKDF_TYPE_REKEY); 1248c2ecf20Sopenharmony_ci if (ret < 0) 1258c2ecf20Sopenharmony_ci return ret; 1268c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_key, new_key, HMDFS_KEY_SIZE); 1278c2ecf20Sopenharmony_ci ret = update_key(tcp->connect->send_key, key_meterial, HKDF_TYPE_IV); 1288c2ecf20Sopenharmony_ci if (ret < 0) 1298c2ecf20Sopenharmony_ci return ret; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.key, tcp->connect->send_key, 1328c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_KEY_SIZE); 1338c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.iv, 1348c2ecf20Sopenharmony_ci key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE); 1358c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.salt, 1368c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SALT_OFFSET, 1378c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_SALT_SIZE); 1388c2ecf20Sopenharmony_ci memcpy(tcp->connect->send_crypto_info.rec_seq, 1398c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SEQ_OFFSET, 1408c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); 1418c2ecf20Sopenharmony_ci memset(new_key, 0, HMDFS_KEY_SIZE); 1428c2ecf20Sopenharmony_ci memset(key_meterial, 0, HMDFS_KEY_SIZE); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci tls_crypto_set_key(tcp->connect, 1); 1458c2ecf20Sopenharmony_ci return 0; 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic int tls_set_rx(struct tcp_handle *tcp) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci int ret = 0; 1518c2ecf20Sopenharmony_ci u8 new_key[HMDFS_KEY_SIZE]; 1528c2ecf20Sopenharmony_ci u8 key_meterial[HMDFS_KEY_SIZE]; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ret = update_key(tcp->connect->recv_key, new_key, HKDF_TYPE_REKEY); 1558c2ecf20Sopenharmony_ci if (ret < 0) 1568c2ecf20Sopenharmony_ci return ret; 1578c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_key, new_key, HMDFS_KEY_SIZE); 1588c2ecf20Sopenharmony_ci ret = update_key(tcp->connect->recv_key, key_meterial, HKDF_TYPE_IV); 1598c2ecf20Sopenharmony_ci if (ret < 0) 1608c2ecf20Sopenharmony_ci return ret; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.key, tcp->connect->recv_key, 1638c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_KEY_SIZE); 1648c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.iv, 1658c2ecf20Sopenharmony_ci key_meterial + CRYPTO_IV_OFFSET, TLS_CIPHER_AES_GCM_128_IV_SIZE); 1668c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.salt, 1678c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SALT_OFFSET, 1688c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_SALT_SIZE); 1698c2ecf20Sopenharmony_ci memcpy(tcp->connect->recv_crypto_info.rec_seq, 1708c2ecf20Sopenharmony_ci key_meterial + CRYPTO_SEQ_OFFSET, 1718c2ecf20Sopenharmony_ci TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); 1728c2ecf20Sopenharmony_ci memset(new_key, 0, HMDFS_KEY_SIZE); 1738c2ecf20Sopenharmony_ci memset(key_meterial, 0, HMDFS_KEY_SIZE); 1748c2ecf20Sopenharmony_ci tls_crypto_set_key(tcp->connect, 0); 1758c2ecf20Sopenharmony_ci return 0; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciint set_crypto_info(struct connection *conn_impl, int set_type) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci int ret = 0; 1818c2ecf20Sopenharmony_ci struct tcp_handle *tcp = 1828c2ecf20Sopenharmony_ci (struct tcp_handle *)(conn_impl->connect_handle); 1838c2ecf20Sopenharmony_ci if (!tcp) 1848c2ecf20Sopenharmony_ci return -EINVAL; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (set_type == SET_CRYPTO_SEND) { 1878c2ecf20Sopenharmony_ci ret = tls_set_tx(tcp); 1888c2ecf20Sopenharmony_ci if (ret) { 1898c2ecf20Sopenharmony_ci hmdfs_err("tls set tx fail"); 1908c2ecf20Sopenharmony_ci return ret; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci if (set_type == SET_CRYPTO_RECV) { 1948c2ecf20Sopenharmony_ci ret = tls_set_rx(tcp); 1958c2ecf20Sopenharmony_ci if (ret) { 1968c2ecf20Sopenharmony_ci hmdfs_err("tls set rx fail"); 1978c2ecf20Sopenharmony_ci return ret; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci hmdfs_info("KTLS setting success"); 2018c2ecf20Sopenharmony_ci return ret; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic int hmac_sha256(u8 *key, u8 key_len, char *info, u8 info_len, u8 *output) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci struct crypto_shash *tfm = NULL; 2078c2ecf20Sopenharmony_ci struct shash_desc *shash = NULL; 2088c2ecf20Sopenharmony_ci int ret = 0; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (!key) 2118c2ecf20Sopenharmony_ci return -EINVAL; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); 2148c2ecf20Sopenharmony_ci if (IS_ERR(tfm)) { 2158c2ecf20Sopenharmony_ci hmdfs_err("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm)); 2168c2ecf20Sopenharmony_ci return PTR_ERR(tfm); 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci ret = crypto_shash_setkey(tfm, key, key_len); 2208c2ecf20Sopenharmony_ci if (ret) { 2218c2ecf20Sopenharmony_ci hmdfs_err("crypto_ahash_setkey failed: err %d", ret); 2228c2ecf20Sopenharmony_ci goto failed; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), 2268c2ecf20Sopenharmony_ci GFP_KERNEL); 2278c2ecf20Sopenharmony_ci if (!shash) { 2288c2ecf20Sopenharmony_ci ret = -ENOMEM; 2298c2ecf20Sopenharmony_ci goto failed; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci shash->tfm = tfm; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ret = crypto_shash_digest(shash, info, info_len, output); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci kfree(shash); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cifailed: 2398c2ecf20Sopenharmony_ci crypto_free_shash(tfm); 2408c2ecf20Sopenharmony_ci return ret; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic const char *const g_key_lable[] = { "ktls key initiator", 2448c2ecf20Sopenharmony_ci "ktls key accepter", 2458c2ecf20Sopenharmony_ci "ktls key update", "ktls iv&salt" }; 2468c2ecf20Sopenharmony_cistatic const int g_key_lable_len[] = { 18, 17, 15, 12 }; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciint update_key(__u8 *old_key, __u8 *new_key, int type) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci int ret = 0; 2518c2ecf20Sopenharmony_ci char lable[MAX_LABLE_SIZE]; 2528c2ecf20Sopenharmony_ci u8 lable_size; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci lable_size = g_key_lable_len[type] + sizeof(u16) + sizeof(char); 2558c2ecf20Sopenharmony_ci *((u16 *)lable) = HMDFS_KEY_SIZE; 2568c2ecf20Sopenharmony_ci memcpy(lable + sizeof(u16), g_key_lable[type], g_key_lable_len[type]); 2578c2ecf20Sopenharmony_ci *(lable + sizeof(u16) + g_key_lable_len[type]) = 0x01; 2588c2ecf20Sopenharmony_ci ret = hmac_sha256(old_key, HMDFS_KEY_SIZE, lable, lable_size, new_key); 2598c2ecf20Sopenharmony_ci if (ret < 0) 2608c2ecf20Sopenharmony_ci hmdfs_err("hmac sha256 error"); 2618c2ecf20Sopenharmony_ci return ret; 2628c2ecf20Sopenharmony_ci} 263