1+ #include <openssl/evp.h>
2+ #include <openssl/ssl.h>
3+ #include <xquic/xquic.h>
4+ #include "src/transport/xqc_engine.h"
5+
6+
7+ #define XQC_MAX_TRUNCATE_LEN 128
8+ #define XQC_EN_SINGLE_PASS_ENCRYPTION_LEN 16
9+ #define XQC_FIRST_OCTET 1
10+
11+ /* Each encrypted CID creates and releases a cipher ctx, which may occupies cpu resources a lot. It should be optimaized in the future.*/
12+ xqc_int_t
13+ xqc_cid_encryption_aes_128_ecb (unsigned char * plaintext , size_t plaintext_len , uint8_t * ciphertext , size_t ciphertext_len , uint8_t * key , size_t key_len , xqc_engine_t * engine )
14+ {
15+ xqc_int_t update_len = 0 , final_len = 0 ;
16+ xqc_log_t * log = engine -> log ;
17+
18+ if (plaintext_len != XQC_EN_SINGLE_PASS_ENCRYPTION_LEN ) {
19+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption parameter plaintext'length illegal(expect = 16)|" );
20+ return - XQC_EPARAM ;
21+ }
22+
23+ if (plaintext_len != ciphertext_len ) {
24+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption parameter plaintext and ciphertext illegal(expect equals in length)|" );
25+ return - XQC_EPARAM ;
26+ }
27+
28+ if (key_len != XQC_LB_CID_KEY_LEN ) {
29+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption parameter key'length illegal(expect = 16)|" );
30+ return - XQC_EPARAM ;
31+ }
32+
33+
34+ EVP_CIPHER_CTX * cipher_ctx = EVP_CIPHER_CTX_new ();
35+ if (!cipher_ctx ) {
36+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption ctx generate error|" );
37+ EVP_CIPHER_CTX_free (cipher_ctx );
38+ return - XQC_EENCRYPT_AES_128_ECB ;
39+ }
40+
41+ if (!EVP_EncryptInit_ex (cipher_ctx , EVP_aes_128_ecb (), NULL , key , NULL )) {
42+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption init error|" );
43+ EVP_CIPHER_CTX_free (cipher_ctx );
44+ return - XQC_EENCRYPT_AES_128_ECB ;
45+ }
46+
47+ EVP_CIPHER_CTX_set_padding (cipher_ctx , 0 );
48+
49+ if (!EVP_EncryptUpdate (cipher_ctx , ciphertext , & update_len , plaintext , plaintext_len )) {
50+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid aes_128_ecb encryption update error|" );
51+ EVP_CIPHER_CTX_free (cipher_ctx );
52+ return - XQC_EENCRYPT_AES_128_ECB ;
53+ }
54+
55+ if (!EVP_EncryptFinal_ex (cipher_ctx , ciphertext + update_len , & final_len )) {
56+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid four-aes_128_ecb encryption final error|" );
57+ EVP_CIPHER_CTX_free (cipher_ctx );
58+ return - XQC_EENCRYPT_AES_128_ECB ;
59+ }
60+
61+ EVP_CIPHER_CTX_free (cipher_ctx );
62+
63+ return XQC_OK ;
64+ }
65+
66+ __uint128_t
67+ xqc_expand_left (__uint128_t left , __uint128_t right )
68+ {
69+ __uint128_t out = 0 ;
70+ __uint128_t left_bound = 0xf ;
71+
72+ left_bound <<= 124 ;
73+ out |= left ;
74+
75+ if (out != 0 ) {
76+ out <<= (128 - 80 );
77+ while ((out & left_bound ) == 0 ){
78+ out <<= 4 ;
79+ }
80+ }
81+ out |= right ;
82+ return out ;
83+ }
84+
85+ __uint128_t
86+ xqc_expand_right (__uint128_t left , __uint128_t right )
87+ {
88+ return xqc_expand_left (right , left );
89+ }
90+
91+ __uint128_t
92+ xqc_n_bit_1 (xqc_int_t n )
93+ {
94+ __uint128_t out = 0 ;
95+ for (xqc_int_t i = 0 ; i < n ; i ++ ) {
96+ out <<= 1 ;
97+ out |= 1 ;
98+ }
99+ return out ;
100+ }
101+
102+ __uint128_t
103+ xqc_truncate_right (__uint128_t in , xqc_int_t cut_len , __uint128_t * out , xqc_engine_t * engine )
104+ {
105+ xqc_log_t * log = engine -> log ;
106+ if (cut_len > XQC_MAX_TRUNCATE_LEN ) {
107+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid xqc_truncate_right parameter `cut_len` overflow(expect <= 128)|" );
108+ return - XQC_EPARAM ;
109+ }
110+ __uint128_t flag ;
111+ flag = 0 ;
112+ flag = xqc_n_bit_1 (cut_len );
113+ * out = flag & in ;
114+ return XQC_OK ;
115+ }
116+
117+ __uint128_t
118+ xqc_truncate_left (__uint128_t in , xqc_int_t cut_len , __uint128_t * out , xqc_engine_t * engine )
119+ {
120+ xqc_log_t * log = engine -> log ;
121+ if (cut_len > XQC_MAX_TRUNCATE_LEN ) {
122+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid xqc_truncate_left parameter `cut_len` overflow(expect <= 128)|" );
123+ return - XQC_EPARAM ;
124+ }
125+ __uint128_t flag ;
126+ flag = 0 ;
127+ flag = xqc_n_bit_1 (cut_len );
128+ flag <<= (XQC_MAX_TRUNCATE_LEN - cut_len );
129+ * out = (flag & in ) >> (XQC_MAX_TRUNCATE_LEN - cut_len );
130+ return XQC_OK ;
131+ }
132+
133+ void
134+ xqc_array_right_shift (uint8_t * in_out , xqc_int_t bits , xqc_int_t in_out_len )
135+ {
136+ if (bits == 0 ) {
137+ return ;
138+ }
139+ xqc_int_t i = 0 ;
140+ while (i < in_out_len ) {
141+ /* keep the lowest `bits(int)` bits unchanged when i=0 */
142+ if (i ) {
143+ in_out [i ] >>= bits ;
144+ }
145+ if (i + 1 < in_out_len ) {
146+ uint8_t tmp = xqc_n_bit_1 (bits );
147+ tmp = in_out [i + 1 ] & tmp ;
148+ tmp <<= (8 - bits );
149+ in_out [i ] |= tmp ;
150+ }
151+ i ++ ;
152+ }
153+ }
154+
155+ xqc_int_t
156+ xqc_cid_encryption_four_pass (uint8_t * in , size_t in_len , uint8_t * out , size_t out_len , uint8_t * key , size_t key_len , xqc_engine_t * engine )
157+ {
158+ __uint128_t left_0 , right_0 , left_1 , right_1 , left_2 , right_2 ;
159+ __uint128_t tmp_out , tmp_exp , tmp_tru ;
160+ xqc_int_t bits_per_byte = 8 ;
161+ xqc_int_t octet_per_128bits = 16 ;
162+ xqc_int_t left_len_bit , right_len_bit , left_len_byte , right_len_byte ;
163+ xqc_int_t shift_offset ;
164+ xqc_log_t * log = engine -> log ;
165+ xqc_int_t ret ;
166+
167+ if (in_len > XQC_MAX_CID_LEN - XQC_FIRST_OCTET ) {
168+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid four-pass encryption parameter in_lengtn illegal(expect > 0 && <= 19)|" );
169+ return - XQC_EPARAM ;
170+ }
171+
172+ if (out_len < in_len ) {
173+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid four-pass encryption parameter out_len illegal(expect no less than in_len)|" );
174+ return - XQC_EPARAM ;
175+ }
176+
177+ if (key_len != XQC_LB_CID_KEY_LEN ) {
178+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error|lb-cid four-pass encryption parameter key'length illegal(expect = 16)|" );
179+ return - XQC_EPARAM ;
180+ }
181+
182+ left_len_bit = right_len_bit = in_len * 4 ;
183+ left_len_byte = right_len_byte = (in_len + 1 ) / 2 ;
184+ shift_offset = right_len_byte * 8 - right_len_bit ;
185+
186+ memset (& left_0 , 0 , sizeof (left_0 ));
187+ memset (& left_1 , 0 , sizeof (left_1 ));
188+ memset (& left_2 , 0 , sizeof (left_2 ));
189+ memset (& right_0 , 0 , sizeof (right_0 ));
190+ memset (& right_1 , 0 , sizeof (right_1 ));
191+ memset (& right_2 , 0 , sizeof (right_2 ));
192+
193+ memcpy (& left_0 , in + right_len_byte - 1 , left_len_byte );
194+ left_0 >>= right_len_bit - (right_len_byte - 1 ) * 8 ;
195+ memcpy (& right_0 , in , right_len_byte );
196+ right_0 &= xqc_n_bit_1 (right_len_bit );
197+
198+ tmp_exp = xqc_expand_left (left_0 , 0x01 );
199+ ret = xqc_cid_encryption_aes_128_ecb ((uint8_t * )& tmp_exp , octet_per_128bits , (uint8_t * )& tmp_out , octet_per_128bits , key , key_len , engine );
200+ if (ret != XQC_OK ) {
201+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass encryption first-pass aes encryption error|%d|" , ret );
202+ return ret ;
203+ }
204+ ret = xqc_truncate_right (tmp_out , right_len_bit , & tmp_tru , engine );
205+ if (ret != XQC_OK ) {
206+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass encryption first-pass truncate error|%d|" , ret );
207+ return ret ;
208+ }
209+ right_1 = right_0 ^ tmp_tru ;
210+
211+ tmp_exp = xqc_expand_right (right_1 , 0x02 );
212+ ret = xqc_cid_encryption_aes_128_ecb ((uint8_t * )& tmp_exp , octet_per_128bits , (uint8_t * )& tmp_out , octet_per_128bits , key , key_len , engine );
213+ if (ret != XQC_OK ) {
214+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass second-pass aes encryption error|%d|" , ret );
215+ return ret ;
216+ }
217+ ret = xqc_truncate_left (tmp_out , left_len_bit , & tmp_tru , engine );
218+ if (ret != XQC_OK ) {
219+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass encryption second-pass truncate error|%d|" , ret );
220+ return ret ;
221+ }
222+ left_1 = left_0 ^ tmp_tru ;
223+
224+ tmp_exp = xqc_expand_left (left_1 , 0x03 );
225+ ret = xqc_cid_encryption_aes_128_ecb ((uint8_t * )& tmp_exp , octet_per_128bits , (uint8_t * )& tmp_out , octet_per_128bits , key , key_len , engine );
226+ if (ret != XQC_OK ) {
227+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass third-pass aes encryption error|%d|" , ret );
228+ return ret ;
229+ }
230+ ret = xqc_truncate_right (tmp_out , right_len_bit , & tmp_tru , engine );
231+ if (ret != XQC_OK ) {
232+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass encryption third-pass truncate error|%d|" , ret );
233+ return ret ;
234+ }
235+ right_2 = right_1 ^ tmp_tru ;
236+
237+ tmp_exp = xqc_expand_right (right_2 , 0x04 );
238+ ret = xqc_cid_encryption_aes_128_ecb ((uint8_t * )& tmp_exp , octet_per_128bits , (uint8_t * )& tmp_out , octet_per_128bits , key , key_len , engine );
239+ if (ret != XQC_OK ) {
240+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass fourth-pass aes encryption error|%d|" , ret );
241+ return ret ;
242+ }
243+ ret = xqc_truncate_left (tmp_out , left_len_bit , & tmp_tru , engine );
244+ if (ret != XQC_OK ) {
245+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid generate|lb-cid four-pass encryption fourth-pass truncate error|%d|" , ret );
246+ return ret ;
247+ }
248+ left_2 = left_1 ^ tmp_tru ;
249+
250+ memcpy (out + right_len_byte , & left_2 , left_len_byte );
251+ memcpy (out , & right_2 , right_len_byte );
252+ /* The lowest right shift byte will overwrite the high-order bits of its right byte, thus the function requires the address of (startbyte - 1) */
253+ xqc_array_right_shift (out + right_len_byte - 1 , shift_offset , left_len_byte + 1 );
254+
255+ return XQC_OK ;
256+ }
257+
258+ /**
259+ * @brief load balance cid encryption.
260+ * According to Draft : https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers-13#section-4.3
261+ */
262+ xqc_int_t
263+ xqc_lb_cid_encryption (uint8_t * cid_buf , size_t enc_len , uint8_t * out_buf , size_t out_buf_len , uint8_t * lb_cid_key , size_t lb_cid_key_len , xqc_engine_t * engine )
264+ {
265+ size_t cid_buf_len = enc_len + XQC_FIRST_OCTET ;
266+
267+ xqc_log_t * log = engine -> log ;
268+
269+ if (cid_buf_len > XQC_MAX_CID_LEN ) {
270+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error| parameter enc_len illegal(expect <= 19)|" );
271+ return - XQC_EPARAM ;
272+ }
273+
274+ if (lb_cid_key_len != XQC_LB_CID_KEY_LEN ) {
275+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error| parameter lb_cid_key illegal(expect = 16)|" );
276+ return - XQC_EPARAM ;
277+ }
278+
279+ if (out_buf_len < cid_buf_len ) {
280+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid encryption error| parameter out_buf_len illegal(expect no less than cid_buf_len)|" );
281+ return - XQC_EPARAM ;
282+ }
283+
284+ if (enc_len == XQC_EN_SINGLE_PASS_ENCRYPTION_LEN ) {
285+ xqc_int_t res = xqc_cid_encryption_aes_128_ecb (cid_buf + XQC_FIRST_OCTET , enc_len , out_buf + XQC_FIRST_OCTET , enc_len , lb_cid_key , lb_cid_key_len , engine );
286+ if (res < XQC_OK ) {
287+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid aes_128_ecb encryption error|%d|" , res );
288+ return - XQC_EENCRYPT_LB_CID ;
289+ }
290+ } else {
291+ xqc_int_t res = xqc_cid_encryption_four_pass (cid_buf + XQC_FIRST_OCTET , enc_len , out_buf + XQC_FIRST_OCTET , enc_len , lb_cid_key , lb_cid_key_len , engine );
292+ if (res < XQC_OK ) {
293+ xqc_log (log , XQC_LOG_ERROR , "|lb-cid four-pass encryption error|%d|" , res );
294+ return - XQC_EENCRYPT_LB_CID ;
295+ }
296+ }
297+
298+ unsigned char tmp_cid_buf [XQC_MAX_CID_LEN * 2 + 1 ];
299+ xqc_hex_dump (tmp_cid_buf , cid_buf , enc_len );
300+ tmp_cid_buf [enc_len * 2 ] = '\0' ;
301+ unsigned char tmp_out_buf [XQC_MAX_CID_LEN * 2 + 1 ];
302+ xqc_hex_dump (tmp_out_buf , out_buf , enc_len );
303+ tmp_out_buf [enc_len * 2 ] = '\0' ;
304+ xqc_log (log , XQC_LOG_INFO , "|lb cid encrypted|ori:%s|new:%s|" ,
305+ tmp_cid_buf , tmp_out_buf );
306+ return XQC_OK ;
307+ }
0 commit comments