-
Notifications
You must be signed in to change notification settings - Fork 18
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
MbedTlsError(-30592) after upgrading to commit d5e29f8 #60
Comments
Following the guidelines in the discussion that originated this issue I activated logs. |
Can anyone assist with this? @ivmarkov I noticed you referenced this on your PR, maybe you know what could cause this? |
I made some progress. I took the commit with the SHA acceleration which doesn't work for my use case, I removed all the SHA functions from the rs files and used the binaries from the previous commit that included their mbedtls versions, and ... it works. So it can be either that these functions that were replaced are the root cause or something different about the binary in terms of compilation/configuration options or something with the hardware acceleration generating different data ? Any ideas? Attached are the logs of the faulty session that fails. I fed the logs to ChatGPT to see what it has to say, this is what it came up with, but I don't know how to continue from here: Any assistance would be appreciated. -- Observations
Likely Causes1. Cipher Suite Mismatch or Unsupported Algorithm
2. Key Exchange Issue
3. Encryption or MAC Calculation
4. Data Corruption or Implementation Bugs
Next Steps1. Enable Detailed Server Logs
2. Reduce Cipher Suites
3. Verify Handshake Hash and Finished Message
4. Analyze Network Traffic
5. Configuration Check
If you can narrow down the logs to a specific area (or share server-side logs), further diagnosis can be provided! |
I think the most likely root cause is that the HW accel functions have a bug. Here's a short action plan:
#[no_mangle]
pub unsafe extern "C" fn mbedtls_sha1_starts(_ctx: *mut mbedtls_sha1_context) -> c_int {
0
}
#[no_mangle]
pub unsafe extern "C" fn mbedtls_sha1_update(
ctx: *mut mbedtls_sha1_context,
input: *const c_uchar,
ilen: usize,
) -> c_int {
let mut data = core::ptr::slice_from_raw_parts(input as *const u8, ilen as usize);
critical_section::with(|cs| {
// ===========> Copy roughly from here below
let mut sha = SHARED_SHA.borrow_ref_mut(cs);
let mut hasher = ShaDigest::restore(sha.as_mut().unwrap(), (*ctx).hasher.as_mut().unwrap());
while !data.is_empty() {
data = nb::block!(hasher.update(&*data)).unwrap();
}
nb::block!(hasher.save((*ctx).hasher.as_mut().unwrap())).unwrap();
// <=========== Until here
});
0
}
#[no_mangle]
pub unsafe extern "C" fn mbedtls_sha1_finish(
ctx: *mut mbedtls_sha1_context,
output: *mut c_uchar,
) -> c_int {
let mut data: [u8; 20] = [0u8; 20];
critical_section::with(|cs| {
// ===========> Copy roughly from here below
let mut sha = SHARED_SHA.borrow_ref_mut(cs);
let mut hasher = ShaDigest::restore(sha.as_mut().unwrap(), (*ctx).hasher.as_mut().unwrap());
nb::block!(hasher.finish(&mut data)).unwrap();
nb::block!(hasher.save((*ctx).hasher.as_mut().unwrap())).unwrap();
// <=========== Until here
});
core::ptr::copy_nonoverlapping(data.as_ptr(), output, data.len());
0
}
=> If you get differences, we have a problem, and we need to figure out where in the HW computation we are making a mistake ... and it is good to have such a test anyway. |
NOTE: You could also even temporarily replace/comment-out the HW computation with the algorithms from the |
Disabled, still doesn't work.
I'll try to follow your action plan and see if I understand your guidelines, I've never been into this crypto coding territory before. What I can say is that in the logs it looks like sha384 was chosen. |
Which sounds strange to me actually. It's a pretty primitive device, supporting only TLS 1.2, security there isn't that critical there really, so why would they choose sha384? Maybe there's some misunderstanding during the negotiation phase and one side thinks it's sha384 and the other sha256? That's why I wanted to see debug logs of the session that work but I can't figure how to build the mbedtls with the sha functions in debug mode. |
Btw, you don't have to do crypto-coding, just call existing algos. |
I've followed your general action plan but differently and solved it !!! What I did is as follows:
The hash for sha1, 224, 256, 384, 512 seemed the same initially, but I (accidentally) passed the large buffer to 224/256 and 284/512 since it's the same function for each pair. So I checked the code and noticed that in each function, in both cases the large internal data size is copied instead of smaller one in cases of 224 and 384. Once I changed that to 48 bytes in the case of sha384 it worked. So that's what needs to be fixed for both functions. Here are the hashes for SHA acceleration:
mbedtls:
|
Amazing! Could you try the following and see if this fixes the issue for hardware acceleration: diff --git a/esp-mbedtls/src/esp_hal/sha/sha256.rs b/esp-mbedtls/src/esp_hal/sha/sha256.rs
index 023641e..797a8f7 100644
--- a/esp-mbedtls/src/esp_hal/sha/sha256.rs
+++ b/esp-mbedtls/src/esp_hal/sha/sha256.rs
@@ -114,6 +114,7 @@ pub unsafe extern "C" fn mbedtls_sha256_finish(
);
nb::block!(hasher.finish(&mut data)).unwrap();
nb::block!(hasher.save((*ctx).sha224_hasher.as_mut().unwrap())).unwrap();
+ core::ptr::copy_nonoverlapping(data.as_ptr(), output, 28);
} else {
let mut hasher = ShaDigest::restore(
sha.as_mut().unwrap(),
@@ -121,8 +122,8 @@ pub unsafe extern "C" fn mbedtls_sha256_finish(
);
nb::block!(hasher.finish(&mut data)).unwrap();
nb::block!(hasher.save((*ctx).sha256_hasher.as_mut().unwrap())).unwrap();
+ core::ptr::copy_nonoverlapping(data.as_ptr(), output, 32);
}
});
- core::ptr::copy_nonoverlapping(data.as_ptr(), output, data.len());
0
}
diff --git a/esp-mbedtls/src/esp_hal/sha/sha512.rs b/esp-mbedtls/src/esp_hal/sha/sha512.rs
index e1cc4c9..dd270ab 100644
--- a/esp-mbedtls/src/esp_hal/sha/sha512.rs
+++ b/esp-mbedtls/src/esp_hal/sha/sha512.rs
@@ -114,6 +114,7 @@ pub unsafe extern "C" fn mbedtls_sha512_finish(
);
nb::block!(hasher.finish(&mut data)).unwrap();
nb::block!(hasher.save((*ctx).sha384_hasher.as_mut().unwrap())).unwrap();
+ core::ptr::copy_nonoverlapping(data.as_ptr(), output, 48);
} else {
let mut hasher = ShaDigest::restore(
sha.as_mut().unwrap(),
@@ -121,8 +122,8 @@ pub unsafe extern "C" fn mbedtls_sha512_finish(
);
nb::block!(hasher.finish(&mut data)).unwrap();
nb::block!(hasher.save((*ctx).sha512_hasher.as_mut().unwrap())).unwrap();
+ core::ptr::copy_nonoverlapping(data.as_ptr(), output, 64);
}
});
- core::ptr::copy_nonoverlapping(data.as_ptr(), output, data.len());
0
}
|
These were the exact changes I've made, I tested only the SHA384 since it's what I have but the rest looks good as well. BTW: from looking at the code, specifically 👍
It looks like the HW SHA is supported only on esp32s2 and esp32s3, so now esp-mbedtls won't work any longer on esp32 for example and all other chips? Also, it seemed to me like the way the code works is that espmbedtls initializes some memory area for the sha context, but it is based on its own internal structures for sha contexts, and the assumption is that there's enough memory there for the rust structures so the sha_init functions initializes this memory as if it was the rust context, is that indeed the case? |
I do not understand. Are you saying, that with the changes suggested by Anthony, it does work for you now, with HW accel, or not yet?
For esp32 and the others where sha256 and sha512 HW accel is missing, the library is compiled with the software mbedtls fallbacks for these algorithms, so it should all work (albeit slowly) on these chips.
My understanding is that there is no problem here. Mbedtls just tells you "initialize your internal buffers" and then the HW accel does that (with its own internal structures of course). Then mbedtls only carries around these internal HW accel structures, and passes them back to the HW accel when hashing. When the hashing is complete, mbedtls passes again these structures to the HW accel code, so that they can be released. But it does not assume anything about the layout and size of these structures at any point in time. |
Ah ok you have updated your original comment and I did not notice that... |
Yes, many times ... made so many mistakes along the way.
This binary usage raised another point I had in mind (maybe worth a separate discussion since I'm hijacking a thread again 😄 ), the crate depends on binaries as the source (at least the sha version which is the latest I was able to use). I think the correct approach should be (not sure if possible) to have every build (also on developer machine) compile mbedtls from source. But given I wasn't able to compile it myself I'm not sure if the toolset on all systems can support this.
Here is how I understand it, could be I'm missing something: If I get it right, the rust side of initialization starts in the shaXXX_init function as below.
It assumes it receives a pointer to memory buffer that can fit:
And only allocates memory for the Context pointers and fills pointers to them in that struct. But the struct itself is allocated by the client. In mbedtls, here is one usage which is easiest to show of the struct allocation and usage of init function:
Luckily it is a larger structure but future implementation may change how it works.
|
Baremetal folks do not want to deal with C toolchains just to compile the mbedtls C library. Hence we provide BTW If you are not ok with using binary blobs, you have other places to worry about as well. Namely, the Wifi libs in ESP-IDF (and baremetal!) are only supplied by Espressif as pre-compiled blobs. These blobs do contain security-related stuff as well, like a custom copy of With that said, if you are security-savy, you can always re-compile your own libs using the supplied xtasks which are actually well documented. But yes, that requires dealing with C toolchains provided by
As I said, this is possible. In fact, for the host and ESP-IDF targets, mbedtls IS compiled from source, always. But these targets do have the C toolchains installed by default (100% for ESP-IDF and almost always for the host) so that's a non-issue there. |
Your analysis is incorrect, because you are looking at the wrong stuff. Then look also here. |
BTW "always compiling from source" is not a panacea either. The recent injections of backdoors directly in GH source code repos masquerading themselves as "innocent" commits prove that. I guess it is not black and white, but levels of trust you want to accept to the upstream source code (or |
I must take this back, partially. With ESP-IDF, the For |
Providing pre-compiled wpa-supplicant and mbedtls static libraries is for convenience since setting up everything needed to compile those is ..... extremely inconvenient especially if the user won't need the C toolchains for anything else. (as Ivan already said) All other static libraries in esp-wifi-sys are not available in source (for reasons) I'd really wish we will see a pure-Rust replacement of wpa-supplicant some day (for a couple of reasons). (And we are currently going the same route for OpenThread - I'd love to see a pure Rust Thread implementation) However, all the scripts to compile all of that are available and people could build those on a trusted machine and cargo-patch those dependencies if they really want |
Maybe worth adding some instructions for poor Mac users like me on how to setup the toolchain to work on Mac. I couldn't get it to compile, had some issue with lld not supporting ZLib. |
Closing as fixed by d6e5041 Feel free to open a new issue addressing the build concerns, if any. I had a long-term goal of automatically building the libs in CI, whenever there's a change related to |
This is an issue as followup to discussion #57, so it's not forgotten.
I have a program that works using esp-mbedtls (async)
I upgraded to the latest commit, it required adding SHA parameter to the Session::new and did the same as the example.
I started receiving MbedTlsError(-30592) which based on error codes I found mean:
0x7780 SSL - A fatal alert message was received from our peer.
Note that I'm using TLS1.2 (that's why I'm using esp-mbedtls).
The issue is probably due to the use of
ca_chain: None
which wasn't considered in that change.The text was updated successfully, but these errors were encountered: