1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* rsa.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2008, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** modification, are permitted provided that the following conditions are met:
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Redistributions of source code must retain the above copyright
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       notice, this list of conditions and the following disclaimer.
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Redistributions in binary form must reproduce the above copyright
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       notice, this list of conditions and the following disclaimer in the
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       documentation and/or other materials provided with the distribution.
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Neither the name of Google Inc. nor the names of its contributors may
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       be used to endorse or promote products derived from this software
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       without specific prior written permission.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mincrypt/rsa.h"
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mincrypt/sha.h"
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* a[] -= mod */
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void subM(const RSAPublicKey *key, uint32_t *a) {
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int64_t A = 0;
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < key->len; ++i) {
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        A += (uint64_t)a[i] - key->n[i];
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        a[i] = (uint32_t)A;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        A >>= 32;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* return a[] >= mod */
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int geM(const RSAPublicKey *key, const uint32_t *a) {
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = key->len; i;) {
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        --i;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (a[i] < key->n[i]) return 0;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (a[i] > key->n[i]) return 1;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;  /* equal */
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* montgomery c[] += a * b[] / R % mod */
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void montMulAdd(const RSAPublicKey *key,
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       uint32_t* c,
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       const uint32_t a,
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       const uint32_t* b) {
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t A = (uint64_t)a * b[0] + c[0];
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t d0 = (uint32_t)A * key->n0inv;
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 1; i < key->len; ++i) {
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        A = (A >> 32) + (uint64_t)a * b[i] + c[i];
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c[i - 1] = (uint32_t)B;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    A = (A >> 32) + (B >> 32);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c[i - 1] = (uint32_t)A;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (A >> 32) {
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        subM(key, c);
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* montgomery c[] = a[] * b[] / R % mod */
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void montMul(const RSAPublicKey *key,
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    uint32_t* c,
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    const uint32_t* a,
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    const uint32_t* b) {
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < key->len; ++i) {
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c[i] = 0;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < key->len; ++i) {
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        montMulAdd(key, c, a[i], b);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* In-place public exponentiation.
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Input and output big-endian byte array in inout.
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void modpow3(const RSAPublicKey *key,
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    uint8_t* inout) {
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t a[RSANUMWORDS];
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t aR[RSANUMWORDS];
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t aaR[RSANUMWORDS];
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t *aaa = aR;  /* Re-use location. */
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Convert from big endian byte array to little endian word array. */
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < key->len; ++i) {
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp =
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (inout[((key->len - 1 - i) * 4) + 0] << 24) |
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (inout[((key->len - 1 - i) * 4) + 1] << 16) |
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (inout[((key->len - 1 - i) * 4) + 2] << 8) |
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (inout[((key->len - 1 - i) * 4) + 3] << 0);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        a[i] = tmp;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    montMul(key, aR, a, key->rr);  /* aR = a * RR / R mod M   */
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    montMul(key, aaR, aR, aR);     /* aaR = aR * aR / R mod M */
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    montMul(key, aaa, aaR, a);     /* aaa = aaR * a / R mod M */
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Make sure aaa < mod; aaa is at most 1x mod too large. */
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (geM(key, aaa)) {
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        subM(key, aaa);
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Convert to bigendian byte array */
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = key->len - 1; i >= 0; --i) {
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp = aaa[i];
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *inout++ = tmp >> 24;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *inout++ = tmp >> 16;
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *inout++ = tmp >> 8;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *inout++ = tmp >> 0;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** other flavor which omits the optional parameter entirely). This code does not
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** accept signatures without the optional parameter.
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const uint8_t padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x04,0x14
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Verify a 2048 bit RSA PKCS1.5 signature against an expected SHA-1 hash.
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Returns 0 on failure, 1 on success.
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint RSA_verify(const RSAPublicKey *key,
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               const uint8_t *signature,
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               const int len,
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               const uint8_t *sha) {
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t buf[RSANUMBYTES];
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (key->len != RSANUMWORDS) {
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;  /* Wrong key passed in. */
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (len != sizeof(buf)) {
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;  /* Wrong input length. */
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < len; ++i) {
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        buf[i] = signature[i];
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    modpow3(key, buf);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Check pkcs1.5 padding bytes. */
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < (int) sizeof(padding); ++i) {
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (buf[i] != padding[i]) {
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* Check sha digest matches. */
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (; i < len; ++i) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (buf[i] != *sha++) {
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
199