Skip to content

Commit 0ca83b3

Browse files
committed
FIX: Using init-vector instead of just iv in crypt port specification; take on crypt port is now like read update; updated crypt port initialization to be compatible with the changes of decode-url function.
1 parent ce13fcf commit 0ca83b3

File tree

3 files changed

+139
-40
lines changed

3 files changed

+139
-40
lines changed

src/core/p-crypt.c

+44-26
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,44 @@ static void free_crypt_cipher_context(CRYPT_CTX *ctx);
713713
return CRYPT_OK;
714714
}
715715

716+
/***********************************************************************
717+
**
718+
*/ static REBINT Crypt_Update(CRYPT_CTX* ctx)
719+
/*
720+
***********************************************************************/
721+
{
722+
REBSER* bin;
723+
REBCNT len, ofs, blk;
724+
REBINT err;
725+
size_t olen = 0;
726+
727+
bin = ctx->buffer;
728+
729+
//puts("update");
730+
#ifdef MBEDTLS_CHACHAPOLY_C
731+
if (ctx->cipher_type == SYM_CHACHA20_POLY1305) {
732+
Extend_Series(bin, 16);
733+
err = mbedtls_chachapoly_finish((mbedtls_chachapoly_context*)ctx->cipher_ctx, BIN_TAIL(bin));
734+
SERIES_TAIL(bin) += 16;
735+
ctx->state = CRYPT_PORT_NEEDS_AAD;
736+
return R_ARG1;
737+
}
738+
#endif
739+
if (ctx->unprocessed_len > 0) {
740+
ofs = 0;
741+
blk = ctx->cipher_block_size;
742+
Extend_Series(bin, blk);
743+
744+
if (ctx->unprocessed_len > blk) abort();
745+
len = blk - ctx->unprocessed_len;
746+
// pad with zeros...
747+
CLEAR(ctx->unprocessed_data + ctx->unprocessed_len, len);
748+
749+
Crypt_Crypt(ctx, ctx->unprocessed_data, blk, &olen);
750+
ctx->unprocessed_len = 0;
751+
}
752+
return R_ARG1;
753+
}
716754

717755
/***********************************************************************
718756
**
@@ -763,7 +801,7 @@ static void free_crypt_cipher_context(CRYPT_CTX *ctx);
763801
return CRYPT_OK;
764802
}
765803
// test if input have enough data to do the block crypt
766-
if (len > blk) {
804+
if (len >= blk) {
767805
// we have enough data to call crypt
768806
Crypt_Crypt(ctx, input, len, &olen);
769807
if (olen > len) return CRYPT_ERROR_BAD_PROCESSED_SIZE;
@@ -837,8 +875,11 @@ static void free_crypt_cipher_context(CRYPT_CTX *ctx);
837875
}
838876
Crypt_Write(ctx, VAL_BIN_AT(arg1), VAL_LEN(arg1));
839877
break;
840-
case A_READ:
841878
case A_TAKE:
879+
// `take` is same like `read`, but also calls `update` to process also
880+
// yet not processed data from the unprocessed buffer
881+
Crypt_Update(ctx);
882+
case A_READ:
842883
//puts("read");
843884
len = BIN_LEN(bin);
844885
if (len > 0) {
@@ -852,30 +893,7 @@ static void free_crypt_cipher_context(CRYPT_CTX *ctx);
852893
else return R_NONE;
853894
break;
854895
case A_UPDATE:
855-
//puts("update");
856-
#ifdef MBEDTLS_CHACHAPOLY_C
857-
if (ctx->cipher_type == SYM_CHACHA20_POLY1305) {
858-
Extend_Series(bin, 16);
859-
err = mbedtls_chachapoly_finish((mbedtls_chachapoly_context*)ctx->cipher_ctx, BIN_TAIL(bin));
860-
SERIES_TAIL(bin) += 16;
861-
ctx->state = CRYPT_PORT_NEEDS_AAD;
862-
return R_ARG1;
863-
}
864-
#endif
865-
if (ctx->unprocessed_len > 0) {
866-
ofs = 0;
867-
blk = ctx->cipher_block_size;
868-
Extend_Series(bin, blk);
869-
870-
if (ctx->unprocessed_len > blk) abort();
871-
len = blk - ctx->unprocessed_len;
872-
// pad with zeros...
873-
CLEAR(ctx->unprocessed_data + ctx->unprocessed_len, len);
874-
875-
Crypt_Crypt(ctx, ctx->unprocessed_data, blk, &olen);
876-
ctx->unprocessed_len = 0;
877-
}
878-
break;
896+
return Crypt_Update(ctx);
879897

880898
case A_CLOSE:
881899
if (ctx) {

src/mezz/sys-ports.reb

+23-7
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,8 @@ init-schemes: func [
418418
spec: port/spec
419419
method: any [
420420
select spec 'method
421-
select spec 'target ; if scheme was opened using url type
421+
select spec 'target ; if scheme was opened using url type (checksum:sha1)
422+
select spec 'host ; when used as: checksum://sha1
422423
'md5 ; default method
423424
]
424425
if any [
@@ -427,7 +428,7 @@ init-schemes: func [
427428
][
428429
cause-error 'access 'invalid-spec method
429430
]
430-
; make port/spec to be only with midi related keys
431+
; make port/spec to be only with checksum related keys
431432
set port/spec: copy system/standard/port-spec-checksum spec
432433
;protect/words port/spec ; protect spec object keys of modification
433434
]
@@ -444,20 +445,35 @@ init-schemes: func [
444445
spec: port/spec
445446
algorithm: any [
446447
select spec 'algorithm
447-
select spec 'target ; if scheme was opened using url type
448-
'AES-256-CBC ; default cipher
448+
select spec 'target ; if scheme was opened using url type: crypt:chacha20
449+
select spec 'host ; or when used as: crypt://chacha20
450+
]
451+
direction: any [
452+
select spec 'fragment ; from: crypt://chacha20#decrypt
453+
select spec 'direction
449454
]
450455
if any [
451-
error? try [spec/algorithm: to word! algorithm] ; in case it was not
456+
error? try [spec/algorithm: to word! :algorithm] ; in case it was not
452457
not find system/catalog/ciphers spec/algorithm
453458
][
454-
cause-error 'access 'invalid-spec algorithm
455-
]
459+
cause-error 'access 'invalid-spec :algorithm
460+
]
461+
if any [
462+
error? try [spec/direction: to word! :direction] ; in case it was not
463+
not find [encrypt decrypt] spec/direction
464+
][
465+
cause-error 'access 'invalid-spec :direction
466+
]
467+
; make port/spec to be only with crypt related keys
456468
set port/spec: copy system/standard/port-spec-crypt spec
469+
if block? port/spec/ref [
470+
port/spec/ref: as url! ajoin ["crypt://" :algorithm #"#" :direction]
471+
]
457472
;protect/words port/spec ; protect spec object keys of modification
458473
]
459474
]
460475

476+
461477
make-scheme [
462478
title: "Clipboard"
463479
name: 'clipboard

src/tests/units/crypt-port-test.r3

+72-7
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ Rebol [
1313
test-crypt: func[port key iv plain cipher][
1414
modify port 'direction 'encrypt
1515
modify port 'key key
16-
modify port 'iv iv
16+
modify port 'init-vector iv
1717
--assert cipher = try [read write port plain]
1818
modify port 'direction 'decrypt
19+
modify port 'init-vector iv ; must reset IV, because it was changed internally!
1920
--assert plain = try [read write port cipher]
2021
]
2122
tests: [
@@ -109,6 +110,69 @@ foreach [cipher tests] tests [
109110
close port
110111
]
111112
]
113+
--test-- "AES-128-CBC with chunked input"
114+
port: open make port! [
115+
scheme: 'crypt
116+
algorithm: 'AES-128-CBC
117+
key: #{2B7E151628AED2A6ABF7158809CF4F3C}
118+
]
119+
iv: #{000102030405060708090A0B0C0D0E0F}
120+
modify port 'init-vector :iv
121+
; writing data in 2 chunks
122+
write port #{6BC1BEE22E409F96}
123+
write port #{E93D7E117393172A}
124+
; no need to `update`, because the input has full block size now
125+
--assert #{7649ABAC8119B246CEE98E9B12E9197D} = read port
126+
127+
modify port 'init-vector :iv
128+
write port #{6BC1BEE22E409F96}
129+
130+
--assert none? read port ; because the input was not long enough
131+
crypted: read update port ; the input is padded by `update` call
132+
--assert crypted = #{6F8BB83BE51C9A7DE442745E517D4377}
133+
--assert none? read update port ; there are no more data
134+
--assert none? take port
135+
136+
modify port 'direction 'decrypt
137+
modify port 'init-vector :iv
138+
; result contains padded data!
139+
--assert #{6BC1BEE22E409F960000000000000000} = read write port :crypted
140+
141+
--test-- "AES-128-CBC with chunked input which needs padding"
142+
c-port: open make port! [
143+
scheme: 'crypt
144+
algorithm: 'AES-128-CBC
145+
key: #{2B7E151628AED2A6ABF7158809CF4F3C}
146+
init-vector: #{000102030405060708090A0B0C0D0E0F}
147+
]
148+
;d-port: open make port! [
149+
; scheme: 'crypt
150+
; direction: 'decrypt
151+
; algorithm: 'AES-128-CBC
152+
; key: #{2B7E151628AED2A6ABF7158809CF4F3C}
153+
; init-vector: #{000102030405060708090A0B0C0D0E0F}
154+
;]
155+
;- above code can be also done using:
156+
d-port: open crypt://AES-128-CBC#decrypt
157+
modify d-port 'key #{2B7E151628AED2A6ABF7158809CF4F3C}
158+
modify d-port 'init-vector #{000102030405060708090A0B0C0D0E0F}
159+
160+
write c-port #{6BC1BEE22E409F96}
161+
write c-port #{E93D7E117393172ADEADBEEF}
162+
; notice that there is just a partial output, because the input is longer than a block!
163+
crypted: read c-port
164+
--assert crypted = #{7649ABAC8119B246CEE98E9B12E9197D}
165+
write d-port :crypted
166+
crypted: take c-port ; same as `read update c-port` -> take forces the padding
167+
--assert crypted = #{00CA0B3A31A8BD78A2815653B0C4C9DB}
168+
write d-port :crypted
169+
plain: take d-port
170+
; the output is padded!
171+
--assert plain = #{6BC1BEE22E409F96E93D7E117393172ADEADBEEF000000000000000000000000}
172+
close c-port
173+
close d-port
174+
175+
112176
===end-group===
113177

114178

@@ -118,7 +182,7 @@ foreach [cipher tests] tests [
118182
monte-carlo-test-crypt: function[port key iv plain cipher][
119183
modify port 'direction 'encrypt
120184
modify port 'key key
121-
modify port 'iv iv
185+
modify port 'init-vector iv
122186
x: plain
123187
loop 10000 [ x: read write port x ]
124188
--assert cipher = x
@@ -172,7 +236,7 @@ foreach [cipher tests] monte-carlo-ecb-tests [
172236
monte-carlo-cbc-test-crypt: function[port key iv plain cipher][
173237
modify port 'direction 'encrypt
174238
modify port 'key key
175-
modify port 'iv iv
239+
modify port 'init-vector iv
176240
pt: plain
177241
ct-1: iv
178242
loop 10000 [
@@ -283,10 +347,11 @@ foreach [cipher tests] monte-carlo-cbc-tests [
283347
foreach [cipher tests] tests [
284348
unless find system/catalog/ciphers cipher [continue]
285349
foreach [k i p c] tests [
286-
port: open [scheme: 'crypt algorithm: cipher key: k iv: i]
350+
port: open [scheme: 'crypt algorithm: cipher key: k init-vector: i]
287351
--test-- join "Crypt port: " cipher
288352
--assert c = read write port p
289353
modify port 'direction 'decrypt
354+
modify port 'init-vector i ; must reset IV, because it was changed internally!
290355
--assert p = read write port c
291356
close port
292357
]
@@ -330,7 +395,7 @@ if find system/catalog/ciphers 'CHACHA20 [
330395
foreach [key nonce plain cipher] tests [
331396
--test-- join "Test Vector #" n
332397
modify port 'key key
333-
modify port 'iv nonce
398+
modify port 'init-vector nonce
334399
--assert cipher = read write port plain
335400
++ n
336401
]
@@ -339,7 +404,7 @@ if find system/catalog/ciphers 'CHACHA20 [
339404

340405
===start-group=== "The ChaCha20 encryption from RFC7539"
341406
;https://datatracker.ietf.org/doc/rfc7539/
342-
port: open crypt://CHACHA20
407+
port: open crypt:CHACHA20
343408

344409
tests: [
345410
#{0000000000000000000000000000000000000000000000000000000000000000}
@@ -371,7 +436,7 @@ if find system/catalog/ciphers 'CHACHA20 [
371436
foreach [key nonce plain cipher] tests [
372437
--test-- join "Test Vector #" n
373438
modify port 'key key
374-
modify port 'iv nonce
439+
modify port 'init-vector nonce
375440
--assert cipher = read write port plain
376441
++ n
377442
]

0 commit comments

Comments
 (0)