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