1 /*
   2  * Copyright (c) 2003, 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.rsa;
  27 
  28 import java.io.IOException;
  29 import java.nio.ByteBuffer;
  30 import java.math.BigInteger;
  31 import java.util.Arrays;
  32 
  33 import java.security.*;
  34 import java.security.interfaces.*;
  35 
  36 import sun.security.util.*;
  37 import sun.security.x509.AlgorithmId;
  38 
  39 /**
  40  * PKCS#1 RSA signatures with the various message digest algorithms.
  41  * This file contains an abstract base class with all the logic plus
  42  * a nested static class for each of the message digest algorithms
  43  * (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256,
  44  * SHA-384, and SHA-512.
  45  *
  46  * @since   1.5
  47  * @author  Andreas Sterbenz
  48  */
  49 public abstract class RSASignature extends SignatureSpi {
  50 
  51     // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
  52     // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
  53     // this means the encoded length is (8 + digestOID.length + digest.length)
  54     private static final int baseLength = 8;
  55 
  56     // object identifier for the message digest algorithm used
  57     private final ObjectIdentifier digestOID;
  58 
  59     // length of the encoded signature blob
  60     private final int encodedLength;
  61 
  62     // message digest implementation we use
  63     private final MessageDigest md;
  64     // flag indicating whether the digest is reset
  65     private boolean digestReset;
  66 
  67     // private key, if initialized for signing
  68     private RSAPrivateKey privateKey;
  69     // public key, if initialized for verifying
  70     private RSAPublicKey publicKey;
  71 
  72     // padding to use, set when the initSign/initVerify is called
  73     private RSAPadding padding;
  74 
  75     /**
  76      * Construct a new RSASignature. Used by subclasses.
  77      */
  78     RSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
  79         this.digestOID = digestOID;
  80         try {
  81             md = MessageDigest.getInstance(algorithm);
  82         } catch (NoSuchAlgorithmException e) {
  83             throw new ProviderException(e);
  84         }
  85         digestReset = true;
  86         encodedLength = baseLength + oidLength + md.getDigestLength();
  87     }
  88 
  89     // initialize for verification. See JCA doc
  90     protected void engineInitVerify(PublicKey publicKey)
  91             throws InvalidKeyException {
  92         RSAPublicKey rsaKey = (RSAPublicKey)RSAKeyFactory.toRSAKey(publicKey);
  93         this.privateKey = null;
  94         this.publicKey = rsaKey;
  95         initCommon(rsaKey, null);
  96     }
  97 
  98     // initialize for signing. See JCA doc
  99     protected void engineInitSign(PrivateKey privateKey)
 100             throws InvalidKeyException {
 101         engineInitSign(privateKey, null);
 102     }
 103 
 104     // initialize for signing. See JCA doc
 105     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
 106             throws InvalidKeyException {
 107         RSAPrivateKey rsaKey =
 108             (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
 109         this.privateKey = rsaKey;
 110         this.publicKey = null;
 111         initCommon(rsaKey, random);
 112     }
 113 
 114     /**
 115      * Init code common to sign and verify.
 116      */
 117     private void initCommon(RSAKey rsaKey, SecureRandom random)
 118             throws InvalidKeyException {
 119         resetDigest();
 120         int keySize = RSACore.getByteLength(rsaKey);
 121         try {
 122             padding = RSAPadding.getInstance
 123                 (RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
 124         } catch (InvalidAlgorithmParameterException iape) {
 125             throw new InvalidKeyException(iape.getMessage());
 126         }
 127         int maxDataSize = padding.getMaxDataSize();
 128         if (encodedLength > maxDataSize) {
 129             throw new InvalidKeyException
 130                 ("Key is too short for this signature algorithm");
 131         }
 132     }
 133 
 134     /**
 135      * Reset the message digest if it is not already reset.
 136      */
 137     private void resetDigest() {
 138         if (digestReset == false) {
 139             md.reset();
 140             digestReset = true;
 141         }
 142     }
 143 
 144     /**
 145      * Return the message digest value.
 146      */
 147     private byte[] getDigestValue() {
 148         digestReset = true;
 149         return md.digest();
 150     }
 151 
 152     // update the signature with the plaintext data. See JCA doc
 153     protected void engineUpdate(byte b) throws SignatureException {
 154         md.update(b);
 155         digestReset = false;
 156     }
 157 
 158     // update the signature with the plaintext data. See JCA doc
 159     protected void engineUpdate(byte[] b, int off, int len)
 160             throws SignatureException {
 161         md.update(b, off, len);
 162         digestReset = false;
 163     }
 164 
 165     // update the signature with the plaintext data. See JCA doc
 166     protected void engineUpdate(ByteBuffer b) {
 167         md.update(b);
 168         digestReset = false;
 169     }
 170 
 171     // sign the data and return the signature. See JCA doc
 172     protected byte[] engineSign() throws SignatureException {
 173         byte[] digest = getDigestValue();
 174         try {
 175             byte[] encoded = encodeSignature(digestOID, digest);
 176             byte[] padded = padding.pad(encoded);
 177             byte[] encrypted = RSACore.rsa(padded, privateKey);
 178             return encrypted;
 179         } catch (GeneralSecurityException e) {
 180             throw new SignatureException("Could not sign data", e);
 181         } catch (IOException e) {
 182             throw new SignatureException("Could not encode data", e);
 183         }
 184     }
 185 
 186     // verify the data and return the result. See JCA doc
 187     protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
 188         if (sigBytes.length != RSACore.getByteLength(publicKey)) {
 189             throw new SignatureException("Signature length not correct: got " +
 190                     sigBytes.length + " but was expecting " +
 191                     RSACore.getByteLength(publicKey));
 192         }
 193         byte[] digest = getDigestValue();
 194         try {
 195             byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
 196             byte[] unpadded = padding.unpad(decrypted);
 197             byte[] decodedDigest = decodeSignature(digestOID, unpadded);
 198             return Arrays.equals(digest, decodedDigest);
 199         } catch (javax.crypto.BadPaddingException e) {
 200             // occurs if the app has used the wrong RSA public key
 201             // or if sigBytes is invalid
 202             // return false rather than propagating the exception for
 203             // compatibility/ease of use
 204             return false;
 205         } catch (GeneralSecurityException e) {
 206             throw new SignatureException("Signature verification failed", e);
 207         } catch (IOException e) {
 208             throw new SignatureException("Signature encoding error", e);
 209         }
 210     }
 211 
 212     /**
 213      * Encode the digest, return the to-be-signed data.
 214      * Also used by the PKCS#11 provider.
 215      */
 216     public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest)
 217             throws IOException {
 218         DerOutputStream out = new DerOutputStream();
 219         new AlgorithmId(oid).encode(out);
 220         out.putOctetString(digest);
 221         DerValue result =
 222             new DerValue(DerValue.tag_Sequence, out.toByteArray());
 223         return result.toByteArray();
 224     }
 225 
 226     /**
 227      * Decode the signature data. Verify that the object identifier matches
 228      * and return the message digest.
 229      */
 230     public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
 231             throws IOException {
 232         DerInputStream in = new DerInputStream(signature);
 233         DerValue[] values = in.getSequence(2);
 234         if ((values.length != 2) || (in.available() != 0)) {
 235             throw new IOException("SEQUENCE length error");
 236         }
 237         AlgorithmId algId = AlgorithmId.parse(values[0]);
 238         if (algId.getOID().equals(oid) == false) {
 239             throw new IOException("ObjectIdentifier mismatch: "
 240                 + algId.getOID());
 241         }
 242         if (algId.getEncodedParams() != null) {
 243             throw new IOException("Unexpected AlgorithmId parameters");
 244         }
 245         byte[] digest = values[1].getOctetString();
 246         return digest;
 247     }
 248 
 249     // set parameter, not supported. See JCA doc
 250     protected void engineSetParameter(String param, Object value)
 251             throws InvalidParameterException {
 252         throw new UnsupportedOperationException("setParameter() not supported");
 253     }
 254 
 255     // get parameter, not supported. See JCA doc
 256     protected Object engineGetParameter(String param)
 257             throws InvalidParameterException {
 258         throw new UnsupportedOperationException("getParameter() not supported");
 259     }
 260 
 261     // Nested class for MD2withRSA signatures
 262     public static final class MD2withRSA extends RSASignature {
 263         public MD2withRSA() {
 264             super("MD2", AlgorithmId.MD2_oid, 10);
 265         }
 266     }
 267 
 268     // Nested class for MD5withRSA signatures
 269     public static final class MD5withRSA extends RSASignature {
 270         public MD5withRSA() {
 271             super("MD5", AlgorithmId.MD5_oid, 10);
 272         }
 273     }
 274 
 275     // Nested class for SHA1withRSA signatures
 276     public static final class SHA1withRSA extends RSASignature {
 277         public SHA1withRSA() {
 278             super("SHA-1", AlgorithmId.SHA_oid, 7);
 279         }
 280     }
 281 
 282     // Nested class for SHA224withRSA signatures
 283     public static final class SHA224withRSA extends RSASignature {
 284         public SHA224withRSA() {
 285             super("SHA-224", AlgorithmId.SHA224_oid, 11);
 286         }
 287     }
 288 
 289     // Nested class for SHA256withRSA signatures
 290     public static final class SHA256withRSA extends RSASignature {
 291         public SHA256withRSA() {
 292             super("SHA-256", AlgorithmId.SHA256_oid, 11);
 293         }
 294     }
 295 
 296     // Nested class for SHA384withRSA signatures
 297     public static final class SHA384withRSA extends RSASignature {
 298         public SHA384withRSA() {
 299             super("SHA-384", AlgorithmId.SHA384_oid, 11);
 300         }
 301     }
 302 
 303     // Nested class for SHA512withRSA signatures
 304     public static final class SHA512withRSA extends RSASignature {
 305         public SHA512withRSA() {
 306             super("SHA-512", AlgorithmId.SHA512_oid, 11);
 307         }
 308     }
 309 
 310 }