src/java.base/share/classes/sun/security/ssl/RSASignature.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56592 b1902b22005e
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    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
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 
       
    27 package sun.security.ssl;
    26 package sun.security.ssl;
    28 
    27 
    29 import java.security.*;
    28 import java.security.*;
       
    29 import java.security.spec.AlgorithmParameterSpec;
    30 
    30 
    31 /**
    31 /**
    32  * Signature implementation for the SSL/TLS RSA Signature variant with both
    32  * Signature implementation for the SSL/TLS RSA Signature variant with both
    33  * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication
    33  * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication
    34  * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client
    34  * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client
    43  * implementation allows the hashes to be explicitly set, which is required
    43  * implementation allows the hashes to be explicitly set, which is required
    44  * for RSA client authentication. It can be obtained via the
    44  * for RSA client authentication. It can be obtained via the
    45  * getInternalInstance() method.
    45  * getInternalInstance() method.
    46  *
    46  *
    47  * This class is not thread safe.
    47  * This class is not thread safe.
    48  *
       
    49  */
    48  */
    50 public final class RSASignature extends SignatureSpi {
    49 public final class RSASignature extends SignatureSpi {
    51 
       
    52     private final Signature rawRsa;
    50     private final Signature rawRsa;
    53     private MessageDigest md5, sha;
    51     private final MessageDigest mdMD5;
    54 
    52     private final MessageDigest mdSHA;
    55     // flag indicating if the MessageDigests are in reset state
       
    56     private boolean isReset;
       
    57 
    53 
    58     public RSASignature() throws NoSuchAlgorithmException {
    54     public RSASignature() throws NoSuchAlgorithmException {
    59         super();
    55         super();
    60         rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
    56         rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
    61         isReset = true;
    57         this.mdMD5 = JsseJce.getMessageDigest("MD5");
       
    58         this.mdSHA = JsseJce.getMessageDigest("SHA");
    62     }
    59     }
    63 
    60 
    64     /**
    61     /**
    65      * Get an implementation for the RSA signature. Follows the standard
    62      * Get an implementation for the RSA signature.
    66      * JCA getInstance() model, so it return the implementation from the
    63      *
    67      * provider with the highest precedence, which may be this class.
    64      * Follows the standard JCA getInstance() model, so it return the
       
    65      * implementation from the  provider with the highest precedence,
       
    66      * which may be this class.
    68      */
    67      */
    69     static Signature getInstance() throws NoSuchAlgorithmException {
    68     static Signature getInstance() throws NoSuchAlgorithmException {
    70         return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA);
    69         return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA);
    71     }
    70     }
    72 
    71 
    73     /**
    72     /**
    74      * Get an internal implementation for the RSA signature. Used for RSA
    73      * Get an internal implementation for the RSA signature.
    75      * client authentication, which needs the ability to set the digests
    74      *
    76      * to externally provided values via the setHashes() method.
    75      * Used for RSA client authentication, which needs the ability to set
       
    76      * the digests to externally provided values via the setHashes() method.
    77      */
    77      */
    78     static Signature getInternalInstance()
    78     static Signature getInternalInstance()
    79             throws NoSuchAlgorithmException, NoSuchProviderException {
    79             throws NoSuchAlgorithmException, NoSuchProviderException {
    80         return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE");
    80         return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE");
    81     }
    81     }
    86     @SuppressWarnings("deprecation")
    86     @SuppressWarnings("deprecation")
    87     static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) {
    87     static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) {
    88         sig.setParameter("hashes", new MessageDigest[] {md5, sha});
    88         sig.setParameter("hashes", new MessageDigest[] {md5, sha});
    89     }
    89     }
    90 
    90 
    91     /**
       
    92      * Reset the MessageDigests unless they are already reset.
       
    93      */
       
    94     private void reset() {
       
    95         if (isReset == false) {
       
    96             md5.reset();
       
    97             sha.reset();
       
    98             isReset = true;
       
    99         }
       
   100     }
       
   101 
       
   102     private static void checkNull(Key key) throws InvalidKeyException {
       
   103         if (key == null) {
       
   104             throw new InvalidKeyException("Key must not be null");
       
   105         }
       
   106     }
       
   107 
       
   108     @Override
    91     @Override
   109     protected void engineInitVerify(PublicKey publicKey)
    92     protected void engineInitVerify(PublicKey publicKey)
   110             throws InvalidKeyException {
    93             throws InvalidKeyException {
   111         checkNull(publicKey);
    94         if (publicKey == null) {
   112         reset();
    95             throw new InvalidKeyException("Public key must not be null");
       
    96         }
       
    97         mdMD5.reset();
       
    98         mdSHA.reset();
   113         rawRsa.initVerify(publicKey);
    99         rawRsa.initVerify(publicKey);
   114     }
   100     }
   115 
   101 
   116     @Override
   102     @Override
   117     protected void engineInitSign(PrivateKey privateKey)
   103     protected void engineInitSign(PrivateKey privateKey)
   120     }
   106     }
   121 
   107 
   122     @Override
   108     @Override
   123     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
   109     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
   124             throws InvalidKeyException {
   110             throws InvalidKeyException {
   125         checkNull(privateKey);
   111         if (privateKey == null) {
   126         reset();
   112             throw new InvalidKeyException("Private key must not be null");
       
   113         }
       
   114         mdMD5.reset();
       
   115         mdSHA.reset();
   127         rawRsa.initSign(privateKey, random);
   116         rawRsa.initSign(privateKey, random);
   128     }
       
   129 
       
   130     // lazily initialize the MessageDigests
       
   131     private void initDigests() {
       
   132         if (md5 == null) {
       
   133             md5 = JsseJce.getMD5();
       
   134             sha = JsseJce.getSHA();
       
   135         }
       
   136     }
   117     }
   137 
   118 
   138     @Override
   119     @Override
   139     protected void engineUpdate(byte b) {
   120     protected void engineUpdate(byte b) {
   140         initDigests();
   121         mdMD5.update(b);
   141         isReset = false;
   122         mdSHA.update(b);
   142         md5.update(b);
       
   143         sha.update(b);
       
   144     }
   123     }
   145 
   124 
   146     @Override
   125     @Override
   147     protected void engineUpdate(byte[] b, int off, int len) {
   126     protected void engineUpdate(byte[] b, int off, int len) {
   148         initDigests();
   127         mdMD5.update(b, off, len);
   149         isReset = false;
   128         mdSHA.update(b, off, len);
   150         md5.update(b, off, len);
       
   151         sha.update(b, off, len);
       
   152     }
   129     }
   153 
   130 
   154     private byte[] getDigest() throws SignatureException {
   131     private byte[] getDigest() throws SignatureException {
   155         try {
   132         try {
   156             initDigests();
       
   157             byte[] data = new byte[36];
   133             byte[] data = new byte[36];
   158             md5.digest(data, 0, 16);
   134             mdMD5.digest(data, 0, 16);
   159             sha.digest(data, 16, 20);
   135             mdSHA.digest(data, 16, 20);
   160             isReset = true;
       
   161             return data;
   136             return data;
   162         } catch (DigestException e) {
   137         } catch (DigestException e) {
   163             // should never occur
   138             // should never occur
   164             throw new SignatureException(e);
   139             throw new SignatureException(e);
   165         }
   140         }
   183         return rawRsa.verify(sigBytes, offset, length);
   158         return rawRsa.verify(sigBytes, offset, length);
   184     }
   159     }
   185 
   160 
   186     @Override
   161     @Override
   187     @SuppressWarnings("deprecation")
   162     @SuppressWarnings("deprecation")
   188     protected void engineSetParameter(String param, Object value)
   163     protected void engineSetParameter(String param,
   189             throws InvalidParameterException {
   164             Object value) throws InvalidParameterException {
   190         if (param.equals("hashes") == false) {
   165         throw new InvalidParameterException("Parameters not supported");
   191             throw new InvalidParameterException
   166     }
   192                 ("Parameter not supported: " + param);
   167 
       
   168     @Override
       
   169     protected void engineSetParameter(AlgorithmParameterSpec params)
       
   170             throws InvalidAlgorithmParameterException {
       
   171         if (params != null) {
       
   172             throw new InvalidAlgorithmParameterException("No parameters accepted");
   193         }
   173         }
   194         if (value instanceof MessageDigest[] == false) {
       
   195             throw new InvalidParameterException
       
   196                 ("value must be MessageDigest[]");
       
   197         }
       
   198         MessageDigest[] digests = (MessageDigest[])value;
       
   199         md5 = digests[0];
       
   200         sha = digests[1];
       
   201     }
   174     }
   202 
   175 
   203     @Override
   176     @Override
   204     @SuppressWarnings("deprecation")
   177     @SuppressWarnings("deprecation")
   205     protected Object engineGetParameter(String param)
   178     protected Object engineGetParameter(
   206             throws InvalidParameterException {
   179             String param) throws InvalidParameterException {
   207         throw new InvalidParameterException("Parameters not supported");
   180         throw new InvalidParameterException("Parameters not supported");
   208     }
   181     }
   209 
   182 
       
   183     @Override
       
   184     protected AlgorithmParameters engineGetParameters() {
       
   185         return null;
       
   186     }
   210 }
   187 }