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.MGFParameters;
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generator for MGF1 as defined in PKCS 1v2
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class MGF1BytesGenerator
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    implements DerivationFunction
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Digest  digest;
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[]  seed;
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int     hLen;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param digest the digest to be used as the source of generated bytes
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public MGF1BytesGenerator(
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Digest  digest)
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.digest = digest;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.hLen = digest.getDigestSize();
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void init(
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DerivationParameters    param)
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(param instanceof MGFParameters))
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("MGF parameters required for MGF1Generator");
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MGFParameters   p = (MGFParameters)param;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        seed = p.getSeed();
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return the underlying digest.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Digest getDigest()
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return digest;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * int to octet string.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void ItoOSP(
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     i,
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  sp)
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[0] = (byte)(i >>> 24);
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[1] = (byte)(i >>> 16);
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[2] = (byte)(i >>> 8);
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[3] = (byte)(i >>> 0);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fill len bytes of the output buffer with bytes generated from
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the derivation function.
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
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        byte[]  hashBuf = new byte[hLen];
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  C = new byte[4];
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     counter = 0;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.reset();
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len > hLen)
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            do
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ItoOSP(counter, C);
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                digest.update(seed, 0, seed.length);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                digest.update(C, 0, C.length);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                digest.doFinal(hashBuf, 0);
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (++counter < (len / hLen));
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((counter * hLen) < len)
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ItoOSP(counter, C);
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(seed, 0, seed.length);
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(C, 0, C.length);
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.doFinal(hashBuf, 0);
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen));
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return len;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
115