HandshakeProtocol.java revision 6b811c5daec1b28e6f63b57f98a032236f2c3cf7
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.xnet.provider.jsse; 19 20import java.math.BigInteger; 21import java.security.GeneralSecurityException; 22import java.security.KeyFactory; 23import java.security.MessageDigest; 24import java.security.NoSuchAlgorithmException; 25import java.security.PublicKey; 26import java.security.interfaces.RSAKey; 27import java.security.spec.InvalidKeySpecException; 28import java.security.spec.RSAPublicKeySpec; 29import java.util.Arrays; 30import java.util.Vector; 31 32import javax.net.ssl.SSLEngineResult; 33import javax.net.ssl.SSLException; 34import javax.net.ssl.SSLHandshakeException; 35 36/** 37 * Base class for ClientHandshakeImpl and ServerHandshakeImpl classes. 38 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4. 39 * Handshake protocol</a> 40 * 41 */ 42public abstract class HandshakeProtocol { 43 44 /** 45 * Handshake status NEED_UNWRAP - HandshakeProtocol needs to receive data 46 */ 47 public final static int NEED_UNWRAP = 1; 48 49 /** 50 * Handshake status NOT_HANDSHAKING - is not currently handshaking 51 */ 52 public final static int NOT_HANDSHAKING = 2; 53 54 /** 55 * Handshake status FINISHED - HandshakeProtocol has just finished 56 */ 57 public final static int FINISHED = 3; 58 59 /** 60 * Handshake status NEED_TASK - HandshakeProtocol needs the results of delegated task 61 */ 62 public final static int NEED_TASK = 4; 63 64 /** 65 * Current handshake status 66 */ 67 protected int status = NOT_HANDSHAKING; 68 69 /** 70 * IO stream for income/outcome handshake data 71 */ 72 protected HandshakeIODataStream io_stream = new HandshakeIODataStream(); 73 74 /** 75 * SSL Record Protocol implementation. 76 */ 77 protected SSLRecordProtocol recordProtocol; 78 79 /** 80 * SSLParameters suplied by SSLSocket or SSLEngine 81 */ 82 protected SSLParameters parameters; 83 84 /** 85 * Delegated tasks for this handshake implementation 86 */ 87 protected Vector<DelegatedTask> delegatedTasks = new Vector<DelegatedTask>(); 88 89 /** 90 * Indicates non-blocking handshake 91 */ 92 protected boolean nonBlocking; 93 94 /** 95 * Pending session 96 */ 97 protected SSLSessionImpl session; 98 99 /** 100 * Sended and received handshake messages 101 */ 102 protected ClientHello clientHello; 103 protected ServerHello serverHello; 104 protected CertificateMessage serverCert; 105 protected ServerKeyExchange serverKeyExchange; 106 protected CertificateRequest certificateRequest; 107 protected ServerHelloDone serverHelloDone; 108 protected CertificateMessage clientCert; 109 protected ClientKeyExchange clientKeyExchange; 110 protected CertificateVerify certificateVerify; 111 protected Finished clientFinished; 112 protected Finished serverFinished; 113 114 /** 115 * Indicates that change cipher spec message has been received 116 */ 117 protected boolean changeCipherSpecReceived = false; 118 119 /** 120 * Indicates previous session resuming 121 */ 122 protected boolean isResuming = false; 123 124 /** 125 * Premaster secret 126 */ 127 protected byte[] preMasterSecret; 128 129 /** 130 * Exception occured in delegated task 131 */ 132 protected Exception delegatedTaskErr; 133 134 // reference verify_data used to verify finished message 135 private byte[] verify_data = new byte[12]; 136 137 // Encoding of "master secret" string: "master secret".getBytes() 138 private byte[] master_secret_bytes = 139 {109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 }; 140 141 // indicates whether protocol needs to send change cipher spec message 142 private boolean needSendCCSpec = false; 143 144 // indicates whether protocol needs to send change cipher spec message 145 protected boolean needSendHelloRequest = false; 146 147 /** 148 * SSLEngine owning this HandshakeProtocol 149 */ 150 public SSLEngineImpl engineOwner; 151 152 /** 153 * SSLSocket owning this HandshakeProtocol 154 */ 155 // BEGIN android-removed 156 // public SSLSocketImpl socketOwner; 157 // END android-removed 158 159 /** 160 * Creates HandshakeProtocol instance 161 * @param owner 162 */ 163 protected HandshakeProtocol(Object owner) { 164 if (owner instanceof SSLEngineImpl) { 165 engineOwner = (SSLEngineImpl) owner; 166 nonBlocking = true; 167 this.parameters = engineOwner.sslParameters; 168 } 169 // BEGIN android-removed 170 // else if (owner instanceof SSLSocketImpl) { 171 // socketOwner = (SSLSocketImpl) owner; 172 // nonBlocking = false; 173 // this.parameters = socketOwner.sslParameters; 174 // } 175 // END android-removed 176 } 177 178 /** 179 * Sets SSL Record Protocol 180 * @param recordProtocol 181 */ 182 public void setRecordProtocol(SSLRecordProtocol recordProtocol) { 183 this.recordProtocol = recordProtocol; 184 } 185 186 /** 187 * Start session negotiation 188 * @param session 189 */ 190 public abstract void start(); 191 192 /** 193 * Stops the current session renegotiation process. 194 * Such functionality is needed when it is session renegotiation 195 * process and no_renegotiation alert message is received 196 * from another peer. 197 * @param session 198 */ 199 protected void stop() { 200 clearMessages(); 201 status = NOT_HANDSHAKING; 202 } 203 204 /** 205 * Returns handshake status 206 * @return 207 */ 208 public SSLEngineResult.HandshakeStatus getStatus() { 209 if (io_stream.hasData() || needSendCCSpec || 210 needSendHelloRequest || delegatedTaskErr != null) { 211 return SSLEngineResult.HandshakeStatus.NEED_WRAP; 212 } 213 if (!delegatedTasks.isEmpty()) { 214 return SSLEngineResult.HandshakeStatus.NEED_TASK; 215 } 216 217 switch (status) { 218 case HandshakeProtocol.NEED_UNWRAP: 219 return SSLEngineResult.HandshakeStatus.NEED_UNWRAP; 220 case HandshakeProtocol.FINISHED: 221 status = NOT_HANDSHAKING; 222 clearMessages(); 223 return SSLEngineResult.HandshakeStatus.FINISHED; 224 default: // HandshakeProtocol.NOT_HANDSHAKING: 225 return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; 226 } 227 } 228 229 /** 230 * Returns pending session 231 * @return session 232 */ 233 public SSLSessionImpl getSession() { 234 return session; 235 } 236 237 protected void sendChangeCipherSpec() { 238 needSendCCSpec = true; 239 } 240 241 protected void sendHelloRequest() { 242 needSendHelloRequest = true; 243 } 244 245 /** 246 * Proceses inbound ChangeCipherSpec message 247 */ 248 abstract void receiveChangeCipherSpec(); 249 250 /** 251 * Creates and sends finished message 252 */ 253 abstract void makeFinished(); 254 255 /** 256 * Proceses inbound handshake messages 257 * @param bytes 258 */ 259 public abstract void unwrap(byte[] bytes); 260 261 /** 262 * Processes SSLv2 Hello message 263 * @param bytes 264 */ 265 public abstract void unwrapSSLv2(byte[] bytes); 266 267 /** 268 * Proceses outbound handshake messages 269 * @return 270 */ 271 public byte[] wrap() { 272 if (delegatedTaskErr != null) { 273 // process error occured in delegated task 274 Exception e = delegatedTaskErr; 275 delegatedTaskErr = null; 276 fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 277 "Error occured in delegated task:" + e.getMessage(), e); 278 } 279 if (io_stream.hasData()) { 280 return recordProtocol.wrap(ContentType.HANDSHAKE, io_stream); 281 } else if (needSendCCSpec) { 282 makeFinished(); 283 needSendCCSpec = false; 284 return recordProtocol.getChangeCipherSpecMesage(getSession()); 285 } else if (needSendHelloRequest) { 286 needSendHelloRequest = false; 287 return recordProtocol.wrap(ContentType.HANDSHAKE, 288 // hello request message 289 // (see TLS v 1 specification: 290 // http://www.ietf.org/rfc/rfc2246.txt) 291 new byte[] {0, 0, 0, 0}, 0, 4); 292 } else { 293 return null; // nothing to send; 294 } 295 } 296 297 /** 298 * Sends fatal alert, breaks execution 299 * 300 * @param description 301 */ 302 protected void sendWarningAlert(byte description) { 303 recordProtocol.alert(AlertProtocol.WARNING, description); 304 } 305 306 /** 307 * Sends fatal alert, breaks execution 308 * 309 * @param description 310 * @param reason 311 */ 312 protected void fatalAlert(byte description, String reason) { 313 throw new AlertException(description, new SSLHandshakeException(reason)); 314 } 315 316 /** 317 * Sends fatal alert, breaks execution 318 * 319 * @param description 320 * @param reason 321 * @param cause 322 */ 323 protected void fatalAlert(byte description, String reason, Exception cause) { 324 throw new AlertException(description, new SSLException(reason, cause)); 325 } 326 327 /** 328 * Sends fatal alert, breaks execution 329 * 330 * @param description 331 * @param cause 332 */ 333 protected void fatalAlert(byte description, SSLException cause) { 334 throw new AlertException(description, cause); 335 } 336 337 /** 338 * Computers reference TLS verify_data that is used to verify finished message 339 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a> 340 * @param label 341 */ 342 protected void computerReferenceVerifyDataTLS(String label) { 343 computerVerifyDataTLS(label, verify_data); 344 } 345 346 /** 347 * Computer TLS verify_data 348 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a> 349 * @param label 350 * @param buf 351 */ 352 protected void computerVerifyDataTLS(String label, byte[] buf) { 353 byte[] md5_digest = io_stream.getDigestMD5(); 354 byte[] sha_digest = io_stream.getDigestSHA(); 355 356 byte[] digest = new byte[md5_digest.length + sha_digest.length]; 357 System.arraycopy(md5_digest, 0, digest, 0, md5_digest.length); 358 System.arraycopy(sha_digest, 0, digest, md5_digest.length, 359 sha_digest.length); 360 try { 361 PRF.computePRF(buf, session.master_secret, 362 label.getBytes(), digest); 363 } catch (GeneralSecurityException e) { 364 fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e); 365 } 366 } 367 368 /** 369 * Computer reference SSLv3 verify_data that is used to verify finished message 370 * @see "SSLv3 spec. 7.6.9. Finished" 371 * @param label 372 */ 373 protected void computerReferenceVerifyDataSSLv3(byte[] sender) { 374 verify_data = new byte[36]; 375 computerVerifyDataSSLv3(sender, verify_data); 376 } 377 378 /** 379 * Computer SSLv3 verify_data 380 * @see "SSLv3 spec. 7.6.9. Finished" 381 * @param label 382 * @param buf 383 */ 384 protected void computerVerifyDataSSLv3(byte[] sender, byte[] buf) { 385 MessageDigest md5; 386 MessageDigest sha; 387 try { 388 md5 = MessageDigest.getInstance("MD5"); 389 sha = MessageDigest.getInstance("SHA-1"); 390 } catch (Exception e) { 391 fatalAlert(AlertProtocol.INTERNAL_ERROR, "Could not initialize the Digest Algorithms.", e); 392 return; 393 } 394 try { 395 byte[] hanshake_messages = io_stream.getMessages(); 396 md5.update(hanshake_messages); 397 md5.update(sender); 398 md5.update(session.master_secret); 399 byte[] b = md5.digest(SSLv3Constants.MD5pad1); 400 md5.update(session.master_secret); 401 md5.update(SSLv3Constants.MD5pad2); 402 System.arraycopy(md5.digest(b), 0, buf, 0, 16); 403 404 sha.update(hanshake_messages); 405 sha.update(sender); 406 sha.update(session.master_secret); 407 b = sha.digest(SSLv3Constants.SHApad1); 408 sha.update(session.master_secret); 409 sha.update(SSLv3Constants.SHApad2); 410 System.arraycopy(sha.digest(b), 0, buf, 16, 20); 411 } catch (Exception e) { 412 fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e); 413 414 } 415 } 416 417 /** 418 * Verifies finished data 419 * 420 * @param data 421 * @param isServer 422 */ 423 protected void verifyFinished(byte[] data) { 424 if (!Arrays.equals(verify_data, data)) { 425 fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Incorrect FINISED"); 426 } 427 } 428 429 /** 430 * Sends fatal alert "UNEXPECTED MESSAGE" 431 * 432 */ 433 protected void unexpectedMessage() { 434 fatalAlert(AlertProtocol.UNEXPECTED_MESSAGE, "UNEXPECTED MESSAGE"); 435 } 436 437 /** 438 * Writes message to HandshakeIODataStream 439 * 440 * @param message 441 */ 442 public void send(Message message) { 443 io_stream.writeUint8(message.getType()); 444 io_stream.writeUint24(message.length()); 445 message.send(io_stream); 446 } 447 448 /** 449 * Computers master secret 450 * 451 */ 452 public void computerMasterSecret() { 453 byte[] seed = new byte[64]; 454 System.arraycopy(clientHello.getRandom(), 0, seed, 0, 32); 455 System.arraycopy(serverHello.getRandom(), 0, seed, 32, 32); 456 session.master_secret = new byte[48]; 457 if (serverHello.server_version[1] == 1) { // TLSv1 458 try { 459 PRF.computePRF(session.master_secret, preMasterSecret, 460 master_secret_bytes, seed); 461 } catch (GeneralSecurityException e) { 462 fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e); 463 } 464 } else { // SSL3.0 465 PRF.computePRF_SSLv3(session.master_secret, preMasterSecret, seed); 466 } 467 468 //delete preMasterSecret from memory 469 Arrays.fill(preMasterSecret, (byte)0); 470 preMasterSecret = null; 471 } 472 473 /** 474 * Returns a delegated task. 475 * @return Delegated task or null 476 */ 477 public Runnable getTask() { 478 if (delegatedTasks.isEmpty()) { 479 return null; 480 } 481 return delegatedTasks.remove(0); 482 } 483 484 /** 485 * 486 * Clears previously sended and received handshake messages 487 */ 488 protected void clearMessages() { 489 io_stream.clearBuffer(); 490 clientHello = null; 491 serverHello = null; 492 serverCert = null; 493 serverKeyExchange = null; 494 certificateRequest = null; 495 serverHelloDone = null; 496 clientCert = null; 497 clientKeyExchange = null; 498 certificateVerify = null; 499 clientFinished = null; 500 serverFinished = null; 501 } 502 503 /** 504 * Returns RSA key length 505 * @param pk 506 * @return 507 * @throws NoSuchAlgorithmException 508 * @throws InvalidKeySpecException 509 */ 510 protected static int getRSAKeyLength(PublicKey pk) 511 throws NoSuchAlgorithmException, InvalidKeySpecException { 512 513 BigInteger mod; 514 if (pk instanceof RSAKey) { 515 mod = ((RSAKey) pk).getModulus(); 516 } else { 517 KeyFactory kf = KeyFactory.getInstance("RSA"); 518 mod = kf.getKeySpec(pk, RSAPublicKeySpec.class) 519 .getModulus(); 520 } 521 return mod.bitLength(); 522 } 523 524 /** 525 * Shutdownes the protocol. It will be impossiblke to use the instance 526 * after the calling of this method. 527 */ 528 protected void shutdown() { 529 clearMessages(); 530 session = null; 531 preMasterSecret = null; 532 delegatedTasks.clear(); 533 } 534} 535