From: Richard Levitte Date: Mon, 24 Nov 2025 13:26:42 +0000 (+0100) Subject: Add ossl_num_bits(), which returns the significant number of bits in a size_t X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=17c679fd808da87e82863466cbd2bb40b3d7ad48;p=thirdparty%2Fopenssl.git Add ossl_num_bits(), which returns the significant number of bits in a size_t This existed as an isolated static function in crypto/asn1/x_long.c, but is really a pretty generic integer function, so it will serve better by being exactly that. Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/29203) --- diff --git a/crypto/asn1/x_long.c b/crypto/asn1/x_long.c index 4dc9dc6c6bd..19f44f7b681 100644 --- a/crypto/asn1/x_long.c +++ b/crypto/asn1/x_long.c @@ -8,8 +8,8 @@ */ #include -#include "internal/cryptlib.h" #include +#include "crypto/cryptlib.h" #define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b)) @@ -56,31 +56,6 @@ static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); } -/* - * Originally BN_num_bits_word was called to perform this operation, but - * trouble is that there is no guarantee that sizeof(long) equals to - * sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide - * as long, but also double or half... - */ -static int num_bits_ulong(unsigned long value) -{ - size_t i; - unsigned long ret = 0; - - /* - * It is argued that *on average* constant counter loop performs - * not worse [if not better] than one with conditional break or - * mask-n-table-lookup-style, because of branch misprediction - * penalties. - */ - for (i = 0; i < sizeof(value) * 8; i++) { - ret += (value != 0); - value >>= 1; - } - - return (int)ret; -} - static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) { @@ -103,7 +78,7 @@ static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, sign = 0; utmp = ltmp; } - clen = num_bits_ulong(utmp); + clen = (int)ossl_num_bits(utmp); /* If MSB of leading octet set we need to pad */ if (!(clen & 0x7)) pad = 1; diff --git a/crypto/build.info b/crypto/build.info index ef31eb8486c..9b0b46e6e09 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -100,7 +100,8 @@ $UTIL_COMMON=\ threads_pthread.c threads_win.c threads_none.c threads_common.c \ initthread.c context.c sparse_array.c asn1_dsa.c packet.c \ param_build.c param_build_set.c der_writer.c threads_lib.c \ - params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c + params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c \ + int.c SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ diff --git a/crypto/int.c b/crypto/int.c new file mode 100644 index 00000000000..f782c2aec63 --- /dev/null +++ b/crypto/int.c @@ -0,0 +1,29 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/cryptlib.h" + +size_t ossl_num_bits(size_t value) +{ + size_t i; + unsigned long ret = 0; + + /* + * It is argued that *on average* constant counter loop performs + * not worse [if not better] than one with conditional break or + * mask-n-table-lookup-style, because of branch misprediction + * penalties. + */ + for (i = 0; i < sizeof(value) * 8; i++) { + ret += (value != 0); + value >>= 1; + } + + return (int)ret; +} diff --git a/include/crypto/cryptlib.h b/include/crypto/cryptlib.h index 242de6fc2f2..823cbbcf2c0 100644 --- a/include/crypto/cryptlib.h +++ b/include/crypto/cryptlib.h @@ -36,4 +36,6 @@ void ossl_malloc_setup_failures(void); int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj, CRYPTO_EX_DATA *ad, int idx); +size_t ossl_num_bits(size_t value); + #endif /* OSSL_CRYPTO_CRYPTLIB_H */