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