package com.google.crypto.tink.subtle;

import com.google.crypto.tink.PublicKeyVerify;
import com.google.crypto.tink.config.TinkFips;
import com.google.crypto.tink.subtle.Enums;
import com.google.errorprone.annotations.Immutable;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;

@Immutable
public final class RsaSsaPssVerifyJce implements PublicKeyVerify {
    public static final TinkFips.AlgorithmFipsCompatibility FIPS = TinkFips.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
    private final Enums.HashType mgf1Hash;
    private final RSAPublicKey publicKey;
    private final int saltLength;
    private final Enums.HashType sigHash;

    public RsaSsaPssVerifyJce(RSAPublicKey rSAPublicKey, Enums.HashType hashType, Enums.HashType hashType2, int i) throws GeneralSecurityException {
        if (FIPS.isCompatible()) {
            Validators.validateSignatureHash(hashType);
            Validators.validateRsaModulusSize(rSAPublicKey.getModulus().bitLength());
            Validators.validateRsaPublicExponent(rSAPublicKey.getPublicExponent());
            this.publicKey = rSAPublicKey;
            this.sigHash = hashType;
            this.mgf1Hash = hashType2;
            this.saltLength = i;
            return;
        }
        throw new GeneralSecurityException("Can not use RSA PSS in FIPS-mode, as BoringCrypto module is not available.");
    }

    @Override // com.google.crypto.tink.PublicKeyVerify
    public void verify(byte[] bArr, byte[] bArr2) throws GeneralSecurityException {
        BigInteger publicExponent = this.publicKey.getPublicExponent();
        BigInteger modulus = this.publicKey.getModulus();
        int bitLength = (modulus.bitLength() + 7) / 8;
        int bitLength2 = ((modulus.bitLength() - 1) + 7) / 8;
        if (bitLength == bArr.length) {
            BigInteger bytes2Integer = SubtleUtil.bytes2Integer(bArr);
            if (bytes2Integer.compareTo(modulus) < 0) {
                emsaPssVerify(bArr2, SubtleUtil.integer2Bytes(bytes2Integer.modPow(publicExponent, modulus), bitLength2), modulus.bitLength() - 1);
                return;
            }
            throw new GeneralSecurityException("signature out of range");
        }
        throw new GeneralSecurityException("invalid signature's length");
    }

    private void emsaPssVerify(byte[] bArr, byte[] bArr2, int i) throws GeneralSecurityException {
        Validators.validateSignatureHash(this.sigHash);
        MessageDigest instance = EngineFactory.MESSAGE_DIGEST.getInstance(SubtleUtil.toDigestAlgo(this.sigHash));
        byte[] digest = instance.digest(bArr);
        int digestLength = instance.getDigestLength();
        int length = bArr2.length;
        if (length < this.saltLength + digestLength + 2) {
            throw new GeneralSecurityException("inconsistent");
        } else if (bArr2[bArr2.length - 1] == -68) {
            int i2 = length - digestLength;
            int i3 = i2 - 1;
            byte[] copyOf = Arrays.copyOf(bArr2, i3);
            byte[] copyOfRange = Arrays.copyOfRange(bArr2, copyOf.length, copyOf.length + digestLength);
            int i4 = 0;
            while (true) {
                long j = (((long) length) * 8) - ((long) i);
                if (((long) i4) < j) {
                    if (((copyOf[i4 / 8] >> (7 - (i4 % 8))) & 1) == 0) {
                        i4++;
                        i3 = i3;
                        instance = instance;
                        digest = digest;
                    } else {
                        throw new GeneralSecurityException("inconsistent");
                    }
                } else {
                    byte[] mgf1 = SubtleUtil.mgf1(copyOfRange, i3, this.mgf1Hash);
                    int length2 = mgf1.length;
                    byte[] bArr3 = new byte[length2];
                    for (int i5 = 0; i5 < length2; i5++) {
                        bArr3[i5] = (byte) (mgf1[i5] ^ copyOf[i5]);
                    }
                    for (int i6 = 0; ((long) i6) <= j; i6++) {
                        int i7 = i6 / 8;
                        bArr3[i7] = (byte) ((~(1 << (7 - (i6 % 8)))) & bArr3[i7]);
                    }
                    int i8 = 0;
                    while (true) {
                        int i9 = this.saltLength;
                        if (i8 < (i2 - i9) - 2) {
                            if (bArr3[i8] == 0) {
                                i8++;
                            } else {
                                throw new GeneralSecurityException("inconsistent");
                            }
                        } else if (bArr3[(i2 - i9) - 2] == 1) {
                            byte[] copyOfRange2 = Arrays.copyOfRange(bArr3, length2 - i9, length2);
                            int i10 = digestLength + 8;
                            byte[] bArr4 = new byte[(this.saltLength + i10)];
                            System.arraycopy(digest, 0, bArr4, 8, digest.length);
                            System.arraycopy(copyOfRange2, 0, bArr4, i10, copyOfRange2.length);
                            if (!Bytes.equal(instance.digest(bArr4), copyOfRange)) {
                                throw new GeneralSecurityException("inconsistent");
                            }
                            return;
                        } else {
                            throw new GeneralSecurityException("inconsistent");
                        }
                    }
                }
            }
        } else {
            throw new GeneralSecurityException("inconsistent");
        }
    }
}
