376 Commits

Author SHA1 Message Date
Julius Pfrommer 6901aedc07 Merge remote-tracking branch 'origin/1.5' into merge_15_master
Port keyless certificate validation into the GDS receiver driver instead
of restoring the removed server implementation. Preserve master's timer
batching, PubSub lifecycle and client HTTP configuration handling.

Adapt Publish cancellation to response tokens and the HEL/fuzz harnesses
to the explicit TCP driver. Keep SKS policy history and custom datatype
ownership intact, including failed replacement configuration cleanup.
Retain TPM error cleanup while enforcing key-handle and nonce lengths.

Validation:
- Full mbedTLS unit-test build with full namespace, GDS, SKS and Query.
- 21 affected suites passed with ASan/UBSan, plus 9 isolated SKS ownership
  and lifecycle checks.
- OpenSSL certificate update, GDS information model and client encryption
  suites passed with sanitizers.
- OPN, MSG and binary-message fuzzers each completed 100 sanitizer runs.
- Both TPM PubSub policy sources passed compilation checks.

The full SKS client suite timed out after multicast UDP sends reported
"No route to host" on this machine; its affected ownership and lifecycle
cases passed separately. No live TPM hardware validation was performed.
2026-10-04 16:49:17 +02:00
Andreas Ebner 918f2cfd4b fix(docs): typos in comments, docs and messages
Fix misspellings found with codespell across headers, sources, examples,
tests and the documentation, including "propably" in the nodeset
compiler docs. Identifiers, companion spec names and generated code are
left untouched.
2026-09-28 16:20:44 +02:00
StalderT e23ad2f4ee feat(plugins): support OpenSSL 4
OpenSSL 4 makes ASN1_STRING opaque, returns const pointers from the X509_NAME, X509_CRL and X509_EXTENSION getters, and deprecates the X509_cmp_*time family and X509_NAME_get_text_by_NID. The plugin no longer built: the ASN1_IA5STRING access is a hard error, and -Werror turns the rest into errors too.

Read ASN1 strings through ASN1_STRING_length and ASN1_STRING_get0_data, keep the getter results const, compare the validity period with ASN1_TIME_cmp_time_t and read the common name through its name entry. The self-signed certificate gets its subject from a fresh X509_NAME instead of editing the one X509_get_subject_name returns, and the CSR duplicates the subjectAltName extension instead of pushing one it does not own. All of this exists since OpenSSL 1.1.1, which the plugin already requires.

Add a CI job that builds OpenSSL 4.0.2 from source like the LibreSSL job does. The runner ships OpenSSL 3, so the job sets OPENSSL_ROOT_DIR to make sure it cannot quietly fall back to the system library.

Refs #8493
2026-09-27 17:40:24 +02:00
Andreas Ebner 44b527efb7 fix(plugins): bound the key handle and nonce copies of the PKCS#11 PubSub policies
The TPM AES-CTR policies copied sizeof(pointer) bytes regardless of the key length,
and setKeys read 8 bytes from the 4-byte key nonce, past the end of the SKS key
buffer. Check the lengths and copy the size of the destination.
2026-09-26 19:17:01 +02:00
Andreas Ebner 45ccdb1fda fix(plugins): release the lock and context on PKCS#11 PubSub setup errors
newContext of the TPM AES-CTR policies leaked the group context on errors, and
the AES128 variant also returned with initLock128_g still held, deadlocking the
next call. Route all error paths through one cleanup.
2026-09-26 19:17:01 +02:00
Andreas Ebner c0be293ee5 fix(plugins): fail closed when a PKCS#11 PubSub encryption fails
On a C_EncryptUpdate/Final error the TPM AES-CTR policies returned GOOD with the
buffer unchanged, so the NetworkMessage was sent in plaintext. Return the error,
also for decryption, and check the allocation before the operation is initialized.
2026-09-26 19:17:01 +02:00
Andreas Ebner c021a5a772 fix(plugins): add the UA_CertificateUtils_getKeySize stub without encryption
certificategroup.h declares it in every configuration, but only the crypto backends defined
it, so a caller failed to link without encryption. Return BadNotSupported like the others.
2026-09-26 13:52:32 +02:00
Bastian Engel 3d36a7ef0e fix(crypto): don't clear the securityPolicy context
The `securityPolicy` context is still in use, so it should not be
cleared. This commit stores changes in intermediate keys and
certificates and on failure clears these instead.
2026-09-25 13:25:54 +02:00
Bastian Engel a3e733cc16 feat(plugins): restrict MAC context digest initialization to initial key setup
Re-initializing the MAC context with the same digest for every message
is unnecessary work. The digest is set once at key import and later
initializations pass NULL.
2026-09-24 16:52:03 +02:00
Andreas Ebner 9cb2a89c35 feat(plugins): implement PubSub-Aes128/256-CTR with OpenSSL and LibreSSL (Part 14 §7.2.4.4.3.2)
Mirrors the mbedTLS policy (Tables 155-157, HMAC-SHA256 over the whole
NetworkMessage). A group context caches the AES and the MAC context. The
MAC is re-keyed per message as OpenSSL 3.0 cannot restart it otherwise.
2026-09-24 16:52:03 +02:00
Andreas Ebner 1c903aa45b fix(plugins): wipe the P_SHA scratch memory in the OpenSSL backend
The P_SHA256/P_SHA1 key derivation left the derived key stream, the
secret, the seed and the A(n) chain in freed heap memory. The SKS
derives every group key this way. Buffer and context are now cleansed.
2026-09-24 16:52:03 +02:00
Julius Pfrommer e01e2310af Merge remote-tracking branch 'origin/1.4' into merge_14_15 2026-09-24 12:31:21 +02:00
Julius Pfrommer 7b3a849f8e Merge remote-tracking branch 'origin/1.3' into 1.4
# Conflicts:
#	plugins/ua_pubsub_udp.c
#	src/pubsub/ua_pubsub_ns0.c
#	tests/server/check_accesscontrol.c
2026-09-23 10:35:30 +02:00
Julius Pfrommer 9a43b33a4b Merge remote-tracking branch 'origin/1.5' into merge_15_master
# Conflicts:
#	plugins/crypto/mbedtls/create_certificate.c
#	plugins/crypto/mbedtls/securitypolicy_aes256sha256rsapss.c
#	plugins/crypto/mbedtls/securitypolicy_common.c
#	src/client/ua_client.c
#	src/pubsub/ua_pubsub_config.c
#	src/pubsub/ua_pubsub_keystorage.c
#	src/pubsub/ua_pubsub_keystorage.h
#	src/pubsub/ua_pubsub_ns0.c
#	src/pubsub/ua_pubsub_ns0_sks.c
#	src/pubsub/ua_pubsub_securitygroup.c
#	src/pubsub/ua_pubsub_writer.c
#	src/pubsub/ua_pubsub_writergroup.c
#	src/server/ua_server_ns0.c
#	src/server/ua_server_ns0_gds.c
#	src/server/ua_server_utils.c
#	src/server/ua_services_session.c
#	src/server/ua_subscription_alarms_conditions.c
#	src/ua_types_encoding_xml.c
#	tests/check_types_builtin_xml.c
#	tests/encryption/check_cert_generation.c
#	tests/pubsub/check_pubsub_configuration.c
#	tests/pubsub/check_pubsub_informationmodel_methods.c
#	tests/pubsub/check_pubsub_publish.c
#	tests/pubsub/check_pubsub_sks_client.c
#	tests/pubsub/check_pubsub_sks_keystorage.c
#	tests/pubsub/check_pubsub_sks_push.c
#	tests/pubsub/check_pubsub_sks_securitygroups.c
#	tests/server/check_server_alarmsconditions.c
2026-09-20 10:02:09 +02:00
Julius Pfrommer 30b54d61af fix(crypto): bound PEM certificate-chain search
Search the certificate input for the next PEM header with the haystack and needle in the correct order. Use a length-bounded helper so partial headers at the end cannot read past the input.
2026-09-18 18:16:02 +02:00
Julius Pfrommer 0677590700 fix(crypto): reject certificates without an application URI
The exact-comparison change in f4c2dc2aa made an absent URI compare equal to an empty ApplicationUri. Require a non-empty URI SAN before accepting the certificate.
2026-09-18 18:16:02 +02:00
Julius Pfrommer 3065049520 fix(securitypolicy): validate RSA-PSS signature length
The mbedTLS RSA-PSS verifier consumes one complete RSA modulus but its low-level API does not take an input length. Reject malformed ByteStrings before invoking it so a short application signature cannot cause an out-of-bounds read.
2026-09-18 18:16:02 +02:00
Julius Pfrommer 9f28ac4ac8 fix(securitypolicy): validate raw ECDSA signature lengths
Reject malformed raw ECDSA signatures before converting their r and s coordinates. Short signatures could otherwise cause out-of-bounds reads in the OpenSSL backend and an underflowing bounds check in the mbedTLS backend; oversized mbedTLS signatures could overflow the fixed DER buffer.
2026-09-18 18:16:02 +02:00
Julius Pfrommer f782a38cb6 fix(pubsub): validate TPM key handles and nonce
Require serialized PKCS#11 handles and the specified four-byte key nonce before copying key material into the TPM channel context. This rejects incompatible raw SKS keys and prevents out-of-bounds reads from undersized inputs.
2026-09-18 12:14:58 +02:00
Julius Pfrommer c15f297b8d Merge remote-tracking branch 'origin/1.4' into merge_14_15
# Conflicts:
#	CHANGELOG
#	CMakeLists.txt
#	plugins/crypto/openssl/securitypolicy_openssl_common.c
#	plugins/crypto/pkcs11/securitypolicy_pubsub_aes128ctr_tpm.c
#	plugins/crypto/pkcs11/securitypolicy_pubsub_aes256ctr_tpm.c
#	src/pubsub/ua_pubsub_networkmessage.c
#	src/pubsub/ua_pubsub_ns0.c
#	src/pubsub/ua_pubsub_writer.c
#	src/pubsub/ua_pubsub_writergroup.c
#	src/server/ua_services_monitoreditem.c
#	src/server/ua_services_session.c
#	src/server/ua_session.h
#	tests/CMakeLists.txt
#	tests/check_securechannel.c
#	tests/pubsub/check_pubsub_encryption.c
#	tests/pubsub/check_pubsub_publish.c
#	tests/server/check_server_alarmsconditions.c
2026-09-17 21:58:21 +02:00
Julius Pfrommer c3742e2a5b Merge remote-tracking branch 'origin/1.3' into merge_13_14 2026-09-17 19:53:50 +02:00
Niels Beier 54eaa5b3bf fix(pubsub): fix OOB read/write and truncation in AES-CTR TPM en/decrypt
encrypt_pubsub_aes128ctr_tpm/decrypt_pubsub_aes128ctr_tpm and their
AES-256-CTR counterparts computed the block-aligned processing size
(sizeToEncrypt/sizeToDecrypt) by rounding data->length up to the next
16-byte boundary, but stored the result in a CK_BYTE. Two distinct bugs
followed from this:

- For a data->length whose rounded-up value exceeds 255, the 8-bit value
  wraps around, so far fewer bytes than intended are processed while the
  function still returns UA_STATUSCODE_GOOD.
- For any data->length that is not itself a multiple of 16, the rounded-up
  size is larger than the caller's actual buffer. The PKCS#11 update calls
  then read block-sized chunks directly from data->data past its end, and
  the final loop that copies the result back writes that same rounded-up
  size into data->data, overflowing the caller's allocation.

AES-CTR is a stream cipher and never needs block-aligned input. Fix this
by processing exactly data->length bytes throughout, using size_t/CK_ULONG
for all lengths instead of CK_BYTE: each PKCS#11 update call is chunked at
MAX_ENCRYPTION_SIZE bytes with a shorter final chunk when data->length is
not itself a multiple of it, operating on the caller's buffer directly
with no rounding, no padding, and no risk of the output exceeding the
caller's allocation.

Co-authored-by: Luigi Colluto <gigioneggiando@users.noreply.github.com>

Internal Vulnerability Advisory: open62541-SA-2026-0033
2026-09-16 07:11:01 +02:00
Niels Beier 1c1cbbdf8a fix(crypto): use constant-time, length-checked comparison for HMAC/MAC verification
The OpenSSL HMAC-SHA1/SHA256 verify helpers compared the recomputed
MAC against the peer-supplied signature with UA_ByteString_equal(),
which reduces to a plain memcmp(). memcmp() carries no constant-time
guarantee and, on a byte-at-a-time implementation (the norm on the
small-footprint libcs open62541 is routinely built against), returns
as soon as it finds a differing byte -- a timing side channel a
remote peer can use to recover a valid MAC byte-by-byte.

Switch to UA_constantTimeEqual(), already used correctly by every
other symmetric SecurityPolicy (mbedTLS Basic128Rsa15, Basic256,
Basic256Sha256, Aes128Sha256RsaOaep). Since it takes a single length
and reads that many bytes from both buffers, first validate
signature->length against the expected MAC length, mirroring the
pattern used by the project's mbedTLS RSA policy Verify functions.
The digest length is fixed by the algorithm and policy, not attacker
data, so this early-return introduces no new timing side channel.

Internal Vulnerability Advisory: open62541-SA-2026-0038
Co-authored-by: Luigi Colluto <gigioneggiando@users.noreply.github.com>
2026-09-15 20:31:48 +02:00
Niels Beier b6bd2cf88d fix(pubsub): fix OOB read/write and truncation in AES-CTR TPM en/decrypt
encrypt_sp_pubsub_aes128ctr_tpm/decrypt_sp_pubsub_aes128ctr_tpm and their
AES-256-CTR counterparts computed the block-aligned processing size
(sizeToEncrypt/sizeToDecrypt) by rounding data->length up to the next
16-byte boundary, but stored the result in a CK_BYTE. Two distinct bugs
followed from this:

- For a data->length whose rounded-up value exceeds 255, the 8-bit value
  wraps around, so far fewer bytes than intended are processed while the
  function still returns UA_STATUSCODE_GOOD.
- For any data->length that is not itself a multiple of 16, the rounded-up
  size is larger than the caller's actual buffer. The PKCS#11 update calls
  then read block-sized chunks directly from data->data past its end, and
  the final loop that copies the result back writes that same rounded-up
  size into data->data, overflowing the caller's allocation.

AES-CTR is a stream cipher and never needs block-aligned input. Fix this
by processing exactly data->length bytes throughout, using size_t/CK_ULONG
for all lengths instead of CK_BYTE: each PKCS#11 update call is chunked at
MAX_ENCRYPTION_SIZE bytes with a shorter final chunk when data->length is
not itself a multiple of it, operating on the caller's buffer directly
with no rounding, no padding, and no risk of the output exceeding the
caller's allocation.

Co-authored-by: Luigi Colluto <gigioneggiando@users.noreply.github.com>

Internal Vulnerability Advisory: open62541-SA-2026-0033
2026-09-15 20:10:23 +02:00
StalderT 1a67cf7ab0 fix(arch,plugins): remove the non-threadsafe gmtime and inet_ntoa calls
gmtime and inet_ntoa return a pointer to a static buffer shared by all threads. The mbedTLS certificate creation now derives its validity dates from UA_DateTime_now/UA_DateTime_toStruct, which also keeps the expiry date in UTC (mktime interpreted the gmtime result as local time). Zephyr uses gmtime_r and lwIP ip4addr_ntoa_r.

Fixes #7997
2026-09-13 17:54:16 +02:00
Julius Pfrommer d2bc0bccb5 fix(pubsub): validate security policy contracts early 2026-09-05 20:57:32 +02:00
Julius Pfrommer 548bc703d6 fix(pubsub): harden SKS key lifecycle and policy contracts 2026-09-05 20:57:32 +02:00
Julius Pfrommer 46a74698bb fix(plugin): generate valid filestore names for certificates and CRLs
Use the common name when available and fall back to the subject for CRLs and
certificates without a common name.

Check path formatting, propagate storage errors, and clean up trust-list data
on every exit path.
2026-09-03 17:43:01 +02:00
Julius Pfrommer a476806541 Merge remote-tracking branch 'origin/1.5' into merge_15_master
# Conflicts:
#	.github/workflows/build_linux.yml
#	CHANGES.md
#	arch/common/eventloop_mqtt.c
#	examples/encryption/server_encryption_filestore.c
#	plugins/crypto/ua_certificategroup_filestore.c
#	src/pubsub/ua_pubsub_networkmessage_json.c
#	src/server/ua_discovery.h
#	src/server/ua_discovery_mdns.c
#	src/server/ua_discovery_mdns_avahi.c
#	src/server/ua_services_attribute.c
#	src/server/ua_services_discovery.c
#	src/server/ua_services_monitoreditem.c
#	src/server/ua_services_nodemanagement.c
#	src/server/ua_subscription.c
#	src/server/ua_subscription.h
#	src/server/ua_subscription_alarms_conditions.c
#	src/server/ua_subscription_event.c
#	src/ua_types_encoding_json_105.c
#	tests/client/check_activateSessionAsync.c
#	tests/server/check_local_monitored_item.c
#	tests/server/check_services_subscriptions.c
2026-09-03 14:33:21 +02:00
Andreas Eckerstorfer f31d226c50 fix(plugins): Use file extension for certificates and CRLs (#8315)
According to the OPC UA specification part 12 appendix F.1 all
certificate files should have a '.der' extension and all CRLs
should have a '.crl' extension in the file name.
2026-08-28 19:12:21 +02:00
Julius Pfrommer bdd6ed40d4 Merge remote-tracking branch 'origin/1.5' into merge_15_master_2
# Conflicts:
#	plugins/crypto/mbedtls/certificategroup.c
#	src/pubsub/ua_pubsub_config.c
#	src/server/ua_discovery_mdns.c
#	src/server/ua_server.c
#	src/server/ua_server_internal.h
#	src/server/ua_server_ns0_gds.c
#	src/server/ua_services_nodemanagement.c
#	src/server/ua_subscription_alarms_conditions.c
#	src/ua_types_definition.c
#	tests/server/check_services_nodemanagement.c
2026-08-16 16:46:48 +02:00
Niels Beier f4c2dc2aa4 fix(plugin): replace substring URI match with exact comparison in verifyApplicationUri
UA_CertificateUtils_verifyApplicationUri() checked the certificate's Subject
Alternative Name URI field using a substring search: the function returned
success whenever the expected applicationURI appeared anywhere inside the
certificate's URI string.

An attacker who can present a certificate trusted by the peer (e.g. a
self-signed certificate added to the trust list, or any certificate issued by
a trusted CA) can craft a URI SAN of the form
"urn:attacker.example:padding:<legitimateURI>:suffix". The substring search
accepts this certificate as if it belonged to the legitimate application,
allowing impersonation of any OPC UA endpoint whose ApplicationUri is known.

OpenSSL backend: replace the UA_Bstrstr() call with a length-and-memcmp exact
match against the first URI SAN entry extracted by OpenSSL.

mbedTLS backend (< 3.4.0): replace the raw-blob UA_Bstrstr() call with a
minimal DER walker (verifySanUri) that locates the Subject Alternative Name
extension by OID (2.5.29.17), iterates the GeneralNames SEQUENCE, and
performs an exact length+memcmp comparison against each URI ([6] IMPLICIT
IA5String) GeneralName entry, using the existing named mbedTLS constants
for the tag class and SAN type instead of raw literals. mbedTLS >= 3.4.0
already used UA_String_equal() and is unaffected.

Internal Vulnerability Advisory: open62541-SA-2026-0019
Co-authored-by: Joerg Fischer <joerg.fischer@sick.de>

Thanks-to: Chuan Wei [SCU] for the responsible disclosure.
2026-08-15 10:48:05 +02:00
Niels Beier f10983c82d fix(plugin): sanitize certificate subject before use as filestore filename
The filestore security policy derives the filename for a certificate
written by ServerConfiguration.UpdateCertificate from the certificate's
Subject Common Name. On the mbedTLS backend, the subject-name renderer
preserves path separator characters found in the CN field, so a
certificate with a CN such as "../../trusted/certs/x" or containing
backslashes causes the resulting .der/.key files to be written outside
the intended own/certs and own/private directories once ApplyChanges is
called, including into other parts of the certificate store.

createCertName() now sanitizes the subject-name substring used to build
the filename: '/', '\', and control characters are replaced with '_'
before the string is combined with the certificate thumbprint. Since the
sanitized value can no longer contain a path separator, it cannot be used
to address any file outside the fixed own/certs and own/private
directories, independent of how a given crypto backend renders the
subject string.

Internal Vulnerability Advisory: open62541-SA-2026-0016

Thanks-to: Chuan Wei [SCU] for the responsible disclosure.
2026-08-14 23:22:02 +02:00
Julius Pfrommer e920163ec1 fix(server): extract X509 identity subject correctly
Pass the certificate and output subject in the documented order. The reversed arguments caused the mbedTLS implementation to clear the decoded certificate buffer before request cleanup, leaking the original allocation.
2026-08-12 05:44:46 +02:00
Julius Pfrommer 136aac08e3 refactor(mbedtls): simplify shared PSA implementation 2026-08-12 05:44:46 +02:00
Julius Pfrommer 700fb96acf test(mbedtls): cover policy integration and amalgamation 2026-08-12 05:44:46 +02:00
Julius Pfrommer 8ab275e42e refactor(mbedtls): centralize compatibility and policy descriptors 2026-08-12 05:44:46 +02:00
Julius Pfrommer f5af470c69 fix(mbedtls): make certificate and key updates transactional 2026-08-12 05:44:46 +02:00
Julius Pfrommer 669bc32f06 refactor(mbedtls): consolidate PSA-backed policies 2026-08-12 05:44:46 +02:00
Julius Pfrommer 73acba006c feat(mbedtls): add mbedTLS 4 support 2026-08-12 05:44:46 +02:00
Julius Pfrommer b77f1099a5 refactor(mbedtls): migrate security policies to PSA 2026-08-12 05:44:46 +02:00
Julius Pfrommer f4742a2d5f refactor(mbedtls): establish PSA crypto foundations 2026-08-12 05:44:46 +02:00
Julius Pfrommer ac0d474638 fix(win32): restore filestore platform definitions 2026-08-10 19:31:57 +02:00
Julius Pfrommer 4e7f4597e9 feat(crypto): expose certificate EKU parsing
Add a backend-neutral API for reading certificate extended key usage.

Jörg Fischer of SICK AG reported the EKU validation gap and supplied the
negative-test PKI stores that motivated this API.

Co-authored-by: Jörg Fischer <joerg.fischer@sick.de>
2026-08-09 18:07:45 +02:00
Julius Pfrommer 2ba24e2528 Merge remote-tracking branch 'origin/1.5' into merge_15_master
# Conflicts:
#	CMakeLists.txt
#	include/open62541/config.h.in
#	plugins/crypto/ua_certificategroup_filestore.c
#	plugins/ua_config_json.c
#	src/server/ua_services_attribute.c
#	tests/CMakeLists.txt
#	tests/server/check_services_attributes.c
2026-07-25 22:36:06 +02:00
Niels Beier 7e66dcf20d fix(plugins): sanitize CN in getCertFileName
getCertFileName() extracts the certificate subject's CN field via
strstr() and inserts it directly into the rejected-certificate file
path without sanitization or truncation at the trailing RDN comma. A
remote peer presenting a certificate with a subject such as
CN=../../tmp/evil can make the FileCertStore plugin write the
rejected certificate DER outside the configured rejected-certificate
directory, into any existing directory reachable via the traversal
sequence. The untruncated CN also lets subsequent RDN components leak
into the generated filename.

Truncate subName at the first ',' to drop trailing RDN components,
and replace '/' and '\' in the extracted CN with '_' before it is
used to build the file path.

Internal Vulnerability Advisory: open62541-SA-2026-0011
Co-authored-by: Tomer Dricker <tomerdricker@microsoft.com>
2026-07-24 09:40:14 +02:00
Julius Pfrommer ba6c0fe3d6 fix(plugins): Manage PubSub AES contexts correctly
Initialize and clear the temporary AES contexts used by the PubSub AES-CTR security policies.
2026-07-22 14:48:59 +02:00
Andreas Ebner d2c5d0aff0 Merge remote-tracking branch 'origin/1.5' into merge_15_master_5
# Conflicts:
#	CMakeLists.txt
#	src/server/ua_session.c
#	src/ua_types_encoding_json.c
#	src/ua_types_encoding_json_105.c
#	tests/CMakeLists.txt
#	tests/pubsub/check_pubsub_publish.c
#	tests/server/check_services_subscriptions.c
#	tests/valgrind_check_error.py
#	tools/ci/linux/ci.sh
2026-07-17 09:19:33 +02:00
Andreas Ebner 4a6eb23941 fix(test): wrap test_helpers.h in extern C so fuzz_client links UA_Client_newForUnitTest
Also carry over review fixes (openssl keySize==0 guard, check_client/ns0_diagnostics, etc).
2026-07-15 14:15:49 +02:00
Andreas Ebner f5d91fd427 fix(sec): reject non-block-aligned RSA decrypt input
Mirror the mbedtls backend by validating length is a non-zero multiple of keySize.
2026-07-15 14:15:49 +02:00