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