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