11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 2014-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 "internal/cryptlib.h"
111cb0ef41Sopenharmony_ci#include "bn_local.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci/*
141cb0ef41Sopenharmony_ci * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
151cb0ef41Sopenharmony_ci * This is an array  r[]  of values that are either zero or odd with an
161cb0ef41Sopenharmony_ci * absolute value less than  2^w  satisfying
171cb0ef41Sopenharmony_ci *     scalar = \sum_j r[j]*2^j
181cb0ef41Sopenharmony_ci * where at most one of any  w+1  consecutive digits is non-zero
191cb0ef41Sopenharmony_ci * with the exception that the most significant digit may be only
201cb0ef41Sopenharmony_ci * w-1 zeros away from that next non-zero digit.
211cb0ef41Sopenharmony_ci */
221cb0ef41Sopenharmony_cisigned char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
231cb0ef41Sopenharmony_ci{
241cb0ef41Sopenharmony_ci    int window_val;
251cb0ef41Sopenharmony_ci    signed char *r = NULL;
261cb0ef41Sopenharmony_ci    int sign = 1;
271cb0ef41Sopenharmony_ci    int bit, next_bit, mask;
281cb0ef41Sopenharmony_ci    size_t len = 0, j;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci    if (BN_is_zero(scalar)) {
311cb0ef41Sopenharmony_ci        r = OPENSSL_malloc(1);
321cb0ef41Sopenharmony_ci        if (r == NULL) {
331cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
341cb0ef41Sopenharmony_ci            goto err;
351cb0ef41Sopenharmony_ci        }
361cb0ef41Sopenharmony_ci        r[0] = 0;
371cb0ef41Sopenharmony_ci        *ret_len = 1;
381cb0ef41Sopenharmony_ci        return r;
391cb0ef41Sopenharmony_ci    }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    if (w <= 0 || w > 7) {      /* 'signed char' can represent integers with
421cb0ef41Sopenharmony_ci                                 * absolute values less than 2^7 */
431cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
441cb0ef41Sopenharmony_ci        goto err;
451cb0ef41Sopenharmony_ci    }
461cb0ef41Sopenharmony_ci    bit = 1 << w;               /* at most 128 */
471cb0ef41Sopenharmony_ci    next_bit = bit << 1;        /* at most 256 */
481cb0ef41Sopenharmony_ci    mask = next_bit - 1;        /* at most 255 */
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci    if (BN_is_negative(scalar)) {
511cb0ef41Sopenharmony_ci        sign = -1;
521cb0ef41Sopenharmony_ci    }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    if (scalar->d == NULL || scalar->top == 0) {
551cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
561cb0ef41Sopenharmony_ci        goto err;
571cb0ef41Sopenharmony_ci    }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci    len = BN_num_bits(scalar);
601cb0ef41Sopenharmony_ci    r = OPENSSL_malloc(len + 1); /*
611cb0ef41Sopenharmony_ci                                  * Modified wNAF may be one digit longer than binary representation
621cb0ef41Sopenharmony_ci                                  * (*ret_len will be set to the actual length, i.e. at most
631cb0ef41Sopenharmony_ci                                  * BN_num_bits(scalar) + 1)
641cb0ef41Sopenharmony_ci                                  */
651cb0ef41Sopenharmony_ci    if (r == NULL) {
661cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
671cb0ef41Sopenharmony_ci        goto err;
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci    window_val = scalar->d[0] & mask;
701cb0ef41Sopenharmony_ci    j = 0;
711cb0ef41Sopenharmony_ci    while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len,
721cb0ef41Sopenharmony_ci                                                      * window_val will not
731cb0ef41Sopenharmony_ci                                                      * increase */
741cb0ef41Sopenharmony_ci        int digit = 0;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci        /* 0 <= window_val <= 2^(w+1) */
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci        if (window_val & 1) {
791cb0ef41Sopenharmony_ci            /* 0 < window_val < 2^(w+1) */
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci            if (window_val & bit) {
821cb0ef41Sopenharmony_ci                digit = window_val - next_bit; /* -2^w < digit < 0 */
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci#if 1                           /* modified wNAF */
851cb0ef41Sopenharmony_ci                if (j + w + 1 >= len) {
861cb0ef41Sopenharmony_ci                    /*
871cb0ef41Sopenharmony_ci                     * Special case for generating modified wNAFs:
881cb0ef41Sopenharmony_ci                     * no new bits will be added into window_val,
891cb0ef41Sopenharmony_ci                     * so using a positive digit here will decrease
901cb0ef41Sopenharmony_ci                     * the total length of the representation
911cb0ef41Sopenharmony_ci                     */
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci                    digit = window_val & (mask >> 1); /* 0 < digit < 2^w */
941cb0ef41Sopenharmony_ci                }
951cb0ef41Sopenharmony_ci#endif
961cb0ef41Sopenharmony_ci            } else {
971cb0ef41Sopenharmony_ci                digit = window_val; /* 0 < digit < 2^w */
981cb0ef41Sopenharmony_ci            }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci            if (digit <= -bit || digit >= bit || !(digit & 1)) {
1011cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
1021cb0ef41Sopenharmony_ci                goto err;
1031cb0ef41Sopenharmony_ci            }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci            window_val -= digit;
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci            /*
1081cb0ef41Sopenharmony_ci             * now window_val is 0 or 2^(w+1) in standard wNAF generation;
1091cb0ef41Sopenharmony_ci             * for modified window NAFs, it may also be 2^w
1101cb0ef41Sopenharmony_ci             */
1111cb0ef41Sopenharmony_ci            if (window_val != 0 && window_val != next_bit
1121cb0ef41Sopenharmony_ci                && window_val != bit) {
1131cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
1141cb0ef41Sopenharmony_ci                goto err;
1151cb0ef41Sopenharmony_ci            }
1161cb0ef41Sopenharmony_ci        }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci        r[j++] = sign * digit;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci        window_val >>= 1;
1211cb0ef41Sopenharmony_ci        window_val += bit * BN_is_bit_set(scalar, j + w);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci        if (window_val > next_bit) {
1241cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
1251cb0ef41Sopenharmony_ci            goto err;
1261cb0ef41Sopenharmony_ci        }
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci    if (j > len + 1) {
1301cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
1311cb0ef41Sopenharmony_ci        goto err;
1321cb0ef41Sopenharmony_ci    }
1331cb0ef41Sopenharmony_ci    *ret_len = j;
1341cb0ef41Sopenharmony_ci    return r;
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci err:
1371cb0ef41Sopenharmony_ci    OPENSSL_free(r);
1381cb0ef41Sopenharmony_ci    return NULL;
1391cb0ef41Sopenharmony_ci}
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ciint bn_get_top(const BIGNUM *a)
1421cb0ef41Sopenharmony_ci{
1431cb0ef41Sopenharmony_ci    return a->top;
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ciint bn_get_dmax(const BIGNUM *a)
1471cb0ef41Sopenharmony_ci{
1481cb0ef41Sopenharmony_ci    return a->dmax;
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_civoid bn_set_all_zero(BIGNUM *a)
1521cb0ef41Sopenharmony_ci{
1531cb0ef41Sopenharmony_ci    int i;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci    for (i = a->top; i < a->dmax; i++)
1561cb0ef41Sopenharmony_ci        a->d[i] = 0;
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ciint bn_copy_words(BN_ULONG *out, const BIGNUM *in, int size)
1601cb0ef41Sopenharmony_ci{
1611cb0ef41Sopenharmony_ci    if (in->top > size)
1621cb0ef41Sopenharmony_ci        return 0;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci    memset(out, 0, sizeof(*out) * size);
1651cb0ef41Sopenharmony_ci    if (in->d != NULL)
1661cb0ef41Sopenharmony_ci        memcpy(out, in->d, sizeof(*out) * in->top);
1671cb0ef41Sopenharmony_ci    return 1;
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ciBN_ULONG *bn_get_words(const BIGNUM *a)
1711cb0ef41Sopenharmony_ci{
1721cb0ef41Sopenharmony_ci    return a->d;
1731cb0ef41Sopenharmony_ci}
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_civoid bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size)
1761cb0ef41Sopenharmony_ci{
1771cb0ef41Sopenharmony_ci    /*
1781cb0ef41Sopenharmony_ci     * |const| qualifier omission is compensated by BN_FLG_STATIC_DATA
1791cb0ef41Sopenharmony_ci     * flag, which effectively means "read-only data".
1801cb0ef41Sopenharmony_ci     */
1811cb0ef41Sopenharmony_ci    a->d = (BN_ULONG *)words;
1821cb0ef41Sopenharmony_ci    a->dmax = a->top = size;
1831cb0ef41Sopenharmony_ci    a->neg = 0;
1841cb0ef41Sopenharmony_ci    a->flags |= BN_FLG_STATIC_DATA;
1851cb0ef41Sopenharmony_ci    bn_correct_top(a);
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ciint bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words)
1891cb0ef41Sopenharmony_ci{
1901cb0ef41Sopenharmony_ci    if (bn_wexpand(a, num_words) == NULL) {
1911cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
1921cb0ef41Sopenharmony_ci        return 0;
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci    memcpy(a->d, words, sizeof(BN_ULONG) * num_words);
1961cb0ef41Sopenharmony_ci    a->top = num_words;
1971cb0ef41Sopenharmony_ci    bn_correct_top(a);
1981cb0ef41Sopenharmony_ci    return 1;
1991cb0ef41Sopenharmony_ci}
200