tttls1.3 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +4 -2
- data/.rubocop.yml +16 -11
- data/.ruby-version +1 -1
- data/Gemfile +5 -4
- data/README.md +4 -4
- data/Rakefile +3 -3
- data/example/helper.rb +14 -5
- data/example/https_client_using_0rtt.rb +1 -1
- data/example/https_client_using_ech.rb +1 -1
- data/example/https_client_using_hrr_and_ech.rb +1 -1
- data/example/https_client_using_hrr_and_ticket.rb +1 -1
- data/example/https_client_using_status_request.rb +1 -1
- data/example/https_client_using_ticket.rb +1 -1
- data/example/https_client_using_ticket_and_ech.rb +3 -3
- data/example/https_server.rb +1 -1
- data/interop/client_spec.rb +57 -31
- data/interop/server_spec.rb +74 -46
- data/interop/spec_helper.rb +2 -2
- data/lib/tttls1.3/cipher_suites.rb +21 -16
- data/lib/tttls1.3/client.rb +89 -78
- data/lib/tttls1.3/connection.rb +6 -15
- data/lib/tttls1.3/cryptograph/aead.rb +26 -21
- data/lib/tttls1.3/ech.rb +13 -17
- data/lib/tttls1.3/endpoint.rb +4 -25
- data/lib/tttls1.3/key_schedule.rb +2 -2
- data/lib/tttls1.3/logging.rb +1 -1
- data/lib/tttls1.3/message/alert.rb +3 -4
- data/lib/tttls1.3/message/application_data.rb +1 -1
- data/lib/tttls1.3/message/certificate.rb +4 -7
- data/lib/tttls1.3/message/certificate_verify.rb +3 -5
- data/lib/tttls1.3/message/client_hello.rb +17 -15
- data/lib/tttls1.3/message/compressed_certificate.rb +3 -9
- data/lib/tttls1.3/message/encrypted_extensions.rb +1 -2
- data/lib/tttls1.3/message/extension/alpn.rb +2 -7
- data/lib/tttls1.3/message/extension/compress_certificate.rb +1 -2
- data/lib/tttls1.3/message/extension/cookie.rb +1 -2
- data/lib/tttls1.3/message/extension/early_data_indication.rb +1 -2
- data/lib/tttls1.3/message/extension/ech.rb +9 -19
- data/lib/tttls1.3/message/extension/ech_outer_extensions.rb +1 -3
- data/lib/tttls1.3/message/extension/key_share.rb +20 -49
- data/lib/tttls1.3/message/extension/pre_shared_key.rb +8 -20
- data/lib/tttls1.3/message/extension/psk_key_exchange_modes.rb +1 -2
- data/lib/tttls1.3/message/extension/record_size_limit.rb +1 -2
- data/lib/tttls1.3/message/extension/server_name.rb +1 -3
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +1 -2
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +1 -1
- data/lib/tttls1.3/message/extension/status_request.rb +4 -12
- data/lib/tttls1.3/message/extension/supported_groups.rb +1 -4
- data/lib/tttls1.3/message/extension/supported_versions.rb +2 -8
- data/lib/tttls1.3/message/extension/unknown_extension.rb +2 -4
- data/lib/tttls1.3/message/extensions.rb +1 -9
- data/lib/tttls1.3/message/finished.rb +1 -2
- data/lib/tttls1.3/message/new_session_ticket.rb +6 -12
- data/lib/tttls1.3/message/record.rb +10 -25
- data/lib/tttls1.3/message/server_hello.rb +10 -21
- data/lib/tttls1.3/named_group.rb +13 -9
- data/lib/tttls1.3/server.rb +39 -35
- data/lib/tttls1.3/shared_secret.rb +118 -0
- data/lib/tttls1.3/utils.rb +0 -15
- data/lib/tttls1.3/version.rb +1 -1
- data/lib/tttls1.3.rb +1 -1
- data/spec/certificate_verify_spec.rb +1 -1
- data/spec/client_hello_spec.rb +22 -3
- data/spec/client_spec.rb +13 -13
- data/spec/endpoint_spec.rb +11 -11
- data/spec/key_schedule_spec.rb +4 -4
- data/spec/new_session_ticket_spec.rb +4 -4
- data/spec/pre_shared_key_spec.rb +8 -8
- data/spec/record_spec.rb +1 -1
- data/spec/server_hello_spec.rb +5 -5
- data/spec/server_spec.rb +8 -8
- data/tttls1.3.gemspec +2 -2
- metadata +7 -10
- data/example/https_client_using_grease_psk.rb +0 -58
data/lib/tttls1.3/client.rb
CHANGED
@@ -37,6 +37,7 @@ module TTTLS13
|
|
37
37
|
private_constant :DEFAULT_CH_SIGNATURE_ALGORITHMS
|
38
38
|
|
39
39
|
DEFAULT_CH_NAMED_GROUP_LIST = [
|
40
|
+
NamedGroup::X25519,
|
40
41
|
NamedGroup::SECP256R1,
|
41
42
|
NamedGroup::SECP384R1,
|
42
43
|
NamedGroup::SECP521R1
|
@@ -89,8 +90,8 @@ module TTTLS13
|
|
89
90
|
class Client
|
90
91
|
include Logging
|
91
92
|
|
92
|
-
HpkeSymmetricCipherSuit
|
93
|
-
ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
93
|
+
HpkeSymmetricCipherSuit \
|
94
|
+
= ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
94
95
|
|
95
96
|
attr_reader :transcript
|
96
97
|
|
@@ -110,7 +111,6 @@ module TTTLS13
|
|
110
111
|
raise Error::ConfigError unless valid_settings?
|
111
112
|
end
|
112
113
|
|
113
|
-
# NOTE:
|
114
114
|
# START <----+
|
115
115
|
# Send ClientHello | | Recv HelloRetryRequest
|
116
116
|
# [K_send = early data] | |
|
@@ -153,7 +153,6 @@ module TTTLS13
|
|
153
153
|
@transcript = Transcript.new
|
154
154
|
key_schedule = nil # TTTLS13::KeySchedule
|
155
155
|
psk = nil
|
156
|
-
priv_keys = {} # Hash of NamedGroup => OpenSSL::PKey::$Object
|
157
156
|
if use_psk?
|
158
157
|
psk = gen_psk_from_nst(
|
159
158
|
@settings[:resumption_secret],
|
@@ -161,13 +160,14 @@ module TTTLS13
|
|
161
160
|
CipherSuite.digest(@settings[:psk_cipher_suite])
|
162
161
|
)
|
163
162
|
key_schedule = KeySchedule.new(
|
164
|
-
psk
|
163
|
+
psk:,
|
165
164
|
shared_secret: nil,
|
166
165
|
cipher_suite: @settings[:psk_cipher_suite],
|
167
166
|
transcript: @transcript
|
168
167
|
)
|
169
168
|
end
|
170
169
|
|
170
|
+
shared_secret = nil # TTTLS13::SharedSecret
|
171
171
|
hs_wcipher = nil # TTTLS13::Cryptograph::$Object
|
172
172
|
hs_rcipher = nil # TTTLS13::Cryptograph::$Object
|
173
173
|
e_wcipher = nil # TTTLS13::Cryptograph::$Object
|
@@ -190,7 +190,7 @@ module TTTLS13
|
|
190
190
|
when ClientState::START
|
191
191
|
logger.debug('ClientState::START')
|
192
192
|
|
193
|
-
extensions,
|
193
|
+
extensions, shared_secret = gen_ch_extensions
|
194
194
|
binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
|
195
195
|
ch, inner, ech_state = send_client_hello(extensions, binder_key)
|
196
196
|
ch_outer = ch
|
@@ -281,8 +281,7 @@ module TTTLS13
|
|
281
281
|
unless ngl.include?(group) && !kse.map(&:group).include?(group)
|
282
282
|
|
283
283
|
# send new client_hello
|
284
|
-
extensions,
|
285
|
-
priv_keys = pk.merge(priv_keys)
|
284
|
+
extensions, shared_secret = gen_newch_extensions(ch1, hrr)
|
286
285
|
binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
|
287
286
|
ch, inner = send_new_client_hello(
|
288
287
|
ch1,
|
@@ -313,21 +312,20 @@ module TTTLS13
|
|
313
312
|
@connection.terminate(:illegal_parameter) unless ch_ks.include?(sh_ks)
|
314
313
|
|
315
314
|
kse = sh.extensions[Message::ExtensionType::KEY_SHARE]
|
316
|
-
.key_share_entry
|
315
|
+
.key_share_entry
|
316
|
+
.first
|
317
317
|
ke = kse.key_exchange
|
318
318
|
@named_group = kse.group
|
319
|
-
priv_key = priv_keys[@named_group]
|
320
|
-
shared_secret = Endpoint.gen_shared_secret(ke, priv_key, @named_group)
|
321
319
|
@cipher_suite = sh.cipher_suite
|
322
320
|
key_schedule = KeySchedule.new(
|
323
|
-
psk
|
324
|
-
shared_secret: shared_secret,
|
321
|
+
psk:,
|
322
|
+
shared_secret: shared_secret.build(@named_group, ke),
|
325
323
|
cipher_suite: @cipher_suite,
|
326
324
|
transcript: @transcript
|
327
325
|
)
|
328
326
|
|
329
327
|
# rejected ECH
|
330
|
-
#
|
328
|
+
# It can compute (hrr_)accept_ech until client selects the
|
331
329
|
# cipher_suite.
|
332
330
|
if !sh.hrr? && use_ech?
|
333
331
|
if !@transcript.include?(HRR) && !key_schedule.accept_ech?
|
@@ -457,7 +455,7 @@ module TTTLS13
|
|
457
455
|
@connection.terminate(:decrypt_error) \
|
458
456
|
unless Endpoint.verified_finished?(
|
459
457
|
finished: sf,
|
460
|
-
digest
|
458
|
+
digest:,
|
461
459
|
finished_key: key_schedule.server_finished_key,
|
462
460
|
hash: @transcript.hash(digest, CV)
|
463
461
|
)
|
@@ -468,7 +466,7 @@ module TTTLS13
|
|
468
466
|
end
|
469
467
|
# TODO: Send Certificate [+ CertificateVerify]
|
470
468
|
signature = Endpoint.sign_finished(
|
471
|
-
digest
|
469
|
+
digest:,
|
472
470
|
finished_key: key_schedule.client_finished_key,
|
473
471
|
hash: @transcript.hash(digest, EOED)
|
474
472
|
)
|
@@ -691,25 +689,49 @@ module TTTLS13
|
|
691
689
|
# rubocop: enable Metrics/CyclomaticComplexity
|
692
690
|
# rubocop: enable Metrics/PerceivedComplexity
|
693
691
|
|
692
|
+
# @return [Boolean]
|
693
|
+
def use_alpn?
|
694
|
+
!@settings[:alpn].nil? && !@settings[:alpn].empty?
|
695
|
+
end
|
696
|
+
|
697
|
+
# @return [Boolean]
|
698
|
+
def use_signature_algorithms_cert?
|
699
|
+
!@settings[:signature_algorithms_cert].nil? &&
|
700
|
+
!@settings[:signature_algorithms_cert].empty?
|
701
|
+
end
|
702
|
+
|
703
|
+
# @return [Boolean]
|
704
|
+
def use_compress_certificate?
|
705
|
+
!@settings[:compress_certificate_algorithms].nil? &&
|
706
|
+
!@settings[:compress_certificate_algorithms].empty?
|
707
|
+
end
|
708
|
+
|
709
|
+
# @return [Boolean]
|
710
|
+
def use_record_size_limit?
|
711
|
+
!@settings[:record_size_limit].nil?
|
712
|
+
end
|
713
|
+
|
694
714
|
# @return [Boolean]
|
695
715
|
def use_psk?
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
716
|
+
%i[
|
717
|
+
ticket
|
718
|
+
resumption_secret
|
719
|
+
psk_cipher_suite
|
720
|
+
ticket_nonce
|
721
|
+
ticket_age_add
|
722
|
+
ticket_timestamp
|
723
|
+
].all? { |sy| !@settings[sy].nil? }
|
702
724
|
end
|
703
725
|
|
704
726
|
# @return [Boolean]
|
705
727
|
def use_early_data?
|
706
|
-
|
728
|
+
!@early_data.nil? && !@early_data.empty?
|
707
729
|
end
|
708
730
|
|
709
731
|
# @return [Boolean]
|
710
732
|
def use_ech?
|
711
|
-
|
712
|
-
|
733
|
+
ehcs = @settings[:ech_hpke_cipher_suites]
|
734
|
+
!ehcs.nil? && !ehcs.empty?
|
713
735
|
end
|
714
736
|
|
715
737
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
@@ -719,7 +741,7 @@ module TTTLS13
|
|
719
741
|
type: Message::ContentType::APPLICATION_DATA,
|
720
742
|
legacy_record_version: Message::ProtocolVersion::TLS_1_2,
|
721
743
|
messages: [ap],
|
722
|
-
cipher:
|
744
|
+
cipher:
|
723
745
|
)
|
724
746
|
@connection.send_record(ap_record)
|
725
747
|
end
|
@@ -736,18 +758,16 @@ module TTTLS13
|
|
736
758
|
end
|
737
759
|
|
738
760
|
# @return [TTTLS13::Message::Extensions]
|
739
|
-
# @return [
|
761
|
+
# @return [TTTLS13::SharedSecret]
|
740
762
|
# rubocop: disable Metrics/AbcSize
|
741
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
742
763
|
# rubocop: disable Metrics/MethodLength
|
743
|
-
# rubocop: disable Metrics/PerceivedComplexity
|
744
764
|
def gen_ch_extensions
|
745
765
|
exs = Message::Extensions.new
|
746
766
|
# server_name
|
747
767
|
exs << Message::Extension::ServerName.new(@hostname)
|
748
768
|
|
749
769
|
# record_size_limit
|
750
|
-
|
770
|
+
if use_record_size_limit?
|
751
771
|
exs << Message::Extension::RecordSizeLimit.new(
|
752
772
|
@settings[:record_size_limit]
|
753
773
|
)
|
@@ -764,8 +784,7 @@ module TTTLS13
|
|
764
784
|
)
|
765
785
|
|
766
786
|
# signature_algorithms_cert
|
767
|
-
if
|
768
|
-
!@settings[:signature_algorithms_cert].empty?
|
787
|
+
if use_signature_algorithms_cert?
|
769
788
|
exs << Message::Extension::SignatureAlgorithmsCert.new(
|
770
789
|
@settings[:signature_algorithms_cert]
|
771
790
|
)
|
@@ -777,7 +796,7 @@ module TTTLS13
|
|
777
796
|
|
778
797
|
# key_share
|
779
798
|
ksg = @settings[:key_share_groups] || groups
|
780
|
-
key_share,
|
799
|
+
key_share, shared_secret \
|
781
800
|
= Message::Extension::KeyShare.gen_ch_key_share(ksg)
|
782
801
|
exs << key_share
|
783
802
|
|
@@ -785,28 +804,24 @@ module TTTLS13
|
|
785
804
|
exs << Message::Extension::EarlyDataIndication.new if use_early_data?
|
786
805
|
|
787
806
|
# alpn
|
788
|
-
exs << Message::Extension::Alpn.new(@settings[:alpn]
|
789
|
-
if !@settings[:alpn].nil? && !@settings[:alpn].empty?
|
807
|
+
exs << Message::Extension::Alpn.new(@settings[:alpn]) if use_alpn?
|
790
808
|
|
791
809
|
# status_request
|
792
810
|
exs << Message::Extension::OCSPStatusRequest.new \
|
793
811
|
if @settings[:check_certificate_status]
|
794
812
|
|
795
813
|
# compress_certificate
|
796
|
-
if
|
797
|
-
!@settings[:compress_certificate_algorithms].empty?
|
814
|
+
if use_compress_certificate?
|
798
815
|
exs << Message::Extension::CompressCertificate.new(
|
799
816
|
@settings[:compress_certificate_algorithms]
|
800
817
|
)
|
801
818
|
end
|
802
819
|
|
803
|
-
[exs,
|
820
|
+
[exs, shared_secret]
|
804
821
|
end
|
822
|
+
|
805
823
|
# rubocop: enable Metrics/AbcSize
|
806
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
807
824
|
# rubocop: enable Metrics/MethodLength
|
808
|
-
# rubocop: enable Metrics/PerceivedComplexity
|
809
|
-
|
810
825
|
# @param extensions [TTTLS13::Message::Extensions]
|
811
826
|
# @param binder_key [String, nil]
|
812
827
|
#
|
@@ -817,7 +832,7 @@ module TTTLS13
|
|
817
832
|
def send_client_hello(extensions, binder_key = nil)
|
818
833
|
ch = Message::ClientHello.new(
|
819
834
|
cipher_suites: CipherSuites.new(@settings[:cipher_suites]),
|
820
|
-
extensions:
|
835
|
+
extensions:
|
821
836
|
)
|
822
837
|
|
823
838
|
# encrypted_client_hello
|
@@ -850,8 +865,8 @@ module TTTLS13
|
|
850
865
|
# at the end, sign PSK binder
|
851
866
|
if use_psk?
|
852
867
|
sign_psk_binder(
|
853
|
-
ch
|
854
|
-
binder_key:
|
868
|
+
ch:,
|
869
|
+
binder_key:
|
855
870
|
)
|
856
871
|
|
857
872
|
if use_ech?
|
@@ -875,7 +890,7 @@ module TTTLS13
|
|
875
890
|
# @param binder_key [String]
|
876
891
|
#
|
877
892
|
# @return [String]
|
878
|
-
def sign_psk_binder(ch1: nil, hrr: nil
|
893
|
+
def sign_psk_binder(ch:, binder_key:, ch1: nil, hrr: nil)
|
879
894
|
# pre_shared_key
|
880
895
|
#
|
881
896
|
# binder is computed as an HMAC over a transcript hash containing a
|
@@ -899,11 +914,11 @@ module TTTLS13
|
|
899
914
|
ch.extensions[Message::ExtensionType::PRE_SHARED_KEY] = psk
|
900
915
|
|
901
916
|
psk.offered_psks.binders[0] = Endpoint.sign_psk_binder(
|
902
|
-
ch1
|
903
|
-
hrr
|
904
|
-
ch
|
905
|
-
binder_key
|
906
|
-
digest:
|
917
|
+
ch1:,
|
918
|
+
hrr:,
|
919
|
+
ch:,
|
920
|
+
binder_key:,
|
921
|
+
digest:
|
907
922
|
)
|
908
923
|
end
|
909
924
|
|
@@ -914,11 +929,8 @@ module TTTLS13
|
|
914
929
|
# @param binder_key [String]
|
915
930
|
#
|
916
931
|
# @return [String]
|
917
|
-
def sign_grease_psk_binder(ch1: nil,
|
918
|
-
hrr: nil
|
919
|
-
ch_outer:,
|
920
|
-
inner_psk:,
|
921
|
-
binder_key:)
|
932
|
+
def sign_grease_psk_binder(ch_outer:, inner_psk:, binder_key:, ch1: nil,
|
933
|
+
hrr: nil)
|
922
934
|
digest = CipherSuite.digest(@settings[:psk_cipher_suite])
|
923
935
|
hash_len = OpenSSL::Digest.new(digest).digest_length
|
924
936
|
placeholder_binders = [hash_len.zeros]
|
@@ -940,7 +952,7 @@ module TTTLS13
|
|
940
952
|
msg_type: Message::HandshakeType::CLIENT_HELLO,
|
941
953
|
offered_psks: Message::Extension::OfferedPsks.new(
|
942
954
|
identities: [Message::Extension::PskIdentity.new(
|
943
|
-
identity
|
955
|
+
identity:,
|
944
956
|
obfuscated_ticket_age: ota
|
945
957
|
)],
|
946
958
|
binders: placeholder_binders
|
@@ -949,11 +961,11 @@ module TTTLS13
|
|
949
961
|
ch_outer.extensions[Message::ExtensionType::PRE_SHARED_KEY] = psk
|
950
962
|
|
951
963
|
psk.offered_psks.binders[0] = Endpoint.sign_psk_binder(
|
952
|
-
ch1
|
953
|
-
hrr
|
964
|
+
ch1:,
|
965
|
+
hrr:,
|
954
966
|
ch: ch_outer,
|
955
|
-
binder_key
|
956
|
-
digest:
|
967
|
+
binder_key:,
|
968
|
+
digest:
|
957
969
|
)
|
958
970
|
end
|
959
971
|
|
@@ -978,14 +990,14 @@ module TTTLS13
|
|
978
990
|
# @param hrr [TTTLS13::Message::ServerHello]
|
979
991
|
#
|
980
992
|
# @return [TTTLS13::Message::Extensions]
|
981
|
-
# @return [
|
993
|
+
# @return [TTTLS13::SharedSecret]
|
982
994
|
def gen_newch_extensions(ch1, hrr)
|
983
995
|
exs = Message::Extensions.new
|
984
996
|
# key_share
|
985
997
|
if hrr.extensions.include?(Message::ExtensionType::KEY_SHARE)
|
986
998
|
group = hrr.extensions[Message::ExtensionType::KEY_SHARE]
|
987
999
|
.key_share_entry.first.group
|
988
|
-
key_share,
|
1000
|
+
key_share, shared_secret \
|
989
1001
|
= Message::Extension::KeyShare.gen_ch_key_share([group])
|
990
1002
|
exs << key_share
|
991
1003
|
end
|
@@ -1005,10 +1017,9 @@ module TTTLS13
|
|
1005
1017
|
new_exs = ch1.extensions.merge(exs)
|
1006
1018
|
new_exs.delete(Message::ExtensionType::EARLY_DATA)
|
1007
1019
|
|
1008
|
-
[new_exs,
|
1020
|
+
[new_exs, shared_secret]
|
1009
1021
|
end
|
1010
1022
|
|
1011
|
-
# NOTE:
|
1012
1023
|
# https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2
|
1013
1024
|
#
|
1014
1025
|
# @param ch1 [TTTLS13::Message::ClientHello]
|
@@ -1032,7 +1043,7 @@ module TTTLS13
|
|
1032
1043
|
legacy_session_id: ch1.legacy_session_id,
|
1033
1044
|
cipher_suites: ch1.cipher_suites,
|
1034
1045
|
legacy_compression_methods: ch1.legacy_compression_methods,
|
1035
|
-
extensions:
|
1046
|
+
extensions:
|
1036
1047
|
)
|
1037
1048
|
|
1038
1049
|
# encrypted_client_hello
|
@@ -1054,7 +1065,7 @@ module TTTLS13
|
|
1054
1065
|
# Updating the "pre_shared_key" extension if present by recomputing
|
1055
1066
|
# the "obfuscated_ticket_age" and binder values.
|
1056
1067
|
if ch1.extensions.include?(Message::ExtensionType::PRE_SHARED_KEY)
|
1057
|
-
sign_psk_binder(ch1
|
1068
|
+
sign_psk_binder(ch1:, hrr:, ch:, binder_key:)
|
1058
1069
|
|
1059
1070
|
if use_ech?
|
1060
1071
|
# it MUST also copy the "psk_key_exchange_modes" from the
|
@@ -1065,11 +1076,11 @@ module TTTLS13
|
|
1065
1076
|
ch.extensions[Message::ExtensionType::EARLY_DATA] \
|
1066
1077
|
= inner.extensions[Message::ExtensionType::EARLY_DATA]
|
1067
1078
|
sign_grease_psk_binder(
|
1068
|
-
ch1
|
1069
|
-
hrr
|
1079
|
+
ch1:,
|
1080
|
+
hrr:,
|
1070
1081
|
ch_outer: ch,
|
1071
1082
|
inner_psk: inner.extensions[Message::ExtensionType::PRE_SHARED_KEY],
|
1072
|
-
binder_key:
|
1083
|
+
binder_key:
|
1073
1084
|
)
|
1074
1085
|
end
|
1075
1086
|
end
|
@@ -1105,7 +1116,7 @@ module TTTLS13
|
|
1105
1116
|
# @return [String]
|
1106
1117
|
def recv_encrypted_extensions(cipher)
|
1107
1118
|
ee, orig_msg \
|
1108
|
-
= @connection.recv_message(receivable_ccs: true, cipher:
|
1119
|
+
= @connection.recv_message(receivable_ccs: true, cipher:)
|
1109
1120
|
@connection.terminate(:unexpected_message) \
|
1110
1121
|
unless ee.is_a?(Message::EncryptedExtensions)
|
1111
1122
|
|
@@ -1120,7 +1131,7 @@ module TTTLS13
|
|
1120
1131
|
# @return [String]
|
1121
1132
|
def recv_certificate(cipher)
|
1122
1133
|
ct, orig_msg \
|
1123
|
-
= @connection.recv_message(receivable_ccs: true, cipher:
|
1134
|
+
= @connection.recv_message(receivable_ccs: true, cipher:)
|
1124
1135
|
@connection.terminate(:unexpected_message) \
|
1125
1136
|
unless ct.is_a?(Message::Certificate)
|
1126
1137
|
|
@@ -1135,7 +1146,7 @@ module TTTLS13
|
|
1135
1146
|
# @return [String]
|
1136
1147
|
def recv_certificate_verify(cipher)
|
1137
1148
|
cv, orig_msg \
|
1138
|
-
= @connection.recv_message(receivable_ccs: true, cipher:
|
1149
|
+
= @connection.recv_message(receivable_ccs: true, cipher:)
|
1139
1150
|
@connection.terminate(:unexpected_message) \
|
1140
1151
|
unless cv.is_a?(Message::CertificateVerify)
|
1141
1152
|
|
@@ -1150,7 +1161,7 @@ module TTTLS13
|
|
1150
1161
|
# @return [String]
|
1151
1162
|
def recv_finished(cipher)
|
1152
1163
|
sf, orig_msg \
|
1153
|
-
= @connection.recv_message(receivable_ccs: true, cipher:
|
1164
|
+
= @connection.recv_message(receivable_ccs: true, cipher:)
|
1154
1165
|
@connection.terminate(:unexpected_message) \
|
1155
1166
|
unless sf.is_a?(Message::Finished)
|
1156
1167
|
|
@@ -1205,7 +1216,7 @@ module TTTLS13
|
|
1205
1216
|
if @settings[:check_certificate_status]
|
1206
1217
|
ee = ct.certificate_list.first
|
1207
1218
|
ocsp_response = ee.extensions[Message::ExtensionType::STATUS_REQUEST]
|
1208
|
-
|
1219
|
+
&.ocsp_response
|
1209
1220
|
cert = ee.cert_data
|
1210
1221
|
chain = ct.certificate_list[1..]&.map(&:cert_data)
|
1211
1222
|
return :bad_certificate_status_response \
|
@@ -1226,11 +1237,11 @@ module TTTLS13
|
|
1226
1237
|
signature = cv.signature
|
1227
1238
|
|
1228
1239
|
Endpoint.verified_certificate_verify?(
|
1229
|
-
public_key
|
1230
|
-
signature_scheme
|
1231
|
-
signature
|
1240
|
+
public_key:,
|
1241
|
+
signature_scheme:,
|
1242
|
+
signature:,
|
1232
1243
|
context: 'TLS 1.3, server CertificateVerify',
|
1233
|
-
hash:
|
1244
|
+
hash:
|
1234
1245
|
)
|
1235
1246
|
end
|
1236
1247
|
|
data/lib/tttls1.3/connection.rb
CHANGED
@@ -9,10 +9,7 @@ module TTTLS13
|
|
9
9
|
class Connection
|
10
10
|
include Logging
|
11
11
|
|
12
|
-
attr_accessor :state
|
13
|
-
attr_accessor :ap_wcipher
|
14
|
-
attr_accessor :ap_rcipher
|
15
|
-
attr_accessor :alert_wcipher
|
12
|
+
attr_accessor :state, :ap_wcipher, :ap_rcipher, :alert_wcipher
|
16
13
|
|
17
14
|
# @param socket [Socket]
|
18
15
|
# @param side [:client or :server]
|
@@ -34,8 +31,6 @@ module TTTLS13
|
|
34
31
|
# @raise [TTTLS13::Error::ConfigError]
|
35
32
|
#
|
36
33
|
# @return [String]
|
37
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
38
|
-
# rubocop: disable Metrics/PerceivedComplexity
|
39
34
|
def read(nst_process)
|
40
35
|
# secure channel has not established yet
|
41
36
|
raise Error::ConfigError \
|
@@ -58,8 +53,6 @@ module TTTLS13
|
|
58
53
|
|
59
54
|
message.fragment
|
60
55
|
end
|
61
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
62
|
-
# rubocop: enable Metrics/PerceivedComplexity
|
63
56
|
|
64
57
|
# @return [Boolean]
|
65
58
|
def eof?
|
@@ -91,9 +84,9 @@ module TTTLS13
|
|
91
84
|
# @param cipher [TTTLS13::Cryptograph::Aead, Passer]
|
92
85
|
def send_handshakes(type, messages, cipher)
|
93
86
|
record = Message::Record.new(
|
94
|
-
type
|
95
|
-
messages
|
96
|
-
cipher:
|
87
|
+
type:,
|
88
|
+
messages:,
|
89
|
+
cipher:
|
97
90
|
)
|
98
91
|
send_record(record)
|
99
92
|
end
|
@@ -115,7 +108,7 @@ module TTTLS13
|
|
115
108
|
type: Message::ContentType::APPLICATION_DATA,
|
116
109
|
legacy_record_version: Message::ProtocolVersion::TLS_1_2,
|
117
110
|
messages: [message],
|
118
|
-
cipher:
|
111
|
+
cipher:
|
119
112
|
)
|
120
113
|
send_record(ap_record)
|
121
114
|
end
|
@@ -129,7 +122,7 @@ module TTTLS13
|
|
129
122
|
type = Message::ContentType::APPLICATION_DATA \
|
130
123
|
if @alert_wcipher.is_a?(Cryptograph::Aead)
|
131
124
|
alert_record = Message::Record.new(
|
132
|
-
type
|
125
|
+
type:,
|
133
126
|
legacy_record_version: Message::ProtocolVersion::TLS_1_2,
|
134
127
|
messages: [message],
|
135
128
|
cipher: @alert_wcipher
|
@@ -150,7 +143,6 @@ module TTTLS13
|
|
150
143
|
#
|
151
144
|
# @return [TTTLS13::Message::$Object]
|
152
145
|
# @return [String]
|
153
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
154
146
|
def recv_message(receivable_ccs:, cipher:)
|
155
147
|
return @message_queue.shift unless @message_queue.empty?
|
156
148
|
|
@@ -184,7 +176,6 @@ module TTTLS13
|
|
184
176
|
|
185
177
|
[message, orig_msg]
|
186
178
|
end
|
187
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
188
179
|
|
189
180
|
# @param cipher [TTTLS13::Cryptograph::Aead, Passer]
|
190
181
|
#
|
@@ -17,16 +17,15 @@ module TTTLS13
|
|
17
17
|
@cipher_suite = cipher_suite
|
18
18
|
case cipher_suite
|
19
19
|
when CipherSuite::TLS_AES_128_GCM_SHA256
|
20
|
-
@cipher = OpenSSL::Cipher
|
20
|
+
@cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
21
21
|
when CipherSuite::TLS_AES_256_GCM_SHA384
|
22
|
-
@cipher = OpenSSL::Cipher
|
22
|
+
@cipher = OpenSSL::Cipher.new('aes-256-gcm')
|
23
23
|
when CipherSuite::TLS_CHACHA20_POLY1305_SHA256
|
24
24
|
@cipher = OpenSSL::Cipher.new('chacha20-poly1305')
|
25
|
+
when CipherSuite::TLS_AES_128_CCM_SHA256,
|
26
|
+
CipherSuite::TLS_AES_128_CCM_8_SHA256
|
27
|
+
@cipher = OpenSSL::Cipher.new('aes-128-ccm')
|
25
28
|
else
|
26
|
-
# Note:
|
27
|
-
# not supported
|
28
|
-
# CipherSuite::TLS_AES_128_CCM_SHA256
|
29
|
-
# CipherSuite::TLS_AES_128_CCM_8_SHA256
|
30
29
|
raise Error::ErrorAlerts, :internal_error
|
31
30
|
end
|
32
31
|
@write_key = write_key
|
@@ -36,7 +35,6 @@ module TTTLS13
|
|
36
35
|
@auth_tag_len = CipherSuite.auth_tag_len(@cipher_suite)
|
37
36
|
end
|
38
37
|
|
39
|
-
# NOTE:
|
40
38
|
# AEAD-Encrypt(write_key, nonce, additional_data, plaintext)
|
41
39
|
#
|
42
40
|
# @param content [String]
|
@@ -45,15 +43,16 @@ module TTTLS13
|
|
45
43
|
# @return [String]
|
46
44
|
def encrypt(content, type)
|
47
45
|
cipher = reset_cipher
|
48
|
-
|
49
|
-
cipher.
|
50
|
-
|
46
|
+
plain_text = content + type + @length_of_padding.zeros
|
47
|
+
cipher.ccm_data_len = plain_text.length \
|
48
|
+
if CipherSuite.ccm?(@cipher_suite)
|
49
|
+
cipher.auth_data = additional_data(plain_text.length)
|
50
|
+
cipher_text = cipher.update(plain_text) + cipher.final
|
51
51
|
@sequence_number.succ
|
52
52
|
|
53
|
-
|
53
|
+
cipher_text + cipher.auth_tag
|
54
54
|
end
|
55
55
|
|
56
|
-
# NOTE:
|
57
56
|
# AEAD-Decrypt(peer_write_key, nonce,
|
58
57
|
# additional_data, AEADEncrypted)
|
59
58
|
#
|
@@ -66,19 +65,21 @@ module TTTLS13
|
|
66
65
|
# @return [TTTLS13::Message::ContentType]
|
67
66
|
def decrypt(encrypted_record, auth_data)
|
68
67
|
decipher = reset_decipher
|
69
|
-
|
68
|
+
cipher_text = encrypted_record[0...-@auth_tag_len]
|
69
|
+
decipher.ccm_data_len = cipher_text.length \
|
70
|
+
if CipherSuite.ccm?(@cipher_suite)
|
71
|
+
auth_tag = encrypted_record[-@auth_tag_len..]
|
70
72
|
decipher.auth_tag = auth_tag
|
71
73
|
decipher.auth_data = auth_data # record header of TLSCiphertext
|
72
|
-
|
74
|
+
plain_text = decipher.update(cipher_text)
|
73
75
|
decipher.final
|
74
|
-
zeros_len = scan_zeros(
|
76
|
+
zeros_len = scan_zeros(plain_text)
|
75
77
|
postfix_len = 1 + zeros_len # type || zeros
|
76
78
|
@sequence_number.succ
|
77
79
|
|
78
|
-
[
|
80
|
+
[plain_text[0...-postfix_len], plain_text[-postfix_len]]
|
79
81
|
end
|
80
82
|
|
81
|
-
# NOTE:
|
82
83
|
# struct {
|
83
84
|
# opaque content[TLSPlaintext.length];
|
84
85
|
# ContentType type;
|
@@ -107,9 +108,11 @@ module TTTLS13
|
|
107
108
|
def reset_cipher
|
108
109
|
cipher = @cipher.encrypt
|
109
110
|
cipher.reset
|
111
|
+
cipher.auth_tag_len = @auth_tag_len \
|
112
|
+
if CipherSuite.ccm?(@cipher_suite)
|
113
|
+
cipher.iv_len = CipherSuite.iv_len(@cipher_suite)
|
110
114
|
cipher.key = @write_key
|
111
|
-
|
112
|
-
cipher.iv = @sequence_number.xor(@write_iv, iv_len)
|
115
|
+
cipher.iv = @sequence_number.xor(@write_iv, cipher.iv_len)
|
113
116
|
|
114
117
|
cipher
|
115
118
|
end
|
@@ -118,9 +121,11 @@ module TTTLS13
|
|
118
121
|
def reset_decipher
|
119
122
|
decipher = @cipher.decrypt
|
120
123
|
decipher.reset
|
124
|
+
decipher.auth_tag_len = @auth_tag_len \
|
125
|
+
if CipherSuite.ccm?(@cipher_suite)
|
126
|
+
decipher.iv_len = CipherSuite.iv_len(@cipher_suite)
|
121
127
|
decipher.key = @write_key
|
122
|
-
|
123
|
-
decipher.iv = @sequence_number.xor(@write_iv, iv_len)
|
128
|
+
decipher.iv = @sequence_number.xor(@write_iv, decipher.iv_len)
|
124
129
|
|
125
130
|
decipher
|
126
131
|
end
|