1 /*
   2  * Copyright (c) 1996, 2019, 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 java.security;
  27 
  28 import java.security.spec.AlgorithmParameterSpec;
  29 import java.util.*;
  30 import java.util.concurrent.ConcurrentHashMap;
  31 import java.io.*;
  32 import java.security.cert.Certificate;
  33 import java.security.cert.X509Certificate;
  34 
  35 import java.nio.ByteBuffer;
  36 
  37 import java.security.Provider.Service;
  38 
  39 import javax.crypto.Cipher;
  40 import javax.crypto.IllegalBlockSizeException;
  41 import javax.crypto.BadPaddingException;
  42 import javax.crypto.NoSuchPaddingException;
  43 import jdk.internal.access.JavaSecuritySignatureAccess;
  44 import jdk.internal.access.SharedSecrets;
  45 
  46 import sun.security.util.Debug;
  47 import sun.security.jca.*;
  48 import sun.security.jca.GetInstance.Instance;
  49 
  50 /**
  51  * The Signature class is used to provide applications the functionality
  52  * of a digital signature algorithm. Digital signatures are used for
  53  * authentication and integrity assurance of digital data.
  54  *
  55  * <p> The signature algorithm can be, among others, the NIST standard
  56  * DSA, using DSA and SHA-256. The DSA algorithm using the
  57  * SHA-256 message digest algorithm can be specified as {@code SHA256withDSA}.
  58  * In the case of RSA the signing algorithm could be specified as, for example,
  59  * {@code SHA256withRSA}.
  60  * The algorithm name must be specified, as there is no default.
  61  *
  62  * <p> A Signature object can be used to generate and verify digital
  63  * signatures.
  64  *
  65  * <p> There are three phases to the use of a Signature object for
  66  * either signing data or verifying a signature:<ol>
  67  *
  68  * <li>Initialization, with either
  69  *
  70  *     <ul>
  71  *
  72  *     <li>a public key, which initializes the signature for
  73  *     verification (see {@link #initVerify(PublicKey) initVerify}), or
  74  *
  75  *     <li>a private key (and optionally a Secure Random Number Generator),
  76  *     which initializes the signature for signing
  77  *     (see {@link #initSign(PrivateKey)}
  78  *     and {@link #initSign(PrivateKey, SecureRandom)}).
  79  *
  80  *     </ul>
  81  *
  82  * <li>Updating
  83  *
  84  * <p>Depending on the type of initialization, this will update the
  85  * bytes to be signed or verified. See the
  86  * {@link #update(byte) update} methods.
  87  *
  88  * <li>Signing or Verifying a signature on all updated bytes. See the
  89  * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
  90  * method.
  91  *
  92  * </ol>
  93  *
  94  * <p>Note that this class is abstract and extends from
  95  * {@code SignatureSpi} for historical reasons.
  96  * Application developers should only take notice of the methods defined in
  97  * this {@code Signature} class; all the methods in
  98  * the superclass are intended for cryptographic service providers who wish to
  99  * supply their own implementations of digital signature algorithms.
 100  *
 101  * <p> Every implementation of the Java platform is required to support the
 102  * following standard {@code Signature} algorithms:
 103  * <ul>
 104  * <li>{@code SHA1withDSA}</li>
 105  * <li>{@code SHA256withDSA}</li>
 106  * <li>{@code SHA1withRSA}</li>
 107  * <li>{@code SHA256withRSA}</li>
 108  * </ul>
 109  * These algorithms are described in the <a href=
 110  * "{@docRoot}/../specs/security/standard-names.html#signature-algorithms">
 111  * Signature section</a> of the
 112  * Java Security Standard Algorithm Names Specification.
 113  * Consult the release documentation for your implementation to see if any
 114  * other algorithms are supported.
 115  *
 116  * @author Benjamin Renaud
 117  * @since 1.1
 118  *
 119  */
 120 
 121 public abstract class Signature extends SignatureSpi {
 122 
 123     static {
 124         SharedSecrets.setJavaSecuritySignatureAccess(
 125             new JavaSecuritySignatureAccess() {
 126                 @Override
 127                 public void initVerify(Signature s, PublicKey publicKey,
 128                         AlgorithmParameterSpec params)
 129                         throws InvalidKeyException,
 130                         InvalidAlgorithmParameterException {
 131                     s.initVerify(publicKey, params);
 132                 }
 133                 @Override
 134                 public void initVerify(Signature s,
 135                         java.security.cert.Certificate certificate,
 136                         AlgorithmParameterSpec params)
 137                         throws InvalidKeyException,
 138                         InvalidAlgorithmParameterException {
 139                     s.initVerify(certificate, params);
 140                 }
 141                 @Override
 142                 public void initSign(Signature s, PrivateKey privateKey,
 143                         AlgorithmParameterSpec params, SecureRandom random)
 144                         throws InvalidKeyException,
 145                         InvalidAlgorithmParameterException {
 146                     s.initSign(privateKey, params, random);
 147                 }
 148         });
 149     }
 150 
 151     private static final Debug debug =
 152                         Debug.getInstance("jca", "Signature");
 153 
 154     private static final Debug pdebug =
 155                         Debug.getInstance("provider", "Provider");
 156     private static final boolean skipDebug =
 157         Debug.isOn("engine=") && !Debug.isOn("signature");
 158 
 159     /*
 160      * The algorithm for this signature object.
 161      * This value is used to map an OID to the particular algorithm.
 162      * The mapping is done in AlgorithmObject.algOID(String algorithm)
 163      */
 164     private String algorithm;
 165 
 166     // The provider
 167     Provider provider;
 168 
 169     /**
 170      * Possible {@link #state} value, signifying that
 171      * this signature object has not yet been initialized.
 172      */
 173     protected static final int UNINITIALIZED = 0;
 174 
 175     /**
 176      * Possible {@link #state} value, signifying that
 177      * this signature object has been initialized for signing.
 178      */
 179     protected static final int SIGN = 2;
 180 
 181     /**
 182      * Possible {@link #state} value, signifying that
 183      * this signature object has been initialized for verification.
 184      */
 185     protected static final int VERIFY = 3;
 186 
 187     /**
 188      * Current state of this signature object.
 189      */
 190     protected int state = UNINITIALIZED;
 191 
 192     /**
 193      * Creates a Signature object for the specified algorithm.
 194      *
 195      * @param algorithm the standard string name of the algorithm.
 196      * See the Signature section in the <a href=
 197      * "{@docRoot}/../specs/security/standard-names.html#signature-algorithms">
 198      * Java Security Standard Algorithm Names Specification</a>
 199      * for information about standard algorithm names.
 200      */
 201     protected Signature(String algorithm) {
 202         this.algorithm = algorithm;
 203     }
 204 
 205     // name of the special signature alg
 206     private static final String RSA_SIGNATURE = "NONEwithRSA";
 207 
 208     // name of the equivalent cipher alg
 209     private static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
 210 
 211     // all the services we need to lookup for compatibility with Cipher
 212     private static final List<ServiceId> rsaIds = List.of(
 213         new ServiceId("Signature", "NONEwithRSA"),
 214         new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
 215         new ServiceId("Cipher", "RSA/ECB"),
 216         new ServiceId("Cipher", "RSA//PKCS1Padding"),
 217         new ServiceId("Cipher", "RSA"));
 218 
 219     /**
 220      * Returns a Signature object that implements the specified signature
 221      * algorithm.
 222      *
 223      * <p> This method traverses the list of registered security Providers,
 224      * starting with the most preferred Provider.
 225      * A new Signature object encapsulating the
 226      * SignatureSpi implementation from the first
 227      * Provider that supports the specified algorithm is returned.
 228      *
 229      * <p> Note that the list of registered providers may be retrieved via
 230      * the {@link Security#getProviders() Security.getProviders()} method.
 231      *
 232      * @implNote
 233      * The JDK Reference Implementation additionally uses the
 234      * {@code jdk.security.provider.preferred}
 235      * {@link Security#getProperty(String) Security} property to determine
 236      * the preferred provider order for the specified algorithm. This
 237      * may be different than the order of providers returned by
 238      * {@link Security#getProviders() Security.getProviders()}.
 239      *
 240      * @param algorithm the standard name of the algorithm requested.
 241      * See the Signature section in the <a href=
 242      * "{@docRoot}/../specs/security/standard-names.html#signature-algorithms">
 243      * Java Security Standard Algorithm Names Specification</a>
 244      * for information about standard algorithm names.
 245      *
 246      * @return the new {@code Signature} object
 247      *
 248      * @throws NoSuchAlgorithmException if no {@code Provider} supports a
 249      *         {@code Signature} implementation for the
 250      *         specified algorithm
 251      *
 252      * @throws NullPointerException if {@code algorithm} is {@code null}
 253      *
 254      * @see Provider
 255      */
 256     public static Signature getInstance(String algorithm)
 257             throws NoSuchAlgorithmException {
 258         Objects.requireNonNull(algorithm, "null algorithm name");
 259         List<Service> list;
 260         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
 261             list = GetInstance.getServices(rsaIds);
 262         } else {
 263             list = GetInstance.getServices("Signature", algorithm);
 264         }
 265         Iterator<Service> t = list.iterator();
 266         if (t.hasNext() == false) {
 267             throw new NoSuchAlgorithmException
 268                 (algorithm + " Signature not available");
 269         }
 270         // try services until we find an Spi or a working Signature subclass
 271         NoSuchAlgorithmException failure;
 272         do {
 273             Service s = t.next();
 274             if (isSpi(s)) {
 275                 return new Delegate(s, t, algorithm);
 276             } else {
 277                 // must be a subclass of Signature, disable dynamic selection
 278                 try {
 279                     Instance instance =
 280                         GetInstance.getInstance(s, SignatureSpi.class);
 281                     return getInstance(instance, algorithm);
 282                 } catch (NoSuchAlgorithmException e) {
 283                     failure = e;
 284                 }
 285             }
 286         } while (t.hasNext());
 287         throw failure;
 288     }
 289 
 290     private static Signature getInstance(Instance instance, String algorithm) {
 291         Signature sig;
 292         if (instance.impl instanceof Signature) {
 293             sig = (Signature)instance.impl;
 294             sig.algorithm = algorithm;
 295         } else {
 296             SignatureSpi spi = (SignatureSpi)instance.impl;
 297             sig = new Delegate(spi, algorithm);
 298         }
 299         sig.provider = instance.provider;
 300         return sig;
 301     }
 302 
 303     private static final Map<String,Boolean> signatureInfo;
 304 
 305     static {
 306         signatureInfo = new ConcurrentHashMap<>();
 307         Boolean TRUE = Boolean.TRUE;
 308         // pre-initialize with values for our SignatureSpi implementations
 309         signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
 310         signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
 311         signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
 312         signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
 313         signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
 314         signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
 315         signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
 316         signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
 317         signatureInfo.put("sun.security.rsa.RSAPSSSignature", TRUE);
 318         signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
 319     }
 320 
 321     private static boolean isSpi(Service s) {
 322         if (s.getType().equals("Cipher")) {
 323             // must be a CipherSpi, which we can wrap with the CipherAdapter
 324             return true;
 325         }
 326         String className = s.getClassName();
 327         Boolean result = signatureInfo.get(className);
 328         if (result == null) {
 329             try {
 330                 Object instance = s.newInstance(null);
 331                 // Signature extends SignatureSpi
 332                 // so it is a "real" Spi if it is an
 333                 // instance of SignatureSpi but not Signature
 334                 boolean r = (instance instanceof SignatureSpi)
 335                                 && (instance instanceof Signature == false);
 336                 if ((debug != null) && (r == false)) {
 337                     debug.println("Not a SignatureSpi " + className);
 338                     debug.println("Delayed provider selection may not be "
 339                         + "available for algorithm " + s.getAlgorithm());
 340                 }
 341                 result = Boolean.valueOf(r);
 342                 signatureInfo.put(className, result);
 343             } catch (Exception e) {
 344                 // something is wrong, assume not an SPI
 345                 return false;
 346             }
 347         }
 348         return result.booleanValue();
 349     }
 350 
 351     /**
 352      * Returns a Signature object that implements the specified signature
 353      * algorithm.
 354      *
 355      * <p> A new Signature object encapsulating the
 356      * SignatureSpi implementation from the specified provider
 357      * is returned.  The specified provider must be registered
 358      * in the security provider list.
 359      *
 360      * <p> Note that the list of registered providers may be retrieved via
 361      * the {@link Security#getProviders() Security.getProviders()} method.
 362      *
 363      * @param algorithm the name of the algorithm requested.
 364      * See the Signature section in the <a href=
 365      * "{@docRoot}/../specs/security/standard-names.html#signature-algorithms">
 366      * Java Security Standard Algorithm Names Specification</a>
 367      * for information about standard algorithm names.
 368      *
 369      * @param provider the name of the provider.
 370      *
 371      * @return the new {@code Signature} object
 372      *
 373      * @throws IllegalArgumentException if the provider name is {@code null}
 374      *         or empty
 375      *
 376      * @throws NoSuchAlgorithmException if a {@code SignatureSpi}
 377      *         implementation for the specified algorithm is not
 378      *         available from the specified provider
 379      *
 380      * @throws NoSuchProviderException if the specified provider is not
 381      *         registered in the security provider list
 382      *
 383      * @throws NullPointerException if {@code algorithm} is {@code null}
 384      *
 385      * @see Provider
 386      */
 387     public static Signature getInstance(String algorithm, String provider)
 388             throws NoSuchAlgorithmException, NoSuchProviderException {
 389         Objects.requireNonNull(algorithm, "null algorithm name");
 390         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
 391             // exception compatibility with existing code
 392             if (provider == null || provider.isEmpty()) {
 393                 throw new IllegalArgumentException("missing provider");
 394             }
 395             Provider p = Security.getProvider(provider);
 396             if (p == null) {
 397                 throw new NoSuchProviderException
 398                     ("no such provider: " + provider);
 399             }
 400             return getInstanceRSA(p);
 401         }
 402         Instance instance = GetInstance.getInstance
 403                 ("Signature", SignatureSpi.class, algorithm, provider);
 404         return getInstance(instance, algorithm);
 405     }
 406 
 407     /**
 408      * Returns a Signature object that implements the specified
 409      * signature algorithm.
 410      *
 411      * <p> A new Signature object encapsulating the
 412      * SignatureSpi implementation from the specified Provider
 413      * object is returned.  Note that the specified Provider object
 414      * does not have to be registered in the provider list.
 415      *
 416      * @param algorithm the name of the algorithm requested.
 417      * See the Signature section in the <a href=
 418      * "{@docRoot}/../specs/security/standard-names.html#signature-algorithms">
 419      * Java Security Standard Algorithm Names Specification</a>
 420      * for information about standard algorithm names.
 421      *
 422      * @param provider the provider.
 423      *
 424      * @return the new {@code Signature} object
 425      *
 426      * @throws IllegalArgumentException if the provider is {@code null}
 427      *
 428      * @throws NoSuchAlgorithmException if a {@code SignatureSpi}
 429      *         implementation for the specified algorithm is not available
 430      *         from the specified {@code Provider} object
 431      *
 432      * @throws NullPointerException if {@code algorithm} is {@code null}
 433      *
 434      * @see Provider
 435      *
 436      * @since 1.4
 437      */
 438     public static Signature getInstance(String algorithm, Provider provider)
 439             throws NoSuchAlgorithmException {
 440         Objects.requireNonNull(algorithm, "null algorithm name");
 441         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
 442             // exception compatibility with existing code
 443             if (provider == null) {
 444                 throw new IllegalArgumentException("missing provider");
 445             }
 446             return getInstanceRSA(provider);
 447         }
 448         Instance instance = GetInstance.getInstance
 449                 ("Signature", SignatureSpi.class, algorithm, provider);
 450         return getInstance(instance, algorithm);
 451     }
 452 
 453     // return an implementation for NONEwithRSA, which is a special case
 454     // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper
 455     private static Signature getInstanceRSA(Provider p)
 456             throws NoSuchAlgorithmException {
 457         // try Signature first
 458         Service s = p.getService("Signature", RSA_SIGNATURE);
 459         if (s != null) {
 460             Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
 461             return getInstance(instance, RSA_SIGNATURE);
 462         }
 463         // check Cipher
 464         try {
 465             Cipher c = Cipher.getInstance(RSA_CIPHER, p);
 466             return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
 467         } catch (GeneralSecurityException e) {
 468             // throw Signature style exception message to avoid confusion,
 469             // but append Cipher exception as cause
 470             throw new NoSuchAlgorithmException("no such algorithm: "
 471                 + RSA_SIGNATURE + " for provider " + p.getName(), e);
 472         }
 473     }
 474 
 475     /**
 476      * Returns the provider of this signature object.
 477      *
 478      * @return the provider of this signature object
 479      */
 480     public final Provider getProvider() {
 481         chooseFirstProvider();
 482         return this.provider;
 483     }
 484 
 485     private String getProviderName() {
 486         return (provider == null)  ? "(no provider)" : provider.getName();
 487     }
 488 
 489     void chooseFirstProvider() {
 490         // empty, overridden in Delegate
 491     }
 492 
 493     /**
 494      * Initializes this object for verification. If this method is called
 495      * again with a different argument, it negates the effect
 496      * of this call.
 497      *
 498      * @param publicKey the public key of the identity whose signature is
 499      * going to be verified.
 500      *
 501      * @exception InvalidKeyException if the key is invalid.
 502      */
 503     public final void initVerify(PublicKey publicKey)
 504             throws InvalidKeyException {
 505         engineInitVerify(publicKey);
 506         state = VERIFY;
 507 
 508         if (!skipDebug && pdebug != null) {
 509             pdebug.println("Signature." + algorithm +
 510                 " verification algorithm from: " + getProviderName());
 511         }
 512     }
 513 
 514     /**
 515      * Initialize this object for verification. If this method is called
 516      * again with different arguments, it negates the effect
 517      * of this call.
 518      *
 519      * @param publicKey the public key of the identity whose signature is
 520      * going to be verified.
 521      * @param params the parameters used for verifying this signature.
 522      *
 523      * @exception InvalidKeyException if the key is invalid.
 524      * @exception InvalidAlgorithmParameterException if the params is invalid.
 525      */
 526     final void initVerify(PublicKey publicKey, AlgorithmParameterSpec params)
 527             throws InvalidKeyException, InvalidAlgorithmParameterException {
 528         engineInitVerify(publicKey, params);
 529         state = VERIFY;
 530 
 531         if (!skipDebug && pdebug != null) {
 532             pdebug.println("Signature." + algorithm +
 533                 " verification algorithm from: " + getProviderName());
 534         }
 535     }
 536 
 537     private static PublicKey getPublicKeyFromCert(Certificate cert)
 538             throws InvalidKeyException {
 539         // If the certificate is of type X509Certificate,
 540         // we should check whether it has a Key Usage
 541         // extension marked as critical.
 542         //if (cert instanceof java.security.cert.X509Certificate) {
 543         if (cert instanceof X509Certificate) {
 544             // Check whether the cert has a key usage extension
 545             // marked as a critical extension.
 546             // The OID for KeyUsage extension is 2.5.29.15.
 547             X509Certificate c = (X509Certificate)cert;
 548             Set<String> critSet = c.getCriticalExtensionOIDs();
 549 
 550             if (critSet != null && !critSet.isEmpty()
 551                 && critSet.contains("2.5.29.15")) {
 552                 boolean[] keyUsageInfo = c.getKeyUsage();
 553                 // keyUsageInfo[0] is for digitalSignature.
 554                 if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
 555                     throw new InvalidKeyException("Wrong key usage");
 556             }
 557         }
 558         return cert.getPublicKey();
 559     }
 560 
 561     /**
 562      * Initializes this object for verification, using the public key from
 563      * the given certificate.
 564      * <p>If the certificate is of type X.509 and has a <i>key usage</i>
 565      * extension field marked as critical, and the value of the <i>key usage</i>
 566      * extension field implies that the public key in
 567      * the certificate and its corresponding private key are not
 568      * supposed to be used for digital signatures, an
 569      * {@code InvalidKeyException} is thrown.
 570      *
 571      * @param certificate the certificate of the identity whose signature is
 572      * going to be verified.
 573      *
 574      * @exception InvalidKeyException  if the public key in the certificate
 575      * is not encoded properly or does not include required  parameter
 576      * information or cannot be used for digital signature purposes.
 577      * @since 1.3
 578      */
 579     public final void initVerify(Certificate certificate)
 580             throws InvalidKeyException {
 581         engineInitVerify(getPublicKeyFromCert(certificate));
 582         state = VERIFY;
 583 
 584         if (!skipDebug && pdebug != null) {
 585             pdebug.println("Signature." + algorithm +
 586                 " verification algorithm from: " + getProviderName());
 587         }
 588     }
 589 
 590     /**
 591      * Initializes this object for verification, using the public key from
 592      * the given certificate.
 593      * <p>If the certificate is of type X.509 and has a <i>key usage</i>
 594      * extension field marked as critical, and the value of the <i>key usage</i>
 595      * extension field implies that the public key in
 596      * the certificate and its corresponding private key are not
 597      * supposed to be used for digital signatures, an
 598      * {@code InvalidKeyException} is thrown.
 599      *
 600      * @param certificate the certificate of the identity whose signature is
 601      * going to be verified.
 602      * @param params the parameters used for verifying this signature.
 603      *
 604      * @exception InvalidKeyException  if the public key in the certificate
 605      * is not encoded properly or does not include required  parameter
 606      * information or cannot be used for digital signature purposes.
 607      * @exception InvalidAlgorithmParameterException if the params is invalid.
 608      *
 609      * @since 13
 610      */
 611     final void initVerify(Certificate certificate,
 612             AlgorithmParameterSpec params)
 613             throws InvalidKeyException, InvalidAlgorithmParameterException {
 614         engineInitVerify(getPublicKeyFromCert(certificate), params);
 615         state = VERIFY;
 616 
 617         if (!skipDebug && pdebug != null) {
 618             pdebug.println("Signature." + algorithm +
 619                 " verification algorithm from: " + getProviderName());
 620         }
 621     }
 622 
 623     /**
 624      * Initialize this object for signing. If this method is called
 625      * again with a different argument, it negates the effect
 626      * of this call.
 627      *
 628      * @param privateKey the private key of the identity whose signature
 629      * is going to be generated.
 630      *
 631      * @exception InvalidKeyException if the key is invalid.
 632      */
 633     public final void initSign(PrivateKey privateKey)
 634             throws InvalidKeyException {
 635         engineInitSign(privateKey);
 636         state = SIGN;
 637 
 638         if (!skipDebug && pdebug != null) {
 639             pdebug.println("Signature." + algorithm +
 640                 " signing algorithm from: " + getProviderName());
 641         }
 642     }
 643 
 644     /**
 645      * Initialize this object for signing. If this method is called
 646      * again with a different argument, it negates the effect
 647      * of this call.
 648      *
 649      * @param privateKey the private key of the identity whose signature
 650      * is going to be generated.
 651      *
 652      * @param random the source of randomness for this signature.
 653      *
 654      * @exception InvalidKeyException if the key is invalid.
 655      */
 656     public final void initSign(PrivateKey privateKey, SecureRandom random)
 657             throws InvalidKeyException {
 658         engineInitSign(privateKey, random);
 659         state = SIGN;
 660 
 661         if (!skipDebug && pdebug != null) {
 662             pdebug.println("Signature." + algorithm +
 663                 " signing algorithm from: " + getProviderName());
 664         }
 665     }
 666 
 667     /**
 668      * Initialize this object for signing. If this method is called
 669      * again with different arguments, it negates the effect
 670      * of this call.
 671      *
 672      * @param privateKey the private key of the identity whose signature
 673      * is going to be generated.
 674      * @param params the parameters used for generating signature.
 675      * @param random the source of randomness for this signature.
 676      *
 677      * @exception InvalidKeyException if the key is invalid.
 678      * @exception InvalidAlgorithmParameterException if the params is invalid
 679      */
 680     final void initSign(PrivateKey privateKey,
 681             AlgorithmParameterSpec params, SecureRandom random)
 682             throws InvalidKeyException, InvalidAlgorithmParameterException {
 683         engineInitSign(privateKey, params, random);
 684         state = SIGN;
 685 
 686         if (!skipDebug && pdebug != null) {
 687             pdebug.println("Signature." + algorithm +
 688                 " signing algorithm from: " + getProviderName());
 689         }
 690     }
 691 
 692     /**
 693      * Returns the signature bytes of all the data updated.
 694      * The format of the signature depends on the underlying
 695      * signature scheme.
 696      *
 697      * <p>A call to this method resets this signature object to the state
 698      * it was in when previously initialized for signing via a
 699      * call to {@code initSign(PrivateKey)}. That is, the object is
 700      * reset and available to generate another signature from the same
 701      * signer, if desired, via new calls to {@code update} and
 702      * {@code sign}.
 703      *
 704      * @return the signature bytes of the signing operation's result.
 705      *
 706      * @exception SignatureException if this signature object is not
 707      * initialized properly or if this signature algorithm is unable to
 708      * process the input data provided.
 709      */
 710     public final byte[] sign() throws SignatureException {
 711         if (state == SIGN) {
 712             return engineSign();
 713         }
 714         throw new SignatureException("object not initialized for " +
 715                                      "signing");
 716     }
 717 
 718     /**
 719      * Finishes the signature operation and stores the resulting signature
 720      * bytes in the provided buffer {@code outbuf}, starting at
 721      * {@code offset}.
 722      * The format of the signature depends on the underlying
 723      * signature scheme.
 724      *
 725      * <p>This signature object is reset to its initial state (the state it
 726      * was in after a call to one of the {@code initSign} methods) and
 727      * can be reused to generate further signatures with the same private key.
 728      *
 729      * @param outbuf buffer for the signature result.
 730      *
 731      * @param offset offset into {@code outbuf} where the signature is
 732      * stored.
 733      *
 734      * @param len number of bytes within {@code outbuf} allotted for the
 735      * signature.
 736      *
 737      * @return the number of bytes placed into {@code outbuf}.
 738      *
 739      * @exception SignatureException if this signature object is not
 740      *     initialized properly, if this signature algorithm is unable to
 741      *     process the input data provided, or if {@code len} is less
 742      *     than the actual signature length.
 743      * @exception IllegalArgumentException if {@code outbuf} is {@code null},
 744      *     or {@code offset} or {@code len} is less than 0, or the sum of
 745      *     {@code offset} and {@code len} is greater than the length of
 746      *     {@code outbuf}.
 747      *
 748      * @since 1.2
 749      */
 750     public final int sign(byte[] outbuf, int offset, int len)
 751         throws SignatureException {
 752         if (outbuf == null) {
 753             throw new IllegalArgumentException("No output buffer given");
 754         }
 755         if (offset < 0 || len < 0) {
 756             throw new IllegalArgumentException("offset or len is less than 0");
 757         }
 758         if (outbuf.length - offset < len) {
 759             throw new IllegalArgumentException
 760                 ("Output buffer too small for specified offset and length");
 761         }
 762         if (state != SIGN) {
 763             throw new SignatureException("object not initialized for " +
 764                                          "signing");
 765         }
 766         return engineSign(outbuf, offset, len);
 767     }
 768 
 769     /**
 770      * Verifies the passed-in signature.
 771      *
 772      * <p>A call to this method resets this signature object to the state
 773      * it was in when previously initialized for verification via a
 774      * call to {@code initVerify(PublicKey)}. That is, the object is
 775      * reset and available to verify another signature from the identity
 776      * whose public key was specified in the call to {@code initVerify}.
 777      *
 778      * @param signature the signature bytes to be verified.
 779      *
 780      * @return true if the signature was verified, false if not.
 781      *
 782      * @exception SignatureException if this signature object is not
 783      * initialized properly, the passed-in signature is improperly
 784      * encoded or of the wrong type, if this signature algorithm is unable to
 785      * process the input data provided, etc.
 786      */
 787     public final boolean verify(byte[] signature) throws SignatureException {
 788         if (state == VERIFY) {
 789             return engineVerify(signature);
 790         }
 791         throw new SignatureException("object not initialized for " +
 792                                      "verification");
 793     }
 794 
 795     /**
 796      * Verifies the passed-in signature in the specified array
 797      * of bytes, starting at the specified offset.
 798      *
 799      * <p>A call to this method resets this signature object to the state
 800      * it was in when previously initialized for verification via a
 801      * call to {@code initVerify(PublicKey)}. That is, the object is
 802      * reset and available to verify another signature from the identity
 803      * whose public key was specified in the call to {@code initVerify}.
 804      *
 805      *
 806      * @param signature the signature bytes to be verified.
 807      * @param offset the offset to start from in the array of bytes.
 808      * @param length the number of bytes to use, starting at offset.
 809      *
 810      * @return true if the signature was verified, false if not.
 811      *
 812      * @exception SignatureException if this signature object is not
 813      * initialized properly, the passed-in signature is improperly
 814      * encoded or of the wrong type, if this signature algorithm is unable to
 815      * process the input data provided, etc.
 816      * @exception IllegalArgumentException if the {@code signature}
 817      * byte array is {@code null}, or the {@code offset} or {@code length}
 818      * is less than 0, or the sum of the {@code offset} and
 819      * {@code length} is greater than the length of the
 820      * {@code signature} byte array.
 821      * @since 1.4
 822      */
 823     public final boolean verify(byte[] signature, int offset, int length)
 824         throws SignatureException {
 825         if (state == VERIFY) {
 826             if (signature == null) {
 827                 throw new IllegalArgumentException("signature is null");
 828             }
 829             if (offset < 0 || length < 0) {
 830                 throw new IllegalArgumentException
 831                     ("offset or length is less than 0");
 832             }
 833             if (signature.length - offset < length) {
 834                 throw new IllegalArgumentException
 835                     ("signature too small for specified offset and length");
 836             }
 837 
 838             return engineVerify(signature, offset, length);
 839         }
 840         throw new SignatureException("object not initialized for " +
 841                                      "verification");
 842     }
 843 
 844     /**
 845      * Updates the data to be signed or verified by a byte.
 846      *
 847      * @param b the byte to use for the update.
 848      *
 849      * @exception SignatureException if this signature object is not
 850      * initialized properly.
 851      */
 852     public final void update(byte b) throws SignatureException {
 853         if (state == VERIFY || state == SIGN) {
 854             engineUpdate(b);
 855         } else {
 856             throw new SignatureException("object not initialized for "
 857                                          + "signature or verification");
 858         }
 859     }
 860 
 861     /**
 862      * Updates the data to be signed or verified, using the specified
 863      * array of bytes.
 864      *
 865      * @param data the byte array to use for the update.
 866      *
 867      * @exception SignatureException if this signature object is not
 868      * initialized properly.
 869      */
 870     public final void update(byte[] data) throws SignatureException {
 871         update(data, 0, data.length);
 872     }
 873 
 874     /**
 875      * Updates the data to be signed or verified, using the specified
 876      * array of bytes, starting at the specified offset.
 877      *
 878      * @param data the array of bytes.
 879      * @param off the offset to start from in the array of bytes.
 880      * @param len the number of bytes to use, starting at offset.
 881      *
 882      * @exception SignatureException if this signature object is not
 883      *     initialized properly.
 884      * @exception IllegalArgumentException if {@code data} is {@code null},
 885      *     or {@code off} or {@code len} is less than 0, or the sum of
 886      *     {@code off} and {@code len} is greater than the length of
 887      *     {@code data}.
 888      */
 889     public final void update(byte[] data, int off, int len)
 890             throws SignatureException {
 891         if (state == SIGN || state == VERIFY) {
 892             if (data == null) {
 893                 throw new IllegalArgumentException("data is null");
 894             }
 895             if (off < 0 || len < 0) {
 896                 throw new IllegalArgumentException("off or len is less than 0");
 897             }
 898             if (data.length - off < len) {
 899                 throw new IllegalArgumentException
 900                     ("data too small for specified offset and length");
 901             }
 902             engineUpdate(data, off, len);
 903         } else {
 904             throw new SignatureException("object not initialized for "
 905                                          + "signature or verification");
 906         }
 907     }
 908 
 909     /**
 910      * Updates the data to be signed or verified using the specified
 911      * ByteBuffer. Processes the {@code data.remaining()} bytes
 912      * starting at {@code data.position()}.
 913      * Upon return, the buffer's position will be equal to its limit;
 914      * its limit will not have changed.
 915      *
 916      * @param data the ByteBuffer
 917      *
 918      * @exception SignatureException if this signature object is not
 919      * initialized properly.
 920      * @since 1.5
 921      */
 922     public final void update(ByteBuffer data) throws SignatureException {
 923         if ((state != SIGN) && (state != VERIFY)) {
 924             throw new SignatureException("object not initialized for "
 925                                          + "signature or verification");
 926         }
 927         if (data == null) {
 928             throw new NullPointerException();
 929         }
 930         engineUpdate(data);
 931     }
 932 
 933     /**
 934      * Returns the name of the algorithm for this signature object.
 935      *
 936      * @return the name of the algorithm for this signature object.
 937      */
 938     public final String getAlgorithm() {
 939         return this.algorithm;
 940     }
 941 
 942     /**
 943      * Returns a string representation of this signature object,
 944      * providing information that includes the state of the object
 945      * and the name of the algorithm used.
 946      *
 947      * @return a string representation of this signature object.
 948      */
 949     public String toString() {
 950         String initState = "";
 951         switch (state) {
 952         case UNINITIALIZED:
 953             initState = "<not initialized>";
 954             break;
 955         case VERIFY:
 956             initState = "<initialized for verifying>";
 957             break;
 958         case SIGN:
 959             initState = "<initialized for signing>";
 960             break;
 961         }
 962         return "Signature object: " + getAlgorithm() + initState;
 963     }
 964 
 965     /**
 966      * Sets the specified algorithm parameter to the specified value.
 967      * This method supplies a general-purpose mechanism through
 968      * which it is possible to set the various parameters of this object.
 969      * A parameter may be any settable parameter for the algorithm, such as
 970      * a parameter size, or a source of random bits for signature generation
 971      * (if appropriate), or an indication of whether or not to perform
 972      * a specific but optional computation. A uniform algorithm-specific
 973      * naming scheme for each parameter is desirable but left unspecified
 974      * at this time.
 975      *
 976      * @param param the string identifier of the parameter.
 977      * @param value the parameter value.
 978      *
 979      * @exception InvalidParameterException if {@code param} is an
 980      * invalid parameter for this signature algorithm engine,
 981      * the parameter is already set
 982      * and cannot be set again, a security exception occurs, and so on.
 983      *
 984      * @see #getParameter
 985      *
 986      * @deprecated Use
 987      * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
 988      * setParameter}.
 989      */
 990     @Deprecated
 991     public final void setParameter(String param, Object value)
 992             throws InvalidParameterException {
 993         engineSetParameter(param, value);
 994     }
 995 
 996     /**
 997      * Initializes this signature engine with the specified parameter set.
 998      *
 999      * @param params the parameters
1000      *
1001      * @exception InvalidAlgorithmParameterException if the given parameters
1002      * are inappropriate for this signature engine
1003      *
1004      * @see #getParameters
1005      */
1006     public final void setParameter(AlgorithmParameterSpec params)
1007             throws InvalidAlgorithmParameterException {
1008         engineSetParameter(params);
1009     }
1010 
1011     /**
1012      * Returns the parameters used with this signature object.
1013      *
1014      * <p> If this signature has been previously initialized with parameters
1015      * (by calling the {@code setParameter} method), this method returns
1016      * the same parameters. If this signature has not been initialized with
1017      * parameters, this method may return a combination of default and
1018      * randomly generated parameter values if the underlying
1019      * signature implementation supports it and can successfully generate
1020      * them. Otherwise, {@code null} is returned.
1021      *
1022      * @return the parameters used with this signature, or {@code null}
1023      *
1024      * @see #setParameter(AlgorithmParameterSpec)
1025      * @since 1.4
1026      */
1027     public final AlgorithmParameters getParameters() {
1028         return engineGetParameters();
1029     }
1030 
1031     /**
1032      * Gets the value of the specified algorithm parameter. This method
1033      * supplies a general-purpose mechanism through which it is possible to
1034      * get the various parameters of this object. A parameter may be any
1035      * settable parameter for the algorithm, such as a parameter size, or
1036      * a source of random bits for signature generation (if appropriate),
1037      * or an indication of whether or not to perform a specific but optional
1038      * computation. A uniform algorithm-specific naming scheme for each
1039      * parameter is desirable but left unspecified at this time.
1040      *
1041      * @param param the string name of the parameter.
1042      *
1043      * @return the object that represents the parameter value, or {@code null} if
1044      * there is none.
1045      *
1046      * @exception InvalidParameterException if {@code param} is an invalid
1047      * parameter for this engine, or another exception occurs while
1048      * trying to get this parameter.
1049      *
1050      * @see #setParameter(String, Object)
1051      *
1052      * @deprecated
1053      */
1054     @Deprecated
1055     public final Object getParameter(String param)
1056             throws InvalidParameterException {
1057         return engineGetParameter(param);
1058     }
1059 
1060     /**
1061      * Returns a clone if the implementation is cloneable.
1062      *
1063      * @return a clone if the implementation is cloneable.
1064      *
1065      * @exception CloneNotSupportedException if this is called
1066      * on an implementation that does not support {@code Cloneable}.
1067      */
1068     public Object clone() throws CloneNotSupportedException {
1069         if (this instanceof Cloneable) {
1070             return super.clone();
1071         } else {
1072             throw new CloneNotSupportedException();
1073         }
1074     }
1075 
1076     /*
1077      * The following class allows providers to extend from SignatureSpi
1078      * rather than from Signature. It represents a Signature with an
1079      * encapsulated, provider-supplied SPI object (of type SignatureSpi).
1080      * If the provider implementation is an instance of SignatureSpi, the
1081      * getInstance() methods above return an instance of this class, with
1082      * the SPI object encapsulated.
1083      *
1084      * Note: All SPI methods from the original Signature class have been
1085      * moved up the hierarchy into a new class (SignatureSpi), which has
1086      * been interposed in the hierarchy between the API (Signature)
1087      * and its original parent (Object).
1088      */
1089 
1090     @SuppressWarnings("deprecation")
1091     private static class Delegate extends Signature {
1092 
1093         // The provider implementation (delegate)
1094         // filled in once the provider is selected
1095         private SignatureSpi sigSpi;
1096 
1097         // lock for mutex during provider selection
1098         private final Object lock;
1099 
1100         // next service to try in provider selection
1101         // null once provider is selected
1102         private Service firstService;
1103 
1104         // remaining services to try in provider selection
1105         // null once provider is selected
1106         private Iterator<Service> serviceIterator;
1107 
1108         // constructor
1109         Delegate(SignatureSpi sigSpi, String algorithm) {
1110             super(algorithm);
1111             this.sigSpi = sigSpi;
1112             this.lock = null; // no lock needed
1113         }
1114 
1115         // used with delayed provider selection
1116         Delegate(Service service,
1117                         Iterator<Service> iterator, String algorithm) {
1118             super(algorithm);
1119             this.firstService = service;
1120             this.serviceIterator = iterator;
1121             this.lock = new Object();
1122         }
1123 
1124         /**
1125          * Returns a clone if the delegate is cloneable.
1126          *
1127          * @return a clone if the delegate is cloneable.
1128          *
1129          * @exception CloneNotSupportedException if this is called on a
1130          * delegate that does not support {@code Cloneable}.
1131          */
1132         public Object clone() throws CloneNotSupportedException {
1133             chooseFirstProvider();
1134             if (sigSpi instanceof Cloneable) {
1135                 SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone();
1136                 // Because 'algorithm' and 'provider' are private
1137                 // members of our supertype, we must perform a cast to
1138                 // access them.
1139                 Signature that =
1140                     new Delegate(sigSpiClone, ((Signature)this).algorithm);
1141                 that.provider = ((Signature)this).provider;
1142                 return that;
1143             } else {
1144                 throw new CloneNotSupportedException();
1145             }
1146         }
1147 
1148         private static SignatureSpi newInstance(Service s)
1149                 throws NoSuchAlgorithmException {
1150             if (s.getType().equals("Cipher")) {
1151                 // must be NONEwithRSA
1152                 try {
1153                     Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider());
1154                     return new CipherAdapter(c);
1155                 } catch (NoSuchPaddingException e) {
1156                     throw new NoSuchAlgorithmException(e);
1157                 }
1158             } else {
1159                 Object o = s.newInstance(null);
1160                 if (o instanceof SignatureSpi == false) {
1161                     throw new NoSuchAlgorithmException
1162                         ("Not a SignatureSpi: " + o.getClass().getName());
1163                 }
1164                 return (SignatureSpi)o;
1165             }
1166         }
1167 
1168         // max number of debug warnings to print from chooseFirstProvider()
1169         private static int warnCount = 10;
1170 
1171         /**
1172          * Choose the Spi from the first provider available. Used if
1173          * delayed provider selection is not possible because initSign()/
1174          * initVerify() is not the first method called.
1175          */
1176         void chooseFirstProvider() {
1177             if (sigSpi != null) {
1178                 return;
1179             }
1180             synchronized (lock) {
1181                 if (sigSpi != null) {
1182                     return;
1183                 }
1184                 if (debug != null) {
1185                     int w = --warnCount;
1186                     if (w >= 0) {
1187                         debug.println("Signature.init() not first method "
1188                             + "called, disabling delayed provider selection");
1189                         if (w == 0) {
1190                             debug.println("Further warnings of this type will "
1191                                 + "be suppressed");
1192                         }
1193                         new Exception("Debug call trace").printStackTrace();
1194                     }
1195                 }
1196                 Exception lastException = null;
1197                 while ((firstService != null) || serviceIterator.hasNext()) {
1198                     Service s;
1199                     if (firstService != null) {
1200                         s = firstService;
1201                         firstService = null;
1202                     } else {
1203                         s = serviceIterator.next();
1204                     }
1205                     if (isSpi(s) == false) {
1206                         continue;
1207                     }
1208                     try {
1209                         sigSpi = newInstance(s);
1210                         provider = s.getProvider();
1211                         // not needed any more
1212                         firstService = null;
1213                         serviceIterator = null;
1214                         return;
1215                     } catch (NoSuchAlgorithmException e) {
1216                         lastException = e;
1217                     }
1218                 }
1219                 ProviderException e = new ProviderException
1220                         ("Could not construct SignatureSpi instance");
1221                 if (lastException != null) {
1222                     e.initCause(lastException);
1223                 }
1224                 throw e;
1225             }
1226         }
1227 
1228         // Used by engineSetParameter/engineInitSign/engineInitVerify() to
1229         // find the right provider with the supplied key, parameters, random source
1230         private void chooseProvider(int type, Key key,
1231                 AlgorithmParameterSpec params, SecureRandom random)
1232                 throws InvalidKeyException, InvalidAlgorithmParameterException {
1233             synchronized (lock) {
1234                 if (sigSpi != null) {
1235                     return;
1236                 }
1237                 Exception lastException = null;
1238                 while ((firstService != null) || serviceIterator.hasNext()) {
1239                     Service s;
1240                     if (firstService != null) {
1241                         s = firstService;
1242                         firstService = null;
1243                     } else {
1244                         s = serviceIterator.next();
1245                     }
1246                     // if provider says it does not support this key, ignore it
1247                     if (key != null && s.supportsParameter(key) == false) {
1248                         continue;
1249                     }
1250                     // if instance is not a SignatureSpi, ignore it
1251                     if (isSpi(s) == false) {
1252                         continue;
1253                     }
1254                     try {
1255                         SignatureSpi spi = newInstance(s);
1256                         tryOperation(spi, type, key, params, random);
1257                         provider = s.getProvider();
1258                         sigSpi = spi;
1259                         firstService = null;
1260                         serviceIterator = null;
1261                         return;
1262                     } catch (Exception e) {
1263                         // NoSuchAlgorithmException from newInstance()
1264                         // InvalidKeyException from init()
1265                         // RuntimeException (ProviderException) from init()
1266                         if (lastException == null) {
1267                             lastException = e;
1268                         }
1269                     }
1270                 }
1271                 // no working provider found, fail
1272                 if (lastException instanceof InvalidKeyException) {
1273                     throw (InvalidKeyException)lastException;
1274                 }
1275                 if (lastException instanceof RuntimeException) {
1276                     throw (RuntimeException)lastException;
1277                 }
1278                 if (lastException instanceof InvalidAlgorithmParameterException) {
1279                     throw (InvalidAlgorithmParameterException)lastException;
1280                 }
1281 
1282                 String k = (key != null) ? key.getClass().getName() : "(null)";
1283                 throw new InvalidKeyException
1284                     ("No installed provider supports this key: "
1285                     + k, lastException);
1286             }
1287         }
1288 
1289         private static final int I_PUB           = 1;
1290         private static final int I_PRIV          = 2;
1291         private static final int I_PRIV_SR       = 3;
1292         private static final int I_PUB_PARAM     = 4;
1293         private static final int I_PRIV_PARAM_SR = 5;
1294         private static final int S_PARAM         = 6;
1295 
1296         private void tryOperation(SignatureSpi spi, int type, Key  key,
1297                 AlgorithmParameterSpec params, SecureRandom random)
1298                 throws InvalidKeyException, InvalidAlgorithmParameterException {
1299             switch (type) {
1300             case I_PUB:
1301                 spi.engineInitVerify((PublicKey)key);
1302                 break;
1303             case I_PUB_PARAM:
1304                 spi.engineInitVerify((PublicKey)key, params);
1305                 break;
1306             case I_PRIV:
1307                 spi.engineInitSign((PrivateKey)key);
1308                 break;
1309             case I_PRIV_SR:
1310                 spi.engineInitSign((PrivateKey)key, random);
1311                 break;
1312             case I_PRIV_PARAM_SR:
1313                 spi.engineInitSign((PrivateKey)key, params, random);
1314                 break;
1315             case S_PARAM:
1316                 spi.engineSetParameter(params);
1317                 break;
1318             default:
1319                 throw new AssertionError("Internal error: " + type);
1320             }
1321         }
1322 
1323         protected void engineInitVerify(PublicKey publicKey)
1324                 throws InvalidKeyException {
1325             if (sigSpi != null) {
1326                 sigSpi.engineInitVerify(publicKey);
1327             } else {
1328                 try {
1329                     chooseProvider(I_PUB, publicKey, null, null);
1330                 } catch (InvalidAlgorithmParameterException iape) {
1331                     // should not happen, re-throw as IKE just in case
1332                     throw new InvalidKeyException(iape);
1333                 }
1334             }
1335         }
1336 
1337         void engineInitVerify(PublicKey publicKey,
1338                 AlgorithmParameterSpec params)
1339                 throws InvalidKeyException, InvalidAlgorithmParameterException {
1340             if (sigSpi != null) {
1341                 sigSpi.engineInitVerify(publicKey, params);
1342             } else {
1343                 chooseProvider(I_PUB_PARAM, publicKey, params, null);
1344             }
1345         }
1346 
1347         protected void engineInitSign(PrivateKey privateKey)
1348                 throws InvalidKeyException {
1349             if (sigSpi != null) {
1350                 sigSpi.engineInitSign(privateKey);
1351             } else {
1352                 try {
1353                     chooseProvider(I_PRIV, privateKey, null, null);
1354                 } catch (InvalidAlgorithmParameterException iape) {
1355                     // should not happen, re-throw as IKE just in case
1356                     throw new InvalidKeyException(iape);
1357                 }
1358             }
1359         }
1360 
1361         protected void engineInitSign(PrivateKey privateKey, SecureRandom sr)
1362                 throws InvalidKeyException {
1363             if (sigSpi != null) {
1364                 sigSpi.engineInitSign(privateKey, sr);
1365             } else {
1366                 try {
1367                     chooseProvider(I_PRIV_SR, privateKey, null, sr);
1368                 } catch (InvalidAlgorithmParameterException iape) {
1369                     // should not happen, re-throw as IKE just in case
1370                     throw new InvalidKeyException(iape);
1371                 }
1372             }
1373         }
1374 
1375         void engineInitSign(PrivateKey privateKey,
1376                 AlgorithmParameterSpec params, SecureRandom sr)
1377                 throws InvalidKeyException, InvalidAlgorithmParameterException {
1378             if (sigSpi != null) {
1379                 sigSpi.engineInitSign(privateKey, params, sr);
1380             } else {
1381                 chooseProvider(I_PRIV_PARAM_SR, privateKey, params, sr);
1382             }
1383         }
1384 
1385         protected void engineUpdate(byte b) throws SignatureException {
1386             chooseFirstProvider();
1387             sigSpi.engineUpdate(b);
1388         }
1389 
1390         protected void engineUpdate(byte[] b, int off, int len)
1391                 throws SignatureException {
1392             chooseFirstProvider();
1393             sigSpi.engineUpdate(b, off, len);
1394         }
1395 
1396         protected void engineUpdate(ByteBuffer data) {
1397             chooseFirstProvider();
1398             sigSpi.engineUpdate(data);
1399         }
1400 
1401         protected byte[] engineSign() throws SignatureException {
1402             chooseFirstProvider();
1403             return sigSpi.engineSign();
1404         }
1405 
1406         protected int engineSign(byte[] outbuf, int offset, int len)
1407                 throws SignatureException {
1408             chooseFirstProvider();
1409             return sigSpi.engineSign(outbuf, offset, len);
1410         }
1411 
1412         protected boolean engineVerify(byte[] sigBytes)
1413                 throws SignatureException {
1414             chooseFirstProvider();
1415             return sigSpi.engineVerify(sigBytes);
1416         }
1417 
1418         protected boolean engineVerify(byte[] sigBytes, int offset, int length)
1419                 throws SignatureException {
1420             chooseFirstProvider();
1421             return sigSpi.engineVerify(sigBytes, offset, length);
1422         }
1423 
1424         protected void engineSetParameter(String param, Object value)
1425                 throws InvalidParameterException {
1426             chooseFirstProvider();
1427             sigSpi.engineSetParameter(param, value);
1428         }
1429 
1430         protected void engineSetParameter(AlgorithmParameterSpec params)
1431                 throws InvalidAlgorithmParameterException {
1432             if (sigSpi != null) {
1433                 sigSpi.engineSetParameter(params);
1434             } else {
1435                 try {
1436                     chooseProvider(S_PARAM, null, params, null);
1437                 } catch (InvalidKeyException ike) {
1438                     // should never happen, rethrow just in case
1439                     throw new InvalidAlgorithmParameterException(ike);
1440                 }
1441             }
1442         }
1443 
1444         protected Object engineGetParameter(String param)
1445                 throws InvalidParameterException {
1446             chooseFirstProvider();
1447             return sigSpi.engineGetParameter(param);
1448         }
1449 
1450         protected AlgorithmParameters engineGetParameters() {
1451             chooseFirstProvider();
1452             return sigSpi.engineGetParameters();
1453         }
1454     }
1455 
1456     // adapter for RSA/ECB/PKCS1Padding ciphers
1457     @SuppressWarnings("deprecation")
1458     private static class CipherAdapter extends SignatureSpi {
1459 
1460         private final Cipher cipher;
1461 
1462         private ByteArrayOutputStream data;
1463 
1464         CipherAdapter(Cipher cipher) {
1465             this.cipher = cipher;
1466         }
1467 
1468         protected void engineInitVerify(PublicKey publicKey)
1469                 throws InvalidKeyException {
1470             cipher.init(Cipher.DECRYPT_MODE, publicKey);
1471             if (data == null) {
1472                 data = new ByteArrayOutputStream(128);
1473             } else {
1474                 data.reset();
1475             }
1476         }
1477 
1478         protected void engineInitSign(PrivateKey privateKey)
1479                 throws InvalidKeyException {
1480             cipher.init(Cipher.ENCRYPT_MODE, privateKey);
1481             data = null;
1482         }
1483 
1484         protected void engineInitSign(PrivateKey privateKey,
1485                 SecureRandom random) throws InvalidKeyException {
1486             cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
1487             data = null;
1488         }
1489 
1490         protected void engineUpdate(byte b) throws SignatureException {
1491             engineUpdate(new byte[] {b}, 0, 1);
1492         }
1493 
1494         protected void engineUpdate(byte[] b, int off, int len)
1495                 throws SignatureException {
1496             if (data != null) {
1497                 data.write(b, off, len);
1498                 return;
1499             }
1500             byte[] out = cipher.update(b, off, len);
1501             if ((out != null) && (out.length != 0)) {
1502                 throw new SignatureException
1503                     ("Cipher unexpectedly returned data");
1504             }
1505         }
1506 
1507         protected byte[] engineSign() throws SignatureException {
1508             try {
1509                 return cipher.doFinal();
1510             } catch (IllegalBlockSizeException e) {
1511                 throw new SignatureException("doFinal() failed", e);
1512             } catch (BadPaddingException e) {
1513                 throw new SignatureException("doFinal() failed", e);
1514             }
1515         }
1516 
1517         protected boolean engineVerify(byte[] sigBytes)
1518                 throws SignatureException {
1519             try {
1520                 byte[] out = cipher.doFinal(sigBytes);
1521                 byte[] dataBytes = data.toByteArray();
1522                 data.reset();
1523                 return MessageDigest.isEqual(out, dataBytes);
1524             } catch (BadPaddingException e) {
1525                 // e.g. wrong public key used
1526                 // return false rather than throwing exception
1527                 return false;
1528             } catch (IllegalBlockSizeException e) {
1529                 throw new SignatureException("doFinal() failed", e);
1530             }
1531         }
1532 
1533         protected void engineSetParameter(String param, Object value)
1534                 throws InvalidParameterException {
1535             throw new InvalidParameterException("Parameters not supported");
1536         }
1537 
1538         protected Object engineGetParameter(String param)
1539                 throws InvalidParameterException {
1540             throw new InvalidParameterException("Parameters not supported");
1541         }
1542 
1543     }
1544 
1545 }