mirror of
https://github.com/open62541/open62541.git
synced 2026-10-17 04:42:09 +08:00
docs(security): restructure into top-level Security section
This commit is contained in:
committed by
Julius Pfrommer
parent
7f609cc6bc
commit
e7f89a540f
@@ -99,3 +99,9 @@ nbdist/
|
||||
.nb-gradle/
|
||||
tests/interop/node-opcua/node_modules/
|
||||
tests/interop/node-opcua/package-lock.json
|
||||
|
||||
# Python virtualenv
|
||||
.venv/
|
||||
|
||||
# Local doc-review helper (not part of the project)
|
||||
gen_review_docs.sh
|
||||
|
||||
@@ -16,6 +16,26 @@ list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/CMakeLists.txt")
|
||||
string(REPLACE "${PROJECT_SOURCE_DIR}/doc" "${DOC_SRC_DIR}" DOC_TARGET "${DOC_SRC}")
|
||||
file(COPY ${DOC_SRC} DESTINATION ${DOC_SRC_DIR})
|
||||
|
||||
# Recursively copy sub-directories (e.g. doc/security/) so nested RST
|
||||
# sources are picked up by the Sphinx build.
|
||||
file(GLOB DOC_SUBDIR_SRC "${PROJECT_SOURCE_DIR}/doc/*/")
|
||||
set(DOC_SUBDIR_TARGET "")
|
||||
foreach(SUBDIR ${DOC_SUBDIR_SRC})
|
||||
get_filename_component(SUBDIR_NAME "${SUBDIR}" NAME)
|
||||
file(GLOB_RECURSE SUBDIR_FILES "${SUBDIR}*")
|
||||
foreach(SRC_FILE ${SUBDIR_FILES})
|
||||
string(REPLACE "${PROJECT_SOURCE_DIR}/doc/" "" SRC_REL "${SRC_FILE}")
|
||||
set(DST_FILE "${DOC_SRC_DIR}/${SRC_REL}")
|
||||
list(APPEND DOC_SUBDIR_TARGET "${DST_FILE}")
|
||||
add_custom_command(OUTPUT "${DST_FILE}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${SRC_FILE}" "${DST_FILE}"
|
||||
DEPENDS "${SRC_FILE}"
|
||||
COMMENT "Copy ${SRC_REL} to doc_src")
|
||||
endforeach()
|
||||
endforeach()
|
||||
list(APPEND DOC_TARGET ${DOC_SUBDIR_TARGET})
|
||||
|
||||
configure_file("${PROJECT_SOURCE_DIR}/doc/conf.py" "${DOC_SRC_DIR}/conf.py")
|
||||
|
||||
list(APPEND GENERATED_RST "")
|
||||
|
||||
+1
-1
@@ -318,7 +318,7 @@ Detailed SDK Features
|
||||
|
||||
ECC security policies (NIST P-256/P-384, Brainpool) are available with OpenSSL
|
||||
or mbedTLS ≥ 3.0. Curve25519 and Curve448 require OpenSSL. See
|
||||
:ref:`ecc-security` for details.
|
||||
:ref:`security-ecc` for details.
|
||||
|
||||
**UA_ENABLE_ENCRYPTION_TPM2**
|
||||
Enable TPM hardware for encryption. The possible options are:
|
||||
|
||||
+7
-211
@@ -1,216 +1,12 @@
|
||||
:orphan:
|
||||
|
||||
.. _ecc-security:
|
||||
|
||||
ECC Security Policies
|
||||
=====================
|
||||
|
||||
open62541 supports Elliptic Curve Cryptography (ECC) security policies as
|
||||
defined in the OPC UA Security Profiles. ECC policies provide equivalent or
|
||||
stronger security than RSA-based policies with shorter key lengths, making them
|
||||
suitable for resource-constrained and modern deployments.
|
||||
|
||||
Supported Curves
|
||||
----------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - OPC UA Policy
|
||||
- Curve
|
||||
- OpenSSL
|
||||
- mbedTLS ≥ 3.0
|
||||
* - ``EccNistP256``
|
||||
- NIST P-256 (prime256v1)
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccNistP384``
|
||||
- NIST P-384 (secp384r1)
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccBrainpoolP256r1``
|
||||
- Brainpool P-256r1
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccBrainpoolP384r1``
|
||||
- Brainpool P-384r1
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccCurve25519``
|
||||
- Curve25519 (Ed25519)
|
||||
- ✓
|
||||
- ✗
|
||||
* - ``EccCurve448``
|
||||
- Curve448 (Ed448)
|
||||
- ✓
|
||||
- ✗
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
- **OpenSSL ≥ 3.0** is recommended for full ECC support including
|
||||
Curve25519 and Curve448.
|
||||
- **mbedTLS ≥ 3.0** supports NIST and Brainpool curves. Curve25519 and
|
||||
Curve448 are not available with mbedTLS (OpenSSL only).
|
||||
- Build with ``-DUA_ENABLE_ENCRYPTION=OPENSSL`` (or ``MBEDTLS``).
|
||||
|
||||
ECC Certificate Requirements
|
||||
-----------------------------
|
||||
|
||||
Each ECC security policy requires its own certificate and private key that
|
||||
matches the curve. A single certificate **cannot** be shared across different
|
||||
curves. RSA and ECC policies can coexist on the same server, but each requires
|
||||
its own key pair.
|
||||
|
||||
**Key Usage** (X.509 extension):
|
||||
|
||||
- ECC certificates **must** include ``keyAgreement`` (required for ECDH key
|
||||
exchange). The recommended key usage for ECDSA curves is::
|
||||
|
||||
digitalSignature, nonRepudiation, keyAgreement, keyCertSign
|
||||
|
||||
- RSA certificates use ``keyEncipherment`` instead of ``keyAgreement``.
|
||||
|
||||
**SubjectAltName** must include at minimum:
|
||||
|
||||
- ``URI:<ApplicationUri>`` — matching the server's ApplicationDescription
|
||||
- ``DNS:<hostname>`` — for hostname validation
|
||||
|
||||
Generating ECC Certificates
|
||||
----------------------------
|
||||
|
||||
Using ``UA_CreateCertificate`` (auto-generation)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The built-in certificate generator supports ECC when the ``key-type`` parameter
|
||||
is set to ``"EC"``:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
UA_KeyValueMap *kvm = UA_KeyValueMap_new();
|
||||
UA_UInt16 expiresIn = 365;
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "expires-in-days"),
|
||||
&expiresIn, &UA_TYPES[UA_TYPES_UINT16]);
|
||||
UA_String keyType = UA_STRING_STATIC("EC");
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "key-type"),
|
||||
&keyType, &UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_String curve = UA_STRING_STATIC("prime256v1");
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "ecc-curve"),
|
||||
&curve, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
UA_ByteString privateKey = UA_BYTESTRING_NULL;
|
||||
UA_ByteString certificate = UA_BYTESTRING_NULL;
|
||||
UA_CreateCertificate(UA_Log_Stdout, subject, lenSubject,
|
||||
subjectAltName, lenSubjectAltName,
|
||||
UA_CERTIFICATEFORMAT_DER, kvm,
|
||||
&privateKey, &certificate);
|
||||
UA_KeyValueMap_delete(kvm);
|
||||
|
||||
Supported ``ecc-curve`` values: ``prime256v1``, ``secp384r1``,
|
||||
``brainpoolP256r1``, ``brainpoolP384r1``, ``ed25519``, ``ed448``
|
||||
(last two require OpenSSL).
|
||||
|
||||
Using OpenSSL command line
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For ECDSA curves (P-256, P-384, Brainpool):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Generate NIST P-256 key and self-signed certificate
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out server_nistP256.key.pem
|
||||
openssl req -new -x509 -key server_nistP256.key.pem \
|
||||
-out server_nistP256.cert.pem -days 3650 -sha256 \
|
||||
-subj "/C=DE/O=MyOrg/CN=OPC-UA-Server" \
|
||||
-addext "subjectAltName=URI:urn:my.app:server,DNS:localhost,IP:127.0.0.1" \
|
||||
-addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=critical,digitalSignature,nonRepudiation,keyAgreement" \
|
||||
-addext "extendedKeyUsage=serverAuth,clientAuth"
|
||||
# Convert to DER (required by open62541)
|
||||
openssl x509 -in server_nistP256.cert.pem -outform DER -out server_nistP256.cert.der
|
||||
openssl pkey -in server_nistP256.key.pem -outform DER -out server_nistP256.key.der
|
||||
|
||||
For EdDSA curves (Curve25519, Curve448):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Generate Ed25519 key and self-signed certificate
|
||||
openssl genpkey -algorithm ed25519 -out server_curve25519.key.pem
|
||||
openssl req -new -x509 -key server_curve25519.key.pem \
|
||||
-out server_curve25519.cert.pem -days 3650 \
|
||||
-subj "/C=DE/O=MyOrg/CN=OPC-UA-Server" \
|
||||
-addext "subjectAltName=URI:urn:my.app:server,DNS:localhost,IP:127.0.0.1" \
|
||||
-addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=critical,digitalSignature,nonRepudiation,keyAgreement" \
|
||||
-addext "extendedKeyUsage=serverAuth,clientAuth"
|
||||
openssl x509 -in server_curve25519.cert.pem -outform DER -out server_curve25519.cert.der
|
||||
openssl pkey -in server_curve25519.key.pem -outform DER -out server_curve25519.key.der
|
||||
|
||||
Use ``-sha384`` for P-384 and brainpoolP384r1 curves. Replace ``prime256v1``
|
||||
with ``secp384r1``, ``brainpoolP256r1``, or ``brainpoolP384r1`` respectively.
|
||||
Replace ``ed25519`` with ``ed448`` for Curve448.
|
||||
|
||||
Using the helper script ``create_self-signed.py``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``tools/certs/create_self-signed.py`` script can generate ECC certificates
|
||||
for development and testing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Generate a single ECC certificate (e.g. NIST P-256)
|
||||
python3 tools/certs/create_self-signed.py /tmp/certs --ecc prime256v1
|
||||
|
||||
# Generate certificates for all supported ECC curves at once
|
||||
python3 tools/certs/create_self-signed.py /tmp/certs --ecc-all
|
||||
|
||||
The ``--ecc <curve>`` flag accepts: ``prime256v1``, ``secp384r1``,
|
||||
``brainpoolP256r1``, ``brainpoolP384r1``, ``ed25519``, ``ed448``.
|
||||
The ``--ecc-all`` flag generates certificates for all six curves. Output files
|
||||
are named ``server_c_<curve>.cert.der`` / ``server_c_<curve>.key.der``, ready
|
||||
for use with the ``--ecc-cert-dir`` option of the ``server_encryption`` example.
|
||||
|
||||
Running the Encryption Server Example
|
||||
--------------------------------------
|
||||
|
||||
The ``server_encryption`` example supports two modes for ECC:
|
||||
|
||||
**Auto-generated P-256 certificate** (no external files needed):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./server_encryption --ecc
|
||||
|
||||
This generates a NIST P-256 self-signed certificate at startup and configures
|
||||
the server with ECC security policies matching that key.
|
||||
|
||||
**Multiple ECC curves from a certificate directory**:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./server_encryption server_rsa.cert.der server_rsa.key.der \
|
||||
--ecc-cert-dir /path/to/ecc_certs/
|
||||
|
||||
The directory must contain DER files named ``server_c_<curve>.cert.der`` and
|
||||
``server_c_<curve>.key.der`` where ``<curve>`` is one of: ``nistP256``,
|
||||
``nistP384``, ``brainpoolP256r1``, ``brainpoolP384r1``, ``curve25519``,
|
||||
``curve448``. Missing curves are silently skipped. The RSA certificate
|
||||
provided as positional argument enables the standard RSA policies alongside
|
||||
the ECC policies.
|
||||
|
||||
Server API Usage
|
||||
----------------
|
||||
|
||||
Adding individual ECC policies:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
UA_ServerConfig_addSecurityPolicyEccNistP256(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccNistP384(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccBrainpoolP256r1(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccBrainpoolP384r1(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccCurve25519(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccCurve448(config, &cert, &key);
|
||||
/* Create endpoints for the added policies */
|
||||
UA_ServerConfig_addAllEndpoints(config);
|
||||
|
||||
Alternatively, ``UA_ServerConfig_addAllSecurityPolicies()`` auto-detects the key
|
||||
type (RSA vs EC) and adds all matching policies.
|
||||
This page has moved. The ECC content is now part of the new top-level
|
||||
:ref:`Security <security>` section -- see :ref:`security-ecc` for ECC
|
||||
specifics (supported curves, certificate requirements, generation, and
|
||||
the related server API) and :ref:`security-overview` for the rest of the
|
||||
security stack.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
.. _security-authentication:
|
||||
|
||||
Authentication
|
||||
==============
|
||||
|
||||
Authentication in OPC UA happens at the *Session* layer, on top of an
|
||||
already-open SecureChannel. The client presents an *IdentityToken* during
|
||||
``ActivateSession``. The server validates it through its *AccessControl*
|
||||
plugin and either accepts or rejects the session.
|
||||
|
||||
Identity token types
|
||||
--------------------
|
||||
|
||||
The standard defines four token types. All four are accepted by
|
||||
open62541's default access-control plugin and may be enabled in any
|
||||
combination.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 26 28 46
|
||||
|
||||
* - Token
|
||||
- Type constant
|
||||
- Typical use
|
||||
* - Anonymous
|
||||
- ``UA_AnonymousIdentityToken``
|
||||
- Public, read-only data, discovery. Opt out for protected servers.
|
||||
* - Username / Password
|
||||
- ``UA_UserNameIdentityToken``
|
||||
- Simple human-user login. Credentials checked against an
|
||||
in-server list or a custom callback.
|
||||
* - X.509 Certificate
|
||||
- ``UA_X509IdentityToken``
|
||||
- Mutual-TLS-style login. The client proves possession of the
|
||||
private key matching a certificate the server trusts.
|
||||
* - Issued Token
|
||||
- ``UA_IssuedIdentityToken``
|
||||
- External STS / OAuth-style flows. The server forwards the token
|
||||
to an authorization service.
|
||||
|
||||
Default server configuration
|
||||
----------------------------
|
||||
|
||||
``UA_AccessControl_default()`` (in
|
||||
``plugins/ua_accesscontrol_default.c``) wires up the standard validator.
|
||||
It checks anonymous logins, looks up username/password pairs in a static
|
||||
list, and (when configured) verifies X.509 chains through a
|
||||
``UA_CertificateGroup``. The actual session-validation routine is
|
||||
``activateSession_default()`` in the same file.
|
||||
|
||||
Useful entry points in the public plugin header
|
||||
``plugins/include/open62541/plugin/accesscontrol_default.h``:
|
||||
|
||||
- ``UA_AccessControl_default()`` -- construct a default access-control
|
||||
plugin with a username/password allow-list and an optional
|
||||
``UA_UsernamePasswordLoginCallback`` for custom validation.
|
||||
- ``verifyX509`` -- a ``UA_CertificateGroup`` used to validate X.509
|
||||
identity tokens. See :ref:`security-certificates`.
|
||||
|
||||
For the protocol-level description of how authentication fits into
|
||||
``CreateSession`` / ``ActivateSession``, see :doc:`../core_concepts`
|
||||
("Session" section).
|
||||
@@ -0,0 +1,76 @@
|
||||
.. _security-backends:
|
||||
|
||||
Crypto Backends
|
||||
===============
|
||||
|
||||
open62541 does not implement cryptography itself. It delegates to an
|
||||
external library through a thin plugin layer. The build option
|
||||
``UA_ENABLE_ENCRYPTION`` selects which library is compiled in. No security
|
||||
policy from :ref:`security-policies` is available when this option is
|
||||
``OFF``.
|
||||
|
||||
Backend selection
|
||||
-----------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 32 68
|
||||
|
||||
* - CMake option
|
||||
- Effect
|
||||
* - ``UA_ENABLE_ENCRYPTION=OFF``
|
||||
- No encryption support. Default. Only the ``None`` policy is usable.
|
||||
* - ``UA_ENABLE_ENCRYPTION=MBEDTLS``
|
||||
- mbedTLS. All RSA profiles + the four NIST/Brainpool ECC curves.
|
||||
* - ``UA_ENABLE_ENCRYPTION=OPENSSL``
|
||||
- OpenSSL. All RSA profiles + every ECC curve, including
|
||||
Curve25519 and Curve448 (EdDSA).
|
||||
* - ``UA_ENABLE_ENCRYPTION=LIBRESSL``
|
||||
- LibreSSL. Experimental. Coverage is similar to OpenSSL.
|
||||
|
||||
The two boolean aliases ``UA_ENABLE_ENCRYPTION_OPENSSL`` and
|
||||
``UA_ENABLE_ENCRYPTION_MBEDTLS`` are still accepted for backward
|
||||
compatibility. Prefer the unified ``UA_ENABLE_ENCRYPTION`` form in new
|
||||
projects.
|
||||
|
||||
Hardware-backed key storage (TPM2)
|
||||
----------------------------------
|
||||
|
||||
``UA_ENABLE_ENCRYPTION_TPM2=ON`` adds TPM2-backed key storage on top of an
|
||||
already-selected ``UA_ENABLE_ENCRYPTION`` backend. It is **not** a
|
||||
standalone crypto library, so it must be combined with ``MBEDTLS`` or
|
||||
``OPENSSL``. When enabled, the private key used by the server lives on a
|
||||
TPM2 device instead of in a DER file. See the
|
||||
``server_encryption_tpm_keystore`` and ``client_encryption_tpm_keystore``
|
||||
examples, and the ``README_client_server_tpm_keystore.txt`` next to them
|
||||
for the required software stack.
|
||||
|
||||
Library version requirements
|
||||
----------------------------
|
||||
|
||||
- **mbedTLS ≥ 3.0** is required for the four NIST/Brainpool ECC curves.
|
||||
mbedTLS does not support Curve25519 / Curve448.
|
||||
- **OpenSSL ≥ 3.0** is required for full ECC support including EdDSA
|
||||
curves.
|
||||
- See :ref:`building` for the exact flag set and the
|
||||
``UA_ENABLE_ENCRYPTION_TPM2`` option.
|
||||
|
||||
Registering policies
|
||||
--------------------
|
||||
|
||||
The backend is selected at build time, not at runtime. Once built with
|
||||
``UA_ENABLE_ENCRYPTION=OPENSSL`` (or ``MBEDTLS``), adding a policy to a
|
||||
server is one call per policy and the same call works with either backend:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
UA_ServerConfig_addSecurityPolicyNone(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, &cert, &key);
|
||||
UA_ServerConfig_addSecurityPolicyEccNistP256(config, &cert, &key);
|
||||
/* ... or, in one shot: */
|
||||
UA_ServerConfig_addAllSecurityPolicies(config, &cert, &key);
|
||||
|
||||
``UA_ServerConfig_addAllSecurityPolicies()`` auto-detects the key type
|
||||
(RSA vs EC) and registers all policies matching the key. The
|
||||
ECC-specific helpers and the full set of ``addSecurityPolicy*()`` calls
|
||||
are listed in :ref:`security-ecc`.
|
||||
@@ -0,0 +1,94 @@
|
||||
.. _security-certificates:
|
||||
|
||||
Certificates and Trust
|
||||
======================
|
||||
|
||||
Every SecureChannel protected by anything other than the ``None`` policy
|
||||
requires an X.509 certificate and matching private key on both sides.
|
||||
Trust is managed by *CertificateGroup* plugins, which store the trusted
|
||||
issuer list, the rejected-certificate list, and the CRLs used during
|
||||
validation.
|
||||
|
||||
CertificateGroup backends
|
||||
-------------------------
|
||||
|
||||
open62541 ships three CertificateGroup backends. Pick one when you
|
||||
configure your server.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 28 72
|
||||
|
||||
* - Backend
|
||||
- Notes
|
||||
* - ``UA_CertificateGroup_AcceptAll``
|
||||
- Trust every certificate. Useful for tests and demos, **not for
|
||||
production**.
|
||||
* - ``UA_CertificateGroup_Memorystore``
|
||||
- Trust list kept in RAM. Configurable size limits
|
||||
(``0:max-trust-listsize`` defaults to 64 KiB;
|
||||
``0:max-rejected-listsize`` defaults to 100).
|
||||
* - ``UA_CertificateGroup_Filestore``
|
||||
- Trust list on disk under a PKI directory. Default location is
|
||||
the current working directory, override with
|
||||
``UA_CertificateGroup_Filestore``'s path argument.
|
||||
|
||||
Filestore PKI layout
|
||||
--------------------
|
||||
|
||||
The Filestore backend reads and writes a fixed directory layout rooted
|
||||
at the configured path:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
pki/
|
||||
├── ApplCerts/
|
||||
│ ├── issuer/{certs,crl}/
|
||||
│ ├── own/{certs,private}/
|
||||
│ ├── rejected/certs/
|
||||
│ └── trusted/{certs,crl}/
|
||||
└── UserTokenCerts/
|
||||
└── (same layout as ApplCerts)
|
||||
|
||||
Generate a certificate
|
||||
----------------------
|
||||
|
||||
For development and self-signed certificates, ``UA_CreateCertificate``
|
||||
(in ``plugins/include/open62541/plugin/create_certificate.h``) generates
|
||||
a key pair and a self-signed certificate in one call. RSA key sizes
|
||||
2048 / 4096 are supported (4096 default). ECC usage is documented in
|
||||
:ref:`security-ecc`.
|
||||
|
||||
Certificate utility functions
|
||||
-----------------------------
|
||||
|
||||
The ``UA_CertificateUtils_*`` helpers in
|
||||
``include/open62541/plugin/certificategroup.h`` extract common
|
||||
information from a DER certificate without exposing the underlying
|
||||
crypto library:
|
||||
|
||||
- ``UA_CertificateUtils_verifyApplicationUri()`` -- check that the
|
||||
cert's SubjectAltName URI matches the application's
|
||||
``ApplicationUri``.
|
||||
- ``UA_CertificateUtils_getExpirationDate()`` -- X.509 ``notAfter``.
|
||||
- ``UA_CertificateUtils_getSubjectName()`` -- X.509 Subject DN.
|
||||
- ``UA_CertificateUtils_getThumbprint()`` -- SHA-1 thumbprint.
|
||||
- ``UA_CertificateUtils_getKeySize()`` -- asymmetric key length in bits.
|
||||
- ``UA_CertificateUtils_comparePublicKeys()`` -- compare public keys
|
||||
from a certificate and a CSR.
|
||||
|
||||
Revocation
|
||||
----------
|
||||
|
||||
When a certificate fails trust validation, the standard OPC UA status
|
||||
codes used by open62541 are:
|
||||
|
||||
- ``UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN``
|
||||
- ``UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN``
|
||||
- ``UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED``
|
||||
- ``UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED``
|
||||
|
||||
The Filestore backend's ``getCertificateCrls()`` operation returns the
|
||||
CRLs relevant to a certificate, used by the verification step.
|
||||
|
||||
For the full plugin API, see :doc:`../plugin_certificategroup`.
|
||||
@@ -0,0 +1,158 @@
|
||||
.. _security-ecc:
|
||||
|
||||
ECC Specifics
|
||||
=============
|
||||
|
||||
ECC policies give equivalent or stronger security than the RSA-based
|
||||
profiles with much shorter key lengths, which makes them well suited for
|
||||
resource-constrained and modern deployments. This page documents only
|
||||
the ECC-specific configuration. For the general picture read
|
||||
:ref:`security-overview` first.
|
||||
|
||||
Supported curves
|
||||
----------------
|
||||
|
||||
Each row corresponds to one SecurityPolicy. The presence of a check
|
||||
mark means that backend can register the policy given a matching
|
||||
certificate and private key.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 36 32 16 16
|
||||
|
||||
* - OPC UA Policy
|
||||
- Curve
|
||||
- OpenSSL
|
||||
- mbedTLS ≥ 3.0
|
||||
* - ``EccNistP256``
|
||||
- NIST P-256 (prime256v1)
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccNistP384``
|
||||
- NIST P-384 (secp384r1)
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccBrainpoolP256r1``
|
||||
- Brainpool P-256r1
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccBrainpoolP384r1``
|
||||
- Brainpool P-384r1
|
||||
- ✓
|
||||
- ✓
|
||||
* - ``EccCurve25519``
|
||||
- Curve25519 (Ed25519)
|
||||
- ✓
|
||||
- ✗
|
||||
* - ``EccCurve448``
|
||||
- Curve448 (Ed448)
|
||||
- ✓
|
||||
- ✗
|
||||
|
||||
Curve25519 and Curve448 require OpenSSL ≥ 3.0. The NIST and Brainpool
|
||||
curves require mbedTLS ≥ 3.0 or OpenSSL ≥ 3.0. See
|
||||
:ref:`security-backends` for the build flags.
|
||||
|
||||
Certificate requirements
|
||||
------------------------
|
||||
|
||||
Each ECC policy requires its own certificate and private key, and the
|
||||
key must match the curve. A single certificate **cannot** be shared
|
||||
across different curves. RSA and ECC policies can coexist on the same
|
||||
server. Each carries its own key pair.
|
||||
|
||||
X.509 extensions to set when creating an ECC certificate:
|
||||
|
||||
- **Key Usage** -- ``keyAgreement`` is required (for ECDH key exchange).
|
||||
The recommended set for ECDSA curves is::
|
||||
|
||||
digitalSignature, nonRepudiation, keyAgreement, keyCertSign
|
||||
|
||||
RSA certificates use ``keyEncipherment`` instead.
|
||||
- **SubjectAltName** -- must include at least ``URI:<ApplicationUri>``
|
||||
and ``DNS:<hostname>`` (or ``IP:...``).
|
||||
|
||||
Generating ECC certificates
|
||||
---------------------------
|
||||
|
||||
There are three ways to obtain an ECC certificate for use with
|
||||
open62541.
|
||||
|
||||
**1. ``UA_CreateCertificate`` (built-in, recommended for development)**
|
||||
|
||||
Pass ``key-type = "EC"`` and the desired ``ecc-curve`` value in the
|
||||
key-value map. Supported curves: ``prime256v1``, ``secp384r1``,
|
||||
``brainpoolP256r1``, ``brainpoolP384r1``, ``ed25519``, ``ed448`` (last
|
||||
two require OpenSSL).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
UA_KeyValueMap *kvm = UA_KeyValueMap_new();
|
||||
UA_UInt16 expiresIn = 365;
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "expires-in-days"),
|
||||
&expiresIn, &UA_TYPES[UA_TYPES_UINT16]);
|
||||
UA_String keyType = UA_STRING_STATIC("EC");
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "key-type"),
|
||||
&keyType, &UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_String curve = UA_STRING_STATIC("prime256v1");
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, "ecc-curve"),
|
||||
&curve, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
UA_ByteString privateKey = UA_BYTESTRING_NULL;
|
||||
UA_ByteString certificate = UA_BYTESTRING_NULL;
|
||||
UA_CreateCertificate(UA_Log_Stdout, subject, lenSubject,
|
||||
subjectAltName, lenSubjectAltName,
|
||||
UA_CERTIFICATEFORMAT_DER, kvm,
|
||||
&privateKey, &certificate);
|
||||
UA_KeyValueMap_delete(kvm);
|
||||
|
||||
**2. OpenSSL CLI (production, full control)**
|
||||
|
||||
ECDSA curves (P-256, P-384, Brainpool):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out server_nistP256.key.pem
|
||||
openssl req -new -x509 -key server_nistP256.key.pem \
|
||||
-out server_nistP256.cert.pem -days 3650 -sha256 \
|
||||
-subj "/C=DE/O=MyOrg/CN=OPC-UA-Server" \
|
||||
-addext "subjectAltName=URI:urn:my.app:server,DNS:localhost,IP:127.0.0.1" \
|
||||
-addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=critical,digitalSignature,nonRepudiation,keyAgreement" \
|
||||
-addext "extendedKeyUsage=serverAuth,clientAuth"
|
||||
openssl x509 -in server_nistP256.cert.pem -outform DER -out server_nistP256.cert.der
|
||||
openssl pkey -in server_nistP256.key.pem -outform DER -out server_nistP256.key.der
|
||||
|
||||
Use ``-sha384`` and ``prime256v1`` replaced with ``secp384r1`` or
|
||||
``brainpoolP256r1`` / ``brainpoolP384r1`` accordingly.
|
||||
|
||||
EdDSA curves (Curve25519, Curve448):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl genpkey -algorithm ed25519 -out server_curve25519.key.pem
|
||||
openssl req -new -x509 -key server_curve25519.key.pem \
|
||||
-out server_curve25519.cert.pem -days 3650 \
|
||||
-subj "/C=DE/O=MyOrg/CN=OPC-UA-Server" \
|
||||
-addext "subjectAltName=URI:urn:my.app:server,DNS:localhost,IP:127.0.0.1" \
|
||||
-addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=critical,digitalSignature,nonRepudiation,keyAgreement" \
|
||||
-addext "extendedKeyUsage=serverAuth,clientAuth"
|
||||
openssl x509 -in server_curve25519.cert.pem -outform DER -out server_curve25519.cert.der
|
||||
openssl pkey -in server_curve25519.key.pem -outform DER -out server_curve25519.key.der
|
||||
|
||||
Replace ``ed25519`` with ``ed448`` for Curve448.
|
||||
|
||||
**3. ``tools/certs/create_self-signed.py`` (development helper)**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Single ECC certificate
|
||||
python3 tools/certs/create_self-signed.py /tmp/certs --ecc prime256v1
|
||||
|
||||
# All supported ECC curves at once
|
||||
python3 tools/certs/create_self-signed.py /tmp/certs --ecc-all
|
||||
|
||||
The ``--ecc-all`` mode produces DER files named
|
||||
``server_c_<curve>.cert.der`` / ``server_c_<curve>.key.der`` ready for
|
||||
``--ecc-cert-dir``.
|
||||
@@ -0,0 +1,39 @@
|
||||
.. _security:
|
||||
.. _security-overview:
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
OPC UA security rests on two layers: the *SecureChannel* protects the wire
|
||||
between client and server, and the *Session* authenticates the user on top of
|
||||
an open channel. open62541 ships with a complete, pluggable security stack
|
||||
covering both.
|
||||
|
||||
This section documents the parts you actually configure and operate:
|
||||
|
||||
.. toctree::
|
||||
|
||||
policies
|
||||
backends
|
||||
authentication
|
||||
certificates
|
||||
ecc
|
||||
|
||||
- :doc:`policies` -- the standard OPC UA SecurityPolicies supported by
|
||||
open62541 and how to register them on a server.
|
||||
- :doc:`backends` -- the underlying crypto library (mbedTLS, OpenSSL, or
|
||||
LibreSSL) and the build flags that select it.
|
||||
- :doc:`authentication` -- the identity-token types used to authenticate
|
||||
Sessions (Anonymous, Username/Password, X.509, Issued Token).
|
||||
- :doc:`certificates` -- X.509 certificate management: trust lists, the
|
||||
three CertificateGroup backends (AcceptAll, Memorystore, Filestore),
|
||||
and the ``UA_CreateCertificate`` helper.
|
||||
- :doc:`ecc` -- ECC specifics: supported curves, certificate requirements,
|
||||
generation, and the related examples.
|
||||
|
||||
For the protocol-level overview (SecureChannel, SecurityMode, Endpoint
|
||||
discovery) -- see :doc:`../core_concepts`. This section focuses on the
|
||||
configuration and operational side.
|
||||
|
||||
For the auto-generated plugin API, see
|
||||
:doc:`../plugin_securitypolicy` and :doc:`../plugin_certificategroup`.
|
||||
@@ -0,0 +1,71 @@
|
||||
.. _security-policies:
|
||||
|
||||
Supported Security Policies
|
||||
===========================
|
||||
|
||||
A *SecurityPolicy* is a named bundle of algorithms for asymmetric signing,
|
||||
asymmetric encryption, symmetric encryption, key derivation, and message
|
||||
signing -- defined in Part 7 of the OPC UA standard. A server advertises its
|
||||
supported policies through its *Endpoints* (returned by ``GetEndpoints``).
|
||||
The client picks one when opening a SecureChannel.
|
||||
|
||||
The table below lists every standard profile implemented in open62541.
|
||||
Adding a policy to a server is the same call regardless of backend --
|
||||
``UA_ServerConfig_addSecurityPolicy*()`` (see :ref:`security-ecc` for the
|
||||
full call list).
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 30 14 56
|
||||
|
||||
* - Policy
|
||||
- Type
|
||||
- Notes
|
||||
* - ``None``
|
||||
- Universal
|
||||
- No signing, no encryption. Required for unencrypted discovery.
|
||||
* - ``Basic128Rsa15``
|
||||
- RSA
|
||||
- Legacy. RSA-1024 + AES-128. Deprecated, do not use for new systems.
|
||||
* - ``Basic256``
|
||||
- RSA
|
||||
- RSA-2048 + AES-256. Replaced by ``Basic256Sha256``.
|
||||
* - ``Basic256Sha256``
|
||||
- RSA
|
||||
- RSA-2048 + SHA-256 + AES-256. The current RSA baseline.
|
||||
* - ``Aes128_Sha256_RsaOaep``
|
||||
- RSA
|
||||
- RSA-OAEP + AES-128 + SHA-256. Modern RSA profile.
|
||||
* - ``Aes256_Sha256_RsaPss``
|
||||
- RSA
|
||||
- RSA-PSS + AES-256 + SHA-256. Strongest RSA profile.
|
||||
* - ``ECC_nistP256``
|
||||
- ECC
|
||||
- NIST P-256 (prime256v1). See :ref:`security-ecc`.
|
||||
* - ``ECC_nistP384``
|
||||
- ECC
|
||||
- NIST P-384 (secp384r1). See :ref:`security-ecc`.
|
||||
* - ``ECC_brainpoolP256r1``
|
||||
- ECC
|
||||
- Brainpool P-256r1. See :ref:`security-ecc`.
|
||||
* - ``ECC_brainpoolP384r1``
|
||||
- ECC
|
||||
- Brainpool P-384r1. See :ref:`security-ecc`.
|
||||
* - ``ECC_curve25519``
|
||||
- ECC (EdDSA)
|
||||
- Curve25519 / Ed25519. OpenSSL only. See :ref:`security-ecc`.
|
||||
* - ``ECC_curve448``
|
||||
- ECC (EdDSA)
|
||||
- Curve448 / Ed448. OpenSSL only. See :ref:`security-ecc`.
|
||||
* - ``PubSub-Aes128-CTR``
|
||||
- PubSub
|
||||
- Symmetric-only, AES-128-CTR. Used with PubSub message security.
|
||||
* - ``PubSub-Aes256-CTR``
|
||||
- PubSub
|
||||
- Symmetric-only, AES-256-CTR. Used with PubSub message security.
|
||||
|
||||
Which of these you can actually enable depends on the :ref:`crypto backend
|
||||
<security-backends>` and the certificate you load. ECC-specifics -- the
|
||||
curve support matrix, certificate requirements, and the
|
||||
``UA_ServerConfig_addSecurityPolicy*Ecc*()`` helpers -- are documented in
|
||||
:ref:`security-ecc`.
|
||||
+1
-1
@@ -11,7 +11,7 @@ open62541 Documentation
|
||||
client
|
||||
pubsub
|
||||
tutorials
|
||||
ecc_security
|
||||
security/index
|
||||
common
|
||||
util
|
||||
nodeset_compiler
|
||||
|
||||
Reference in New Issue
Block a user