Hi Beat,
This is still an open point in the design.
It's clear that some back-and-forth is needed. An accelerator needing a
source of randomness is a good example. In some cases, it's possible to
have the core call a deterministic function in the driver, for example
accelerated RSA-PSS can often be broken down into the RSA exponentiation
(accelerated) and PSS padding (unaccelerated except maybe for the hash
calculations, done by the core). This kind of scenario calls for
additional entry points in the driver, which has the advantage of not
requiring any control inversion. These additional entry points are
evoked under “substitution points” in the specification draft.
However, other cases cannot be done this way, for example if a driver
needs a random generator to perform blinding. Other examples include an
opaque driver using a local cipher to encrypt communication with a
secure element over an insecure bus, or a driver loading an auxiliary
firmware image and verifying its signature. These cases are varied
enough that I think it must be possible for drivers to call any API
function. But as you note this may cause reentrancy problems, so there
should be some limitations.
It's not clear to me at this stage what the limitations should be. For
example, what rules would facilitate static bounds on stack usage? Can
the rules be enforced cheaply at runtime, and are violations likely to
be detected by unit tests? Can the rules realistically be validated by
static analysis?
The exact manner in which drivers might call core functions is also
open. Are there additional auxiliary functions that the core should
expose (for example, might a driver prefer to have the core expose
rsa_pss_pad())? The functions that the driver sees are not necessarily
the same that the functions that applications see (at the very least,
they're different on platforms where applications run in their own
memory space and PSA API calls are remote procedure calls, whereas
drivers live in the crypto service's memory space). So they can't be
guaranteed to have the same symbol name. Types like psa_key_id_t and
psa_key_attributes_t may be different in applications and in drivers as
well.
I expect it's going to take a while to converge on all of these open
questions. As the use cases are diverse, feedback is very welcome.
--
Gilles Peskine
PSA Crypto architect and Mbed TLS developer
On 07/05/2021 10:55, Beat Heeb via psa-crypto wrote:
> Hi,
>
> It is unclear whether drivers are allowed to call functions of the outer PSA crypto interface.
> If this is allowed, strict rules are needed to avoid hard to find recursive invocation and reentrancy problems.
> Such problems are not necessarily detected at development time because they may be caused by a combination of several drivers developed by different vendors.
> The easiest and most secure way would be to prohibit such calls completely.
> However, at least in one case they are unavoidable:
> Several driver functions need a source of randomness to fill some random values (cipher_encrypt, RSA_PSS, non-deterministic ECDSA, ..).
> Getting randomness is non-trivial and involves special hardware in most cases which is usually not accessible to any driver (in particular accelerators).
> So drivers must be allowed to call at least psa_generate_random().
> The only alternative would be to split up all affected functions to separate randomness generation from cryptographic calculations.
> Regards
> Beat
>
Hi,
It is unclear whether drivers are allowed to call functions of the outer PSA crypto interface.
If this is allowed, strict rules are needed to avoid hard to find recursive invocation and reentrancy problems.
Such problems are not necessarily detected at development time because they may be caused by a combination of several drivers developed by different vendors.
The easiest and most secure way would be to prohibit such calls completely.
However, at least in one case they are unavoidable:
Several driver functions need a source of randomness to fill some random values (cipher_encrypt, RSA_PSS, non-deterministic ECDSA, ..).
Getting randomness is non-trivial and involves special hardware in most cases which is usually not accessible to any driver (in particular accelerators).
So drivers must be allowed to call at least psa_generate_random().
The only alternative would be to split up all affected functions to separate randomness generation from cryptographic calculations.
Regards
Beat
Hello,
There is no security boundary between the crypto core and drivers, so
you can assume that all pointers are valid (including the fact that
they're non-null, except possibly for 0-size buffers).
You can also assume that the multipart operations follow a valid
sequence (setup-update-update...-finish, or whatever is suitable for the
operation type), and that every operation is eventually finished or
aborted. Do however keep in mind that different operations can be
interspersed (setup(op1); setup(op2); update(op1); update(op2); ...).
The validity of buffer sizes and cryptographic data is less clear-cut.
It's definitely one of the areas that needs to be clarified before this
specification reaches a final stage. In general, it's better if the core
validates everything it can: it saves effort overall since there are far
fewer core implementers than driver implementers, it allows the
validation to be tested generically, it guarantees that the behavior is
the same everywhere. However, there are also integration reasons to have
the driver do validation. If the core is responsible for validation then
yo can't have a driver for an algorithm that the core doesn't support,
which is useful especially with secure elements. There's also some
validation that benefits from acceleration, for example checking that
the public key is a curve point before performing an ECDH operation. The
driver specification should be explicit as to who checks what (we
definitely must not end up with each side thinking that the other side
will do it). But at this stage I don't know yet where the limit must be.
Best regards,
--
Gilles Peskine
PSA crypto architect and Mbed TLS developer
On 06/05/2021 13:39, Beat Heeb via psa-crypto wrote:
> Hi,
>
> The Unified Driver Specification should state which precondition checks are needed in a driver function.
> It would be redundant to do all validity checks in both the core and the drivers.
> From the samples it seems to be safe to assume all pointer arguments are non-null.
> What about sizes?
> Is it safe to assume only valid key sizes are delivered to a driver?
> (For instance only 192, 224, 256, 384 or 521 for PSA_ECC_CURVE_SECP_R1.)
> Is it guaranteed that the key_length is always correct for the given bit size of the key?
> (For instance key_length is always 32 for a 256 bit SECP_R1 secret key.)
> What about the sequence of function calls for a multi-part interface?
> Is a driver expected to check for out-of-sequence calls and return PSA_ERROR_BAD_STATE?
>
> Thanks for clarifications.
> Regards
> Beat Heeb
Hi,
The Unified Driver Specification should state which precondition checks are needed in a driver function.
It would be redundant to do all validity checks in both the core and the drivers.
>From the samples it seems to be safe to assume all pointer arguments are non-null.
What about sizes?
Is it safe to assume only valid key sizes are delivered to a driver?
(For instance only 192, 224, 256, 384 or 521 for PSA_ECC_CURVE_SECP_R1.)
Is it guaranteed that the key_length is always correct for the given bit size of the key?
(For instance key_length is always 32 for a 256 bit SECP_R1 secret key.)
What about the sequence of function calls for a multi-part interface?
Is a driver expected to check for out-of-sequence calls and return PSA_ERROR_BAD_STATE?
Thanks for clarifications.
Regards
Beat Heeb