1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.macs; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Hashtable; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Digest; 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.ExtendedDigest; 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Mac; 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter; 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * HMAC implementation based on RFC2104 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * H(K XOR opad, H(K XOR ipad, text)) 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class HMac 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam implements Mac 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private final static byte IPAD = (byte)0x36; 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private final static byte OPAD = (byte)0x5C; 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private Digest digest; 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private int digestSize; 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private int blockLength; 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] inputPad; 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] outputPad; 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private static Hashtable blockLengths; 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam static 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths = new Hashtable(); 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // BEGIN android-removed 364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("GOST3411", Integer.valueOf(32)); 374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // 384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("MD2", Integer.valueOf(16)); 394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("MD4", Integer.valueOf(64)); 404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // END android-removed 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths.put("MD5", Integer.valueOf(64)); 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // BEGIN android-removed 444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("RIPEMD128", Integer.valueOf(64)); 454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("RIPEMD160", Integer.valueOf(64)); 464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // END android-removed 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths.put("SHA-1", Integer.valueOf(64)); 494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // BEGIN android-removed 504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("SHA-224", Integer.valueOf(64)); 514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // END android-removed 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths.put("SHA-256", Integer.valueOf(64)); 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths.put("SHA-384", Integer.valueOf(128)); 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam blockLengths.put("SHA-512", Integer.valueOf(128)); 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // BEGIN android-removed 574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("Tiger", Integer.valueOf(64)); 584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // blockLengths.put("Whirlpool", Integer.valueOf(64)); 594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // END android-removed 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private static int getByteLength( 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Digest digest) 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (digest instanceof ExtendedDigest) 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return ((ExtendedDigest)digest).getByteLength(); 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Integer b = (Integer)blockLengths.get(digest.getAlgorithmName()); 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (b == null) 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName()); 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return b.intValue(); 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Base constructor for one of the standard digest algorithms that the 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * byteLength of the algorithm is know for. 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param digest the digest. 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public HMac( 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Digest digest) 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this(digest, getByteLength(digest)); 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private HMac( 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Digest digest, 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int byteLength) 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.digest = digest; 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digestSize = digest.getDigestSize(); 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.blockLength = byteLength; 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inputPad = new byte[blockLength]; 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam outputPad = new byte[blockLength]; 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public String getAlgorithmName() 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return digest.getAlgorithmName() + "/HMAC"; 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public Digest getUnderlyingDigest() 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return digest; 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void init( 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam CipherParameters params) 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.reset(); 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] key = ((KeyParameter)params).getKey(); 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (key.length > blockLength) 123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(key, 0, key.length); 125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.doFinal(inputPad, 0); 126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = digestSize; i < inputPad.length; i++) 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inputPad[i] = 0; 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(key, 0, inputPad, 0, key.length); 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = key.length; i < inputPad.length; i++) 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inputPad[i] = 0; 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam outputPad = new byte[inputPad.length]; 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length); 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i < inputPad.length; i++) 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inputPad[i] ^= IPAD; 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i < outputPad.length; i++) 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam outputPad[i] ^= OPAD; 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(inputPad, 0, inputPad.length); 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getMacSize() 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return digestSize; 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void update( 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte in) 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(in); 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void update( 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int len) 171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(in, inOff, len); 173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int doFinal( 176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] tmp = new byte[digestSize]; 180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.doFinal(tmp, 0); 181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(outputPad, 0, outputPad.length); 183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(tmp, 0, tmp.length); 184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int len = digest.doFinal(out, outOff); 186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return len; 190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Reset the mac generator. 194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void reset() 196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * reset the underlying digest. 199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.reset(); 201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * reinitialize the digest. 204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam digest.update(inputPad, 0, inputPad.length); 206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 208