remove OPENSSL_FIPSAPI
[openssl.git] / crypto / rsa / rsa_pk1.c
1 /* crypto/rsa/rsa_pk1.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59
60
61 #include "constant_time_locl.h"
62
63 #include <stdio.h>
64 #include "cryptlib.h"
65 #include <openssl/bn.h>
66 #include <openssl/rsa.h>
67 #include <openssl/rand.h>
68
69 int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
70              const unsigned char *from, int flen)
71         {
72         int j;
73         unsigned char *p;
74
75         if (flen > (tlen-RSA_PKCS1_PADDING_SIZE))
76                 {
77                 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
78                 return(0);
79                 }
80         
81         p=(unsigned char *)to;
82
83         *(p++)=0;
84         *(p++)=1; /* Private Key BT (Block Type) */
85
86         /* pad out with 0xff data */
87         j=tlen-3-flen;
88         memset(p,0xff,j);
89         p+=j;
90         *(p++)='\0';
91         memcpy(p,from,(unsigned int)flen);
92         return(1);
93         }
94
95 int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
96              const unsigned char *from, int flen, int num)
97         {
98         int i,j;
99         const unsigned char *p;
100
101         p=from;
102         if ((num != (flen+1)) || (*(p++) != 01))
103                 {
104                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BLOCK_TYPE_IS_NOT_01);
105                 return(-1);
106                 }
107
108         /* scan over padding data */
109         j=flen-1; /* one for type. */
110         for (i=0; i<j; i++)
111                 {
112                 if (*p != 0xff) /* should decrypt to 0xff */
113                         {
114                         if (*p == 0)
115                                 { p++; break; }
116                         else    {
117                                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BAD_FIXED_HEADER_DECRYPT);
118                                 return(-1);
119                                 }
120                         }
121                 p++;
122                 }
123
124         if (i == j)
125                 {
126                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_NULL_BEFORE_BLOCK_MISSING);
127                 return(-1);
128                 }
129
130         if (i < 8)
131                 {
132                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BAD_PAD_BYTE_COUNT);
133                 return(-1);
134                 }
135         i++; /* Skip over the '\0' */
136         j-=i;
137         if (j > tlen)
138                 {
139                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_DATA_TOO_LARGE);
140                 return(-1);
141                 }
142         memcpy(to,p,(unsigned int)j);
143
144         return(j);
145         }
146
147 int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
148              const unsigned char *from, int flen)
149         {
150         int i,j;
151         unsigned char *p;
152         
153         if (flen > (tlen-11))
154                 {
155                 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
156                 return(0);
157                 }
158         
159         p=(unsigned char *)to;
160
161         *(p++)=0;
162         *(p++)=2; /* Public Key BT (Block Type) */
163
164         /* pad out with non-zero random data */
165         j=tlen-3-flen;
166
167         if (RAND_bytes(p,j) <= 0)
168                 return(0);
169         for (i=0; i<j; i++)
170                 {
171                 if (*p == '\0')
172                         do      {
173                                 if (RAND_bytes(p,1) <= 0)
174                                         return(0);
175                                 } while (*p == '\0');
176                 p++;
177                 }
178
179         *(p++)='\0';
180
181         memcpy(p,from,(unsigned int)flen);
182         return(1);
183         }
184
185 int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
186              const unsigned char *from, int flen, int num)
187         {
188         int i;
189         /* |em| is the encoded message, zero-padded to exactly |num| bytes */
190         unsigned char *em = NULL;
191         unsigned int good, found_zero_byte;
192         int zero_index = 0, msg_index, mlen = -1;
193
194         if (tlen < 0 || flen < 0)
195                 return -1;
196
197         /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
198          * Standard", section 7.2.2. */
199
200         if (flen > num)
201                 goto err;
202
203         if (num < 11)
204                 goto err;
205
206         em = OPENSSL_malloc(num);
207         if (em == NULL)
208                 {
209                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
210                 return -1;
211                 }
212         memset(em, 0, num);
213         /*
214          * Always do this zero-padding copy (even when num == flen) to avoid
215          * leaking that information. The copy still leaks some side-channel
216          * information, but it's impossible to have a fixed  memory access
217          * pattern since we can't read out of the bounds of |from|.
218          *
219          * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
220          */
221         memcpy(em + num - flen, from, flen);
222
223         good = constant_time_is_zero(em[0]);
224         good &= constant_time_eq(em[1], 2);
225
226         found_zero_byte = 0;
227         for (i = 2; i < num; i++)
228                 {
229                 unsigned int equals0 = constant_time_is_zero(em[i]);
230                 zero_index = constant_time_select_int(~found_zero_byte & equals0, i, zero_index);
231                 found_zero_byte |= equals0;
232                 }
233
234         /*
235          * PS must be at least 8 bytes long, and it starts two bytes into |em|.
236          * If we never found a 0-byte, then |zero_index| is 0 and the check
237          * also fails.
238          */
239         good &= constant_time_ge((unsigned int)(zero_index), 2 + 8);
240
241         /* Skip the zero byte. This is incorrect if we never found a zero-byte
242          * but in this case we also do not copy the message out. */
243         msg_index = zero_index + 1;
244         mlen = num - msg_index;
245
246         /* For good measure, do this check in constant time as well; it could
247          * leak something if |tlen| was assuming valid padding. */
248         good &= constant_time_ge((unsigned int)(tlen), (unsigned int)(mlen));
249
250         /*
251          * We can't continue in constant-time because we need to copy the result
252          * and we cannot fake its length. This unavoidably leaks timing
253          * information at the API boundary.
254          * TODO(emilia): this could be addressed at the call site,
255          * see BoringSSL commit 0aa0767340baf925bda4804882aab0cb974b2d26.
256          */
257         if (!good)
258                 {
259                 mlen = -1;
260                 goto err;
261                 }
262
263         memcpy(to, em + msg_index, mlen);
264
265 err:
266         if (em != NULL)
267                 OPENSSL_free(em);
268         if (mlen == -1)
269                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR);
270         return mlen;
271         }