1238384Sjkim/* crypto/rsa/rsa_lib.c */
2238384Sjkim/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3238384Sjkim * All rights reserved.
4238384Sjkim *
5238384Sjkim * This package is an SSL implementation written
6238384Sjkim * by Eric Young (eay@cryptsoft.com).
7238384Sjkim * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
9238384Sjkim * This library is free for commercial and non-commercial use as long as
10238384Sjkim * the following conditions are aheared to.  The following conditions
11238384Sjkim * apply to all code found in this distribution, be it the RC4, RSA,
12238384Sjkim * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13238384Sjkim * included with this distribution is covered by the same copyright terms
14238384Sjkim * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
16238384Sjkim * Copyright remains Eric Young's, and as such any Copyright notices in
17238384Sjkim * the code are not to be removed.
18238384Sjkim * If this package is used in a product, Eric Young should be given attribution
19238384Sjkim * as the author of the parts of the library used.
20238384Sjkim * This can be in the form of a textual message at program startup or
21238384Sjkim * in documentation (online or textual) provided with the package.
22296341Sdelphij *
23238384Sjkim * Redistribution and use in source and binary forms, with or without
24238384Sjkim * modification, are permitted provided that the following conditions
25238384Sjkim * are met:
26238384Sjkim * 1. Redistributions of source code must retain the copyright
27238384Sjkim *    notice, this list of conditions and the following disclaimer.
28238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
29238384Sjkim *    notice, this list of conditions and the following disclaimer in the
30238384Sjkim *    documentation and/or other materials provided with the distribution.
31238384Sjkim * 3. All advertising materials mentioning features or use of this software
32238384Sjkim *    must display the following acknowledgement:
33238384Sjkim *    "This product includes cryptographic software written by
34238384Sjkim *     Eric Young (eay@cryptsoft.com)"
35238384Sjkim *    The word 'cryptographic' can be left out if the rouines from the library
36238384Sjkim *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
38238384Sjkim *    the apps directory (application code) you must include an acknowledgement:
39238384Sjkim *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
41238384Sjkim * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42238384Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44238384Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45238384Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46238384Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47238384Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49238384Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50238384Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51238384Sjkim * SUCH DAMAGE.
52296341Sdelphij *
53238384Sjkim * The licence and distribution terms for any publically available version or
54238384Sjkim * derivative of this code cannot be changed.  i.e. this code cannot simply be
55238384Sjkim * copied and put under another distribution licence
56238384Sjkim * [including the GNU Public Licence.]
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include <openssl/crypto.h>
61238384Sjkim#include "cryptlib.h"
62238384Sjkim#include <openssl/lhash.h>
63238384Sjkim#include <openssl/bn.h>
64238384Sjkim#include <openssl/rsa.h>
65238384Sjkim#include <openssl/rand.h>
66238384Sjkim#ifndef OPENSSL_NO_ENGINE
67296341Sdelphij# include <openssl/engine.h>
68238384Sjkim#endif
69238384Sjkim
70238384Sjkimint RSA_size(const RSA *r)
71296341Sdelphij{
72296341Sdelphij    return (BN_num_bytes(r->n));
73296341Sdelphij}
74238384Sjkim
75238384Sjkimint RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
76296341Sdelphij                       RSA *rsa, int padding)
77296341Sdelphij{
78238384Sjkim#ifdef OPENSSL_FIPS
79296341Sdelphij    if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
80296341Sdelphij        && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
81296341Sdelphij        RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_NON_FIPS_RSA_METHOD);
82296341Sdelphij        return -1;
83296341Sdelphij    }
84238384Sjkim#endif
85296341Sdelphij    return (rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding));
86296341Sdelphij}
87238384Sjkim
88296341Sdelphijint RSA_private_encrypt(int flen, const unsigned char *from,
89296341Sdelphij                        unsigned char *to, RSA *rsa, int padding)
90296341Sdelphij{
91238384Sjkim#ifdef OPENSSL_FIPS
92296341Sdelphij    if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
93296341Sdelphij        && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
94296341Sdelphij        RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_NON_FIPS_RSA_METHOD);
95296341Sdelphij        return -1;
96296341Sdelphij    }
97238384Sjkim#endif
98296341Sdelphij    return (rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding));
99296341Sdelphij}
100238384Sjkim
101296341Sdelphijint RSA_private_decrypt(int flen, const unsigned char *from,
102296341Sdelphij                        unsigned char *to, RSA *rsa, int padding)
103296341Sdelphij{
104238384Sjkim#ifdef OPENSSL_FIPS
105296341Sdelphij    if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
106296341Sdelphij        && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
107296341Sdelphij        RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_NON_FIPS_RSA_METHOD);
108296341Sdelphij        return -1;
109296341Sdelphij    }
110238384Sjkim#endif
111296341Sdelphij    return (rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding));
112296341Sdelphij}
113238384Sjkim
114238384Sjkimint RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
115296341Sdelphij                       RSA *rsa, int padding)
116296341Sdelphij{
117238384Sjkim#ifdef OPENSSL_FIPS
118296341Sdelphij    if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
119296341Sdelphij        && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
120296341Sdelphij        RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_NON_FIPS_RSA_METHOD);
121296341Sdelphij        return -1;
122296341Sdelphij    }
123238384Sjkim#endif
124296341Sdelphij    return (rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding));
125296341Sdelphij}
126238384Sjkim
127238384Sjkimint RSA_flags(const RSA *r)
128296341Sdelphij{
129296341Sdelphij    return ((r == NULL) ? 0 : r->meth->flags);
130296341Sdelphij}
131238384Sjkim
132238384Sjkimvoid RSA_blinding_off(RSA *rsa)
133296341Sdelphij{
134296341Sdelphij    if (rsa->blinding != NULL) {
135296341Sdelphij        BN_BLINDING_free(rsa->blinding);
136296341Sdelphij        rsa->blinding = NULL;
137296341Sdelphij    }
138296341Sdelphij    rsa->flags &= ~RSA_FLAG_BLINDING;
139296341Sdelphij    rsa->flags |= RSA_FLAG_NO_BLINDING;
140296341Sdelphij}
141238384Sjkim
142238384Sjkimint RSA_blinding_on(RSA *rsa, BN_CTX *ctx)
143296341Sdelphij{
144296341Sdelphij    int ret = 0;
145238384Sjkim
146296341Sdelphij    if (rsa->blinding != NULL)
147296341Sdelphij        RSA_blinding_off(rsa);
148238384Sjkim
149296341Sdelphij    rsa->blinding = RSA_setup_blinding(rsa, ctx);
150296341Sdelphij    if (rsa->blinding == NULL)
151296341Sdelphij        goto err;
152238384Sjkim
153296341Sdelphij    rsa->flags |= RSA_FLAG_BLINDING;
154296341Sdelphij    rsa->flags &= ~RSA_FLAG_NO_BLINDING;
155296341Sdelphij    ret = 1;
156296341Sdelphij err:
157296341Sdelphij    return (ret);
158296341Sdelphij}
159238384Sjkim
160238384Sjkimstatic BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
161296341Sdelphij                                  const BIGNUM *q, BN_CTX *ctx)
162238384Sjkim{
163296341Sdelphij    BIGNUM *ret = NULL, *r0, *r1, *r2;
164238384Sjkim
165296341Sdelphij    if (d == NULL || p == NULL || q == NULL)
166296341Sdelphij        return NULL;
167238384Sjkim
168296341Sdelphij    BN_CTX_start(ctx);
169296341Sdelphij    r0 = BN_CTX_get(ctx);
170296341Sdelphij    r1 = BN_CTX_get(ctx);
171296341Sdelphij    r2 = BN_CTX_get(ctx);
172296341Sdelphij    if (r2 == NULL)
173296341Sdelphij        goto err;
174238384Sjkim
175296341Sdelphij    if (!BN_sub(r1, p, BN_value_one()))
176296341Sdelphij        goto err;
177296341Sdelphij    if (!BN_sub(r2, q, BN_value_one()))
178296341Sdelphij        goto err;
179296341Sdelphij    if (!BN_mul(r0, r1, r2, ctx))
180296341Sdelphij        goto err;
181238384Sjkim
182296341Sdelphij    ret = BN_mod_inverse(NULL, d, r0, ctx);
183296341Sdelphij err:
184296341Sdelphij    BN_CTX_end(ctx);
185296341Sdelphij    return ret;
186238384Sjkim}
187238384Sjkim
188238384SjkimBN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
189238384Sjkim{
190296341Sdelphij    BIGNUM local_n;
191296341Sdelphij    BIGNUM *e, *n;
192296341Sdelphij    BN_CTX *ctx;
193296341Sdelphij    BN_BLINDING *ret = NULL;
194238384Sjkim
195296341Sdelphij    if (in_ctx == NULL) {
196296341Sdelphij        if ((ctx = BN_CTX_new()) == NULL)
197296341Sdelphij            return 0;
198296341Sdelphij    } else
199296341Sdelphij        ctx = in_ctx;
200238384Sjkim
201296341Sdelphij    BN_CTX_start(ctx);
202296341Sdelphij    e = BN_CTX_get(ctx);
203296341Sdelphij    if (e == NULL) {
204296341Sdelphij        RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
205296341Sdelphij        goto err;
206296341Sdelphij    }
207238384Sjkim
208296341Sdelphij    if (rsa->e == NULL) {
209296341Sdelphij        e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
210296341Sdelphij        if (e == NULL) {
211296341Sdelphij            RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
212296341Sdelphij            goto err;
213296341Sdelphij        }
214296341Sdelphij    } else
215296341Sdelphij        e = rsa->e;
216238384Sjkim
217296341Sdelphij    if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) {
218296341Sdelphij        /*
219296341Sdelphij         * if PRNG is not properly seeded, resort to secret exponent as
220296341Sdelphij         * unpredictable seed
221296341Sdelphij         */
222296341Sdelphij        RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0);
223296341Sdelphij    }
224238384Sjkim
225296341Sdelphij    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
226296341Sdelphij        /* Set BN_FLG_CONSTTIME flag */
227296341Sdelphij        n = &local_n;
228296341Sdelphij        BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
229296341Sdelphij    } else
230296341Sdelphij        n = rsa->n;
231238384Sjkim
232296341Sdelphij    ret = BN_BLINDING_create_param(NULL, e, n, ctx,
233296341Sdelphij                                   rsa->meth->bn_mod_exp, rsa->_method_mod_n);
234296341Sdelphij    if (ret == NULL) {
235296341Sdelphij        RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
236296341Sdelphij        goto err;
237296341Sdelphij    }
238296341Sdelphij    CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
239296341Sdelphij err:
240296341Sdelphij    BN_CTX_end(ctx);
241296341Sdelphij    if (in_ctx == NULL)
242296341Sdelphij        BN_CTX_free(ctx);
243296341Sdelphij    if (rsa->e == NULL)
244296341Sdelphij        BN_free(e);
245238384Sjkim
246296341Sdelphij    return ret;
247238384Sjkim}
248