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
27package sun.security.ssl;
28
29import java.security.InvalidKeyException;
30import java.security.NoSuchAlgorithmException;
31
32import java.nio.ByteBuffer;
33
34import javax.crypto.Mac;
35import javax.crypto.SecretKey;
36
37import sun.security.ssl.CipherSuite.MacAlg;
38import 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 */
54final 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}