Inline check_pair functions #580

Merged
bjwtaylor merged 43 commits from inline-check_pair into development 2026-01-27 08:27:44 -06:00
bjwtaylor commented 2025-11-21 05:41:32 -06:00 (Migrated from github.com)

Description

Inline check_pair functions resolves https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/521

PR checklist

  • changelog not required because: No public changes
  • framework PR not required
  • mbedtls development PR not required because: No changes
  • mbedtls 3.6 PRnot required because: No changes
  • tests provided
## Description Inline check_pair functions resolves https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/521 ## PR checklist - [x] **changelog** not required because: No public changes - [x] **framework PR** not required - [x] **mbedtls development PR** not required because: No changes - [x] **mbedtls 3.6 PR**not required because: No changes - **tests** provided
gilles-peskine-arm (Migrated from github.com) reviewed 2025-11-21 05:41:32 -06:00
davidhorstmann-arm (Migrated from github.com) reviewed 2025-12-10 08:39:56 -06:00
davidhorstmann-arm (Migrated from github.com) left a comment
No description provided.
A few small things and questions, but looks good otherwise!
davidhorstmann-arm commented 2025-12-10 08:50:08 -06:00 (Migrated from github.com)
Module Base This PR Delta % Delta
pk 3963 4043 +80 +2.02%
pk_wrap 2090 1958 -132 -6.32%
TOTAL 209749 209697 -52 -0.02%

52B code size reduction, thanks!

| Module | Base | This PR | Delta | % Delta | | ---- | ---- | ---- | ---- | ---- | pk | 3963 | 4043 | +80 | +2.02% | pk_wrap | 2090 | 1958 | -132 | -6.32% | TOTAL | 209749 | 209697 | -52 | -0.02% | 52B code size reduction, thanks!
bjwtaylor (Migrated from github.com) reviewed 2026-01-08 08:48:11 -06:00
@ -1070,2 +1049,2 @@
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
}
TEST_EQUAL(mbedtls_pk_wrap_psa(&prv, wrapped_key_id), 0);
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), expected_ret);
bjwtaylor (Migrated from github.com) commented 2026-01-08 08:48:11 -06:00

So, this was because the previous implementation was able to check the function pointer to check_pair in the structure to see if it was supported. With the new architecture this isn't available, so it progresses further before failing with a different error. You make a good point though, so I've added additional logic to return the same error as before.

So, this was because the previous implementation was able to check the function pointer to check_pair in the structure to see if it was supported. With the new architecture this isn't available, so it progresses further before failing with a different error. You make a good point though, so I've added additional logic to return the same error as before.
bjwtaylor (Migrated from github.com) reviewed 2026-01-08 09:22:40 -06:00
bjwtaylor (Migrated from github.com) commented 2026-01-08 09:22:40 -06:00

Yes, this is a good point. I've removed the type check.

Yes, this is a good point. I've removed the type check.
bjwtaylor (Migrated from github.com) reviewed 2026-01-08 09:23:03 -06:00
bjwtaylor (Migrated from github.com) commented 2026-01-08 09:23:02 -06:00

I've replaced these calls with the new mbedtls_pk_get_key_type function.

I've replaced these calls with the new mbedtls_pk_get_key_type function.
mpg (Migrated from github.com) reviewed 2026-01-15 05:49:58 -06:00
@ -1070,2 +1049,2 @@
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
}
TEST_EQUAL(mbedtls_pk_wrap_psa(&prv, wrapped_key_id), 0);
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), expected_ret);
mpg (Migrated from github.com) commented 2026-01-15 05:49:58 -06:00

My expectation is that with the new implementation it should progress further to success, not to a different error.

I don't care a lot about adding support for wrapped RSA keys, I only suggested it because I though it would be easy. So I'm OK if we keep erroring out on wrapped RSA keys.

OTOH, I do care quite a lot about understanding how our code works, and so far I have no idea why wrapped RSA is giving this error. I wouldn't like us to merge this PR without understanding that.

To re-iterate, deciding that we don't add support for RSA keys after all is OK with me, but making that decision without fully understanding why the obvious implementation doesn't work would not make me happy.

My expectation is that with the new implementation it should progress further to success, not to a different error. I don't care a lot about adding support for wrapped RSA keys, I only suggested it because I though it would be easy. So I'm OK if we keep erroring out on wrapped RSA keys. OTOH, I do care quite a lot about understanding how our code works, and so far I have no idea why wrapped RSA is giving this error. I wouldn't like us to merge this PR without understanding that. To re-iterate, deciding that we don't add support for RSA keys after all is OK with me, but making that decision without fully understanding why the obvious implementation doesn't work would not make me happy.
mpg (Migrated from github.com) reviewed 2026-01-15 05:57:09 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
mpg (Migrated from github.com) commented 2026-01-15 05:57:08 -06:00

Why do we need to do that? We should already have the serialized public key of the prv context in prv->pub_raw and be able to using without messing with export or anything. Why are you not using the implementation suggested by Gilles?

The plan was that Gilles's suggestion (turned form pseudo-code to actual code, see following comments) would be the entire implementation of the function, ie right after the initial NULL checks we'd directly have return <the expression in Gilles's> comment (or something equivalent).

Again, I don't mind deviating from the original plan, but if we do, I want to understand why.

Why do we need to do that? We should already have the serialized public key of the `prv` context in `prv->pub_raw` and be able to using without messing with export or anything. Why are you not using the implementation [suggested by Gilles](https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/521#issuecomment-3401958915)? The plan was that Gilles's suggestion (turned form pseudo-code to actual code, see following comments) would be the entire implementation of the function, ie right after the initial NULL checks we'd directly have `return <the expression in Gilles's> comment` (or something equivalent). Again, I don't mind deviating from the original plan, but if we do, I want to understand why.
bjwtaylor (Migrated from github.com) reviewed 2026-01-15 05:58:13 -06:00
@ -1070,2 +1049,2 @@
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
}
TEST_EQUAL(mbedtls_pk_wrap_psa(&prv, wrapped_key_id), 0);
TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), expected_ret);
bjwtaylor (Migrated from github.com) commented 2026-01-15 05:58:13 -06:00

So, this comment was prior to the decision to enable wrapped RSA keys. I think these should now work, though I'm still testing and developing the latest version.

So, this comment was prior to the decision to enable wrapped RSA keys. I think these should now work, though I'm still testing and developing the latest version.
bjwtaylor (Migrated from github.com) reviewed 2026-01-16 01:48:17 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-16 01:48:17 -06:00

Not sure, I'm implementing it as per above now though.

Not sure, I'm implementing it as per above now though.
bjwtaylor (Migrated from github.com) reviewed 2026-01-16 04:05:17 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-16 04:05:17 -06:00

Ok, think I might have come across the reason. So for the current plan to work we assume that the the supplied context already has the exported public key supplied, so the caller has to call something like mbedtls_pk_parse_keyfile() and then mbedtls_pk_set_pubkey_from_prv(). However in the original implementation I was assuming that this was not the case and allowing for use case where mbedtls_pk_set_pubkey_from_prv() had not been called. In this case the pubkey context is blank and therefore we can't check it. Admittedly it would be better to call mbedtls_pk_set_pubkey_from_prv(), rather than export and calloc. So this is a fair point. @gilles-peskine-arm whilst Manuel is on holiday, am I safe to assume the public key has been exported into the context? Or do I need to export it prior to attempting the check pair functionality?

Ok, think I might have come across the reason. So for the current plan to work we assume that the the supplied context already has the exported public key supplied, so the caller has to call something like mbedtls_pk_parse_keyfile() and then mbedtls_pk_set_pubkey_from_prv(). However in the original implementation I was assuming that this was not the case and allowing for use case where mbedtls_pk_set_pubkey_from_prv() had not been called. In this case the pubkey context is blank and therefore we can't check it. Admittedly it would be better to call mbedtls_pk_set_pubkey_from_prv(), rather than export and calloc. So this is a fair point. @gilles-peskine-arm whilst Manuel is on holiday, am I safe to assume the public key has been exported into the context? Or do I need to export it prior to attempting the check pair functionality?
gilles-peskine-arm (Migrated from github.com) reviewed 2026-01-16 04:38:10 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
gilles-peskine-arm (Migrated from github.com) commented 2026-01-16 04:38:10 -06:00

I haven't followed the evolution of pk last quarter, but I believe that was part the goal: to make the handling of different cases uniform, including keeping the public key in the context in all cases. (Why would we waste MBEDTLS_PK_MAX_PUBKEY_RAW_LEN bytes in the pk context if it's not to use them?)

I haven't followed the evolution of pk last quarter, but I believe that was part the goal: to make the handling of different cases uniform, including keeping the public key in the context in all cases. (Why would we waste `MBEDTLS_PK_MAX_PUBKEY_RAW_LEN` bytes in the pk context if it's not to use them?)
bjwtaylor (Migrated from github.com) reviewed 2026-01-16 05:14:35 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-16 05:14:35 -06:00

So, I've probably been following it closer than you have. Though unfortunately this one only came up when Manuel mentioned it. So the issue is that all the the check_pair functions currently don't assume the public key is exported prior to being called. So if you call them after the context is populated with the private key using a function like mbedtls_pk_parse_keyfile() they will still succeed, as they will just export the public key from the private one. In the implementation suggested we are assuming the key has been exported and therefore don't bother to export it again. I think this is sensible, as you say why would we waste the bytes? Though the issue is this is a change to the API of check_pair and might break things, if other parts of the system/existing users are assuming you don't need to populate the public key for this to work. A basic run of the test suite seems to succeed with this change, so we might be ok. It's difficult to know for sure though. What do you think, is this change ok?

So, I've probably been following it closer than you have. Though unfortunately this one only came up when Manuel mentioned it. So the issue is that all the the check_pair functions currently don't assume the public key is exported prior to being called. So if you call them after the context is populated with the private key using a function like mbedtls_pk_parse_keyfile() they will still succeed, as they will just export the public key from the private one. In the implementation suggested we are assuming the key has been exported and therefore don't bother to export it again. I think this is sensible, as you say why would we waste the bytes? Though the issue is this is a change to the API of check_pair and might break things, if other parts of the system/existing users are assuming you don't need to populate the public key for this to work. A basic run of the test suite seems to succeed with this change, so we might be ok. It's difficult to know for sure though. What do you think, is this change ok?
gilles-peskine-arm (Migrated from github.com) reviewed 2026-01-16 09:41:21 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
gilles-peskine-arm (Migrated from github.com) commented 2026-01-16 09:41:21 -06:00

all the the check_pair functions currently don't assume the public key is exported prior to being called.

The check_pair function assumes a valid pk context (if one is in unpopulated it will reliably return an error). It's not something that gets called internally while constructing a context. Is there a way for a valid, populated pk context containing a key pair not to have the pub_raw field filled? AFAIK there isn't: all ways of populating a pk context with a private key call mbedtls_pk_set_pubkey_from_prv.

other parts of the system/existing users are assuming you don't need to populate the public key for this to work.

You can search the code of pk*.c to see if pk calls check_pair internally. It doesn't. Any other code can't populate the PK object itself, it has to rely on one of the public functions in pk.h. And AFAICT they do. The documentation of the pub_raw field doesn't mention any restriction.

So yes, please change check_pair to the simple implementation where it assumes that the pub_raw field is populated. If there's a case where it doesn't work and we have adequate test coverage (which I haven't checked), that would have to be an edge case that we haven't thought of testing, and the fix would be to populate pub_raw in that edge case.

> all the the check_pair functions currently don't assume the public key is exported prior to being called. The `check_pair` function assumes a valid pk context (if one is in unpopulated it will reliably return an error). It's not something that gets called internally while constructing a context. Is there a way for a valid, populated pk context containing a key pair not to have the `pub_raw` field filled? AFAIK there isn't: all ways of populating a pk context with a private key call `mbedtls_pk_set_pubkey_from_prv`. > other parts of the system/existing users are assuming you don't need to populate the public key for this to work. You can search the code of `pk*.c` to see if pk calls `check_pair` internally. It doesn't. Any other code can't populate the PK object itself, it has to rely on one of the public functions in `pk.h`. And AFAICT they do. The documentation of the `pub_raw` field doesn't mention any restriction. So yes, please change `check_pair` to the simple implementation where it assumes that the `pub_raw` field is populated. If there's a case where it doesn't work and we have adequate test coverage (which I haven't checked), that would have to be an edge case that we haven't thought of testing, and the fix would be to populate `pub_raw` in that edge case.
bjwtaylor (Migrated from github.com) reviewed 2026-01-19 01:48:45 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-19 01:48:45 -06:00

OK, sounds good. I'll update it assuming that it is populated and return an error if it's not.

OK, sounds good. I'll update it assuming that it is populated and return an error if it's not.
bjwtaylor commented 2026-01-19 07:48:30 -06:00 (Migrated from github.com)

Apologies for the force push, however it was necessary to add a missed DCO.

Apologies for the force push, however it was necessary to add a missed DCO.
bjwtaylor commented 2026-01-19 08:06:31 -06:00 (Migrated from github.com)

Updated as per Manuel's test plan, Test report as follows:

<html> <head> </head>
Reference Test case Commit
MTC1 Correct documentation to remove failure on wrapped RSA https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/fe3e39a5f5980ad323f6515230a57ed27eac9d03
MTC2 Return PSA_ERROR_INVALID_ARGUMENT if the contect is invalid. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/e63eef4ca78df616a9f080285ed6c61151bd9cba
MTC3 pk_psa_utils(): check that it fails with "opaque" (wrapping) contexts (RSA,ECC) -> no longer relevant, remove that. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/bc6407f162dddd6bef748a7519f2ad05466f1cda
MTC4 pk_psa_utils:: no longer relevant, we're removing check_pair() from here,see above. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/bc6407f162dddd6bef748a7519f2ad05466f1cda
MTC5 newly supported case: prv is wrapping RSA -> just adjust existing code inmbedtls_pk_check_pair() so that RSA keys are tested the same as ECC keys(actually a simplification, no longer need to distinguish ECC vs RSA). https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/1a6c7dcf7b2ecbec350e45dd6f22b6334ab88ba7
MTC6 public key was created with copy_public_from_psa -> extendpk_copy_from_psa_success() to also call check_pair on the existingcontexts pk_priv_copy_public and pk_pub_copy_public in addition to theexisting call. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/b22cc698e175c76d005a616a4c225fd29b63cb0c
MTC7 pub or prv hasn't been populated -> add an empty context inthe existing test function mbedtls_pk_check_pair(), add calls with (pub,empty) and (empty, prv) and always expect failure (in addition to normaltesting that can either succeed or fail depending on the data). https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/1c5e1b70f17ffe1cbb22101eb8da53294cb6b114
MTC8 The function expects (pub, prv) -> what if we pass (pub, pub), (prv, pub) or(prv, prv)? -> as above, we can just add calls with the wrong argument inthe existing test function mbedtls_pk_check_pair() always expecting failure.(All other items below assume arguments in the correct order and populated.) https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/0ac71fdbc2db8c7f19afa624e1520f9450a5350a
MTC9 pub and prv have the same type (both RSA or both ECC) but different sizes ->should test with both pub larger than prv and prv larger than prv (we want tomake sure our internal memcmp() never overreads). Can be done by adding newnegative test cases for mbedtls_pk_check_pair: with varying key sizes. Sincethe function accepts two file names as arguments, it should be a simple matterof locating existing files with keys of different sizes, and adjusting thetest case dependencies. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/c620a58a3ff0afa7f9477407efb881dd7e2ce54d
MTC10 pub and prv are both ECC keys of the same bitsize, but different curves ->again can be done by adding a new case for mbedtls_pk_check_pair: as above. https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/205e831eed2f9df873cff9c59881fb6ac1df74fc
</html>
Updated as per Manuel's test plan, Test report as follows: <!DOCTYPE html> <html> <head> </head> <body> Reference | Test case | Commit -- | -- | -- MTC1 | Correct documentation to remove failure on wrapped RSA | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/fe3e39a5f5980ad323f6515230a57ed27eac9d03 MTC2 | Return PSA_ERROR_INVALID_ARGUMENT if the contect is invalid. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/e63eef4ca78df616a9f080285ed6c61151bd9cba MTC3 | pk_psa_utils(): check that it fails with "opaque" (wrapping) contexts (RSA,ECC) -> no longer relevant, remove that. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/bc6407f162dddd6bef748a7519f2ad05466f1cda MTC4 | pk_psa_utils:: no longer relevant, we're removing check_pair() from here,see above. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/bc6407f162dddd6bef748a7519f2ad05466f1cda MTC5 | newly supported case: prv is wrapping RSA -> just adjust existing code inmbedtls_pk_check_pair() so that RSA keys are tested the same as ECC keys(actually a simplification, no longer need to distinguish ECC vs RSA). | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/1a6c7dcf7b2ecbec350e45dd6f22b6334ab88ba7 MTC6 | public key was created with copy_public_from_psa -> extendpk_copy_from_psa_success() to also call check_pair on the existingcontexts pk_priv_copy_public and pk_pub_copy_public in addition to theexisting call. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/b22cc698e175c76d005a616a4c225fd29b63cb0c MTC7 | pub or prv hasn't been populated -> add an empty context inthe existing test function mbedtls_pk_check_pair(), add calls with (pub,empty) and (empty, prv) and always expect failure (in addition to normaltesting that can either succeed or fail depending on the data). | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/1c5e1b70f17ffe1cbb22101eb8da53294cb6b114 MTC8 | The function expects (pub, prv) -> what if we pass (pub, pub), (prv, pub) or(prv, prv)? -> as above, we can just add calls with the wrong argument inthe existing test function mbedtls_pk_check_pair() always expecting failure.(All other items below assume arguments in the correct order and populated.) | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/0ac71fdbc2db8c7f19afa624e1520f9450a5350a MTC9 | pub and prv have the same type (both RSA or both ECC) but different sizes ->should test with both pub larger than prv and prv larger than prv (we want tomake sure our internal memcmp() never overreads). Can be done by adding newnegative test cases for mbedtls_pk_check_pair: with varying key sizes. Sincethe function accepts two file names as arguments, it should be a simple matterof locating existing files with keys of different sizes, and adjusting thetest case dependencies. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/c620a58a3ff0afa7f9477407efb881dd7e2ce54d MTC10 | pub and prv are both ECC keys of the same bitsize, but different curves ->again can be done by adding a new case for mbedtls_pk_check_pair: as above. | https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580/changes/205e831eed2f9df873cff9c59881fb6ac1df74fc </body> </html>
bjwtaylor commented 2026-01-22 01:54:28 -06:00 (Migrated from github.com)

@gilles-peskine-arm, so I tried removing the export from check pair as discussed and it appears to be a "feature" required by the sample programs here: github.com/bjwtaylor/mbedtls@069cfbd43c/programs/ssl/ssl_server2.c (L1170) . Maybe one to discuss at stand up, for now I have added an improved version of the export. Maybe it might be better to change the functionality of the sample programs though the problem is how many people will have copied that implementation and then this would be a breaking change for them?

@gilles-peskine-arm, so I tried removing the export from check pair as discussed and it appears to be a "feature" required by the sample programs here: https://github.com/bjwtaylor/mbedtls/blob/069cfbd43cc19dd4146580617611f0f8f2e290ba/programs/ssl/ssl_server2.c#L1170 . Maybe one to discuss at stand up, for now I have added an improved version of the export. Maybe it might be better to change the functionality of the sample programs though the problem is how many people will have copied that implementation and then this would be a breaking change for them?
mpg (Migrated from github.com) reviewed 2026-01-22 06:23:03 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
mpg (Migrated from github.com) commented 2026-01-22 06:23:03 -06:00

To sum up & confirm what has been said: we are moving towards more uniformity in PK. Previously pub_raw was not always populated by public functions that populate a context. Since some time last quarter, it always is (if it isn't, that's something we should fix).

The current implementations of check_pair() date back from a time before this was guaranteed. So they can't rely on that assumption and must use export(). But the new implementation fortunately comes at a time where a lot more things are uniformly guaranteed, and can rely on that.

the caller has to call something like mbedtls_pk_parse_keyfile() and then mbedtls_pk_set_pubkey_from_prv().

Nope, mbedtls_pk_parse_keyfile() should already be calling mbedtls_pk_set_pubkey_from_prv(), it it's not, we should fix it. (Anyway, set_pubkey_from_prv() is not a public function, users can't call it, it's out job to call it at the right time(s).)

There are currently 5 ways to populate a PK context: mbedtls_pk_wrap_psa(), mbedtls_copy{,_public}_from_psa() and mbedtls_pk_parse{,_public}_key (plus the obvious "file" variants of the two parse functions). The theory/goal is that all those 5 ways should result in a PK context where all fields (pub_raw, psa_type, bits) are set and valid, so that the rest of the code can use them without worrying what kind of context this is or how it was populated (the only exception being priv_id which is currently only set for private keys aka keypairs).

I think we are already there, but if I'm wrong and we're not, the proper fix is to get there, not work around the fact that we're not there yet.

To sum up & confirm what has been said: we are moving towards more uniformity in PK. Previously `pub_raw` was not always populated by public functions that populate a context. Since some time last quarter, it always is (if it isn't, that's something we should fix). The current implementations of `check_pair()` date back from a time before this was guaranteed. So they can't rely on that assumption and must use `export()`. But the new implementation fortunately comes at a time where a lot more things are uniformly guaranteed, and can rely on that. > the caller has to call something like `mbedtls_pk_parse_keyfile()` and then `mbedtls_pk_set_pubkey_from_prv()`. Nope, `mbedtls_pk_parse_keyfile()` should already be calling `mbedtls_pk_set_pubkey_from_prv()`, it it's not, we should fix it. (Anyway, `set_pubkey_from_prv()` is not a public function, users can't call it, it's out job to call it at the right time(s).) There are currently 5 ways to populate a PK context: `mbedtls_pk_wrap_psa()`, `mbedtls_copy{,_public}_from_psa()` and `mbedtls_pk_parse{,_public}_key` (plus the obvious "file" variants of the two parse functions). The theory/goal is that all those 5 ways should result in a PK context where all fields (`pub_raw`, `psa_type`, `bits`) are set and valid, so that the rest of the code can use them without worrying what kind of context this is or how it was populated (the only exception being `priv_id` which is currently only set for private keys aka keypairs). I _think_ we are already there, but if I'm wrong and we're not, the proper fix is to get there, not work around the fact that we're not there yet.
gilles-peskine-arm commented 2026-01-22 06:43:36 -06:00 (Migrated from github.com)

@bjwtaylor ssl_server2 is a test program, not a sample program. It may be taking liberties with the API. If you follow the API, all the ways to construct a pk object should fill in the public key field, or if they don't we should fix that, maybe not in this PR but as part of the ongoing pk cleanup.

What's failing here is specifically the tests of MBEDTLS_SSL_ASYNC_PRIVATE. That test code might plausibly do bad things with pk contexts that used to be ok, but no longer are. To summarize this feature, it's a way for a TLS server to have its private key in some external server (predating PSA secure elements). So when it's in use, it's plausible that there would be a pk context that normally contains a private key, but actually doesn't. It's weird that this would cause a problem in check_pair though, and by looking quickly at the source code I can't see an obvious problem.

Would you mind looking at the failure in a debugger and seeing where precisely ssl_server2 is doing something bad? (I.e. look deeper than just where it notices something bad.) I wrote that feature so I might be able to help, but it's been years so I don't remember much other than the general design.

@bjwtaylor `ssl_server2` is a test program, not a sample program. It may be taking liberties with the API. If you follow the API, all the ways to construct a pk object should fill in the public key field, or if they don't we should fix that, maybe not in this PR but as part of the ongoing pk cleanup. What's failing here is specifically the tests of `MBEDTLS_SSL_ASYNC_PRIVATE`. That test code might plausibly do bad things with pk contexts that used to be ok, but no longer are. To summarize this feature, it's a way for a TLS server to have its private key in some external server (predating PSA secure elements). So when it's in use, it's plausible that there would be a pk context that normally contains a _private_ key, but actually doesn't. It's weird that this would cause a problem in `check_pair` though, and by looking quickly at the source code I can't see an obvious problem. Would you mind looking at the failure in a debugger and seeing where precisely `ssl_server2` is doing something bad? (I.e. look deeper than just where it _notices_ something bad.) I wrote that feature so I might be able to help, but it's been years so I don't remember much other than the general design.
mpg commented 2026-01-22 06:54:16 -06:00 (Migrated from github.com)

If you follow the API, all the ways to construct a pk object should fill in the public key field, or if they don't we should fix that, maybe not in this PR but as part of the ongoing pk cleanup.

IMO in this PR, because otherwise we need to work around it and it makes this PR more complicated than it should be anyway. (Also, I just remembered why I think it's already done: the implementation of mbedtls_pk_write_pubkey_psa() relies on the fact that pub_raw is populated, and that function is properly tested with all 5 public ways of populating a PK context, so really we should be fine already.)

Would you mind looking at the failure in a debugger and seeing where precisely ssl_server2 is doing something bad? (I.e. look deeper than just where it notices something bad.)

I was going to ask the same: how exactly is the context created? I strongly suspect it's not with one of the 5 public APIs mentioned above, but rather by directly calling mbedtls_pk_setup() (now an internal function) or perhaps even directly messing with the private fields of the PK context structure). We should either change the code to use only public functions if that can easily be done, or otherwise if the code is already using private stuff, then it may as well call one more internal function, namely mbedtls_pk_set_pubkey_from_prv(), so that the context it populates in unsanctioned ways still satisfies the invariants of context populated in one of the official ways.

> If you follow the API, all the ways to construct a pk object should fill in the public key field, or if they don't we should fix that, maybe not in this PR but as part of the ongoing pk cleanup. IMO in this PR, because otherwise we need to work around it and it makes this PR more complicated than it should be anyway. (Also, I just remembered why I think it's already done: the implementation of `mbedtls_pk_write_pubkey_psa()` relies on the fact that `pub_raw` is populated, and that function is properly tested with all 5 public ways of populating a PK context, so really we should be fine already.) > Would you mind looking at the failure in a debugger and seeing where precisely ssl_server2 is doing something bad? (I.e. look deeper than just where it notices something bad.) I was going to ask the same: how exactly is the context created? I strongly suspect it's not with one of the 5 public APIs mentioned above, but rather by directly calling `mbedtls_pk_setup()` (now an internal function) or perhaps even directly messing with the private fields of the PK context structure). We should either change the code to use only public functions if that can easily be done, or otherwise if the code is already using private stuff, then it may as well call one more internal function, namely `mbedtls_pk_set_pubkey_from_prv()`, so that the context it populates in unsanctioned ways still satisfies the invariants of context populated in one of the official ways.
gilles-peskine-arm commented 2026-01-22 07:05:07 -06:00 (Migrated from github.com)

I was going to ask the same: how exactly is the context created? I strongly suspect it's not with one of the 5 public APIs mentioned above, but rather by directly calling mbedtls_pk_setup() (now an internal function) or perhaps even directly messing with the private fields of the PK context structure).

That's the thing: it's neither accessing pk_ctx (which doesn't even exist anymore) nor calling mbedtls_pk_setup (not called at all in mbedtls). I also can't find anything like a shallow copy. There may be places where more than one piece of the code have a pointer to the same context, and this could cause one piece to call mbedtls_pk_free when another piece still needs the context, but (1) I don't see how it could cause a problem now that didn't cause a problem before, and (2) AFAICT that potential weirdness only happens with SNI and even non-SNI test cases are failing.

> I was going to ask the same: how exactly is the context created? I strongly suspect it's not with one of the 5 public APIs mentioned above, but rather by directly calling mbedtls_pk_setup() (now an internal function) or perhaps even directly messing with the private fields of the PK context structure). That's the thing: it's neither accessing `pk_ctx` (which doesn't even exist anymore) nor calling `mbedtls_pk_setup` (not called at all in mbedtls). I also can't find anything like a shallow copy. There may be places where more than one piece of the code have a pointer to the same context, and this could cause one piece to call `mbedtls_pk_free` when another piece still needs the context, but (1) I don't see how it could cause a problem now that didn't cause a problem before, and (2) AFAICT that potential weirdness only happens with SNI and even non-SNI test cases are failing.
bjwtaylor commented 2026-01-22 07:46:09 -06:00 (Migrated from github.com)

then it may as well call one more internal function, namely mbedtls_pk_set_pubkey_from_prv(), so that the context it populates in unsanctioned ways still satisfies the invariants of context populated in one of the official ways.

@mpg I like this suggestion. I'll investigate further, as to how the program functions and how it ends up with a partially populated context. Though I suspect to fix the underlying issue maybe a more work than we want to do and is arguably outside of the scope of this issue. If this program is just for test, not intended as an example and is already using the API in unsanctioned ways. Then adding one more unsanctioned API for now and logging another issue might be the best way forward if @gilles-peskine-arm you're happy with that?

> then it may as well call one more internal function, namely `mbedtls_pk_set_pubkey_from_prv()`, so that the context it populates in unsanctioned ways still satisfies the invariants of context populated in one of the official ways. @mpg I like this suggestion. I'll investigate further, as to how the program functions and how it ends up with a partially populated context. Though I suspect to fix the underlying issue maybe a more work than we want to do and is arguably outside of the scope of this issue. If this program is just for test, not intended as an example and is already using the API in unsanctioned ways. Then adding one more unsanctioned API for now and logging another issue might be the best way forward if @gilles-peskine-arm you're happy with that?
bjwtaylor commented 2026-01-22 08:11:45 -06:00 (Migrated from github.com)

So, on further investigation it looks like it's using mbedtls_pk_parse_keyfile() here github.com/bjwtaylor/mbedtls@069cfbd43c/programs/ssl/ssl_server2.c (L2615) to populate the privkey. Which I know doesn't populate the pubkey and I guess is now not public? I think I copied this code and was using the same function in the test, thinking this was public :( So I was planning to add a mbedtls_pk_set_pubkey_from_prv() here and will do the same in the test progs. Let me know if anyone has objections though.

So, on further investigation it looks like it's using mbedtls_pk_parse_keyfile() here https://github.com/bjwtaylor/mbedtls/blob/069cfbd43cc19dd4146580617611f0f8f2e290ba/programs/ssl/ssl_server2.c#L2615 to populate the privkey. Which I know doesn't populate the pubkey and I guess is now not public? I think I copied this code and was using the same function in the test, thinking this was public :( So I was planning to add a mbedtls_pk_set_pubkey_from_prv() here and will do the same in the test progs. Let me know if anyone has objections though.
gilles-peskine-arm commented 2026-01-22 08:29:59 -06:00 (Migrated from github.com)

it's using mbedtls_pk_parse_keyfile() (…) to populate the privkey. Which I know doesn't populate the pubkey

Even if mbedtls_pk_parse_keyfile is not in the public API, I would expect it to be just load file + mbedtls_pk_parse_key. And in fact, that is exactly what the function does. So how do we end up with a malformed pk object after mbedtls_pk_parse_keyfile?

> it's using mbedtls_pk_parse_keyfile() (…) to populate the privkey. Which I know doesn't populate the pubkey Even if `mbedtls_pk_parse_keyfile` is not in the public API, I would expect it to be just load file + `mbedtls_pk_parse_key`. And in fact, that is exactly what the function does. So how do we end up with a malformed pk object after `mbedtls_pk_parse_keyfile`?
bjwtaylor commented 2026-01-22 08:36:28 -06:00 (Migrated from github.com)

That's a good question, I know that call ends up with a malformed PK object. Though I've not dug into why, I shall investigate. Interestingly mbedtls_pk_parse_keyfile is in pk.h, so presumably this means it's public? So adding an additional mbedtls_pk_set_pubkey_from_prv(), is not as easy as I though as I'd need to hack the include path, so it can access pk_internal.h. Which I don't like, let me have another look if the issue is with the mbedtls_pk_parse_keyfile() it might be better to fix it.

That's a good question, I know that call ends up with a malformed PK object. Though I've not dug into why, I shall investigate. Interestingly mbedtls_pk_parse_keyfile is in pk.h, so presumably this means it's public? So adding an additional mbedtls_pk_set_pubkey_from_prv(), is not as easy as I though as I'd need to hack the include path, so it can access pk_internal.h. Which I don't like, let me have another look if the issue is with the mbedtls_pk_parse_keyfile() it might be better to fix it.
gilles-peskine-arm commented 2026-01-22 08:49:50 -06:00 (Migrated from github.com)

Yes, mbedtls_pk_parse_keyfile is in fact public (we talked about making it private, but evidently we didn't end up doing it).

It's definitely a problem if mbedtls_pk_parse_keyfile constructs a malformed key. But I doubt that this is the problem, because a lot of our test code uses that function.

I suspect that the code of ssl_server2 is doing something unusual after mbedtls_pk_parse_keyfile, and based on which test cases fail, it's evidently in code guarded by MBEDTLS_SSL_ASYNC_PRIVATE. But so far I can't see what.

Yes, `mbedtls_pk_parse_keyfile` is in fact public (we talked about making it private, but evidently we didn't end up doing it). It's definitely a problem if `mbedtls_pk_parse_keyfile` constructs a malformed key. But I doubt that this is the problem, because a lot of our test code uses that function. I suspect that the code of `ssl_server2` is doing something unusual after `mbedtls_pk_parse_keyfile`, and based on which test cases fail, it's evidently in code guarded by `MBEDTLS_SSL_ASYNC_PRIVATE`. But so far I can't see what.
bjwtaylor commented 2026-01-22 09:03:30 -06:00 (Migrated from github.com)

I agree, it's weird that only the async cases fail. I'll look into it and report back.

I agree, it's weird that only the async cases fail. I'll look into it and report back.
bjwtaylor commented 2026-01-22 09:37:24 -06:00 (Migrated from github.com)

So it looks like there could be a corner case where the public key is not exported if you are using pem encoded keys in a file. I've added a fix, which seems to resolve it locally. Let's see what the CI thinks though.

So it looks like there could be a corner case where the public key is not exported if you are using pem encoded keys in a file. I've added a fix, which seems to resolve it locally. Let's see what the CI thinks though.
bjwtaylor commented 2026-01-23 02:51:13 -06:00 (Migrated from github.com)

So, it looks like the fix worked overnight. Let me know what people think to it? I think at best it's a temporary fix, long term we may want to privatise this function and maybe refactor it to avoid duplicate calls. Though I think if so this is out of scope of this issue. I've also added some tidy up.

So, it looks like the fix worked overnight. Let me know what people think to it? I think at best it's a temporary fix, long term we may want to privatise this function and maybe refactor it to avoid duplicate calls. Though I think if so this is out of scope of this issue. I've also added some tidy up.
mpg (Migrated from github.com) requested changes 2026-01-23 03:45:33 -06:00
mpg (Migrated from github.com) left a comment

Looking pretty good! A few minor points, but I think the overall shape is good now.

Looking pretty good! A few minor points, but I think the overall shape is good now.
mpg (Migrated from github.com) commented 2026-01-23 03:20:05 -06:00

Ok, I'm surprised the changes here require this. If this is for memcmp(), I'd rather just include string.h.

Ok, I'm surprised the changes here require this. If this is for `memcmp()`, I'd rather just include `string.h`.
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
mpg (Migrated from github.com) commented 2026-01-23 02:56:40 -06:00

In the long run, we want to get rid of pk_info. I know this is pre-existing, but do we really need to keep this now?

Actually, I tried removing this line (keeping only the two lines below based on psa_type) and all the tests seem to still pass locally. So, I think we should just stop checking pk_info here.

In the long run, we want to get rid of `pk_info`. I know this is pre-existing, but do we really need to keep this now? Actually, I tried removing this line (keeping only the two lines below based on `psa_type`) and all the tests seem to still pass locally. So, I think we should just stop checking `pk_info` here.
mpg (Migrated from github.com) commented 2026-01-23 03:13:23 -06:00

The documentation says #PSA_ERROR_INVALID_ARGUMENT if a context is invalid. Now MBEDTLS_ERR_PK_BAD_INPUT_DATA is indeed an alias for PSA_ERROR_INVALID_ARGUMENT but I would find it a bit more readable to directly write return PSA_ERROR_INVALID_ARGUMENT here - that way it's obvious we do what the documentation says, without relying on non-local knowledge of error code aliasing.

The documentation says `#PSA_ERROR_INVALID_ARGUMENT if a context is invalid.` Now `MBEDTLS_ERR_PK_BAD_INPUT_DATA` is indeed an alias for `PSA_ERROR_INVALID_ARGUMENT` but I would find it a bit more readable to directly write `return PSA_ERROR_INVALID_ARGUMENT` here - that way it's obvious we do what the documentation says, without relying on non-local knowledge of error code aliasing.
mpg (Migrated from github.com) commented 2026-01-23 03:18:17 -06:00

Minor, pre-existing: the documentation says "another error code if the keys do not match" (right after PSA_ERROR_INVALID_ARGUMENT if a context is invalid), so technically we should return something other than PSA_ERROR_INVALID_ARGUMENT aka MBEDTLS_ERR_PK_BAD_INPUT_DATA here.

The problem here, I'm not sure what would be more fitting. MBEDTLS_ERR_PK_TYPE_MISMATCH is perhaps the least bad match, but it's not ideal either.

Or perhaps we just change the documentation to match the existing behaviour: s/Another/Some/ non-zero value if the keys do not match?

Minor, pre-existing: the documentation says "another error code if the keys do not match" (right after PSA_ERROR_INVALID_ARGUMENT if a context is invalid), so technically we should return something other than `PSA_ERROR_INVALID_ARGUMENT` aka `MBEDTLS_ERR_PK_BAD_INPUT_DATA` here. The problem here, I'm not sure what would be more fitting. `MBEDTLS_ERR_PK_TYPE_MISMATCH` is perhaps the least bad match, but it's not ideal either. Or perhaps we just change the documentation to match the existing behaviour: s/Another/Some/ non-zero value if the keys do not match?
mpg (Migrated from github.com) commented 2026-01-23 03:21:30 -06:00

Minor: I would check the types before checking the contents. Intuitively makes more sense. Also is more consistent with existing behaviour.

Minor: I would check the types before checking the contents. Intuitively makes more sense. Also is more consistent with existing behaviour.
@ -964,2 +964,3 @@
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0) {
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0 ||
(ret = mbedtls_pk_set_pubkey_from_prv(pk)) != 0) {
mbedtls_pk_free(pk);
mpg (Migrated from github.com) commented 2026-01-23 03:05:46 -06:00

Nice catch, thanks!

Ok, interesting, so parse_key() has different code paths for PEM and DER, and was improperly populating the context in some code paths, and this was not caught by existing tests because the only tests that currently rely on pub_raw being properly populated are using DER not PEM. Our testing strategy was not good enough and we were lucky that ssl_server2 caught it for us.

I think we probably want to revisit a previous suggestion by Gilles about testing: create a helper function that checks invariants of a populated PK context (like psa_type is not NONE, pub_raw_len is not 0, etc. perhaps even that the contents of pub_raw match what we get from exporting from priv_id, etc.) and then add calls to this helper to all existing parsing test functions (or more generally, tests function that are about a method of populating a PK context).

This is obviously out of scope here. I'll file a separate issue and might have a go at it myself.

Nice catch, thanks! Ok, interesting, so `parse_key()` has different code paths for PEM and DER, and was improperly populating the context in some code paths, and this was not caught by existing tests because the only tests that currently rely on `pub_raw` being properly populated are using DER not PEM. Our testing strategy was not good enough and we were lucky that `ssl_server2` caught it for us. I think we probably want to revisit a previous suggestion by Gilles about testing: create a helper function that checks invariants of a populated PK context (like `psa_type` is not NONE, `pub_raw_len` is not 0, etc. perhaps even that the contents of `pub_raw` match what we get from exporting from `priv_id`, etc.) and then add calls to this helper to all existing parsing test functions (or more generally, tests function that are about a method of populating a PK context). This is obviously out of scope here. I'll file a separate issue and might have a go at it myself.
@ -712,15 +711,10 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t sig_type,
/**
mpg (Migrated from github.com) commented 2026-01-23 03:07:37 -06:00

Nope, that's an internal detail, users are not supposed to know what this means and should not be exposed to this. I think the way we want to express this is to add "Must be populated" to both pub and prv arguments. (Also, we already say above #PSA_ERROR_INVALID_ARGUMENT if a context is invalid.)

Nope, that's an internal detail, users are not supposed to know what this means and should not be exposed to this. I think the way we want to express this is to add "Must be populated" to both `pub` and `prv` arguments. (Also, we already say above `#PSA_ERROR_INVALID_ARGUMENT if a context is invalid.`)
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
mpg (Migrated from github.com) commented 2026-01-23 03:22:37 -06:00

Minor: we wouldn't need to change the expected return code here if we kept the existing behaviour of checking the type before we check the content (see my other comment on the implementation).

Minor: we wouldn't need to change the expected return code here if we kept the existing behaviour of checking the type before we check the content (see my other comment on the implementation).
mpg (Migrated from github.com) commented 2026-01-23 03:25:18 -06:00

Nit: I see what you mean but brainpool curves also are over a prime field and have prime order. I think "NIST vs Brainpool" would be better.

Nit: I see what you mean but brainpool curves also are over a prime field and have prime order. I think "NIST vs Brainpool" would be better.
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
mpg (Migrated from github.com) commented 2026-01-23 03:27:54 -06:00

Minor, pre-existing: I think we're no longer using this alt context and could remove it.

Minor, pre-existing: I think we're no longer using this `alt` context and could remove it.
mpg (Migrated from github.com) commented 2026-01-23 03:31:10 -06:00

That change does not look correct to me:

  • we always want the TEST_ASSERT() (or these days, TEST_EQUAL(), but anyway)
  • even when expected_ret is not zero, we want to keep testing with wrapped and check that we get the same (non-zero) return value.

I think the code was fine as it was, and this change is probably a leftover from some intermediate state or debugging?

That change does not look correct to me: - we always want the `TEST_ASSERT()` (or these days, `TEST_EQUAL()`, but anyway) - even when `expected_ret` is not zero, we want to keep testing with wrapped and check that we get the same (non-zero) return value. I think the code was fine as it was, and this change is probably a leftover from some intermediate state or debugging?
mpg (Migrated from github.com) commented 2026-01-23 03:33:48 -06:00

Thanks! For the sake of completeness, can we add the following too?

TEST_EQUAL(mbedtls_pk_check_pair(&pk_pub_copy_public, &pk_priv), 0);
Thanks! For the sake of completeness, can we add the following too? ``` TEST_EQUAL(mbedtls_pk_check_pair(&pk_pub_copy_public, &pk_priv), 0); ```
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 05:38:11 -06:00
@ -964,2 +964,3 @@
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0) {
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0 ||
(ret = mbedtls_pk_set_pubkey_from_prv(pk)) != 0) {
mbedtls_pk_free(pk);
bjwtaylor (Migrated from github.com) commented 2026-01-23 05:38:10 -06:00

I completely agree, this is probably the tip of the iceberg. There are probably other corner cases that we are not catching in the test. The new tests I added will catch this one as I think I copied the test programs implementation of reading pem files. Though we should probably add more, it's also easier to debug these things if they are caught in the standard tests rather than having to rely on ssl-opt. Also agree it is out of scope here though.

I completely agree, this is probably the tip of the iceberg. There are probably other corner cases that we are not catching in the test. The new tests I added will catch this one as I think I copied the test programs implementation of reading pem files. Though we should probably add more, it's also easier to debug these things if they are caught in the standard tests rather than having to rely on ssl-opt. Also agree it is out of scope here though.
mpg (Migrated from github.com) reviewed 2026-01-23 06:13:19 -06:00
@ -964,2 +964,3 @@
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0) {
(ret = mbedtls_pk_rsa_set_key(pk, pem.buf, pem.buflen)) != 0 ||
(ret = mbedtls_pk_set_pubkey_from_prv(pk)) != 0) {
mbedtls_pk_free(pk);
mpg (Migrated from github.com) commented 2026-01-23 06:13:19 -06:00

This is obviously out of scope here. I'll file a separate issue

https://github.com/Mbed-TLS/mbedtls/issues/10573

> This is obviously out of scope here. I'll file a separate issue https://github.com/Mbed-TLS/mbedtls/issues/10573
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:21:29 -06:00
@ -712,15 +711,10 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t sig_type,
/**
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:21:29 -06:00

OK, I've removed the note. If we don't want to expose the detail the content is largely explained by the note above.

OK, I've removed the note. If we don't want to expose the detail the content is largely explained by the note above.
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:25:18 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:25:18 -06:00

OK, I've updated it. Maybe one that's outside the scope of this function, however we now have mbedtls_* functions in PK that are in psa and use a mixture of MBEDTLS* and PSA* error codes. Presumably we should eventually move everything to PSA*? Or do we have another plan?

OK, I've updated it. Maybe one that's outside the scope of this function, however we now have mbedtls_* functions in PK that are in psa and use a mixture of MBEDTLS* and PSA* error codes. Presumably we should eventually move everything to PSA*? Or do we have another plan?
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:29:06 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:29:06 -06:00

I don't have a strong opinion either way, so I've updated it to MBEDTLS_ERR_PK_TYPE_MISMATCH. As this is the smalles change. Let me know if you think the doc change would be better though.

I don't have a strong opinion either way, so I've updated it to MBEDTLS_ERR_PK_TYPE_MISMATCH. As this is the smalles change. Let me know if you think the doc change would be better though.
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:38:05 -06:00
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:38:05 -06:00

I think this is related to the previous comment on the MBEDTLS_ERR_PK_BAD_INPUT_DATA -> MBEDTLS_ERR_PK_TYPE_MISMATCH. As above I've changed this and have also now updated the data file.

I think this is related to the previous comment on the MBEDTLS_ERR_PK_BAD_INPUT_DATA -> MBEDTLS_ERR_PK_TYPE_MISMATCH. As above I've changed this and have also now updated the data file.
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:48:21 -06:00
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:48:21 -06:00

Should now be removed.

Should now be removed.
bjwtaylor (Migrated from github.com) reviewed 2026-01-23 07:49:56 -06:00
bjwtaylor (Migrated from github.com) commented 2026-01-23 07:49:56 -06:00

Should now be updated.

Should now be updated.
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 01:58:49 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-26 01:58:49 -06:00

I've put the change in, also seems to pass locally for me. Though lets see if the CI agrees.

I've put the change in, also seems to pass locally for me. Though lets see if the CI agrees.
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 02:24:32 -06:00
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
bjwtaylor (Migrated from github.com) commented 2026-01-26 02:24:32 -06:00

So, currently it's using a NIST though it's a prime field one. We could change it to a binary field, however I don't believe we have any in the data_files directory. I could create one, though I would then need another PR on the framework. Let's discuss in the catchup if this is worth it?

So, currently it's using a NIST though it's a prime field one. We could change it to a binary field, however I don't believe we have any in the data_files directory. I could create one, though I would then need another PR on the framework. Let's discuss in the catchup if this is worth it?
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 02:35:46 -06:00
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
bjwtaylor (Migrated from github.com) commented 2026-01-26 02:35:45 -06:00

So, I've basically compacted this function to do multiple tests in one. This has probably reduced test size, though it may of also unacceptably decreased readablity. The idea of this line is that expected ret is used twice in the tests to check the output of multiple check_pair tests. So in some cases we want to check that the call to check_pair on that line and sometimes here github.com/bjwtaylor/TF-PSA-Crypto@1b4b6a491d/tests/suites/test_suite_pk.function (L1066). If we want to check the second instance then this one will return ) and the test will continue. If we want to check this one, then it will return an error and we want to exit at this point as we are probably using test data that is crafted just to use this case to fail. Let me know what you think, maybe we leave it as is. Or maybe we need two expected_return variables. Or maybe we need to unravel this into a number of simpler functions for readability?

So, I've basically compacted this function to do multiple tests in one. This has probably reduced test size, though it may of also unacceptably decreased readablity. The idea of this line is that expected ret is used twice in the tests to check the output of multiple check_pair tests. So in some cases we want to check that the call to check_pair on that line and sometimes here https://github.com/bjwtaylor/TF-PSA-Crypto/blob/1b4b6a491df5243d829087864c9b343850a091d1/tests/suites/test_suite_pk.function#L1066. If we want to check the second instance then this one will return ) and the test will continue. If we want to check this one, then it will return an error and we want to exit at this point as we are probably using test data that is crafted just to use this case to fail. Let me know what you think, maybe we leave it as is. Or maybe we need two expected_return variables. Or maybe we need to unravel this into a number of simpler functions for readability?
mpg (Migrated from github.com) reviewed 2026-01-26 02:54:50 -06:00
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
mpg (Migrated from github.com) commented 2026-01-26 02:54:50 -06:00

We don't support binary fields at all. I'm perfectly happy with the test data as it is, I just think "NIST vs Brainpool" would be a better description for it than "prime vs brainpool", considering "prime" is true of all the curves in this test (and actually all the curves we support).

We don't support binary fields at all. I'm perfectly happy with the test data as it is, I just think "NIST vs Brainpool" would be a better description for it than "prime vs brainpool", considering "prime" is true of all the curves in this test (and actually all the curves we support).
mpg commented 2026-01-26 02:59:30 -06:00 (Migrated from github.com)

Github won't let me line comment on this, but I'm surprised there's a commit here updating the framework pointer: why is that needed for this PR?

Github won't let me line comment on this, but I'm surprised there's a commit here updating the framework pointer: why is that needed for this PR?
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 03:04:52 -06:00
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
bjwtaylor (Migrated from github.com) commented 2026-01-26 03:04:51 -06:00

Understood, now corrected.

Understood, now corrected.
mpg (Migrated from github.com) reviewed 2026-01-26 03:09:29 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
mpg (Migrated from github.com) commented 2026-01-26 03:09:29 -06:00

Using a mixture is OK for the time being. But here since the documentation mentions the PSA one, I thought using the same name in the implementation would make correctness more obvious.

Using a mixture is OK for the time being. But here since the documentation mentions the PSA one, I thought using the same name in the implementation would make correctness more obvious.
mpg (Migrated from github.com) reviewed 2026-01-26 03:11:04 -06:00
@ -520,3 +520,3 @@
depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PEM_PARSE_C
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_BAD_INPUT_DATA
mbedtls_pk_check_pair:"../framework/data_files/server1.pubkey":"../framework/data_files/server2.key":MBEDTLS_ERR_PK_TYPE_MISMATCH
mpg (Migrated from github.com) commented 2026-01-26 03:11:04 -06:00

Ah sorry for not including a link( github wouldn't let me as the other comment was still pending), but this was related to this comment actually.

Ah sorry for not including a link( github wouldn't let me as the other comment was still pending), but this was related to [this comment](https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/580#discussion_r2720386092) actually.
bjwtaylor commented 2026-01-26 03:14:28 -06:00 (Migrated from github.com)

@mpg, I suspect the framework pointer update was needed at some point to resolve an issue as the pointer was maybe out of date? Either that or I was trying multiple things to rebase and left this in even though it had no impact. It isn't currently required though, so I can remove it. Though I'd then need to do a force push. As we will probably need to upgrade it at some point anyway and it doesn't cause any issue it it worth it?

@mpg, I suspect the framework pointer update was needed at some point to resolve an issue as the pointer was maybe out of date? Either that or I was trying multiple things to rebase and left this in even though it had no impact. It isn't currently required though, so I can remove it. Though I'd then need to do a force push. As we will probably need to upgrade it at some point anyway and it doesn't cause any issue it it worth it?
mpg (Migrated from github.com) reviewed 2026-01-26 03:14:34 -06:00
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
mpg (Migrated from github.com) commented 2026-01-26 03:14:34 -06:00

Ok I see. Yes I think that's a bit too clever for readability. We should either have a comment about it, or perhaps use two parameters expected_ret1 and expected_ret2.

But taking a step back, I don't really understand why we'd expect different results on lines 1053 and 1066. Either the key materials match or they don't, and that should have nothing to do with whether the private context is wrapping or not.

Am I missing something?

Ok I see. Yes I think that's a bit too clever for readability. We should either have a comment about it, or perhaps use two parameters `expected_ret1` and `expected_ret2`. But taking a step back, I don't really understand why we'd expect different results on lines 1053 and 1066. Either the key materials match or they don't, and that should have nothing to do with whether the private context is wrapping or not. Am I missing something?
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 03:21:30 -06:00
@ -1340,22 +1340,29 @@ int mbedtls_pk_sign_ext(mbedtls_pk_sigalg_t pk_type,
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv)
bjwtaylor (Migrated from github.com) commented 2026-01-26 03:21:30 -06:00

I've now swapped these over.

I've now swapped these over.
mpg (Migrated from github.com) reviewed 2026-01-26 03:22:42 -06:00
mpg (Migrated from github.com) commented 2026-01-26 03:22:42 -06:00

Minor: please remove the comment "unsupported functions: check_pair, debug" a few lines above. We're removing check_pair here, and debug was removed in another PR but without updating the comment, so let's clean it up here while at it.

Also, does this function still need pk2 or was it only used for check_pair?

Minor: please remove the comment "unsupported functions: check_pair, debug" a few lines above. We're removing `check_pair` here, and debug was removed in another PR but without updating the comment, so let's clean it up here while at it. Also, does this function still need `pk2` or was it only used for `check_pair`?
mpg commented 2026-01-26 03:32:29 -06:00 (Migrated from github.com)

I suspect the framework pointer update was needed at some point to resolve an issue as the pointer was maybe out of date? Either that or I was trying multiple things to rebase and left this in even though it had no impact.

Well if it was to resolve an issue, you should know which one. As to rebasing, this PR was not rebased recently, so that seems weird. I can understand that in complex situations sometimes we try a lot of things and don't always remember everything, but here I don't feel like anything particularly complex was going on, just run of the mill rework to address review comments. So it seems weird to end up with unexplained commits in this context.

It isn't currently required though, so I can remove it. Though I'd then need to do a force push.

Generally speaking, let's avoid force pushes unless required. But that's also a reason to avoid updating submodule pointers unless actually required: they tend to cause conflicts that then require force-pushes to resolve.

So, in the future, please do not update submodule pointers unless there is a specific reason - and then be prepared to explain that reason :)

> I suspect the framework pointer update was needed at some point to resolve an issue as the pointer was maybe out of date? Either that or I was trying multiple things to rebase and left this in even though it had no impact. Well if it was to resolve an issue, you should know which one. As to rebasing, this PR was not rebased recently, so that seems weird. I can understand that in complex situations sometimes we try a lot of things and don't always remember everything, but here I don't feel like anything particularly complex was going on, just run of the mill rework to address review comments. So it seems weird to end up with unexplained commits in this context. > It isn't currently required though, so I can remove it. Though I'd then need to do a force push. Generally speaking, let's avoid force pushes unless required. But that's also a reason to avoid updating submodule pointers unless actually required: they tend to cause conflicts that then require force-pushes to resolve. So, in the future, please do not update submodule pointers unless there is a specific reason - and then be prepared to explain that reason :)
mpg (Migrated from github.com) reviewed 2026-01-26 03:33:58 -06:00
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
mpg (Migrated from github.com) commented 2026-01-26 03:33:58 -06:00

Am I missing something?

I don't think I'm missing anything. I applied the following patch and tests are still passing locally:

--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -1039,7 +1039,6 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int expected_ret)
     mbedtls_pk_context pub, prv, empty_ctx;
     mbedtls_svc_key_id_t wrapped_key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t wrapped_key_attr = PSA_KEY_ATTRIBUTES_INIT;
-    int ret;
 
     mbedtls_pk_init(&pub);
     mbedtls_pk_init(&prv);
@@ -1050,11 +1049,7 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int expected_ret)
     TEST_ASSERT(mbedtls_pk_parse_keyfile(&prv, prv_file, NULL)
                 == 0);
 
-    ret = mbedtls_pk_check_pair(&pub, &prv);
-    if (ret != 0) {
-        TEST_ASSERT(expected_ret == ret);
-        goto exit;
-    }
+    TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), expected_ret);
 
     /* Turn the prv PK context into an wrapped one.*/
     TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH,
> Am I missing something? I don't think I'm missing anything. I applied the following patch and tests are still passing locally: ```diff --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -1039,7 +1039,6 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int expected_ret) mbedtls_pk_context pub, prv, empty_ctx; mbedtls_svc_key_id_t wrapped_key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t wrapped_key_attr = PSA_KEY_ATTRIBUTES_INIT; - int ret; mbedtls_pk_init(&pub); mbedtls_pk_init(&prv); @@ -1050,11 +1049,7 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int expected_ret) TEST_ASSERT(mbedtls_pk_parse_keyfile(&prv, prv_file, NULL) == 0); - ret = mbedtls_pk_check_pair(&pub, &prv); - if (ret != 0) { - TEST_ASSERT(expected_ret == ret); - goto exit; - } + TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv), expected_ret); /* Turn the prv PK context into an wrapped one.*/ TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH, ```
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 04:15:58 -06:00
bjwtaylor (Migrated from github.com) commented 2026-01-26 04:15:58 -06:00

This is left over from debug, now removed.

This is left over from debug, now removed.
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 04:20:15 -06:00
@ -1046,3 +1032,3 @@
mbedtls_pk_init(&pub);
mbedtls_pk_init(&prv);
mbedtls_pk_init(&alt);
mbedtls_pk_init(&empty_ctx);
bjwtaylor (Migrated from github.com) commented 2026-01-26 04:20:14 -06:00

Agreed, now removed. Lets see if the CI agrees.

Agreed, now removed. Lets see if the CI agrees.
bjwtaylor (Migrated from github.com) reviewed 2026-01-26 08:29:10 -06:00
bjwtaylor (Migrated from github.com) commented 2026-01-26 08:29:10 -06:00

I've removed the comment and the unused context.

I've removed the comment and the unused context.
mpg (Migrated from github.com) reviewed 2026-01-27 02:28:35 -06:00
mpg (Migrated from github.com) left a comment
No description provided.
LGTM, thanks!
valeriosetti (Migrated from github.com) requested changes 2026-01-27 04:04:07 -06:00
valeriosetti (Migrated from github.com) left a comment

I only have 1 question, but a part from this it looks good to me

I only have 1 question, but a part from this it looks good to me
@ -1346,1 +1346,4 @@
pub->pub_raw_len == 0 ||
prv->pub_raw_len == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
valeriosetti (Migrated from github.com) commented 2026-01-27 03:54:11 -06:00

don't we want to also add a check for pub->pub_raw_len == 0 here?
I know the function is going to fail anyway because below there is prv->pub_raw_len != pub->pub_raw_len, but it would return a different error code. IMO PSA_ERROR_INVALID_ARGUMENT would be more appropriate. Wdyt?

don't we want to also add a check for `pub->pub_raw_len == 0` here? I know the function is going to fail anyway because below there is `prv->pub_raw_len != pub->pub_raw_len`, but it would return a different error code. IMO `PSA_ERROR_INVALID_ARGUMENT` would be more appropriate. Wdyt?
mpg (Migrated from github.com) reviewed 2026-01-27 04:28:31 -06:00
@ -1346,1 +1346,4 @@
pub->pub_raw_len == 0 ||
prv->pub_raw_len == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mpg (Migrated from github.com) commented 2026-01-27 04:28:31 -06:00

It shouldn't matter because in theory there is no situation where pk_info != NULL but pub_raw_len == 0. However in practice this might still happen (even though we'd consider it a bug).

In the long run, we'd like to remove pk_info, and since we want to keep checking that both contexts are valid (ie, populated), I think it makes sense to add a check for pub->pub_raw_len, which will remain when we remove pk_info in the future.

It shouldn't matter because in theory there is no situation where `pk_info != NULL` but `pub_raw_len == 0`. However in practice this might still happen (even though we'd consider it a bug). In the long run, we'd like to remove `pk_info`, and since we want to keep checking that both contexts are valid (ie, populated), I think it makes sense to add a check for `pub->pub_raw_len`, which will remain when we remove `pk_info` in the future.
valeriosetti (Migrated from github.com) approved these changes 2026-01-27 05:23:23 -06:00
valeriosetti (Migrated from github.com) left a comment

LGTM, thanks!

LGTM, thanks!
mpg (Migrated from github.com) approved these changes 2026-01-27 06:02:31 -06:00
valeriosetti commented 2026-01-27 06:27:15 -06:00 (Migrated from github.com)

@mpg I was about to add this PR to the merge queue when a question suddenly popped up: is the fact that after this PR we allow also opaque RSA keys to have check_pair something that's worth a changelog?
Perhaps the check_pair functionality is mostly used "internally" from the TLS side so this is not much of interest for final users. Moreover I don't want to delay this PR for no reason, so I'll let you decide whether it is OK or not to add the changelog or add to the merge queue

@mpg I was about to add this PR to the merge queue when a question suddenly popped up: is the fact that after this PR we allow also opaque RSA keys to have `check_pair` something that's worth a changelog? Perhaps the `check_pair` functionality is mostly used "internally" from the TLS side so this is not much of interest for final users. Moreover I don't want to delay this PR for no reason, so I'll let you decide whether it is OK or not to add the changelog or add to the merge queue
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-Mbed-TLS/TF-PSA-Crypto!580
No description provided.