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