1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.jce.provider;
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.KDFParameters;
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generator for PBE derived keys and ivs as defined by IEEE P1363a
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <br>
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implementation is based on draft 9 of IEEE P1363a. <b>Note:</b>
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as this is still a draft the output of this generator may change, don't
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * use it for anything that might be subject to long term storage.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class BrokenKDF2BytesGenerator
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    implements DerivationFunction
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
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 KDF2 Parameters generator. Generates key material
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * according to IEEE P1363a - if you want orthodox results you should
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * use a digest specified in the standard.
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <b>Note:</b> IEEE P1363a standard is still a draft standard, if the standard
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * changes this function, the output of this function will change as well.
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Don't use this routine for anything subject to long term storage.
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param digest the digest to be used as the source of derived keys.
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public BrokenKDF2BytesGenerator(
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Digest  digest)
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.digest = digest;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void init(
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DerivationParameters    param)
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(param instanceof KDFParameters))
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        KDFParameters   p = (KDFParameters)param;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        shared = p.getSharedSecret();
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        iv = p.getIV();
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return the underlying digest.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Digest getDigest()
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return digest;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fill len bytes of the output buffer with bytes generated from
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the derivation function.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalArgumentException if the size of the request will cause an overflow.
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws DataLengthException if the out buffer is too small.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int generateBytes(
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  out,
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     outOff,
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     len)
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throws DataLengthException, IllegalArgumentException
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((out.length - len) < outOff)
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new DataLengthException("output buffer too small");
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long    oBits = len * 8;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // this is at odds with the standard implementation, the
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // maximum value should be hBits * (2^23 - 1) where hBits
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // is the digest output size in bits. We can't have an
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // array with a long index at the moment...
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (oBits > (digest.getDigestSize() * 8 * (2L^32 - 1)))
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new IllegalArgumentException("Output length to large");
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cThreshold = (int)(oBits / digest.getDigestSize());
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] dig = null;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dig = new byte[digest.getDigestSize()];
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int counter = 1; counter <= cThreshold; counter++)
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(shared, 0, shared.length);
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update((byte)(counter & 0xff));
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update((byte)((counter >> 8) & 0xff));
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update((byte)((counter >> 16) & 0xff));
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update((byte)((counter >> 24) & 0xff));
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(iv, 0, iv.length);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.doFinal(dig, 0);
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((len - outOff) > dig.length)
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.arraycopy(dig, 0, out, outOff, dig.length);
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outOff += dig.length;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.arraycopy(dig, 0, out, outOff, len - outOff);
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.reset();
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return len;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
128