From: Richard Levitte Date: Wed, 22 Oct 2025 13:50:41 +0000 (+0200) Subject: OSSL_FN: Add internal construction and introspection functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd0a17c522936d24baff7d902ad36476a3a212ef;p=thirdparty%2Fopenssl.git OSSL_FN: Add internal construction and introspection functions These functions will be useful with other test programs without having to include crypto/fn/fn_local.h, making them closer to real world use. This also introduces OSSL_FN errors Related-to: doc/designs/fixed-size-large-numbers.md Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/29028) --- diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index be3d91280ae..6955d7d22bf 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -13,6 +13,7 @@ #include "crypto/cryptoerr.h" #include "crypto/asn1err.h" #include "crypto/bnerr.h" +#include "crypto/fnerr.h" #include "crypto/ecerr.h" #include "crypto/buffererr.h" #include "crypto/bioerr.h" @@ -50,6 +51,7 @@ int ossl_err_load_crypto_strings(void) #ifndef OPENSSL_NO_ERR || ossl_err_load_ERR_strings() == 0 /* include error strings for SYSerr */ || ossl_err_load_BN_strings() == 0 + || ossl_err_load_OSSL_FN_strings() == 0 || ossl_err_load_RSA_strings() == 0 #ifndef OPENSSL_NO_DH || ossl_err_load_DH_strings() == 0 diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index a3fce495489..db4e40fe1a1 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -43,6 +43,7 @@ L PROV include/openssl/proverr.h providers/common/provider_err.c L OSSL_ENCODER include/openssl/encodererr.h crypto/encode_decode/encoder_err.c include/crypto/encodererr.h L OSSL_DECODER include/openssl/decodererr.h crypto/encode_decode/decoder_err.c include/crypto/decodererr.h L HTTP include/openssl/httperr.h crypto/http/http_err.c include/crypto/httperr.h +L OSSL_FN NONE crypto/fn/fn_err.c include/crypto/fnerr.h # SSL/TLS alerts R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 70e06a6a38a..4acda0f0a5d 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -884,6 +884,7 @@ OSSL_DECODER_R_MISSING_GET_PARAMS:100:missing get params OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query OSSL_ENCODER_R_MISSING_GET_PARAMS:102:missing get params +OSSL_FN_R_RESULT_ARG_TOO_SMALL:100:result arg too small OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac diff --git a/crypto/fn/build.info b/crypto/fn/build.info index 218e4b01e5c..694acce2e4d 100644 --- a/crypto/fn/build.info +++ b/crypto/fn/build.info @@ -2,7 +2,7 @@ $LIBCRYPTO=../../libcrypto $LIBFIPS=../../providers/libfips.a LIBS=$LIBCRYPTO -$COMMON=fn_lib.c +$COMMON=fn_err.c fn_lib.c fn_intern.c SOURCE[$LIBCRYPTO]=$COMMON SOURCE[$LIBFIPS]=$COMMON diff --git a/crypto/fn/fn_err.c b/crypto/fn/fn_err.c new file mode 100644 index 00000000000..bf6c1478204 --- /dev/null +++ b/crypto/fn/fn_err.c @@ -0,0 +1,31 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-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 +#include "crypto/fnerr.h" + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OSSL_FN_str_reasons[] = { + { ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_RESULT_ARG_TOO_SMALL), + "result arg too small" }, + { 0, NULL } +}; + +#endif + +int ossl_err_load_OSSL_FN_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_reason_error_string(OSSL_FN_str_reasons[0].error) == NULL) + ERR_load_strings_const(OSSL_FN_str_reasons); +#endif + return 1; +} diff --git a/crypto/fn/fn_intern.c b/crypto/fn/fn_intern.c new file mode 100644 index 00000000000..3aa3afb3f1b --- /dev/null +++ b/crypto/fn/fn_intern.c @@ -0,0 +1,56 @@ +/* + * 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 "internal/cryptlib.h" +#include "crypto/fn_intern.h" +#include "crypto/fnerr.h" +#include "fn_local.h" +#include + +int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs) +{ + if (ossl_unlikely(f == NULL)) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if ((size_t)f->dsize < limbs) { + ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL); + return 0; + } + + memcpy(f->d, words, sizeof(OSSL_FN_ULONG) * limbs); + memset(f->d + limbs, 0, sizeof(OSSL_FN_ULONG) * (f->dsize - limbs)); + return 1; +} + +const OSSL_FN_ULONG *ossl_fn_get_words(OSSL_FN *f) +{ + if (ossl_unlikely(f == NULL)) { + ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + return f->d; +} + +size_t ossl_fn_get_dsize(OSSL_FN *f) +{ + return f->dsize; +} + +bool ossl_fn_is_dynamically_allocated(OSSL_FN *f) +{ + return f->is_dynamically_allocated; +} + +bool ossl_fn_is_securely_allocated(OSSL_FN *f) +{ + return f->is_securely_allocated; +} diff --git a/crypto/fn/fn_local.h b/crypto/fn/fn_local.h index 46b3e82b269..c30ab723044 100644 --- a/crypto/fn/fn_local.h +++ b/crypto/fn/fn_local.h @@ -15,6 +15,19 @@ #include #include "internal/common.h" #include "crypto/fn.h" +#include "crypto/fn_intern.h" + +#if OSSL_FN_BYTES == 4 +/* 32-bit systems */ +#define OSSL_FN_MASK UINT32_MAX +#elif OSSL_FN_BYTES == 8 +/* 64-bit systems */ +#define OSSL_FN_MASK UINT64_MAX +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +#define OSSL_FN_HIGH_BIT_MASK (OSSL_FN_ULONG_C(1) << (OSSL_FN_BYTES * 8 - 1)) struct ossl_fn_st { /* Flag: alloced with OSSL_FN_new() or OSSL_FN_secure_new() */ diff --git a/include/crypto/fn_intern.h b/include/crypto/fn_intern.h new file mode 100644 index 00000000000..df35a0a5dc3 --- /dev/null +++ b/include/crypto/fn_intern.h @@ -0,0 +1,53 @@ +/* + * 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 + */ + +/** + * @file A set of internal functions to manipulate the OSSL_FN d array, and + * for introspection. + */ + +#ifndef OPENSSL_FN_INTERN_H +#define OPENSSL_FN_INTERN_H +#pragma once + +#include +#include "crypto/fn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if OSSL_FN_BYTES == 4 +/* 32-bit systems */ +#define OSSL_FN_ULONG_C(n) UINT32_C(n) +#define OSSL_FN_ULONG64_C(hi32, lo32) OSSL_FN_ULONG_C(lo32), OSSL_FN_ULONG_C(hi32) +#elif OSSL_FN_BYTES == 8 +/* 64-bit systems */ +#define OSSL_FN_ULONG_C(n) UINT64_C(n) +#define OSSL_FN_ULONG64_C(hi32, lo32) (OSSL_FN_ULONG_C(hi32) << 32 | OSSL_FN_ULONG_C(lo32)) +#else +#error "OpenSSL doesn't support large numbers on this platform" +#endif + +int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs); +const OSSL_FN_ULONG *ossl_fn_get_words(OSSL_FN *f); + +size_t ossl_fn_get_dsize(OSSL_FN *f); + +void ossl_fn_set_negative(OSSL_FN *f, bool neg); + +bool ossl_fn_is_negative(OSSL_FN *f); +bool ossl_fn_is_dynamically_allocated(OSSL_FN *f); +bool ossl_fn_is_securely_allocated(OSSL_FN *f); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crypto/fnerr.h b/include/crypto/fnerr.h new file mode 100644 index 00000000000..c3aeb326715 --- /dev/null +++ b/include/crypto/fnerr.h @@ -0,0 +1,32 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 2020-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 + */ + +#ifndef OSSL_CRYPTO_FNERR_H +#define OSSL_CRYPTO_FNERR_H +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ossl_err_load_OSSL_FN_strings(void); + +/* + * OSSL_FN reason codes. + */ +#define OSSL_FN_R_RESULT_ARG_TOO_SMALL 100 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in index d451f82eca6..e1c076c2259 100644 --- a/include/openssl/err.h.in +++ b/include/openssl/err.h.in @@ -124,6 +124,7 @@ struct err_state_st { #define ERR_LIB_OSSL_ENCODER 59 #define ERR_LIB_OSSL_DECODER 60 #define ERR_LIB_HTTP 61 +#define ERR_LIB_OSSL_FN 62 #define ERR_LIB_USER 128 diff --git a/test/fn_internal_test.c b/test/fn_internal_test.c index fd3f17f0304..b94422bee70 100644 --- a/test/fn_internal_test.c +++ b/test/fn_internal_test.c @@ -15,6 +15,7 @@ */ #include "crypto/fn.h" +#include "crypto/fn_intern.h" #include "fn_local.h" #include "testutil.h" @@ -37,6 +38,7 @@ static int test_alloc(void) { int ret = 1; OSSL_FN *f = NULL; + const OSSL_FN_ULONG *u = NULL; /* * OSSL_FN_new_bits() calls OSSL_FN_new_bytes(), which calls @@ -49,11 +51,12 @@ static int test_alloc(void) * shaving off 17 bits for demonstration purposes. */ if (!TEST_ptr(f = OSSL_FN_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17)) - || !TEST_uint_eq(f->is_dynamically_allocated, 1) - || !TEST_uint_eq(f->is_securely_allocated, 0) - || !TEST_int_eq(f->dsize, 2) - || !TEST_size_t_eq(f->d[0], 0) - || !TEST_size_t_eq(f->d[1], 0)) + || !TEST_true(ossl_fn_is_dynamically_allocated(f)) + || !TEST_false(ossl_fn_is_securely_allocated(f)) + || !TEST_size_t_eq(ossl_fn_get_dsize(f), 2) + || !TEST_ptr(u = ossl_fn_get_words(f)) + || !TEST_size_t_eq(u[0], 0) + || !TEST_size_t_eq(u[1], 0)) ret = 0; OSSL_FN_free(f); @@ -64,6 +67,7 @@ static int test_secure_alloc(void) { int ret = 1; OSSL_FN *f = NULL; + const OSSL_FN_ULONG *u = NULL; /* * OSSL_FN_secure_new_bits() calls OSSL_FN_secure_new_bytes(), which calls @@ -76,11 +80,12 @@ static int test_secure_alloc(void) * shaving off 17 bits for demonstration purposes. */ if (!TEST_ptr(f = OSSL_FN_secure_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17)) - || !TEST_uint_eq(f->is_dynamically_allocated, 1) - || !TEST_uint_eq(f->is_securely_allocated, 1) - || !TEST_int_eq(f->dsize, 2) - || !TEST_size_t_eq(f->d[0], 0) - || !TEST_size_t_eq(f->d[1], 0)) + || !TEST_true(ossl_fn_is_dynamically_allocated(f)) + || !TEST_true(ossl_fn_is_securely_allocated(f)) + || !TEST_size_t_eq(ossl_fn_get_dsize(f), 2) + || !TEST_ptr(u = ossl_fn_get_words(f)) + || !TEST_size_t_eq(u[0], 0) + || !TEST_size_t_eq(u[1], 0)) ret = 0; OSSL_FN_free(f);