Skip to content

Commit c8befe7

Browse files
committed
FEAT: added support for SHA384 cipher modes in the TLS protocol
1 parent c17863b commit c8befe7

File tree

1 file changed

+53
-39
lines changed

1 file changed

+53
-39
lines changed

src/mezz/prot-tls.reb

+53-39
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ REBOL [
3535
0.8.0 "Oldes" "Using new `crypt` port introduced in Rebol 3.8.0"
3636
0.9.0 "Oldes" "Added (limited) support for a `server` role"
3737
0.9.1 "Oldes" "Improved initialization to be able reuse already opened TCP port"
38-
0.9.2 "Oldes" "Added support for GCM crypt mode"
38+
0.9.2 "Oldes" "Added support for GCM and SHA384 crypt modes"
3939
]
4040
todo: {
4141
* cached sessions
@@ -82,7 +82,9 @@ TLS-context: context [
8282
tls-port:
8383
encrypt-port:
8484
decrypt-port:
85-
sha-port: ;used for progressive checksum computations
85+
sha256-port: ;used for progressive checksum computations
86+
sha384-port: ;used for progressive checksum computations with SHA384 cipher modes
87+
sha-port: ;one of the above
8688
md5-port: ;used for progressive checksum computations (in TLSv1.0)
8789

8890
version: none ; TLS version (currently just TLSv1.2)
@@ -447,14 +449,14 @@ suported-cipher-suites: decode-cipher-suites suported-cipher-suites-binary: rejo
447449
#{CCA9} ;TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
448450
#{CCA8} ;TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
449451
#{C02F} ;TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
450-
;#{C030} ;TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
452+
#{C030} ;TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
451453
#{C02B} ;TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
452-
;#{C02C} ;TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
454+
#{C02C} ;TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
453455
#{009C} ;TLS-RSA-WITH-AES-128-GCM-SHA256
454456

455457
;- CBC mode is considered to be weak, but still used!
456-
;#{C028} ;TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ;need test with https://snappygoat.com/b/8d6492a33fee8f8f0ea289203fdf080608d9d61d
457-
;#{C024} ;TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
458+
#{C028} ;TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
459+
#{C024} ;TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
458460
#{C027} ;TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
459461
#{C023} ;TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
460462
#{C014} ;TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
@@ -554,6 +556,17 @@ TLS-init-cipher-suite: func [
554556
ctx/crypt-method: to word! cipher
555557
ctx/is-aead?: to logic! find [AES-128-GCM AES-256-GCM CHACHA20-POLY1305] ctx/crypt-method
556558

559+
either ctx/hash-method = 'SHA384 [
560+
; upgrade hashing from default sha256 to sha384
561+
close ctx/sha256-port
562+
ctx/sha256-port: none
563+
ctx/sha-port: ctx/sha384-port
564+
][
565+
; the sha384 hasning is not needed anymore
566+
close ctx/sha384-port
567+
ctx/sha384-port: none
568+
]
569+
557570
log-more [
558571
"Key:^[[1m" ctx/key-method
559572
"^[[22mcrypt:^[[1m" ctx/crypt-method
@@ -609,9 +622,12 @@ TLS-update-messages-hash: function [
609622
][
610623
log-more ["Update-messages-hash bytes:" len "hash:" all [ctx/sha-port ctx/sha-port/spec/method]]
611624
if none? ctx/sha-port [
612-
ctx/sha-port: open either ctx/mac-size = 48 [checksum:sha384][checksum:sha256]
625+
ctx/sha256-port: open checksum:sha256
626+
ctx/sha384-port: open checksum:sha384
627+
ctx/sha-port: ctx/sha256-port
613628
log-more ["Initialized SHA method:" ctx/sha-port/spec/method]
614629
]
630+
unless ctx/hash-method [ write/part ctx/sha384-port msg len ]
615631
write/part ctx/sha-port msg len
616632
log-debug ["messages-hash:" read ctx/sha-port]
617633
]
@@ -1046,7 +1062,7 @@ finished: function [
10461062
unencrypted: rejoin [
10471063
#{14} ; protocol message type (20=Finished)
10481064
#{00000C} ; protocol message length (12 bytes)
1049-
prf either ctx/server? ["server finished"]["client finished"] seed ctx/master-secret 12
1065+
prf :ctx/sha-port/spec/method either ctx/server? ["server finished"]["client finished"] seed ctx/master-secret 12
10501066
]
10511067

10521068
TLS-update-messages-hash ctx unencrypted length? unencrypted
@@ -1077,15 +1093,13 @@ encrypt-handshake-msg: function [
10771093
decrypt-msg: function [
10781094
ctx [object!]
10791095
data [binary!]
1080-
/type
1081-
msg-type [integer!] "application data is default"
1096+
type [integer!]
10821097
][
10831098
;print "CRYPTED message!"
1084-
msg-type: any [msg-type 23]
10851099
with ctx [
10861100
binary/write bin compose [
10871101
UI64 :seq-read
1088-
UI8 :msg-type
1102+
UI8 :type
10891103
UI16 :version
10901104
]
10911105
either is-aead? [
@@ -1095,13 +1109,13 @@ decrypt-msg: function [
10951109
;? remote-IV
10961110
modify decrypt-port 'iv remote-IV
10971111

1098-
log-more ["Remote-IV: ^[[32m" remote-IV]
1112+
log-more ["Remote-IV:^[[32m" remote-IV]
10991113
]
11001114

11011115
binary/write bin reduce ['UI16 (length? data) - 16]
11021116
write decrypt-port bin/buffer ; AAD chunk
11031117

1104-
log-more ["AAD: ^[[32m" bin/buffer]
1118+
log-more ["AAD: ^[[32m" bin/buffer]
11051119

11061120
mac: take/last/part data 16 ; expected mac
11071121
data: read write decrypt-port data
@@ -1246,6 +1260,7 @@ encrypt-data: function [
12461260

12471261
prf: function [
12481262
{(P)suedo-(R)andom (F)unction, generates arbitrarily long binaries}
1263+
hash [word!]
12491264
label [string! binary!]
12501265
seed [binary!]
12511266
secret [binary!]
@@ -1257,7 +1272,7 @@ prf: function [
12571272
; PRF(secret, label, seed) = P_<hash>(secret, label + seed)
12581273
;
12591274

1260-
log-more ["PRF" mold label "len:" output-length]
1275+
log-more ["PRF" hash mold label "len:" output-length]
12611276
seed: join to binary! label seed
12621277

12631278
; TLS 1.2 includes the pseudorandom function as part of its cipher
@@ -1269,8 +1284,8 @@ prf: function [
12691284
p-sha256: make binary! output-length
12701285
a: seed ; A(0)
12711286
while [output-length >= length? p-sha256][
1272-
a: checksum/with a 'sha256 secret
1273-
append p-sha256 checksum/with append copy :a :seed 'sha256 secret
1287+
a: checksum/with a :hash :secret
1288+
append p-sha256 checksum/with append copy :a :seed :hash :secret
12741289
;?? p-sha256
12751290
]
12761291
;trim the result to required output length
@@ -1281,7 +1296,7 @@ prf: function [
12811296

12821297
TLS-key-expansion: func[
12831298
ctx [object!]
1284-
/local rnd1 rnd2 key-expansion
1299+
/local rnd1 rnd2 key-expansion sha
12851300
][
12861301
with ctx [
12871302
;-- make all secure data
@@ -1292,8 +1307,9 @@ TLS-key-expansion: func[
12921307
rnd2: append copy ctx/remote-random ctx/local-random
12931308
rnd1: append copy ctx/local-random ctx/remote-random
12941309
]
1295-
master-secret: prf "master secret" rnd1 pre-secret 48
1296-
key-expansion: prf "key expansion" rnd2 master-secret (mac-size + crypt-size + iv-size) * 2
1310+
sha: ctx/sha-port/spec/method
1311+
master-secret: prf :sha "master secret" rnd1 pre-secret 48
1312+
key-expansion: prf :sha "key expansion" rnd2 master-secret (mac-size + crypt-size + iv-size) * 2
12971313

12981314
either server? [
12991315
unless is-aead? [
@@ -1373,13 +1389,7 @@ TLS-init-context: func [
13731389
TLS-init-connection: function [ctx [object!]][
13741390
binary/init ctx/out none ;reset output buffer
13751391
client-hello ctx
1376-
;ctx/out/buffer: head ctx/out/buffer
1377-
;?? ctx/out/buffer
1378-
log-debug ["Writing bytes:" length? ctx/out/buffer]
1379-
ctx/out/buffer: head ctx/out/buffer
1380-
write ctx/tcp-port ctx/out/buffer
1381-
binary/init ctx/out none ;reset output buffer
1382-
ctx/reading?: true
1392+
do-TCP-write ctx
13831393

13841394
false
13851395
]
@@ -1455,7 +1465,7 @@ TLS-read-data: function [
14551465
;?? data
14561466
;?? ctx/cipher-spec-set
14571467
if ctx/cipher-spec-set > 1 [
1458-
if data: decrypt-msg ctx data [
1468+
if data: decrypt-msg ctx data :type [
14591469
append ctx/port-data data
14601470
;@@ TODO: the parent scheme (HTTPS) should be notified here,
14611471
;@@ that there are already some decrypted data available!
@@ -1469,7 +1479,7 @@ TLS-read-data: function [
14691479
;? ctx/cipher-spec-set
14701480
either ctx/cipher-spec-set > 1 [
14711481
ctx/seq-read: 0
1472-
data: decrypt-msg/type ctx data 22
1482+
data: decrypt-msg ctx data :type
14731483
;ctx/protocol: 'APPLICATION
14741484
;change-state ctx 'APPLICATION
14751485
ctx/reading?: ctx/server?
@@ -1499,7 +1509,7 @@ TLS-read-data: function [
14991509
binary/read inp [data: BYTES :len]
15001510
if ctx/cipher-spec-set > 1 [
15011511
log-debug ["Decrypting ALERT message:" mold data]
1502-
data: decrypt-msg ctx data
1512+
data: decrypt-msg ctx data :type
15031513
unless data [
15041514
log-error "Failed to decode ALERT message!"
15051515
;@@ TODO: inspect how it's possible that decrypt failes
@@ -1885,7 +1895,7 @@ TLS-parse-handshake-message: function [
18851895
FINISHED [
18861896
binary/read msg [verify-data: BYTES] ;rest of data
18871897
seed: read ctx/sha-port
1888-
result: prf either ctx/server? ["client finished"]["server finished"] seed ctx/master-secret 12
1898+
result: prf :ctx/sha-port/spec/method either ctx/server? ["client finished"]["server finished"] seed ctx/master-secret 12
18891899
;? verify-data ? result
18901900
if result <> verify-data [
18911901
return *Alert/Handshake_failure
@@ -2080,8 +2090,7 @@ TLS-client-awake: function [event [event!]][
20802090
client-key-exchange ctx
20812091
change-cipher-spec ctx
20822092
finished ctx
2083-
write ctx/tcp-port ctx/out/buffer
2084-
ctx/reading?: true
2093+
do-TCP-write ctx
20852094
return false
20862095
]
20872096
FINISHED [
@@ -2250,16 +2259,21 @@ do-TLS-write: func[port [port!] value [any-type!] /local ctx][
22502259
binary/init ctx/out none ;resets the output buffer
22512260
application-data ctx :value
22522261

2253-
log-debug ["Writing bytes:" length? ctx/out/buffer]
2254-
;ctx/out/buffer: head ctx/out/buffer
2255-
write ctx/tcp-port ctx/out/buffer
2256-
2257-
ctx/reading?: true
2258-
binary/init ctx/out none ;resets the output buffer
2262+
do-TCP-write ctx
22592263
return port
22602264
]
22612265
]
22622266

2267+
do-TCP-write: func[ctx][
2268+
log-debug ["Writing bytes:" length? ctx/out/buffer]
2269+
;?? ctx/out/buffer
2270+
;ctx/out/buffer: head ctx/out/buffer
2271+
write ctx/tcp-port ctx/out/buffer
2272+
2273+
ctx/reading?: true
2274+
binary/init ctx/out none ;resets the output buffer
2275+
]
2276+
22632277
sys/make-scheme [
22642278
name: 'tls
22652279
title: "TLS protocol v1.2"

0 commit comments

Comments
 (0)