< prev index next >

src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java

Print this page




1182         dh_p = input.getBytes16();
1183         dh_g = input.getBytes16();
1184         dh_Ys = input.getBytes16();
1185         KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
1186                                              new BigInteger(1, dh_p),
1187                                              new BigInteger(1, dh_g)));
1188 
1189         // read the signature and hash algorithm
1190         if (protocolVersion.useTLS12PlusSpec()) {
1191             int hash = input.getInt8();         // hash algorithm
1192             int signature = input.getInt8();    // signature algorithm
1193 
1194             preferableSignatureAlgorithm =
1195                 SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
1196 
1197             // Is it a local supported signature algorithm?
1198             if (!localSupportedSignAlgs.contains(
1199                     preferableSignatureAlgorithm)) {
1200                 throw new SSLHandshakeException(
1201                         "Unsupported SignatureAndHashAlgorithm in " +
1202                         "ServerKeyExchange message");
1203             }
1204         } else {
1205             this.preferableSignatureAlgorithm = null;
1206         }
1207 
1208         // read the signature
1209         byte[] signature;
1210         if (dhKeyExchangeFix) {
1211             signature = input.getBytes16();
1212         } else {
1213             messageSize -= (dh_p.length + 2);
1214             messageSize -= (dh_g.length + 2);
1215             messageSize -= (dh_Ys.length + 2);
1216 
1217             signature = new byte[messageSize];
1218             input.read(signature);
1219         }
1220 
1221         Signature sig;
1222         String algorithm = publicKey.getAlgorithm();
1223         if (protocolVersion.useTLS12PlusSpec()) {
1224             sig = JsseJce.getSignature(
1225                         preferableSignatureAlgorithm.getAlgorithmName());
1226         } else {
1227                 switch (algorithm) {
1228                     case "DSA":
1229                         sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
1230                         break;
1231                     case "RSA":
1232                         sig = RSASignature.getInstance();
1233                         break;
1234                     default:
1235                         throw new SSLKeyException("neither an RSA or a DSA key");
1236                 }
1237         }
1238 
1239         sig.initVerify(publicKey);
1240         updateSignature(sig, clntNonce, svrNonce);
1241 
1242         if (sig.verify(signature) == false ) {
1243             throw new SSLKeyException("Server D-H key verification failed");
1244         }
1245     }
1246 
1247     /* Return the Diffie-Hellman modulus */
1248     BigInteger getModulus() {
1249         return new BigInteger(1, dh_p);
1250     }
1251 
1252     /* Return the Diffie-Hellman base/generator */
1253     BigInteger getBase() {
1254         return new BigInteger(1, dh_g);
1255     }


1465             new ECPublicKeySpec(point, parameters));
1466 
1467         if (signingKey == null) {
1468             // ECDH_anon
1469             return;
1470         }
1471 
1472         // read the signature and hash algorithm
1473         if (protocolVersion.useTLS12PlusSpec()) {
1474             int hash = input.getInt8();         // hash algorithm
1475             int signature = input.getInt8();    // signature algorithm
1476 
1477             preferableSignatureAlgorithm =
1478                 SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
1479 
1480             // Is it a local supported signature algorithm?
1481             if (!localSupportedSignAlgs.contains(
1482                     preferableSignatureAlgorithm)) {
1483                 throw new SSLHandshakeException(
1484                         "Unsupported SignatureAndHashAlgorithm in " +
1485                         "ServerKeyExchange message");
1486             }
1487         }
1488 
1489         // read the signature
1490         signatureBytes = input.getBytes16();
1491 
1492         // verify the signature
1493         Signature sig;
1494         if (protocolVersion.useTLS12PlusSpec()) {
1495             sig = JsseJce.getSignature(
1496                         preferableSignatureAlgorithm.getAlgorithmName());
1497         } else {
1498             sig = getSignature(signingKey.getAlgorithm());
1499         }
1500         sig.initVerify(signingKey);
1501 
1502         updateSignature(sig, clntNonce, svrNonce);
1503 
1504         if (sig.verify(signatureBytes) == false ) {
1505             throw new SSLKeyException(
1506                 "Invalid signature on ECDH server key exchange message");
1507         }
1508     }
1509 
1510     /*
1511      * Get the ephemeral EC public key encapsulated in this message.
1512      */
1513     ECPublicKey getPublicKey() {
1514         return publicKey;
1515     }
1516 
1517     private static Signature getSignature(String keyAlgorithm)
1518             throws NoSuchAlgorithmException {
1519             switch (keyAlgorithm) {
1520                 case "EC":
1521                     return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
1522                 case "RSA":
1523                     return RSASignature.getInstance();
1524                 default:
1525                     throw new NoSuchAlgorithmException("neither an RSA or a EC key");

1526             }
1527     }
1528 
1529     private void updateSignature(Signature sig, byte[] clntNonce,
1530             byte[] svrNonce) throws SignatureException {
1531         sig.update(clntNonce);
1532         sig.update(svrNonce);
1533 
1534         sig.update((byte)CURVE_NAMED_CURVE);
1535         sig.update((byte)(curveId >> 8));
1536         sig.update((byte)curveId);
1537         sig.update((byte)pointBytes.length);
1538         sig.update(pointBytes);
1539     }
1540 
1541     @Override
1542     int messageLength() {
1543         int sigLen = 0;
1544         if (signatureBytes != null) {
1545             sigLen = 2 + signatureBytes.length;


1712                 SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
1713         } else {
1714             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1715             algorithmsLen = 0;
1716         }
1717     }
1718 
1719     CertificateRequest(HandshakeInStream input,
1720             ProtocolVersion protocolVersion) throws IOException {
1721 
1722         this.protocolVersion = protocolVersion;
1723 
1724         // Read the certificate_types.
1725         types = input.getBytes8();
1726 
1727         // Read the supported_signature_algorithms for TLS 1.2 or later.
1728         if (protocolVersion.useTLS12PlusSpec()) {
1729             algorithmsLen = input.getInt16();
1730             if (algorithmsLen < 2) {
1731                 throw new SSLProtocolException(
1732                         "Invalid supported_signature_algorithms field");
1733             }
1734 
1735             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1736             int remains = algorithmsLen;
1737             int sequence = 0;
1738             while (remains > 1) {    // needs at least two bytes
1739                 int hash = input.getInt8();         // hash algorithm
1740                 int signature = input.getInt8();    // signature algorithm
1741 
1742                 SignatureAndHashAlgorithm algorithm =
1743                     SignatureAndHashAlgorithm.valueOf(hash, signature,
1744                                                                 ++sequence);
1745                 algorithms.add(algorithm);
1746                 remains -= 2;  // one byte for hash, one byte for signature
1747             }
1748 
1749             if (remains != 0) {
1750                 throw new SSLProtocolException(
1751                         "Invalid supported_signature_algorithms field");
1752             }
1753         } else {
1754             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1755             algorithmsLen = 0;
1756         }
1757 
1758         // read the certificate_authorities
1759         int len = input.getInt16();
1760         ArrayList<DistinguishedName> v = new ArrayList<>();
1761         while (len >= 3) {
1762             DistinguishedName dn = new DistinguishedName(input);
1763             v.add(dn);
1764             len -= dn.length();
1765         }
1766 
1767         if (len != 0) {
1768             throw new SSLProtocolException("Bad CertificateRequest DN length");
1769         }
1770 
1771         authorities = v.toArray(new DistinguishedName[v.size()]);
1772     }
1773 
1774     X500Principal[] getAuthorities() throws IOException {
1775         X500Principal[] ret = new X500Principal[authorities.length];
1776         for (int i = 0; i < authorities.length; i++) {
1777             ret[i] = authorities[i].getX500Principal();
1778         }
1779         return ret;
1780     }
1781 
1782     Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
1783         return algorithms;
1784     }
1785 
1786     @Override
1787     int messageType() {
1788         return ht_certificate_request;


1979     //
1980     CertificateVerify(HandshakeInStream input,
1981             Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
1982             ProtocolVersion protocolVersion) throws IOException  {
1983 
1984         this.protocolVersion = protocolVersion;
1985 
1986         // read the signature and hash algorithm
1987         if (protocolVersion.useTLS12PlusSpec()) {
1988             int hashAlg = input.getInt8();         // hash algorithm
1989             int signAlg = input.getInt8();         // signature algorithm
1990 
1991             preferableSignatureAlgorithm =
1992                 SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
1993 
1994             // Is it a local supported signature algorithm?
1995             if (!localSupportedSignAlgs.contains(
1996                     preferableSignatureAlgorithm)) {
1997                 throw new SSLHandshakeException(
1998                         "Unsupported SignatureAndHashAlgorithm in " +
1999                         "CertificateVerify message");
2000             }
2001         }
2002 
2003         // read the signature
2004         signature = input.getBytes16();
2005     }
2006 
2007     /*
2008      * Get the preferable signature algorithm used by this message
2009      */
2010     SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
2011         return preferableSignatureAlgorithm;
2012     }
2013 
2014     /*
2015      * Verify a certificate verify message. Return the result of verification,
2016      * if there is a problem throw a GeneralSecurityException.
2017      */
2018     boolean verify(ProtocolVersion protocolVersion,
2019             HandshakeHash handshakeHash, PublicKey publicKey,


2347                 String prfHashAlg = prf.getPRFHashAlg();
2348                 int prfHashLength = prf.getPRFHashLength();
2349                 int prfBlockSize = prf.getPRFBlockSize();
2350 
2351                 /*
2352                  * RFC 5246/7.4.9 says that finished messages can
2353                  * be ciphersuite-specific in both length/PRF hash
2354                  * algorithm.  If we ever run across a different
2355                  * length, this call will need to be updated.
2356                  */
2357                 @SuppressWarnings("deprecation")
2358                 TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
2359                     masterKey, tlsLabel, seed, 12,
2360                     prfHashAlg, prfHashLength, prfBlockSize);
2361 
2362                 KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
2363                 kg.init(spec);
2364                 SecretKey prfKey = kg.generateKey();
2365                 if ("RAW".equals(prfKey.getFormat()) == false) {
2366                     throw new ProviderException(
2367                         "Invalid PRF output, format must be RAW");

2368                 }
2369                 byte[] finished = prfKey.getEncoded();
2370                 return finished;
2371             } catch (GeneralSecurityException e) {
2372                 throw new RuntimeException("PRF failed", e);
2373             }
2374         } else {
2375             // SSLv3
2376             MessageDigest md5Clone = handshakeHash.getMD5Clone();
2377             MessageDigest shaClone = handshakeHash.getSHAClone();
2378             updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
2379             updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
2380             byte[] finished = new byte[36];
2381             try {
2382                 md5Clone.digest(finished, 0, 16);
2383                 shaClone.digest(finished, 16, 20);
2384             } catch (DigestException e) {
2385                 // cannot occur
2386                 throw new RuntimeException("Digest failed", e);
2387             }




1182         dh_p = input.getBytes16();
1183         dh_g = input.getBytes16();
1184         dh_Ys = input.getBytes16();
1185         KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
1186                                              new BigInteger(1, dh_p),
1187                                              new BigInteger(1, dh_g)));
1188 
1189         // read the signature and hash algorithm
1190         if (protocolVersion.useTLS12PlusSpec()) {
1191             int hash = input.getInt8();         // hash algorithm
1192             int signature = input.getInt8();    // signature algorithm
1193 
1194             preferableSignatureAlgorithm =
1195                 SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
1196 
1197             // Is it a local supported signature algorithm?
1198             if (!localSupportedSignAlgs.contains(
1199                     preferableSignatureAlgorithm)) {
1200                 throw new SSLHandshakeException(
1201                         "Unsupported SignatureAndHashAlgorithm in " +
1202                         "ServerKeyExchange message: " + preferableSignatureAlgorithm);
1203             }
1204         } else {
1205             this.preferableSignatureAlgorithm = null;
1206         }
1207 
1208         // read the signature
1209         byte[] signature;
1210         if (dhKeyExchangeFix) {
1211             signature = input.getBytes16();
1212         } else {
1213             messageSize -= (dh_p.length + 2);
1214             messageSize -= (dh_g.length + 2);
1215             messageSize -= (dh_Ys.length + 2);
1216 
1217             signature = new byte[messageSize];
1218             input.read(signature);
1219         }
1220 
1221         Signature sig;
1222         String algorithm = publicKey.getAlgorithm();
1223         if (protocolVersion.useTLS12PlusSpec()) {
1224             sig = JsseJce.getSignature(
1225                         preferableSignatureAlgorithm.getAlgorithmName());
1226         } else {
1227                 switch (algorithm) {
1228                     case "DSA":
1229                         sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
1230                         break;
1231                     case "RSA":
1232                         sig = RSASignature.getInstance();
1233                         break;
1234                     default:
1235                         throw new SSLKeyException("neither an RSA or a DSA key: " + algorithm);
1236                 }
1237         }
1238 
1239         sig.initVerify(publicKey);
1240         updateSignature(sig, clntNonce, svrNonce);
1241 
1242         if (sig.verify(signature) == false ) {
1243             throw new SSLKeyException("Server D-H key verification failed");
1244         }
1245     }
1246 
1247     /* Return the Diffie-Hellman modulus */
1248     BigInteger getModulus() {
1249         return new BigInteger(1, dh_p);
1250     }
1251 
1252     /* Return the Diffie-Hellman base/generator */
1253     BigInteger getBase() {
1254         return new BigInteger(1, dh_g);
1255     }


1465             new ECPublicKeySpec(point, parameters));
1466 
1467         if (signingKey == null) {
1468             // ECDH_anon
1469             return;
1470         }
1471 
1472         // read the signature and hash algorithm
1473         if (protocolVersion.useTLS12PlusSpec()) {
1474             int hash = input.getInt8();         // hash algorithm
1475             int signature = input.getInt8();    // signature algorithm
1476 
1477             preferableSignatureAlgorithm =
1478                 SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
1479 
1480             // Is it a local supported signature algorithm?
1481             if (!localSupportedSignAlgs.contains(
1482                     preferableSignatureAlgorithm)) {
1483                 throw new SSLHandshakeException(
1484                         "Unsupported SignatureAndHashAlgorithm in " +
1485                         "ServerKeyExchange message: " + preferableSignatureAlgorithm);
1486             }
1487         }
1488 
1489         // read the signature
1490         signatureBytes = input.getBytes16();
1491 
1492         // verify the signature
1493         Signature sig;
1494         if (protocolVersion.useTLS12PlusSpec()) {
1495             sig = JsseJce.getSignature(
1496                         preferableSignatureAlgorithm.getAlgorithmName());
1497         } else {
1498             sig = getSignature(signingKey.getAlgorithm());
1499         }
1500         sig.initVerify(signingKey);
1501 
1502         updateSignature(sig, clntNonce, svrNonce);
1503 
1504         if (sig.verify(signatureBytes) == false ) {
1505             throw new SSLKeyException(
1506                 "Invalid signature on ECDH server key exchange message");
1507         }
1508     }
1509 
1510     /*
1511      * Get the ephemeral EC public key encapsulated in this message.
1512      */
1513     ECPublicKey getPublicKey() {
1514         return publicKey;
1515     }
1516 
1517     private static Signature getSignature(String keyAlgorithm)
1518             throws NoSuchAlgorithmException {
1519             switch (keyAlgorithm) {
1520                 case "EC":
1521                     return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
1522                 case "RSA":
1523                     return RSASignature.getInstance();
1524                 default:
1525                     throw new NoSuchAlgorithmException(
1526                         "neither an RSA or a EC key : " + keyAlgorithm);
1527             }
1528     }
1529 
1530     private void updateSignature(Signature sig, byte[] clntNonce,
1531             byte[] svrNonce) throws SignatureException {
1532         sig.update(clntNonce);
1533         sig.update(svrNonce);
1534 
1535         sig.update((byte)CURVE_NAMED_CURVE);
1536         sig.update((byte)(curveId >> 8));
1537         sig.update((byte)curveId);
1538         sig.update((byte)pointBytes.length);
1539         sig.update(pointBytes);
1540     }
1541 
1542     @Override
1543     int messageLength() {
1544         int sigLen = 0;
1545         if (signatureBytes != null) {
1546             sigLen = 2 + signatureBytes.length;


1713                 SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
1714         } else {
1715             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1716             algorithmsLen = 0;
1717         }
1718     }
1719 
1720     CertificateRequest(HandshakeInStream input,
1721             ProtocolVersion protocolVersion) throws IOException {
1722 
1723         this.protocolVersion = protocolVersion;
1724 
1725         // Read the certificate_types.
1726         types = input.getBytes8();
1727 
1728         // Read the supported_signature_algorithms for TLS 1.2 or later.
1729         if (protocolVersion.useTLS12PlusSpec()) {
1730             algorithmsLen = input.getInt16();
1731             if (algorithmsLen < 2) {
1732                 throw new SSLProtocolException(
1733                     "Invalid supported_signature_algorithms field: " + algorithmsLen);
1734             }
1735 
1736             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1737             int remains = algorithmsLen;
1738             int sequence = 0;
1739             while (remains > 1) {    // needs at least two bytes
1740                 int hash = input.getInt8();         // hash algorithm
1741                 int signature = input.getInt8();    // signature algorithm
1742 
1743                 SignatureAndHashAlgorithm algorithm =
1744                     SignatureAndHashAlgorithm.valueOf(hash, signature,
1745                                                                 ++sequence);
1746                 algorithms.add(algorithm);
1747                 remains -= 2;  // one byte for hash, one byte for signature
1748             }
1749 
1750             if (remains != 0) {
1751                 throw new SSLProtocolException(
1752                     "Invalid supported_signature_algorithms field. remains: " + remains);
1753             }
1754         } else {
1755             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1756             algorithmsLen = 0;
1757         }
1758 
1759         // read the certificate_authorities
1760         int len = input.getInt16();
1761         ArrayList<DistinguishedName> v = new ArrayList<>();
1762         while (len >= 3) {
1763             DistinguishedName dn = new DistinguishedName(input);
1764             v.add(dn);
1765             len -= dn.length();
1766         }
1767 
1768         if (len != 0) {
1769             throw new SSLProtocolException("Bad CertificateRequest DN length: " + len);
1770         }
1771 
1772         authorities = v.toArray(new DistinguishedName[v.size()]);
1773     }
1774 
1775     X500Principal[] getAuthorities() throws IOException {
1776         X500Principal[] ret = new X500Principal[authorities.length];
1777         for (int i = 0; i < authorities.length; i++) {
1778             ret[i] = authorities[i].getX500Principal();
1779         }
1780         return ret;
1781     }
1782 
1783     Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
1784         return algorithms;
1785     }
1786 
1787     @Override
1788     int messageType() {
1789         return ht_certificate_request;


1980     //
1981     CertificateVerify(HandshakeInStream input,
1982             Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
1983             ProtocolVersion protocolVersion) throws IOException  {
1984 
1985         this.protocolVersion = protocolVersion;
1986 
1987         // read the signature and hash algorithm
1988         if (protocolVersion.useTLS12PlusSpec()) {
1989             int hashAlg = input.getInt8();         // hash algorithm
1990             int signAlg = input.getInt8();         // signature algorithm
1991 
1992             preferableSignatureAlgorithm =
1993                 SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
1994 
1995             // Is it a local supported signature algorithm?
1996             if (!localSupportedSignAlgs.contains(
1997                     preferableSignatureAlgorithm)) {
1998                 throw new SSLHandshakeException(
1999                         "Unsupported SignatureAndHashAlgorithm in " +
2000                         "CertificateVerify message: " + preferableSignatureAlgorithm);
2001             }
2002         }
2003 
2004         // read the signature
2005         signature = input.getBytes16();
2006     }
2007 
2008     /*
2009      * Get the preferable signature algorithm used by this message
2010      */
2011     SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
2012         return preferableSignatureAlgorithm;
2013     }
2014 
2015     /*
2016      * Verify a certificate verify message. Return the result of verification,
2017      * if there is a problem throw a GeneralSecurityException.
2018      */
2019     boolean verify(ProtocolVersion protocolVersion,
2020             HandshakeHash handshakeHash, PublicKey publicKey,


2348                 String prfHashAlg = prf.getPRFHashAlg();
2349                 int prfHashLength = prf.getPRFHashLength();
2350                 int prfBlockSize = prf.getPRFBlockSize();
2351 
2352                 /*
2353                  * RFC 5246/7.4.9 says that finished messages can
2354                  * be ciphersuite-specific in both length/PRF hash
2355                  * algorithm.  If we ever run across a different
2356                  * length, this call will need to be updated.
2357                  */
2358                 @SuppressWarnings("deprecation")
2359                 TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
2360                     masterKey, tlsLabel, seed, 12,
2361                     prfHashAlg, prfHashLength, prfBlockSize);
2362 
2363                 KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
2364                 kg.init(spec);
2365                 SecretKey prfKey = kg.generateKey();
2366                 if ("RAW".equals(prfKey.getFormat()) == false) {
2367                     throw new ProviderException(
2368                         "Invalid PRF output, format must be RAW. Format received:" +
2369                         prfKey.getFormat());
2370                 }
2371                 byte[] finished = prfKey.getEncoded();
2372                 return finished;
2373             } catch (GeneralSecurityException e) {
2374                 throw new RuntimeException("PRF failed", e);
2375             }
2376         } else {
2377             // SSLv3
2378             MessageDigest md5Clone = handshakeHash.getMD5Clone();
2379             MessageDigest shaClone = handshakeHash.getSHAClone();
2380             updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
2381             updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
2382             byte[] finished = new byte[36];
2383             try {
2384                 md5Clone.digest(finished, 0, 16);
2385                 shaClone.digest(finished, 16, 20);
2386             } catch (DigestException e) {
2387                 // cannot occur
2388                 throw new RuntimeException("Digest failed", e);
2389             }


< prev index next >