// 
// Decompiled by Procyon v0.6.0
// 

package com.google.crypto.tink.aead.internal;

import javax.crypto.Cipher;
import java.security.spec.AlgorithmParameterSpec;
import java.security.Key;
import java.security.GeneralSecurityException;
import javax.crypto.SecretKey;
import com.google.crypto.tink.config.internal.TinkFipsUtil;

public final class InsecureNonceAesGcmJce
{
    public static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS;
    public static final int IV_SIZE_IN_BYTES = 12;
    public static final int TAG_SIZE_IN_BYTES = 16;
    private final SecretKey keySpec;
    
    public InsecureNonceAesGcmJce(final byte[] key) throws GeneralSecurityException {
        if (!InsecureNonceAesGcmJce.FIPS.isCompatible()) {
            throw new GeneralSecurityException("Can not use AES-GCM in FIPS-mode, as BoringCrypto module is not available.");
        }
        this.keySpec = AesGcmJceUtil.getSecretKey(key);
    }
    
    public byte[] encrypt(final byte[] iv, final byte[] plaintext, final byte[] associatedData) throws GeneralSecurityException {
        return this.encrypt(iv, plaintext, 0, associatedData);
    }
    
    public byte[] encrypt(final byte[] iv, final byte[] plaintext, final int ciphertextOffset, final byte[] associatedData) throws GeneralSecurityException {
        if (iv.length != 12) {
            throw new GeneralSecurityException("iv is wrong size");
        }
        final AlgorithmParameterSpec params = AesGcmJceUtil.getParams(iv);
        final Cipher localCipher = AesGcmJceUtil.getThreadLocalCipher();
        localCipher.init(1, this.keySpec, params);
        if (associatedData != null && associatedData.length != 0) {
            localCipher.updateAAD(associatedData);
        }
        final int ciphertextSize = localCipher.getOutputSize(plaintext.length);
        if (ciphertextSize > Integer.MAX_VALUE - ciphertextOffset) {
            throw new GeneralSecurityException("plaintext too long");
        }
        final int outputSize = ciphertextOffset + ciphertextSize;
        final byte[] output = new byte[outputSize];
        final int written = localCipher.doFinal(plaintext, 0, plaintext.length, output, ciphertextOffset);
        if (written != ciphertextSize) {
            throw new GeneralSecurityException("not enough data written");
        }
        return output;
    }
    
    public byte[] decrypt(final byte[] iv, final byte[] ciphertext, final byte[] associatedData) throws GeneralSecurityException {
        return this.decrypt(iv, ciphertext, 0, associatedData);
    }
    
    public byte[] decrypt(final byte[] iv, final byte[] ciphertextWithPrefix, final int ciphertextOffset, final byte[] associatedData) throws GeneralSecurityException {
        if (iv.length != 12) {
            throw new GeneralSecurityException("iv is wrong size");
        }
        if (ciphertextWithPrefix.length < 16 + ciphertextOffset) {
            throw new GeneralSecurityException("ciphertext too short");
        }
        final AlgorithmParameterSpec params = AesGcmJceUtil.getParams(iv);
        final Cipher localCipher = AesGcmJceUtil.getThreadLocalCipher();
        localCipher.init(2, this.keySpec, params);
        if (associatedData != null && associatedData.length != 0) {
            localCipher.updateAAD(associatedData);
        }
        return localCipher.doFinal(ciphertextWithPrefix, ciphertextOffset, ciphertextWithPrefix.length - ciphertextOffset);
    }
    
    static {
        FIPS = TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
    }
}
