01: package ch.ethz.ssh2.crypto;
02:
03: import ch.ethz.ssh2.crypto.digest.HashForSSH2Types;
04: import java.math.BigInteger;
05:
06: /**
07: * Establishes key material for iv/key/mac (both directions).
08: *
09: * @author Christian Plattner, plattner@inf.ethz.ch
10: * @version $Id: KeyMaterial.java,v 1.2 2005/12/05 17:13:27 cplattne Exp $
11: */
12: public class KeyMaterial {
13: public byte[] initial_iv_client_to_server;
14: public byte[] initial_iv_server_to_client;
15: public byte[] enc_key_client_to_server;
16: public byte[] enc_key_server_to_client;
17: public byte[] integrity_key_client_to_server;
18: public byte[] integrity_key_server_to_client;
19:
20: private static byte[] calculateKey(HashForSSH2Types sh,
21: BigInteger K, byte[] H, byte type, byte[] SessionID,
22: int keyLength) {
23: byte[] res = new byte[keyLength];
24:
25: int dglen = sh.getDigestLength();
26: int numRounds = (keyLength + dglen - 1) / dglen;
27:
28: byte[][] tmp = new byte[numRounds][];
29:
30: sh.reset();
31: sh.updateBigInt(K);
32: sh.updateBytes(H);
33: sh.updateByte(type);
34: sh.updateBytes(SessionID);
35:
36: tmp[0] = sh.getDigest();
37:
38: int off = 0;
39: int produced = Math.min(dglen, keyLength);
40:
41: System.arraycopy(tmp[0], 0, res, off, produced);
42:
43: keyLength -= produced;
44: off += produced;
45:
46: for (int i = 1; i < numRounds; i++) {
47: sh.updateBigInt(K);
48: sh.updateBytes(H);
49:
50: for (int j = 0; j < i; j++)
51: sh.updateBytes(tmp[j]);
52:
53: tmp[i] = sh.getDigest();
54:
55: produced = Math.min(dglen, keyLength);
56: System.arraycopy(tmp[i], 0, res, off, produced);
57: keyLength -= produced;
58: off += produced;
59: }
60:
61: return res;
62: }
63:
64: public static KeyMaterial create(String hashType, byte[] H,
65: BigInteger K, byte[] SessionID, int keyLengthCS,
66: int blockSizeCS, int macLengthCS, int keyLengthSC,
67: int blockSizeSC, int macLengthSC)
68: throws IllegalArgumentException {
69: KeyMaterial km = new KeyMaterial();
70:
71: HashForSSH2Types sh = new HashForSSH2Types(hashType);
72:
73: km.initial_iv_client_to_server = calculateKey(sh, K, H,
74: (byte) 'A', SessionID, blockSizeCS);
75:
76: km.initial_iv_server_to_client = calculateKey(sh, K, H,
77: (byte) 'B', SessionID, blockSizeSC);
78:
79: km.enc_key_client_to_server = calculateKey(sh, K, H,
80: (byte) 'C', SessionID, keyLengthCS);
81:
82: km.enc_key_server_to_client = calculateKey(sh, K, H,
83: (byte) 'D', SessionID, keyLengthSC);
84:
85: km.integrity_key_client_to_server = calculateKey(sh, K, H,
86: (byte) 'E', SessionID, macLengthCS);
87:
88: km.integrity_key_server_to_client = calculateKey(sh, K, H,
89: (byte) 'F', SessionID, macLengthSC);
90:
91: return km;
92: }
93: }
|