]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add ossl_num_bits(), which returns the significant number of bits in a size_t
authorRichard Levitte <levitte@openssl.org>
Mon, 24 Nov 2025 13:26:42 +0000 (14:26 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 11 Dec 2025 09:35:46 +0000 (10:35 +0100)
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 <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/29203)

crypto/asn1/x_long.c
crypto/build.info
crypto/int.c [new file with mode: 0644]
include/crypto/cryptlib.h

index 4dc9dc6c6bd0c40c21e73970a750b8056858a049..19f44f7b6815af5e237e12af097dd8ad10b1618e 100644 (file)
@@ -8,8 +8,8 @@
  */
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
+#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;
index ef31eb8486ca65b638dbe852d5ffc71a915204bc..9b0b46e6e0986ef216033a1f81dd996a5037e4ad 100644 (file)
@@ -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 (file)
index 0000000..f782c2a
--- /dev/null
@@ -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;
+}
index 242de6fc2f2fff0f00ebb2e5cfb2eb25d874cb1f..823cbbcf2c087439cc2c405fa686d7ba52fbcca0 100644 (file)
@@ -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 */