1 /* 2 * Copyright (c) 1996, 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.security.InvalidKeyException; 29 import java.security.NoSuchAlgorithmException; 30 31 import java.nio.ByteBuffer; 32 33 import javax.crypto.Mac; 34 import javax.crypto.SecretKey; 35 36 import sun.security.ssl.CipherSuite.MacAlg; 37 import static sun.security.ssl.CipherSuite.*; 38 import static sun.security.ssl.CipherSuite.MacAlg.*; 39 40 /** 41 * This class computes the "Message Authentication Code" (MAC) for each 42 * SSL stream and block cipher message. This is essentially a shared-secret 43 * signature, used to provide integrity protection for SSL messages. The 44 * MAC is actually one of several keyed hashes, as associated with the cipher 45 * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.) 46 * 47 * @author David Brownell 48 * @author Andreas Sterbenz 49 */ 50 final class MAC extends Authenticator { 51 52 static final MAC TLS_NULL = new MAC(false); 53 54 // Value of the null MAC is fixed 55 private static final byte[] nullMAC = new byte[0]; 56 57 // internal identifier for the MAC algorithm 58 private final MacAlg macAlg; 59 60 // JCE Mac object 61 private final Mac mac; 62 63 MAC(boolean isDTLS) { 64 super(isDTLS); 65 66 macAlg = M_NULL; 67 mac = null; 68 } 69 70 /** 71 * Set up, configured for the given MAC type and version. 72 */ 73 MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) 74 throws NoSuchAlgorithmException, InvalidKeyException { 75 super(protocolVersion); 76 this.macAlg = macAlg; 77 78 String algorithm; 79 80 // using SSL MAC computation? 81 boolean useSSLMac = (protocolVersion.v < ProtocolVersion.TLS10.v); 82 83 if (macAlg == M_MD5) { 84 algorithm = useSSLMac ? "SslMacMD5" : "HmacMD5"; 85 } else if (macAlg == M_SHA) { 86 algorithm = useSSLMac ? "SslMacSHA1" : "HmacSHA1"; 87 } else if (macAlg == M_SHA256) { 88 algorithm = "HmacSHA256"; // TLS 1.2+ 89 } else if (macAlg == M_SHA384) { 90 algorithm = "HmacSHA384"; // TLS 1.2+ 91 } else { 92 throw new RuntimeException("Unknown Mac " + macAlg); 93 } 94 95 mac = JsseJce.getMac(algorithm); 96 mac.init(key); 97 } 98 99 /** 100 * Returns the length of the MAC. 101 */ 102 int MAClen() { 103 return macAlg.size; 104 } 105 106 /** 107 * Returns the hash function block length of the MAC alorithm. 108 */ 109 int hashBlockLen() { 110 return macAlg.hashBlockSize; 111 } 112 113 /** 114 * Returns the hash function minimal padding length of the MAC alorithm. 115 */ 116 int minimalPaddingLen() { 117 return macAlg.minimalPaddingSize; 118 } 119 120 /** 121 * Computes and returns the MAC for the data in this byte array. 122 * 123 * @param type record type 124 * @param buf compressed record on which the MAC is computed 125 * @param offset start of compressed record data 126 * @param len the size of the compressed record 127 * @param isSimulated if true, simulate the MAC computation 128 * 129 * @return the MAC result 130 */ 131 final byte[] compute(byte type, byte buf[], 132 int offset, int len, boolean isSimulated) { 133 if (macAlg.size == 0) { 134 return nullMAC; 135 } 136 137 if (!isSimulated) { 138 // Uses the implicit sequence number for the computation. 139 byte[] additional = acquireAuthenticationBytes(type, len, null); 140 mac.update(additional); 141 } 142 mac.update(buf, offset, len); 143 144 return mac.doFinal(); 145 } 146 147 /** 148 * Compute and returns the MAC for the remaining data 149 * in this ByteBuffer. 150 * 151 * On return, the bb position == limit, and limit will 152 * have not changed. 153 * 154 * @param type record type 155 * @param bb a ByteBuffer in which the position and limit 156 * demarcate the data to be MAC'd. 157 * @param isSimulated if true, simulate the MAC computation 158 * @param sequence the explicit sequence number, or null if using 159 * the implicit sequence number for the computation 160 * 161 * @return the MAC result 162 */ 163 final byte[] compute(byte type, ByteBuffer bb, 164 byte[] sequence, boolean isSimulated) { 165 166 if (macAlg.size == 0) { 167 return nullMAC; 168 } 169 170 if (!isSimulated) { 171 // Uses the explicit sequence number for the computation. 172 byte[] additional = 173 acquireAuthenticationBytes(type, bb.remaining(), sequence); 174 mac.update(additional); 175 } 176 mac.update(bb); 177 178 return mac.doFinal(); 179 } 180 181 /** 182 * Compute and returns the MAC for the remaining data 183 * in this ByteBuffer. 184 * 185 * On return, the bb position == limit, and limit will 186 * have not changed. 187 * 188 * @param type record type 189 * @param bb a ByteBuffer in which the position and limit 190 * demarcate the data to be MAC'd. 191 * @param isSimulated if true, simulate the MAC computation 192 * 193 * @return the MAC result 194 */ 195 final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { 196 // Uses the implicit sequence number for the computation. 197 return compute(type, bb, null, isSimulated); 198 } 199 }