1 /* 2 * Copyright (c) 2002, 2012, 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 33 /** 34 * Abstraction for the SSL/TLS hash of all handshake messages that is 35 * maintained to verify the integrity of the negotiation. Internally, 36 * it consists of an MD5 and an SHA1 digest. They are used in the client 37 * and server finished messages and in certificate verify messages (if sent). 38 * 39 * This class transparently deals with cloneable and non-cloneable digests. 40 * 41 * This class now supports TLS 1.2 also. The key difference for TLS 1.2 42 * is that you cannot determine the hash algorithms for CertificateVerify 43 * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier) 44 * that there is no messy MD5+SHA1 digests. 45 * 46 * You need to obey these conventions when using this class: 47 * 48 * 1. protocolDetermined(version) should be called when the negotiated 49 * protocol version is determined. 50 * 51 * 2. Before protocolDetermined() is called, only update(), and reset() 52 * and setFinishedAlg() can be called. 53 * 54 * 3. After protocolDetermined() is called, reset() cannot be called. 55 * 56 * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2, 57 * getFinishedHash() cannot be called. Otherwise, 58 * getMD5Clone() and getSHAClone() cannot be called. 59 * 60 * 5. getMD5Clone() and getSHAClone() can only be called after 61 * protocolDetermined() is called and version is pre-TLS 1.2. 62 * 63 * 6. getFinishedHash() can only be called after protocolDetermined() 64 * and setFinishedAlg() have been called and the version is TLS 1.2. 65 * 66 * Suggestion: Call protocolDetermined() and setFinishedAlg() 67 * as early as possible. 68 * 69 * Example: 70 * <pre> 71 * HandshakeHash hh = new HandshakeHash(...) 72 * hh.protocolDetermined(ProtocolVersion.TLS12); 73 * hh.update(clientHelloBytes); 74 * hh.setFinishedAlg("SHA-256"); 75 * hh.update(serverHelloBytes); 76 * ... 77 * hh.update(CertificateVerifyBytes); 78 * ... 79 * hh.update(finished1); 80 * byte[] finDigest1 = hh.getFinishedHash(); 81 * hh.update(finished2); 82 * byte[] finDigest2 = hh.getFinishedHash(); 83 * </pre> 84 */ 85 final class HandshakeHash { 86 87 // Common 88 89 // -1: unknown 90 // 1: <=TLS 1.1 91 // 2: TLS 1.2 92 private int version = -1; 93 private ByteArrayOutputStream data = new ByteArrayOutputStream(); 94 95 // For TLS 1.1 96 private MessageDigest md5, sha; 97 private final int clonesNeeded; // needs to be saved for later use 98 99 // For TLS 1.2 100 private MessageDigest finMD; 101 102 /** 103 * Create a new HandshakeHash. needCertificateVerify indicates whether 104 * a hash for the certificate verify message is required. 105 */ 106 HandshakeHash(boolean needCertificateVerify) { 107 clonesNeeded = needCertificateVerify ? 3 : 2; 108 } 109 110 void update(byte[] b, int offset, int len) { 111 switch (version) { 112 case 1: 113 md5.update(b, offset, len); 114 sha.update(b, offset, len); 115 break; 116 default: 117 if (finMD != null) { 118 finMD.update(b, offset, len); 119 } 120 data.write(b, offset, len); 121 break; 122 } 123 } 124 125 /** 126 * Reset the remaining digests. Note this does *not* reset the number of 127 * digest clones that can be obtained. Digests that have already been 128 * cloned and are gone remain gone. 129 */ 130 void reset() { 131 if (version != -1) { 132 throw new RuntimeException( 133 "reset() can be only be called before protocolDetermined"); 134 } 135 data.reset(); 136 } 137 138 139 void protocolDetermined(ProtocolVersion pv) { 140 141 // Do not set again, will ignore 142 if (version != -1) return; 143 144 version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1; 145 switch (version) { 146 case 1: 147 // initiate md5, sha and call update on saved array 148 try { 149 md5 = CloneableDigest.getDigest("MD5", clonesNeeded); 150 sha = CloneableDigest.getDigest("SHA", clonesNeeded); 151 } catch (NoSuchAlgorithmException e) { 152 throw new RuntimeException 153 ("Algorithm MD5 or SHA not available", e); 154 } 155 byte[] bytes = data.toByteArray(); 156 update(bytes, 0, bytes.length); 157 break; 158 case 2: 159 break; 160 } 161 } 162 163 ///////////////////////////////////////////////////////////// 164 // Below are old methods for pre-TLS 1.1 165 ///////////////////////////////////////////////////////////// 166 167 /** 168 * Return a new MD5 digest updated with all data hashed so far. 169 */ 170 MessageDigest getMD5Clone() { 171 if (version != 1) { 172 throw new RuntimeException( 173 "getMD5Clone() can be only be called for TLS 1.1"); 174 } 175 return cloneDigest(md5); 176 } 177 178 /** 179 * Return a new SHA digest updated with all data hashed so far. 180 */ 181 MessageDigest getSHAClone() { 182 if (version != 1) { 183 throw new RuntimeException( 184 "getSHAClone() can be only be called for TLS 1.1"); 185 } 186 return cloneDigest(sha); 187 } 188 189 private static MessageDigest cloneDigest(MessageDigest digest) { 190 try { 191 return (MessageDigest)digest.clone(); 192 } catch (CloneNotSupportedException e) { 193 // cannot occur for digests generated via CloneableDigest 194 throw new RuntimeException("Could not clone digest", e); 195 } 196 } 197 198 ///////////////////////////////////////////////////////////// 199 // Below are new methods for TLS 1.2 200 ///////////////////////////////////////////////////////////// 201 202 private static String normalizeAlgName(String alg) { 203 alg = alg.toUpperCase(Locale.US); 204 if (alg.startsWith("SHA")) { 205 if (alg.length() == 3) { 206 return "SHA-1"; 207 } 208 if (alg.charAt(3) != '-') { 209 return "SHA-" + alg.substring(3); 210 } 211 } 212 return alg; 213 } 214 /** 215 * Specifies the hash algorithm used in Finished. This should be called 216 * based in info in ServerHello. 217 * Can be called multiple times. 218 */ 219 void setFinishedAlg(String s) { 220 if (s == null) { 221 throw new RuntimeException( 222 "setFinishedAlg's argument cannot be null"); 223 } 224 225 // Can be called multiple times, but only set once 226 if (finMD != null) return; 227 228 try { 229 finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2); 230 } catch (NoSuchAlgorithmException e) { 231 throw new Error(e); 232 } 233 finMD.update(data.toByteArray()); 234 } 235 236 byte[] getAllHandshakeMessages() { 237 return data.toByteArray(); 238 } 239 240 /** 241 * Calculates the hash in Finished. Must be called after setFinishedAlg(). 242 * This method can be called twice, for Finished messages of the server 243 * side and client side respectively. 244 */ 245 byte[] getFinishedHash() { 246 try { 247 return cloneDigest(finMD).digest(); 248 } catch (Exception e) { 249 throw new Error("BAD"); 250 } 251 } 252 } 253 254 /** 255 * A wrapper for MessageDigests that simulates cloning of non-cloneable 256 * digests. It uses the standard MessageDigest API and therefore can be used 257 * transparently in place of a regular digest. 258 * 259 * Note that we extend the MessageDigest class directly rather than 260 * MessageDigestSpi. This works because MessageDigest was originally designed 261 * this way in the JDK 1.1 days which allows us to avoid creating an internal 262 * provider. 263 * 264 * It can be "cloned" a limited number of times, which is specified at 265 * construction time. This is achieved by internally maintaining n digests 266 * in parallel. Consequently, it is only 1/n-th times as fast as the original 267 * digest. 268 * 269 * Example: 270 * MessageDigest md = CloneableDigest.getDigest("SHA", 2); 271 * md.update(data1); 272 * MessageDigest md2 = (MessageDigest)md.clone(); 273 * md2.update(data2); 274 * byte[] d1 = md2.digest(); // digest of data1 || data2 275 * md.update(data3); 276 * byte[] d2 = md.digest(); // digest of data1 || data3 277 * 278 * This class is not thread safe. 279 * 280 */ 281 final class CloneableDigest extends MessageDigest implements Cloneable { 282 283 /** 284 * The individual MessageDigests. Initially, all elements are non-null. 285 * When clone() is called, the non-null element with the maximum index is 286 * returned and the array element set to null. 287 * 288 * All non-null element are always in the same state. 289 */ 290 private final MessageDigest[] digests; 291 292 private CloneableDigest(MessageDigest digest, int n, String algorithm) 293 throws NoSuchAlgorithmException { 294 super(algorithm); 295 digests = new MessageDigest[n]; 296 digests[0] = digest; 297 for (int i = 1; i < n; i++) { 298 digests[i] = JsseJce.getMessageDigest(algorithm); 299 } 300 } 301 302 /** 303 * Return a MessageDigest for the given algorithm that can be cloned the 304 * specified number of times. If the default implementation supports 305 * cloning, it is returned. Otherwise, an instance of this class is 306 * returned. 307 */ 308 static MessageDigest getDigest(String algorithm, int n) 309 throws NoSuchAlgorithmException { 310 MessageDigest digest = JsseJce.getMessageDigest(algorithm); 311 try { 312 digest.clone(); 313 // already cloneable, use it 314 return digest; 315 } catch (CloneNotSupportedException e) { 316 return new CloneableDigest(digest, n, algorithm); 317 } 318 } 319 320 /** 321 * Check if this object is still usable. If it has already been cloned the 322 * maximum number of times, there are no digests left and this object can no 323 * longer be used. 324 */ 325 private void checkState() { 326 // XXX handshaking currently doesn't stop updating hashes... 327 // if (digests[0] == null) { 328 // throw new IllegalStateException("no digests left"); 329 // } 330 } 331 332 @Override 333 protected int engineGetDigestLength() { 334 checkState(); 335 return digests[0].getDigestLength(); 336 } 337 338 @Override 339 protected void engineUpdate(byte b) { 340 checkState(); 341 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 342 digests[i].update(b); 343 } 344 } 345 346 @Override 347 protected void engineUpdate(byte[] b, int offset, int len) { 348 checkState(); 349 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 350 digests[i].update(b, offset, len); 351 } 352 } 353 354 @Override 355 protected byte[] engineDigest() { 356 checkState(); 357 byte[] digest = digests[0].digest(); 358 digestReset(); 359 return digest; 360 } 361 362 @Override 363 protected int engineDigest(byte[] buf, int offset, int len) 364 throws DigestException { 365 checkState(); 366 int n = digests[0].digest(buf, offset, len); 367 digestReset(); 368 return n; 369 } 370 371 /** 372 * Reset all digests after a digest() call. digests[0] has already been 373 * implicitly reset by the digest() call and does not need to be reset 374 * again. 375 */ 376 private void digestReset() { 377 for (int i = 1; (i < digests.length) && (digests[i] != null); i++) { 378 digests[i].reset(); 379 } 380 } 381 382 @Override 383 protected void engineReset() { 384 checkState(); 385 for (int i = 0; (i < digests.length) && (digests[i] != null); i++) { 386 digests[i].reset(); 387 } 388 } 389 390 @Override 391 public Object clone() { 392 checkState(); 393 for (int i = digests.length - 1; i >= 0; i--) { 394 if (digests[i] != null) { 395 MessageDigest digest = digests[i]; 396 digests[i] = null; 397 return digest; 398 } 399 } 400 // cannot occur 401 throw new InternalError(); 402 } 403 404 }