0%

使用OpenSSL内置的密码算法定义新的加密套件(TLS1.3)

这篇文章内容接上一篇。上一篇文章给出了使用openssl提供的api建立server与client并指定PSK与加密套件的代码。在TLS1.3中,加密套件被缩减至5种,PSK也成为TLS1.3协议中的标配。这篇文章则会介绍一下怎么样利用TLS1.3中已有的加密算法定义新的加密套件。

加密套件(cipher suites)简介

加密套件会在握手阶段被确定。加密套件的定义在TLS1.3之前与TLS1.3中有着一定区别。在TLS1.3中,被使用的五种加密套件如下(图源与介绍来自知乎,见文末参考资料):

ciphersuites

TLS_AES_128_CCM_SHA256为例,TLS表明该加密组件用于TLS协议,AES表明使用AES对称加密算法,128表示密钥长度为128位,CCM表明分组加密模式,SHA256是HKDF过程使用的哈希算法。

OpenSSL中的加密套件定义

想要添加新的加密套件,首先需要找到OpenSSL中TLS1.3的加密套件是如何定义的。通过命令行工具,我们可以输出目前TLS1.3中支持的加密套件,根据源码我们可以找到其定义。当然,也可以选择全局搜索相关变量名找到关联代码,从而定位定义位置。TLS1.3的加密套件定义在ssl/s3_lib.c中,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* The list of available TLSv1.3 ciphers */
static SSL_CIPHER tls13_ciphers[] = {
{
1,
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_CK_AES_128_GCM_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128GCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}, {
1,
TLS1_3_RFC_AES_256_GCM_SHA384,
TLS1_3_RFC_AES_256_GCM_SHA384,
TLS1_3_CK_AES_256_GCM_SHA384,
SSL_kANY,
SSL_aANY,
SSL_AES256GCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384,
256,
256,
},
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
1,
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
TLS1_3_CK_CHACHA20_POLY1305_SHA256,
SSL_kANY,
SSL_aANY,
SSL_CHACHA20POLY1305,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
256,
256,
},
#endif
{
1,
TLS1_3_RFC_AES_128_CCM_SHA256,
TLS1_3_RFC_AES_128_CCM_SHA256,
TLS1_3_CK_AES_128_CCM_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128CCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}, {
1,
TLS1_3_RFC_AES_128_CCM_8_SHA256,
TLS1_3_RFC_AES_128_CCM_8_SHA256,
TLS1_3_CK_AES_128_CCM_8_SHA256,
SSL_kANY,
SSL_aANY,
SSL_AES128CCM8,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_NOT_DEFAULT | SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
}
};

我们查看SSL_CIPHER的定义,可以看到各个成员的详细意义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* CipherSuite length. SSLv3 and all TLS versions. */
# define TLS_CIPHER_LEN 2
/* used to hold info on the particular ciphers used */
struct ssl_cipher_st {
uint32_t valid;
const char *name; /* text name */
const char *stdname; /* RFC name */
uint32_t id; /* id, 4 bytes, first is version */
/*
* changed in 1.0.0: these four used to be portions of a single value
* 'algorithms'
*/
uint32_t algorithm_mkey; /* key exchange algorithm */
uint32_t algorithm_auth; /* server authentication */
uint32_t algorithm_enc; /* symmetric encryption */
uint32_t algorithm_mac; /* symmetric authentication */
int min_tls; /* minimum SSL/TLS protocol version */
int max_tls; /* maximum SSL/TLS protocol version */
int min_dtls; /* minimum DTLS protocol version */
int max_dtls; /* maximum DTLS protocol version */
uint32_t algo_strength; /* strength and export flags */
uint32_t algorithm2; /* Extra flags */
int32_t strength_bits; /* Number of bits really used */
uint32_t alg_bits; /* Number of bits for algorithm */
};

定义新的加密套件

其中所有定义均为宏定义的常量,我们为这个结构体添加新成员,并增加相应的宏定义,即可为OpenSSL定义新的TLS1.3加密套件。这里我们选择增加加密套件TLS_AES_256_GCM_SHA512,向tls13_ciphers增加如下的成员即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
1,
TLS1_3_RFC_AES_256_GCM_SHA512,
TLS1_3_RFC_AES_256_GCM_SHA512,
TLS1_3_CK_AES_256_GCM_SHA512,
SSL_kANY,
SSL_aANY,
SSL_AES256GCM,
SSL_AEAD,
TLS1_3_VERSION, TLS1_3_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA512,
256,
256,
},

部分变量没有进行定义,我们增加其定义即可。注意定义保持一致。如果使用编辑器的快速跳转注意不要跳转到系统库中了。

1
2
3
4
5
6
7
8
9
//tls1.h
/* TLS v1.3 ciphersuites */
# define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301
# define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302
# define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303
# define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304
# define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305
// new!
# define TLS1_3_CK_AES_256_GCM_SHA512 0x03001306
1
2
3
4
5
6
7
8
9
10
11
12
//ssl_local.h
/* Bits 0-7 are handshake MAC */
# define SSL_HANDSHAKE_MAC_MASK 0xFF
# define SSL_HANDSHAKE_MAC_MD5_SHA1 SSL_MD_MD5_SHA1_IDX
# define SSL_HANDSHAKE_MAC_SHA256 SSL_MD_SHA256_IDX
# define SSL_HANDSHAKE_MAC_SHA384 SSL_MD_SHA384_IDX
//new!
# define SSL_HANDSHAKE_MAC_SHA512 SSL_MD_SHA512_IDX
# define SSL_HANDSHAKE_MAC_GOST94 SSL_MD_GOST94_IDX
# define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX
# define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX
# define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1
1
2
3
4
5
6
// tls1.h 
# define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256"
# define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384"
//new!
# define TLS1_3_RFC_AES_256_GCM_SHA512 "TLS_AES_256_GCM_SHA512"
# define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256"

之后进行编译就结束了,将上一篇文章中设置的加密套件设置为TLS_AES_256_GCM_SHA512,并在PSK选用的加密套件id设置为0x1306即可。需要注意的是,如果没有安装在默认的路径,在编译时可能需要作额外的设置。我折腾了很久还是没有折腾出来,最后选择安装在了默认的路径。

参考资料

TLS 1.3科普——新特性与协议实现