1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.generators;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.Digest;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Mac;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.PBEParametersGenerator;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-changed
8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.crypto.digests.AndroidDigestFactory;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-changed
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.macs.HMac;
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter;
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithIV;
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * This generator uses a SHA-1 HMac as the calculation function.
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p>
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The document this implementation is based on can be found at
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * RSA's PKCS5 Page</a>
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class PKCS5S2ParametersGenerator
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends PBEParametersGenerator
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private Mac hMac;
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * construct a PKCS5 Scheme 2 Parameters generator.
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public PKCS5S2ParametersGenerator()
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-changed
33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    	this(AndroidDigestFactory.getSHA1());
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-changed
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public PKCS5S2ParametersGenerator(Digest digest)
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        hMac = new HMac(digest);
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void F(
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  P,
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  S,
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     c,
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  iBuf,
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  out,
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     outOff)
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]              state = new byte[hMac.getMacSize()];
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CipherParameters    param = new KeyParameter(P);
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        hMac.init(param);
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (S != null)
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            hMac.update(S, 0, S.length);
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        hMac.update(iBuf, 0, iBuf.length);
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        hMac.doFinal(state, 0);
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        System.arraycopy(state, 0, out, outOff, state.length);
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (c == 0)
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("iteration count must be at least 1.");
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int count = 1; count < c; count++)
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            hMac.init(param);
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            hMac.update(state, 0, state.length);
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            hMac.doFinal(state, 0);
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int j = 0; j != state.length; j++)
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                out[outOff + j] ^= state[j];
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void intToOctet(
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  buf,
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     i)
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        buf[0] = (byte)(i >>> 24);
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        buf[1] = (byte)(i >>> 16);
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        buf[2] = (byte)(i >>> 8);
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        buf[3] = (byte)i;
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private byte[] generateDerivedKey(
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int dkLen)
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     hLen = hMac.getMacSize();
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     l = (dkLen + hLen - 1) / hLen;
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  iBuf = new byte[4];
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  out = new byte[l * hLen];
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 1; i <= l; i++)
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            intToOctet(iBuf, i);
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen);
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return out;
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Generate a key parameter derived from the password, salt, and iteration
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * count we are currently initialised with.
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param keySize the size of the key we want (in bits)
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return a KeyParameter object.
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public CipherParameters generateDerivedParameters(
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int keySize)
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keySize = keySize / 8;
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  dKey = generateDerivedKey(keySize);
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return new KeyParameter(dKey, 0, keySize);
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Generate a key with initialisation vector parameter derived from
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * the password, salt, and iteration count we are currently initialised
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * with.
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param keySize the size of the key we want (in bits)
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param ivSize the size of the iv we want (in bits)
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return a ParametersWithIV object.
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public CipherParameters generateDerivedParameters(
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     keySize,
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     ivSize)
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        keySize = keySize / 8;
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ivSize = ivSize / 8;
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  dKey = generateDerivedKey(keySize + ivSize);
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Generate a key parameter for use with a MAC derived from the password,
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * salt, and iteration count we are currently initialised with.
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param keySize the size of the key we want (in bits)
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return a KeyParameter object.
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public CipherParameters generateDerivedMacParameters(
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int keySize)
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return generateDerivedParameters(keySize);
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
163