1 /* 2 * Copyright (c) 2003, 2018, 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 sun.security.rsa; 27 28 import java.util.*; 29 30 import java.security.*; 31 import java.security.spec.*; 32 33 import javax.crypto.BadPaddingException; 34 import javax.crypto.spec.PSource; 35 import javax.crypto.spec.OAEPParameterSpec; 36 37 import sun.security.jca.JCAUtil; 38 39 /** 40 * RSA padding and unpadding. 41 * 42 * The various PKCS#1 versions can be found in the IETF RFCs 43 * tracking the corresponding PKCS#1 standards. 44 * 45 * RFC 2313: PKCS#1 v1.5 46 * RFC 2437: PKCS#1 v2.0 47 * RFC 3447: PKCS#1 v2.1 48 * RFC 8017: PKCS#1 v2.2 49 * 50 * The format of PKCS#1 v1.5 padding is: 51 * 52 * 0x00 | BT | PS...PS | 0x00 | data...data 53 * 54 * where BT is the blocktype (1 or 2). The length of the entire string 55 * must be the same as the size of the modulus (i.e. 128 byte for a 1024 bit 56 * key). Per spec, the padding string must be at least 8 bytes long. That 57 * leaves up to (length of key in bytes) - 11 bytes for the data. 58 * 59 * OAEP padding was introduced in PKCS#1 v2.0 and is a bit more complicated 60 * and has a number of options. We support: 61 * 62 * . arbitrary hash functions ('Hash' in the specification), MessageDigest 63 * implementation must be available 64 * . MGF1 as the mask generation function 65 * . the empty string as the default value for label L and whatever 66 * specified in javax.crypto.spec.OAEPParameterSpec 67 * 68 * The algorithms (representations) are forwards-compatible: that is, 69 * the algorithm described in previous releases are in later releases. 70 * However, additional comments/checks/clarifications were added to the 71 * later versions based on real-world experience (e.g. stricter v1.5 72 * format checking.) 73 * 74 * Note: RSA keys should be at least 512 bits long 75 * 76 * @since 1.5 77 * @author Andreas Sterbenz 78 */ 79 public final class RSAPadding { 80 81 // NOTE: the constants below are embedded in the JCE RSACipher class 82 // file. Do not change without coordinating the update 83 84 // PKCS#1 v1.5 padding, blocktype 1 (signing) 85 public static final int PAD_BLOCKTYPE_1 = 1; 86 // PKCS#1 v1.5 padding, blocktype 2 (encryption) 87 public static final int PAD_BLOCKTYPE_2 = 2; 88 // nopadding. Does not do anything, but allows simpler RSACipher code 89 public static final int PAD_NONE = 3; 90 // PKCS#1 v2.1 OAEP padding 91 public static final int PAD_OAEP_MGF1 = 4; 92 93 // type, one of PAD_* 94 private final int type; 95 96 // size of the padded block (i.e. size of the modulus) 97 private final int paddedSize; 98 99 // PRNG used to generate padding bytes (PAD_BLOCKTYPE_2, PAD_OAEP_MGF1) 100 private SecureRandom random; 101 102 // maximum size of the data 103 private final int maxDataSize; 104 105 // OAEP: main message digest 106 private MessageDigest md; 107 108 // OAEP: MGF1 109 private MGF1 mgf; 110 111 // OAEP: value of digest of data (user-supplied or zero-length) using md 112 private byte[] lHash; 113 114 /** 115 * Get a RSAPadding instance of the specified type. 116 * Keys used with this padding must be paddedSize bytes long. 117 */ 118 public static RSAPadding getInstance(int type, int paddedSize) 119 throws InvalidKeyException, InvalidAlgorithmParameterException { 120 return new RSAPadding(type, paddedSize, null, null); 121 } 122 123 /** 124 * Get a RSAPadding instance of the specified type. 125 * Keys used with this padding must be paddedSize bytes long. 126 */ 127 public static RSAPadding getInstance(int type, int paddedSize, 128 SecureRandom random) throws InvalidKeyException, 129 InvalidAlgorithmParameterException { 130 return new RSAPadding(type, paddedSize, random, null); 131 } 132 133 /** 134 * Get a RSAPadding instance of the specified type, which must be 135 * OAEP. Keys used with this padding must be paddedSize bytes long. 136 */ 137 public static RSAPadding getInstance(int type, int paddedSize, 138 SecureRandom random, OAEPParameterSpec spec) 139 throws InvalidKeyException, InvalidAlgorithmParameterException { 140 return new RSAPadding(type, paddedSize, random, spec); 141 } 142 143 // internal constructor 144 private RSAPadding(int type, int paddedSize, SecureRandom random, 145 OAEPParameterSpec spec) throws InvalidKeyException, 146 InvalidAlgorithmParameterException { 147 this.type = type; 148 this.paddedSize = paddedSize; 149 this.random = random; 150 if (paddedSize < 64) { 151 // sanity check, already verified in RSASignature/RSACipher 152 throw new InvalidKeyException("Padded size must be at least 64"); 153 } 154 switch (type) { 155 case PAD_BLOCKTYPE_1: 156 case PAD_BLOCKTYPE_2: 157 maxDataSize = paddedSize - 11; 158 break; 159 case PAD_NONE: 160 maxDataSize = paddedSize; 161 break; 162 case PAD_OAEP_MGF1: 163 String mdName = "SHA-1"; 164 String mgfMdName = mdName; 165 byte[] digestInput = null; 166 try { 167 if (spec != null) { 168 mdName = spec.getDigestAlgorithm(); 169 String mgfName = spec.getMGFAlgorithm(); 170 if (!mgfName.equalsIgnoreCase("MGF1")) { 171 throw new InvalidAlgorithmParameterException 172 ("Unsupported MGF algo: " + mgfName); 173 } 174 mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters()) 175 .getDigestAlgorithm(); 176 PSource pSrc = spec.getPSource(); 177 String pSrcAlgo = pSrc.getAlgorithm(); 178 if (!pSrcAlgo.equalsIgnoreCase("PSpecified")) { 179 throw new InvalidAlgorithmParameterException 180 ("Unsupported pSource algo: " + pSrcAlgo); 181 } 182 digestInput = ((PSource.PSpecified) pSrc).getValue(); 183 } 184 md = MessageDigest.getInstance(mdName); 185 mgf = new MGF1(mgfMdName); 186 } catch (NoSuchAlgorithmException e) { 187 throw new InvalidKeyException("Digest not available", e); 188 } 189 lHash = getInitialHash(md, digestInput); 190 int digestLen = lHash.length; 191 maxDataSize = paddedSize - 2 - 2 * digestLen; 192 if (maxDataSize <= 0) { 193 throw new InvalidKeyException 194 ("Key is too short for encryption using OAEPPadding" + 195 " with " + mdName + " and " + mgf.getName()); 196 } 197 break; 198 default: 199 throw new InvalidKeyException("Invalid padding: " + type); 200 } 201 } 202 203 // cache of hashes of zero length data 204 private static final Map<String,byte[]> emptyHashes = 205 Collections.synchronizedMap(new HashMap<String,byte[]>()); 206 207 /** 208 * Return the value of the digest using the specified message digest 209 * <code>md</code> and the digest input <code>digestInput</code>. 210 * if <code>digestInput</code> is null or 0-length, zero length 211 * is used to generate the initial digest. 212 * Note: the md object must be in reset state 213 */ 214 private static byte[] getInitialHash(MessageDigest md, 215 byte[] digestInput) { 216 byte[] result; 217 if ((digestInput == null) || (digestInput.length == 0)) { 218 String digestName = md.getAlgorithm(); 219 result = emptyHashes.get(digestName); 220 if (result == null) { 221 result = md.digest(); 222 emptyHashes.put(digestName, result); 223 } 224 } else { 225 result = md.digest(digestInput); 226 } 227 return result; 228 } 229 230 /** 231 * Return the maximum size of the plaintext data that can be processed 232 * using this object. 233 */ 234 public int getMaxDataSize() { 235 return maxDataSize; 236 } 237 238 /** 239 * Pad the data and return the padded block. 240 */ 241 public byte[] pad(byte[] data, int ofs, int len) 242 throws BadPaddingException { 243 return pad(RSACore.convert(data, ofs, len)); 244 } 245 246 /** 247 * Pad the data and return the padded block. 248 */ 249 public byte[] pad(byte[] data) throws BadPaddingException { 250 if (data.length > maxDataSize) { 251 throw new BadPaddingException("Data must be shorter than " 252 + (maxDataSize + 1) + " bytes but received " 253 + data.length + " bytes."); 254 } 255 switch (type) { 256 case PAD_NONE: 257 return data; 258 case PAD_BLOCKTYPE_1: 259 case PAD_BLOCKTYPE_2: 260 return padV15(data); 261 case PAD_OAEP_MGF1: 262 return padOAEP(data); 263 default: 264 throw new AssertionError(); 265 } 266 } 267 268 /** 269 * Unpad the padded block and return the data. 270 */ 271 public byte[] unpad(byte[] padded, int ofs, int len) 272 throws BadPaddingException { 273 return unpad(RSACore.convert(padded, ofs, len)); 274 } 275 276 /** 277 * Unpad the padded block and return the data. 278 */ 279 public byte[] unpad(byte[] padded) throws BadPaddingException { 280 if (padded.length != paddedSize) { 281 throw new BadPaddingException("Decryption error." + 282 "The padded array length (" + padded.length + 283 ") is not the specified padded size (" + paddedSize + ")"); 284 } 285 switch (type) { 286 case PAD_NONE: 287 return padded; 288 case PAD_BLOCKTYPE_1: 289 case PAD_BLOCKTYPE_2: 290 return unpadV15(padded); 291 case PAD_OAEP_MGF1: 292 return unpadOAEP(padded); 293 default: 294 throw new AssertionError(); 295 } 296 } 297 298 /** 299 * PKCS#1 v1.5 padding (blocktype 1 and 2). 300 */ 301 private byte[] padV15(byte[] data) throws BadPaddingException { 302 byte[] padded = new byte[paddedSize]; 303 System.arraycopy(data, 0, padded, paddedSize - data.length, 304 data.length); 305 int psSize = paddedSize - 3 - data.length; 306 int k = 0; 307 padded[k++] = 0; 308 padded[k++] = (byte)type; 309 if (type == PAD_BLOCKTYPE_1) { 310 // blocktype 1: all padding bytes are 0xff 311 while (psSize-- > 0) { 312 padded[k++] = (byte)0xff; 313 } 314 } else { 315 // blocktype 2: padding bytes are random non-zero bytes 316 if (random == null) { 317 random = JCAUtil.getSecureRandom(); 318 } 319 // generate non-zero padding bytes 320 // use a buffer to reduce calls to SecureRandom 321 while (psSize > 0) { 322 // extra bytes to avoid zero bytes, 323 // number of zero bytes <= 4 in 98% cases 324 byte[] r = new byte[psSize + 4]; 325 random.nextBytes(r); 326 for (int i = 0; i < r.length && psSize > 0; i++) { 327 if (r[i] != 0) { 328 padded[k++] = r[i]; 329 psSize--; 330 } 331 } 332 } 333 } 334 return padded; 335 } 336 337 /** 338 * PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)). 339 * 340 * Note that we want to make it a constant-time operation 341 */ 342 private byte[] unpadV15(byte[] padded) throws BadPaddingException { 343 int k = 0; 344 boolean bp = false; 345 346 if (padded[k++] != 0) { 347 bp = true; 348 } 349 if (padded[k++] != type) { 350 bp = true; 351 } 352 int p = 0; 353 while (k < padded.length) { 354 int b = padded[k++] & 0xff; 355 if ((b == 0) && (p == 0)) { 356 p = k; 357 } 358 if ((k == padded.length) && (p == 0)) { 359 bp = true; 360 } 361 if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) && 362 (p == 0)) { 363 bp = true; 364 } 365 } 366 int n = padded.length - p; 367 if (n > maxDataSize) { 368 bp = true; 369 } 370 371 // copy useless padding array for a constant-time method 372 byte[] padding = new byte[p]; 373 System.arraycopy(padded, 0, padding, 0, p); 374 375 byte[] data = new byte[n]; 376 System.arraycopy(padded, p, data, 0, n); 377 378 BadPaddingException bpe = new BadPaddingException("Decryption error"); 379 380 if (bp) { 381 throw bpe; 382 } else { 383 return data; 384 } 385 } 386 387 /** 388 * PKCS#1 v2.0 OAEP padding (MGF1). 389 * Paragraph references refer to PKCS#1 v2.1 (June 14, 2002) 390 */ 391 private byte[] padOAEP(byte[] M) throws BadPaddingException { 392 if (random == null) { 393 random = JCAUtil.getSecureRandom(); 394 } 395 int hLen = lHash.length; 396 397 // 2.d: generate a random octet string seed of length hLen 398 // if necessary 399 byte[] seed = new byte[hLen]; 400 random.nextBytes(seed); 401 402 // buffer for encoded message EM 403 byte[] EM = new byte[paddedSize]; 404 405 // start and length of seed (as index into EM) 406 int seedStart = 1; 407 int seedLen = hLen; 408 409 // copy seed into EM 410 System.arraycopy(seed, 0, EM, seedStart, seedLen); 411 412 // start and length of data block DB in EM 413 // we place it inside of EM to reduce copying 414 int dbStart = hLen + 1; 415 int dbLen = EM.length - dbStart; 416 417 // start of message M in EM 418 int mStart = paddedSize - M.length; 419 420 // build DB 421 // 2.b: Concatenate lHash, PS, a single octet with hexadecimal value 422 // 0x01, and the message M to form a data block DB of length 423 // k - hLen -1 octets as DB = lHash || PS || 0x01 || M 424 // (note that PS is all zeros) 425 System.arraycopy(lHash, 0, EM, dbStart, hLen); 426 EM[mStart - 1] = 1; 427 System.arraycopy(M, 0, EM, mStart, M.length); 428 429 // produce maskedDB 430 mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart); 431 432 // produce maskSeed 433 mgf.generateAndXor(EM, dbStart, dbLen, seedLen, EM, seedStart); 434 435 return EM; 436 } 437 438 /** 439 * PKCS#1 v2.1 OAEP unpadding (MGF1). 440 */ 441 private byte[] unpadOAEP(byte[] padded) throws BadPaddingException { 442 byte[] EM = padded; 443 boolean bp = false; 444 int hLen = lHash.length; 445 446 if (EM[0] != 0) { 447 bp = true; 448 } 449 450 int seedStart = 1; 451 int seedLen = hLen; 452 453 int dbStart = hLen + 1; 454 int dbLen = EM.length - dbStart; 455 456 mgf.generateAndXor(EM, dbStart, dbLen, seedLen, EM, seedStart); 457 mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart); 458 459 // verify lHash == lHash' 460 for (int i = 0; i < hLen; i++) { 461 if (lHash[i] != EM[dbStart + i]) { 462 bp = true; 463 } 464 } 465 466 int padStart = dbStart + hLen; 467 int onePos = -1; 468 469 for (int i = padStart; i < EM.length; i++) { 470 int value = EM[i]; 471 if (onePos == -1) { 472 if (value == 0x00) { 473 // continue; 474 } else if (value == 0x01) { 475 onePos = i; 476 } else { // Anything other than {0,1} is bad. 477 bp = true; 478 } 479 } 480 } 481 482 // We either ran off the rails or found something other than 0/1. 483 if (onePos == -1) { 484 bp = true; 485 onePos = EM.length - 1; // Don't inadvertently return any data. 486 } 487 488 int mStart = onePos + 1; 489 490 // copy useless padding array for a constant-time method 491 byte [] tmp = new byte[mStart - padStart]; 492 System.arraycopy(EM, padStart, tmp, 0, tmp.length); 493 494 byte [] m = new byte[EM.length - mStart]; 495 System.arraycopy(EM, mStart, m, 0, m.length); 496 497 BadPaddingException bpe = new BadPaddingException("Decryption error"); 498 499 if (bp) { 500 throw bpe; 501 } else { 502 return m; 503 } 504 } 505 }