Unify native output buffer sizing for OCK and OpenSSL in SymmetricCipher

Abierto
#2,092 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
20/100
Tipo de issue
Refactorización
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
c, java
Área
cryptography

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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.
Lenguaje dominante
Java
Estrellas
16
Forks
26
Merge medio
3 d 7 h
PR fusionados (30 d)
108

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de IBM/OpenJCEPlus

Todos los issues de IBM/OpenJCEPlus

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.