| /* |
| * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.security.ssl; |
| |
| import java.security.InvalidKeyException; |
| import java.security.NoSuchAlgorithmException; |
| |
| import java.nio.ByteBuffer; |
| |
| import javax.crypto.Mac; |
| import javax.crypto.SecretKey; |
| |
| import sun.security.ssl.CipherSuite.MacAlg; |
| import static sun.security.ssl.CipherSuite.*; |
| import static sun.security.ssl.CipherSuite.MacAlg.*; |
| |
| /** |
| * This class computes the "Message Authentication Code" (MAC) for each |
| * SSL stream and block cipher message. This is essentially a shared-secret |
| * signature, used to provide integrity protection for SSL messages. The |
| * MAC is actually one of several keyed hashes, as associated with the cipher |
| * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.) |
| * |
| * @author David Brownell |
| * @author Andreas Sterbenz |
| */ |
| final class MAC extends Authenticator { |
| |
| static final MAC TLS_NULL = new MAC(false); |
| |
| // Value of the null MAC is fixed |
| private static final byte[] nullMAC = new byte[0]; |
| |
| // internal identifier for the MAC algorithm |
| private final MacAlg macAlg; |
| |
| // JCE Mac object |
| private final Mac mac; |
| |
| MAC(boolean isDTLS) { |
| super(isDTLS); |
| |
| macAlg = M_NULL; |
| mac = null; |
| } |
| |
| /** |
| * Set up, configured for the given MAC type and version. |
| */ |
| MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) |
| throws NoSuchAlgorithmException, InvalidKeyException { |
| super(protocolVersion); |
| this.macAlg = macAlg; |
| |
| String algorithm; |
| |
| // using SSL MAC computation? |
| boolean useSSLMac = (protocolVersion.v < ProtocolVersion.TLS10.v); |
| |
| if (macAlg == M_MD5) { |
| algorithm = useSSLMac ? "SslMacMD5" : "HmacMD5"; |
| } else if (macAlg == M_SHA) { |
| algorithm = useSSLMac ? "SslMacSHA1" : "HmacSHA1"; |
| } else if (macAlg == M_SHA256) { |
| algorithm = "HmacSHA256"; // TLS 1.2+ |
| } else if (macAlg == M_SHA384) { |
| algorithm = "HmacSHA384"; // TLS 1.2+ |
| } else { |
| throw new RuntimeException("Unknown Mac " + macAlg); |
| } |
| |
| mac = JsseJce.getMac(algorithm); |
| mac.init(key); |
| } |
| |
| /** |
| * Returns the length of the MAC. |
| */ |
| int MAClen() { |
| return macAlg.size; |
| } |
| |
| /** |
| * Returns the hash function block length of the MAC alorithm. |
| */ |
| int hashBlockLen() { |
| return macAlg.hashBlockSize; |
| } |
| |
| /** |
| * Returns the hash function minimal padding length of the MAC alorithm. |
| */ |
| int minimalPaddingLen() { |
| return macAlg.minimalPaddingSize; |
| } |
| |
| /** |
| * Computes and returns the MAC for the data in this byte array. |
| * |
| * @param type record type |
| * @param buf compressed record on which the MAC is computed |
| * @param offset start of compressed record data |
| * @param len the size of the compressed record |
| * @param isSimulated if true, simulate the MAC computation |
| * |
| * @return the MAC result |
| */ |
| final byte[] compute(byte type, byte buf[], |
| int offset, int len, boolean isSimulated) { |
| if (macAlg.size == 0) { |
| return nullMAC; |
| } |
| |
| if (!isSimulated) { |
| // Uses the implicit sequence number for the computation. |
| byte[] additional = acquireAuthenticationBytes(type, len, null); |
| mac.update(additional); |
| } |
| mac.update(buf, offset, len); |
| |
| return mac.doFinal(); |
| } |
| |
| /** |
| * Compute and returns the MAC for the remaining data |
| * in this ByteBuffer. |
| * |
| * On return, the bb position == limit, and limit will |
| * have not changed. |
| * |
| * @param type record type |
| * @param bb a ByteBuffer in which the position and limit |
| * demarcate the data to be MAC'd. |
| * @param isSimulated if true, simulate the MAC computation |
| * @param sequence the explicit sequence number, or null if using |
| * the implicit sequence number for the computation |
| * |
| * @return the MAC result |
| */ |
| final byte[] compute(byte type, ByteBuffer bb, |
| byte[] sequence, boolean isSimulated) { |
| |
| if (macAlg.size == 0) { |
| return nullMAC; |
| } |
| |
| if (!isSimulated) { |
| // Uses the explicit sequence number for the computation. |
| byte[] additional = |
| acquireAuthenticationBytes(type, bb.remaining(), sequence); |
| mac.update(additional); |
| } |
| mac.update(bb); |
| |
| return mac.doFinal(); |
| } |
| |
| /** |
| * Compute and returns the MAC for the remaining data |
| * in this ByteBuffer. |
| * |
| * On return, the bb position == limit, and limit will |
| * have not changed. |
| * |
| * @param type record type |
| * @param bb a ByteBuffer in which the position and limit |
| * demarcate the data to be MAC'd. |
| * @param isSimulated if true, simulate the the MAC computation |
| * |
| * @return the MAC result |
| */ |
| final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { |
| // Uses the implicit sequence number for the computation. |
| return compute(type, bb, null, isSimulated); |
| } |
| } |