-
Notifications
You must be signed in to change notification settings - Fork 56
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
Fix input wiping on decryption failure #337
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -707,8 +707,8 @@ private int engineDecryptFinal( | |
workingInputArray, | ||
workingInputOffset, | ||
workingInputLength, | ||
output, | ||
outputOffset, | ||
workingInputArray, // Output | ||
workingInputOffset, // Output Offset | ||
tagLength, | ||
key, | ||
iv, | ||
|
@@ -730,8 +730,8 @@ private int engineDecryptFinal( | |
workingInputArray, | ||
workingInputOffset, | ||
workingInputLength, | ||
output, | ||
outputOffset, | ||
workingInputArray, // Output | ||
workingInputOffset, // Output Offset | ||
tagLength, | ||
key, | ||
iv, | ||
|
@@ -747,12 +747,9 @@ private int engineDecryptFinal( | |
} | ||
} | ||
// Decryption completed successfully. | ||
// Copy from working buffer into actual output | ||
System.arraycopy(workingInputArray, workingInputOffset, output, outputOffset, outLen); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can avoid this copy in case the output buffer doesn't overlap input. Still in the case of failure the output buffer would potentially be modified, but it's output buffer after all. |
||
return outLen; | ||
} catch (AEADBadTagException e) { | ||
final int maxFillSize = output.length - outputOffset; | ||
Arrays.fill( | ||
output, outputOffset, Math.min(maxFillSize, engineGetOutputSize(inputLen)), (byte) 0); | ||
throw e; | ||
} finally { | ||
stateReset(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 cases where the output buffer is distinct from the input, like here the copying back can be avoided by directly using the output buffer.
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 am willing to change this, however:
So, if left to me, I would leave this as written, but I am willing to change it. (Or, to read it another way. I have one approval and one request for changes. Mind reaching consensus?)
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 spoke offline and I'm more hesitant now. My interpretation of the contract is that if the caller gives us an output buffer and a length we have no obligation to preserve the contents of that buffer even if the tag check fails. If we can preserve it for free, awesome, but if it adds O(n) memory I/O to all AES-GCM operations I'm less inclined. Even if we add the risky logic for overlap detection, what we'll find is that the perfect overlap case is the common case and it won't buy us much.
The remaining point of clarity for us is to look at how other libraries handle this case to determine if this is considered a bug as that's still a bit subjective to me. AFAICT, OpenSSL/AWS-LC will scribble over the output buffer and simply return an error code if the tag fails. I'd be hesitant to add new semantics at the ACCP layer which don't line up with the native library.
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.
My concern is us overwriting the input buffer (which happens to be the same).
I have personally seen decryption logic which attempts repeated in-place decryption using multiple keys. Unfortunately, I no longer have access to said code. However, wiping the in-place buffer on failure would absolutely break that code.
More interesting than how OpenSSL/AWS-LC behave is how other JCA providers behave as that's what ACCP is replacing.