in src/com/amazon/corretto/crypto/provider/AesGcmSpi.java [294:384]
protected synchronized void engineInit(
int jceOpMode, Key key, AlgorithmParameterSpec algorithmParameterSpec, SecureRandom secureRandom
) throws InvalidKeyException, InvalidAlgorithmParameterException {
if (key == null) {
throw new InvalidKeyException("Key can't be null");
}
final GCMParameterSpec spec;
if (algorithmParameterSpec instanceof GCMParameterSpec) {
spec = (GCMParameterSpec) algorithmParameterSpec;
} else if (algorithmParameterSpec instanceof IvParameterSpec) {
spec = new GCMParameterSpec(DEFAULT_TAG_LENGTH,
((IvParameterSpec) algorithmParameterSpec).getIV());
} else {
throw new InvalidAlgorithmParameterException("I don't know how to handle a " + algorithmParameterSpec.getClass());
}
byte[] encodedKey = null;
if (jceKey != key) {
if (!(key instanceof SecretKey)) {
throw new InvalidKeyException("Need a SecretKey");
}
String keyAlgorithm = key.getAlgorithm();
if (!"RAW".equalsIgnoreCase(key.getFormat())) {
throw new InvalidKeyException("Need a raw format key");
}
if (!keyAlgorithm.equalsIgnoreCase("AES")) {
throw new InvalidKeyException("Expected an AES key");
}
encodedKey = key.getEncoded();
if (encodedKey == null) {
throw new InvalidKeyException("Key doesn't support encoding");
}
if (!MessageDigest.isEqual(encodedKey, this.key)) {
if (encodedKey.length != 128 / 8 && encodedKey.length != 192 / 8 && encodedKey.length != 256 / 8) {
throw new InvalidKeyException("Bad key length of " + (encodedKey.length * 8) + " bits; expected 128, 192, or 256 bits");
}
keyUsageCount = 0;
if (context != null) {
context.release();
}
context = null;
} else {
encodedKey = null;
}
}
byte[] iv = spec.getIV();
if ((spec.getTLen() % 8 != 0) || spec.getTLen() > 128 || spec.getTLen() < 96) {
throw new InvalidAlgorithmParameterException("Unsupported TLen value; must be one of {128, 120, 112, 104, 96}");
}
if (this.iv != null && this.key != null && (jceOpMode == Cipher.ENCRYPT_MODE || jceOpMode == Cipher.WRAP_MODE)) {
if (Arrays.equals(this.iv, iv) && (encodedKey == null || MessageDigest.isEqual(this.key, encodedKey))) {
throw new InvalidAlgorithmParameterException("Cannot reuse same iv and key for GCM encryption");
}
}
if (iv == null || iv.length == 0) {
throw new InvalidAlgorithmParameterException("IV must be at least one byte long");
}
switch (jceOpMode) {
case Cipher.ENCRYPT_MODE:
case Cipher.WRAP_MODE:
this.opMode = NATIVE_MODE_ENCRYPT;
break;
case Cipher.DECRYPT_MODE:
case Cipher.UNWRAP_MODE:
this.opMode = NATIVE_MODE_DECRYPT;
break;
default:
throw new InvalidAlgorithmParameterException("Unsupported cipher mode " + jceOpMode);
}
this.iv = iv;
this.tagLength = spec.getTLen() / 8;
if (encodedKey != null) {
this.key = encodedKey;
this.jceKey = (SecretKey) key;
}
this.needReset = false;
stateReset();
}