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