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