History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/MAC.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/MAC.java+235−0
@@ -0,0 +1,235 @@
1+/*
2+ * Copyright (c) 1996, 2010, 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+
40+/**
41+ * This class computes the "Message Authentication Code" (MAC) for each
42+ * SSL message. This is essentially a shared-secret signature, used to
43+ * provide integrity protection for SSL messages. The MAC is actually
44+ * one of several keyed hashes, as associated with the cipher suite and
45+ * protocol version. (SSL v3.0 uses one construct, TLS uses another.)
46+ *
47+ * <P>NOTE: MAC computation is the only place in the SSL protocol that the
48+ * sequence number is used. It's also reset to zero with each change of
49+ * a cipher spec, so this is the only place this state is needed.
50+ *
51+ * @author David Brownell
52+ * @author Andreas Sterbenz
53+ */
54+final class MAC {
55+
56+ final static MAC NULL = new MAC();
57+
58+ // Value of the null MAC is fixed
59+ private static final byte nullMAC[] = new byte[0];
60+
61+ // internal identifier for the MAC algorithm
62+ private final MacAlg macAlg;
63+
64+ // stuff defined by the kind of MAC algorithm
65+ private final int macSize;
66+
67+ // JCE Mac object
68+ private final Mac mac;
69+
70+ // byte array containing the additional information we MAC in each record
71+ // (see below)
72+ private final byte[] block;
73+
74+ // sequence number + record type + + record length
75+ private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
76+
77+ // sequence number + record type + protocol version + record length
78+ private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
79+
80+ // offset of record type in block
81+ private static final int BLOCK_OFFSET_TYPE = 8;
82+
83+ // offset of protocol version number in block (TLS only)
84+ private static final int BLOCK_OFFSET_VERSION = 8 + 1;
85+
86+ private MAC() {
87+ macSize = 0;
88+ macAlg = M_NULL;
89+ mac = null;
90+ block = null;
91+ }
92+
93+ /**
94+ * Set up, configured for the given SSL/TLS MAC type and version.
95+ */
96+ MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
97+ throws NoSuchAlgorithmException, InvalidKeyException {
98+ this.macAlg = macAlg;
99+ this.macSize = macAlg.size;
100+
101+ String algorithm;
102+ boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);
103+
104+ if (macAlg == M_MD5) {
105+ algorithm = tls ? "HmacMD5" : "SslMacMD5";
106+ } else if (macAlg == M_SHA) {
107+ algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
108+ } else if (macAlg == M_SHA256) {
109+ algorithm = "HmacSHA256"; // TLS 1.2+
110+ } else if (macAlg == M_SHA384) {
111+ algorithm = "HmacSHA384"; // TLS 1.2+
112+ } else {
113+ throw new RuntimeException("Unknown Mac " + macAlg);
114+ }
115+
116+ mac = JsseJce.getMac(algorithm);
117+ mac.init(key);
118+
119+ if (tls) {
120+ block = new byte[BLOCK_SIZE_TLS];
121+ block[BLOCK_OFFSET_VERSION] = protocolVersion.major;
122+ block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
123+ } else {
124+ block = new byte[BLOCK_SIZE_SSL];
125+ }
126+ }
127+
128+ /**
129+ * Returns the length of the MAC.
130+ */
131+ int MAClen() {
132+ return macSize;
133+ }
134+
135+ /**
136+ * Computes and returns the MAC for the data in this byte array.
137+ *
138+ * @param type record type
139+ * @param buf compressed record on which the MAC is computed
140+ * @param offset start of compressed record data
141+ * @param len the size of the compressed record
142+ */
143+ final byte[] compute(byte type, byte buf[], int offset, int len) {
144+ return compute(type, null, buf, offset, len);
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+ */
158+ final byte[] compute(byte type, ByteBuffer bb) {
159+ return compute(type, bb, null, 0, bb.remaining());
160+ }
161+
162+ /**
163+ * Check whether the sequence number is close to wrap
164+ *
165+ * Sequence numbers are of type uint64 and may not exceed 2^64-1.
166+ * Sequence numbers do not wrap. When the sequence number is near
167+ * to wrap, we need to close the connection immediately.
168+ */
169+ final boolean seqNumOverflow() {
170+ /*
171+ * Conservatively, we don't allow more records to be generated
172+ * when there are only 2^8 sequence numbers left.
173+ */
174+ return (block != null && mac != null &&
175+ block[0] == 0xFF && block[1] == 0xFF &&
176+ block[2] == 0xFF && block[3] == 0xFF &&
177+ block[4] == 0xFF && block[5] == 0xFF &&
178+ block[6] == 0xFF);
179+ }
180+
181+ /*
182+ * Check whether to renew the sequence number
183+ *
184+ * Sequence numbers are of type uint64 and may not exceed 2^64-1.
185+ * Sequence numbers do not wrap. If a TLS
186+ * implementation would need to wrap a sequence number, it must
187+ * renegotiate instead.
188+ */
189+ final boolean seqNumIsHuge() {
190+ /*
191+ * Conservatively, we should ask for renegotiation when there are
192+ * only 2^48 sequence numbers left.
193+ */
194+ return (block != null && mac != null &&
195+ block[0] == 0xFF && block[1] == 0xFF);
196+ }
197+
198+ // increment the sequence number in the block array
199+ // it is a 64-bit number stored in big-endian format
200+ private void incrementSequenceNumber() {
201+ int k = 7;
202+ while ((k >= 0) && (++block[k] == 0)) {
203+ k--;
204+ }
205+ }
206+
207+ /*
208+ * Compute based on either buffer type, either bb.position/limit
209+ * or buf/offset/len.
210+ */
211+ private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
212+ int offset, int len) {
213+
214+ if (macSize == 0) {
215+ return nullMAC;
216+ }
217+
218+ block[BLOCK_OFFSET_TYPE] = type;
219+ block[block.length - 2] = (byte)(len >> 8);
220+ block[block.length - 1] = (byte)(len );
221+
222+ mac.update(block);
223+ incrementSequenceNumber();
224+
225+ // content
226+ if (bb != null) {
227+ mac.update(bb);
228+ } else {
229+ mac.update(buf, offset, len);
230+ }
231+
232+ return mac.doFinal();
233+ }
234+
235+}