The RFC8998 specification defines the use of the ShangMi algorithm
cipher suites in TLS 1.3, and also supports the GCM/CCM mode using
the SM4 algorithm.
Signed-off-by: Tianjia Zhang <[email protected]>
---
include/uapi/linux/tls.h | 30 ++++++++++++++++++++++++++
net/tls/tls_main.c | 46 ++++++++++++++++++++++++++++++++++++++++
net/tls/tls_sw.c | 34 +++++++++++++++++++++++++++++
3 files changed, 110 insertions(+)
diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h
index 0d54baea1d8d..5f38be0ec0f3 100644
--- a/include/uapi/linux/tls.h
+++ b/include/uapi/linux/tls.h
@@ -84,6 +84,20 @@
#define TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE 16
#define TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE 8
+#define TLS_CIPHER_SM4_GCM 55
+#define TLS_CIPHER_SM4_GCM_IV_SIZE 8
+#define TLS_CIPHER_SM4_GCM_KEY_SIZE 16
+#define TLS_CIPHER_SM4_GCM_SALT_SIZE 4
+#define TLS_CIPHER_SM4_GCM_TAG_SIZE 16
+#define TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE 8
+
+#define TLS_CIPHER_SM4_CCM 56
+#define TLS_CIPHER_SM4_CCM_IV_SIZE 8
+#define TLS_CIPHER_SM4_CCM_KEY_SIZE 16
+#define TLS_CIPHER_SM4_CCM_SALT_SIZE 4
+#define TLS_CIPHER_SM4_CCM_TAG_SIZE 16
+#define TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE 8
+
#define TLS_SET_RECORD_TYPE 1
#define TLS_GET_RECORD_TYPE 2
@@ -124,6 +138,22 @@ struct tls12_crypto_info_chacha20_poly1305 {
unsigned char rec_seq[TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE];
};
+struct tls12_crypto_info_sm4_gcm {
+ struct tls_crypto_info info;
+ unsigned char iv[TLS_CIPHER_SM4_GCM_IV_SIZE];
+ unsigned char key[TLS_CIPHER_SM4_GCM_KEY_SIZE];
+ unsigned char salt[TLS_CIPHER_SM4_GCM_SALT_SIZE];
+ unsigned char rec_seq[TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE];
+};
+
+struct tls12_crypto_info_sm4_ccm {
+ struct tls_crypto_info info;
+ unsigned char iv[TLS_CIPHER_SM4_CCM_IV_SIZE];
+ unsigned char key[TLS_CIPHER_SM4_CCM_KEY_SIZE];
+ unsigned char salt[TLS_CIPHER_SM4_CCM_SALT_SIZE];
+ unsigned char rec_seq[TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE];
+};
+
enum {
TLS_INFO_UNSPEC,
TLS_INFO_VERSION,
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index fde56ff49163..f140a6594e9c 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -421,6 +421,46 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
rc = -EFAULT;
break;
}
+ case TLS_CIPHER_SM4_GCM: {
+ struct tls12_crypto_info_sm4_gcm *sm4_gcm_info =
+ container_of(crypto_info,
+ struct tls12_crypto_info_sm4_gcm, info);
+
+ if (len != sizeof(*sm4_gcm_info)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ lock_sock(sk);
+ memcpy(sm4_gcm_info->iv,
+ cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
+ TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ memcpy(sm4_gcm_info->rec_seq, cctx->rec_seq,
+ TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+ release_sock(sk);
+ if (copy_to_user(optval, sm4_gcm_info, sizeof(*sm4_gcm_info)))
+ rc = -EFAULT;
+ break;
+ }
+ case TLS_CIPHER_SM4_CCM: {
+ struct tls12_crypto_info_sm4_ccm *sm4_ccm_info =
+ container_of(crypto_info,
+ struct tls12_crypto_info_sm4_ccm, info);
+
+ if (len != sizeof(*sm4_ccm_info)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ lock_sock(sk);
+ memcpy(sm4_ccm_info->iv,
+ cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
+ TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ memcpy(sm4_ccm_info->rec_seq, cctx->rec_seq,
+ TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+ release_sock(sk);
+ if (copy_to_user(optval, sm4_ccm_info, sizeof(*sm4_ccm_info)))
+ rc = -EFAULT;
+ break;
+ }
default:
rc = -EINVAL;
}
@@ -524,6 +564,12 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
case TLS_CIPHER_CHACHA20_POLY1305:
optsize = sizeof(struct tls12_crypto_info_chacha20_poly1305);
break;
+ case TLS_CIPHER_SM4_GCM:
+ optsize = sizeof(struct tls12_crypto_info_sm4_gcm);
+ break;
+ case TLS_CIPHER_SM4_CCM:
+ optsize = sizeof(struct tls12_crypto_info_sm4_ccm);
+ break;
default:
rc = -EINVAL;
goto err_crypto_info;
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 4feb95e34b64..989d1423a245 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2424,6 +2424,40 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
cipher_name = "rfc7539(chacha20,poly1305)";
break;
}
+ case TLS_CIPHER_SM4_GCM: {
+ struct tls12_crypto_info_sm4_gcm *sm4_gcm_info;
+
+ sm4_gcm_info = (void *)crypto_info;
+ nonce_size = TLS_CIPHER_SM4_GCM_IV_SIZE;
+ tag_size = TLS_CIPHER_SM4_GCM_TAG_SIZE;
+ iv_size = TLS_CIPHER_SM4_GCM_IV_SIZE;
+ iv = sm4_gcm_info->iv;
+ rec_seq_size = TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE;
+ rec_seq = sm4_gcm_info->rec_seq;
+ keysize = TLS_CIPHER_SM4_GCM_KEY_SIZE;
+ key = sm4_gcm_info->key;
+ salt = sm4_gcm_info->salt;
+ salt_size = TLS_CIPHER_SM4_GCM_SALT_SIZE;
+ cipher_name = "gcm(sm4)";
+ break;
+ }
+ case TLS_CIPHER_SM4_CCM: {
+ struct tls12_crypto_info_sm4_ccm *sm4_ccm_info;
+
+ sm4_ccm_info = (void *)crypto_info;
+ nonce_size = TLS_CIPHER_SM4_CCM_IV_SIZE;
+ tag_size = TLS_CIPHER_SM4_CCM_TAG_SIZE;
+ iv_size = TLS_CIPHER_SM4_CCM_IV_SIZE;
+ iv = sm4_ccm_info->iv;
+ rec_seq_size = TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE;
+ rec_seq = sm4_ccm_info->rec_seq;
+ keysize = TLS_CIPHER_SM4_CCM_KEY_SIZE;
+ key = sm4_ccm_info->key;
+ salt = sm4_ccm_info->salt;
+ salt_size = TLS_CIPHER_SM4_CCM_SALT_SIZE;
+ cipher_name = "ccm(sm4)";
+ break;
+ }
default:
rc = -EINVAL;
goto free_priv;
--
2.19.1.3.ge56e4f7
On Wed, 15 Sep 2021 19:12:42 +0800 Tianjia Zhang wrote:
> + memcpy(sm4_gcm_info->iv,
> + cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
> + TLS_CIPHER_AES_GCM_128_IV_SIZE);
> + memcpy(sm4_gcm_info->rec_seq, cctx->rec_seq,
> + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
> + release_sock(sk);
> + if (copy_to_user(optval, sm4_gcm_info, sizeof(*sm4_gcm_info)))
> + rc = -EFAULT;
> + break;
> + }
> + case TLS_CIPHER_SM4_CCM: {
> + struct tls12_crypto_info_sm4_ccm *sm4_ccm_info =
> + container_of(crypto_info,
> + struct tls12_crypto_info_sm4_ccm, info);
> +
> + if (len != sizeof(*sm4_ccm_info)) {
> + rc = -EINVAL;
> + goto out;
> + }
> + lock_sock(sk);
> + memcpy(sm4_ccm_info->iv,
> + cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
> + TLS_CIPHER_AES_GCM_128_IV_SIZE);
> + memcpy(sm4_ccm_info->rec_seq, cctx->rec_seq,
> + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
Doesn't matter from the functional perspective but perhaps use the SM4
defines rather than the AES ones, since they exist, anyway?
With that fixed feel free to add my ack.
Hi Jakub,
On 9/16/21 4:06 AM, Jakub Kicinski wrote:
> On Wed, 15 Sep 2021 19:12:42 +0800 Tianjia Zhang wrote:
>> + memcpy(sm4_gcm_info->iv,
>> + cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
>> + TLS_CIPHER_AES_GCM_128_IV_SIZE);
>> + memcpy(sm4_gcm_info->rec_seq, cctx->rec_seq,
>> + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
>> + release_sock(sk);
>> + if (copy_to_user(optval, sm4_gcm_info, sizeof(*sm4_gcm_info)))
>> + rc = -EFAULT;
>> + break;
>> + }
>> + case TLS_CIPHER_SM4_CCM: {
>> + struct tls12_crypto_info_sm4_ccm *sm4_ccm_info =
>> + container_of(crypto_info,
>> + struct tls12_crypto_info_sm4_ccm, info);
>> +
>> + if (len != sizeof(*sm4_ccm_info)) {
>> + rc = -EINVAL;
>> + goto out;
>> + }
>> + lock_sock(sk);
>> + memcpy(sm4_ccm_info->iv,
>> + cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
>> + TLS_CIPHER_AES_GCM_128_IV_SIZE);
>> + memcpy(sm4_ccm_info->rec_seq, cctx->rec_seq,
>> + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
>
> Doesn't matter from the functional perspective but perhaps use the SM4
> defines rather than the AES ones, since they exist, anyway?
>
> With that fixed feel free to add my ack.
>
Thanks for pointing it out, I forgot to modify the macro name, this is
not my intention, I was careless. will fix it in v2.
Best regards,
Tianjia