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

package com.google.crypto.tink.daead;

import com.google.protobuf.MessageLite;
import com.google.protobuf.Parser;
import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.internal.TinkBugException;
import com.google.crypto.tink.KeyTemplate;
import com.google.crypto.tink.internal.KeyManagerRegistry;
import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
import com.google.crypto.tink.internal.MutableParametersRegistry;
import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
import com.google.crypto.tink.daead.internal.AesSivProtoSerialization;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import java.util.Collections;
import java.util.HashMap;
import com.google.crypto.tink.Parameters;
import java.util.Map;
import com.google.crypto.tink.util.SecretBytes;
import com.google.crypto.tink.AccessesPartialKey;
import com.google.crypto.tink.internal.Util;
import com.google.crypto.tink.SecretKeyAccess;
import javax.annotation.Nullable;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.subtle.AesSiv;
import com.google.crypto.tink.internal.KeyCreator;
import com.google.crypto.tink.internal.MutableKeyDerivationRegistry;
import com.google.crypto.tink.KeyManager;
import com.google.crypto.tink.DeterministicAead;
import com.google.crypto.tink.internal.PrimitiveConstructor;

public final class AesSivKeyManager
{
    private static final PrimitiveConstructor<AesSivKey, DeterministicAead> AES_SIV_PRIMITIVE_CONSTRUCTOR;
    private static final int KEY_SIZE_IN_BYTES = 64;
    private static final KeyManager<DeterministicAead> legacyKeyManager;
    private static final MutableKeyDerivationRegistry.InsecureKeyCreator<AesSivParameters> KEY_DERIVER;
    private static final KeyCreator<AesSivParameters> KEY_CREATOR;
    
    private static DeterministicAead createDeterministicAead(final AesSivKey key) throws GeneralSecurityException {
        validateParameters(key.getParameters());
        return AesSiv.create(key);
    }
    
    static String getKeyType() {
        return "type.googleapis.com/google.crypto.tink.AesSivKey";
    }
    
    private static void validateParameters(final AesSivParameters parameters) throws GeneralSecurityException {
        if (parameters.getKeySizeBytes() != 64) {
            throw new InvalidAlgorithmParameterException("invalid key size: " + parameters.getKeySizeBytes() + ". Valid keys must have " + 64 + " bytes.");
        }
    }
    
    @AccessesPartialKey
    static AesSivKey createAesSivKeyFromRandomness(final AesSivParameters parameters, final InputStream stream, @Nullable final Integer idRequirement, final SecretKeyAccess access) throws GeneralSecurityException {
        validateParameters(parameters);
        return AesSivKey.builder().setParameters(parameters).setIdRequirement(idRequirement).setKeyBytes(Util.readIntoSecretBytes(stream, parameters.getKeySizeBytes(), access)).build();
    }
    
    @AccessesPartialKey
    static AesSivKey newKey(final AesSivParameters parameters, @Nullable final Integer idRequirement) throws GeneralSecurityException {
        validateParameters(parameters);
        return AesSivKey.builder().setParameters(parameters).setIdRequirement(idRequirement).setKeyBytes(SecretBytes.randomBytes(parameters.getKeySizeBytes())).build();
    }
    
    private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
        final Map<String, Parameters> result = new HashMap<String, Parameters>();
        result.put("AES256_SIV", PredefinedDeterministicAeadParameters.AES256_SIV);
        result.put("AES256_SIV_RAW", AesSivParameters.builder().setKeySizeBytes(64).setVariant(AesSivParameters.Variant.NO_PREFIX).build());
        return Collections.unmodifiableMap((Map<? extends String, ? extends Parameters>)result);
    }
    
    public static void register(final boolean newKeyAllowed) throws GeneralSecurityException {
        if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
            throw new GeneralSecurityException("Registering AES SIV is not supported in FIPS mode");
        }
        AesSivProtoSerialization.register();
        MutablePrimitiveRegistry.globalInstance().registerPrimitiveConstructor(AesSivKeyManager.AES_SIV_PRIMITIVE_CONSTRUCTOR);
        MutableParametersRegistry.globalInstance().putAll(namedParameters());
        MutableKeyDerivationRegistry.globalInstance().add(AesSivKeyManager.KEY_DERIVER, AesSivParameters.class);
        MutableKeyCreationRegistry.globalInstance().add(AesSivKeyManager.KEY_CREATOR, AesSivParameters.class);
        KeyManagerRegistry.globalInstance().registerKeyManager(AesSivKeyManager.legacyKeyManager, newKeyAllowed);
    }
    
    public static final KeyTemplate aes256SivTemplate() {
        return TinkBugException.exceptionIsBug(() -> KeyTemplate.createFrom(AesSivParameters.builder().setKeySizeBytes(64).setVariant(AesSivParameters.Variant.TINK).build()));
    }
    
    public static final KeyTemplate rawAes256SivTemplate() {
        return TinkBugException.exceptionIsBug(() -> KeyTemplate.createFrom(AesSivParameters.builder().setKeySizeBytes(64).setVariant(AesSivParameters.Variant.NO_PREFIX).build()));
    }
    
    private AesSivKeyManager() {
    }
    
    static {
        AES_SIV_PRIMITIVE_CONSTRUCTOR = PrimitiveConstructor.create(AesSivKeyManager::createDeterministicAead, AesSivKey.class, DeterministicAead.class);
        legacyKeyManager = LegacyKeyManagerImpl.create(getKeyType(), DeterministicAead.class, KeyData.KeyMaterialType.SYMMETRIC, com.google.crypto.tink.proto.AesSivKey.parser());
        KEY_DERIVER = AesSivKeyManager::createAesSivKeyFromRandomness;
        KEY_CREATOR = AesSivKeyManager::newKey;
    }
}
