AESWrapEngine.java revision b61a96e7ef1a78acf013bbf08fe537e5b5f129ca
1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.engines; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.BlockCipher; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.DataLengthException; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.InvalidCipherTextException; 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Wrapper; 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter; 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithIV; 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * an implementation of the AES Key Wrapper from the NIST Key Wrap 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Specification. 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>. 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class AESWrapEngine 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam implements Wrapper 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private BlockCipher engine = new AESEngine(); 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private KeyParameter param; 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private boolean forWrapping; 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] iv = { 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6, 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 }; 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void init( 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean forWrapping, 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam CipherParameters param) 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.forWrapping = forWrapping; 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (param instanceof KeyParameter) 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.param = (KeyParameter)param; 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else if (param instanceof ParametersWithIV) 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.iv = ((ParametersWithIV) param).getIV(); 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.param = (KeyParameter) ((ParametersWithIV) param).getParameters(); 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (this.iv.length != 8) 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException("IV not multiple of 8"); 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public String getAlgorithmName() 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return "AES"; 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public byte[] wrap( 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inLen) 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (!forWrapping) 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalStateException("not set for wrapping"); 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int n = inLen / 8; 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((n * 8) != inLen) 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new DataLengthException("wrap data must be a multiple of 8 bytes"); 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] block = new byte[inLen + iv.length]; 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] buf = new byte[8 + iv.length]; 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(iv, 0, block, 0, iv.length); 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, 0, block, iv.length, inLen); 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam engine.init(true, param); 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int j = 0; j != 6; j++) 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 1; i <= n; i++) 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(block, 0, buf, 0, iv.length); 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(block, 8 * i, buf, iv.length, 8); 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam engine.processBlock(buf, 0, buf, 0); 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int t = n * j + i; 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int k = 1; t != 0; k++) 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte v = (byte)t; 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam buf[iv.length - k] ^= v; 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam t >>>= 8; 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(buf, 0, block, 0, 8); 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(buf, 8, block, 8 * i, 8); 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return block; 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public byte[] unwrap( 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inLen) 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws InvalidCipherTextException 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (forWrapping) 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalStateException("not set for unwrapping"); 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int n = inLen / 8; 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((n * 8) != inLen) 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes"); 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] block = new byte[inLen - iv.length]; 124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] a = new byte[iv.length]; 125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] buf = new byte[8 + iv.length]; 126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, 0, a, 0, iv.length); 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, iv.length, block, 0, inLen - iv.length); 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam engine.init(false, param); 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam n = n - 1; 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int j = 5; j >= 0; j--) 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = n; i >= 1; i--) 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(a, 0, buf, 0, iv.length); 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8); 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int t = n * j + i; 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int k = 1; t != 0; k++) 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte v = (byte)t; 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam buf[iv.length - k] ^= v; 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam t >>>= 8; 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam engine.processBlock(buf, 0, buf, 0); 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(buf, 0, a, 0, 8); 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(buf, 8, block, 8 * (i - 1), 8); 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i != iv.length; i++) 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (a[i] != iv[i]) 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new InvalidCipherTextException("checksum failed"); 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return block; 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 168