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