01: package org.bouncycastle.crypto.tls;
02:
03: import org.bouncycastle.crypto.Digest;
04: import org.bouncycastle.crypto.macs.HMac;
05: import org.bouncycastle.crypto.params.KeyParameter;
06:
07: import java.io.ByteArrayOutputStream;
08: import java.io.IOException;
09:
10: /**
11: * A generic TLS MAC implementation, which can be used with any kind of
12: * Digest to act as an HMAC.
13: */
14: public class TlsMac {
15: private long seqNo;
16: private HMac mac;
17:
18: /**
19: * Generate a new instance of an TlsMac.
20: *
21: * @param digest The digest to use.
22: * @param key_block A byte-array where the key for this mac is located.
23: * @param offset The number of bytes to skip, before the key starts in the buffer.
24: * @param len The length of the key.
25: */
26: protected TlsMac(Digest digest, byte[] key_block, int offset,
27: int len) {
28: this .mac = new HMac(digest);
29: KeyParameter param = new KeyParameter(key_block, offset, len);
30: this .mac.init(param);
31: this .seqNo = 0;
32: }
33:
34: /**
35: * @return The Keysize of the mac.
36: */
37: protected int getSize() {
38: return mac.getMacSize();
39: }
40:
41: /**
42: * Calculate the mac for some given data.
43: * <p/>
44: * TlsMac will keep track of the sequence number internally.
45: *
46: * @param type The message type of the message.
47: * @param message A byte-buffer containing the message.
48: * @param offset The number of bytes to skip, before the message starts.
49: * @param len The length of the message.
50: * @return A new byte-buffer containing the mac value.
51: */
52: protected byte[] calculateMac(short type, byte[] message,
53: int offset, int len) {
54: try {
55: ByteArrayOutputStream bosMac = new ByteArrayOutputStream();
56: TlsUtils.writeUint64(seqNo++, bosMac);
57: TlsUtils.writeUint8(type, bosMac);
58: TlsUtils.writeVersion(bosMac);
59: TlsUtils.writeUint16(len, bosMac);
60: bosMac.write(message, offset, len);
61: byte[] macData = bosMac.toByteArray();
62: mac.update(macData, 0, macData.length);
63: byte[] result = new byte[mac.getMacSize()];
64: mac.doFinal(result, 0);
65: mac.reset();
66: return result;
67: } catch (IOException e) {
68: // This should never happen
69: throw new IllegalStateException(
70: "Internal error during mac calculation");
71: }
72: }
73:
74: }
|