1 /*
2 * Copyright (c) 2005, 2012, 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.PublicKey;
30 import java.security.PrivateKey;
31 import java.security.InvalidKeyException;
32 import java.security.InvalidParameterException;
33 import java.security.KeyStoreException;
34 import java.security.NoSuchAlgorithmException;
35 import java.security.ProviderException;
36 import java.security.MessageDigest;
37 import java.security.SignatureException;
38 import java.math.BigInteger;
39
40 import sun.security.rsa.RSAKeyFactory;
41
42 /**
43 * RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
44 *
45 * Objects should be instantiated by calling Signature.getInstance() using the
46 * following algorithm names:
47 *
48 * . "NONEwithRSA"
49 * . "SHA1withRSA"
50 * . "SHA256withRSA"
51 * . "SHA384withRSA"
52 * . "SHA512withRSA"
53 * . "MD5withRSA"
54 * . "MD2withRSA"
55 *
56 * NOTE: RSA keys must be at least 512 bits long.
57 *
213
214 public static final class SHA512 extends RSASignature {
215 public SHA512() {
216 super("SHA-512");
217 }
218 }
219
220 public static final class MD5 extends RSASignature {
221 public MD5() {
222 super("MD5");
223 }
224 }
225
226 public static final class MD2 extends RSASignature {
227 public MD2() {
228 super("MD2");
229 }
230 }
231
232 // initialize for signing. See JCA doc
233 protected void engineInitVerify(PublicKey key)
234 throws InvalidKeyException
235 {
236 // This signature accepts only RSAPublicKey
237 if ((key instanceof java.security.interfaces.RSAPublicKey) == false) {
238 throw new InvalidKeyException("Key type not supported");
239 }
240
241 java.security.interfaces.RSAPublicKey rsaKey =
242 (java.security.interfaces.RSAPublicKey) key;
243
244 if ((key instanceof sun.security.mscapi.RSAPublicKey) == false) {
245
246 // convert key to MSCAPI format
247
248 BigInteger modulus = rsaKey.getModulus();
249 BigInteger exponent = rsaKey.getPublicExponent();
250
251 // Check against the local and global values to make sure
252 // the sizes are ok. Round up to the nearest byte.
263
264 byte[] keyBlob = generatePublicKeyBlob(
265 keyBitLength, modulusBytes, exponentBytes);
266
267 try {
268 publicKey = importPublicKey(keyBlob, keyBitLength);
269
270 } catch (KeyStoreException e) {
271 throw new InvalidKeyException(e);
272 }
273
274 } else {
275 publicKey = (sun.security.mscapi.RSAPublicKey) key;
276 }
277
278 this.privateKey = null;
279 resetDigest();
280 }
281
282 // initialize for signing. See JCA doc
283 protected void engineInitSign(PrivateKey key) throws InvalidKeyException
284 {
285 // This signature accepts only RSAPrivateKey
286 if ((key instanceof sun.security.mscapi.RSAPrivateKey) == false) {
287 throw new InvalidKeyException("Key type not supported");
288 }
289 privateKey = (sun.security.mscapi.RSAPrivateKey) key;
290
291 // Check against the local and global values to make sure
292 // the sizes are ok. Round up to nearest byte.
293 RSAKeyFactory.checkKeyLengths(((privateKey.length() + 7) & ~7),
294 null, RSAKeyPairGenerator.KEY_SIZE_MIN,
295 RSAKeyPairGenerator.KEY_SIZE_MAX);
296
297 this.publicKey = null;
298 resetDigest();
299 }
300
301 /**
302 * Resets the message digest if needed.
309 }
310
311 protected byte[] getDigestValue() throws SignatureException {
312 needsReset = false;
313 return messageDigest.digest();
314 }
315
316 protected void setDigestName(String name) {
317 messageDigestAlgorithm = name;
318 }
319
320 /**
321 * Updates the data to be signed or verified
322 * using the specified byte.
323 *
324 * @param b the byte to use for the update.
325 *
326 * @exception SignatureException if the engine is not initialized
327 * properly.
328 */
329 protected void engineUpdate(byte b) throws SignatureException
330 {
331 messageDigest.update(b);
332 needsReset = true;
333 }
334
335 /**
336 * Updates the data to be signed or verified, using the
337 * specified array of bytes, starting at the specified offset.
338 *
339 * @param b the array of bytes
340 * @param off the offset to start from in the array of bytes
341 * @param len the number of bytes to use, starting at offset
342 *
343 * @exception SignatureException if the engine is not initialized
344 * properly
345 */
346 protected void engineUpdate(byte[] b, int off, int len)
347 throws SignatureException
348 {
349 messageDigest.update(b, off, len);
350 needsReset = true;
351 }
352
353 /**
354 * Updates the data to be signed or verified, using the
355 * specified ByteBuffer.
356 *
357 * @param input the ByteBuffer
358 */
359 protected void engineUpdate(ByteBuffer input)
360 {
361 messageDigest.update(input);
362 needsReset = true;
363 }
364
365 /**
366 * Returns the signature bytes of all the data
367 * updated so far.
368 * The format of the signature depends on the underlying
369 * signature scheme.
370 *
371 * @return the signature bytes of the signing operation's result.
372 *
373 * @exception SignatureException if the engine is not
374 * initialized properly or if this signature algorithm is unable to
375 * process the input data provided.
376 */
377 protected byte[] engineSign() throws SignatureException {
378
379 byte[] hash = getDigestValue();
380
381 // Omit the hash OID when generating a Raw signature
382 boolean noHashOID = this instanceof Raw;
383
384 // Sign hash using MS Crypto APIs
385
386 byte[] result = signHash(noHashOID, hash, hash.length,
387 messageDigestAlgorithm, privateKey.getHCryptProvider(),
388 privateKey.getHCryptKey());
389
390 // Convert signature array from little endian to big endian
391 return convertEndianArray(result);
392 }
393
394 /**
395 * Convert array from big endian to little endian, or vice versa.
396 */
418
419 /**
420 * Verify a signed hash using Microsoft Crypto API with HCRYPTKEY.
421 */
422 private native static boolean verifySignedHash(byte[] hash, int hashSize,
423 String hashAlgorithm, byte[] signature, int signatureSize,
424 long hCryptProv, long hCryptKey) throws SignatureException;
425
426 /**
427 * Verifies the passed-in signature.
428 *
429 * @param sigBytes the signature bytes to be verified.
430 *
431 * @return true if the signature was verified, false if not.
432 *
433 * @exception SignatureException if the engine is not
434 * initialized properly, the passed-in signature is improperly
435 * encoded or of the wrong type, if this signature algorithm is unable to
436 * process the input data provided, etc.
437 */
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 @Deprecated
474 protected void engineSetParameter(String param, Object value)
475 throws InvalidParameterException
476 {
477 throw new InvalidParameterException("Parameter not supported");
478 }
479
480
481 /**
482 * Gets the value of the specified algorithm parameter.
483 * This method supplies a general-purpose mechanism through which it
484 * is possible to get the various parameters of this object. A parameter
485 * may be any settable parameter for the algorithm, such as a parameter
486 * size, or a source of random bits for signature generation (if
487 * appropriate), or an indication of whether or not to perform a
488 * specific but optional computation. A uniform algorithm-specific
489 * naming scheme for each parameter is desirable but left unspecified
490 * at this time.
491 *
492 * @param param the string name of the parameter.
493 *
494 * @return the object that represents the parameter value, or null if
495 * there is none.
496 *
497 * @exception InvalidParameterException if <code>param</code> is an
498 * invalid parameter for this engine, or another exception occurs while
499 * trying to get this parameter.
500 *
501 * @deprecated
502 */
503 @Deprecated
504 protected Object engineGetParameter(String param)
505 throws InvalidParameterException
506 {
507 throw new InvalidParameterException("Parameter not supported");
508 }
509
510 /**
511 * Generates a public-key BLOB from a key's components.
512 */
513 // used by RSACipher
514 static native byte[] generatePublicKeyBlob(
515 int keyBitLength, byte[] modulus, byte[] publicExponent)
516 throws InvalidKeyException;
517
518 /**
519 * Imports a public-key BLOB.
520 */
521 // used by RSACipher
522 static native RSAPublicKey importPublicKey(byte[] keyBlob, int keySize)
523 throws KeyStoreException;
524 }
|
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 *
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.
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.
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 */
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 }
|