1010
1111#include < string>
1212#include < string_view>
13- #include < cassert >
13+ #include < mutex > // NEW: std::once_flag, std::call_once
1414
1515#include " src/utils/string.h"
1616
17- // NEU: PSA statt mbedtls/sha1.h
17+ // PSA statt mbedtls/sha1.h
1818#include < psa/crypto.h>
1919
2020namespace modsecurity ::Utils {
2121
2222using DigestOp = int (*)(const unsigned char *, size_t , unsigned char []);
2323
24+ // Gemeinsamer, thread-sicherer PSA-Init für alle Digests
25+ namespace detail {
26+ inline bool ensure_psa_init () {
27+ static std::once_flag once;
28+ static psa_status_t init_status = PSA_ERROR_GENERIC_ERROR;
29+
30+ std::call_once (once, []() {
31+ init_status = psa_crypto_init ();
32+ });
33+
34+ return init_status == PSA_SUCCESS;
35+ }
36+ } // namespace detail
37+
2438
2539template <DigestOp digestOp, int DigestSize>
2640class DigestImpl {
2741 public:
2842 static std::string digest (const std::string& input) {
29- return digestHelper (input, [](const auto digest) {
43+ return digestHelper (input, [](std::string_view digest) {
3044 return std::string (digest);
3145 });
3246 }
3347
3448 static void digestReplace (std::string& value) {
35- digestHelper (value, [&value](const auto digest) mutable {
36- value = digest;
49+ digestHelper (value, [&value](std::string_view digest) mutable {
50+ value. assign (digest. data (), digest. size ()) ;
3751 });
3852 }
3953
4054 static std::string hexdigest (const std::string &input) {
41- return digestHelper (input, [](const auto digest) {
55+ return digestHelper (input, [](std::string_view digest) {
4256 return utils::string::string_to_hex (digest);
4357 });
4458 }
4559
4660 private:
4761 template <typename ConvertOp>
48- static auto digestHelper (const std::string &input,
49- ConvertOp convertOp) -> auto {
50- char digest[DigestSize];
62+ static auto digestHelper (const std::string &input, ConvertOp convertOp)
63+ -> decltype(convertOp(std::string_view{})) {
5164
52- const auto ret = (*digestOp)(
53- reinterpret_cast <const unsigned char *>(input.c_str ()),
65+ unsigned char digest[DigestSize];
66+
67+ const int ret = (*digestOp)(
68+ reinterpret_cast <const unsigned char *>(input.data ()),
5469 input.size (),
55- reinterpret_cast < unsigned char *>( digest)
70+ digest
5671 );
57- assert (ret == 0 );
5872
59- return convertOp (std::string_view (digest, DigestSize));
73+ // NEW: kein assert-only; in Release sonst potentiell UB.
74+ if (ret != 0 ) {
75+ return convertOp (std::string_view{}); // leerer Digest signalisiert Fehler
76+ }
77+
78+ return convertOp (std::string_view (
79+ reinterpret_cast <const char *>(digest), DigestSize
80+ ));
6081 }
6182};
6283
63- // NEU: Wrapper, der die PSA-API in die alte Signatur presst.
84+
85+ // PSA-Wrapper mit alter Signatur
6486inline int modsec_psa_sha1 (const unsigned char *input,
6587 size_t ilen,
6688 unsigned char output[20 ])
6789{
68- static bool psa_initialized = false ;
69-
70- if (!psa_initialized) {
71- psa_status_t init_status = psa_crypto_init ();
72- if (init_status != PSA_SUCCESS) {
73- return -1 ;
74- }
75- psa_initialized = true ;
90+ if (!detail::ensure_psa_init ()) {
91+ return -1 ;
7692 }
7793
7894 size_t out_len = 0 ;
@@ -85,17 +101,11 @@ inline int modsec_psa_sha1(const unsigned char *input,
85101 &out_len
86102 );
87103
88- if (status != PSA_SUCCESS || out_len != 20 ) {
89- return -1 ;
90- }
91-
92- return 0 ;
104+ return (status == PSA_SUCCESS && out_len == 20 ) ? 0 : -1 ;
93105}
94106
95- // Statt &mbedtls_sha1 nehmen wir jetzt unseren PSA-Wrapper
96- class Sha1 : public DigestImpl <&modsec_psa_sha1, 20 > {
97- };
107+ class Sha1 : public DigestImpl <&modsec_psa_sha1, 20 > {};
98108
99109} // namespace modsecurity::Utils
100110
101- #endif // SRC_UTILS_SHA1_H_
111+ #endif // SRC_UTILS_SHA1_H_
0 commit comments