Path: blob/main/contrib/bearssl/src/rsa/rsa_i15_priv.c
39483 views
/*1* Copyright (c) 2017 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))27#define TLEN (8 * U)2829/* see bearssl_rsa.h */30uint32_t31br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)32{33const unsigned char *p, *q;34size_t plen, qlen;35size_t fwlen;36uint16_t p0i, q0i;37size_t xlen, u;38uint16_t tmp[1 + TLEN];39long z;40uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;41uint32_t r;4243/*44* Compute the actual lengths of p and q, in bytes.45* These lengths are not considered secret (we cannot really hide46* them anyway in constant-time code).47*/48p = sk->p;49plen = sk->plen;50while (plen > 0 && *p == 0) {51p ++;52plen --;53}54q = sk->q;55qlen = sk->qlen;56while (qlen > 0 && *q == 0) {57q ++;58qlen --;59}6061/*62* Compute the maximum factor length, in words.63*/64z = (long)(plen > qlen ? plen : qlen) << 3;65fwlen = 1;66while (z > 0) {67z -= 15;68fwlen ++;69}70/*71* Round up the word length to an even number.72*/73fwlen += (fwlen & 1);7475/*76* We need to fit at least 6 values in the stack buffer.77*/78if (6 * fwlen > TLEN) {79return 0;80}8182/*83* Compute signature length (in bytes).84*/85xlen = (sk->n_bitlen + 7) >> 3;8687/*88* Ensure 32-bit alignment for value words.89*/90mq = tmp;91if (((uintptr_t)mq & 2) == 0) {92mq ++;93}9495/*96* Decode q.97*/98br_i15_decode(mq, q, qlen);99100/*101* Decode p.102*/103t1 = mq + fwlen;104br_i15_decode(t1, p, plen);105106/*107* Compute the modulus (product of the two factors), to compare108* it with the source value. We use br_i15_mulacc(), since it's109* already used later on.110*/111t2 = mq + 2 * fwlen;112br_i15_zero(t2, mq[0]);113br_i15_mulacc(t2, mq, t1);114115/*116* We encode the modulus into bytes, to perform the comparison117* with bytes. We know that the product length, in bytes, is118* exactly xlen.119* The comparison actually computes the carry when subtracting120* the modulus from the source value; that carry must be 1 for121* a value in the correct range. We keep it in r, which is our122* accumulator for the error code.123*/124t3 = mq + 4 * fwlen;125br_i15_encode(t3, xlen, t2);126u = xlen;127r = 0;128while (u > 0) {129uint32_t wn, wx;130131u --;132wn = ((unsigned char *)t3)[u];133wx = x[u];134r = ((wx - (wn + r)) >> 8) & 1;135}136137/*138* Move the decoded p to another temporary buffer.139*/140mp = mq + 2 * fwlen;141memmove(mp, t1, fwlen * sizeof *t1);142143/*144* Compute s2 = x^dq mod q.145*/146q0i = br_i15_ninv15(mq[1]);147s2 = mq + fwlen;148br_i15_decode_reduce(s2, x, xlen, mq);149r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,150mq + 3 * fwlen, TLEN - 3 * fwlen);151152/*153* Compute s1 = x^dq mod q.154*/155p0i = br_i15_ninv15(mp[1]);156s1 = mq + 3 * fwlen;157br_i15_decode_reduce(s1, x, xlen, mp);158r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,159mq + 4 * fwlen, TLEN - 4 * fwlen);160161/*162* Compute:163* h = (s1 - s2)*(1/q) mod p164* s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is165* unclear about whether p may be lower than q (some existing,166* widely deployed implementations of RSA don't tolerate p < q),167* but we want to support that occurrence, so we need to use the168* reduction function.169*170* Since we use br_i15_decode_reduce() for iq (purportedly, the171* inverse of q modulo p), we also tolerate improperly large172* values for this parameter.173*/174t1 = mq + 4 * fwlen;175t2 = mq + 5 * fwlen;176br_i15_reduce(t2, s2, mp);177br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));178br_i15_to_monty(s1, mp);179br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp);180br_i15_montymul(t2, s1, t1, mp, p0i);181182/*183* h is now in t2. We compute the final result:184* s = s2 + q*h185* All these operations are non-modular.186*187* We need mq, s2 and t2. We use the t3 buffer as destination.188* The buffers mp, s1 and t1 are no longer needed, so we can189* reuse them for t3. Moreover, the first step of the computation190* is to copy s2 into t3, after which s2 is not needed. Right191* now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5.192* Therefore, we have ample room for t3 by simply using s2.193*/194t3 = s2;195br_i15_mulacc(t3, mq, t2);196197/*198* Encode the result. Since we already checked the value of xlen,199* we can just use it right away.200*/201br_i15_encode(x, xlen, t3);202203/*204* The only error conditions remaining at that point are invalid205* values for p and q (even integers).206*/207return p0i & q0i & r;208}209210211