Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 package ch.ethz.ssh2.crypto;
      6 
      7 import ch.ethz.ssh2.crypto.digest.HashForSSH2Types;
      8 import 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  */
     16 public 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