Source Code Cross Referenced for HandshakeMessage.java in  » 6.0-JDK-Modules-sun » security » sun » security » ssl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » security » sun.security.ssl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:/*
0002: * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation.  Sun designates this 
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this  code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this  code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this  work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026:
0027:package sun.security.ssl;
0028:
0029:import java.io.*;
0030:import java.math.BigInteger;
0031:import java.security.*;
0032:import java.security.interfaces.*;
0033:import java.security.spec.*;
0034:import java.security.cert.*;
0035:import java.security.cert.Certificate;
0036:import java.util.*;
0037:import java.util.concurrent.ConcurrentHashMap;
0038:
0039:import java.lang.reflect.*;
0040:
0041:import javax.security.auth.x500.X500Principal;
0042:
0043:import javax.crypto.KeyGenerator;
0044:import javax.crypto.SecretKey;
0045:import javax.crypto.spec.SecretKeySpec;
0046:
0047:import javax.net.ssl.*;
0048:
0049:import sun.security.action.GetPropertyAction;
0050:
0051:import sun.security.internal.spec.TlsPrfParameterSpec;
0052:
0053:import sun.security.ssl.CipherSuite.*;
0054:
0055:/**
0056: * Many data structures are involved in the handshake messages.  These
0057: * classes are used as structures, with public data members.  They are
0058: * not visible outside the SSL package.
0059: *
0060: * Handshake messages all have a common header format, and they are all
0061: * encoded in a "handshake data" SSL record substream.  The base class
0062: * here (HandshakeMessage) provides a common framework and records the
0063: * SSL record type of the particular handshake message.
0064: *
0065: * This file contains subclasses for all the basic handshake messages.
0066: * All handshake messages know how to encode and decode themselves on
0067: * SSL streams; this facilitates using the same code on SSL client and
0068: * server sides, although they don't send and receive the same messages.
0069: *
0070: * Messages also know how to print themselves, which is quite handy
0071: * for debugging.  They always identify their type, and can optionally
0072: * dump all of their content.
0073: *
0074: * @version 1.104, 05/05/07
0075: * @author David Brownell
0076: */
0077:abstract class HandshakeMessage {
0078:
0079:    HandshakeMessage() { }
0080:
0081:    // enum HandshakeType:
0082:    static final byte	ht_hello_request = 0;
0083:    static final byte	ht_client_hello = 1;
0084:    static final byte	ht_server_hello = 2;
0085:
0086:    static final byte	ht_certificate = 11;
0087:    static final byte	ht_server_key_exchange = 12;
0088:    static final byte	ht_certificate_request = 13;
0089:    static final byte	ht_server_hello_done = 14;
0090:    static final byte	ht_certificate_verify = 15;
0091:    static final byte	ht_client_key_exchange = 16;
0092:
0093:    static final byte	ht_finished = 20;
0094:
0095:    /* Class and subclass dynamic debugging support */
0096:    static final Debug debug = Debug.getInstance("ssl");
0097:    
0098:    /**
0099:     * Utility method to convert a BigInteger to a byte array in unsigned
0100:     * format as needed in the handshake messages. BigInteger uses
0101:     * 2's complement format, i.e. it prepends an extra zero if the MSB
0102:     * is set. We remove that.
0103:     */
0104:    static byte[] toByteArray(BigInteger bi) {
0105:	byte[] b = bi.toByteArray();
0106:	if ((b.length > 1) && (b[0] == 0)) {
0107:	    int n = b.length - 1;
0108:	    byte[] newarray = new byte[n];
0109:	    System.arraycopy(b, 1, newarray, 0, n);
0110:	    b = newarray;
0111:	}
0112:	return b;
0113:    }
0114:
0115:    /*
0116:     * SSL 3.0 MAC padding constants.
0117:     * Also used by CertificateVerify and Finished during the handshake.
0118:     */
0119:    static final byte[] MD5_pad1 = genPad(0x36, 48);
0120:    static final byte[] MD5_pad2 = genPad(0x5c, 48);
0121:
0122:    static final byte[] SHA_pad1 = genPad(0x36, 40);
0123:    static final byte[] SHA_pad2 = genPad(0x5c, 40);
0124:
0125:    private static byte[] genPad(int b, int count) {
0126:	byte[] padding = new byte[count];
0127:	Arrays.fill(padding, (byte)b);
0128:	return padding;
0129:    }
0130:
0131:    /*
0132:     * Write a handshake message on the (handshake) output stream.
0133:     * This is just a four byte header followed by the data.
0134:     *
0135:     * NOTE that huge messages -- notably, ones with huge cert
0136:     * chains -- are handled correctly.
0137:     */
0138:    final void write(HandshakeOutStream s) throws IOException {
0139:	int len = messageLength();
0140:	if (len > (1 << 24)) {
0141:	    throw new SSLException("Handshake message too big"
0142:		+ ", type = " + messageType() + ", len = " + len);
0143:	}
0144:	s.write(messageType());
0145:	s.putInt24(len);
0146:	send(s);
0147:    }
0148:
0149:    /*
0150:     * Subclasses implement these methods so those kinds of
0151:     * messages can be emitted.  Base class delegates to subclass.
0152:     */
0153:    abstract int  messageType();
0154:    abstract int  messageLength();
0155:    abstract void send(HandshakeOutStream s) throws IOException;
0156:
0157:    /*
0158:     * Write a descriptive message on the output stream; for debugging.
0159:     */
0160:    abstract void print(PrintStream p) throws IOException;
0161:
0162://
0163:// NOTE:  the rest of these classes are nested within this one, and are
0164:// imported by other classes in this package.  There are a few other
0165:// handshake message classes, not neatly nested here because of current
0166:// licensing requirement for native (RSA) methods.  They belong here,
0167:// but those native methods complicate things a lot!
0168://
0169:
0170:
0171:/*
0172: * HelloRequest ... SERVER --> CLIENT
0173: *
0174: * Server can ask the client to initiate a new handshake, e.g. to change
0175: * session parameters after a connection has been (re)established.
0176: */
0177:static final
0178:class HelloRequest extends HandshakeMessage
0179:{
0180:    int messageType() { return ht_hello_request; }
0181:
0182:    HelloRequest() { }
0183:
0184:    HelloRequest(HandshakeInStream in) throws IOException
0185:    {
0186:	// nothing in this message
0187:    }
0188:
0189:    int messageLength() { return 0; }
0190:
0191:    void send(HandshakeOutStream out) throws IOException
0192:    {
0193:	// nothing in this messaage
0194:    }
0195:
0196:    void print(PrintStream out) throws IOException
0197:    {
0198:	out.println("*** HelloRequest (empty)");
0199:    }
0200:
0201:}
0202:
0203:
0204:/*
0205: * ClientHello ... CLIENT --> SERVER
0206: *
0207: * Client initiates handshake by telling server what it wants, and what it
0208: * can support (prioritized by what's first in the ciphe suite list).
0209: *
0210: * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
0211: * will have more data added at the end ... e.g. what CAs the client trusts.
0212: * Until we know how to parse it, we will just read what we know
0213: * about, and let our caller handle the jumps over unknown data.
0214: */
0215:static final
0216:class ClientHello extends HandshakeMessage
0217:{
0218:    int messageType() { return ht_client_hello; }
0219:
0220:    ProtocolVersion	protocolVersion;
0221:    RandomCookie	clnt_random;
0222:    SessionId		sessionId;
0223:    private CipherSuiteList    cipherSuites;
0224:    byte[]		compression_methods;
0225:
0226:    HelloExtensions extensions = new HelloExtensions();
0227:    
0228:    private final static byte[]	 NULL_COMPRESSION = new byte[] {0};
0229:
0230:    ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
0231:	this .protocolVersion = protocolVersion;
0232:	clnt_random = new RandomCookie(generator);
0233:	compression_methods = NULL_COMPRESSION;
0234:	// sessionId, cipher_suites TBS later
0235:    }
0236:    
0237:    CipherSuiteList getCipherSuites() {
0238:	return cipherSuites;
0239:    }
0240:
0241:    // Set the ciphersuites.
0242:    // This method may only be called once.
0243:    void setCipherSuites(CipherSuiteList cipherSuites) {
0244:	this .cipherSuites = cipherSuites;
0245:	if (cipherSuites.containsEC()) {
0246:	    extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
0247:	    extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
0248:	}
0249:    }
0250:    
0251:    int messageLength() {
0252:	/*
0253:	 * Add fixed size parts of each field...
0254:	 * version + random + session + cipher + compress
0255:	 */
0256:	return (2 + 32 + 1 + 2 + 1
0257:	    + sessionId.length()		/* ... + variable parts */
0258:	    + (cipherSuites.size() * 2)
0259:	    + compression_methods.length)
0260:	    + extensions.length();
0261:    }
0262:
0263:    ClientHello(HandshakeInStream s, int messageLength) throws IOException {
0264:	protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
0265:	clnt_random = new RandomCookie(s);
0266:	sessionId = new SessionId(s.getBytes8());
0267:	cipherSuites = new CipherSuiteList(s);
0268:	compression_methods = s.getBytes8();
0269:	if (messageLength() != messageLength) {
0270:	    extensions = new HelloExtensions(s);
0271:	}
0272:    }
0273:
0274:    void send(HandshakeOutStream s) throws IOException {
0275:	s.putInt8(protocolVersion.major);
0276:	s.putInt8(protocolVersion.minor);
0277:	clnt_random.send(s);
0278:	s.putBytes8(sessionId.getId());
0279:	cipherSuites.send(s);
0280:	s.putBytes8(compression_methods);
0281:	extensions.send(s);
0282:    }
0283:
0284:    void print(PrintStream s) throws IOException {
0285:	s.println("*** ClientHello, " + protocolVersion);
0286:
0287:	if (debug != null && Debug.isOn("verbose")) {
0288:	    s.print   ("RandomCookie:  "); clnt_random.print(s);
0289:
0290:	    s.print("Session ID:  ");
0291:	    s.println(sessionId);
0292:
0293:	    s.println("Cipher Suites: " + cipherSuites);
0294:	    
0295:	    Debug.println(s, "Compression Methods", compression_methods);
0296:	    extensions.print(s);
0297:	    s.println("***");
0298:	}
0299:    }
0300:}
0301:
0302:/*
0303: * ServerHello ... SERVER --> CLIENT
0304: *
0305: * Server chooses protocol options from among those it supports and the
0306: * client supports.  Then it sends the basic session descriptive parameters
0307: * back to the client.
0308: */
0309:static final
0310:class ServerHello extends HandshakeMessage
0311:{
0312:    int messageType() { return ht_server_hello; }
0313:    
0314:    ProtocolVersion	protocolVersion;
0315:    RandomCookie	svr_random;
0316:    SessionId           sessionId;
0317:    CipherSuite		cipherSuite;
0318:    byte		compression_method;
0319:    HelloExtensions extensions = new HelloExtensions();
0320:    int extensionLength;
0321:
0322:    ServerHello() {
0323:	// empty
0324:    }
0325:
0326:    ServerHello(HandshakeInStream input, int messageLength) throws IOException {
0327:	protocolVersion = ProtocolVersion.valueOf(input.getInt8(), 
0328:						  input.getInt8());
0329:	svr_random = new RandomCookie(input);
0330:	sessionId = new SessionId(input.getBytes8());
0331:	cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
0332:	compression_method = (byte)input.getInt8();
0333:	if (messageLength() != messageLength) {
0334:	    extensions = new HelloExtensions(input);
0335:	}
0336:    }
0337:
0338:    int messageLength()
0339:    {
0340:	// almost fixed size, except session ID and extensions:
0341:	//	major + minor = 2
0342:	//	random = 32
0343:	//	session ID len field = 1
0344:	//	cipher suite + compression = 3
0345:	//	extensions: if present, 2 + length of extensions
0346:	return 38 + sessionId.length() + extensions.length();
0347:    }
0348:
0349:    void send(HandshakeOutStream s) throws IOException
0350:    {
0351:	s.putInt8(protocolVersion.major);
0352:	s.putInt8(protocolVersion.minor);
0353:	svr_random.send(s);
0354:	s.putBytes8(sessionId.getId());
0355:	s.putInt8(cipherSuite.id >> 8);
0356:	s.putInt8(cipherSuite.id & 0xff);
0357:	s.putInt8(compression_method);
0358:	extensions.send(s);
0359:    }
0360:
0361:    void print(PrintStream s) throws IOException
0362:    {
0363:	s.println("*** ServerHello, " + protocolVersion);
0364:
0365:	if (debug != null && Debug.isOn("verbose")) {
0366:	    s.print   ("RandomCookie:  "); svr_random.print(s);
0367:
0368:	    int i;
0369:
0370:	    s.print("Session ID:  ");
0371:	    s.println(sessionId);
0372:
0373:	    s.println("Cipher Suite: " + cipherSuite);
0374:	    s.println("Compression Method: " + compression_method);
0375:	    extensions.print(s);
0376:	    s.println("***");
0377:	}
0378:    }
0379:}
0380:
0381:
0382:/*
0383: * CertificateMsg ... send by both CLIENT and SERVER
0384: *
0385: * Each end of a connection may need to pass its certificate chain to
0386: * the other end.  Such chains are intended to validate an identity with
0387: * reference to some certifying authority.  Examples include companies
0388: * like Verisign, or financial institutions.  There's some control over
0389: * the certifying authorities which are sent.
0390: *
0391: * NOTE: that these messages might be huge, taking many handshake records.
0392: * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
0393: * bytes each ... up to 2^32 records sent on the output stream.
0394: */
0395:static final
0396:class CertificateMsg extends HandshakeMessage
0397:{
0398:    int messageType() { return ht_certificate; }
0399:
0400:    private X509Certificate[] chain;
0401:    
0402:    private List<byte[]> encodedChain;
0403:    
0404:    private int messageLength;
0405:
0406:    CertificateMsg(X509Certificate[] certs) {
0407:	chain = certs;
0408:    }
0409:
0410:    CertificateMsg(HandshakeInStream input) throws IOException {
0411:	int chainLen = input.getInt24();
0412:	List<Certificate> v = new ArrayList<Certificate>(4);
0413:
0414:	CertificateFactory cf = null;
0415:	while (chainLen > 0) {
0416:	    byte[] cert = input.getBytes24();
0417:	    chainLen -= (3 + cert.length);
0418:	    try {
0419:		if (cf == null) {
0420:		    cf = CertificateFactory.getInstance("X.509");
0421:		}
0422:		v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
0423:	    } catch (CertificateException e) {
0424:		throw (SSLProtocolException)new SSLProtocolException
0425:			(e.getMessage()).initCause(e);
0426:	    }
0427:	}
0428:
0429:	chain = v.toArray(new X509Certificate[v.size()]);
0430:    }
0431:    
0432:    int messageLength() {
0433:	if (encodedChain == null) {
0434:	    messageLength = 3;
0435:	    encodedChain = new ArrayList<byte[]>(chain.length);
0436:	    try {
0437:		for (X509Certificate cert : chain) {
0438:		    byte[] b = cert.getEncoded();
0439:		    encodedChain.add(b);
0440:		    messageLength += b.length + 3;
0441:		}
0442:	    } catch (CertificateEncodingException e) {
0443:		encodedChain = null;
0444:		throw new RuntimeException("Could not encode certificates", e);
0445:	    }
0446:	}
0447:	return messageLength;
0448:    }
0449:
0450:    void send(HandshakeOutStream s) throws IOException {
0451:	s.putInt24(messageLength() - 3);
0452:	for (byte[] b : encodedChain) {
0453:	    s.putBytes24(b);
0454:	}
0455:    }
0456:
0457:    void print(PrintStream s) throws IOException {
0458:	s.println("*** Certificate chain");
0459:
0460:	if (debug != null && Debug.isOn("verbose")) {
0461:	    for (int i = 0; i < chain.length; i++)
0462:		s.println("chain [" + i + "] = " + chain[i]);
0463:	    s.println("***");
0464:	}
0465:    }
0466:
0467:    X509Certificate[] getCertificateChain() {
0468:	return chain;
0469:    }
0470:}
0471:
0472:
0473:/*
0474: * ServerKeyExchange ... SERVER --> CLIENT
0475: *
0476: * The cipher suite selected, when combined with the certificate exchanged,
0477: * implies one of several different kinds of key exchange.  Most current
0478: * cipher suites require the server to send more than its certificate.
0479: *
0480: * The primary exceptions are when a server sends an encryption-capable
0481: * RSA public key in its cert, to be used with RSA (or RSA_export) key
0482: * exchange; and when a server sends its Diffie-Hellman cert.  Those kinds
0483: * of key exchange do not require a ServerKeyExchange message.
0484: *
0485: * Key exchange can be viewed as having three modes, which are explicit
0486: * for the Diffie-Hellman flavors and poorly specified for RSA ones:
0487: *
0488: *	- "Ephemeral" keys.  Here, a "temporary" key is allocated by the
0489: *	  server, and signed.  Diffie-Hellman keys signed using RSA or
0490: *	  DSS are ephemeral (DHE flavor).  RSA keys get used to do the same
0491: *	  thing, to cut the key size down to 512 bits (export restrictions)
0492: *	  or for signing-only RSA certificates.
0493: *
0494: *	- Anonymity.  Here no server certificate is sent, only the public
0495: *	  key of the server.  This case is subject to man-in-the-middle
0496: *	  attacks.  This can be done with Diffie-Hellman keys (DH_anon) or
0497: *	  with RSA keys, but is only used in SSLv3 for DH_anon.
0498: *
0499: *	- "Normal" case.  Here a server certificate is sent, and the public
0500: *	  key there is used directly in exchanging the premaster secret.
0501: *	  For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
0502: *	  only 512 bit keys.
0503: *
0504: * If a server certificate is sent, there is no anonymity.  However,
0505: * when a certificate is sent, ephemeral keys may still be used to
0506: * exchange the premaster secret.  That's how RSA_EXPORT often works,
0507: * as well as how the DHE_* flavors work.
0508: */
0509:static abstract class ServerKeyExchange extends HandshakeMessage
0510:{
0511:    int messageType() { return ht_server_key_exchange; }
0512:}
0513:
0514:
0515:/*
0516: * Using RSA for Key Exchange:  exchange a session key that's not as big
0517: * as the signing-only key.  Used for export applications, since exported
0518: * RSA encryption keys can't be bigger than 512 bytes.
0519: *
0520: * This is never used when keys are 512 bits or smaller, and isn't used
0521: * on "US Domestic" ciphers in any case.
0522: */
0523:static final
0524:class RSA_ServerKeyExchange extends ServerKeyExchange
0525:{
0526:    private byte rsa_modulus[];     // 1 to 2^16 - 1 bytes
0527:    private byte rsa_exponent[];    // 1 to 2^16 - 1 bytes
0528:
0529:    private Signature signature;
0530:    private byte[] signatureBytes;
0531:
0532:    /*
0533:     * Hash the nonces and the ephemeral RSA public key.
0534:     */
0535:    private void updateSignature(byte clntNonce[], byte svrNonce[]) 
0536:	    throws SignatureException {
0537:	int tmp;
0538:
0539:	signature.update(clntNonce);
0540:	signature.update(svrNonce);
0541:
0542:	tmp = rsa_modulus.length;
0543:	signature.update((byte)(tmp >> 8));
0544:	signature.update((byte)(tmp & 0x0ff));
0545:	signature.update(rsa_modulus);
0546:
0547:	tmp = rsa_exponent.length;
0548:	signature.update((byte)(tmp >> 8));
0549:	signature.update((byte)(tmp & 0x0ff));
0550:	signature.update(rsa_exponent);
0551:    }
0552:
0553:
0554:    /*
0555:     * Construct an RSA server key exchange message, using data
0556:     * known _only_ to the server.
0557:     *
0558:     * The client knows the public key corresponding to this private
0559:     * key, from the Certificate message sent previously.  To comply
0560:     * with US export regulations we use short RSA keys ... either
0561:     * long term ones in the server's X509 cert, or else ephemeral
0562:     * ones sent using this message.
0563:     */
0564:    RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
0565:    	    RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
0566:	    throws GeneralSecurityException {
0567:	RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
0568:	rsa_modulus = toByteArray(rsaKey.getModulus());
0569:	rsa_exponent = toByteArray(rsaKey.getPublicExponent());
0570:	signature = RSASignature.getInstance();
0571:	signature.initSign(privateKey, sr);
0572:	updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
0573:	signatureBytes = signature.sign();
0574:    }
0575:
0576:
0577:    /*
0578:     * Parse an RSA server key exchange message, using data known
0579:     * to the client (and, in some situations, eavesdroppers).
0580:     */
0581:    RSA_ServerKeyExchange(HandshakeInStream input)
0582:    	    throws IOException, NoSuchAlgorithmException {
0583:	signature = RSASignature.getInstance();
0584:	rsa_modulus = input.getBytes16();
0585:	rsa_exponent = input.getBytes16();
0586:	signatureBytes = input.getBytes16();
0587:    }
0588:
0589:    /*
0590:     * Get the ephemeral RSA public key that will be used in this
0591:     * SSL connection.
0592:     */
0593:    PublicKey getPublicKey() {
0594:	try {
0595:	    KeyFactory kfac = JsseJce.getKeyFactory("RSA");
0596:	    // modulus and exponent are always positive
0597:	    RSAPublicKeySpec kspec = new RSAPublicKeySpec
0598:					 (new BigInteger(1, rsa_modulus),
0599:					  new BigInteger(1, rsa_exponent));
0600:	    return kfac.generatePublic(kspec);
0601:	} catch (Exception e) {
0602:	    throw new RuntimeException(e);
0603:	}
0604:    }
0605:
0606:    /*
0607:     * Verify the signed temporary key using the hashes computed
0608:     * from it and the two nonces.  This is called by clients
0609:     * with "exportable" RSA flavors.
0610:     */
0611:    boolean verify(PublicKey certifiedKey, RandomCookie clntNonce, 
0612:	    RandomCookie svrNonce) throws GeneralSecurityException { 
0613:	signature.initVerify(certifiedKey);
0614:	updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
0615:	return signature.verify(signatureBytes);
0616:    }
0617:
0618:    int messageLength() {
0619:	return 6 + rsa_modulus.length + rsa_exponent.length
0620:	       + signatureBytes.length;
0621:    }
0622:
0623:    void send(HandshakeOutStream s) throws IOException {
0624:	s.putBytes16(rsa_modulus);
0625:	s.putBytes16(rsa_exponent);
0626:	s.putBytes16(signatureBytes);
0627:    }
0628:
0629:    void print(PrintStream s) throws IOException {
0630:	s.println("*** RSA ServerKeyExchange");
0631:
0632:	if (debug != null && Debug.isOn("verbose")) {
0633:	    Debug.println(s, "RSA Modulus", rsa_modulus);
0634:	    Debug.println(s, "RSA Public Exponent", rsa_exponent);
0635:	}
0636:    }
0637:}
0638:
0639:
0640:/*
0641: * Using Diffie-Hellman algorithm for key exchange.  All we really need to
0642: * do is securely get Diffie-Hellman keys (using the same P, G parameters)
0643: * to our peer, then we automatically have a shared secret without need
0644: * to exchange any more data.  (D-H only solutions, such as SKIP, could
0645: * eliminate key exchange negotiations and get faster connection setup.
0646: * But they still need a signature algorithm like DSS/DSA to support the
0647: * trusted distribution of keys without relying on unscalable physical
0648: * key distribution systems.)
0649: *
0650: * This class supports several DH-based key exchange algorithms, though
0651: * perhaps eventually each deserves its own class.  Notably, this has
0652: * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
0653: */
0654:static final
0655:class DH_ServerKeyExchange extends ServerKeyExchange
0656:{
0657:    // Fix message encoding, see 4348279
0658:    private final static boolean dhKeyExchangeFix = 
0659:    	Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
0660:
0661:    private byte		dh_p [];	// 1 to 2^16 - 1 bytes
0662:    private byte		dh_g [];	// 1 to 2^16 - 1 bytes
0663:    private byte		dh_Ys [];	// 1 to 2^16 - 1 bytes
0664:
0665:    private byte		signature [];
0666:
0667:    /* Return the Diffie-Hellman modulus */
0668:    BigInteger getModulus() {
0669:    	return new BigInteger(1, dh_p);
0670:    }
0671:
0672:    /* Return the Diffie-Hellman base/generator */
0673:    BigInteger getBase() {
0674:    	return new BigInteger(1, dh_g);
0675:    }
0676:
0677:    /* Return the server's Diffie-Hellman public key */
0678:    BigInteger getServerPublicKey() {
0679:    	return new BigInteger(1, dh_Ys);
0680:    }
0681:
0682:    /*
0683:     * Update sig with nonces and Diffie-Hellman public key.
0684:     */
0685:    private void updateSignature(Signature sig, byte clntNonce[], 
0686:    	    byte svrNonce[]) throws SignatureException {
0687:	int tmp;
0688:
0689:	sig.update(clntNonce);
0690:	sig.update(svrNonce);
0691:
0692:	tmp = dh_p.length;
0693:	sig.update((byte)(tmp >> 8));
0694:	sig.update((byte)(tmp & 0x0ff));
0695:	sig.update(dh_p);
0696:
0697:	tmp = dh_g.length;
0698:	sig.update((byte)(tmp >> 8));
0699:	sig.update((byte)(tmp & 0x0ff));
0700:	sig.update(dh_g);
0701:
0702:	tmp = dh_Ys.length;
0703:	sig.update((byte)(tmp >> 8));
0704:	sig.update((byte)(tmp & 0x0ff));
0705:	sig.update(dh_Ys);
0706:    }
0707:
0708:    /*
0709:     * Construct from initialized DH key object, for DH_anon
0710:     * key exchange.
0711:     */
0712:    DH_ServerKeyExchange(DHCrypt obj) {
0713:	getValues(obj);
0714:	signature = null;
0715:    }
0716:
0717:    /*
0718:     * Construct from initialized DH key object and the key associated
0719:     * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
0720:     * key exchange.  (Constructor called by server.)
0721:     */
0722:    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
0723:	    byte svrNonce[], SecureRandom sr) throws GeneralSecurityException {
0724:
0725:	getValues(obj);
0726:
0727:	Signature sig;
0728:	if (key.getAlgorithm().equals("DSA")) {
0729:	    sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
0730:	} else {
0731:	    sig = RSASignature.getInstance();
0732:	}
0733:	sig.initSign(key, sr);
0734:	updateSignature(sig, clntNonce, svrNonce);
0735:	signature = sig.sign();
0736:    }
0737:
0738:    private void getValues(DHCrypt obj) {
0739:	dh_p = toByteArray(obj.getModulus());
0740:	dh_g = toByteArray(obj.getBase());
0741:	dh_Ys = toByteArray(obj.getPublicKey());
0742:    }
0743:
0744:    /*
0745:     * Construct a DH_ServerKeyExchange message from an input
0746:     * stream, as if sent from server to client for use with
0747:     * DH_anon key exchange
0748:     */
0749:    DH_ServerKeyExchange(HandshakeInStream input) throws IOException {
0750:	dh_p = input.getBytes16();
0751:	dh_g = input.getBytes16();
0752:	dh_Ys = input.getBytes16();
0753:	signature = null;
0754:    }
0755:
0756:    /*
0757:     * Construct a DH_ServerKeyExchange message from an input stream
0758:     * and a certificate, as if sent from server to client for use with
0759:     * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
0760:     */
0761:    DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
0762:    	    byte clntNonce[], byte svrNonce[], int messageSize) 
0763:	    throws IOException, GeneralSecurityException {
0764:
0765:	dh_p = input.getBytes16();
0766:	dh_g = input.getBytes16();
0767:	dh_Ys = input.getBytes16();
0768:
0769:	byte signature[];
0770:	if (dhKeyExchangeFix) {
0771:	    signature = input.getBytes16();
0772:	} else {
0773:	    messageSize -= (dh_p.length + 2);
0774:	    messageSize -= (dh_g.length + 2);
0775:	    messageSize -= (dh_Ys.length + 2);
0776:
0777:	    signature = new byte[messageSize];
0778:	    input.read(signature);
0779:	}
0780:	
0781:	Signature sig;
0782:	String algorithm = publicKey.getAlgorithm();
0783:	if (algorithm.equals("DSA")) {
0784:	    sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
0785:	} else if (algorithm.equals("RSA")) {
0786:	    sig = RSASignature.getInstance();
0787:	} else {
0788:	    throw new SSLKeyException("neither an RSA or a DSA key");
0789:	}
0790:
0791:	sig.initVerify(publicKey);
0792:	updateSignature(sig, clntNonce, svrNonce);
0793:
0794:	if (sig.verify(signature) == false ) {
0795:	    throw new SSLKeyException("Server D-H key verification failed");
0796:	}
0797:    }
0798:
0799:    int messageLength() {
0800:	int temp = 6;	// overhead for p, g, y(s) values.
0801:
0802:	temp += dh_p.length;
0803:	temp += dh_g.length;
0804:	temp += dh_Ys.length;
0805:	if (signature != null) {
0806:	    temp += signature.length;
0807:	    if (dhKeyExchangeFix) {
0808:		temp += 2;
0809:	    }
0810:	}
0811:	return temp;
0812:    }
0813:
0814:    void send(HandshakeOutStream s) throws IOException {
0815:	s.putBytes16(dh_p);
0816:	s.putBytes16(dh_g);
0817:	s.putBytes16(dh_Ys);
0818:	if (signature != null) {
0819:	    if (dhKeyExchangeFix) {
0820:		s.putBytes16(signature);
0821:	    } else {
0822:		s.write(signature);
0823:	    }
0824:	}
0825:    }
0826:
0827:    void print(PrintStream s) throws IOException {
0828:	s.println("*** Diffie-Hellman ServerKeyExchange");
0829:
0830:	if (debug != null && Debug.isOn("verbose")) {
0831:	    Debug.println(s, "DH Modulus", dh_p);
0832:	    Debug.println(s, "DH Base", dh_g);
0833:	    Debug.println(s, "Server DH Public Key", dh_Ys);
0834:
0835:	    if (signature == null) {
0836:		s.println("Anonymous");
0837:	    } else {
0838:		s.println("Signed with a DSA or RSA public key");
0839:	    }
0840:	}
0841:    }
0842:}
0843:
0844:/*
0845: * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
0846: * ciphersuites to communicate its ephemeral public key (including the
0847: * EC domain parameters).
0848: *
0849: * We support named curves only, no explicitly encoded curves.
0850: */
0851:static final
0852:class ECDH_ServerKeyExchange extends ServerKeyExchange
0853:{
0854:
0855:    // constants for ECCurveType
0856:    private final static int CURVE_EXPLICIT_PRIME = 1;
0857:    private final static int CURVE_EXPLICIT_CHAR2 = 2;
0858:    private final static int CURVE_NAMED_CURVE    = 3;
0859:
0860:    // id of the curve we are using
0861:    private int curveId;
0862:    // encoded public point
0863:    private byte[] pointBytes;
0864:
0865:    // signature bytes (or null if anonymous)
0866:    private byte[] signatureBytes;
0867:
0868:    // public key object encapsulated in this message
0869:    private ECPublicKey publicKey;
0870:    
0871:    ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
0872:    	    byte[] clntNonce, byte[] svrNonce, SecureRandom sr)
0873:	    throws GeneralSecurityException {
0874:	publicKey = (ECPublicKey)obj.getPublicKey();
0875:	ECParameterSpec params = publicKey.getParams();
0876:	ECPoint point = publicKey.getW();
0877:	pointBytes = JsseJce.encodePoint(point, params.getCurve());
0878:	curveId = SupportedEllipticCurvesExtension.getCurveIndex(params);
0879:	
0880:	if (privateKey == null) {
0881:	    // ECDH_anon
0882:	    return;
0883:	}
0884:
0885:	Signature sig = getSignature(privateKey.getAlgorithm());
0886:	sig.initSign(privateKey);
0887:	
0888:	updateSignature(sig, clntNonce, svrNonce);
0889:	signatureBytes = sig.sign();
0890:    }
0891:    
0892:    /*
0893:     * Parse an ECDH server key exchange message.
0894:     */
0895:    ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
0896:    	    byte[] clntNonce, byte[] svrNonce) 
0897:	    throws IOException, GeneralSecurityException {
0898:	int curveType = input.getInt8();
0899:	ECParameterSpec parameters;
0900:	// These parsing errors should never occur as we negotiated
0901:	// the supported curves during the exchange of the Hello messages.
0902:	if (curveType == CURVE_NAMED_CURVE) {
0903:	    curveId = input.getInt16();
0904:	    if (SupportedEllipticCurvesExtension.isSupported(curveId) == false) {
0905:		throw new SSLHandshakeException("Unsupported curveId: " + curveId);
0906:	    }
0907:	    String curveOid = SupportedEllipticCurvesExtension.getCurveOid(curveId);
0908:	    if (curveOid == null) {
0909:		throw new SSLHandshakeException("Unknown named curve: " + curveId);
0910:	    }
0911:	    parameters = JsseJce.getECParameterSpec(curveOid);
0912:	    if (parameters == null) {
0913:		throw new SSLHandshakeException("Unsupported curve: " + curveOid);
0914:	    }
0915:	} else {
0916:	    throw new SSLHandshakeException("Unsupported ECCurveType: " + curveType);
0917:	}
0918:	pointBytes = input.getBytes8();
0919:
0920:	ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
0921:	KeyFactory factory = JsseJce.getKeyFactory("EC");
0922:	publicKey = (ECPublicKey)factory.generatePublic(new ECPublicKeySpec(point, parameters));
0923:	
0924:	if (signingKey == null) {
0925:	    // ECDH_anon
0926:	    return;
0927:	}
0928:
0929:	// verify the signature
0930:	signatureBytes = input.getBytes16();
0931:	Signature sig = getSignature(signingKey.getAlgorithm());
0932:	sig.initVerify(signingKey);
0933:	
0934:	updateSignature(sig, clntNonce, svrNonce);
0935:	
0936:	if (sig.verify(signatureBytes) == false ) {
0937:	    throw new SSLKeyException
0938:		("Invalid signature on ECDH server key exchange message");
0939:	}
0940:    }
0941:
0942:    /*
0943:     * Get the ephemeral EC public key encapsulated in this message.
0944:     */
0945:    ECPublicKey getPublicKey() {
0946:	return publicKey;
0947:    }
0948:
0949:    private static Signature getSignature(String keyAlgorithm) throws NoSuchAlgorithmException {
0950:	if (keyAlgorithm.equals("EC")) {
0951:	    return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
0952:	} else if (keyAlgorithm.equals("RSA")) {
0953:	    return RSASignature.getInstance();
0954:	} else {
0955:	    throw new NoSuchAlgorithmException("neither an RSA or a EC key");
0956:	}
0957:    }
0958:
0959:    private void updateSignature(Signature sig, byte clntNonce[],
0960:	    byte svrNonce[]) throws SignatureException {
0961:	sig.update(clntNonce);
0962:	sig.update(svrNonce);
0963:	
0964:	sig.update((byte)CURVE_NAMED_CURVE);
0965:	sig.update((byte)(curveId >> 8));
0966:	sig.update((byte)curveId);
0967:	sig.update((byte)pointBytes.length);
0968:	sig.update(pointBytes);
0969:    }
0970:
0971:    int messageLength() {
0972:	int sigLen = (signatureBytes == null) ? 0 : 2 + signatureBytes.length;
0973:	return 4 + pointBytes.length + sigLen;
0974:    }
0975:
0976:    void send(HandshakeOutStream s) throws IOException {
0977:	s.putInt8(CURVE_NAMED_CURVE);
0978:	s.putInt16(curveId);
0979:	s.putBytes8(pointBytes);
0980:	if (signatureBytes != null) {
0981:	    s.putBytes16(signatureBytes);
0982:	}
0983:    }
0984:
0985:    void print(PrintStream s) throws IOException {
0986:	s.println("*** ECDH ServerKeyExchange");
0987:
0988:	if (debug != null && Debug.isOn("verbose")) {
0989:	    s.println("Server key: " + publicKey);
0990:	}
0991:    }
0992:}
0993:
0994:static final class DistinguishedName {
0995:
0996:    /* 
0997:     * DER encoded distinguished name.
0998:     * TLS requires that its not longer than 65535 bytes.
0999:     */ 
1000:    byte name[];
1001:
1002:    DistinguishedName(HandshakeInStream input) throws IOException {
1003:	name = input.getBytes16();
1004:    }
1005:
1006:    DistinguishedName(X500Principal dn) {
1007:        name = dn.getEncoded();
1008:    }
1009:    
1010:    X500Principal getX500Principal() throws IOException {
1011:        try {
1012:            return new X500Principal(name);
1013:	} catch (IllegalArgumentException e) {
1014:	    throw (SSLProtocolException)new SSLProtocolException
1015:		    (e.getMessage()).initCause(e);
1016:	}
1017:    }
1018:
1019:    int length() { 
1020:        return 2 + name.length;
1021:    }
1022:
1023:    void send(HandshakeOutStream output) throws IOException {
1024:	output.putBytes16(name);
1025:    }
1026:
1027:    void print(PrintStream output) throws IOException {
1028:        X500Principal principal = new X500Principal(name);
1029:	output.println("<" + principal.toString() + ">");
1030:    }
1031:}
1032:
1033:/*
1034: * CertificateRequest ... SERVER --> CLIENT
1035: *
1036: * Authenticated servers may ask clients to authenticate themselves
1037: * in turn, using this message.
1038: */
1039:static final
1040:class CertificateRequest extends HandshakeMessage
1041:{
1042:    int messageType() { return ht_certificate_request; }
1043:
1044:    // enum ClientCertificateType
1045:    static final int   cct_rsa_sign = 1;
1046:    static final int   cct_dss_sign = 2;
1047:    static final int   cct_rsa_fixed_dh = 3;
1048:    static final int   cct_dss_fixed_dh = 4;
1049:    
1050:    // The existance of these two values is a bug in the SSL specification.
1051:    // They are never used in the protocol.
1052:    static final int   cct_rsa_ephemeral_dh = 5;
1053:    static final int   cct_dss_ephemeral_dh = 6;
1054:    
1055:    // From RFC 4492 (ECC)
1056:    static final int	cct_ecdsa_sign       = 64;
1057:    static final int	cct_rsa_fixed_ecdh   = 65;
1058:    static final int	cct_ecdsa_fixed_ecdh = 66;
1059:
1060:    private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
1061:    private final static byte[] TYPES_ECC = 
1062:	{ cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
1063:    
1064:    byte		types [];		// 1 to 255 types
1065:    DistinguishedName	authorities [];		// 3 to 2^16 - 1
1066:	// ... "3" because that's the smallest DER-encoded X500 DN
1067:    
1068:    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange) 
1069:	    throws IOException {
1070:	// always use X500Principal
1071:	authorities = new DistinguishedName[ca.length];
1072:	for (int i = 0; i < ca.length; i++) {
1073:	    X500Principal x500Principal = ca[i].getSubjectX500Principal();
1074:	    authorities[i] = new DistinguishedName(x500Principal);
1075:	}
1076:	// we support RSA, DSS, and ECDSA client authentication and they
1077:	// can be used with all ciphersuites. If this changes, the code
1078:	// needs to be adapted to take keyExchange into account.
1079:	// We only request ECDSA client auth if we have ECC crypto available.
1080:	this .types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
1081:    }
1082:
1083:    CertificateRequest(HandshakeInStream input) throws IOException {
1084:	types = input.getBytes8();
1085:	int len = input.getInt16();
1086:	ArrayList<DistinguishedName> v = new ArrayList<DistinguishedName>();
1087:	while (len >= 3) {
1088:	    DistinguishedName dn = new DistinguishedName(input);
1089:	    v.add(dn);
1090:	    len -= dn.length();
1091:	}
1092:
1093:	if (len != 0) {
1094:	    throw new SSLProtocolException("Bad CertificateRequest DN length");
1095:	}
1096:	
1097:	authorities = v.toArray(new DistinguishedName[v.size()]);
1098:    }
1099:
1100:    X500Principal[] getAuthorities() throws IOException {
1101:	X500Principal[] ret = new X500Principal[authorities.length];
1102:	for (int i = 0; i < authorities.length; i++) {
1103:	    ret[i] = authorities[i].getX500Principal();
1104:	}
1105:	return ret;
1106:    }
1107:
1108:    int messageLength()
1109:    {
1110:	int len;
1111:
1112:	len = 1 + types.length + 2;
1113:	for (int i = 0; i < authorities.length; i++)
1114:	    len += authorities[i].length();
1115:	return len;
1116:    }
1117:
1118:    void send(HandshakeOutStream output) throws IOException
1119:    {
1120:	int	len = 0;
1121:
1122:	for (int i = 0; i < authorities.length; i++)
1123:	    len += authorities[i].length();
1124:
1125:	output.putBytes8(types);
1126:	output.putInt16(len);
1127:	for (int i = 0; i < authorities.length; i++)
1128:	    authorities[i].send(output);
1129:    }
1130:
1131:    void print(PrintStream s) throws IOException
1132:    {
1133:	s.println("*** CertificateRequest");
1134:
1135:	if (debug != null && Debug.isOn("verbose")) {
1136:	    s.print("Cert Types: ");
1137:	    for (int i = 0; i < types.length; i++) {
1138:		switch (types[i]) {
1139:		  case cct_rsa_sign:
1140:		    s.print("RSA"); break;
1141:		  case cct_dss_sign:
1142:		    s.print("DSS"); break;
1143:		  case cct_rsa_fixed_dh:
1144:		    s.print("Fixed DH (RSA sig)"); break;
1145:		  case cct_dss_fixed_dh:
1146:		    s.print("Fixed DH (DSS sig)"); break;
1147:		  case cct_rsa_ephemeral_dh:
1148:		    s.print("Ephemeral DH (RSA sig)"); break;
1149:		  case cct_dss_ephemeral_dh:
1150:		    s.print("Ephemeral DH (DSS sig)"); break;
1151:		  case cct_ecdsa_sign:
1152:		    s.print("ECDSA"); break;
1153:		  case cct_rsa_fixed_ecdh:
1154:		    s.print("Fixed ECDH (RSA sig)"); break;
1155:		  case cct_ecdsa_fixed_ecdh:
1156:		    s.print("Fixed ECDH (ECDSA sig)"); break;
1157:		  default:
1158:		    s.print("Type-" + (types[i] & 0xff)); break;
1159:		}
1160:		if (i != types.length - 1) {
1161:		    s.print(", ");
1162:		}
1163:	    }
1164:	    s.println();
1165:
1166:	    s.println("Cert Authorities:");
1167:	    for (int i = 0; i < authorities.length; i++)
1168:		authorities[i].print(s);
1169:	}
1170:    }
1171:}
1172:
1173:
1174:/*
1175: * ServerHelloDone ... SERVER --> CLIENT
1176: *
1177: * When server's done sending its messages in response to the client's
1178: * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
1179: * client certificate request) it sends this message to flag that it's
1180: * done that part of the handshake.
1181: */
1182:static final
1183:class ServerHelloDone extends HandshakeMessage
1184:{
1185:    int messageType() { return ht_server_hello_done; }
1186:
1187:    ServerHelloDone() { }
1188:
1189:    ServerHelloDone(HandshakeInStream input)
1190:    {
1191:	// nothing to do
1192:    }
1193:
1194:    int messageLength()
1195:    {
1196:	return 0;
1197:    }
1198:
1199:    void send(HandshakeOutStream s) throws IOException
1200:    {
1201:	// nothing to send
1202:    }
1203:
1204:    void print(PrintStream s) throws IOException
1205:    {
1206:	s.println("*** ServerHelloDone");
1207:    }
1208:}
1209:
1210:
1211:/*
1212: * CertificateVerify ... CLIENT --> SERVER
1213: *
1214: * Sent after client sends signature-capable certificates (e.g. not
1215: * Diffie-Hellman) to verify.
1216: */
1217:static final class CertificateVerify extends HandshakeMessage {
1218:
1219:    int messageType() { return ht_certificate_verify; }
1220:
1221:    private byte[] signature;
1222:    
1223:    /*
1224:     * Create an RSA or DSA signed certificate verify message.
1225:     */
1226:    CertificateVerify(ProtocolVersion protocolVersion, HandshakeHash 
1227:	    handshakeHash, PrivateKey privateKey, SecretKey masterSecret, 
1228:	    SecureRandom sr) throws GeneralSecurityException {
1229:	String algorithm = privateKey.getAlgorithm();
1230:	Signature sig = getSignature(protocolVersion, algorithm);
1231:	sig.initSign(privateKey, sr);
1232:	updateSignature(sig, protocolVersion, handshakeHash, algorithm, 
1233:			masterSecret);
1234:	signature = sig.sign();
1235:    }
1236:
1237:    //
1238:    // Unmarshal the signed data from the input stream.
1239:    //
1240:    CertificateVerify(HandshakeInStream input) throws IOException  {
1241:	signature = input.getBytes16();
1242:    }
1243:    
1244:    /*
1245:     * Verify a certificate verify message. Return the result of verification,
1246:     * if there is a problem throw a GeneralSecurityException.
1247:     */
1248:    boolean verify(ProtocolVersion protocolVersion, 
1249:    	    HandshakeHash handshakeHash, PublicKey publicKey, 
1250:	    SecretKey masterSecret) throws GeneralSecurityException {
1251:	String algorithm = publicKey.getAlgorithm();
1252:	Signature sig = getSignature(protocolVersion, algorithm);
1253:	sig.initVerify(publicKey);
1254:	updateSignature(sig, protocolVersion, handshakeHash, algorithm, 
1255:			masterSecret);
1256:	return sig.verify(signature);
1257:    }
1258:
1259:    /*
1260:     * Get the Signature object appropriate for verification using the
1261:     * given signature algorithm and protocol version.
1262:     */
1263:    private static Signature getSignature(ProtocolVersion protocolVersion,
1264:    	    String algorithm) throws GeneralSecurityException {
1265:	if (algorithm.equals("RSA")) {
1266:	    return RSASignature.getInternalInstance();
1267:	} else if (algorithm.equals("DSA")) {
1268:	    return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
1269:	} else if (algorithm.equals("EC")) {
1270:	    return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
1271:	} else {
1272:	    throw new SignatureException("Unrecognized algorithm: "
1273:	    	+ algorithm);
1274:	}
1275:    }
1276:    
1277:    /*
1278:     * Update the Signature with the data appropriate for the given
1279:     * signature algorithm and protocol version so that the object is
1280:     * ready for signing or verifying.
1281:     */
1282:    private static void updateSignature(Signature sig, 
1283:    	    ProtocolVersion protocolVersion,
1284:	    HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
1285:	    throws SignatureException {
1286:	MessageDigest md5Clone = handshakeHash.getMD5Clone();
1287:	MessageDigest shaClone = handshakeHash.getSHAClone();
1288:	boolean tls = protocolVersion.v >= ProtocolVersion.TLS10.v;
1289:	if (algorithm.equals("RSA")) {
1290:	    if (tls) {
1291:		// nothing to do
1292:	    } else { // SSLv3
1293:		updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
1294:		updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
1295:	    }
1296:	    // need to use these hashes directly
1297:	    RSASignature.setHashes(sig, md5Clone, shaClone);
1298:	} else { // DSA, ECDSA
1299:	    if (tls) {
1300:		// nothing to do
1301:	    } else { // SSLv3
1302:		updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
1303:	    }
1304:	    sig.update(shaClone.digest());
1305:	}
1306:    }
1307:    
1308:    /*
1309:     * Update the MessageDigest for SSLv3 certificate verify or finished 
1310:     * message calculation. The digest must already have been updated with 
1311:     * all preceding handshake messages.
1312:     * Used by the Finished class as well.
1313:     */
1314:    static void updateDigest(MessageDigest md, byte[] pad1, byte[] pad2,
1315:	    SecretKey masterSecret) {
1316:	// Digest the key bytes if available.
1317:	// Otherwise (sensitive key), try digesting the key directly.
1318:	// That is currently only implemented in SunPKCS11 using a private
1319:	// reflection API, so we avoid that if possible.
1320:	byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
1321:			? masterSecret.getEncoded() : null;
1322:	if (keyBytes != null) {
1323:	    md.update(keyBytes);
1324:	} else {
1325:	    digestKey(md, masterSecret);
1326:	}
1327:	md.update(pad1);
1328:	byte[] temp = md.digest();
1329:
1330:	if (keyBytes != null) {
1331:	    md.update(keyBytes);
1332:	} else {
1333:	    digestKey(md, masterSecret);
1334:	}
1335:	md.update(pad2);
1336:	md.update(temp);
1337:    }
1338:    
1339:    private final static Class delegate;
1340:    private final static Field spiField;
1341:    
1342:    static {
1343:	try {
1344:	    delegate = Class.forName("java.security.MessageDigest$Delegate");
1345:	    spiField = delegate.getDeclaredField("digestSpi");
1346:	} catch (Exception e) {
1347:	    throw new RuntimeException("Reflection failed", e);
1348:	}
1349:	makeAccessible(spiField);
1350:    }
1351:    
1352:    private static void makeAccessible(final AccessibleObject o) {
1353:	AccessController.doPrivileged(new PrivilegedAction<Object>() {
1354:	    public Object run() {
1355:		o.setAccessible(true);
1356:		return null;
1357:	    }
1358:	});
1359:    }
1360:
1361:    // ConcurrentHashMap does not allow null values, use this marker object
1362:    private final static Object NULL_OBJECT = new Object();
1363:
1364:    // cache Method objects per Spi class
1365:    // Note that this will prevent the Spi classes from being GC'd. We assume
1366:    // that is not a problem.
1367:    private final static Map<Class,Object> methodCache =
1368:					new ConcurrentHashMap<Class,Object>();
1369:    
1370:    private static void digestKey(MessageDigest md, SecretKey key) {
1371:	try {
1372:	    // Verify that md is implemented via MessageDigestSpi, not
1373:	    // via JDK 1.1 style MessageDigest subclassing.
1374:	    if (md.getClass() != delegate) {
1375:		throw new Exception("Digest is not a MessageDigestSpi");
1376:	    }
1377:	    MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
1378:	    Class<?> clazz = spi.getClass();
1379:	    Object r = methodCache.get(clazz);
1380:	    if (r == null) {
1381:		try {
1382:		    r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
1383:		    makeAccessible((Method)r);
1384:		} catch (NoSuchMethodException e) {
1385:		    r = NULL_OBJECT;
1386:		}
1387:		methodCache.put(clazz, r);
1388:	    }
1389:	    if (r == NULL_OBJECT) {
1390:		throw new Exception("Digest does not support implUpdate(SecretKey)");
1391:	    }
1392:	    Method update = (Method)r;
1393:	    update.invoke(spi, key);
1394:	} catch (Exception e) {
1395:	    throw new RuntimeException
1396:	    ("Could not obtain encoded key and MessageDigest cannot digest key", e);
1397:	}
1398:    }
1399:    
1400:    int messageLength() {
1401:	return 2 + signature.length;
1402:    }
1403:
1404:    void send(HandshakeOutStream s) throws IOException {
1405:	s.putBytes16(signature);
1406:    }
1407:
1408:    void print(PrintStream s) throws IOException {
1409:	s.println("*** CertificateVerify");
1410:    }
1411:}
1412:
1413:
1414:/*
1415: * FINISHED ... sent by both CLIENT and SERVER
1416: *
1417: * This is the FINISHED message as defined in the SSL and TLS protocols.
1418: * Both protocols define this handshake message slightly differently.
1419: * This class supports both formats.
1420: *
1421: * When handshaking is finished, each side sends a "change_cipher_spec"
1422: * record, then immediately sends a "finished" handshake message prepared
1423: * according to the newly adopted cipher spec.
1424: *
1425: * NOTE that until this is sent, no application data may be passed, unless
1426: * some non-default cipher suite has already been set up on this connection
1427: * connection (e.g. a previous handshake arranged one).
1428: */
1429:static final class Finished extends HandshakeMessage {
1430:
1431:    int messageType() { return ht_finished; }
1432:    
1433:    // constant for a Finished message sent by the client
1434:    final static int CLIENT = 1;
1435:
1436:    // constant for a Finished message sent by the server
1437:    final static int SERVER = 2;
1438:
1439:    // enum Sender:  "CLNT" and "SRVR"
1440:    private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
1441:    private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
1442:    
1443:    /*
1444:     * Contents of the finished message ("checksum"). For TLS, it
1445:     * is 12 bytes long, for SSLv3 36 bytes.
1446:     */
1447:    private byte[] verifyData;
1448:
1449:    /*
1450:     * Create a finished message to send to the remote peer.
1451:     */
1452:    Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash, 
1453:	    int sender, SecretKey master) {
1454:	verifyData = getFinished(protocolVersion, handshakeHash, sender, 
1455:				 master);
1456:    }
1457:    
1458:    /*
1459:     * Constructor that reads FINISHED message from stream.
1460:     */
1461:    Finished(ProtocolVersion protocolVersion, HandshakeInStream input)
1462:	    throws IOException {
1463:	int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
1464:	verifyData = new byte[msgLen];
1465:	input.read(verifyData);
1466:    }
1467:
1468:    /*
1469:     * Verify that the hashes here are what would have been produced
1470:     * according to a given set of inputs.  This is used to ensure that
1471:     * both client and server are fully in sync, and that the handshake
1472:     * computations have been successful.
1473:     */
1474:     boolean verify(ProtocolVersion protocolVersion, 
1475:	     HandshakeHash handshakeHash, int sender, SecretKey master) {
1476:	byte[] myFinished = getFinished(protocolVersion, handshakeHash, 
1477:					sender, master);
1478:	return Arrays.equals(myFinished, verifyData);
1479:    }
1480:    
1481:    /*
1482:     * Perform the actual finished message calculation.
1483:     */
1484:    private static byte[] getFinished(ProtocolVersion protocolVersion, 
1485:	    HandshakeHash handshakeHash, int sender, SecretKey masterKey) {
1486:	byte[] sslLabel;
1487:	String tlsLabel;
1488:	if (sender == CLIENT) {
1489:	    sslLabel = SSL_CLIENT;
1490:	    tlsLabel = "client finished";
1491:	} else if (sender == SERVER) {
1492:	    sslLabel = SSL_SERVER;
1493:	    tlsLabel = "server finished";
1494:	} else {
1495:	    throw new RuntimeException("Invalid sender: " + sender);
1496:	}
1497:	MessageDigest md5Clone = handshakeHash.getMD5Clone();
1498:	MessageDigest shaClone = handshakeHash.getSHAClone();
1499:	if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
1500:	    // TLS
1501:	    try {
1502:		byte[] seed = new byte[36];
1503:		md5Clone.digest(seed, 0, 16);
1504:		shaClone.digest(seed, 16, 20);
1505:    
1506:		TlsPrfParameterSpec spec = new TlsPrfParameterSpec
1507:						(masterKey, tlsLabel, seed, 12);
1508:		KeyGenerator prf = JsseJce.getKeyGenerator("SunTlsPrf");
1509:		prf.init(spec);
1510:		SecretKey prfKey = prf.generateKey();
1511:		if ("RAW".equals(prfKey.getFormat()) == false) {
1512:		    throw new ProviderException
1513:			("Invalid PRF output, format must be RAW");
1514:		}
1515:		byte[] finished = prfKey.getEncoded();
1516:		return finished;
1517:	    } catch (GeneralSecurityException e) {
1518:		throw new RuntimeException("PRF failed", e);
1519:	    }
1520:	} else {
1521:	    // SSLv3
1522:	    updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
1523:	    updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
1524:	    byte[] finished = new byte[36];
1525:	    try {
1526:		md5Clone.digest(finished, 0, 16);
1527:		shaClone.digest(finished, 16, 20);
1528:	    } catch (DigestException e) {
1529:		// cannot occur
1530:		throw new RuntimeException("Digest failed", e);
1531:	    }
1532:	    return finished;
1533:	}
1534:    }
1535:    
1536:    /*
1537:     * Update the MessageDigest for SSLv3 finished message calculation.
1538:     * The digest must already have been updated with all preceding handshake
1539:     * messages. This operation is almost identical to the certificate verify
1540:     * hash, reuse that code.
1541:     */
1542:    private static void updateDigest(MessageDigest md, byte[] sender, 
1543:	    byte[] pad1, byte[] pad2, SecretKey masterSecret) {
1544:	md.update(sender);
1545:	CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
1546:    }
1547:    
1548:    int messageLength() {
1549:	return verifyData.length;
1550:    }
1551:
1552:    void send(HandshakeOutStream out) throws IOException {
1553:	out.write(verifyData);
1554:    }
1555:
1556:    void print(PrintStream s) throws IOException {
1557:	s.println("*** Finished");
1558:	if (debug != null && Debug.isOn("verbose")) {
1559:	    Debug.println(s, "verify_data", verifyData);
1560:	    s.println("***");
1561:	}
1562:    }
1563:
1564:}
1565:
1566://
1567:// END of nested classes
1568://
1569:
1570:}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.