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 }