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  *
  58  * NOTE: NONEwithRSA must be supplied with a pre-computed message digest.
  59  *       Only the following digest algorithms are supported: MD5, SHA-1,
  60  *       SHA-256, SHA-384, SHA-512 and a special-purpose digest
  61  *       algorithm which is a concatenation of SHA-1 and MD5 digests.
  62  *
  63  * @since   1.6
  64  * @author  Stanley Man-Kit Ho
  65  */
  66 abstract class RSASignature extends java.security.SignatureSpi
  67 {
  68     // message digest implementation we use
  69     private final MessageDigest messageDigest;
  70 
  71     // message digest name
  72     private String messageDigestAlgorithm;
  73 
  74     // flag indicating whether the digest has been reset
  75     private boolean needsReset;
  76 
  77     // the signing key
  78     private Key privateKey = null;
  79 
  80     // the verification key
  81     private Key publicKey = null;
  82 
  83     /**
  84      * Constructs a new RSASignature. Used by Raw subclass.
  85      */
  86     RSASignature() {
  87         messageDigest = null;
  88         messageDigestAlgorithm = null;
  89     }
  90 
  91     /**
  92      * Constructs a new RSASignature. Used by subclasses.
  93      */
  94     RSASignature(String digestName) {
  95 
  96         try {
  97             messageDigest = MessageDigest.getInstance(digestName);
  98             // Get the digest's canonical name
  99             messageDigestAlgorithm = messageDigest.getAlgorithm();
 100 
 101         } catch (NoSuchAlgorithmException e) {
 102            throw new ProviderException(e);
 103         }
 104 
 105         needsReset = false;
 106     }
 107 
 108     // Nested class for NONEwithRSA signatures
 109     public static final class Raw extends RSASignature {
 110 
 111         // the longest supported digest is 512 bits (SHA-512)
 112         private static final int RAW_RSA_MAX = 64;
 113 
 114         private final byte[] precomputedDigest;
 115         private int offset = 0;
 116 
 117         public Raw() {
 118             precomputedDigest = new byte[RAW_RSA_MAX];
 119         }
 120 
 121         // Stores the precomputed message digest value.
 122         @Override
 123         protected void engineUpdate(byte b) throws SignatureException {
 124             if (offset >= precomputedDigest.length) {
 125                 offset = RAW_RSA_MAX + 1;
 126                 return;
 127             }
 128             precomputedDigest[offset++] = b;
 129         }
 130 
 131         // Stores the precomputed message digest value.
 132         @Override
 133         protected void engineUpdate(byte[] b, int off, int len)
 134                 throws SignatureException {
 135             if (offset + len > precomputedDigest.length) {
 136                 offset = RAW_RSA_MAX + 1;
 137                 return;
 138             }
 139             System.arraycopy(b, off, precomputedDigest, offset, len);
 140             offset += len;
 141         }
 142 
 143         // Stores the precomputed message digest value.
 144         @Override
 145         protected void engineUpdate(ByteBuffer byteBuffer) {
 146             int len = byteBuffer.remaining();
 147             if (len <= 0) {
 148                 return;
 149             }
 150             if (offset + len > precomputedDigest.length) {
 151                 offset = RAW_RSA_MAX + 1;
 152                 return;
 153             }
 154             byteBuffer.get(precomputedDigest, offset, len);
 155             offset += len;
 156         }
 157 
 158         @Override
 159         protected void resetDigest(){
 160             offset = 0;
 161         }
 162 
 163         // Returns the precomputed message digest value.
 164         @Override
 165         protected byte[] getDigestValue() throws SignatureException {
 166             if (offset > RAW_RSA_MAX) {
 167                 throw new SignatureException("Message digest is too long");
 168             }
 169 
 170             // Determine the digest algorithm from the digest length
 171             if (offset == 20) {
 172                 setDigestName("SHA1");
 173             } else if (offset == 36) {
 174                 setDigestName("SHA1+MD5");
 175             } else if (offset == 32) {
 176                 setDigestName("SHA-256");
 177             } else if (offset == 48) {
 178                 setDigestName("SHA-384");
 179             } else if (offset == 64) {
 180                 setDigestName("SHA-512");
 181             } else if (offset == 16) {
 182                 setDigestName("MD5");
 183             } else {
 184                 throw new SignatureException(
 185                     "Message digest length is not supported");
 186             }
 187 
 188             byte[] result = new byte[offset];
 189             System.arraycopy(precomputedDigest, 0, result, 0, offset);
 190             offset = 0;
 191 
 192             return result;
 193         }
 194     }
 195 
 196     public static final class SHA1 extends RSASignature {
 197         public SHA1() {
 198             super("SHA1");
 199         }
 200     }
 201 
 202     public static final class SHA256 extends RSASignature {
 203         public SHA256() {
 204             super("SHA-256");
 205         }
 206     }
 207 
 208     public static final class SHA384 extends RSASignature {
 209         public SHA384() {
 210             super("SHA-384");
 211         }
 212     }
 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.
 253             RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
 254                 exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX);
 255 
 256             byte[] modulusBytes = modulus.toByteArray();
 257             byte[] exponentBytes = exponent.toByteArray();
 258 
 259             // Adjust key length due to sign bit
 260             int keyBitLength = (modulusBytes[0] == 0)
 261                 ? (modulusBytes.length - 1) * 8
 262                 : modulusBytes.length * 8;
 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.
 303      */
 304     protected void resetDigest() {
 305         if (needsReset) {
 306             messageDigest.reset();
 307             needsReset = false;
 308         }
 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      */
 397     private byte[] convertEndianArray(byte[] byteArray)
 398     {
 399         if (byteArray == null || byteArray.length == 0)
 400             return byteArray;
 401 
 402         byte [] retval = new byte[byteArray.length];
 403 
 404         // make it big endian
 405         for (int i=0;i < byteArray.length;i++)
 406             retval[i] = byteArray[byteArray.length - i - 1];
 407 
 408         return retval;
 409     }
 410 
 411     /**
 412      * Sign hash using Microsoft Crypto API with HCRYPTKEY.
 413      * The returned data is in little-endian.
 414      */
 415     private native static byte[] signHash(boolean noHashOID, byte[] hash,
 416         int hashSize, String hashAlgorithm, long hCryptProv, long hCryptKey)
 417             throws SignatureException;
 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 }