forked from lexiforest/curl-impersonate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboringssl.patch
1440 lines (1364 loc) · 49.6 KB
/
boringssl.patch
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 77c2e384f..e154f12f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -124,7 +124,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
# clang-cl sets different default warnings than clang. It also treats -Wall
# as -Weverything, to match MSVC. Instead -W3 is the alias for -Wall.
# See http://llvm.org/viewvc/llvm-project?view=revision&revision=319116
- set(C_CXX_FLAGS "${C_CXX_FLAGS} -W3 -Wno-unused-parameter -fmsc-version=1900")
+ set(C_CXX_FLAGS "${C_CXX_FLAGS} -W3 -Wno-unused-parameter -fmsc-version=1900 -Wno-deprecated")
else()
if(EMSCRIPTEN)
# emscripten's emcc/clang does not accept the "-ggdb" flag.
diff --git a/crypto/cipher/e_tls.cc b/crypto/cipher/e_tls.cc
index b21b06207..f77019895 100644
--- a/crypto/cipher/e_tls.cc
+++ b/crypto/cipher/e_tls.cc
@@ -422,6 +422,22 @@ static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
EVP_sha1(), 1);
}
+static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
+ EVP_sha256(), 0);
+}
+
+static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
+ EVP_sha384(), 0);
+}
+
static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
@@ -536,6 +552,40 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
aead_tls_tag_len,
};
+static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
+ SHA256_DIGEST_LENGTH + 32, // key len (SHA256 + AES256)
+ 16, // nonce len (IV)
+ 16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256)
+ SHA256_DIGEST_LENGTH, // max tag length
+ 0, // seal_scatter_supports_extra_in
+
+ NULL, // init
+ aead_aes_256_cbc_sha256_tls_init,
+ aead_tls_cleanup,
+ aead_tls_open,
+ aead_tls_seal_scatter,
+ NULL, // open_gather
+ NULL, // get_iv
+ aead_tls_tag_len,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
+ SHA384_DIGEST_LENGTH + 32, // key len (SHA384 + AES256)
+ 16, // nonce len (IV)
+ 16 + SHA384_DIGEST_LENGTH, // overhead (padding + SHA384)
+ SHA384_DIGEST_LENGTH, // max tag length
+ 0, // seal_scatter_supports_extra_in
+
+ NULL, // init
+ aead_aes_256_cbc_sha384_tls_init,
+ aead_tls_cleanup,
+ aead_tls_open,
+ aead_tls_seal_scatter,
+ NULL, // open_gather
+ NULL, // get_iv
+ aead_tls_tag_len,
+};
+
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
SHA_DIGEST_LENGTH + 24, // key len (SHA1 + 3DES)
8, // nonce len (IV)
@@ -590,6 +640,14 @@ const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) {
return &aead_aes_256_cbc_sha1_tls_implicit_iv;
}
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) {
+ return &aead_aes_256_cbc_sha256_tls;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) {
+ return &aead_aes_256_cbc_sha384_tls;
+}
+
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) {
return &aead_des_ede3_cbc_sha1_tls;
}
diff --git a/crypto/rand/windows.cc b/crypto/rand/windows.cc
index 81f2b4baa..d6d5a23d5 100644
--- a/crypto/rand/windows.cc
+++ b/crypto/rand/windows.cc
@@ -62,6 +62,9 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
typedef BOOL (WINAPI *ProcessPrngFunction)(PBYTE pbData, SIZE_T cbData);
static ProcessPrngFunction g_processprng_fn = NULL;
+typedef BOOL(WINAPI *RtlGenRandomFunction)(PVOID RandomBuffer, ULONG RandomBufferLength);
+static RtlGenRandomFunction g_rtlgenrandom_fn = NULL;
+
static void init_processprng(void) {
HMODULE hmod = LoadLibraryW(L"bcryptprimitives");
if (hmod == NULL) {
@@ -69,7 +72,14 @@ static void init_processprng(void) {
}
g_processprng_fn = (ProcessPrngFunction)GetProcAddress(hmod, "ProcessPrng");
if (g_processprng_fn == NULL) {
- abort();
+ hmod = LoadLibraryW(L"advapi32");
+ if (hmod == NULL) {
+ abort();
+ }
+ g_rtlgenrandom_fn = (RtlGenRandomFunction)GetProcAddress(hmod, "SystemFunction036");
+ if (g_rtlgenrandom_fn == NULL) {
+ abort();
+ }
}
}
@@ -83,8 +93,22 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
// On non-UWP configurations, use ProcessPrng instead of BCryptGenRandom
// to avoid accessing resources that may be unavailable inside the
// Chromium sandbox. See https://crbug.com/74242
- if (!g_processprng_fn(out, requested)) {
- abort();
+ if (g_processprng_fn != NULL) {
+ if (!g_processprng_fn(out, requested)) {
+ abort();
+ }
+ } else {
+ while (requested > 0) {
+ ULONG output_bytes_this_pass = ULONG_MAX;
+ if (requested < output_bytes_this_pass) {
+ output_bytes_this_pass = (ULONG)requested;
+ }
+ if (g_rtlgenrandom_fn(out, output_bytes_this_pass) == FALSE) {
+ abort();
+ }
+ requested -= output_bytes_this_pass;
+ out += output_bytes_this_pass;
+ }
}
}
diff --git a/export.sh b/export.sh
new file mode 100755
index 000000000..7518747ad
--- /dev/null
+++ b/export.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# From here: https://chromium.googlesource.com/chromium/src.git/+/refs/tags/134.0.6970.1/DEPS
+
+BASE_COMMIT=23768dca563c4e62d48bb3675e49e34955dced12
+
+git diff $BASE_COMMIT > boringssl.patch
+mv boringssl.patch ../curl-impersonate/chrome/patches/boringssl.patch
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index f27eb89de..612a1e227 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -404,6 +404,8 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
diff --git a/include/openssl/nid.h b/include/openssl/nid.h
index 2111a942a..c0d2f8da5 100644
--- a/include/openssl/nid.h
+++ b/include/openssl/nid.h
@@ -4211,6 +4211,11 @@ extern "C" {
#define SN_X25519MLKEM768 "X25519MLKEM768"
#define NID_X25519MLKEM768 965
+#define SN_ffdhe2048 "ffdhe2048"
+#define NID_ffdhe2048 966
+
+#define SN_ffdhe3072 "ffdhe3072"
+#define NID_ffdhe3072 967
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index d1f1006bb..5386094b2 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1637,6 +1637,12 @@ OPENSSL_EXPORT size_t SSL_get_all_standard_cipher_names(const char **out,
OPENSSL_EXPORT int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx,
const char *str);
+// curl-impersonate: set the extension order by given string
+OPENSSL_EXPORT int SSL_CTX_set_extension_order(SSL_CTX *ctx, char *order);
+
+// curl-impersonate
+OPENSSL_EXPORT int SSL_CTX_set_key_usage_check_enabled(SSL_CTX *ctx, int enabled);
+
// SSL_CTX_set_cipher_list configures the cipher list for |ctx|, evaluating
// |str| as a cipher string. It returns one on success and zero on failure.
//
@@ -2451,6 +2457,8 @@ OPENSSL_EXPORT size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
#define SSL_GROUP_X25519 29
#define SSL_GROUP_X25519_MLKEM768 0x11ec
#define SSL_GROUP_X25519_KYBER768_DRAFT00 0x6399
+#define SSL_GROUP_FFDHE2048 0x0100
+#define SSL_GROUP_FFDHE3072 0x0101
// SSL_CTX_set1_group_ids sets the preferred groups for |ctx| to |group_ids|.
// Each element of |group_ids| should be one of the |SSL_GROUP_*| constants. It
@@ -4754,6 +4762,12 @@ OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled);
// permute extensions. For now, this is only implemented for the ClientHello.
OPENSSL_EXPORT void SSL_set_permute_extensions(SSL *ssl, int enabled);
+// curl-impersonate
+OPENSSL_EXPORT int SSL_CTX_set_extension_order(SSL_CTX *ctx, char *order);
+
+// curl-impersonate
+OPENSSL_EXPORT int SSL_CTX_set_key_usage_check_enabled(SSL_CTX *ctx, int enabled);
+
// SSL_max_seal_overhead returns the maximum overhead, in bytes, of sealing a
// record with |ssl|.
OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl);
@@ -5076,6 +5090,33 @@ OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str);
// more convenient to codesearch for specific algorithm values.
OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str);
+// curl-impersoante:
+// SSL_CTX_set_delegated_credentials sets the set of signature algorithms supported
+// by the client.
+OPENSSL_EXPORT int SSL_CTX_set_delegated_credentials(SSL_CTX *ctx, const char *str);
+
+// curl-impersoante:
+// SSL_set_record_size_limit configures whether sockets on |ssl| should
+// send record size limit extension.
+OPENSSL_EXPORT void SSL_set_record_size_limit(SSL *ssl, uint16_t limit);
+
+// curl-impersoante:
+// SSL_CTX_set_record_size_limit configures whether sockets on |ctx| should
+// send record size limit extension.
+OPENSSL_EXPORT void SSL_CTX_set_record_size_limit(SSL_CTX *ctx, uint16_t limit);
+
+// curl-imperonsate:
+// SSL_set_key_shares_limit configures whether sockets on |ssl| should
+// send three key shares.
+OPENSSL_EXPORT void SSL_set_key_shares_limit(SSL *ssl, uint8_t limit);
+
+// curl-impersonate:
+// SSL_CTX_set_key_shares_limit configures whether sockets on |ctx| should
+// send three key shares.
+OPENSSL_EXPORT void SSL_CTX_set_key_shares_limit(SSL_CTX *ctx, uint8_t limit);
+
+
+
#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
#define SSL_SESSION_set_app_data(s, a) \
@@ -5454,6 +5495,8 @@ OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
#define SSL_CURVE_SECP384R1 SSL_GROUP_SECP384R1
#define SSL_CURVE_SECP521R1 SSL_GROUP_SECP521R1
#define SSL_CURVE_X25519 SSL_GROUP_X25519
+#define SSL_CURVE_FFDHE2048 SSL_GROUP_FFDHE2048
+#define SSL_CURVE_FFDHE3072 SSL_GROUP_FFDHE3072
#define SSL_CURVE_X25519_KYBER768_DRAFT00 SSL_GROUP_X25519_KYBER768_DRAFT00
// SSL_get_curve_id calls |SSL_get_group_id|.
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 99d48c526..5134708f2 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -43,6 +43,9 @@ extern "C" {
#define TLS1_AD_NO_APPLICATION_PROTOCOL 120
#define TLS1_AD_ECH_REQUIRED 121 // draft-ietf-tls-esni-13
+// curl-impersonate
+#define TLSEXT_TYPE_record_size_limit 28
+
// ExtensionType values from RFC 6066
#define TLSEXT_TYPE_server_name 0
#define TLSEXT_TYPE_status_request 5
@@ -149,6 +152,7 @@ extern "C" {
// From https://www.rfc-editor.org/rfc/rfc8879.html#section-3
#define TLSEXT_cert_compression_zlib 1
#define TLSEXT_cert_compression_brotli 2
+#define TLSEXT_cert_compression_zstd 3
#define TLSEXT_MAXLEN_host_name 255
diff --git a/ssl/extensions.cc b/ssl/extensions.cc
index df914c806..5bc27c2d4 100644
--- a/ssl/extensions.cc
+++ b/ssl/extensions.cc
@@ -2114,7 +2114,15 @@ bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
SSL *const ssl = hs->ssl;
hs->key_shares[0].reset();
hs->key_shares[1].reset();
+ hs->key_shares[2].reset();
hs->key_share_bytes.Reset();
+ // If key_shares_limit is set, use it. Otherwise, use the default of 2.
+ const uint8_t key_shares_limit = hs->ssl->config->key_shares_limit;
+ // The key_shares_limit is set by the user, so it is a custom value.
+ const bool is_custom = key_shares_limit != 0;
+ const uint8_t limit = (key_shares_limit >= 1 && key_shares_limit <= 3) ? key_shares_limit : 2;
+ const bool enable_second_key_share = (limit >= 2);
+ const bool enable_three_key_shares = (limit >= 3);
if (hs->max_version < TLS1_3_VERSION) {
return true;
@@ -2136,6 +2144,7 @@ bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
uint16_t group_id = override_group_id;
uint16_t second_group_id = 0;
+ uint16_t third_group_id = 0;
if (override_group_id == 0) {
// Predict the most preferred group.
Span<const uint16_t> groups = tls1_get_grouplist(hs);
@@ -2145,13 +2154,14 @@ bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
}
group_id = groups[0];
-
- // We'll try to include one post-quantum and one classical initial key
- // share.
- for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) {
- if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) {
+ // Include one post-quantum and one classical initial key share.
+ for (size_t i = 1; i < groups.size(); i++) {
+ if (enable_second_key_share && second_group_id == 0 && (is_custom || (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])))) {
second_group_id = groups[i];
assert(second_group_id != group_id);
+ } else if (enable_three_key_shares && third_group_id == 0 &&
+ (is_custom || is_post_quantum_group(group_id) != is_post_quantum_group(groups[i]))) {
+ third_group_id = groups[i];
}
}
}
@@ -2175,6 +2185,16 @@ bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
}
}
+ if (third_group_id != 0) {
+ hs->key_shares[2] = SSLKeyShare::Create(third_group_id);
+ if (!hs->key_shares[2] || //
+ !CBB_add_u16(cbb.get(), third_group_id) ||
+ !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
+ !hs->key_shares[2]->Generate(&key_exchange)) {
+ return false;
+ }
+ }
+
return CBBFinishArray(cbb.get(), &hs->key_share_bytes);
}
@@ -2213,13 +2233,21 @@ bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
}
SSLKeyShare *key_share = hs->key_shares[0].get();
+ // group_id is the server chosen group_id, and if key_share[0] is not chosen
if (key_share->GroupID() != group_id) {
+ // the server also did not choose the second one
if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
- *out_alert = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
- return false;
+ // the server also did not choose the third one, we are out of options
+ if (!hs->key_shares[2] || hs->key_shares[2]->GroupID() != group_id) {
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+ return false;
+ } else {
+ key_share = hs->key_shares[2].get();
+ }
+ } else {
+ key_share = hs->key_shares[1].get();
}
- key_share = hs->key_shares[1].get();
}
if (!key_share->Decap(out_secret, out_alert, ciphertext)) {
@@ -2227,9 +2255,11 @@ bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
return false;
}
+ // choose the first one
hs->new_session->group_id = group_id;
hs->key_shares[0].reset();
hs->key_shares[1].reset();
+ hs->key_shares[2].reset();
return true;
}
@@ -2686,6 +2716,27 @@ static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
static bool ext_delegated_credential_add_clienthello(
const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
ssl_client_hello_type_t type) {
+ // curl-impersonate
+ if (hs->config->delegated_credentials.empty()) {
+ return true;
+ }
+
+ CBB contents, data;
+ const Array<uint16_t>& signature_hash_algorithms = hs->config->delegated_credentials;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_delegated_credential) ||
+ !CBB_add_u16_length_prefixed(out, &contents) ||
+ !CBB_add_u16_length_prefixed(&contents, &data)) {
+ return false;
+ }
+
+ for (const uint16_t alg : signature_hash_algorithms) {
+ if (!CBB_add_u16(&data, alg)) {
+ return false;
+ }
+ }
+ if (!CBB_flush(out)) {
+ return false;
+ }
return true;
}
@@ -3033,6 +3084,40 @@ bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return true;
}
+// curl-impersonate
+static bool record_size_limit_add_clienthello(const SSL_HANDSHAKE* hs, CBB* out,
+ CBB* out_compressible,
+ ssl_client_hello_type_t type) {
+ if (hs->config->record_size_limit == 0) {
+ return true;
+ }
+
+ CBB data;
+ const uint16_t data_ = hs->config->record_size_limit;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_record_size_limit) ||
+ !CBB_add_u16_length_prefixed(out, &data) || !CBB_add_u16(&data, data_) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+ return true;
+}
+
+static bool record_size_limit_parse_serverhello(SSL_HANDSHAKE* hs,
+ uint8_t* out_alert,
+ CBS* contents) {
+ return true;
+}
+
+static bool record_size_limit_parse_clienthello(SSL_HANDSHAKE* hs,
+ uint8_t* out_alert,
+ CBS* contents) {
+ return true;
+}
+
+static bool record_size_limit_add_serverhello(SSL_HANDSHAKE* hs, CBB* out) {
+ return true;
+}
+
// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
{
@@ -3206,6 +3291,13 @@ static const struct tls_extension kExtensions[] = {
ignore_parse_clienthello,
ext_alps_add_serverhello,
},
+ {
+ TLSEXT_TYPE_record_size_limit,
+ record_size_limit_add_clienthello,
+ record_size_limit_parse_serverhello,
+ record_size_limit_parse_clienthello,
+ record_size_limit_add_serverhello,
+ },
{
TLSEXT_TYPE_application_settings_old,
ext_alps_add_clienthello_old,
@@ -3245,6 +3337,7 @@ bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
!permutation.InitForOverwrite(kNumExtensions)) {
return false;
}
+ // By default, nothing is permuted.
for (size_t i = 0; i < kNumExtensions; i++) {
permutation[i] = i;
}
@@ -3269,6 +3362,43 @@ static const struct tls_extension *tls_extension_find(uint32_t *out_index,
return NULL;
}
+// curl-impersonate: set customized extension order
+//
+// Generate the extension_permutation array from a customized extension order string.
+//
+// The customized extension order string is a dash-separated list of extensions.
+//
+bool ssl_set_extension_order(SSL_HANDSHAKE *hs) {
+ if (hs->config->extension_order == nullptr) {
+ return true;
+ }
+ // fprintf(stderr, "order %s\n", hs->config->extension_order);
+ Array<uint8_t> order;
+ if (!order.Init(kNumExtensions)) {
+ return false;
+ }
+ // By default, nothing is reordered.
+ for (size_t i = 0; i < kNumExtensions; i++) {
+ order[i] = 255;
+ }
+ // split the order string, and put there order in the table
+ const char *delimiter = "-";
+ char *tmp = strdup(hs->config->extension_order);
+ char *ext = strtok(tmp, delimiter);
+ size_t idx = 0;
+ while (ext != nullptr) {
+ unsigned ext_index = 0;
+ tls_extension_find(&ext_index, atoi(ext));
+ order[idx] = ext_index;
+ ext = strtok(NULL, delimiter);
+ idx++;
+ }
+ free(tmp);
+
+ hs->extension_permutation = std::move(order);
+ return true;
+}
+
static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
CBB child;
if (!CBB_add_u16(cbb, ext) || //
@@ -3315,6 +3445,7 @@ static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out,
size_t i = hs->extension_permutation.empty()
? unpermuted
: hs->extension_permutation[unpermuted];
+ if (i == 255) { continue; } // curl-impersonate: skip non-exist extensions
const size_t len_before = CBB_len(&extensions);
const size_t len_compressed_before = CBB_len(compressed.get());
if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(),
@@ -3424,6 +3555,7 @@ bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded,
size_t i = hs->extension_permutation.empty()
? unpermuted
: hs->extension_permutation[unpermuted];
+ if (i == 255) { continue; } // curl-impersonate: skip non-exist extensions
const size_t len_before = CBB_len(&extensions);
if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 3f8040b63..4f8f34e88 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -21,6 +21,8 @@
#include <openssl/aead.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
+#include <openssl/dh.h>
+#include <../crypto/fipsmodule/dh/internal.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
@@ -77,14 +79,6 @@ static void ssl_get_client_disabled(const SSL_HANDSHAKE *hs,
}
}
-static bool ssl_add_tls13_cipher(CBB *cbb, uint16_t cipher_id,
- ssl_compliance_policy_t policy) {
- if (ssl_tls13_cipher_meets_policy(cipher_id, policy)) {
- return CBB_add_u16(cbb, cipher_id);
- }
- return true;
-}
-
static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
ssl_client_hello_type_t type) {
const SSL *const ssl = hs->ssl;
@@ -102,41 +96,9 @@ static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
return false;
}
- // Add TLS 1.3 ciphers. Order ChaCha20-Poly1305 relative to AES-GCM based on
- // hardware support.
- if (hs->max_version >= TLS1_3_VERSION) {
- static const uint16_t kCiphersNoAESHardware[] = {
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
- TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
- };
- static const uint16_t kCiphersAESHardware[] = {
- TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
- TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- };
- static const uint16_t kCiphersCNSA[] = {
- TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
- TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- };
-
- const bool has_aes_hw = ssl->config->aes_hw_override
- ? ssl->config->aes_hw_override_value
- : EVP_has_aes_hardware();
- const bssl::Span<const uint16_t> ciphers =
- ssl->config->compliance_policy == ssl_compliance_policy_cnsa_202407
- ? bssl::Span<const uint16_t>(kCiphersCNSA)
- : (has_aes_hw ? bssl::Span<const uint16_t>(kCiphersAESHardware)
- : bssl::Span<const uint16_t>(kCiphersNoAESHardware));
-
- for (auto cipher : ciphers) {
- if (!ssl_add_tls13_cipher(&child, cipher,
- ssl->config->compliance_policy)) {
- return false;
- }
- }
- }
+ // curl-impersonate: TLS 1.3 suites are added uniformly with other suites.
+ // TODO: in new versions, perhaps it's OK to keep the original code here.
+
if (hs->min_version < TLS1_3_VERSION && type != ssl_client_hello_inner) {
bool any_enabled = false;
@@ -417,8 +379,9 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) {
hs->early_data_offered = true;
}
+ // curl-impersonate: set extension orders
if (!ssl_setup_key_shares(hs, /*override_group_id=*/0) ||
- !ssl_setup_extension_permutation(hs) ||
+ !ssl_setup_extension_permutation(hs) || !ssl_set_extension_order(hs) ||
!ssl_encrypt_client_hello(hs, Span(ech_enc, ech_enc_len)) ||
!ssl_add_client_hello(hs)) {
return ssl_hs_error;
@@ -1004,7 +967,28 @@ static enum ssl_hs_wait_t do_read_server_key_exchange(SSL_HANDSHAKE *hs) {
hs->peer_psk_identity_hint.reset(raw);
}
- if (alg_k & SSL_kECDHE) {
+ if (alg_k & SSL_kDHE) {
+ CBS dh_p, dh_g, dh_Ys;
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
+ CBS_len(&dh_p) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
+ CBS_len(&dh_g) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
+ CBS_len(&dh_Ys) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return ssl_hs_error;
+ }
+
+ if (!hs->dh_p.CopyFrom(dh_p) || !hs->dh_g.CopyFrom(dh_g)) {
+ return ssl_hs_error;
+ }
+
+ /* Save the peer public key for later. */
+ if (!hs->peer_key.CopyFrom(dh_Ys)) {
+ return ssl_hs_error;
+ }
+ } else if (alg_k & SSL_kECDHE) {
// Parse the server parameters.
uint8_t group_type;
uint16_t group_id;
@@ -1344,7 +1328,9 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
ssl_key_usage_t intended_use = (alg_k & SSL_kRSA)
? key_usage_encipherment
: key_usage_digital_signature;
- if (!ssl_cert_check_key_usage(&leaf_cbs, intended_use)) {
+ // curl-impersonate: optionally disable ssl key usage check
+ if (hs->config->key_usage_check_enabled &&
+ !ssl_cert_check_key_usage(&leaf_cbs, intended_use)) {
if (hs->config->enforce_rsa_key_usage ||
EVP_PKEY_id(hs->peer_pubkey.get()) != EVP_PKEY_RSA) {
return ssl_hs_error;
@@ -1418,6 +1404,64 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
!CBB_flush(&body)) {
return ssl_hs_error;
}
+ } else if (alg_k & SSL_kDHE) {
+ DH *dh = DH_new();
+ if (dh == nullptr) {
+ return ssl_hs_error;
+ }
+
+ dh->p = BN_bin2bn(hs->dh_p.data(), hs->dh_p.size(), nullptr);
+ dh->g = BN_bin2bn(hs->dh_g.data(), hs->dh_g.size(), nullptr);
+ if (dh->p == nullptr || dh->g == nullptr) {
+ DH_free(dh);
+ return ssl_hs_error;
+ }
+
+ unsigned bits = DH_num_bits(dh);
+ if (bits < 1024) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
+ DH_free(dh);
+ return ssl_hs_error;
+ } else if (bits > 4096) {
+ /* Overly large DHE groups are prohibitively expensive, so enforce a limit
+ * to prevent a server from causing us to perform too expensive of a
+ * computation. */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG);
+ DH_free(dh);
+ return ssl_hs_error;
+ }
+
+ CBB child;
+ if (!CBB_add_u16_length_prefixed(&body, &child)) {
+ DH_free(dh);
+ return ssl_hs_error;
+ }
+
+ if (!DH_generate_key(dh) ||
+ !BN_bn2cbb_padded(&child, BN_num_bytes(dh->p), dh->pub_key)) {
+ DH_free(dh);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return ssl_hs_error;
+ }
+
+ int secret_len = 0;
+ BIGNUM *peer_point = BN_bin2bn(hs->peer_key.data(), hs->peer_key.size(), nullptr);
+ if (peer_point == nullptr ||
+ !pms.InitForOverwrite(DH_size(dh)) ||
+ (secret_len = DH_compute_key(pms.data(), peer_point, dh)) <= 0) {
+ BN_free(peer_point);
+ DH_free(dh);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return ssl_hs_error;
+ }
+
+ pms.Shrink(secret_len);
+ BN_free(peer_point);
+ DH_free(dh);
+
+ hs->dh_p.Reset();
+ hs->dh_g.Reset();
+ hs->peer_key.Reset();
} else if (alg_k & SSL_kECDHE) {
CBB child;
if (!CBB_add_u8_length_prefixed(&body, &child)) {
diff --git a/ssl/internal.h b/ssl/internal.h
index bf8bf3602..e30906cb0 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -690,10 +690,11 @@ BSSL_NAMESPACE_BEGIN
// Bits for |algorithm_mkey| (key exchange algorithm).
#define SSL_kRSA 0x00000001u
-#define SSL_kECDHE 0x00000002u
+#define SSL_kDHE 0x00000002u
+#define SSL_kECDHE 0x00000004u
// SSL_kPSK is only set for plain PSK, not ECDHE_PSK.
-#define SSL_kPSK 0x00000004u
-#define SSL_kGENERIC 0x00000008u
+#define SSL_kPSK 0x00000008u
+#define SSL_kGENERIC 0x00000010u
// Bits for |algorithm_auth| (server authentication).
#define SSL_aRSA_SIGN 0x00000001u
@@ -718,8 +719,9 @@ BSSL_NAMESPACE_BEGIN
// Bits for |algorithm_mac| (symmetric authentication).
#define SSL_SHA1 0x00000001u
#define SSL_SHA256 0x00000002u
+#define SSL_SHA384 0x00000004u
// SSL_AEAD is set for all AEADs.
-#define SSL_AEAD 0x00000004u
+#define SSL_AEAD 0x00000008u
// Bits for |algorithm_prf| (handshake digest).
#define SSL_HANDSHAKE_MAC_DEFAULT 0x1
@@ -2131,7 +2133,7 @@ struct SSL_HANDSHAKE {
// key_shares are the current key exchange instances. The second is only used
// as a client if we believe that we should offer two key shares in a
// ClientHello.
- UniquePtr<SSLKeyShare> key_shares[2];
+ UniquePtr<SSLKeyShare> key_shares[3];
// transcript is the current handshake transcript.
SSLTranscript transcript;
@@ -2189,6 +2191,9 @@ struct SSL_HANDSHAKE {
// delegated credentials.
Array<uint16_t> peer_delegated_credential_sigalgs;
+ Array<uint8_t> dh_p;
+ Array<uint8_t> dh_g;
+
// peer_key is the peer's ECDH key for a TLS 1.2 client.
Array<uint8_t> peer_key;
@@ -2457,6 +2462,12 @@ bssl::UniquePtr<SSL_SESSION> tls13_create_session_with_ticket(SSL *ssl,
// for |hs|, if applicable. It returns true on success and false on error.
bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs);
+// curl-impersonate
+bool ssl_set_extension_order(SSL_HANDSHAKE *hs);
+
+// curl-impersonate
+bool ssl_set_key_usage_check_enabled(SSL_HANDSHAKE *hs);
+
// ssl_setup_key_shares computes client key shares and saves them in |hs|. It
// returns true on success and false on failure. If |override_group_id| is zero,
// it offers the default groups, including GREASE. If it is non-zero, it offers
@@ -3520,6 +3531,12 @@ struct SSL_CONFIG {
// crypto
UniquePtr<SSLCipherPreferenceList> cipher_list;
+ // curl-impersonate
+ char *extension_order = nullptr;
+
+ // curl-impersonate
+ int key_usage_check_enabled = 1;
+
// This is used to hold the local certificate used (i.e. the server
// certificate for a server or the client certificate for a client).
UniquePtr<CERT> cert;
@@ -3578,6 +3595,10 @@ struct SSL_CONFIG {
// accepted from the peer in decreasing order of preference.
Array<uint16_t> verify_sigalgs;
+ // delegated_credentials, if not empty, is the set of signature algorithms
+ // supported by the client.
+ Array<uint16_t> delegated_credentials;
+
// srtp_profiles is the list of configured SRTP protection profiles for
// DTLS-SRTP.
UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
@@ -3643,6 +3664,14 @@ struct SSL_CONFIG {
// hardware support, and use the value in aes_hw_override_value instead.
bool aes_hw_override : 1;
+ // curl-impersonate: record_size_limit is whether to send record size limit
+ // extension.
+ uint16_t record_size_limit = 0;
+
+ // curl-impersonate: key_shares_limit is the maximum number of key shares to
+ // send.
+ uint8_t key_shares_limit = 0;
+
// aes_hw_override_value is used for testing to indicate the support or lack
// of support for AES hw. The value is only considered if |aes_hw_override| is
// true.
@@ -4024,6 +4053,12 @@ struct ssl_ctx_st : public bssl::RefCounted<ssl_ctx_st> {
bssl::UniquePtr<bssl::SSLCipherPreferenceList> cipher_list;
+ // curl-impersonate
+ char *extension_order = nullptr;
+
+ // curl-impersonate
+ int key_usage_check_enabled = 1;
+
X509_STORE *cert_store = nullptr;
LHASH_OF(SSL_SESSION) *sessions = nullptr;
// Most session-ids that will be cached, default is
@@ -4248,6 +4283,10 @@ struct ssl_ctx_st : public bssl::RefCounted<ssl_ctx_st> {
// accepted from the peer in decreasing order of preference.
bssl::Array<uint16_t> verify_sigalgs;
+ // delegated_credentials, if not empty, is the set of signature algorithms
+ // supported by the client.
+ bssl::Array<uint16_t> delegated_credentials;
+
// retain_only_sha256_of_client_certs is true if we should compute the SHA256
// hash of the peer's certificate and then discard it to save memory and
// session space. Only effective on the server side.
@@ -4300,6 +4339,14 @@ struct ssl_ctx_st : public bssl::RefCounted<ssl_ctx_st> {
// |aes_hw_override| is true.
bool aes_hw_override_value : 1;
+ // curl-impersonate: record_size_limit is whether to send record size limit
+ // extension.
+ uint16_t record_size_limit = 0;
+
+ // curl-impersonate: key_shares limit is the maximum number of key shares to
+ // send.
+ uint8_t key_shares_limit = 0;
+
private:
friend RefCounted;
~ssl_ctx_st();
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc
index 99c7bc977..eb0e7f753 100644
--- a/ssl/ssl_cipher.cc
+++ b/ssl/ssl_cipher.cc
@@ -56,6 +56,18 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_DEFAULT,
},
+ // Cipher 33
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL_HANDSHAKE_MAC_DEFAULT,
+ },
+
// Cipher 35
{
TLS1_TXT_RSA_WITH_AES_256_SHA,
@@ -68,6 +80,68 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_DEFAULT,
},
+ // Cipher 39
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL_HANDSHAKE_MAC_DEFAULT,
+ },
+
+ // TLS v1.2 ciphersuites
+
+ // Cipher 3C
+ {
+ TLS1_TXT_RSA_WITH_AES_128_SHA256,
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ TLS1_CK_RSA_WITH_AES_128_SHA256,
+ SSL_kRSA,
+ SSL_aRSA_DECRYPT,
+ SSL_AES128,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ // Cipher 3D
+ {
+ TLS1_TXT_RSA_WITH_AES_256_SHA256,
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ TLS1_CK_RSA_WITH_AES_256_SHA256,
+ SSL_kRSA,
+ SSL_aRSA_DECRYPT,
+ SSL_AES256,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ // Cipher 67
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES128,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ // Cipher 6B
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES256,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
// PSK cipher suites.
// Cipher 8C
@@ -120,6 +194,30 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_SHA384,
},
+ // Cipher 9E
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ // Cipher 9F
+ {
+ TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_kDHE,
+ SSL_aRSA_DECRYPT,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA384,