/* $OpenBSD: bn_shift.c,v 1.18 2023/01/05 04:51:13 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include #include "bn_local.h" int BN_lshift1(BIGNUM *r, const BIGNUM *a) { BN_ULONG *ap, *rp, t, c; int i; if (r != a) { r->neg = a->neg; if (!bn_wexpand(r, a->top + 1)) return (0); r->top = a->top; } else { if (!bn_wexpand(r, a->top + 1)) return (0); } ap = a->d; rp = r->d; c = 0; for (i = 0; i < a->top; i++) { t= *(ap++); *(rp++) = ((t << 1) | c) & BN_MASK2; c = (t & BN_TBIT) ? 1 : 0; } if (c) { *rp = 1; r->top++; } return (1); } int BN_rshift1(BIGNUM *r, const BIGNUM *a) { BN_ULONG *ap, *rp, t, c; int i, j; if (BN_is_zero(a)) { BN_zero(r); return (1); } i = a->top; ap = a->d; j = i - (ap[i - 1]==1); if (a != r) { if (!bn_wexpand(r, j)) return (0); r->neg = a->neg; } rp = r->d; t = ap[--i]; c = (t & 1) ? BN_TBIT : 0; if (t >>= 1) rp[i] = t; while (i > 0) { t = ap[--i]; rp[i] = ((t >> 1) & BN_MASK2) | c; c = (t & 1) ? BN_TBIT : 0; } r->top = j; return (1); } int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) { int i, nw, lb, rb; BN_ULONG *t, *f; BN_ULONG l; if (n < 0) { BNerror(BN_R_INVALID_LENGTH); return 0; } r->neg = a->neg; nw = n / BN_BITS2; if (!bn_wexpand(r, a->top + nw + 1)) return (0); lb = n % BN_BITS2; rb = BN_BITS2 - lb; f = a->d; t = r->d; t[a->top + nw] = 0; if (lb == 0) for (i = a->top - 1; i >= 0; i--) t[nw + i] = f[i]; else for (i = a->top - 1; i >= 0; i--) { l = f[i]; t[nw + i + 1] |= (l >> rb) & BN_MASK2; t[nw + i] = (l << lb) & BN_MASK2; } memset(t, 0, nw * sizeof(t[0])); /* for (i=0; itop = a->top + nw + 1; bn_correct_top(r); return (1); } int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { size_t count, shift_bits, shift_words; size_t lshift, rshift; ssize_t lstride; BN_ULONG *dst, *src; size_t i; if (n < 0) { BNerror(BN_R_INVALID_LENGTH); return 0; } shift_bits = n; /* * Right bit shift, potentially across word boundaries. * * When shift is not an exact multiple of BN_BITS2, the top bits of * the next word need to be left shifted and combined with the right * shifted bits using bitwise OR. If shift is an exact multiple of * BN_BITS2, the source for the left and right shifts are the same * and the shifts become zero (which is effectively a memmove). */ shift_words = shift_bits / BN_BITS2; rshift = shift_bits % BN_BITS2; lshift = (BN_BITS2 - rshift) % BN_BITS2; lstride = (lshift + rshift) / BN_BITS2; if (a->top <= shift_words) { BN_zero(r); return 1; } count = a->top - shift_words; if (!bn_wexpand(r, count)) return 0; src = a->d + shift_words; dst = r->d; for (i = 1; i < count; i++) { *dst = src[lstride] << lshift | *src >> rshift; src++; dst++; } *dst = *src >> rshift; r->top = count; r->neg = a->neg; bn_correct_top(r); return 1; }