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