Skip to content

Native crypto improvements: reject malformed cryptograms and failures with an exception instead of crashing the app - #210

Merged
binsky08 merged 14 commits into
masterfrom
fix/native-input-validation
Oct 31, 2026
Merged

binsky08 merged 14 commits into
masterfrom
fix/native-input-validation

Conversation

@binsky08

@binsky08 binsky08 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #209 (fix/native-memory-leaks), which needs to be merged first.

Malformed cryptograms or failures in the native SJCL code crashed the app. They now throw the usual RuntimeException("Error decrypting"/"Error encrypting"). The format and JNI interface are unchanged.

  • reject missing/invalid JSON values, key sizes =/ 256, tag sizes =/ 64, too short ciphertexts/IVs and invalid base64
  • check the results of PBKDF2, RAND_bytes, malloc/calloc, base64 encoding and the cipher context instead of continuing or crashing
  • catch C++ exceptions (e.g. std::bad_alloc) at the JNI boundary
  • a failed decryption returns null instead of a C string
  • new SjclInputValidationTest and a leak test for rejected decryptions

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI (claude opus 5.5)

…shing

The native decryption dereferenced the JSON values without checking them, so a cryptogram without e.g. "iv", or with a value of the wrong type, crashed the whole app with a segmentation fault instead of throwing an exception.
Numbers out of the int range were cast to int, which is undefined behavior.

Missing values, values of the wrong type and numbers that are no positive int now let the decryption fail with the usual exception. The JSON tree is also released if the cryptogram isn't a JSON object.

Signed-off-by: binsky <timo@binsky.org>
…it; the result of the PBKDF2 key derivation is now checked as well, so a failed derivation can no longer encrypt or decrypt with an uninitialized key

Signed-off-by: binsky <timo@binsky.org>
Signed-off-by: binsky <timo@binsky.org>
note: the required IV length depends on the cryptogram length (13 bytes below 64 KB, 12 below 16 MB, 11 above), so decryptccm checks it where the nonce length is calculated
Signed-off-by: binsky <timo@binsky.org>
the decoding no longer exits the app when it runs out of memory, but returns NULL; it no longer leaks the Datagram struct when returning NULL

Signed-off-by: binsky <timo@binsky.org>
the native base64 encoding exited the whole app when it ran out of memory, and returned a result without data for oversized input, which its callers didn't check. It now returns NULL in both cases, and the encryption and decryption fail with the usual exception instead

Signed-off-by: binsky <timo@binsky.org>
basically just by removing two useless lines :D

Signed-off-by: binsky <timo@binsky.org>
…to align with the encryptStringCpp behaviour)

the input validation tests now check the exact exception and message, which are the same before and after this change

Signed-off-by: binsky <timo@binsky.org>
…xt can't be created

Signed-off-by: binsky <timo@binsky.org>
…n exception ( instead of encrypting with an IV and salt of leftover memory)

Signed-off-by: binsky <timo@binsky.org>
…e app

rare possibility, but technically possible

Signed-off-by: binsky <timo@binsky.org>
…va exception

Signed-off-by: binsky <timo@binsky.org>
@binsky08 binsky08 changed the title Fix/improve native input validation Native crypto improvements: reject malformed cryptograms and failures with an exception instead of crashing the app Oct 30, 2026
@binsky08
binsky08 marked this pull request as ready for review October 31, 2026 20:52
Signed-off-by: binsky <timo@binsky.org>
@binsky08
binsky08 merged commit b9c56a6 into master Oct 31, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant