@@ -123,34 +123,54 @@ protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] o
123123
124124 @ Override
125125 protected byte [] engineDoFinal (byte [] input , int inputOffset , int inputLen ) throws IllegalBlockSizeException , BadPaddingException {
126- byte [] output = new byte [engineGetOutputSize (inputBuffer .length + inputLen )];
126+ int outputSize = engineGetOutputSize (inputBuffer .length + inputLen );
127+ if (outputSize < 0 ) {
128+ throw new IllegalBlockSizeException ("Ciphertext too short (must be at least 16 bytes including SIV tag)" );
129+ }
130+ byte [] output = new byte [outputSize ];
127131 try {
128132 engineDoFinal (input , inputOffset , inputLen , output , 0 );
129133 } catch (ShortBufferException e ) {
134+ // outputSize was calculated before, so this should never happen
130135 throw new IllegalStateException (e );
131136 }
132137 return output ;
133138 }
134139
135140 @ Override
136141 protected int engineDoFinal (byte [] input , int inputOffset , int inputLen , byte [] output , int outputOffset ) throws ShortBufferException , IllegalBlockSizeException , BadPaddingException {
142+ int outputSize = engineGetOutputSize (inputBuffer .length + inputLen );
143+ if (outputSize < 0 ) {
144+ throw new IllegalBlockSizeException ("Ciphertext too short (must be at least 16 bytes including SIV tag)" );
145+ }
137146 int availableSpace = output .length - outputOffset ;
138- if (availableSpace < engineGetOutputSize ( inputBuffer . length + inputLen ) ) {
147+ if (availableSpace < outputSize ) {
139148 throw new ShortBufferException ();
140149 }
141150 engineUpdate (input , inputOffset , inputLen );
142151
152+ int resultLength ;
143153 SivEngine siv = new SivEngine (this .key );
144154 byte [][] aad = this .aad .toArray (new byte [this .aad .size ()][]);
145155 if (this .opmode == Cipher .ENCRYPT_MODE || this .opmode == Cipher .WRAP_MODE ) {
146- return siv .encrypt (inputBuffer , output , outputOffset , aad );
156+ resultLength = siv .encrypt (inputBuffer , output , outputOffset , aad );
147157 } else if (this .opmode == Cipher .DECRYPT_MODE || this .opmode == Cipher .UNWRAP_MODE ) {
148158 // for security reasons we can't write into output directly before checking integrity:
149- byte [] plaintext = siv .decrypt (inputBuffer , aad );
150- System .arraycopy (plaintext , 0 , output , outputOffset , plaintext .length );
151- return plaintext .length ;
159+ byte [] plaintext = new byte [0 ];
160+ try {
161+ plaintext = siv .decrypt (inputBuffer , aad );
162+ System .arraycopy (plaintext , 0 , output , outputOffset , plaintext .length );
163+ resultLength = plaintext .length ;
164+ } finally {
165+ Arrays .fill (plaintext , (byte ) 0x00 );
166+ }
152167 } else {
153168 throw new IllegalStateException ("Invalid opmode " + this .opmode );
154169 }
170+
171+ // reset internal state:
172+ this .inputBuffer = EMPTY ;
173+ this .aad .clear ();
174+ return resultLength ;
155175 }
156176}
0 commit comments