1 /* 2 * Copyright (c) 2015, 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 package sun.security.ssl; 27 28 import java.io.IOException; 29 import javax.net.ssl.SSLProtocolException; 30 import java.security.MessageDigest; 31 import java.security.SecureRandom; 32 33 import sun.security.ssl.HandshakeMessage.ClientHello; 34 35 /* 36 * HelloVerifyRequest cookie manager 37 */ 38 final class HelloCookieManager { 39 // the cookie secret life time 40 private static long COOKIE_TIMING_WINDOW = 3600000; // in milliseconds 41 private static int COOKIE_MAX_LENGTH_DTLS10 = 32; // 32 bytes 42 private static int COOKIE_MAX_LENGTH_DTLS12 = 0xFF; // 2^8 -1 bytes 43 44 private final SecureRandom secureRandom; 45 private final MessageDigest cookieDigest; 46 47 private int cookieVersion; // allow to wrap 48 private long secretLifetime; 49 private byte[] cookieSecret; 50 51 private int prevCookieVersion; 52 private byte[] prevCookieSecret; 53 54 HelloCookieManager(SecureRandom secureRandom) { 55 this.secureRandom = secureRandom; 56 this.cookieDigest = JsseJce.getMessageDigest("SHA-256"); 57 58 this.cookieVersion = secureRandom.nextInt(); 59 this.secretLifetime = 0; 60 this.cookieSecret = null; 61 62 this.prevCookieVersion = 0; 63 this.prevCookieSecret = null; 64 } 65 66 // Used by server side to generate cookies in HelloVerifyRequest message. 67 synchronized byte[] getCookie(ClientHello clientHelloMsg) { 68 if (secretLifetime < System.currentTimeMillis()) { 69 if (cookieSecret != null) { 70 prevCookieVersion = cookieVersion; 71 prevCookieSecret = cookieSecret.clone(); 72 } else { 73 cookieSecret = new byte[32]; 74 } 75 76 cookieVersion++; 77 secureRandom.nextBytes(cookieSecret); 78 secretLifetime = System.currentTimeMillis() + COOKIE_TIMING_WINDOW; 79 } 80 81 clientHelloMsg.updateHelloCookie(cookieDigest); 82 byte[] cookie = cookieDigest.digest(cookieSecret); // 32 bytes 83 cookie[0] = (byte)((cookieVersion >> 24) & 0xFF); 84 cookie[1] = (byte)((cookieVersion >> 16) & 0xFF); 85 cookie[2] = (byte)((cookieVersion >> 8) & 0xFF); 86 cookie[3] = (byte)(cookieVersion & 0xFF); 87 88 return cookie; 89 } 90 91 // Used by server side to check the cookie in ClientHello message. 92 synchronized boolean isValid(ClientHello clientHelloMsg) { 93 byte[] cookie = clientHelloMsg.cookie; 94 95 // no cookie exchange or not a valid cookie length 96 if ((cookie == null) || (cookie.length != 32)) { 97 return false; 98 } 99 100 int version = ((cookie[0] & 0xFF) << 24) | 101 ((cookie[1] & 0xFF) << 16) | 102 ((cookie[2] & 0xFF) << 8) | 103 (cookie[3] & 0xFF); 104 105 byte[] secret; 106 if (version == cookieVersion) { 107 secret = cookieSecret; 108 } else if (version == prevCookieVersion) { 109 secret = prevCookieSecret; 110 } else { 111 return false; // may be out of the timing window 112 } 113 114 clientHelloMsg.updateHelloCookie(cookieDigest); 115 byte[] target = cookieDigest.digest(secret); // 32 bytes 116 117 for (int i = 4; i < 32; i++) { 118 if (cookie[i] != target[i]) { 119 return false; 120 } 121 } 122 123 return true; 124 } 125 126 // Used by client side to check the cookie in HelloVerifyRequest message. 127 static void checkCookie(ProtocolVersion protocolVersion, 128 byte[] cookie) throws IOException { 129 if (cookie != null && cookie.length != 0) { 130 int limit = COOKIE_MAX_LENGTH_DTLS12; 131 if (protocolVersion.v == ProtocolVersion.DTLS10.v) { 132 limit = COOKIE_MAX_LENGTH_DTLS10; 133 } 134 135 if (cookie.length > COOKIE_MAX_LENGTH_DTLS10) { 136 throw new SSLProtocolException( 137 "Invalid HelloVerifyRequest.cookie (length = " + 138 cookie.length + " bytes)"); 139 } 140 } 141 142 // Otherwise, no cookie exchange. 143 } 144 }