-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
extmod/mbedtls: Support Alternative Functions Implemented in Python. #15905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0f3841a
to
6dd64e9
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #15905 +/- ##
=======================================
Coverage 98.57% 98.57%
=======================================
Files 164 164
Lines 21341 21345 +4
=======================================
+ Hits 21036 21040 +4
Misses 305 305 ☔ View full report in Codecov by Sentry. |
Code size report:
|
6dd64e9
to
9844dfe
Compare
66ab8ff
to
c15b7c6
Compare
c15b7c6
to
e0b4fcf
Compare
Anything else needs to change here ? |
extmod/modtls_mbedtls.c
Outdated
} | ||
|
||
// Convert the MPI private key (d) to a binary array | ||
ret = mbedtls_mpi_write_binary(d, key, klen); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make more sense to pass this argument in to the Python function as a Python (big) integer? After all, that's what it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, but I think it's more efficient this way, note the bytearrays are passed by reference.
I agree that this is more general than #15817. Did you consider putting the new function on the |
Yes I did, that's actually how I wanted to implement this originally, but quickly realized that there's no way to get the SSL object in mbedtls functions. It's not an issue though, because that's what the fallback is for; if another context uses regular keys, it will still function. FWIW this is how this feature is currently used: This is not merged, waiting on it to be merged upstream first. |
I think we should try to implement it this way, as an attribute per I think that's a lot more flexible, and would interoperate well with other extensions like DTLS #15764 which may not want to use custom signing. |
Sure, I'll get around to making all of the requested changes next week. I will retest everything and need to send a PR to micropython-lib. |
OK, great, thanks! I think having the callback on the // in py/mpconfig.h
#define MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT (MICROPY_PY_SSL_ECDSA_SIGN_CALLBACK)
// in py/mpstate.h, mp_state_thread_t struct
#if MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT
struct _mp_obj_ssl_context_t *tls_ssl_context;
#endif
// in extmod/modtls_mbedtls.c
static inline void store_active_context(mp_obj_ssl_context_t *ssl_context) {
#if MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT
MP_THREAD_STATE(tls_ssl_context) = ssl_context;
#endif
}
// at start of functions that call into mbedtls
store_active_context(ssl_context);
// could also do this at end of functions, but not necessary
store_active_context(NULL); |
@dpgeorge Can we add the callback attribute to
If the root pointer is not cleared, would this stop the socket from being collected after its closed ? |
This callback gets invoked to perform ECDSA signing if enabled. See micropython/micropython#15905 Signed-off-by: iabdalkader <[email protected]>
We are trying hard to keep I'm not sure what you mean by "portability" here? It won't be portable to CPython, and any existing MicroPython code needs to update to firmware that supports this callback, and that firmware will have the new |
It will stop the |
e0b4fcf
to
578676f
Compare
Ah I sent a PR but will remove it.
I usually just import the
I've updated the code, it now stores the context before certain functions, read, write, wrap_socket, and clears it on stream close. Will that be enough ? |
578676f
to
495c6ca
Compare
extmod/mbedtls/mbedtls_alt.c
Outdated
} | ||
|
||
size_t len = 0; | ||
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &s)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably needs to be MBEDTLS_ASN1_CHK_CLEANUP_ADD? Also the ones below.
Also, could this function copy directly into sig
, instead of using temporary buf
? So start p = sig + sig_size
, and buf
would be sig
. Then it should not underflow this buffer. At the end it can do memmove
to shift the data down to the start of sig
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably needs to be MBEDTLS_ASN1_CHK_CLEANUP_ADD?
Yes this makes sense because in this function there's a cleanup
label.
Also, could this function copy directly into sig,
Here I'm just following the reference implementation, see ecdsa_signature_to_asn1
. I'm a bit reluctant to change this code. It's not any less efficient than the default implementation and the buffer is stack based so no dynamic memory.
d6d5d3b
to
0e7f984
Compare
I wanted to document this new attribute, but I couldn't find any docs for the new tls module to begin with. |
0e7f984
to
37983a6
Compare
This will eventually need docs... but we somehow forgot to document the Also would be good to add some tests for this new functionality, that can be run with the unix coverage build. That's also very difficult, it requires at least having a loopback socket and creating a dummy TLS connection. For now, testing on hardware is good enough. |
This is necessary for mbedTLS callbacks that do not carry any user state, so those callbacks can be customised per SSL context. Signed-off-by: iabdalkader <[email protected]>
This commit enables the implementation of alternative mbedTLS cryptography functions, such as ECDSA sign and verify, in pure Python. Alternative functions are implemented in Python callbacks, that get invoked from wrapper functions when needed. The callback can return None to fall back to the default mbedTLS function. A common use case for this feature is with secure elements that have drivers implemented in Python. Currently, only the ECDSA alternate sign function wrapper is implemented. Tested signing with a private EC key stored on an NXP SE05x secure element. Signed-off-by: iabdalkader <[email protected]>
Changes: - Add ISO7816, APDU and SE05x package. - Add support for Opta Expansion protocol. Signed-off-by: iabdalkader <[email protected]>
Signed-off-by: iabdalkader <[email protected]>
Signed-off-by: iabdalkader <[email protected]>
Signed-off-by: iabdalkader <[email protected]>
37983a6
to
4c54335
Compare
Summary
This patch enables the implementation of alternative mbedtls cryptography functions, such as ECDSA sign and verify, in pure Python. Alternative functions are implemented in Python callbacks, that get invoked from
wrapper functions when needed. If the callback fails to sign using the provided key, the calling code falls back to the default mbedtls function. A common use case for this feature is with secure elements that have drivers implemented in Python. Currently, only the ECDSA alternate sign function wrapper is implemented.
Testing
I tested signing using a private EC key stored on a secure element (NXP's SE05x) and with the key stored on the filesystem (DER) both work fine.
Trade-offs and Alternatives
An alternative is adding the drivers/libraries of every secure element we wish to support, make them portable and provide port-specific code, as implemented in my previous PR: #15817
Example usage: