Crypt-Bear
view release on metacpan or search on metacpan
src/rsa/rsa_i15_privexp.c view on Meta::CPAN
/*
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_rsa.h */
size_t
br_rsa_i15_compute_privexp(void *d,
const br_rsa_private_key *sk, uint32_t e)
{
/*
* We want to invert e modulo phi = (p-1)(q-1). This first
* requires computing phi, which is easy since we have the factors
* p and q in the private key structure.
*
* Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
* We could invert e modulo phi/4 then patch the result to
* modulo phi, but this would involve assembling three modulus-wide
* values (phi/4, 1 and e) and calling moddiv, that requires
* three more temporaries, for a total of six big integers, or
* slightly more than 3 kB of stack space for RSA-4096. This
* exceeds our stack requirements.
*
* Instead, we first use one step of the extended GCD:
*
* - We compute phi = k*e + r (Euclidean division of phi by e).
* If public exponent e is correct, then r != 0 (e must be
* invertible modulo phi). We also have k != 0 since we
* enforce non-ridiculously-small factors.
*
* - We find small u, v such that u*e - v*r = 1 (using a
* binary GCD; we can arrange for u < r and v < e, i.e. all
* values fit on 32 bits).
*
* - Solution is: d = u + v*k
* This last computation is exact: since u < r and v < e,
* the above implies d < r + e*((phi-r)/e) = phi
*/
uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12];
uint16_t *p, *q, *k, *m, *z, *phi;
const unsigned char *pbuf, *qbuf;
size_t plen, qlen, u, len, dlen;
uint32_t r, a, b, u0, v0, u1, v1, he, hr;
int i;
/*
* Check that e is correct.
*/
if (e < 3 || (e & 1) == 0) {
return 0;
}
/*
* Check lengths of p and q, and that they are both odd.
*/
pbuf = sk->p;
plen = sk->plen;
while (plen > 0 && *pbuf == 0) {
pbuf ++;
plen --;
}
if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
|| (pbuf[plen - 1] & 1) != 1)
{
return 0;
}
qbuf = sk->q;
qlen = sk->qlen;
( run in 0.690 second using v1.01-cache-2.11-cpan-5a3173703d6 )