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.
1006e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        int maxSize = NativeCrypto.RSA_size(key.getPkeyContext());
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.
1186e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        int maxSize = NativeCrypto.RSA_size(key.getPkeyContext());
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,
142098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                    key.getPkeyContext(), NativeCrypto.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
1626e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        byte[] outputBuffer = new byte[inputBuffer.length];
1636e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        try {
164098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            final int resultSize;
1656e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            try {
166098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                resultSize = NativeCrypto.RSA_public_decrypt(sigBytes.length, sigBytes,
167098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                        outputBuffer, key.getPkeyContext(), NativeCrypto.RSA_PKCS1_PADDING);
168098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            } catch (SignatureException e) {
169098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom                throw e;
1706e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            } catch (Exception e) {
1716e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                return false;
1726e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            }
1736e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            /* Make this constant time by comparing every byte. */
174098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            boolean matches = (resultSize == inputOffset);
175098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom            for (int i = 0; i < resultSize; i++) {
1766e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                if (inputBuffer[i] != outputBuffer[i]) {
1776e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                    matches = false;
1786e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root                }
1796e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            }
1806e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            return matches;
1816e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } catch (Exception ex) {
1826e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            throw new SignatureException(ex);
1836e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        } finally {
1846e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root            inputOffset = 0;
1856e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root        }
1866e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    }
1876e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root}
188