-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PKCS7-internal BIO_f_cipher #1836
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1836 +/- ##
==========================================
+ Coverage 78.49% 78.54% +0.04%
==========================================
Files 585 587 +2
Lines 99630 99893 +263
Branches 14254 14289 +35
==========================================
+ Hits 78206 78459 +253
- Misses 20789 20797 +8
- Partials 635 637 +2 ☔ View full report in Codecov by Sentry. |
f4627f0
to
4f69b78
Compare
6e5c58d
to
94c275e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some preliminary comments, haven't gone through everything yet.
6fe97e9
to
ea1f09d
Compare
ea1f09d
to
f88b1b4
Compare
9e3f145
to
43af6b7
Compare
974506f
to
b575aed
Compare
b575aed
to
62f3691
Compare
4ee0704
to
1a2d1dc
Compare
if (bytes_read == 0 && BIO_eof(next)) { | ||
// EVP_CipherFinal_ex may write up to one block to our buffer. If that | ||
// happens, continue the loop to process the decrypted block as normal. | ||
ctx->ok = EVP_CipherFinal_ex(ctx->cipher, ctx->buf, &ctx->buf_len); | ||
// We have more bytes to output, go back to top of loop. | ||
if (ctx->buf_len > 0) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent making a second call to EVP_CipherFinal_ex
on a subsequent iteration, should it be setting ctx->done = 1
prior to the continue
? Then, ctx->done
would need to be checked prior to the call to BIO_read(next, ctx->buf, to_read)
.
} else if (bytes_read <= 0) { | ||
BIO_copy_next_retry(b); | ||
return bytes_output; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bytes_read <= 0
condition here seems to imply an error in next
for which we should also set: ctx->ok = 0
?
Our documentation says BIO_read
:
returns the number of bytes read, zero on EOF, or a negative number on error
if (bytes_written <= 0) { | ||
goto out; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also set ctx->ok = 0
when bytes_written < 0
?
int remaining = inl; | ||
const int max_crypt_size = | ||
(int)sizeof(ctx->buf) - EVP_CIPHER_CTX_block_size(ctx->cipher) + 1; | ||
while (remaining > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should return an error if this is called when ctx->done == 1
(or ctx->ok == 0
).
remaining -= to_encrypt; | ||
} | ||
int bytes_written = BIO_write(next, &ctx->buf[ctx->buf_off], ctx->buf_len); | ||
if (bytes_written <= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For BIO_write
, I think we should distinguish bytes_written == 0
(no bytes written) from bytes_written < 0
(an error). On an error, we might need to set ctx->ok = 0
and ctx->done = 1
?
GUARD_PTR(b); | ||
GUARD_PTR(next); | ||
GUARD_PTR(ctx); | ||
while (ctx->buf_len > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this loop instead be conditioned on ctx->buf_len > 0 || ctx->done == 0
. It seems possible/likely that ctx->buf_len == 0
holds when BIO_flush
is called, in which case this loop never executes (EVP_CipherFinal_ex
never gets called), and it returns 1 as-if it succeeded.
while (ctx->buf_len > 0 || ctx->done == 0) {
if (ctx->buf_len > 0) {
...
} else if(ctx->done == 0) {
...
}
}
int bytes_written = BIO_write(next, &ctx->buf[ctx->buf_off], ctx->buf_len); | ||
if (bytes_written <= 0) { | ||
BIO_copy_next_retry(b); | ||
return bytes_written; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, I think the return value should be 0 b/c the buffer was not fully flushed. (If we return a positive value, the caller may assume EVP_CipherFinal_ex
was called and all data was written.
Issues:
Addresses CryptoAlg-2494
Description of changes:
This change introduces a new filter BIO,
BIO_f_cipher
for use in PR 1816.The cipher BIO sits in front of a backing BIO, encrypting incoming writes before writing to the backing BIO and decrypting data read from the backing BIO. This implementation is almost an exact copy of OpenSSL's with some functionality removed. We try to change as little of the underlying logic as possible, but rename variables and add comments for clarity.
Call-outs:
Testing:
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.