1 /* 2 * Copyright (c) 2003, 2014, 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", 187 SunJCE.getInstance()); 188 params.init(spec); 189 return params; 190 } catch (NoSuchAlgorithmException nsae) { 191 // should never happen 192 throw new RuntimeException("Cannot find OAEP " + 193 " AlgorithmParameters implementation in SunJCE provider"); 194 } catch (InvalidParameterSpecException ipse) { 195 // should never happen 196 throw new RuntimeException("OAEPParameterSpec not supported"); 197 } 198 } else { 199 return null; 200 } 201 } 202 203 // see JCE spec 204 protected void engineInit(int opmode, Key key, SecureRandom random) 205 throws InvalidKeyException { 206 try { 207 init(opmode, key, random, null); 208 } catch (InvalidAlgorithmParameterException iape) { 209 // never thrown when null parameters are used; 210 // but re-throw it just in case 211 InvalidKeyException ike = 212 new InvalidKeyException("Wrong parameters"); 213 ike.initCause(iape); 214 throw ike; 215 } 216 } 217 218 // see JCE spec 219 protected void engineInit(int opmode, Key key, 220 AlgorithmParameterSpec params, SecureRandom random) 221 throws InvalidKeyException, InvalidAlgorithmParameterException { 222 init(opmode, key, random, params); 223 } 224 225 // see JCE spec 226 protected void engineInit(int opmode, Key key, 227 AlgorithmParameters params, SecureRandom random) 228 throws InvalidKeyException, InvalidAlgorithmParameterException { 229 if (params == null) { 230 init(opmode, key, random, null); 231 } else { 232 try { 233 OAEPParameterSpec spec = 234 params.getParameterSpec(OAEPParameterSpec.class); 235 init(opmode, key, random, spec); 236 } catch (InvalidParameterSpecException ipse) { 237 InvalidAlgorithmParameterException iape = 238 new InvalidAlgorithmParameterException("Wrong parameter"); 239 iape.initCause(ipse); 240 throw iape; 241 } 242 } 243 } 244 245 // initialize this cipher 246 private void init(int opmode, Key key, SecureRandom random, 247 AlgorithmParameterSpec params) 248 throws InvalidKeyException, InvalidAlgorithmParameterException { 249 boolean encrypt; 250 switch (opmode) { 251 case Cipher.ENCRYPT_MODE: 252 case Cipher.WRAP_MODE: 253 encrypt = true; 254 break; 255 case Cipher.DECRYPT_MODE: 256 case Cipher.UNWRAP_MODE: 257 encrypt = false; 258 break; 259 default: 260 throw new InvalidKeyException("Unknown mode: " + opmode); 261 } 262 RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); 263 if (key instanceof RSAPublicKey) { 264 mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY; 265 publicKey = (RSAPublicKey)key; 266 privateKey = null; 267 } else { // must be RSAPrivateKey per check in toRSAKey 268 mode = encrypt ? MODE_SIGN : MODE_DECRYPT; 269 privateKey = (RSAPrivateKey)key; 270 publicKey = null; 271 } 272 int n = RSACore.getByteLength(rsaKey.getModulus()); 273 outputSize = n; 274 bufOfs = 0; 275 if (paddingType == PAD_NONE) { 276 if (params != null) { 277 throw new InvalidAlgorithmParameterException 278 ("Parameters not supported"); 279 } 280 padding = RSAPadding.getInstance(RSAPadding.PAD_NONE, n, random); 281 buffer = new byte[n]; 282 } else if (paddingType == PAD_PKCS1) { 283 if (params != null) { 284 if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { 285 throw new InvalidAlgorithmParameterException( 286 "Parameters not supported"); 287 } 288 289 spec = params; 290 this.random = random; // for TLS RSA premaster secret 291 } 292 int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2 293 : RSAPadding.PAD_BLOCKTYPE_1; 294 padding = RSAPadding.getInstance(blockType, n, random); 295 if (encrypt) { 296 int k = padding.getMaxDataSize(); 297 buffer = new byte[k]; 298 } else { 299 buffer = new byte[n]; 300 } 301 } else { // PAD_OAEP_MGF1 302 if ((mode == MODE_SIGN) || (mode == MODE_VERIFY)) { 303 throw new InvalidKeyException 304 ("OAEP cannot be used to sign or verify signatures"); 305 } 306 if (params != null) { 307 if (!(params instanceof OAEPParameterSpec)) { 308 throw new InvalidAlgorithmParameterException 309 ("Wrong Parameters for OAEP Padding"); 310 } 311 spec = params; 312 } else { 313 spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", 314 MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); 315 } 316 padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n, 317 random, (OAEPParameterSpec)spec); 318 if (encrypt) { 319 int k = padding.getMaxDataSize(); 320 buffer = new byte[k]; 321 } else { 322 buffer = new byte[n]; 323 } 324 } 325 } 326 327 // internal update method 328 private void update(byte[] in, int inOfs, int inLen) { 329 if ((inLen == 0) || (in == null)) { 330 return; 331 } 332 if (bufOfs + inLen > buffer.length) { 333 bufOfs = buffer.length + 1; 334 return; 335 } 336 System.arraycopy(in, inOfs, buffer, bufOfs, inLen); 337 bufOfs += inLen; 338 } 339 340 // internal doFinal() method. Here we perform the actual RSA operation 341 private byte[] doFinal() throws BadPaddingException, 342 IllegalBlockSizeException { 343 if (bufOfs > buffer.length) { 344 throw new IllegalBlockSizeException("Data must not be longer " 345 + "than " + buffer.length + " bytes"); 346 } 347 try { 348 byte[] data; 349 switch (mode) { 350 case MODE_SIGN: 351 data = padding.pad(buffer, 0, bufOfs); 352 return RSACore.rsa(data, privateKey); 353 case MODE_VERIFY: 354 byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs); 355 data = RSACore.rsa(verifyBuffer, publicKey); 356 return padding.unpad(data); 357 case MODE_ENCRYPT: 358 data = padding.pad(buffer, 0, bufOfs); 359 return RSACore.rsa(data, publicKey); 360 case MODE_DECRYPT: 361 byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); 362 data = RSACore.rsa(decryptBuffer, privateKey); 363 return padding.unpad(data); 364 default: 365 throw new AssertionError("Internal error"); 366 } 367 } finally { 368 bufOfs = 0; 369 } 370 } 371 372 // see JCE spec 373 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) { 374 update(in, inOfs, inLen); 375 return B0; 376 } 377 378 // see JCE spec 379 protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out, 380 int outOfs) { 381 update(in, inOfs, inLen); 382 return 0; 383 } 384 385 // see JCE spec 386 protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) 387 throws BadPaddingException, IllegalBlockSizeException { 388 update(in, inOfs, inLen); 389 return doFinal(); 390 } 391 392 // see JCE spec 393 protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, 394 int outOfs) throws ShortBufferException, BadPaddingException, 395 IllegalBlockSizeException { 396 if (outputSize > out.length - outOfs) { 397 throw new ShortBufferException 398 ("Need " + outputSize + " bytes for output"); 399 } 400 update(in, inOfs, inLen); 401 byte[] result = doFinal(); 402 int n = result.length; 403 System.arraycopy(result, 0, out, outOfs, n); 404 return n; 405 } 406 407 // see JCE spec 408 protected byte[] engineWrap(Key key) throws InvalidKeyException, 409 IllegalBlockSizeException { 410 byte[] encoded = key.getEncoded(); 411 if ((encoded == null) || (encoded.length == 0)) { 412 throw new InvalidKeyException("Could not obtain encoded key"); 413 } 414 if (encoded.length > buffer.length) { 415 throw new InvalidKeyException("Key is too long for wrapping"); 416 } 417 update(encoded, 0, encoded.length); 418 try { 419 return doFinal(); 420 } catch (BadPaddingException e) { 421 // should not occur 422 throw new InvalidKeyException("Wrapping failed", e); 423 } 424 } 425 426 // see JCE spec 427 protected Key engineUnwrap(byte[] wrappedKey, String algorithm, 428 int type) throws InvalidKeyException, NoSuchAlgorithmException { 429 if (wrappedKey.length > buffer.length) { 430 throw new InvalidKeyException("Key is too long for unwrapping"); 431 } 432 433 boolean isTlsRsaPremasterSecret = 434 algorithm.equals("TlsRsaPremasterSecret"); 435 Exception failover = null; 436 byte[] encoded = null; 437 438 update(wrappedKey, 0, wrappedKey.length); 439 try { 440 encoded = doFinal(); 441 } catch (BadPaddingException e) { 442 if (isTlsRsaPremasterSecret) { 443 failover = e; 444 } else { 445 throw new InvalidKeyException("Unwrapping failed", e); 446 } 447 } catch (IllegalBlockSizeException e) { 448 // should not occur, handled with length check above 449 throw new InvalidKeyException("Unwrapping failed", e); 450 } 451 452 if (isTlsRsaPremasterSecret) { 453 if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { 454 throw new IllegalStateException( 455 "No TlsRsaPremasterSecretParameterSpec specified"); 456 } 457 458 // polish the TLS premaster secret 459 encoded = KeyUtil.checkTlsPreMasterSecretKey( 460 ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), 461 ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), 462 random, encoded, (failover != null)); 463 } 464 465 return ConstructKeys.constructKey(encoded, algorithm, type); 466 } 467 468 // see JCE spec 469 protected int engineGetKeySize(Key key) throws InvalidKeyException { 470 RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); 471 return rsaKey.getModulus().bitLength(); 472 } 473 }