1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.signers;
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom;
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.AsymmetricBlockCipher;
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.CipherParameters;
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.CryptoException;
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.Digest;
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.SignerWithRecovery;
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// BEGIN android-removed
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// import org.bouncycastle.crypto.digests.RIPEMD128Digest;
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// import org.bouncycastle.crypto.digests.RIPEMD160Digest;
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// END android-removed
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.digests.SHA1Digest;
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.ParametersWithRandom;
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.ParametersWithSalt;
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.RSAKeyParameters;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note: the usual length for the salt is the length of the hash
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * function used in bytes.
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class ISO9796d2PSSSigner
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    implements SignerWithRecovery
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final public int   TRAILER_IMPLICIT    = 0xBC;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final public int   TRAILER_RIPEMD160   = 0x31CC;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final public int   TRAILER_RIPEMD128   = 0x32CC;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final public int   TRAILER_SHA1        = 0x33CC;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Digest                      digest;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private AsymmetricBlockCipher       cipher;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private SecureRandom                random;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[]                      standardSalt;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int         hLen;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int         trailer;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int         keyBits;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[]      block;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[]      mBuf;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int         messageLength;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int         saltLength;
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean     fullMessage;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[]      recoveredMessage;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Generate a signer for the with either implicit or explicit trailers
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for ISO9796-2, scheme 2 or 3.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param cipher base cipher to use for signature creation/verification
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param digest digest to use.
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param saltLength length of salt in bytes.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param implicit whether or not the trailer is implicit or gives the hash.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ISO9796d2PSSSigner(
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AsymmetricBlockCipher   cipher,
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Digest                  digest,
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int                     saltLength,
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean                 implicit)
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.cipher = cipher;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.digest = digest;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.hLen = digest.getDigestSize();
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.saltLength = saltLength;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (implicit)
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            trailer = TRAILER_IMPLICIT;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (digest instanceof SHA1Digest)
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                trailer = TRAILER_SHA1;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // BEGIN android-removed
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // else if (digest instanceof RIPEMD160Digest)
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //     trailer = TRAILER_RIPEMD160;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // else if (digest instanceof RIPEMD128Digest)
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //     trailer = TRAILER_RIPEMD128;
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // END android-removed
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("no valid trailer for digest");
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructor for a signer with an explicit digest trailer.
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param cipher cipher to use.
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param digest digest to sign with.
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param saltLength length of salt in bytes.
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ISO9796d2PSSSigner(
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AsymmetricBlockCipher   cipher,
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Digest                  digest,
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int                     saltLength)
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(cipher, digest, saltLength, false);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Initialise the signer.
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param forSigning true if for signing, false if for verification.
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param param parameters for signature generation/verification. If the
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * parameters are for generation they should be a ParametersWithRandom,
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a ParametersWithSalt, or just an RSAKeyParameters object. If RSAKeyParameters
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * are passed in a SecureRandom will be created.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @exception IllegalArgumentException if wrong parameter type or a fixed
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * salt is passed in which is the wrong length.
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void init(
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean                 forSigning,
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CipherParameters        param)
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RSAKeyParameters    kParam = null;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int                    lengthOfSalt = saltLength;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (param instanceof ParametersWithRandom)
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ParametersWithRandom    p = (ParametersWithRandom)param;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kParam = (RSAKeyParameters)p.getParameters();
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            random = p.getRandom();
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (param instanceof ParametersWithSalt)
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ParametersWithSalt    p = (ParametersWithSalt)param;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kParam = (RSAKeyParameters)p.getParameters();
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            standardSalt = p.getSalt();
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lengthOfSalt = standardSalt.length;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kParam = (RSAKeyParameters)param;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (forSigning)
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                random = new SecureRandom();
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cipher.init(forSigning, kParam);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        keyBits = kParam.getModulus().bitLength();
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        block = new byte[(keyBits + 7) / 8];
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (trailer == TRAILER_IMPLICIT)
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 1];
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 2];
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        reset();
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * compare two byte arrays.
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean isSameAs(
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    a,
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    b)
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (messageLength != b.length)
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != b.length; i++)
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (a[i] != b[i])
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * clear possible sensitive data
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void clearBlock(
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  block)
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != block.length; i++)
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[i] = 0;
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * update the internal digest with the byte b
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void update(
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte    b)
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (messageLength < mBuf.length)
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mBuf[messageLength++] = b;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(b);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * update the internal digest with the byte array in
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void update(
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  in,
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     off,
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     len)
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (len > 0 && messageLength < mBuf.length)
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.update(in[off]);
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            off++;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            len--;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len > 0)
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(in, off, len);
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reset the internal state
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void reset()
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.reset();
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        messageLength = 0;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (recoveredMessage != null)
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clearBlock(recoveredMessage);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        recoveredMessage = null;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fullMessage = false;
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * generate a signature for the loaded message using the key we were
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialised with.
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] generateSignature()
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throws CryptoException
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     digSize = digest.getDigestSize();
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    m2Hash = new byte[digSize];
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.doFinal(m2Hash, 0);
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  C = new byte[8];
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LtoOSP(messageLength * 8, C);
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(C, 0, C.length);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(mBuf, 0, messageLength);
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(m2Hash, 0, m2Hash.length);
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    salt;
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (standardSalt != null)
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            salt = standardSalt;
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            salt = new byte[saltLength];
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            random.nextBytes(salt);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(salt, 0, salt.length);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    hash = new byte[digest.getDigestSize()];
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.doFinal(hash, 0);
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int tLength = 2;
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (trailer == TRAILER_IMPLICIT)
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tLength = 1;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int    off = block.length - messageLength - salt.length - hLen - tLength - 1;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        block[off] = 0x01;
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(mBuf, 0, block, off + 1, messageLength);
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(salt, 0, block, off + 1 + messageLength, salt.length);
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] dbMask = maskGeneratorFunction1(hash, 0, hash.length, block.length - hLen - tLength);
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != dbMask.length; i++)
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[i] ^= dbMask[i];
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(hash, 0, block, block.length - hLen - tLength, hLen);
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (trailer == TRAILER_IMPLICIT)
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[block.length - 1] = (byte)TRAILER_IMPLICIT;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[block.length - 2] = (byte)(trailer >>> 8);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[block.length - 1] = (byte)trailer;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        block[0] &= 0x7f;
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  b = cipher.processBlock(block, 0, block.length);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearBlock(mBuf);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearBlock(block);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        messageLength = 0;
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return b;
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return true if the signature represents a ISO9796-2 signature
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for the passed in message.
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean verifySignature(
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]      signature)
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]      block = null;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block = cipher.processBlock(signature, 0, signature.length);
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catch (Exception e)
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // adjust block size for leading zeroes if necessary
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (block.length < (keyBits + 7) / 8)
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byte[] tmp = new byte[(keyBits + 7) / 8];
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(block, 0, tmp, tmp.length - block.length, block.length);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block = tmp;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     tLength = 0;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tLength = 1;
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (sigTrail)
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // BEGIN android-removed
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // case TRAILER_RIPEMD160:
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         if (!(digest instanceof RIPEMD160Digest))
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         {
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //             throw new IllegalStateException("signer should be initialised with RIPEMD160");
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         }
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         break;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // END android-removed
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case TRAILER_SHA1:
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!(digest instanceof SHA1Digest))
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    {
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new IllegalStateException("signer should be initialised with SHA1");
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // BEGIN android-removed
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // case TRAILER_RIPEMD128:
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         if (!(digest instanceof RIPEMD128Digest))
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         {
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //             throw new IllegalStateException("signer should be initialised with RIPEMD128");
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //        break;
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // END android-removed
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("unrecognised hash in signature");
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tLength = 2;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // calculate H(m2)
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]    m2Hash = new byte[hLen];
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.doFinal(m2Hash, 0);
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // remove the mask
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - tLength, hLen, block.length - hLen - tLength);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != dbMask.length; i++)
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            block[i] ^= dbMask[i];
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        block[0] &= 0x7f;
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // find out how much padding we've got
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mStart = 0;
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (mStart = 0; mStart != block.length; mStart++)
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (block[mStart] == 0x01)
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mStart++;
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mStart >= block.length)
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clearBlock(block);
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mStart > 1)
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fullMessage = true;
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fullMessage = false;
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        recoveredMessage = new byte[dbMask.length - mStart - saltLength];
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // check the hashes
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  C = new byte[8];
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LtoOSP(recoveredMessage.length * 8, C);
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(C, 0, C.length);
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (recoveredMessage.length != 0)
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(recoveredMessage, 0, recoveredMessage.length);
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(m2Hash, 0, m2Hash.length);
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  hash = new byte[digest.getDigestSize()];
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.update(block, mStart + recoveredMessage.length, dbMask.length - mStart - recoveredMessage.length);
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.doFinal(hash, 0);
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int off = block.length - tLength - hash.length;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != hash.length; i++)
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (hash[i] != block[off + i])
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clearBlock(block);
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clearBlock(hash);
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clearBlock(recoveredMessage);
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fullMessage = false;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // if they've input a message check what we've recovered against
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // what was input.
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (messageLength != 0)
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!isSameAs(mBuf, recoveredMessage))
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clearBlock(mBuf);
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clearBlock(block);
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearBlock(mBuf);
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearBlock(block);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        messageLength = 0;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return true if the full message was recoveredMessage.
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true on full message recovery, false otherwise, or if not sure.
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see org.bouncycastle.crypto.SignerWithRecovery#hasFullMessage()
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasFullMessage()
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return fullMessage;
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return a reference to the recoveredMessage message.
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the full/partial recoveredMessage message.
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see org.bouncycastle.crypto.SignerWithRecovery#getRecoveredMessage()
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] getRecoveredMessage()
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return recoveredMessage;
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * int to octet string.
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void ItoOSP(
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     i,
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  sp)
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[0] = (byte)(i >>> 24);
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[1] = (byte)(i >>> 16);
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[2] = (byte)(i >>> 8);
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[3] = (byte)(i >>> 0);
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * long to octet string.
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void LtoOSP(
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long    l,
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  sp)
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[0] = (byte)(l >>> 56);
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[1] = (byte)(l >>> 48);
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[2] = (byte)(l >>> 40);
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[3] = (byte)(l >>> 32);
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[4] = (byte)(l >>> 24);
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[5] = (byte)(l >>> 16);
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[6] = (byte)(l >>> 8);
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sp[7] = (byte)(l >>> 0);
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mask generator function, as described in PKCS1v2.
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] maskGeneratorFunction1(
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  Z,
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     zOff,
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     zLen,
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     length)
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  mask = new byte[length];
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  hashBuf = new byte[hLen];
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  C = new byte[4];
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int     counter = 0;
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        digest.reset();
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (counter < (length / hLen))
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ItoOSP(counter, C);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(Z, zOff, zLen);
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(C, 0, C.length);
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.doFinal(hashBuf, 0);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            counter++;
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((counter * hLen) < length)
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ItoOSP(counter, C);
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(Z, zOff, zLen);
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.update(C, 0, C.length);
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            digest.doFinal(hashBuf, 0);
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return mask;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
612