16e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root/*
26e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * Copyright (C) 2012 The Android Open Source Project
36e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root *
46e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
56e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * you may not use this file except in compliance with the License.
66e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * You may obtain a copy of the License at
76e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root *
86e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
96e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root *
106e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * Unless required by applicable law or agreed to in writing, software
116e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
126e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * See the License for the specific language governing permissions and
146e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * limitations under the License.
156e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root */
166e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
186e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
196e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.InvalidKeyException;
206e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.InvalidParameterException;
216e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.PrivateKey;
226e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.PublicKey;
236e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.SignatureException;
24ca729b856ba17a8c4840f6cf8089da0010706d7cKenny Rootimport java.security.SignatureSpi;
256e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.interfaces.RSAPrivateCrtKey;
266e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.interfaces.RSAPrivateKey;
276e7efe14188211dc0f8a2e08276556e871fd8748Kenny Rootimport java.security.interfaces.RSAPublicKey;
286e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
296e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root/**
306e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * Implements the JDK Signature interface needed for RAW RSA signature
316e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root * generation and verification using OpenSSL.
326e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root */
33ca729b856ba17a8c4840f6cf8089da0010706d7cKenny Rootpublic class OpenSSLSignatureRawRSA extends SignatureSpi {
346e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    /**
356e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     * The current OpenSSL key we're operating on.
366e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     */
376e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    private OpenSSLKey key;
386e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
396e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    /**
406e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     * Buffer to hold value to be signed or verified.
416e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     */
426e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    private byte[] inputBuffer;
436e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
446e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    /**
456e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     * Current offset in input buffer.
466e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     */
476e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    private int inputOffset;
486e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
496e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    /**
506e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     * Provides a flag to specify when the input is too long.
516e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root     */
526e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    private boolean inputIsTooLong;
536e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
546e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
556e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected void engineUpdate(byte input) {
566e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        final int oldOffset = inputOffset++;
576e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
586e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (inputOffset > inputBuffer.length) {
596e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            inputIsTooLong = true;
606e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return;
616e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
626e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
636e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputBuffer[oldOffset] = input;
646e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
656e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
666e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
676e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected void engineUpdate(byte[] input, int offset, int len) {
686e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        final int oldOffset = inputOffset;
696e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputOffset += len;
706e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
716e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (inputOffset > inputBuffer.length) {
726e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            inputIsTooLong = true;
736e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return;
746e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
756e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
766e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        System.arraycopy(input, offset, inputBuffer, oldOffset, len);
776e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
786e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
796e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
806e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected Object engineGetParameter(String param) throws InvalidParameterException {
816e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        return null;
826e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
836e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
846e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
856e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
866e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (privateKey instanceof OpenSSLRSAPrivateKey) {
876e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            OpenSSLRSAPrivateKey rsaPrivateKey = (OpenSSLRSAPrivateKey) privateKey;
886e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            key = rsaPrivateKey.getOpenSSLKey();
896e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } else if (privateKey instanceof RSAPrivateCrtKey) {
906e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            RSAPrivateCrtKey rsaPrivateKey = (RSAPrivateCrtKey) privateKey;
916e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            key = OpenSSLRSAPrivateCrtKey.getInstance(rsaPrivateKey);
926e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } else if (privateKey instanceof RSAPrivateKey) {
936e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
946e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            key = OpenSSLRSAPrivateKey.getInstance(rsaPrivateKey);
956e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } else {
9647cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root            throw new InvalidKeyException("Need RSA private key");
976e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
986e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
996e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        // Allocate buffer according to RSA modulus size.
10037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        int maxSize = NativeCrypto.RSA_size(key.getNativeRef());
1016e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputBuffer = new byte[maxSize];
1026e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputOffset = 0;
1036e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1046e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1056e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
1066e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
1076e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (publicKey instanceof OpenSSLRSAPublicKey) {
1086e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            OpenSSLRSAPublicKey rsaPublicKey = (OpenSSLRSAPublicKey) publicKey;
1096e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            key = rsaPublicKey.getOpenSSLKey();
1106e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } else if (publicKey instanceof RSAPublicKey) {
1116e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
1126e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            key = OpenSSLRSAPublicKey.getInstance(rsaPublicKey);
1136e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } else {
11447cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root            throw new InvalidKeyException("Need RSA public key");
1156e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1166e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1176e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        // Allocate buffer according to RSA modulus size.
11837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        int maxSize = NativeCrypto.RSA_size(key.getNativeRef());
1196e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputBuffer = new byte[maxSize];
1206e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        inputOffset = 0;
1216e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1226e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1236e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
1246e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
1256e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1266e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1276e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
1286e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected byte[] engineSign() throws SignatureException {
1296e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (key == null) {
1306e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            // This can't actually happen, but you never know...
1316e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException("Need RSA private key");
1326e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1336e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1346e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (inputIsTooLong) {
1356e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException("input length " + inputOffset + " != "
1366e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                    + inputBuffer.length + " (modulus size)");
1376e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1386e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1396e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        byte[] outputBuffer = new byte[inputBuffer.length];
1406e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        try {
141098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            NativeCrypto.RSA_private_encrypt(inputOffset, inputBuffer, outputBuffer,
142f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley                    key.getNativeRef(), NativeConstants.RSA_PKCS1_PADDING);
1436e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return outputBuffer;
1446e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } catch (Exception ex) {
1456e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException(ex);
1466e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } finally {
1476e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            inputOffset = 0;
1486e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1496e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1506e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1516e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    @Override
1526e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
1536e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (key == null) {
1546e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            // This can't actually happen, but you never know...
1556e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException("Need RSA public key");
1566e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1576e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
1586e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        if (inputIsTooLong) {
1596e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return false;
1606e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1616e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root
162cecb4da210c1177a93eb753c42db5233217c017aKenny Root        // We catch this case here instead of BoringSSL so we can throw an
163cecb4da210c1177a93eb753c42db5233217c017aKenny Root        // exception that matches other implementations.
164cecb4da210c1177a93eb753c42db5233217c017aKenny Root        if (sigBytes.length > inputBuffer.length) {
165cecb4da210c1177a93eb753c42db5233217c017aKenny Root            throw new SignatureException("Input signature length is too large: " + sigBytes.length
166cecb4da210c1177a93eb753c42db5233217c017aKenny Root                    + " > " + inputBuffer.length);
167cecb4da210c1177a93eb753c42db5233217c017aKenny Root        }
168cecb4da210c1177a93eb753c42db5233217c017aKenny Root
1696e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        byte[] outputBuffer = new byte[inputBuffer.length];
1706e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        try {
171098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            final int resultSize;
1726e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            try {
173098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                resultSize = NativeCrypto.RSA_public_decrypt(sigBytes.length, sigBytes,
174f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley                        outputBuffer, key.getNativeRef(), NativeConstants.RSA_PKCS1_PADDING);
175098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            } catch (SignatureException e) {
176098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                throw e;
1776e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            } catch (Exception e) {
1786e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                return false;
1796e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            }
1806e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            /* Make this constant time by comparing every byte. */
181098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            boolean matches = (resultSize == inputOffset);
182098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            for (int i = 0; i < resultSize; i++) {
1836e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                if (inputBuffer[i] != outputBuffer[i]) {
1846e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                    matches = false;
1856e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                }
1866e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            }
1876e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return matches;
1886e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } catch (Exception ex) {
1896e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException(ex);
1906e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } finally {
1916e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            inputOffset = 0;
1926e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1936e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1946e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root}
195