1 /* 2 * Copyright (c) 2005, 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.mscapi; 27 28 import java.nio.ByteBuffer; 29 import java.security.*; 30 import java.security.spec.AlgorithmParameterSpec; 31 import java.math.BigInteger; 32 33 import sun.security.rsa.RSAKeyFactory; 34 35 /** 36 * RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding. 37 * 38 * Objects should be instantiated by calling Signature.getInstance() using the 39 * following algorithm names: 40 * 41 * . "NONEwithRSA" 42 * . "SHA1withRSA" 43 * . "SHA256withRSA" 44 * . "SHA384withRSA" 45 * . "SHA512withRSA" 46 * . "MD5withRSA" 47 * . "MD2withRSA" 48 * 49 * NOTE: RSA keys must be at least 512 bits long. 50 * 51 * NOTE: NONEwithRSA must be supplied with a pre-computed message digest. 52 * Only the following digest algorithms are supported: MD5, SHA-1, 53 * SHA-256, SHA-384, SHA-512 and a special-purpose digest 54 * algorithm which is a concatenation of SHA-1 and MD5 digests. 55 * 56 * @since 1.6 57 * @author Stanley Man-Kit Ho 58 */ 59 abstract class RSASignature extends java.security.SignatureSpi 60 { 61 // message digest implementation we use 62 private final MessageDigest messageDigest; 63 64 // message digest name 65 private String messageDigestAlgorithm; 66 67 // flag indicating whether the digest has been reset 68 private boolean needsReset; 69 70 // the signing key 71 private Key privateKey = null; 72 73 // the verification key 74 private Key publicKey = null; 75 76 /** 77 * Constructs a new RSASignature. Used by Raw subclass. 78 */ 79 RSASignature() { 80 messageDigest = null; 81 messageDigestAlgorithm = null; 82 } 83 84 /** 85 * Constructs a new RSASignature. Used by subclasses. 86 */ 87 RSASignature(String digestName) { 88 89 try { 90 messageDigest = MessageDigest.getInstance(digestName); 91 // Get the digest's canonical name 92 messageDigestAlgorithm = messageDigest.getAlgorithm(); 93 94 } catch (NoSuchAlgorithmException e) { 95 throw new ProviderException(e); 96 } 97 98 needsReset = false; 99 } 100 101 // Nested class for NONEwithRSA signatures 102 public static final class Raw extends RSASignature { 103 104 // the longest supported digest is 512 bits (SHA-512) 105 private static final int RAW_RSA_MAX = 64; 106 107 private final byte[] precomputedDigest; 108 private int offset = 0; 109 110 public Raw() { 111 precomputedDigest = new byte[RAW_RSA_MAX]; 112 } 113 114 // Stores the precomputed message digest value. 115 @Override 116 protected void engineUpdate(byte b) throws SignatureException { 117 if (offset >= precomputedDigest.length) { 118 offset = RAW_RSA_MAX + 1; 119 return; 120 } 121 precomputedDigest[offset++] = b; 122 } 123 124 // Stores the precomputed message digest value. 125 @Override 126 protected void engineUpdate(byte[] b, int off, int len) 127 throws SignatureException { 128 if (offset + len > precomputedDigest.length) { 129 offset = RAW_RSA_MAX + 1; 130 return; 131 } 132 System.arraycopy(b, off, precomputedDigest, offset, len); 133 offset += len; 134 } 135 136 // Stores the precomputed message digest value. 137 @Override 138 protected void engineUpdate(ByteBuffer byteBuffer) { 139 int len = byteBuffer.remaining(); 140 if (len <= 0) { 141 return; 142 } 143 if (offset + len > precomputedDigest.length) { 144 offset = RAW_RSA_MAX + 1; 145 return; 146 } 147 byteBuffer.get(precomputedDigest, offset, len); 148 offset += len; 149 } 150 151 @Override 152 protected void resetDigest(){ 153 offset = 0; 154 } 155 156 // Returns the precomputed message digest value. 157 @Override 158 protected byte[] getDigestValue() throws SignatureException { 159 if (offset > RAW_RSA_MAX) { 160 throw new SignatureException("Message digest is too long"); 161 } 162 163 // Determine the digest algorithm from the digest length 164 if (offset == 20) { 165 setDigestName("SHA1"); 166 } else if (offset == 36) { 167 setDigestName("SHA1+MD5"); 168 } else if (offset == 32) { 169 setDigestName("SHA-256"); 170 } else if (offset == 48) { 171 setDigestName("SHA-384"); 172 } else if (offset == 64) { 173 setDigestName("SHA-512"); 174 } else if (offset == 16) { 175 setDigestName("MD5"); 176 } else { 177 throw new SignatureException( 178 "Message digest length is not supported"); 179 } 180 181 byte[] result = new byte[offset]; 182 System.arraycopy(precomputedDigest, 0, result, 0, offset); 183 offset = 0; 184 185 return result; 186 } 187 } 188 189 public static final class SHA1 extends RSASignature { 190 public SHA1() { 191 super("SHA1"); 192 } 193 } 194 195 public static final class SHA256 extends RSASignature { 196 public SHA256() { 197 super("SHA-256"); 198 } 199 } 200 201 public static final class SHA384 extends RSASignature { 202 public SHA384() { 203 super("SHA-384"); 204 } 205 } 206 207 public static final class SHA512 extends RSASignature { 208 public SHA512() { 209 super("SHA-512"); 210 } 211 } 212 213 public static final class MD5 extends RSASignature { 214 public MD5() { 215 super("MD5"); 216 } 217 } 218 219 public static final class MD2 extends RSASignature { 220 public MD2() { 221 super("MD2"); 222 } 223 } 224 225 // initialize for signing. See JCA doc 226 @Override 227 protected void engineInitVerify(PublicKey key) 228 throws InvalidKeyException 229 { 230 // This signature accepts only RSAPublicKey 231 if ((key instanceof java.security.interfaces.RSAPublicKey) == false) { 232 throw new InvalidKeyException("Key type not supported"); 233 } 234 235 java.security.interfaces.RSAPublicKey rsaKey = 236 (java.security.interfaces.RSAPublicKey) key; 237 238 if ((key instanceof sun.security.mscapi.RSAPublicKey) == false) { 239 240 // convert key to MSCAPI format 241 242 BigInteger modulus = rsaKey.getModulus(); 243 BigInteger exponent = rsaKey.getPublicExponent(); 244 245 // Check against the local and global values to make sure 246 // the sizes are ok. Round up to the nearest byte. 247 RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7), 248 exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX); 249 250 byte[] modulusBytes = modulus.toByteArray(); 251 byte[] exponentBytes = exponent.toByteArray(); 252 253 // Adjust key length due to sign bit 254 int keyBitLength = (modulusBytes[0] == 0) 255 ? (modulusBytes.length - 1) * 8 256 : modulusBytes.length * 8; 257 258 byte[] keyBlob = generatePublicKeyBlob( 259 keyBitLength, modulusBytes, exponentBytes); 260 261 try { 262 publicKey = importPublicKey(keyBlob, keyBitLength); 263 264 } catch (KeyStoreException e) { 265 throw new InvalidKeyException(e); 266 } 267 268 } else { 269 publicKey = (sun.security.mscapi.RSAPublicKey) key; 270 } 271 272 this.privateKey = null; 273 resetDigest(); 274 } 275 276 // initialize for signing. See JCA doc 277 @Override 278 protected void engineInitSign(PrivateKey key) throws InvalidKeyException 279 { 280 // This signature accepts only RSAPrivateKey 281 if ((key instanceof sun.security.mscapi.RSAPrivateKey) == false) { 282 throw new InvalidKeyException("Key type not supported"); 283 } 284 privateKey = (sun.security.mscapi.RSAPrivateKey) key; 285 286 // Check against the local and global values to make sure 287 // the sizes are ok. Round up to nearest byte. 288 RSAKeyFactory.checkKeyLengths(((privateKey.length() + 7) & ~7), 289 null, RSAKeyPairGenerator.KEY_SIZE_MIN, 290 RSAKeyPairGenerator.KEY_SIZE_MAX); 291 292 this.publicKey = null; 293 resetDigest(); 294 } 295 296 /** 297 * Resets the message digest if needed. 298 */ 299 protected void resetDigest() { 300 if (needsReset) { 301 messageDigest.reset(); 302 needsReset = false; 303 } 304 } 305 306 protected byte[] getDigestValue() throws SignatureException { 307 needsReset = false; 308 return messageDigest.digest(); 309 } 310 311 protected void setDigestName(String name) { 312 messageDigestAlgorithm = name; 313 } 314 315 /** 316 * Updates the data to be signed or verified 317 * using the specified byte. 318 * 319 * @param b the byte to use for the update. 320 * 321 * @exception SignatureException if the engine is not initialized 322 * properly. 323 */ 324 @Override 325 protected void engineUpdate(byte b) throws SignatureException 326 { 327 messageDigest.update(b); 328 needsReset = true; 329 } 330 331 /** 332 * Updates the data to be signed or verified, using the 333 * specified array of bytes, starting at the specified offset. 334 * 335 * @param b the array of bytes 336 * @param off the offset to start from in the array of bytes 337 * @param len the number of bytes to use, starting at offset 338 * 339 * @exception SignatureException if the engine is not initialized 340 * properly 341 */ 342 @Override 343 protected void engineUpdate(byte[] b, int off, int len) 344 throws SignatureException 345 { 346 messageDigest.update(b, off, len); 347 needsReset = true; 348 } 349 350 /** 351 * Updates the data to be signed or verified, using the 352 * specified ByteBuffer. 353 * 354 * @param input the ByteBuffer 355 */ 356 @Override 357 protected void engineUpdate(ByteBuffer input) 358 { 359 messageDigest.update(input); 360 needsReset = true; 361 } 362 363 /** 364 * Returns the signature bytes of all the data 365 * updated so far. 366 * The format of the signature depends on the underlying 367 * signature scheme. 368 * 369 * @return the signature bytes of the signing operation's result. 370 * 371 * @exception SignatureException if the engine is not 372 * initialized properly or if this signature algorithm is unable to 373 * process the input data provided. 374 */ 375 @Override 376 protected byte[] engineSign() throws SignatureException { 377 378 byte[] hash = getDigestValue(); 379 380 // Omit the hash OID when generating a Raw signature 381 boolean noHashOID = this instanceof Raw; 382 383 // Sign hash using MS Crypto APIs 384 385 byte[] result = signHash(noHashOID, hash, hash.length, 386 messageDigestAlgorithm, privateKey.getHCryptProvider(), 387 privateKey.getHCryptKey()); 388 389 // Convert signature array from little endian to big endian 390 return convertEndianArray(result); 391 } 392 393 /** 394 * Convert array from big endian to little endian, or vice versa. 395 */ 396 private byte[] convertEndianArray(byte[] byteArray) 397 { 398 if (byteArray == null || byteArray.length == 0) 399 return byteArray; 400 401 byte [] retval = new byte[byteArray.length]; 402 403 // make it big endian 404 for (int i=0;i < byteArray.length;i++) 405 retval[i] = byteArray[byteArray.length - i - 1]; 406 407 return retval; 408 } 409 410 /** 411 * Sign hash using Microsoft Crypto API with HCRYPTKEY. 412 * The returned data is in little-endian. 413 */ 414 private native static byte[] signHash(boolean noHashOID, byte[] hash, 415 int hashSize, String hashAlgorithm, long hCryptProv, long hCryptKey) 416 throws SignatureException; 417 418 /** 419 * Verify a signed hash using Microsoft Crypto API with HCRYPTKEY. 420 */ 421 private native static boolean verifySignedHash(byte[] hash, int hashSize, 422 String hashAlgorithm, byte[] signature, int signatureSize, 423 long hCryptProv, long hCryptKey) throws SignatureException; 424 425 /** 426 * Verifies the passed-in signature. 427 * 428 * @param sigBytes the signature bytes to be verified. 429 * 430 * @return true if the signature was verified, false if not. 431 * 432 * @exception SignatureException if the engine is not 433 * initialized properly, the passed-in signature is improperly 434 * encoded or of the wrong type, if this signature algorithm is unable to 435 * process the input data provided, etc. 436 */ 437 @Override 438 protected boolean engineVerify(byte[] sigBytes) 439 throws SignatureException 440 { 441 byte[] hash = getDigestValue(); 442 443 return verifySignedHash(hash, hash.length, 444 messageDigestAlgorithm, convertEndianArray(sigBytes), 445 sigBytes.length, publicKey.getHCryptProvider(), 446 publicKey.getHCryptKey()); 447 } 448 449 /** 450 * Sets the specified algorithm parameter to the specified 451 * value. This method supplies a general-purpose mechanism through 452 * which it is possible to set the various parameters of this object. 453 * A parameter may be any settable parameter for the algorithm, such as 454 * a parameter size, or a source of random bits for signature generation 455 * (if appropriate), or an indication of whether or not to perform 456 * a specific but optional computation. A uniform algorithm-specific 457 * naming scheme for each parameter is desirable but left unspecified 458 * at this time. 459 * 460 * @param param the string identifier of the parameter. 461 * 462 * @param value the parameter value. 463 * 464 * @exception InvalidParameterException if <code>param</code> is an 465 * invalid parameter for this signature algorithm engine, 466 * the parameter is already set 467 * and cannot be set again, a security exception occurs, and so on. 468 * 469 * @deprecated Replaced by {@link 470 * #engineSetParameter(java.security.spec.AlgorithmParameterSpec) 471 * engineSetParameter}. 472 */ 473 @Override 474 @Deprecated 475 protected void engineSetParameter(String param, Object value) 476 throws InvalidParameterException 477 { 478 throw new InvalidParameterException("Parameter not supported"); 479 } 480 481 /** 482 * Sets this signature engine with the specified algorithm parameter. 483 * 484 * @param params the parameters 485 * 486 * @exception InvalidAlgorithmParameterException if the given 487 * parameter is invalid 488 */ 489 @Override 490 protected void engineSetParameter(AlgorithmParameterSpec params) 491 throws InvalidAlgorithmParameterException 492 { 493 if (params != null) { 494 throw new InvalidAlgorithmParameterException("No parameter accepted"); 495 } 496 } 497 498 /** 499 * Gets the value of the specified algorithm parameter. 500 * This method supplies a general-purpose mechanism through which it 501 * is possible to get the various parameters of this object. A parameter 502 * may be any settable parameter for the algorithm, such as a parameter 503 * size, or a source of random bits for signature generation (if 504 * appropriate), or an indication of whether or not to perform a 505 * specific but optional computation. A uniform algorithm-specific 506 * naming scheme for each parameter is desirable but left unspecified 507 * at this time. 508 * 509 * @param param the string name of the parameter. 510 * 511 * @return the object that represents the parameter value, or null if 512 * there is none. 513 * 514 * @exception InvalidParameterException if <code>param</code> is an 515 * invalid parameter for this engine, or another exception occurs while 516 * trying to get this parameter. 517 * 518 * @deprecated 519 */ 520 @Override 521 @Deprecated 522 protected Object engineGetParameter(String param) 523 throws InvalidParameterException 524 { 525 throw new InvalidParameterException("Parameter not supported"); 526 } 527 528 /** 529 * Gets the algorithm parameter from this signature engine. 530 * 531 * @return the parameter, or null if no parameter is used. 532 */ 533 @Override 534 protected AlgorithmParameters engineGetParameters() { 535 return null; 536 } 537 538 /** 539 * Generates a public-key BLOB from a key's components. 540 */ 541 // used by RSACipher 542 static native byte[] generatePublicKeyBlob( 543 int keyBitLength, byte[] modulus, byte[] publicExponent) 544 throws InvalidKeyException; 545 546 /** 547 * Imports a public-key BLOB. 548 */ 549 // used by RSACipher 550 static native RSAPublicKey importPublicKey(byte[] keyBlob, int keySize) 551 throws KeyStoreException; 552 }