Unify native output buffer sizing for OCK and OpenSSL in SymmetricCipher

Aperta
#2,092 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
20/100
Tipo di issue
Refactoring
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
c, java
Ambito
cryptography

Direzione di ricerca

Start with SymmetricCipher.java (getOutputSizeForOCK, renamed to getNativeOutputSize in PR #2009) and the checkRange checks in the OpenSSL SymmetricCipher.c (len + blockSize for update/decryptFinal, len + 2*blockSize - 1 for encryptFinal). Trace the OCKC native update/doFinal paths to find where the temporary buffer is sized and add the equivalent range check there, then build the stress loop the issue describes (all modes, padding on/off, lengths 0..~100, multiple threads). Done means one buffer calculation shared by both backends and a clean, ideally crashing-revealing, stress run.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

Summary

SymmetricCipher allocates a temporary buffer for each native update/doFinal call. OCK and OpenSSL use different sizing today, and OCK's is based on an unproven assumption. We want a single calculation for both backends, backed by each library's real maximum write. Failing to provide a big enough buffer will cause an overlay.

Background

  • On main, getOutputSizeForOCK(inputLen) returns (bufferedCount + inputLen) rounded up to the next block, plus OCK_ENCRYPTION_RESIDUE (16). The 16 comes from the comment "GSKit code adds 16 to the input buffer length for every update and provides a 16 byte buffer for the Final". No source in the repo proves it is the maximum OCK writes.
  • PR #2009 adds the OpenSSL backend for AES. Its native code (SymmetricCipher.c) checks the real array length against the worst-case write before every EVP_* call (checkRange) and throws if too small:
    • update / decryptFinal: len + blockSize
    • encryptFinal: len + 2*blockSize - 1
      This change was only applied to the OpenSSL backend even though the same change is expected on both backends. The method getOutputSizeForOCK was also renamed to getNativeOutputSize.

Findings

  • OCKC's real maximum write per mode cannot be determined from documentation or source. Do not plan on "finding" it. OpenSSL is in use so likely it has the same constraint / buffer requirements. Whatever buffer is used should be applied to both OCKC and OpenSSL backends.
  • The fix must be safe and verified empirically with a test.

Proposed work

  1. Add the same range defensive check to the OCKC backend and remove the buffer resize code from the Java driving class SymmetricCipher method getOutputSizeForOCK or getNativeOutputSize that was changed in the mentioned PR.
  2. Stress test to try to force an overwrite, run in a loop on OCK :
    • All modes (ECB, CBC, CFB, CFB8, OFB, CTR; z fast path where available), padding and no padding.
    • update and doFinal, with buffered partial blocks, input lengths 0..~100 and around block boundaries, small and large caller buffers.
    • Many iterations and multiple threads, watching for crashes, heap corruption, or wrong output.
    • Limitation: a Java array overflow does not always crash, so a clean run is evidence, not proof.
  3. Apply a new buffer size common for both backends and validate using developed test. We can keep range checks in for a period of time and later remove them for performance reasons given that Java already should perform caluclations of correct size buffers and they woudl become redundant. Consider keeping the C range checks in if performance is not impacted.
Lingua principale
Java
Stelle
16
Fork
26
Merge medio
3g 7h
PR unite (30g)
108

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di IBM/OpenJCEPlus

Tutte le issue di IBM/OpenJCEPlus

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.