mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-12 08:53:12 +00:00
8149070: Enforce update ordering
Make sure that ISE is thrown when updateAAD is called after update. Reviewed-by: mullan
This commit is contained in:
parent
80083759f2
commit
63276540e2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -172,6 +172,11 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
private final int fixedKeySize; // in bytes, -1 if no restriction
|
||||
|
||||
/*
|
||||
* needed to enforce ISE thrown when updateAAD is called after update for GCM mode.
|
||||
*/
|
||||
private boolean updateCalled;
|
||||
|
||||
/**
|
||||
* Creates an instance of AES cipher with default ECB mode and
|
||||
* PKCS5Padding.
|
||||
@ -304,6 +309,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
checkKeySize(key, fixedKeySize);
|
||||
updateCalled = false;
|
||||
core.init(opmode, key, random);
|
||||
}
|
||||
|
||||
@ -336,6 +342,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
checkKeySize(key, fixedKeySize);
|
||||
updateCalled = false;
|
||||
core.init(opmode, key, params, random);
|
||||
}
|
||||
|
||||
@ -344,6 +351,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
checkKeySize(key, fixedKeySize);
|
||||
updateCalled = false;
|
||||
core.init(opmode, key, params, random);
|
||||
}
|
||||
|
||||
@ -368,6 +376,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
protected byte[] engineUpdate(byte[] input, int inputOffset,
|
||||
int inputLen) {
|
||||
updateCalled = true;
|
||||
return core.update(input, inputOffset, inputLen);
|
||||
}
|
||||
|
||||
@ -397,6 +406,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
|
||||
byte[] output, int outputOffset)
|
||||
throws ShortBufferException {
|
||||
updateCalled = true;
|
||||
return core.update(input, inputOffset, inputLen, output,
|
||||
outputOffset);
|
||||
}
|
||||
@ -433,7 +443,9 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return core.doFinal(input, inputOffset, inputLen);
|
||||
byte[] out = core.doFinal(input, inputOffset, inputLen);
|
||||
updateCalled = false;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -476,8 +488,10 @@ abstract class AESCipher extends CipherSpi {
|
||||
byte[] output, int outputOffset)
|
||||
throws IllegalBlockSizeException, ShortBufferException,
|
||||
BadPaddingException {
|
||||
return core.doFinal(input, inputOffset, inputLen, output,
|
||||
outputOffset);
|
||||
int outLen = core.doFinal(input, inputOffset, inputLen, output,
|
||||
outputOffset);
|
||||
updateCalled = false;
|
||||
return outLen;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -574,6 +588,9 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
@Override
|
||||
protected void engineUpdateAAD(byte[] src, int offset, int len) {
|
||||
if (core.getMode() == CipherCore.GCM_MODE && updateCalled) {
|
||||
throw new IllegalStateException("AAD must be supplied before encryption/decryption starts");
|
||||
}
|
||||
core.updateAAD(src, offset, len);
|
||||
}
|
||||
|
||||
@ -606,6 +623,9 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
@Override
|
||||
protected void engineUpdateAAD(ByteBuffer src) {
|
||||
if (core.getMode() == CipherCore.GCM_MODE && updateCalled) {
|
||||
throw new IllegalStateException("AAD must be supplied before encryption/decryption starts");
|
||||
}
|
||||
if (src != null) {
|
||||
int aadLen = src.limit() - src.position();
|
||||
if (aadLen != 0) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -124,7 +124,7 @@ final class CipherCore {
|
||||
private static final int PCBC_MODE = 4;
|
||||
private static final int CTR_MODE = 5;
|
||||
private static final int CTS_MODE = 6;
|
||||
private static final int GCM_MODE = 7;
|
||||
static final int GCM_MODE = 7;
|
||||
|
||||
/*
|
||||
* variables used for performing the GCM (key+iv) uniqueness check.
|
||||
@ -196,7 +196,7 @@ final class CipherCore {
|
||||
cipher = new CounterMode(rawImpl);
|
||||
unitBytes = 1;
|
||||
padding = null;
|
||||
} else if (modeUpperCase.startsWith("GCM")) {
|
||||
} else if (modeUpperCase.equals("GCM")) {
|
||||
// can only be used for block ciphers w/ 128-bit block size
|
||||
if (blockSize != 16) {
|
||||
throw new NoSuchAlgorithmException
|
||||
@ -223,6 +223,15 @@ final class CipherCore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mode of this cipher.
|
||||
*
|
||||
* @return the parsed cipher mode
|
||||
*/
|
||||
int getMode() {
|
||||
return cipherMode;
|
||||
}
|
||||
|
||||
private static int getNumOfUnit(String mode, int offset, int blockSize)
|
||||
throws NoSuchAlgorithmException {
|
||||
int result = blockSize; // use blockSize as default value
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -319,20 +319,22 @@ final class GaloisCounterMode extends FeedbackCipher {
|
||||
|
||||
// Feed the AAD data to GHASH, pad if necessary
|
||||
void processAAD() {
|
||||
if (aadBuffer != null && aadBuffer.size() > 0) {
|
||||
byte[] aad = aadBuffer.toByteArray();
|
||||
sizeOfAAD = aad.length;
|
||||
aadBuffer = null;
|
||||
if (aadBuffer != null) {
|
||||
if (aadBuffer.size() > 0) {
|
||||
byte[] aad = aadBuffer.toByteArray();
|
||||
sizeOfAAD = aad.length;
|
||||
|
||||
int lastLen = aad.length % AES_BLOCK_SIZE;
|
||||
if (lastLen != 0) {
|
||||
ghashAllToS.update(aad, 0, aad.length - lastLen);
|
||||
byte[] padded = expandToOneBlock(aad, aad.length - lastLen,
|
||||
lastLen);
|
||||
ghashAllToS.update(padded);
|
||||
} else {
|
||||
ghashAllToS.update(aad);
|
||||
int lastLen = aad.length % AES_BLOCK_SIZE;
|
||||
if (lastLen != 0) {
|
||||
ghashAllToS.update(aad, 0, aad.length - lastLen);
|
||||
byte[] padded = expandToOneBlock(aad, aad.length - lastLen,
|
||||
lastLen);
|
||||
ghashAllToS.update(padded);
|
||||
} else {
|
||||
ghashAllToS.update(aad);
|
||||
}
|
||||
}
|
||||
aadBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -59,10 +59,10 @@ class NativeGCMCipher extends NativeCipher {
|
||||
|
||||
// buffer for storing AAD data; if null, meaning buffer content has been
|
||||
// supplied to native context
|
||||
private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
|
||||
private ByteArrayOutputStream aadBuffer;
|
||||
|
||||
// buffer for storing input in decryption, not used for encryption
|
||||
private ByteArrayOutputStream ibuffer = null;
|
||||
private ByteArrayOutputStream ibuffer;
|
||||
|
||||
private int tagLen = DEFAULT_TAG_LEN;
|
||||
|
||||
@ -75,7 +75,7 @@ class NativeGCMCipher extends NativeCipher {
|
||||
* key + iv values used in previous encryption.
|
||||
* For decryption operations, no checking is necessary.
|
||||
*/
|
||||
private boolean requireReinit = false;
|
||||
private boolean requireReinit;
|
||||
private byte[] lastEncKey = null;
|
||||
private byte[] lastEncIv = null;
|
||||
|
||||
@ -86,12 +86,14 @@ class NativeGCMCipher extends NativeCipher {
|
||||
@Override
|
||||
protected void ensureInitialized() {
|
||||
if (!initialized) {
|
||||
if (aadBuffer != null && aadBuffer.size() > 0) {
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
aadBuffer = null;
|
||||
} else {
|
||||
init(encrypt, keyValue, iv, tagLen, null);
|
||||
byte[] aad = null;
|
||||
if (aadBuffer != null) {
|
||||
if (aadBuffer.size() > 0) {
|
||||
aad = aadBuffer.toByteArray();
|
||||
}
|
||||
}
|
||||
init(encrypt, keyValue, iv, tagLen, aad);
|
||||
aadBuffer = null;
|
||||
if (!initialized) {
|
||||
throw new UcryptoException("Cannot initialize Cipher");
|
||||
}
|
||||
@ -185,6 +187,7 @@ class NativeGCMCipher extends NativeCipher {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported mode: " + opmode);
|
||||
}
|
||||
aadBuffer = new ByteArrayOutputStream();
|
||||
boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
|
||||
byte[] keyBytes = key.getEncoded().clone();
|
||||
byte[] ivBytes = null;
|
||||
@ -219,6 +222,7 @@ class NativeGCMCipher extends NativeCipher {
|
||||
}
|
||||
lastEncIv = ivBytes;
|
||||
lastEncKey = keyBytes;
|
||||
ibuffer = null;
|
||||
} else {
|
||||
requireReinit = false;
|
||||
ibuffer = new ByteArrayOutputStream();
|
||||
@ -246,9 +250,11 @@ class NativeGCMCipher extends NativeCipher {
|
||||
// see JCE spec
|
||||
@Override
|
||||
protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
|
||||
if (aadBuffer != null && aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
if (aadBuffer != null) {
|
||||
if (aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
}
|
||||
aadBuffer = null;
|
||||
}
|
||||
if (requireReinit) {
|
||||
@ -274,9 +280,11 @@ class NativeGCMCipher extends NativeCipher {
|
||||
"(at least) " + len + " bytes long. Got: " +
|
||||
(out.length - outOfs));
|
||||
}
|
||||
if (aadBuffer != null && aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
if (aadBuffer != null) {
|
||||
if (aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
}
|
||||
aadBuffer = null;
|
||||
}
|
||||
if (requireReinit) {
|
||||
@ -374,9 +382,11 @@ class NativeGCMCipher extends NativeCipher {
|
||||
+ "(at least) " + len + " bytes long. Got: " +
|
||||
(out.length - outOfs));
|
||||
}
|
||||
if (aadBuffer != null && aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
if (aadBuffer != null) {
|
||||
if (aadBuffer.size() > 0) {
|
||||
// init again with AAD data
|
||||
init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
|
||||
}
|
||||
aadBuffer = null;
|
||||
}
|
||||
if (requireReinit) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user