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