1 /* 2 * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.security.ssl; 28 29 import java.io.ByteArrayOutputStream; 30 import java.security.*; 31 import java.util.Locale; 32 import java.nio.ByteBuffer; 33 34 /** 35 * Abstraction for the SSL/TLS hash of all handshake messages that is 36 * maintained to verify the integrity of the negotiation. Internally, 37 * it consists of an MD5 and an SHA1 digest. They are used in the client 38 * and server finished messages and in certificate verify messages (if sent). 39 * 40 * This class transparently deals with cloneable and non-cloneable digests. 41 * 42 * This class now supports TLS 1.2 also. The key difference for TLS 1.2 43 * is that you cannot determine the hash algorithms for CertificateVerify 44 * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier) 45 * that there is no messy MD5+SHA1 digests. 46 * 47 * You need to obey these conventions when using this class: 48 * 49 * 1. protocolDetermined(version) should be called when the negotiated 50 * protocol version is determined. 51 * 52 * 2. Before protocolDetermined() is called, only update(), and reset() 53 * and setFinishedAlg() can be called. 54 * 55 * 3. After protocolDetermined() is called, reset() cannot be called. 56 * 57 * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2, 58 * getFinishedHash() cannot be called. Otherwise, 59 * getMD5Clone() and getSHAClone() cannot be called. 60 * 61 * 5. getMD5Clone() and getSHAClone() can only be called after 62 * protocolDetermined() is called and version is pre-TLS 1.2. 63 * 64 * 6. getFinishedHash() can only be called after protocolDetermined() 65 * and setFinishedAlg() have been called and the version is TLS 1.2. 66 * 67 * Suggestion: Call protocolDetermined() and setFinishedAlg() 68 * as early as possible. 69 * 70 * Example: 71 * <pre> 72 * HandshakeHash hh = new HandshakeHash(...) 73 * hh.protocolDetermined(ProtocolVersion.TLS12); 74 * hh.update(clientHelloBytes); 75 * hh.setFinishedAlg("SHA-256"); 76 * hh.update(serverHelloBytes); 77 * ... 78 * hh.update(CertificateVerifyBytes); 79 * ... 80 * hh.update(finished1); 81 * byte[] finDigest1 = hh.getFinishedHash(); 82 * hh.update(finished2); 83 * byte[] finDigest2 = hh.getFinishedHash(); 84 * </pre> 85 */ 86 final class HandshakeHash { 87 88 // Common 89 90 // -1: unknown 91 // 1: <=TLS 1.1 92 // 2: TLS 1.2 93 private int version = -1; 94 private ByteArrayOutputStream data = new ByteArrayOutputStream(); 95 96 // For TLS 1.1 97 private MessageDigest md5, sha; 98 private final int clonesNeeded; // needs to be saved for later use 99 100 // For TLS 1.2 101 private MessageDigest finMD; 102 103 // Cache for input record handshake hash computation 104 private ByteArrayOutputStream reserve = new ByteArrayOutputStream(); 105 106 /** 107 * Create a new HandshakeHash. needCertificateVerify indicates whether 108 * a hash for the certificate verify message is required. 109 */ 110 HandshakeHash(boolean needCertificateVerify) { 111 // We may rework the code later, but for now we use hard-coded number 112 // of clones if the underlying MessageDigests are not cloneable. 113 // 114 // The number used here is based on the current handshake protocols and 115 // implementation. It may be changed if the handshake processe gets 116 // changed in the future, for example adding a new extension that 117 // requires handshake hash. Please be careful about the number of 118 // clones if additional handshak hash is required in the future. 119 // 120 // For the current implementation, the handshake hash is required for 121 // the following items: 122 // . CertificateVerify handshake message (optional) 123 // . client Finished handshake message 124 // . server Finished Handshake message 125 // . the extended Master Secret extension [RFC 7627] 126 // 127 // Note that a late call to server setNeedClientAuth dose not update 128 // the number of clones. We may address the issue later. 129 // 130 // Note for safety, we allocate one more clone for the current 131 // implementation. We may consider it more carefully in the future 132 // for the exact number or rework the code in a different way. 133 clonesNeeded = needCertificateVerify ? 5 : 4; 134 } 135 136 void reserve(ByteBuffer input) { 137 if (input.hasArray()) { 138 reserve.write(input.array(), 139 input.position() + input.arrayOffset(), input.remaining()); 140 } else { 141 int inPos = input.position(); 142 byte[] holder = new byte[input.remaining()]; 143 input.get(holder); 144 input.position(inPos); 145 reserve.write(holder, 0, holder.length); 146 } 147 } 148 149 void reserve(byte[] b, int offset, int len) { 150 reserve.write(b, offset, len); 151 } 152 153 void reload() { 154 if (reserve.size() != 0) { 155 byte[] bytes = reserve.toByteArray(); 156 reserve.reset(); 157 update(bytes, 0, bytes.length); 158 } 159 } 160 161 void update(ByteBuffer input) { 162 163 // reload if there are reserved messages. 164 reload(); 165 166 int inPos = input.position(); 167 switch (version) { 168 case 1: 169 md5.update(input); 170 input.position(inPos); 171 172 sha.update(input); 173 input.position(inPos); 174 175 break; 176 default: 177 if (finMD != null) { 178 finMD.update(input); 179 input.position(inPos); 180 } 181 if (input.hasArray()) { 182 data.write(input.array(), 183 inPos + input.arrayOffset(), input.remaining()); 184 } else { 185 byte[] holder = new byte[input.remaining()]; 186 input.get(holder); 187 input.position(inPos); 188 data.write(holder, 0, holder.length); 189 } 190 break; 191 } 192 } 193 194 void update(byte handshakeType, byte[] handshakeBody) { 195 196 // reload if there are reserved messages. 197 reload(); 198 199 switch (version) { 200 case 1: 201 md5.update(handshakeType); 202 sha.update(handshakeType); 203 204 md5.update((byte)((handshakeBody.length >> 16) & 0xFF)); 205 sha.update((byte)((handshakeBody.length >> 16) & 0xFF)); 206 md5.update((byte)((handshakeBody.length >> 8) & 0xFF)); 207 sha.update((byte)((handshakeBody.length >> 8) & 0xFF)); 208 md5.update((byte)(handshakeBody.length & 0xFF)); 209 sha.update((byte)(handshakeBody.length & 0xFF)); 210 211 md5.update(handshakeBody); 212 sha.update(handshakeBody); 213 break; 214 default: 215 if (finMD != null) { 216 finMD.update(handshakeType); 217 finMD.update((byte)((handshakeBody.length >> 16) & 0xFF)); 218 finMD.update((byte)((handshakeBody.length >> 8) & 0xFF)); 219 finMD.update((byte)(handshakeBody.length & 0xFF)); 220 finMD.update(handshakeBody); 221 } 222 data.write(handshakeType); 223 data.write((byte)((handshakeBody.length >> 16) & 0xFF)); 224 data.write((byte)((handshakeBody.length >> 8) & 0xFF)); 225 data.write((byte)(handshakeBody.length & 0xFF)); 226 data.write(handshakeBody, 0, handshakeBody.length); 227 break; 228 } 229 } 230 231 void update(byte[] b, int offset, int len) { 232 233 // reload if there are reserved messages. 234 reload(); 235 236 switch (version) { 237 case 1: 238 md5.update(b, offset, len); 239 sha.update(b, offset, len); 240 break; 241 default: 242 if (finMD != null) { 243 finMD.update(b, offset, len); 244 } 245 data.write(b, offset, len); 246 break; 247 } 248 } 249 250 /** 251 * Reset the remaining digests. Note this does *not* reset the number of 252 * digest clones that can be obtained. Digests that have already been 253 * cloned and are gone remain gone. 254 */ 255 void reset() { 256 if (version != -1) { 257 throw new RuntimeException( 258 "reset() can be only be called before protocolDetermined"); 259 } 260 data.reset(); 261 } 262 263 264 void protocolDetermined(ProtocolVersion pv) { 265 266 // Do not set again, will ignore 267 if (version != -1) { 268 return; 269 } 270 271 if (pv.maybeDTLSProtocol()) { 272 version = pv.compareTo(ProtocolVersion.DTLS12) >= 0 ? 2 : 1; 273 } else { 274 version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1; 275 } 276 switch (version) { 277 case 1: 278 // initiate md5, sha and call update on saved array 279 try { 280 md5 = CloneableDigest.getDigest("MD5", clonesNeeded); 281 sha = CloneableDigest.getDigest("SHA", clonesNeeded); 282 } catch (NoSuchAlgorithmException e) { 283 throw new RuntimeException 284 ("Algorithm MD5 or SHA not available", e); 285 } 286 byte[] bytes = data.toByteArray(); 287 update(bytes, 0, bytes.length); 288 break; 289 case 2: 290 break; 291 } 292 } 293 294 ///////////////////////////////////////////////////////////// 295 // Below are old methods for pre-TLS 1.1 296 ///////////////////////////////////////////////////////////// 297 298 /** 299 * Return a new MD5 digest updated with all data hashed so far. 300 */ 301 MessageDigest getMD5Clone() { 302 if (version != 1) { 303 throw new RuntimeException( 304 "getMD5Clone() can be only be called for TLS 1.1"); 305 } 306 return cloneDigest(md5); 307 } 308 309 /** 310 * Return a new SHA digest updated with all data hashed so far. 311 */ 312 MessageDigest getSHAClone() { 313 if (version != 1) { 314 throw new RuntimeException( 315 "getSHAClone() can be only be called for TLS 1.1"); 316 } 317 return cloneDigest(sha); 318 } 319 320 private static MessageDigest cloneDigest(MessageDigest digest) { 321 try { 322 return (MessageDigest)digest.clone(); 323 } catch (CloneNotSupportedException e) { 324 // cannot occur for digests generated via CloneableDigest 325 throw new RuntimeException("Could not clone digest", e); 326 } 327 } 328 329 ///////////////////////////////////////////////////////////// 330 // Below are new methods for TLS 1.2 331 ///////////////////////////////////////////////////////////// 332 333 private static String normalizeAlgName(String alg) { 334 alg = alg.toUpperCase(Locale.US); 335 if (alg.startsWith("SHA")) { 336 if (alg.length() == 3) { 337 return "SHA-1"; 338 } 339 if (alg.charAt(3) != '-') { 340 return "SHA-" + alg.substring(3); 341 } 342 } 343 return alg; 344 } 345 /** 346 * Specifies the hash algorithm used in Finished. This should be called 347 * based in info in ServerHello. 348 * Can be called multiple times. 349 */ 350 void setFinishedAlg(String s) { 351 if (s == null) { 352 throw new RuntimeException( 353 "setFinishedAlg's argument cannot be null"); 354 } 355 356 // Can be called multiple times, but only set once 357 if (finMD != null) return; 358 359 try { 360 // See comment in the contructor. 361 finMD = CloneableDigest.getDigest(normalizeAlgName(s), 4); 362 } catch (NoSuchAlgorithmException e) { 363 throw new Error(e); 364 } 365 finMD.update(data.toByteArray()); 366 } 367 368 byte[] getAllHandshakeMessages() { 369 return data.toByteArray(); 370 } 371 372 /** 373 * Calculates the hash in Finished. Must be called after setFinishedAlg(). 374 * This method can be called twice, for Finished messages of the server 375 * side and client side respectively. 376 */ 377 byte[] getFinishedHash() { 378 try { 379 return cloneDigest(finMD).digest(); 380 } catch (Exception e) { 381 throw new Error("Error during hash calculation", e); 382 } 383 } 384 } 385 386 /** 387 * A wrapper for MessageDigests that simulates cloning of non-cloneable 388 * digests. It uses the standard MessageDigest API and therefore can be used 389 * transparently in place of a regular digest. 390 * 391 * Note that we extend the MessageDigest class directly rather than 392 * MessageDigestSpi. This works because MessageDigest was originally designed 393 * this way in the JDK 1.1 days which allows us to avoid creating an internal 394 * provider. 395 * 396 * It can be "cloned" a limited number of times, which is specified at 397 * construction time. This is achieved by internally maintaining n digests 398 * in parallel. Consequently, it is only 1/n-th times as fast as the original 399 * digest. 400 * 401 * Example: 402 * MessageDigest md = CloneableDigest.getDigest("SHA", 2); 403 * md.update(data1); 404 * MessageDigest md2 = (MessageDigest)md.clone(); 405 * md2.update(data2); 406 * byte[] d1 = md2.digest(); // digest of data1 || data2 407 * md.update(data3); 408 * byte[] d2 = md.digest(); // digest of data1 || data3 409 * 410 * This class is not thread safe. 411 * 412 */ 413 final class CloneableDigest extends MessageDigest implements Cloneable { 414 415 /** 416 * The individual MessageDigests. Initially, all elements are non-null. 417 * When clone() is called, the non-null element with the maximum index is 418 * returned and the array element set to null. 419 * 420 * All non-null element are always in the same state. 421 */ 422 private final MessageDigest[] digests; 423 424 private CloneableDigest(MessageDigest digest, int n, String algorithm) 425 throws NoSuchAlgorithmException { 426 super(algorithm); 427 digests = new MessageDigest[n]; 428 digests[0] = digest; 429 for (int i = 1; i < n; i++) { 430 digests[i] = JsseJce.getMessageDigest(algorithm); 431 } 432 } 433 434 /** 435 * Return a MessageDigest for the given algorithm that can be cloned the 436 * specified number of times. If the default implementation supports 437 * cloning, it is returned. Otherwise, an instance of this class is 438 * returned. 439 */ 440 static MessageDigest getDigest(String algorithm, int n) 441 throws NoSuchAlgorithmException { 442 MessageDigest digest = JsseJce.getMessageDigest(algorithm); 443 try { 444 digest.clone(); 445 // already cloneable, use it 446 return digest; 447 } catch (CloneNotSupportedException e) { 448 return new CloneableDigest(digest, n, algorithm); 449 } 450 } 451 452 /** 453 * Check if this object is still usable. If it has already been cloned the 454 * maximum number of times, there are no digests left and this object can no 455 * longer be used. 456 */ 457 private void checkState() { 458 // XXX handshaking currently doesn't stop updating hashes... 459 // if (digests[0] == null) { 460 // throw new IllegalStateException("no digests left"); 461 // } 462 } 463 464 @Override 465 protected int engineGetDigestLength() { 466 checkState(); 467 return digests[0].getDigestLength(); 468 } 469 470 @Override 471 protected void engineUpdate(byte b) { 472 checkState(); 473 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 474 digests[i].update(b); 475 } 476 } 477 478 @Override 479 protected void engineUpdate(byte[] b, int offset, int len) { 480 checkState(); 481 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 482 digests[i].update(b, offset, len); 483 } 484 } 485 486 @Override 487 protected byte[] engineDigest() { 488 checkState(); 489 byte[] digest = digests[0].digest(); 490 digestReset(); 491 return digest; 492 } 493 494 @Override 495 protected int engineDigest(byte[] buf, int offset, int len) 496 throws DigestException { 497 checkState(); 498 int n = digests[0].digest(buf, offset, len); 499 digestReset(); 500 return n; 501 } 502 503 /** 504 * Reset all digests after a digest() call. digests[0] has already been 505 * implicitly reset by the digest() call and does not need to be reset 506 * again. 507 */ 508 private void digestReset() { 509 for (int i = 1; (i < digests.length) && (digests[i] != null); i++) { 510 digests[i].reset(); 511 } 512 } 513 514 @Override 515 protected void engineReset() { 516 checkState(); 517 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 518 digests[i].reset(); 519 } 520 } 521 522 @Override 523 public Object clone() { 524 checkState(); 525 for (int i = digests.length - 1; i >= 0; i--) { 526 if (digests[i] != null) { 527 MessageDigest digest = digests[i]; 528 digests[i] = null; 529 return digest; 530 } 531 } 532 // cannot occur 533 throw new InternalError(); 534 } 535 536 }