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