1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.generators; 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.DataLengthException; 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.DerivationFunction; 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.DerivationParameters; 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.Digest; 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.ISO18033KDFParameters; 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.KDFParameters; 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <br> 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implementation is based on ISO 18033/P1363a. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class BaseKDFBytesGenerator 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project implements DerivationFunction 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int counterStart; 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private Digest digest; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] shared; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] iv; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Construct a KDF Parameters generator. 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param counterStart value of counter. 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param digest the digest to be used as the source of derived keys. 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected BaseKDFBytesGenerator( 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int counterStart, 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Digest digest) 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.counterStart = counterStart; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.digest = digest; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void init( 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DerivationParameters param) 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (param instanceof KDFParameters) 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project KDFParameters p = (KDFParameters)param; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shared = p.getSharedSecret(); 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project iv = p.getIV(); 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (param instanceof ISO18033KDFParameters) 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ISO18033KDFParameters p = (ISO18033KDFParameters)param; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shared = p.getSeed(); 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project iv = null; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("KDF parameters required for KDF2Generator"); 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return the underlying digest. 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Digest getDigest() 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return digest; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fill len bytes of the output buffer with bytes generated from 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the derivation function. 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IllegalArgumentException if the size of the request will cause an overflow. 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws DataLengthException if the out buffer is too small. 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int generateBytes( 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] out, 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int outOff, 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len) 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws DataLengthException, IllegalArgumentException 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((out.length - len) < outOff) 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new DataLengthException("output buffer too small"); 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long oBytes = len; 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int outLen = digest.getDigestSize(); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // this is at odds with the standard implementation, the 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // maximum value should be hBits * (2^32 - 1) where hBits 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // is the digest output size in bits. We can't have an 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // array with a long index at the moment... 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (oBytes > ((2L << 32) - 1)) 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("Output length too large"); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int cThreshold = (int)((oBytes + outLen - 1) / outLen); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] dig = null; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dig = new byte[digest.getDigestSize()]; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int counter = counterStart; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < cThreshold; i++) 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update(shared, 0, shared.length); 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update((byte)(counter >> 24)); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update((byte)(counter >> 16)); 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update((byte)(counter >> 8)); 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update((byte)counter); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (iv != null) 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.update(iv, 0, iv.length); 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.doFinal(dig, 0); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len > outLen) 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(dig, 0, out, outOff, outLen); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outOff += outLen; 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project len -= outLen; 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(dig, 0, out, outOff, len); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project counter++; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project digest.reset(); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return len; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 143