Merge pull request #5004 from mpg/doc-psa-migration
Document PSA migration strategy
This commit is contained in:
commit
2c5fbad479
6 changed files with 1010 additions and 4 deletions
393
docs/architecture/psa-migration/psa-limitations.md
Normal file
393
docs/architecture/psa-migration/psa-limitations.md
Normal file
|
@ -0,0 +1,393 @@
|
|||
This document lists current limitations of the PSA Crypto API (as of version
|
||||
1.1) that may impact our ability to (1) use it for all crypto operations in
|
||||
TLS and X.509 and (2) support isolation of all long-term secrets in TLS (that
|
||||
is, goals G1 and G2 in [strategy.md](strategy.md) in the same directory).
|
||||
|
||||
This is supposed to be a complete list, based on a exhaustive review of crypto
|
||||
operations done in TLS and X.509 code, but of course it's still possible that
|
||||
subtle-but-important issues have been missed. The only way to be really sure
|
||||
is, of course, to actually do the migration work.
|
||||
|
||||
Limitations relevant for G1 (performing crypto operations)
|
||||
==========================================================
|
||||
|
||||
Restartable ECC operations
|
||||
--------------------------
|
||||
|
||||
There is currently no support for that in PSA at all. API design, as well as
|
||||
implementation, would be non-trivial.
|
||||
|
||||
Currently, `MBEDTLS_USE_PSA_CRYPTO` is simply incompatible with
|
||||
`MBEDTLS_ECP_RESTARTABLE`.
|
||||
|
||||
Things that are in the API but not implemented yet
|
||||
--------------------------------------------------
|
||||
|
||||
PSA Crypto has an API for FFDH, but it's not implemented in Mbed TLS yet.
|
||||
(Regarding FFDH, see the next section as well.) See issue [3261][ffdh] on
|
||||
github.
|
||||
|
||||
[ffdh]: https://github.com/ARMmbed/mbedtls/issues/3261
|
||||
|
||||
PSA Crypto has an experimental API for EC J-PAKE, but it's not implemented in
|
||||
Mbed TLS yet. See the [EC J-PAKE follow-up EPIC][ecjp] on github.
|
||||
|
||||
[ecjp]: https://github.com/orgs/ARMmbed/projects/18#column-15836385
|
||||
|
||||
Arbitrary parameters for FFDH
|
||||
-----------------------------
|
||||
|
||||
(See also the first paragraph in the previous section.)
|
||||
|
||||
Currently, the PSA Crypto API can only perform FFDH with a limited set of
|
||||
well-know parameters (some of them defined in the spec, but implementations
|
||||
are free to extend that set).
|
||||
|
||||
TLS 1.2 (and earlier) on the other hand have the server send explicit
|
||||
parameters (P and G) in is ServerKeyExchange message. This has been found to
|
||||
be suboptimal for security, as it is prohibitively hard for the client to
|
||||
verify the strength of these parameters. This led to the development of RFC
|
||||
7919 which allows use of named groups in TLS 1.2 - however as this is only an
|
||||
extension, servers can still send custom parameters if they don't support the
|
||||
extension.
|
||||
|
||||
In TLS 1.3 the situation will be simpler: named groups are the only
|
||||
option, so the current PSA Crypto API is a good match for that. (Not
|
||||
coincidentally, the groups used by RFC 7919 and TLS 1.3 are part those defined
|
||||
in the specification.)
|
||||
|
||||
There are several options here:
|
||||
|
||||
1. Implement support for custom FFDH parameters in PSA Crypto: this would pose
|
||||
non-trivial API design problem, but most importantly seems backwards, as
|
||||
the crypto community is moving away from custom FFDH parameters.
|
||||
2. Drop the DHE-RSA and DHE-PSK key exchanges in TLS 1.2 when moving to PSA.
|
||||
3. Implement RFC 7919, support DHE-RSA and DHE-PSK only in conjunction with it
|
||||
when moving to PSA. We can modify our server so that it only selects a DHE
|
||||
ciphersuite if the client offered name FFDH groups; unfortunately
|
||||
client-side the only option is to offer named groups and break the handshake
|
||||
if the server didn't take on our offer. This is not fully satisfying, but is
|
||||
perhaps the least unsatisfying option in terms of result; it's also probably
|
||||
the one that requires the most work, but it would deliver value beyond PSA
|
||||
migration by implementing RFC 7919.
|
||||
|
||||
RSA-PSS parameters
|
||||
------------------
|
||||
|
||||
RSA-PSS signatures are defined by PKCS#1 v2, re-published as RFC 8017
|
||||
(previously RFC 3447).
|
||||
|
||||
As standardized, the signature scheme takes several parameters, in addition to
|
||||
the hash algorithm potentially used to hash the message being signed:
|
||||
- a hash algorithm used for the encoding function
|
||||
- a mask generation function
|
||||
- most commonly MGF1, which in turn is parametrized by a hash algorithm
|
||||
- a salt length
|
||||
- a trailer field - this is universally 0xBC as far as I've seen
|
||||
|
||||
Both the existing `mbedtls_` API and the PSA API support only MGF1 as the
|
||||
generation function (and only 0xBC as the trailer field), but there are
|
||||
discrepancies in handling the salt length and which of the various hash
|
||||
algorithms can differ from each other.
|
||||
|
||||
### API comparison
|
||||
|
||||
- RSA:
|
||||
- signature: `mbedtls_rsa_rsassa_pss_sign()`
|
||||
- message hashed externally
|
||||
- encoding hash = MGF1 hash (from context, or argument = message hash)
|
||||
- salt length: always using the maximum legal value
|
||||
- signature: `mbedtls_rsa_rsassa_pss_sign_ext()`
|
||||
- message hashed externally
|
||||
- encoding hash = MGF1 hash (from context, or argument = message hash)
|
||||
- salt length: specified explicitly
|
||||
- verification: `mbedtls_rsassa_pss_verify()`
|
||||
- message hashed externally
|
||||
- encoding hash = MGF1 hash (from context, or argument = message hash)
|
||||
- salt length: any valid length accepted
|
||||
- verification: `mbedtls_rsassa_pss_verify_ext()`
|
||||
- message hashed externally
|
||||
- encoding hash = MGF1 hash from dedicated argument
|
||||
- expected salt length: specified explicitly, can specify "ANY"
|
||||
- PK:
|
||||
- signature: not supported
|
||||
- verification: `mbedtls_pk_verify_ext()`
|
||||
- message hashed externally
|
||||
- encoding hash = MGF1 hash, specified explicitly
|
||||
- expected salt length: specified explicitly, can specify "ANY"
|
||||
- PSA:
|
||||
- algorithm specification:
|
||||
- hash alg used for message hashing, encoding and MGF1
|
||||
- salt length can be either "standard" (<= hashlen, see note) or "any"
|
||||
- signature generation:
|
||||
- salt length: always <= hashlen (see note) and random salt
|
||||
- verification:
|
||||
- salt length: either <= hashlen (see note), or any depending on algorithm
|
||||
|
||||
Note: above, "<= hashlen" means that hashlen is used if possible, but if it
|
||||
doesn't fit because the key is too short, then the maximum length that fits is
|
||||
used.
|
||||
|
||||
The RSA/PK API is in principle more flexible than the PSA Crypto API. The
|
||||
following sub-sections study whether and how this matters in practice.
|
||||
|
||||
### Use in X.509
|
||||
|
||||
RFC 4055 Section 3.1 defines the encoding of RSA-PSS that's used in X.509.
|
||||
It allows independently specifying the message hash (also used for encoding
|
||||
hash), the MGF (and its hash if MGF1 is used), and the salt length (plus an
|
||||
extra parameter "trailer field" that doesn't vary in practice"). These can be
|
||||
encoded as part of the key, and of the signature. If both encoding are
|
||||
presents, all values must match except possibly for the salt length, where the
|
||||
value from the signature parameters is used.
|
||||
|
||||
In Mbed TLS, RSA-PSS parameters can be parsed and displayed for various
|
||||
objects (certificates, CRLs, CSRs). During parsing, the following properties
|
||||
are enforced:
|
||||
- the extra "trailer field" parameter must have its default value
|
||||
- the mask generation function is MGF1
|
||||
- encoding hash = message hashing algorithm (may differ from MGF1 hash)
|
||||
|
||||
When it comes to cryptographic operations, only two things are supported:
|
||||
- verifying the signature on a certificate from its parent;
|
||||
- verifying the signature on a CRL from the issuing CA.
|
||||
|
||||
The verification is done using `mbedtls_pk_verify_ext()`.
|
||||
|
||||
Note: since X.509 parsing ensures that message hash = encoding hash, and
|
||||
`mbedtls_pk_verify_ext()` use encoding hash = mgf1 hash, it looks like all
|
||||
three hash algorithms must be equal, which would be good news as it would
|
||||
match a limitation of the PSA API.
|
||||
|
||||
It is unclear what parameters people use in practice. It looks like by default
|
||||
OpenSSL picks saltlen = keylen - hashlen - 2 (tested with openssl 1.1.1f).
|
||||
The `certool` command provided by GnuTLS seems to be picking saltlen = hashlen
|
||||
by default (tested with GnuTLS 3.6.13). FIPS 186-4 requires 0 <= saltlen <=
|
||||
hashlen.
|
||||
|
||||
### Use in TLS
|
||||
|
||||
In TLS 1.2 (or lower), RSA-PSS signatures are never used, except via X.509.
|
||||
|
||||
In TLS 1.3, RSA-PSS signatures can be used directly in the protocol (in
|
||||
addition to indirect use via X.509). It has two sets of three signature
|
||||
algorithm identifiers (for SHA-256, SHA-384 and SHA-512), depending of what
|
||||
the OID of the public key is (rsaEncryption or RSASSA-PSS).
|
||||
|
||||
In both cases, it specifies that:
|
||||
- the mask generation function is MGF1
|
||||
- all three hashes are equal
|
||||
- the length of the salt MUST be equal to the length of the digest algorithm
|
||||
|
||||
When signing, the salt length picked by PSA is the one required by TLS 1.3
|
||||
(unless the key is unreasonably small).
|
||||
|
||||
When verifying signatures, PSA will by default enforce the salt len is the one
|
||||
required by TLS 1.3.
|
||||
|
||||
### Current testing - X509
|
||||
|
||||
All test files use the default trailer field of 0xBC, as enforced by our
|
||||
parser. (There's a negative test for that using the
|
||||
`x509_parse_rsassa_pss_params` test function and hex data.)
|
||||
|
||||
Files with "bad" in the name are expected to be invalid and rejected in tests.
|
||||
|
||||
**Test certificates:**
|
||||
|
||||
server9-bad-mgfhash.crt (announcing mgf1(sha224), signed with another mgf)
|
||||
Hash Algorithm: sha256
|
||||
Mask Algorithm: mgf1 with sha224
|
||||
Salt Length: 0xDE
|
||||
server9-bad-saltlen.crt (announcing saltlen = 0xDE, signed with another len)
|
||||
Hash Algorithm: sha256
|
||||
Mask Algorithm: mgf1 with sha256
|
||||
Salt Length: 0xDE
|
||||
server9-badsign.crt (one bit flipped in the signature)
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0xEA
|
||||
server9-defaults.crt
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0x14 (default)
|
||||
server9-sha224.crt
|
||||
Hash Algorithm: sha224
|
||||
Mask Algorithm: mgf1 with sha224
|
||||
Salt Length: 0xE2
|
||||
server9-sha256.crt
|
||||
Hash Algorithm: sha256
|
||||
Mask Algorithm: mgf1 with sha256
|
||||
Salt Length: 0xDE
|
||||
server9-sha384.crt
|
||||
Hash Algorithm: sha384
|
||||
Mask Algorithm: mgf1 with sha384
|
||||
Salt Length: 0xCE
|
||||
server9-sha512.crt
|
||||
Hash Algorithm: sha512
|
||||
Mask Algorithm: mgf1 with sha512
|
||||
Salt Length: 0xBE
|
||||
server9-with-ca.crt
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0xEA
|
||||
server9.crt
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0xEA
|
||||
|
||||
These certificates are signed with a 2048-bit key. It appears that they are
|
||||
all using saltlen = keylen - hashlen - 2, except for server9-defaults which is
|
||||
using saltlen = hashlen.
|
||||
|
||||
**Test CRLs:**
|
||||
|
||||
crl-rsa-pss-sha1-badsign.pem
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0xEA
|
||||
crl-rsa-pss-sha1.pem
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0xEA
|
||||
crl-rsa-pss-sha224.pem
|
||||
Hash Algorithm: sha224
|
||||
Mask Algorithm: mgf1 with sha224
|
||||
Salt Length: 0xE2
|
||||
crl-rsa-pss-sha256.pem
|
||||
Hash Algorithm: sha256
|
||||
Mask Algorithm: mgf1 with sha256
|
||||
Salt Length: 0xDE
|
||||
crl-rsa-pss-sha384.pem
|
||||
Hash Algorithm: sha384
|
||||
Mask Algorithm: mgf1 with sha384
|
||||
Salt Length: 0xCE
|
||||
crl-rsa-pss-sha512.pem
|
||||
Hash Algorithm: sha512
|
||||
Mask Algorithm: mgf1 with sha512
|
||||
Salt Length: 0xBE
|
||||
|
||||
These CRLs are signed with a 2048-bit key. It appears that they are
|
||||
all using saltlen = keylen - hashlen - 2.
|
||||
|
||||
**Test CSRs:**
|
||||
|
||||
server9.req.sha1
|
||||
Hash Algorithm: sha1 (default)
|
||||
Mask Algorithm: mgf1 with sha1 (default)
|
||||
Salt Length: 0x6A
|
||||
server9.req.sha224
|
||||
Hash Algorithm: sha224
|
||||
Mask Algorithm: mgf1 with sha224
|
||||
Salt Length: 0x62
|
||||
server9.req.sha256
|
||||
Hash Algorithm: sha256
|
||||
Mask Algorithm: mgf1 with sha256
|
||||
Salt Length: 0x5E
|
||||
server9.req.sha384
|
||||
Hash Algorithm: sha384
|
||||
Mask Algorithm: mgf1 with sha384
|
||||
Salt Length: 0x4E
|
||||
server9.req.sha512
|
||||
Hash Algorithm: sha512
|
||||
Mask Algorithm: mgf1 with sha512
|
||||
Salt Length: 0x3E
|
||||
|
||||
These CSRss are signed with a 2048-bit key. It appears that they are
|
||||
all using saltlen = keylen - hashlen - 2.
|
||||
|
||||
### Possible courses of action
|
||||
|
||||
There's no question about what to do with TLS (any version); the only question
|
||||
is about X.509 signature verification. Options include:
|
||||
|
||||
1. Doing all verifications with `PSA_ALG_RSA_PSS_ANY_SALT` - while this
|
||||
wouldn't cause a concrete security issue, this would be non-compliant.
|
||||
2. Doing verifications with `PSA_ALG_RSA_PSS` when we're lucky and the encoded
|
||||
saltlen happens to match hashlen, and falling back to `ANY_SALT` otherwise.
|
||||
Same issue as with the previous point, except more contained.
|
||||
3. Reject all certificates with saltlen != hashlen. This includes all
|
||||
certificates generate with OpenSSL using the default parameters, so it's
|
||||
probably not acceptable.
|
||||
4. Request an extension to the PSA Crypto API and use one of the above options
|
||||
in the meantime. Such an extension seems inconvenient and not motivated by
|
||||
strong security arguments, so it's unclear whether it would be accepted.
|
||||
|
||||
HKDF: Expand not exposed on its own (TLS 1.3)
|
||||
---------------------------------------------
|
||||
|
||||
The HKDF function uses and Extract-then-Expand approch, that is:
|
||||
|
||||
HKDF(x, ...) = HKDF-Expand(HKDF-Extract(x, ...), ...)
|
||||
|
||||
Only the full HKDF function is safe in general, however there are cases when
|
||||
one case safely use the individual Extract and Expand; the TLS 1.3 key
|
||||
schedule does so. Specifically, looking at the [hierarchy of secrets][13hs]
|
||||
is seems that Expand and Extract are always chained, so that this hierarchy
|
||||
can be implemented using only the full HKDF. However, looking at the
|
||||
derivation of traffic keys (7.3) and the update mechanism (7.2) it appears
|
||||
that calls to HKDF-Expand are iterated without any intermediated call to
|
||||
HKDF-Extract : that is, the traffic keys are computed as
|
||||
|
||||
HKDF-Expand(HKDF-Expand(HKDF-Extract(...)))
|
||||
|
||||
(with possibly more than two Expands in a row with update).
|
||||
|
||||
[13hs]: https://datatracker.ietf.org/doc/html/rfc8446#page-93
|
||||
|
||||
In the short term (early 2022), we'll work around that by re-implementing HKDF
|
||||
in `ssl_tls13_keys.c` based on the `psa_mac_` APIs (for HMAC).
|
||||
|
||||
In the long term, it is desirable to extend the PSA API. See
|
||||
https://github.com/ARM-software/psa-crypto-api/issues/539
|
||||
|
||||
Limitations relevant for G2 (isolation of long-term secrets)
|
||||
============================================================
|
||||
|
||||
Custom key derivations for mixed-PSK handshake
|
||||
----------------------------------------------
|
||||
|
||||
Currently, `MBEDTLS_USE_PSA_CRYPTO` enables the new configuration function
|
||||
`mbedtls_ssl_conf_psk_opaque()` which allows a PSA-held key to be used for the
|
||||
(pure) `PSK` key exchange in TLS 1.2. This requires that the derivation of the
|
||||
Master Secret (MS) be done on the PSA side. To support this, an algorithm
|
||||
family `PSA_ALG_TLS12_PSK_TO_MS(hash_alg)` was added to PSA Crypto.
|
||||
|
||||
If we want to support key isolation for the "mixed PSK" key exchanges:
|
||||
DHE-PSK, RSA-PSK, ECDHE-PSK, where the PSK is concatenated with the result of
|
||||
a DH key agreement (resp. RSA decryption) to form the pre-master secret (PMS)
|
||||
from which the MS is derived. If the value of the PSK is to remain hidden, we
|
||||
need the derivation PSK + secondary secret -> MS to be implemented as an
|
||||
ad-hoc PSA key derivation algorithm.
|
||||
|
||||
Adding this new, TLS-specific, key derivation algorithm to PSA Crypto should
|
||||
be no harder than it was to add `PSA_ALG_TLS12_PSK_TO_MS()` but still requires
|
||||
an extension to PSA Crypto.
|
||||
|
||||
Note: looking at RFCs 4279 and 5489, it appears that the structure of the PMS
|
||||
is always the same: 2-byte length of the secondary secret, secondary secret,
|
||||
2-byte length of the PSK, PSK. So, a single key derivation algorithm should be
|
||||
able to cover the 3 key exchanges DHE-PSK, RSA-PSK and ECDHE-PSK. (That's a
|
||||
minor gain: adding 3 algorithms would not be a blocker anyway.)
|
||||
|
||||
Note: if later we want to also isolate short-term secret (G3), the "secondary
|
||||
secret" (output of DHE/ECDHE key agreement or RSA decryption) could be a
|
||||
candidate. This wouldn't be a problem as the PSA key derivation API always
|
||||
allows inputs from key slots. (Tangent: the hard part in isolating the result
|
||||
of RSA decryption would be still checking that is has the correct format:
|
||||
48 bytes, the first two matching the TLS version - note that this is timing
|
||||
sensitive.)
|
||||
|
||||
HKDF: Expand not exposed on its own (TLS 1.3)
|
||||
---------------------------------------------
|
||||
|
||||
See the section with the same name in the G1 part above for background.
|
||||
|
||||
The work-around mentioned there works well enough just for acceleration, but
|
||||
is not sufficient for key isolation or generally proper key management (it
|
||||
requires marking keys are usable for HMAC while they should only be used for
|
||||
key derivation).
|
||||
|
||||
The obvious long-term solution is to make HKDF-Expand available as a new KDF
|
||||
(in addition to the full HKDF) in PSA (with appropriate warnings in the
|
||||
documentation).
|
377
docs/architecture/psa-migration/strategy.md
Normal file
377
docs/architecture/psa-migration/strategy.md
Normal file
|
@ -0,0 +1,377 @@
|
|||
This document explains the strategy that was used so far in starting the
|
||||
migration to PSA Crypto and mentions future perspectives and open questions.
|
||||
|
||||
Goals
|
||||
=====
|
||||
|
||||
Several benefits are expected from migrating to PSA Crypto:
|
||||
|
||||
G1. Use PSA Crypto drivers when available.
|
||||
G2. Allow isolation of long-term secrets (for example, private keys).
|
||||
G3. Allow isolation of short-term secrets (for example, TLS session keys).
|
||||
G4. Have a clean, unified API for Crypto (retire the legacy API).
|
||||
G5. Code size: compile out our implementation when a driver is available.
|
||||
|
||||
Currently, some parts of (G1) and (G2) are implemented when
|
||||
`MBEDTLS_USE_PSA_CRYPTO` is enabled. For (G2) to take effect, the application
|
||||
needs to be changed to use new APIs.
|
||||
|
||||
Generally speaking, the numbering above doesn't mean that each goal requires
|
||||
the preceding ones to be completed, for example G2-G5 could be done in any
|
||||
order; however they all either depend on G1 or are just much more convenient
|
||||
if G1 is done before (note that this is not a dependency on G1 being complete,
|
||||
it's more like each bit of G2-G5 is helped by some specific bit in G1).
|
||||
|
||||
So, a solid intermediate goal would be to complete (G1) when
|
||||
`MBEDTLS_USA_PSA_CRYPTO` is enabled - that is, all crypto operations in X.509
|
||||
and TLS would be done via the PSA Crypto API.
|
||||
|
||||
Compile-time options
|
||||
====================
|
||||
|
||||
We currently have two compile-time options that are relevant to the migration:
|
||||
|
||||
- `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA
|
||||
Crypto APIs.
|
||||
- `MBEDTLS_USE_PSA_CRYPTO` - disabled by default (enabled in "full" config),
|
||||
controls usage of PSA Crypto APIs to perform operations in X.509 and TLS
|
||||
(G1 above), as well as the availability of some new APIs (G2 above).
|
||||
|
||||
The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default
|
||||
are:
|
||||
- it's incompatible with `MBEDTLS_ECP_RESTARTABLE`;
|
||||
- historical: used to be incompatible
|
||||
`MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER` (fixed early 2022, see
|
||||
<https://github.com/ARMmbed/mbedtls/issues/5259>);
|
||||
- it does not work well with `MBEDTLS_PSA_CRYPTO_CONFIG` (could compile with
|
||||
both of them, but then `MBEDTLS_PSA_CRYPTO_CONFIG` won't have the desired
|
||||
effect)
|
||||
- to avoid a hard/default dependency of TLS, X.509 and PK on
|
||||
`MBEDTLS_PSA_CRYPTO_C`, for backward compatibility reasons:
|
||||
- when `MBEDTLS_PSA_CRYPTO_C` is enabled and used, applications need to call
|
||||
`psa_crypto_init()` before TLS/X.509 uses PSA functions
|
||||
- `MBEDTLS_PSA_CRYPTO_C` has a hard depend on `MBEDTLS_ENTROPY_C ||
|
||||
MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` but it's
|
||||
currently possible to compilte TLS and X.509 without any of the options.
|
||||
Also, we can't just auto-enable `MBEDTLS_ENTROPY_C` as it doesn't build
|
||||
out of the box on all platforms, and even less
|
||||
`MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` as it requires a user-provided RNG
|
||||
function.
|
||||
|
||||
The downside of this approach is that until we feel ready to make
|
||||
`MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain
|
||||
two versions of some parts of the code: one using PSA, the other using the
|
||||
legacy APIs. However, see next section for strategies that can lower that
|
||||
cost. The rest of this section explains the reasons for the
|
||||
incompatibilities mentioned above.
|
||||
|
||||
In the medium term (writing this in early 2020), we're going to look for ways
|
||||
to make `MBEDTLS_USE_PSA_CRYPTO` non-optional (always enabled).
|
||||
|
||||
### `MBEDTLS_ECP_RESTARTABLE`
|
||||
|
||||
Currently this option controls not only the presence of restartable APIs in
|
||||
the crypto library, but also their use in the TLS and X.509 layers. Since PSA
|
||||
Crypto does not support restartable operations, there's a clear conflict: the
|
||||
TLS and X.509 layers can't both use only PSA APIs and get restartable
|
||||
behaviour.
|
||||
|
||||
Supporting this in PSA is on our roadmap (it's been requested). But it's way
|
||||
below generalizing support for `MBEDTLS_USE_PSA_CRYPTO` for “mainstream” use
|
||||
cases on our priority list. So in the medium term `MBEDTLS_ECP_RESTARTABLE` is
|
||||
incompatible with `MBEDTLS_USE_PSA_CRYPTO`.
|
||||
|
||||
Note: it is possible to make the options compatible at build time simply by
|
||||
deciding that when `USE_PSA_CRYPTO` is enabled, PSA APIs are used except if
|
||||
restartable behaviour was requested at run-time (in addition to enabling
|
||||
`MBEDTLS_ECP_RESTARTABLE` in the build).
|
||||
|
||||
### `MBEDTLS_PSA_CRYPTO_CONFIG`
|
||||
|
||||
(This section taken from a comment by Gilles.)
|
||||
|
||||
X509 and TLS code use `MBEDTLS_xxx` macros to decide whether an algorithm is
|
||||
supported. This doesn't make `MBEDTLS_USE_PSA_CRYPTO` incompatible with
|
||||
`MBEDTLS_PSA_CRYPTO_CONFIG` per se, but it makes it incompatible with most
|
||||
useful uses of `MBEDTLS_PSA_CRYPTO_CONFIG`. The point of
|
||||
`MBEDTLS_PSA_CRYPTO_CONFIG` is to be able to build a library with support for
|
||||
an algorithm through a PSA driver only, without building the software
|
||||
implementation of that algorithm. But then the TLS code would consider the
|
||||
algorithm unavailable.
|
||||
|
||||
This is tracked in https://github.com/ARMmbed/mbedtls/issues/3674 and
|
||||
https://github.com/ARMmbed/mbedtls/issues/3677. But now that I look at it with
|
||||
fresh eyes, I don't think the approach we were planning to use would actually
|
||||
works. This needs more design effort.
|
||||
|
||||
This is something we need to support eventually, and several partners want it.
|
||||
I don't know what the priority is for `MBEDTLS_USE_PSA_CRYPTO` between
|
||||
improving driver support and covering more of the protocol. It seems to me
|
||||
that it'll be less work overall to first implement a good architecture for
|
||||
`MBEDTLS_USE_PSA_CRYPTO + MBEDTLS_PSA_CRYPTO_CONFIG` and then extend to more
|
||||
protocol features, because implementing that architecture will require changes
|
||||
to the existing code and the less code there is at this point the better,
|
||||
whereas extending to more protocol features will require the same amount of
|
||||
work either way.
|
||||
|
||||
### Backward compatibility issues with making it always on
|
||||
|
||||
1. Existing applications may not be calling `psa_crypto_init()` before using
|
||||
TLS, X.509 or PK. We can try to work around that by calling (the relevant
|
||||
part of) it ourselves under the hood as needed, but that would likely require
|
||||
splitting init between the parts that can fail and the parts that can't (see
|
||||
https://github.com/ARM-software/psa-crypto-api/pull/536 for that).
|
||||
2. It's currently not possible to enable `MBEDTLS_PSA_CRYPTO_C` in
|
||||
configurations that don't have `MBEDTLS_ENTROPY_C`, and we can't just
|
||||
auto-enable the latter, as it won't build or work out of the box on all
|
||||
platforms. There are two kinds of things we'd need to do if we want to work
|
||||
around that:
|
||||
1. Make it possible to enable the parts of PSA Crypto that don't require an
|
||||
RNG (typically, public key operations, symmetric crypto, some key
|
||||
management functions (destroy etc)) in configurations that don't have
|
||||
`ENTROPY_C`. This requires going through the PSA code base to adjust
|
||||
dependencies. Risk: there may be annoying dependencies, some of which may be
|
||||
surprising.
|
||||
2. For operations that require an RNG, provide an alternative function
|
||||
accepting an explicit `f_rng` parameter (see #5238), that would be
|
||||
available in entropy-less builds. (Then code using those functions still needs
|
||||
to have one version using it, for entropy-less builds, and one version using
|
||||
the standard function, for driver support in build with entropy.)
|
||||
|
||||
See https://github.com/ARMmbed/mbedtls/issues/5156
|
||||
|
||||
Taking advantage of the existing abstractions layers - or not
|
||||
=============================================================
|
||||
|
||||
The Crypto library in Mbed TLS currently has 3 abstraction layers that offer
|
||||
algorithm-agnostic APIs for a class of algorithms:
|
||||
|
||||
- MD for messages digests aka hashes (including HMAC)
|
||||
- Cipher for symmetric ciphers (included AEAD)
|
||||
- PK for asymmetric (aka public-key) cryptography (excluding key exchange)
|
||||
|
||||
Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer.
|
||||
|
||||
These abstraction layers typically provide, in addition to the API for crypto
|
||||
operations, types and numerical identifiers for algorithms (for
|
||||
example `mbedtls_cipher_mode_t` and its values). The
|
||||
current strategy is to keep using those identifiers in most of the code, in
|
||||
particular in existing structures and public APIs, even when
|
||||
`MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3
|
||||
above, and is only potentially relevant for G4.)
|
||||
|
||||
The are multiple strategies that can be used regarding the place of those
|
||||
layers in the migration to PSA.
|
||||
|
||||
Silently call to PSA from the abstraction layer
|
||||
-----------------------------------------------
|
||||
|
||||
- Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper
|
||||
functions in the abstraction layer, that calls PSA instead of the legacy
|
||||
crypto API.
|
||||
- Upside: changes contained to a single place, no need to change TLS or X.509
|
||||
code anywhere.
|
||||
- Downside: tricky to implement if the PSA implementation is currently done on
|
||||
top of that layer (dependency loop).
|
||||
|
||||
This strategy is currently (late 2021) used for ECDSA signature
|
||||
verification in the PK layer, and could be extended to all operations in the
|
||||
PK layer.
|
||||
|
||||
This strategy is not very well suited to the Cipher layer, as the PSA
|
||||
implementation is currently done on top of that layer.
|
||||
|
||||
This strategy will probably be used for some time for the PK layer, while we
|
||||
figure out what the future of that layer is: parts of it (parse/write, ECDSA
|
||||
signatures in the format that X.509 & TLS want) are not covered by PSA, so
|
||||
they will need to keep existing in some way. Also the PK layer is also a good
|
||||
place for dispatching to either PSA or `mbedtls_xxx_restartable` while that
|
||||
part is not covered by PSA yet.
|
||||
|
||||
Replace calls for each operation
|
||||
--------------------------------
|
||||
|
||||
- For every operation that's done through this layer in TLS or X.509, just
|
||||
replace function call with calls to PSA (conditionally on `USE_PSA_CRYPTO`)
|
||||
- Upside: conceptually simple, and if the PSA implementation is currently done
|
||||
on top of that layer, avoids concerns about dependency loops.
|
||||
- Upside: opens the door to building TLS/X.509 without that layer, saving some
|
||||
code size.
|
||||
- Downside: TLS/X.509 code has to be done for each operation.
|
||||
|
||||
This strategy is currently (late 2021) used for the MD layer. (Currently only
|
||||
a subset of calling places, but will be extended to all of them.)
|
||||
|
||||
In the future (early 2022) we're going to use it for the Cipher layer as well.
|
||||
|
||||
Opt-in use of PSA from the abstraction layer
|
||||
--------------------------------------------
|
||||
|
||||
- Provide a new way to set up a context that causes operations on that context
|
||||
to be done via PSA.
|
||||
- Upside: changes mostly contained in one place, TLS/X.509 code only needs to
|
||||
be changed when setting up the context, but not when using it. In
|
||||
particular, no changes to/duplication of existing public APIs that expect a
|
||||
key to be passed as a context of this layer (eg, `mbedtls_pk_context`).
|
||||
- Upside: avoids dependency loop when PSA implemented on top of that layer.
|
||||
- Downside: when the context is typically set up by the application, requires
|
||||
changes in application code.
|
||||
|
||||
This strategy is not useful when no context is used, for example with the
|
||||
one-shot function `mbedtls_md()`.
|
||||
|
||||
There are two variants of this strategy: one where using the new setup
|
||||
function also allows for key isolation (the key is only held by PSA,
|
||||
supporting both G1 and G2 in that area), and one without isolation (the key is
|
||||
still stored outside of PSA most of the time, supporting only G1).
|
||||
|
||||
This strategy, with support for key isolation, is currently (end of 2021) used for ECDSA
|
||||
signature generation in the PK layer - see `mbedtls_pk_setup_opaque()`. This
|
||||
allows use of PSA-held private ECDSA keys in TLS and X.509 with no change to
|
||||
the TLS/X.509 code, but a contained change in the application. If could be
|
||||
extended to other private key operations in the PK layer, which is the plan as
|
||||
of early 2022.
|
||||
|
||||
This strategy, without key isolation, is also currently used in the Cipher
|
||||
layer - see `mbedtls_cipher_setup_psa()`. This allows use of PSA for cipher
|
||||
operations in TLS with no change to the application code, and a
|
||||
contained change in TLS code. (It currently only supports a subset of
|
||||
ciphers.) However, we'll move to the "Replace calls for each operation"
|
||||
strategy (early 2022), in the hope of being able to build without this layer
|
||||
in order to save some code size in the future.
|
||||
|
||||
Note: for private key operations in the PK layer, both the "silent" and the
|
||||
"opt-in" strategy can apply, and can complement each other, as one provides
|
||||
support for key isolation, but at the (unavoidable) code of change in
|
||||
application code, while the other requires no application change to get
|
||||
support for drivers, but fails to provide isolation support.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Strategies currently used with each abstraction layer:
|
||||
|
||||
- PK (for G1): silently call PSA
|
||||
- PK (for G2): opt-in use of PSA (new key type)
|
||||
- Cipher (G1):
|
||||
- late 2021: opt-in use of PSA (new setup function)
|
||||
- early 2022: moving to "replace calls at each call site"
|
||||
- MD (G1): replace calls at each call site
|
||||
|
||||
Migrating away from the legacy API
|
||||
==================================
|
||||
|
||||
This section briefly introduces questions and possible plans towards G4,
|
||||
mainly as they relate to choices in previous stages.
|
||||
|
||||
The role of the PK/Cipher/MD APIs in user migration
|
||||
---------------------------------------------------
|
||||
|
||||
We're currently taking advantage of the existing PK and Cipher layers in order
|
||||
to reduce the number of places where library code needs to be changed. It's
|
||||
only natural to consider using the same strategy (with the PK, MD and Cipher
|
||||
layers) for facilitating migration of application code.
|
||||
|
||||
Note: a necessary first step for that would be to make sure PSA is no longer
|
||||
implemented of top of the concerned layers
|
||||
|
||||
### Zero-cost compatibility layer?
|
||||
|
||||
The most favourable case is if we can have a zero-cost abstraction (no
|
||||
runtime, RAM usage or code size penalty), for example just a bunch of
|
||||
`#define`s, essentially mapping `mbedtls_` APIs to their `psa_` equivalent.
|
||||
|
||||
Unfortunately that's unlikely fully work. For example, the MD layer uses the
|
||||
same context type for hashes and HMACs, while the PSA API (rightfully) has
|
||||
distinct operation types. Similarly, the Cipher layer uses the same context
|
||||
type for unauthenticated and AEAD ciphers, which again the PSA API
|
||||
distinguishes.
|
||||
|
||||
It is unclear how much value, if any, a zero-cost compatibility layer that's
|
||||
incomplete (for example, for MD covering only hashes, or for Cipher covering
|
||||
only AEAD) or differs significantly from the existing API (for example,
|
||||
introducing new context types) would provide to users.
|
||||
|
||||
### Low-cost compatibility layers?
|
||||
|
||||
Another possibility is to keep most or all of the existing API for the PK, MD
|
||||
and Cipher layers, implemented on top of PSA, aiming for the lowest possible
|
||||
cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union
|
||||
of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()`
|
||||
would initialize the correct part, and the rest of the functions be simple
|
||||
wrappers around PSA functions. This would vastly reduce the complexity of the
|
||||
layers compared to the existing (no need to dispatch through function
|
||||
pointers, just call the corresponding PSA API).
|
||||
|
||||
Since this would still represent a non-zero cost, not only in terms of code
|
||||
size, but also in terms of maintenance (testing, etc.) this would probably
|
||||
be a temporary solution: for example keep the compatibility layers in 4.0 (and
|
||||
make them optional), but remove them in 5.0.
|
||||
|
||||
Again, this provides the most value to users if we can manage to keep the
|
||||
existing API unchanged. Their might be conflicts between this goal and that of
|
||||
reducing the cost, and judgment calls may need to be made.
|
||||
|
||||
Note: when it comes to holding public keys in the PK layer, depending on how
|
||||
the rest of the code is structured, it may be worth holding the key data in
|
||||
memory controlled by the PK layer as opposed to a PSA key slot, moving it to a
|
||||
slot only when needed (see current `ecdsa_verify_wrap` when
|
||||
`MBEDTLS_USE_PSA_CRYPTO` is defined) For example, when parsing a large
|
||||
number, N, of X.509 certificates (for example the list of trusted roots), it
|
||||
might be undesirable to use N PSA key slots for their public keys as long as
|
||||
the certs are loaded. OTOH, this could also be addressed by merging the "X.509
|
||||
parsing on-demand" (#2478), and then the public key data would be held as
|
||||
bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot
|
||||
when it's actually used.
|
||||
|
||||
Note: the PK layer actually consists of two relatively distinct parts: crypto
|
||||
operations, which will be covered by PSA, and parsing/writing (exporting)
|
||||
from/to various formats, which is currently not fully covered by the PSA
|
||||
Crypto API.
|
||||
|
||||
### Algorithm identifiers and other identifiers
|
||||
|
||||
It should be easy to provide the user with a bunch of `#define`s for algorithm
|
||||
identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of
|
||||
those would be in the MD, Cipher and PK compatibility layers mentioned above,
|
||||
but there might be some in other modules that may be worth considering, for
|
||||
example identifiers for elliptic curves.
|
||||
|
||||
### Lower layers
|
||||
|
||||
Generally speaking, we would retire all of the low-level, non-generic modules,
|
||||
such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing
|
||||
compatibility APIs for them. People would be encouraged to switch to the PSA
|
||||
API. (The compatibility implementation of the existing PK, MD, Cipher APIs
|
||||
would mostly benefit people who already used those generic APis rather than
|
||||
the low-level, alg-specific ones.)
|
||||
|
||||
### APIs in TLS and X.509
|
||||
|
||||
Public APIs in TLS and X.509 may be affected by the migration in at least two
|
||||
ways:
|
||||
|
||||
1. APIs that rely on a legacy `mbedtls_` crypto type: for example
|
||||
`mbedtls_ssl_conf_own_cert()` to configure a (certificate and the
|
||||
associated) private key. Currently the private key is passed as a
|
||||
`mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`.
|
||||
Since some users would probably still be using the compatibility PK layer, it
|
||||
would need a way to easily extract the PSA key ID from the PK context.
|
||||
|
||||
2. APIs the accept list of identifiers: for example
|
||||
`mbedtls_ssl_conf_curves()` taking a list of `mbedtls_ecp_group_id`s. This
|
||||
could be changed to accept a list of pairs (`psa_ecc_familiy_t`, size) but we
|
||||
should probably take this opportunity to move to a identifier independent from
|
||||
the underlying crypto implementation and use TLS-specific identifiers instead
|
||||
(based on IANA values or custom enums), as is currently done in the new
|
||||
`mbedtls_ssl_conf_groups()` API, see #4859).
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
An question that needs careful consideration when we come around to removing
|
||||
the low-level crypto APIs and making PK, MD and Cipher optional compatibility
|
||||
layers is to be sure to preserve testing quality. A lot of the existing test
|
||||
cases use the low level crypto APIs; we would need to either keep using that
|
||||
API for tests, or manually migrated test to the PSA Crypto API. Perhaps a
|
||||
combination of both, perhaps evolving gradually over time.
|
58
docs/architecture/psa-migration/syms.sh
Executable file
58
docs/architecture/psa-migration/syms.sh
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Purpose
|
||||
#
|
||||
# Show symbols in the X.509 and TLS libraries that are defined in another
|
||||
# libmbedtlsXXX.a library. This is usually done to list Crypto dependencies.
|
||||
#
|
||||
# Usage:
|
||||
# - build the library with debug symbols and the config you're interested in
|
||||
# (default, full minus MBEDTLS_USE_PSA_CRYPTO, full, etc.)
|
||||
# - run this script with the name of your config as the only argument
|
||||
|
||||
set -eu
|
||||
|
||||
# list mbedtls_ symbols of a given type in a static library
|
||||
syms() {
|
||||
TYPE="$1"
|
||||
FILE="$2"
|
||||
|
||||
nm "$FILE" | sed -n "s/[0-9a-f ]*${TYPE} \(mbedtls_.*\)/\1/p" | sort -u
|
||||
}
|
||||
|
||||
# create listings for the given library
|
||||
list() {
|
||||
NAME="$1"
|
||||
FILE="library/libmbed${NAME}.a"
|
||||
PREF="${CONFIG}-$NAME"
|
||||
|
||||
syms '[TRrD]' $FILE > ${PREF}-defined
|
||||
syms U $FILE > ${PREF}-unresolved
|
||||
|
||||
diff ${PREF}-defined ${PREF}-unresolved \
|
||||
| sed -n 's/^> //p' > ${PREF}-external
|
||||
sed 's/mbedtls_\([^_]*\).*/\1/' ${PREF}-external \
|
||||
| uniq -c | sort -rn > ${PREF}-modules
|
||||
|
||||
rm ${PREF}-defined ${PREF}-unresolved
|
||||
}
|
||||
|
||||
CONFIG="${1:-unknown}"
|
||||
|
||||
list x509
|
||||
list tls
|
80
docs/architecture/psa-migration/tasks-g2.md
Normal file
80
docs/architecture/psa-migration/tasks-g2.md
Normal file
|
@ -0,0 +1,80 @@
|
|||
This document is temporary; it lists tasks to achieve G2 as described in
|
||||
`strategy.md` while the strategy is being reviewed - once that's done,
|
||||
corresponding github issues will be created and this document removed.
|
||||
|
||||
For all of the tasks here, specific testing (integration and unit test depending
|
||||
on the task) is required, see `testing.md`.
|
||||
|
||||
RSA Signature operations
|
||||
========================
|
||||
|
||||
In PK
|
||||
-----
|
||||
|
||||
### Modify existing `PK_OPAQUE` type to allow for RSA keys
|
||||
|
||||
- the following must work and be tested: `mbedtls_pk_get_type()`,
|
||||
`mbedtls_pk_get_name()`, `mbedtls_pk_get_bitlen()`, `mbedtls_pk_get_len()`,
|
||||
`mbedtls_pk_can_do()`.
|
||||
- most likely adapt `pk_psa_genkey()` in `test_suite_pk.function`.
|
||||
- all other function (sign, verify, encrypt, decrypt, check pair, debug) will
|
||||
return `MBEDTLS_ERR_PK_TYPE_MISMATCH` and this will be tested too.
|
||||
|
||||
### Modify `mbedtls_pk_wrap_as_opaque()` to work with RSA.
|
||||
|
||||
- OK to have policy hardcoded on signing with PKCS1v1.5, or allow more if
|
||||
available at this time
|
||||
|
||||
### Modify `mbedtls_pk_write_pubkey_der()` to work with RSA-opaque.
|
||||
|
||||
- OK to just test that a generated key (with `pk_psa_genkey()`) can be
|
||||
written, without checking for correctness of the result - this will be
|
||||
tested as part of another task
|
||||
|
||||
### Make `mbedtls_pk_sign()` work with RSA-opaque.
|
||||
|
||||
- testing may extend `pk_psa_sign()` in `test_suite_pk_function` by adding
|
||||
selector for ECDSA/RSA.
|
||||
|
||||
In X.509
|
||||
--------
|
||||
|
||||
### Test using RSA-opaque for CSR generation
|
||||
|
||||
- similar to what's already done with ECDSA-opaque
|
||||
|
||||
### Test using opaque keys for Certificate generation
|
||||
|
||||
- similar to what's done with testing CSR generation
|
||||
- should test both RSA and ECDSA as ECDSA is not tested yet
|
||||
- might require slight code adaptations, even if unlikely
|
||||
|
||||
|
||||
In TLS
|
||||
------
|
||||
|
||||
### Test using RSA-opaque for TLS client auth
|
||||
|
||||
- similar to what's already done with ECDSA-opaque
|
||||
|
||||
### Test using RSA-opaque for TLS server auth
|
||||
|
||||
- similar to what's already done with ECDSA-opaque
|
||||
- key exchanges: ECDHE-RSA and DHE-RSA
|
||||
|
||||
RSA decrypt
|
||||
===========
|
||||
|
||||
### Extend `PK_OPAQUE` to allow RSA decryption (PKCS1 v1.5)
|
||||
|
||||
### Test using that in TLS for RSA and RSA-PSK key exchange.
|
||||
|
||||
Support opaque PSKs for "mixed-PSK" key exchanges
|
||||
=================================================
|
||||
|
||||
See `PSA-limitations.md`.
|
||||
|
||||
Possible split:
|
||||
- one task to extend PSA (see `PSA-limitations.md`)
|
||||
- then one task per handshake: DHE-PSK, ECDHE-PSK, RSA-PSK (with tests for
|
||||
each)
|
99
docs/architecture/psa-migration/testing.md
Normal file
99
docs/architecture/psa-migration/testing.md
Normal file
|
@ -0,0 +1,99 @@
|
|||
Testing strategy for `MBEDTLS_USE_PSA_CRYPTO`
|
||||
=============================================
|
||||
|
||||
This document records the testing strategy used so far in implementing
|
||||
`MBEDTLS_USE_PSA_CRYPTO`.
|
||||
|
||||
|
||||
General considerations
|
||||
----------------------
|
||||
|
||||
There needs to be at least one build in `all.sh` that enables
|
||||
`MBEDTLS_USE_PSA_CRYPTO` and runs the full battery of tests; currently that's
|
||||
ensured by the fact that `scripts/config.py full` enables
|
||||
`MBEDTLS_USE_PSA_CRYPTO`. There needs to be at least one build with
|
||||
`MBEDTLS_USE_PSA_CRYPTO` disabled (as long as it's optional); currently that's
|
||||
ensured by the fact that it's disabled in the default config.
|
||||
|
||||
Generally, code review is enough to ensure that PSA APIs are indeed used where
|
||||
they should be when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
|
||||
|
||||
However, when it comes to TLS, we also have the option of using debug messages
|
||||
to confirm which code path is taken. This is generally unnecessary, except when
|
||||
a decision is made at run-time about whether to use the PSA or legacy code
|
||||
path. For example, for record protection, currently some ciphers are supported
|
||||
via PSA while some others aren't, with a run-time fallback. In this case, it's
|
||||
good to have a debug message checked by the test case to confirm that the
|
||||
right decision was made at run-time, i. e. that we didn't use the fallback for
|
||||
ciphers that are supposed to be supported.
|
||||
|
||||
|
||||
New APIs meant for application use
|
||||
----------------------------------
|
||||
|
||||
For example, `mbedtls_pk_setup_opaque()` is meant to be used by applications
|
||||
in order to create PK contexts that can then be passed to existing TLS and
|
||||
X.509 APIs (which remain unchanged).
|
||||
|
||||
In that case, we want:
|
||||
|
||||
- unit testing of the new API and directly-related APIs - for example:
|
||||
- in `test_suite_pk` we have a new test function `pk_psa_utils` that exercises
|
||||
`mbedtls_pk_setup_opaque()` and checks that various utility functions
|
||||
(`mbedtls_pk_get_type()` etc.) work and the functions that are expected to
|
||||
fail (`mbedtls_pk_verify()` etc) return the expected error.
|
||||
- in `test_suite_pk` we modified the existing `pk_psa_sign` test function to
|
||||
check that signature generation works as expected
|
||||
- in `test_suite_pkwrite` we should have a new test function checking that
|
||||
exporting (writing out) the public part of the key works as expected and
|
||||
that exporting the private key fails as expected.
|
||||
- integration testing of the new API with each existing API which should
|
||||
accepts a context created this way - for example:
|
||||
- in `programs/ssl/ssl_client2` a new option `key_opaque` that causes the
|
||||
new API to be used, and one or more tests in `ssl-opt.sh` using that.
|
||||
(We should have the same server-side.)
|
||||
- in `test_suite_x509write` we have a new test function
|
||||
`x509_csr_check_opaque()` checking integration of the new API with the
|
||||
existing `mbedtls_x509write_csr_set_key()`.
|
||||
(We should have something similar for
|
||||
`mbedtls_x509write_crt_set_issuer_key()`.)
|
||||
|
||||
For some APIs, for example with `mbedtls_ssl_conf_psk_opaque()`, testing in
|
||||
`test_suite_ssl` was historically not possible, so we only have testing in
|
||||
`ssl-opt.sh`.
|
||||
|
||||
New APIs meant for internal use
|
||||
-------------------------------
|
||||
|
||||
For example, `mbedtls_cipher_setup_psa()` is meant to be used by the TLS
|
||||
layer, but probably not directly by applications.
|
||||
|
||||
In that case, we want:
|
||||
|
||||
- unit testing of the new API and directly-related APIs - for example:
|
||||
- in `test_suite_cipher`, the existing test functions `auth_crypt_tv` and
|
||||
`test_vec_crypt` gained a new parameter `use_psa` and corresponding test
|
||||
cases
|
||||
- integration testing:
|
||||
- usually already covered by existing tests for higher-level modules:
|
||||
- for example simple use of `mbedtls_cipher_setup_psa()` in TLS is already
|
||||
covered by running the existing TLS tests in a build with
|
||||
`MBEDTLS_USA_PSA_CRYPTO` enabled
|
||||
- however if use of the new API in higher layers involves more logic that
|
||||
use of the old API, specific integrations test may be required
|
||||
- for example, the logic to fall back from `mbedtls_cipher_setup_psa()` to
|
||||
`mbedtls_cipher_setup()` in TLS is tested by `run_test_psa` in
|
||||
`ssl-opt.sh`.
|
||||
|
||||
Internal changes
|
||||
----------------
|
||||
|
||||
For example, use of PSA to compute the TLS 1.2 PRF.
|
||||
|
||||
Changes in this category rarely require specific testing, as everything should
|
||||
be already be covered by running the existing tests in a build with
|
||||
`MBEDTLS_USE_PSA_CRYPTO` enabled; however we need to make sure the existing
|
||||
test have sufficient coverage, and improve them if necessary.
|
||||
|
||||
However, if additional logic is involved, or there are run-time decisions about
|
||||
whether to use the PSA or legacy code paths, specific tests might be in order.
|
|
@ -59,10 +59,9 @@ this is supported on both sides, it's currently only tested client-side);
|
|||
- `mbedtls_x509write_csr_set_key()` to generate a CSR (certificate signature
|
||||
request).
|
||||
|
||||
In the TLS and X.509 API, there are two other functions which accept a key or
|
||||
keypair as a PK context: `mbedtls_x509write_crt_set_subject_key()` and
|
||||
`mbedtls_x509write_crt_set_issuer_key()`. Use of opaque contexts here probably
|
||||
works but is so far untested.
|
||||
In the TLS and X.509 API, there's one other function which accepts a keypair
|
||||
as a PK context: `mbedtls_x509write_crt_set_issuer_key()`. Use of opaque
|
||||
contexts here probably works but is so far untested.
|
||||
|
||||
### PSA-held (opaque) keys for TLS pre-shared keys (PSK)
|
||||
|
||||
|
|
Loading…
Reference in a new issue