-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCECPQ2b_for_BoringSSL_706da620b248615b709e71b36a31312f87a2c692.patch
5680 lines (5606 loc) · 184 KB
/
CECPQ2b_for_BoringSSL_706da620b248615b709e71b36a31312f87a2c692.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
From 7853b9e4cc0aee197a2d849b9f8ec9af2da14e08 Mon Sep 17 00:00:00 2001
From: Kris Kwiatkowski <kris@cloudflare.com>
Date: Thu, 24 Oct 2019 14:41:03 +0100
Subject: [PATCH] Implements SIKE/p434.
Implementation based on Microsoft's implementation available on github:
Source: https://github.com/Microsoft/PQCrypto-SIDH
* adds optimized implementation for aarch64
* In intel assembly, use MOV instead of MOVQ:
Intel instruction reference in the Intel Software Developer's Manual
volume 2A, the MOVQ has 4 forms. None of them mentions moving
literal to GPR, hence "movq $rax, 0x0" is wrong. Instead, on 64bit
system, MOV can be used.
* Some variables were wrongly zero-initialized (as per C99 spec).
* Rewrite x86_64 assembly to AT&T format.
* Move assembly for x86_64 and aarch64 to perlasm.
* Changes to aarch64 assembly, to avoid using x18 platform register.
Assembly also correctly constructs linked list of stack-frames as
described in AAPCS64, 5.2.3.
* Move constant values to .RODATA segment, as keeping them in .TEXT
segment is not compatible with XOM.
* Fixes issue in arm64 code related to the fact that compiler doesn't
reserve enough space for the linker to relocate address of a global
variable when used by 'ldr' instructions. Solution is to use 'adrp'
followed by 'add' instruction. Relocations for 'adrp' and 'add'
instructions is generated by prefixing the label with :pg_hi21:
and :lo12: respectively.
* Enable MULX and ADX. Code from MS doesn't support PIC. MULX can't
reference global variable directly. Instead RIP-relative addressing
can be used. This improves performance around 10%-13% on SkyLake
* Check if CPU supports BMI2 and ADOX instruction at runtime. On AMD64
optimized implementation of montgomery multiplication and reduction
have 2 implementations - faster one takes advantage of BMI2
instruction set introduced in Haswell and ADOX introduced in
Broadwell. Thanks to OPENSSL_ia32cap_P it can be decided at runtime
which implementation to choose. As CPU configuration is static by
nature, branch predictor will be correct most of the time and hence
this check very often has no cost.
* Reuse some utilities from boringssl instead of reimplementing them.
This includes things like:
* definition of a limb size (use crypto_word_t instead of digit_t)
* use functions for checking in constant time if value is 0 and/or
less then
* #define's used for conditional compilation
* Fix f2elm_t definition. Code imported from MSR defines f2elm_t type as
a array of arrays. This decays to a pointer to an array (when passing
as an argument). In C, one can't assign const pointer to an array with
non-const pointer to an array. Seems it violates 6.7.3/8 from C99
(same for C11). This problem occures in GCC 6, only when -pedantic
flag is specified and it occures always in GCC 4.9 (debian jessie).
* Fix definition of eval_3_isog. Second argument in eval_3_isog mustn't be
const. Similar reason as above.
* KEM uses SHA256 instead of HMAC-256
* Add speed and unit tests for SIKE.
Some speed results:
Skylake (64-bit):
Did 408 SIKE/P503 generate operations in 1002573us (407.0 ops/sec)
Did 275 SIKE/P503 encap operations in 1070570us (256.9 ops/sec)
Did 264 SIKE/P503 decap operations in 1098955us (240.2 ops/sec)
Change-Id: I0906e2b105cbb66a0f733dd02203211fb703939b
---
LICENSE | 23 +
crypto/CMakeLists.txt | 10 +
crypto/obj/obj_dat.h | 7 +-
crypto/obj/obj_mac.num | 1 +
crypto/obj/objects.txt | 3 +
include/openssl/nid.h | 3 +
include/openssl/ssl.h | 1 +
ssl/s3_both.cc | 3 +-
ssl/ssl_key_share.cc | 85 ++
ssl/t1_lib.cc | 2 +-
ssl/test/runner/common.go | 15 +-
ssl/test/runner/handshake_server.go | 4 +-
ssl/test/runner/key_agreement.go | 97 +-
ssl/test/runner/runner.go | 194 +++-
ssl/test/test_config.cc | 7 +-
third_party/sike/LICENSE | 21 +
third_party/sike/asm/fp-armv8.pl | 915 +++++++++++++++
third_party/sike/asm/fp-x86_64.pl | 1626 +++++++++++++++++++++++++++
third_party/sike/asm/fp_generic.c | 181 +++
third_party/sike/curve_params.c | 128 +++
third_party/sike/fpx.c | 283 +++++
third_party/sike/fpx.h | 113 ++
third_party/sike/isogeny.c | 260 +++++
third_party/sike/isogeny.h | 49 +
third_party/sike/sike.c | 531 +++++++++
third_party/sike/sike.h | 64 ++
third_party/sike/sike_test.cc | 251 +++++
third_party/sike/utils.h | 145 +++
tool/speed.cc | 61 +
util/generate_build_files.py | 6 +-
30 files changed, 5070 insertions(+), 19 deletions(-)
create mode 100644 third_party/sike/LICENSE
create mode 100644 third_party/sike/asm/fp-armv8.pl
create mode 100755 third_party/sike/asm/fp-x86_64.pl
create mode 100644 third_party/sike/asm/fp_generic.c
create mode 100644 third_party/sike/curve_params.c
create mode 100644 third_party/sike/fpx.c
create mode 100644 third_party/sike/fpx.h
create mode 100644 third_party/sike/isogeny.c
create mode 100644 third_party/sike/isogeny.h
create mode 100644 third_party/sike/sike.c
create mode 100644 third_party/sike/sike.h
create mode 100644 third_party/sike/sike_test.cc
create mode 100644 third_party/sike/utils.h
diff --git a/LICENSE b/LICENSE
index 49c41fa7a..2f4dfcdb0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -181,6 +181,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+The code in third_party/sike also carries the MIT license:
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
+
Licenses for support code
-------------------------
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 427bc64e9..f3e2ca477 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -115,6 +115,7 @@ if(${ARCH} STREQUAL "aarch64")
chacha/chacha-armv8.${ASM_EXT}
test/trampoline-armv8.${ASM_EXT}
+ third_party/sike/asm/fp-armv8.${ASM_EXT}
)
endif()
@@ -136,6 +137,7 @@ if(${ARCH} STREQUAL "x86_64")
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
hrss/asm/poly_rq_mul.S
test/trampoline-x86_64.${ASM_EXT}
+ third_party/sike/asm/fp-x86_64.${ASM_EXT}
)
endif()
@@ -145,6 +147,8 @@ perlasm(chacha/chacha-x86.${ASM_EXT} chacha/asm/chacha-x86.pl)
perlasm(chacha/chacha-x86_64.${ASM_EXT} chacha/asm/chacha-x86_64.pl)
perlasm(cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT} cipher_extra/asm/aes128gcmsiv-x86_64.pl)
perlasm(cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} cipher_extra/asm/chacha20_poly1305_x86_64.pl)
+perlasm(third_party/sike/asm/fp-x86_64.${ASM_EXT} ../third_party/sike/asm/fp-x86_64.pl)
+perlasm(third_party/sike/asm/fp-armv8.${ASM_EXT} ../third_party/sike/asm/fp-armv8.pl)
perlasm(test/trampoline-armv4.${ASM_EXT} test/asm/trampoline-armv4.pl)
perlasm(test/trampoline-armv8.${ASM_EXT} test/asm/trampoline-armv8.pl)
perlasm(test/trampoline-x86.${ASM_EXT} test/asm/trampoline-x86.pl)
@@ -408,6 +412,11 @@ add_library(
x509v3/v3_sxnet.c
x509v3/v3_utl.c
../third_party/fiat/curve25519.c
+ ../third_party/sike/fpx.c
+ ../third_party/sike/isogeny.c
+ ../third_party/sike/curve_params.c
+ ../third_party/sike/sike.c
+ ../third_party/sike/asm/fp_generic.c
$<TARGET_OBJECTS:fipsmodule>
@@ -528,6 +537,7 @@ add_executable(
x509/x509_time_test.cc
x509v3/tab_test.cc
x509v3/v3name_test.cc
+ ../third_party/sike/sike_test.cc
$<TARGET_OBJECTS:crypto_test_data>
$<TARGET_OBJECTS:boringssl_gtest_main>
diff --git a/crypto/obj/obj_dat.h b/crypto/obj/obj_dat.h
index 53198f947..b6bbe3036 100644
--- a/crypto/obj/obj_dat.h
+++ b/crypto/obj/obj_dat.h
@@ -57,7 +57,7 @@
/* This file is generated by crypto/obj/objects.go. */
-#define NUM_NID 961
+#define NUM_NID 962
static const uint8_t kObjectData[] = {
/* NID_rsadsi */
@@ -8760,7 +8760,8 @@ static const ASN1_OBJECT kObjects[NUM_NID] = {
{"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
{"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
{"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0},
- {"ED448", "ED448", NID_ED448, 3, &kObjectData[6178], 0},
+ {"CECPQ2b", "CECPQ2b", NID_CECPQ2b, 0, NULL, 0},
+ {"ED448", "ED448", NID_ED448, 3, &kObjectData[6178], 0}
};
static const unsigned kNIDsInShortNameOrder[] = {
@@ -8823,6 +8824,7 @@ static const unsigned kNIDsInShortNameOrder[] = {
109 /* CAST5-ECB */,
111 /* CAST5-OFB */,
959 /* CECPQ2 */,
+ 961 /* CECPQ2b */,
894 /* CMAC */,
13 /* CN */,
141 /* CRLReason */,
@@ -9729,6 +9731,7 @@ static const unsigned kNIDsInLongNameOrder[] = {
179 /* CA Issuers */,
785 /* CA Repository */,
959 /* CECPQ2 */,
+ 961 /* CECPQ2b */,
131 /* Code Signing */,
783 /* Diffie-Hellman based MAC */,
382 /* Directory */,
diff --git a/crypto/obj/obj_mac.num b/crypto/obj/obj_mac.num
index 5310ceb54..b178fad27 100644
--- a/crypto/obj/obj_mac.num
+++ b/crypto/obj/obj_mac.num
@@ -949,3 +949,4 @@ kx_any 957
auth_any 958
CECPQ2 959
ED448 960
+CECPQ2b 961
diff --git a/crypto/obj/objects.txt b/crypto/obj/objects.txt
index 3d7c7a0c1..ce7d7a2b7 100644
--- a/crypto/obj/objects.txt
+++ b/crypto/obj/objects.txt
@@ -1337,6 +1337,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
# NID for CECPQ2 (no corresponding OID).
: CECPQ2
+# NID for CECPQ2 (no corresponding OID).
+ : CECPQ2b
+
# See RFC 8410.
1 3 101 112 : ED25519
diff --git a/include/openssl/nid.h b/include/openssl/nid.h
index b7fb207d3..ee140c248 100644
--- a/include/openssl/nid.h
+++ b/include/openssl/nid.h
@@ -4241,6 +4241,9 @@ extern "C" {
#define NID_ED448 960
#define OBJ_ED448 1L, 3L, 101L, 113L
+#define SN_CECPQ2b "CECPQ2b"
+#define NID_CECPQ2b 960
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index b0ee69ac8..39bf5a584 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2231,6 +2231,7 @@ OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
#define SSL_CURVE_SECP521R1 25
#define SSL_CURVE_X25519 29
#define SSL_CURVE_CECPQ2 16696
+#define SSL_CURVE_CECPQ2b 65074
// SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently
// completed handshake or 0 if not applicable.
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 1ec596a37..58f0f8a87 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -660,7 +660,8 @@ class CipherScorer {
public:
CipherScorer(uint16_t group_id)
: aes_is_fine_(EVP_has_aes_hardware()),
- security_128_is_fine_(group_id != SSL_CURVE_CECPQ2) {}
+ security_128_is_fine_(group_id != SSL_CURVE_CECPQ2 &&
+ group_id != SSL_CURVE_CECPQ2b) {}
typedef std::tuple<bool, bool, bool> Score;
diff --git a/ssl/ssl_key_share.cc b/ssl/ssl_key_share.cc
index 6cac3cf22..826fb1acc 100644
--- a/ssl/ssl_key_share.cc
+++ b/ssl/ssl_key_share.cc
@@ -31,6 +31,7 @@
#include "internal.h"
#include "../crypto/internal.h"
+#include "../third_party/sike/sike.h"
BSSL_NAMESPACE_BEGIN
@@ -299,6 +300,87 @@ class CECPQ2KeyShare : public SSLKeyShare {
HRSS_private_key hrss_private_key_;
};
+class CECPQ2bKeyShare : public SSLKeyShare {
+ public:
+ uint16_t GroupID() const override { return SSL_CURVE_CECPQ2b; }
+
+ bool Offer(CBB *out) override {
+ uint8_t public_x25519[32] = {0};
+ X25519_keypair(public_x25519, private_x25519_);
+ if (!SIKE_keypair(private_sike_, public_sike_)) {
+ return false;
+ }
+
+ return CBB_add_bytes(out, public_x25519, sizeof(public_x25519)) &&
+ CBB_add_bytes(out, public_sike_, sizeof(public_sike_));
+ }
+
+ bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+ uint8_t *out_alert, Span<const uint8_t> peer_key) override {
+ uint8_t public_x25519[32];
+ uint8_t private_x25519[32];
+ uint8_t sike_ciphertext[SIKE_CT_BYTESZ] = {0};
+
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ if (peer_key.size() != sizeof(public_x25519) + SIKE_PUB_BYTESZ) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ return false;
+ }
+
+ Array<uint8_t> secret;
+ if (!secret.Init(sizeof(private_x25519_) + SIKE_SS_BYTESZ)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return false;
+ }
+
+ X25519_keypair(public_x25519, private_x25519);
+ if (!X25519(secret.data(), private_x25519, peer_key.data())) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ return false;
+ }
+
+ SIKE_encaps(secret.data() + sizeof(private_x25519_), sike_ciphertext,
+ peer_key.data() + sizeof(public_x25519));
+ *out_secret = std::move(secret);
+
+ return CBB_add_bytes(out_public_key, public_x25519,
+ sizeof(public_x25519)) &&
+ CBB_add_bytes(out_public_key, sike_ciphertext,
+ sizeof(sike_ciphertext));
+ }
+
+ bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+ Span<const uint8_t> peer_key) override {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ Array<uint8_t> secret;
+ if (!secret.Init(sizeof(private_x25519_) + SIKE_SS_BYTESZ)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return false;
+ }
+
+ if (peer_key.size() != 32 + SIKE_CT_BYTESZ ||
+ !X25519(secret.data(), private_x25519_, peer_key.data())) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ return false;
+ }
+
+ SIKE_decaps(secret.data() + sizeof(private_x25519_), peer_key.data() + 32,
+ public_sike_, private_sike_);
+ *out_secret = std::move(secret);
+ return true;
+ }
+
+ private:
+ uint8_t private_x25519_[32];
+ uint8_t private_sike_[SIKE_PRV_BYTESZ];
+ uint8_t public_sike_[SIKE_PUB_BYTESZ];
+};
+
CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
@@ -306,6 +388,7 @@ CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
{NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
+ {NID_CECPQ2b, SSL_CURVE_CECPQ2b, "CECPQ2b", "CECPQ2b"},
};
} // namespace
@@ -332,6 +415,8 @@ UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
case SSL_CURVE_CECPQ2:
return UniquePtr<SSLKeyShare>(New<CECPQ2KeyShare>());
+ case SSL_CURVE_CECPQ2b:
+ return UniquePtr<SSLKeyShare>(New<CECPQ2bKeyShare>());
default:
return nullptr;
}
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 298dc9b05..7220e99cd 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -200,7 +200,7 @@ static bool tls1_check_duplicate_extensions(const CBS *cbs) {
}
static bool is_post_quantum_group(uint16_t id) {
- return id == SSL_CURVE_CECPQ2;
+ return id == SSL_CURVE_CECPQ2 || id == SSL_CURVE_CECPQ2b;
}
bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index e78e9a299..d1cf757dd 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -145,12 +145,13 @@ var tls13HelloRetryRequest = []uint8{
type CurveID uint16
const (
- CurveP224 CurveID = 21
- CurveP256 CurveID = 23
- CurveP384 CurveID = 24
- CurveP521 CurveID = 25
- CurveX25519 CurveID = 29
- CurveCECPQ2 CurveID = 16696
+ CurveP224 CurveID = 21
+ CurveP256 CurveID = 23
+ CurveP384 CurveID = 24
+ CurveP521 CurveID = 25
+ CurveX25519 CurveID = 29
+ CurveCECPQ2 CurveID = 16696
+ CurveCECPQ2b CurveID = 65074
)
// TLS Elliptic Curve Point Formats
@@ -1731,7 +1732,7 @@ func (c *Config) maxVersion(isDTLS bool) uint16 {
return ret
}
-var defaultCurvePreferences = []CurveID{CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
+var defaultCurvePreferences = []CurveID{CurveCECPQ2b, CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
if c == nil || len(c.CurvePreferences) == 0 {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 24278564d..44b817ee4 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -210,7 +210,7 @@ func (hs *serverHandshakeState) readClientHello() error {
if config.Bugs.FailIfCECPQ2Offered {
for _, offeredCurve := range hs.clientHello.supportedCurves {
if isPqGroup(offeredCurve) {
- return errors.New("tls: CECPQ2 was offered")
+ return errors.New("tls: CECPQ2 or CECPQ2b was offered")
}
}
}
@@ -1227,7 +1227,7 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error)
Curves:
for _, curve := range hs.clientHello.supportedCurves {
if isPqGroup(curve) && c.vers < VersionTLS13 {
- // CECPQ2 is TLS 1.3-only.
+ // CECPQ2 and CECPQ2b is TLS 1.3-only.
continue
}
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 266163ec5..56cfec8b8 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -19,6 +19,7 @@ import (
"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
+ "boringssl.googlesource.com/boringssl/ssl/test/runner/sike"
)
type keyType int
@@ -433,6 +434,98 @@ func (e *cecpq2Curve) finish(peerKey []byte) (preMasterSecret []byte, err error)
return preMasterSecret, nil
}
+// cecpq2BCurve implements CECPQ2b, which is SIKE combined with X25519.
+type cecpq2BCurve struct {
+ // Both public key and shared secret size
+ x25519PrivateKey [32]byte
+ sikePrivateKey *sike.PrivateKey
+}
+
+func (e *cecpq2BCurve) offer(rand io.Reader) (publicKey []byte, err error) {
+ if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
+ return nil, err
+ }
+
+ var x25519Public [32]byte
+ curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
+
+ e.sikePrivateKey = sike.NewPrivateKey(sike.KeyVariant_SIKE)
+ if err = e.sikePrivateKey.Generate(rand); err != nil {
+ return nil, err
+ }
+
+ sikePublic := e.sikePrivateKey.GeneratePublicKey().Export()
+ var ret []byte
+ ret = append(ret, x25519Public[:]...)
+ ret = append(ret, sikePublic...)
+ return ret, nil
+}
+
+func (e *cecpq2BCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+sike.Params.PublicKeySize {
+ return nil, nil, errors.New("tls: bad length CECPQ2b offer")
+ }
+
+ if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
+ return nil, nil, err
+ }
+
+ var x25519Shared, x25519PeerKey, x25519Public [32]byte
+ copy(x25519PeerKey[:], peerKey)
+ curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
+ curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
+
+ // Per RFC 7748, reject the all-zero value in constant time.
+ var zeros [32]byte
+ if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
+ return nil, nil, errors.New("tls: X25519 value with wrong order")
+ }
+
+ var sikePubKey = sike.NewPublicKey(sike.KeyVariant_SIKE)
+ if err = sikePubKey.Import(peerKey[32:]); err != nil {
+ // should never happen as size was already checked
+ return nil, nil, errors.New("tls: implementation error")
+ }
+ sikeCiphertext, sikeShared, err := sike.Encapsulate(rand, sikePubKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ publicKey = append(publicKey, x25519Public[:]...)
+ publicKey = append(publicKey, sikeCiphertext...)
+ preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
+ preMasterSecret = append(preMasterSecret, sikeShared...)
+
+ return publicKey, preMasterSecret, nil
+}
+
+func (e *cecpq2BCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+(sike.Params.PublicKeySize+sike.Params.MsgLen) {
+ return nil, errors.New("tls: bad length CECPQ2b reply")
+ }
+
+ var x25519Shared, x25519PeerKey [32]byte
+ copy(x25519PeerKey[:], peerKey)
+ curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
+
+ // Per RFC 7748, reject the all-zero value in constant time.
+ var zeros [32]byte
+ if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
+ return nil, errors.New("tls: X25519 value with wrong order")
+ }
+
+ var sikePubKey = e.sikePrivateKey.GeneratePublicKey()
+ sikeShared, err := sike.Decapsulate(e.sikePrivateKey, sikePubKey, peerKey[32:])
+ if err != nil {
+ return nil, errors.New("tls: invalid SIKE ciphertext")
+ }
+
+ preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
+ preMasterSecret = append(preMasterSecret, sikeShared...)
+
+ return preMasterSecret, nil
+}
+
func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
switch id {
case CurveP224:
@@ -447,6 +540,8 @@ func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
case CurveCECPQ2:
return &cecpq2Curve{}, true
+ case CurveCECPQ2b:
+ return &cecpq2BCurve{}, true
default:
return nil, false
}
@@ -595,7 +690,7 @@ func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Cer
NextCandidate:
for _, candidate := range preferredCurves {
if isPqGroup(candidate) && version < VersionTLS13 {
- // CECPQ2 is TLS 1.3-only.
+ // CECPQ2 and CECPQ2b is TLS 1.3-only.
continue
}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 660be0aa5..0acb5adf8 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -10455,12 +10455,13 @@ var testCurves = []struct {
{"P-521", CurveP521},
{"X25519", CurveX25519},
{"CECPQ2", CurveCECPQ2},
+ {"CECPQ2b", CurveCECPQ2b},
}
const bogusCurve = 0x1234
func isPqGroup(r CurveID) bool {
- return r == CurveCECPQ2
+ return r == CurveCECPQ2 || r == CurveCECPQ2b
}
func addCurveTests() {
@@ -10933,6 +10934,21 @@ func addCurveTests() {
},
})
+ // CECPQ2b should not be offered by a TLS < 1.3 client.
+ testCases = append(testCases, testCase{
+ name: "CECPQ2bNotInTLS12",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FailIfCECPQ2Offered: true,
+ },
+ },
+ flags: []string{
+ "-max-version", strconv.Itoa(VersionTLS12),
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ },
+ })
+
// CECPQ2 should not crash a TLS < 1.3 client if the server mistakenly
// selects it.
testCases = append(testCases, testCase{
@@ -10951,6 +10967,24 @@ func addCurveTests() {
expectedError: ":WRONG_CURVE:",
})
+ // CECPQ2b should not crash a TLS < 1.3 client if the server mistakenly
+ // selects it.
+ testCases = append(testCases, testCase{
+ name: "CECPQ2bNotAcceptedByTLS12Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendCurve: CurveCECPQ2b,
+ },
+ },
+ flags: []string{
+ "-max-version", strconv.Itoa(VersionTLS12),
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
+
// CECPQ2 should not be offered by default as a client.
testCases = append(testCases, testCase{
name: "CECPQ2NotEnabledByDefaultInClients",
@@ -10962,6 +10996,17 @@ func addCurveTests() {
},
})
+ // CECPQ2b should not be offered by default as a client.
+ testCases = append(testCases, testCase{
+ name: "CECPQ2bNotEnabledByDefaultInClients",
+ config: Config{
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ FailIfCECPQ2Offered: true,
+ },
+ },
+ })
+
// If CECPQ2 is offered, both X25519 and CECPQ2 should have a key-share.
testCases = append(testCases, testCase{
name: "NotJustCECPQ2KeyShare",
@@ -10994,6 +11039,38 @@ func addCurveTests() {
},
})
+ // If CECPQ2b is offered, both X25519 and CECPQ2b should have a key-share.
+ testCases = append(testCases, testCase{
+ name: "NotJustCECPQ2bKeyShare",
+ config: Config{
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectedKeyShares: []CurveID{CurveCECPQ2b, CurveX25519},
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ "-expect-curve-id", strconv.Itoa(int(CurveCECPQ2b)),
+ },
+ })
+
+ // ... but only if CECPQ2b is listed first.
+ testCases = append(testCases, testCase{
+ name: "CECPQ2bKeyShareNotIncludedSecond",
+ config: Config{
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectedKeyShares: []CurveID{CurveX25519},
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+ },
+ })
+
// If CECPQ2 is the only configured curve, the key share is sent.
testCases = append(testCases, testCase{
name: "JustConfiguringCECPQ2Works",
@@ -11009,6 +11086,21 @@ func addCurveTests() {
},
})
+ // If CECPQ2b is the only configured curve, the key share is sent.
+ testCases = append(testCases, testCase{
+ name: "JustConfiguringCECPQ2bWorks",
+ config: Config{
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectedKeyShares: []CurveID{CurveCECPQ2b},
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-expect-curve-id", strconv.Itoa(int(CurveCECPQ2b)),
+ },
+ })
+
// As a server, CECPQ2 is not yet supported by default.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -11023,6 +11115,21 @@ func addCurveTests() {
"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
},
})
+
+ // As a server, CECPQ2b is not yet supported by default.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "CECPQ2bNotEnabledByDefaultForAServer",
+ config: Config{
+ MinVersion: VersionTLS13,
+ CurvePreferences: []CurveID{CurveCECPQ2b, CurveX25519},
+ DefaultCurves: []CurveID{CurveCECPQ2b},
+ },
+ flags: []string{
+ "-server-preference",
+ "-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+ },
+ })
}
func addTLS13RecordTests() {
@@ -13950,6 +14057,21 @@ func addTLS13CipherPreferenceTests() {
},
})
+ // CECPQ2b prefers 256-bit ciphers but will use AES-128 if there's nothing else.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2b-AES128Only",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ },
+ })
+
// When a 256-bit cipher is offered, even if not in first place, it should be
// picked.
testCases = append(testCases, testCase{
@@ -13984,6 +14106,40 @@ func addTLS13CipherPreferenceTests() {
expectedCipher: TLS_AES_128_GCM_SHA256,
})
+ // When a 256-bit cipher is offered, even if not in first place, it should be
+ // picked.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2b-AES256Preferred",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ },
+ expectedCipher: TLS_AES_256_GCM_SHA384,
+ })
+ // ... but when CECPQ2b isn't being used, the client's preference controls.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2b-AES128PreferredOtherwise",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ },
+ expectedCipher: TLS_AES_128_GCM_SHA256,
+ })
+
// Test that CECPQ2 continues to honor AES vs ChaCha20 logic.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -14019,6 +14175,42 @@ func addTLS13CipherPreferenceTests() {
"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
},
})
+
+ // Test that CECPQ2b continues to honor AES vs ChaCha20 logic.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2b-AES128-ChaCha20-AES256",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_CHACHA20_POLY1305_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+ "-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2b-AES128-AES256-ChaCha20",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ TLS_CHACHA20_POLY1305_SHA256,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2b)),
+ "-expect-cipher-aes", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
+ "-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+ },
+ })
}
func addPeekTests() {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index a4a37e6b7..b4e8d37bd 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -1613,6 +1613,9 @@ bssl::UniquePtr<SSL> TestConfig::NewSSL(
case SSL_CURVE_CECPQ2:
nids.push_back(NID_CECPQ2);
break;
+ case SSL_CURVE_CECPQ2b:
+ nids.push_back(NID_CECPQ2b);
+ break;
}
if (!SSL_set1_curves(ssl.get(), &nids[0], nids.size())) {
return nullptr;
@@ -1621,8 +1624,8 @@ bssl::UniquePtr<SSL> TestConfig::NewSSL(
}
if (enable_all_curves) {
static const int kAllCurves[] = {
- NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
- NID_secp521r1, NID_X25519, NID_CECPQ2,
+ NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1,
+ NID_X25519, NID_CECPQ2, NID_CECPQ2b,
};
if (!SSL_set1_curves(ssl.get(), kAllCurves,
OPENSSL_ARRAY_SIZE(kAllCurves))) {
diff --git a/third_party/sike/LICENSE b/third_party/sike/LICENSE
new file mode 100644
index 000000000..5cf7c8db6
--- /dev/null
+++ b/third_party/sike/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
diff --git a/third_party/sike/asm/fp-armv8.pl b/third_party/sike/asm/fp-armv8.pl
new file mode 100644
index 000000000..ce19d8090
--- /dev/null
+++ b/third_party/sike/asm/fp-armv8.pl
@@ -0,0 +1,915 @@
+#! /usr/bin/env perl
+#
+# April 2019
+#
+# Abstract: field arithmetic in aarch64 assembly for SIDH/p434
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../../crypto/perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+*STDOUT=*OUT;
+
+$PREFIX="sike";
+
+$code.=<<___;
+.section .rodata
+
+# p434 x 2
+.Lp434x2:
+ .quad 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF
+ .quad 0xFB82ECF5C5FFFFFF, 0xF78CB8F062B15D47
+ .quad 0xD9F8BFAD038A40AC, 0x0004683E4E2EE688
+
+# p434 + 1
+.Lp434p1:
+ .quad 0xFDC1767AE3000000, 0x7BC65C783158AEA3
+ .quad 0x6CFC5FD681C52056, 0x0002341F27177344
+
+.text
+___
+
+# Computes C0-C2 = A0 * (B0-B1)
+# Inputs remain intact
+sub mul64x128 {
+ my ($A0,$B0,$B1,$C0,$C1,$C2,$T0,$T1)=@_;
+ my $body=<<___;
+ mul $T1, $A0, $B0
+ umulh $B0, $A0, $B0
+ adds $C0, $C0, $C2