1 /* 2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.crypto.provider; 27 28 import java.util.Locale; 29 30 import java.security.*; 31 import java.security.interfaces.*; 32 import java.security.spec.AlgorithmParameterSpec; 33 import java.security.spec.InvalidParameterSpecException; 34 import java.security.spec.MGF1ParameterSpec; 35 36 import javax.crypto.*; 37 import javax.crypto.spec.PSource; 38 import javax.crypto.spec.OAEPParameterSpec; 39 40 import sun.security.rsa.*; 41 import sun.security.jca.Providers; 42 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; 43 import sun.security.util.KeyUtil; 44 45 /** 46 * RSA cipher implementation. Supports RSA en/decryption and signing/verifying 47 * using PKCS#1 v1.5 padding and without padding (raw RSA). Note that raw RSA 48 * is supported mostly for completeness and should only be used in rare cases. 49 * 50 * Objects should be instantiated by calling Cipher.getInstance() using the 51 * following algorithm names: 52 * . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 padding. The mode (blocktype) 53 * is selected based on the en/decryption mode and public/private key used 54 * . "RSA/ECB/NoPadding" for rsa RSA. 55 * 56 * We only do one RSA operation per doFinal() call. If the application passes 57 * more data via calls to update() or doFinal(), we throw an 58 * IllegalBlockSizeException when doFinal() is called (see JCE API spec). 59 * Bulk encryption using RSA does not make sense and is not standardized. 60 * 61 * Note: RSA keys should be at least 512 bits long 62 * 63 * @since 1.5 64 * @author Andreas Sterbenz 65 */ 66 public final class RSACipher extends CipherSpi { 67 68 // constant for an empty byte array 69 private final static byte[] B0 = new byte[0]; 70 71 // mode constant for public key encryption 72 private final static int MODE_ENCRYPT = 1; 73 // mode constant for private key decryption 74 private final static int MODE_DECRYPT = 2; 75 // mode constant for private key encryption (signing) 76 private final static int MODE_SIGN = 3; 77 // mode constant for public key decryption (verifying) 78 private final static int MODE_VERIFY = 4; 79 80 // constant for raw RSA 81 private final static String PAD_NONE = "NoPadding"; 82 // constant for PKCS#1 v1.5 RSA 83 private final static String PAD_PKCS1 = "PKCS1Padding"; 84 // constant for PKCS#2 v2.0 OAEP with MGF1 85 private final static String PAD_OAEP_MGF1 = "OAEP"; 86 87 // current mode, one of MODE_* above. Set when init() is called 88 private int mode; 89 90 // active padding type, one of PAD_* above. Set by setPadding() 91 private String paddingType; 92 93 // padding object 94 private RSAPadding padding; 95 96 // cipher parameter for OAEP padding and TLS RSA premaster secret 97 private AlgorithmParameterSpec spec = null; 98 99 // buffer for the data 100 private byte[] buffer; 101 // offset into the buffer (number of bytes buffered) 102 private int bufOfs; 103 104 // size of the output 105 private int outputSize; 106 107 // the public key, if we were initialized using a public key 108 private RSAPublicKey publicKey; 109 // the private key, if we were initialized using a private key 110 private RSAPrivateKey privateKey; 111 112 // hash algorithm for OAEP 113 private String oaepHashAlgorithm = "SHA-1"; 114 115 // the source of randomness 116 private SecureRandom random; 117 118 public RSACipher() { 119 paddingType = PAD_PKCS1; 120 } 121 122 // modes do not make sense for RSA, but allow ECB 123 // see JCE spec 124 protected void engineSetMode(String mode) throws NoSuchAlgorithmException { 125 if (mode.equalsIgnoreCase("ECB") == false) { 126 throw new NoSuchAlgorithmException("Unsupported mode " + mode); 127 } 128 } 129 130 // set the padding type 131 // see JCE spec 132 protected void engineSetPadding(String paddingName) 133 throws NoSuchPaddingException { 134 if (paddingName.equalsIgnoreCase(PAD_NONE)) { 135 paddingType = PAD_NONE; 136 } else if (paddingName.equalsIgnoreCase(PAD_PKCS1)) { 137 paddingType = PAD_PKCS1; 138 } else { 139 String lowerPadding = paddingName.toLowerCase(Locale.ENGLISH); 140 if (lowerPadding.equals("oaeppadding")) { 141 paddingType = PAD_OAEP_MGF1; 142 } else if (lowerPadding.startsWith("oaepwith") && 143 lowerPadding.endsWith("andmgf1padding")) { 144 paddingType = PAD_OAEP_MGF1; 145 // "oaepwith".length() == 8 146 // "andmgf1padding".length() == 14 147 oaepHashAlgorithm = 148 paddingName.substring(8, paddingName.length() - 14); 149 // check if MessageDigest appears to be available 150 // avoid getInstance() call here 151 if (Providers.getProviderList().getService 152 ("MessageDigest", oaepHashAlgorithm) == null) { 153 throw new NoSuchPaddingException 154 ("MessageDigest not available for " + paddingName); 155 } 156 } else { 157 throw new NoSuchPaddingException 158 ("Padding " + paddingName + " not supported"); 159 } 160 } 161 } 162 163 // return 0 as block size, we are not a block cipher 164 // see JCE spec 165 protected int engineGetBlockSize() { 166 return 0; 167 } 168 169 // return the output size 170 // see JCE spec 171 protected int engineGetOutputSize(int inputLen) { 172 return outputSize; 173 } 174 175 // no iv, return null 176 // see JCE spec 177 protected byte[] engineGetIV() { 178 return null; 179 } 180 181 // see JCE spec 182 protected AlgorithmParameters engineGetParameters() { 183 if (spec != null && spec instanceof OAEPParameterSpec) { 184 try { 185 AlgorithmParameters params = 186 AlgorithmParameters.getInstance("OAEP", "SunJCE"); 187 params.init(spec); 188 return params; 189 } catch (NoSuchAlgorithmException nsae) { 190 // should never happen 191 throw new RuntimeException("Cannot find OAEP " + 192 " AlgorithmParameters implementation in SunJCE provider"); 193 } catch (NoSuchProviderException nspe) { 194 // should never happen 195 throw new RuntimeException("Cannot find SunJCE provider"); 196 } catch (InvalidParameterSpecException ipse) { 197 // should never happen 198 throw new RuntimeException("OAEPParameterSpec not supported"); 199 } 200 } else { 201 return null; 202 } 203 } 204 205 // see JCE spec 206 protected void engineInit(int opmode, Key key, SecureRandom random) 207 throws InvalidKeyException { 208 try { 209 init(opmode, key, random, null); 210 } catch (InvalidAlgorithmParameterException iape) { 211 // never thrown when null parameters are used; 212 // but re-throw it just in case 213 InvalidKeyException ike = 214 new InvalidKeyException("Wrong parameters"); 215 ike.initCause(iape); 216 throw ike; 217 } 218 } 219 220 // see JCE spec 221 protected void engineInit(int opmode, Key key, 222 AlgorithmParameterSpec params, SecureRandom random) 223 throws InvalidKeyException, InvalidAlgorithmParameterException { 224 init(opmode, key, random, params); 225 } 226 227 // see JCE spec 228 protected void engineInit(int opmode, Key key, 229 AlgorithmParameters params, SecureRandom random) 230 throws InvalidKeyException, InvalidAlgorithmParameterException { 231 if (params == null) { 232 init(opmode, key, random, null); 233 } else { 234 try { 235 OAEPParameterSpec spec = 236 params.getParameterSpec(OAEPParameterSpec.class); 237 init(opmode, key, random, spec); 238 } catch (InvalidParameterSpecException ipse) { 239 InvalidAlgorithmParameterException iape = 240 new InvalidAlgorithmParameterException("Wrong parameter"); 241 iape.initCause(ipse); 242 throw iape; 243 } 244 } 245 } 246 247 // initialize this cipher 248 private void init(int opmode, Key key, SecureRandom random, 249 AlgorithmParameterSpec params) 250 throws InvalidKeyException, InvalidAlgorithmParameterException { 251 boolean encrypt; 252 switch (opmode) { 253 case Cipher.ENCRYPT_MODE: 254 case Cipher.WRAP_MODE: 255 encrypt = true; 256 break; 257 case Cipher.DECRYPT_MODE: 258 case Cipher.UNWRAP_MODE: 259 encrypt = false; 260 break; 261 default: 262 throw new InvalidKeyException("Unknown mode: " + opmode); 263 } 264 RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); 265 if (key instanceof RSAPublicKey) { 266 mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY; 267 publicKey = (RSAPublicKey)key; 268 privateKey = null; 269 } else { // must be RSAPrivateKey per check in toRSAKey 270 mode = encrypt ? MODE_SIGN : MODE_DECRYPT; 271 privateKey = (RSAPrivateKey)key; 272 publicKey = null; 273 } 274 int n = RSACore.getByteLength(rsaKey.getModulus()); 275 outputSize = n; 276 bufOfs = 0; 277 if (paddingType == PAD_NONE) { 278 if (params != null) { 279 throw new InvalidAlgorithmParameterException 280 ("Parameters not supported"); 281 } 282 padding = RSAPadding.getInstance(RSAPadding.PAD_NONE, n, random); 283 buffer = new byte[n]; 284 } else if (paddingType == PAD_PKCS1) { 285 if (params != null) { 286 if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { 287 throw new InvalidAlgorithmParameterException( 288 "Parameters not supported"); 289 } 290 291 spec = params; 292 this.random = random; // for TLS RSA premaster secret 293 } 294 int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2 295 : RSAPadding.PAD_BLOCKTYPE_1; 296 padding = RSAPadding.getInstance(blockType, n, random); 297 if (encrypt) { 298 int k = padding.getMaxDataSize(); 299 buffer = new byte[k]; 300 } else { 301 buffer = new byte[n]; 302 } 303 } else { // PAD_OAEP_MGF1 304 if ((mode == MODE_SIGN) || (mode == MODE_VERIFY)) { 305 throw new InvalidKeyException 306 ("OAEP cannot be used to sign or verify signatures"); 307 } 308 if (params != null) { 309 if (!(params instanceof OAEPParameterSpec)) { 310 throw new InvalidAlgorithmParameterException 311 ("Wrong Parameters for OAEP Padding"); 312 } 313 spec = params; 314 } else { 315 spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", 316 MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); 317 } 318 padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n, 319 random, (OAEPParameterSpec)spec); 320 if (encrypt) { 321 int k = padding.getMaxDataSize(); 322 buffer = new byte[k]; 323 } else { 324 buffer = new byte[n]; 325 } 326 } 327 } 328 329 // internal update method 330 private void update(byte[] in, int inOfs, int inLen) { 331 if ((inLen == 0) || (in == null)) { 332 return; 333 } 334 if (bufOfs + inLen > buffer.length) { 335 bufOfs = buffer.length + 1; 336 return; 337 } 338 System.arraycopy(in, inOfs, buffer, bufOfs, inLen); 339 bufOfs += inLen; 340 } 341 342 // internal doFinal() method. Here we perform the actual RSA operation 343 private byte[] doFinal() throws BadPaddingException, 344 IllegalBlockSizeException { 345 if (bufOfs > buffer.length) { 346 throw new IllegalBlockSizeException("Data must not be longer " 347 + "than " + buffer.length + " bytes"); 348 } 349 try { 350 byte[] data; 351 switch (mode) { 352 case MODE_SIGN: 353 data = padding.pad(buffer, 0, bufOfs); 354 return RSACore.rsa(data, privateKey, true); 355 case MODE_VERIFY: 356 byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs); 357 data = RSACore.rsa(verifyBuffer, publicKey); 358 return padding.unpad(data); 359 case MODE_ENCRYPT: 360 data = padding.pad(buffer, 0, bufOfs); 361 return RSACore.rsa(data, publicKey); 362 case MODE_DECRYPT: 363 byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); 364 data = RSACore.rsa(decryptBuffer, privateKey, false); 365 return padding.unpad(data); 366 default: 367 throw new AssertionError("Internal error"); 368 } 369 } finally { 370 bufOfs = 0; 371 } 372 } 373 374 // see JCE spec 375 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) { 376 update(in, inOfs, inLen); 377 return B0; 378 } 379 380 // see JCE spec 381 protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out, 382 int outOfs) { 383 update(in, inOfs, inLen); 384 return 0; 385 } 386 387 // see JCE spec 388 protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) 389 throws BadPaddingException, IllegalBlockSizeException { 390 update(in, inOfs, inLen); 391 return doFinal(); 392 } 393 394 // see JCE spec 395 protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, 396 int outOfs) throws ShortBufferException, BadPaddingException, 397 IllegalBlockSizeException { 398 if (outputSize > out.length - outOfs) { 399 throw new ShortBufferException 400 ("Need " + outputSize + " bytes for output"); 401 } 402 update(in, inOfs, inLen); 403 byte[] result = doFinal(); 404 int n = result.length; 405 System.arraycopy(result, 0, out, outOfs, n); 406 return n; 407 } 408 409 // see JCE spec 410 protected byte[] engineWrap(Key key) throws InvalidKeyException, 411 IllegalBlockSizeException { 412 byte[] encoded = key.getEncoded(); 413 if ((encoded == null) || (encoded.length == 0)) { 414 throw new InvalidKeyException("Could not obtain encoded key"); 415 } 416 if (encoded.length > buffer.length) { 417 throw new InvalidKeyException("Key is too long for wrapping"); 418 } 419 update(encoded, 0, encoded.length); 420 try { 421 return doFinal(); 422 } catch (BadPaddingException e) { 423 // should not occur 424 throw new InvalidKeyException("Wrapping failed", e); 425 } 426 } 427 428 // see JCE spec 429 protected Key engineUnwrap(byte[] wrappedKey, String algorithm, 430 int type) throws InvalidKeyException, NoSuchAlgorithmException { 431 if (wrappedKey.length > buffer.length) { 432 throw new InvalidKeyException("Key is too long for unwrapping"); 433 } 434 435 boolean isTlsRsaPremasterSecret = 436 algorithm.equals("TlsRsaPremasterSecret"); 437 Exception failover = null; 438 byte[] encoded = null; 439 440 update(wrappedKey, 0, wrappedKey.length); 441 try { 442 encoded = doFinal(); 443 } catch (BadPaddingException e) { 444 if (isTlsRsaPremasterSecret) { 445 failover = e; 446 } else { 447 throw new InvalidKeyException("Unwrapping failed", e); 448 } 449 } catch (IllegalBlockSizeException e) { 450 // should not occur, handled with length check above 451 throw new InvalidKeyException("Unwrapping failed", e); 452 } 453 454 if (isTlsRsaPremasterSecret) { 455 if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { 456 throw new IllegalStateException( 457 "No TlsRsaPremasterSecretParameterSpec specified"); 458 } 459 460 // polish the TLS premaster secret 461 encoded = KeyUtil.checkTlsPreMasterSecretKey( 462 ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), 463 ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), 464 random, encoded, (failover != null)); 465 } 466 467 return ConstructKeys.constructKey(encoded, algorithm, type); 468 } 469 470 // see JCE spec 471 protected int engineGetKeySize(Key key) throws InvalidKeyException { 472 RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); 473 return rsaKey.getModulus().bitLength(); 474 } 475 }