11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include <assert.h> 111cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 121cb0ef41Sopenharmony_ci#include "bn_local.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciint BN_lshift1(BIGNUM *r, const BIGNUM *a) 151cb0ef41Sopenharmony_ci{ 161cb0ef41Sopenharmony_ci register BN_ULONG *ap, *rp, t, c; 171cb0ef41Sopenharmony_ci int i; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci bn_check_top(r); 201cb0ef41Sopenharmony_ci bn_check_top(a); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci if (r != a) { 231cb0ef41Sopenharmony_ci r->neg = a->neg; 241cb0ef41Sopenharmony_ci if (bn_wexpand(r, a->top + 1) == NULL) 251cb0ef41Sopenharmony_ci return 0; 261cb0ef41Sopenharmony_ci r->top = a->top; 271cb0ef41Sopenharmony_ci } else { 281cb0ef41Sopenharmony_ci if (bn_wexpand(r, a->top + 1) == NULL) 291cb0ef41Sopenharmony_ci return 0; 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci ap = a->d; 321cb0ef41Sopenharmony_ci rp = r->d; 331cb0ef41Sopenharmony_ci c = 0; 341cb0ef41Sopenharmony_ci for (i = 0; i < a->top; i++) { 351cb0ef41Sopenharmony_ci t = *(ap++); 361cb0ef41Sopenharmony_ci *(rp++) = ((t << 1) | c) & BN_MASK2; 371cb0ef41Sopenharmony_ci c = t >> (BN_BITS2 - 1); 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci *rp = c; 401cb0ef41Sopenharmony_ci r->top += c; 411cb0ef41Sopenharmony_ci bn_check_top(r); 421cb0ef41Sopenharmony_ci return 1; 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciint BN_rshift1(BIGNUM *r, const BIGNUM *a) 461cb0ef41Sopenharmony_ci{ 471cb0ef41Sopenharmony_ci BN_ULONG *ap, *rp, t, c; 481cb0ef41Sopenharmony_ci int i; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci bn_check_top(r); 511cb0ef41Sopenharmony_ci bn_check_top(a); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci if (BN_is_zero(a)) { 541cb0ef41Sopenharmony_ci BN_zero(r); 551cb0ef41Sopenharmony_ci return 1; 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci i = a->top; 581cb0ef41Sopenharmony_ci ap = a->d; 591cb0ef41Sopenharmony_ci if (a != r) { 601cb0ef41Sopenharmony_ci if (bn_wexpand(r, i) == NULL) 611cb0ef41Sopenharmony_ci return 0; 621cb0ef41Sopenharmony_ci r->neg = a->neg; 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci rp = r->d; 651cb0ef41Sopenharmony_ci r->top = i; 661cb0ef41Sopenharmony_ci t = ap[--i]; 671cb0ef41Sopenharmony_ci rp[i] = t >> 1; 681cb0ef41Sopenharmony_ci c = t << (BN_BITS2 - 1); 691cb0ef41Sopenharmony_ci r->top -= (t == 1); 701cb0ef41Sopenharmony_ci while (i > 0) { 711cb0ef41Sopenharmony_ci t = ap[--i]; 721cb0ef41Sopenharmony_ci rp[i] = ((t >> 1) & BN_MASK2) | c; 731cb0ef41Sopenharmony_ci c = t << (BN_BITS2 - 1); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci if (!r->top) 761cb0ef41Sopenharmony_ci r->neg = 0; /* don't allow negative zero */ 771cb0ef41Sopenharmony_ci bn_check_top(r); 781cb0ef41Sopenharmony_ci return 1; 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ciint BN_lshift(BIGNUM *r, const BIGNUM *a, int n) 821cb0ef41Sopenharmony_ci{ 831cb0ef41Sopenharmony_ci int ret; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci if (n < 0) { 861cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT); 871cb0ef41Sopenharmony_ci return 0; 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci ret = bn_lshift_fixed_top(r, a, n); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci bn_correct_top(r); 931cb0ef41Sopenharmony_ci bn_check_top(r); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci return ret; 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci/* 991cb0ef41Sopenharmony_ci * In respect to shift factor the execution time is invariant of 1001cb0ef41Sopenharmony_ci * |n % BN_BITS2|, but not |n / BN_BITS2|. Or in other words pre-condition 1011cb0ef41Sopenharmony_ci * for constant-time-ness is |n < BN_BITS2| or |n / BN_BITS2| being 1021cb0ef41Sopenharmony_ci * non-secret. 1031cb0ef41Sopenharmony_ci */ 1041cb0ef41Sopenharmony_ciint bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) 1051cb0ef41Sopenharmony_ci{ 1061cb0ef41Sopenharmony_ci int i, nw; 1071cb0ef41Sopenharmony_ci unsigned int lb, rb; 1081cb0ef41Sopenharmony_ci BN_ULONG *t, *f; 1091cb0ef41Sopenharmony_ci BN_ULONG l, m, rmask = 0; 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci assert(n >= 0); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci bn_check_top(r); 1141cb0ef41Sopenharmony_ci bn_check_top(a); 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci nw = n / BN_BITS2; 1171cb0ef41Sopenharmony_ci if (bn_wexpand(r, a->top + nw + 1) == NULL) 1181cb0ef41Sopenharmony_ci return 0; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci if (a->top != 0) { 1211cb0ef41Sopenharmony_ci lb = (unsigned int)n % BN_BITS2; 1221cb0ef41Sopenharmony_ci rb = BN_BITS2 - lb; 1231cb0ef41Sopenharmony_ci rb %= BN_BITS2; /* say no to undefined behaviour */ 1241cb0ef41Sopenharmony_ci rmask = (BN_ULONG)0 - rb; /* rmask = 0 - (rb != 0) */ 1251cb0ef41Sopenharmony_ci rmask |= rmask >> 8; 1261cb0ef41Sopenharmony_ci f = &(a->d[0]); 1271cb0ef41Sopenharmony_ci t = &(r->d[nw]); 1281cb0ef41Sopenharmony_ci l = f[a->top - 1]; 1291cb0ef41Sopenharmony_ci t[a->top] = (l >> rb) & rmask; 1301cb0ef41Sopenharmony_ci for (i = a->top - 1; i > 0; i--) { 1311cb0ef41Sopenharmony_ci m = l << lb; 1321cb0ef41Sopenharmony_ci l = f[i - 1]; 1331cb0ef41Sopenharmony_ci t[i] = (m | ((l >> rb) & rmask)) & BN_MASK2; 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci t[0] = (l << lb) & BN_MASK2; 1361cb0ef41Sopenharmony_ci } else { 1371cb0ef41Sopenharmony_ci /* shouldn't happen, but formally required */ 1381cb0ef41Sopenharmony_ci r->d[nw] = 0; 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci if (nw != 0) 1411cb0ef41Sopenharmony_ci memset(r->d, 0, sizeof(*t) * nw); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci r->neg = a->neg; 1441cb0ef41Sopenharmony_ci r->top = a->top + nw + 1; 1451cb0ef41Sopenharmony_ci r->flags |= BN_FLG_FIXED_TOP; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci return 1; 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ciint BN_rshift(BIGNUM *r, const BIGNUM *a, int n) 1511cb0ef41Sopenharmony_ci{ 1521cb0ef41Sopenharmony_ci int ret = 0; 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci if (n < 0) { 1551cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT); 1561cb0ef41Sopenharmony_ci return 0; 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci ret = bn_rshift_fixed_top(r, a, n); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci bn_correct_top(r); 1621cb0ef41Sopenharmony_ci bn_check_top(r); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci return ret; 1651cb0ef41Sopenharmony_ci} 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci/* 1681cb0ef41Sopenharmony_ci * In respect to shift factor the execution time is invariant of 1691cb0ef41Sopenharmony_ci * |n % BN_BITS2|, but not |n / BN_BITS2|. Or in other words pre-condition 1701cb0ef41Sopenharmony_ci * for constant-time-ness for sufficiently[!] zero-padded inputs is 1711cb0ef41Sopenharmony_ci * |n < BN_BITS2| or |n / BN_BITS2| being non-secret. 1721cb0ef41Sopenharmony_ci */ 1731cb0ef41Sopenharmony_ciint bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) 1741cb0ef41Sopenharmony_ci{ 1751cb0ef41Sopenharmony_ci int i, top, nw; 1761cb0ef41Sopenharmony_ci unsigned int lb, rb; 1771cb0ef41Sopenharmony_ci BN_ULONG *t, *f; 1781cb0ef41Sopenharmony_ci BN_ULONG l, m, mask; 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci bn_check_top(r); 1811cb0ef41Sopenharmony_ci bn_check_top(a); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci assert(n >= 0); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci nw = n / BN_BITS2; 1861cb0ef41Sopenharmony_ci if (nw >= a->top) { 1871cb0ef41Sopenharmony_ci /* shouldn't happen, but formally required */ 1881cb0ef41Sopenharmony_ci BN_zero(r); 1891cb0ef41Sopenharmony_ci return 1; 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci rb = (unsigned int)n % BN_BITS2; 1931cb0ef41Sopenharmony_ci lb = BN_BITS2 - rb; 1941cb0ef41Sopenharmony_ci lb %= BN_BITS2; /* say no to undefined behaviour */ 1951cb0ef41Sopenharmony_ci mask = (BN_ULONG)0 - lb; /* mask = 0 - (lb != 0) */ 1961cb0ef41Sopenharmony_ci mask |= mask >> 8; 1971cb0ef41Sopenharmony_ci top = a->top - nw; 1981cb0ef41Sopenharmony_ci if (r != a && bn_wexpand(r, top) == NULL) 1991cb0ef41Sopenharmony_ci return 0; 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci t = &(r->d[0]); 2021cb0ef41Sopenharmony_ci f = &(a->d[nw]); 2031cb0ef41Sopenharmony_ci l = f[0]; 2041cb0ef41Sopenharmony_ci for (i = 0; i < top - 1; i++) { 2051cb0ef41Sopenharmony_ci m = f[i + 1]; 2061cb0ef41Sopenharmony_ci t[i] = (l >> rb) | ((m << lb) & mask); 2071cb0ef41Sopenharmony_ci l = m; 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci t[i] = l >> rb; 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci r->neg = a->neg; 2121cb0ef41Sopenharmony_ci r->top = top; 2131cb0ef41Sopenharmony_ci r->flags |= BN_FLG_FIXED_TOP; 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci return 1; 2161cb0ef41Sopenharmony_ci} 217