Skip to content
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

Support RSA key exchange methods in OpenSSL engine and Key Service #495

Open
quality-leftovers opened this issue Dec 15, 2022 · 6 comments

Comments

@quality-leftovers
Copy link
Contributor

quality-leftovers commented Dec 15, 2022

Since we are already using aziot_keys engine on our edge to connect to IoT Hub we've been wondering if it would also be possible to use it as "crypto backend" for a web server certificate (TLS 1.2+). As far as I understand this is currently not possible since the OpenSSL engine and the key service do not implement "decrypt".

Therefore I'd like to know if you have any plans to add the required functions to key service and the OpenSSL engine, or if you would be interested in a PR (not sure if we have the time and rust skills required for that PR, though).

Greets

@quality-leftovers
Copy link
Contributor Author

quality-leftovers commented Dec 16, 2022

Hm I did some testing with an ASP .NET Core Server connected to the key service and I'm a bit confused now.

I expected it to fail for TLS 1.2 due to the missing decrypt during pre-master secret exchange, but it actually works. So it seems some other algorithm was used during that exchange / handshake? I thought only for TLS 1.3 the server would not need to decrypt something. So I'm happy that it worked, but unhappy that I don't understand why it did so far and also don't know how algorithms are selected, etc.

The only thing that was blocking me initially was that my test setup created a self signed cert using .NET libraries and the .NET crypto libraries refused to "do the sign" until I added openssl_sys2::RSA_set_flags(parameters, RSA_FLAG_EXT_PKEY) to engine_load_privkey in the OpenSSL engine.

@quality-leftovers
Copy link
Contributor Author

quality-leftovers commented Dec 19, 2022

Okay, so I think I've really missed all important stuff in the docs. It seems there are tests for use of server certificates and even a sequence diagram that shows edge hub retrieving a server certificate.

Also it seems that I probably just need to configure openssl using an openssl.cnf so that only ciphers that work are offered to clients.

What I'm still not sure is what aside from implementing /decrypt I'd need to do to support the ciphers with key exchange RSA (for legacy clients). I implemented /decrypt for RSA and it it works via OpenSSL engine, but is not called when a client tries to connect using a cipher with RSA key exchange. I assume that the problem here is down to me not understanding how OpenSSL works and what an engine needs to do to support such a cipher. I'll work on my understanding, before bothering you futher :)

@onalante-msft
Copy link
Contributor

Sorry I missed this. I am not too sure myself what the exact process to get /decrypt working with a custom engine is. @arsing would know best on account of having written the aziot-keys OpenSSL engine subsystem, but they are currently out until 30-12-2022. I am not sure whether I can get to this before then since other bugs are currently occupying my time, but I will take a look if my workload clears up.

@arsing
Copy link
Member

arsing commented Jan 1, 2023

It seems there are tests for use of server certificates [...]

Yes, https://github.com/Azure/iot-identity-service/blob/main/key/test-aziot-key-openssl-engine-shared.sh

[...] and even a sequence diagram that shows edge hub retrieving a server certificate.

Which diagram is that? If you mean https://github.com/Azure/iot-identity-service/blob/main/docs-dev/openssl-engine-internals.md that is not about Edge Hub, just an arbitrary client. Edge Hub's server cert does not have a key backed by the OpenSSL engine, because Edge modules like Edge Hub do not have access to the Keys Service to be able to do key operations. Edge modules get certs with the keys in plaintext via the edged workload API.

I expected it to fail for TLS 1.2 due to the missing decrypt during pre-master secret exchange, but it actually works. So it seems some other algorithm was used during that exchange / handshake?

Decrypting with the RSA private key (RSA_priv_dec) is indeed not implemented (

unsafe extern "C" fn aziot_key_rsa_method_priv_dec(
_flen: std::os::raw::c_int,
_from: *const std::os::raw::c_uchar,
_to: *mut std::os::raw::c_uchar,
_rsa: *mut openssl_sys::RSA,
_padding: std::os::raw::c_int,
) -> std::os::raw::c_int {
// TODO
-1
}
). It would only be used in RSA handshakes, and openssl prefers DH handshakes (as it should) which do not require decrypting the pre-master secret with the private key.

Note that the key exchange algorithm is unrelated to the key algorithm of the certificate. ie the fact that your cert has an RSA key does not mean the key exchange algorithm must be RSA.

What I'm still not sure is what aside from implementing /decrypt I'd need to do to support the ciphers with key exchange RSA (for legacy clients).

Do you really have clients that require RSA key exchange ciphersuites because they don't support DH? I'd really rather not implement RSA_priv_dec in keyd.

@quality-leftovers
Copy link
Contributor Author

It seems there are tests for use of server certificates [...]

Yes, https://github.com/Azure/iot-identity-service/blob/main/key/test-aziot-key-openssl-engine-shared.sh

[...] and even a sequence diagram that shows edge hub retrieving a server certificate.

Which diagram is that? If you mean https://github.com/Azure/iot-identity-service/blob/main/docs-dev/openssl-engine-internals.md that is not about Edge Hub, just an arbitrary client. Edge Hub's server cert does not have a key backed by the OpenSSL engine, because Edge modules like Edge Hub do not have access to the Keys Service to be able to do key operations. Edge modules get certs with the keys in plaintext via the edged workload API.

Thanks for clarification. I just thought that the KS was used by all components in est diagram since KS is not shown for connection to DPS. Probably didn't think too hard since the diagram clearly shows that the EdgeHub receives server cert + private key which makes no sense for KS keypairs.

I expected it to fail for TLS 1.2 due to the missing decrypt during pre-master secret exchange, but it actually works. So it seems some other algorithm was used during that exchange / handshake?

Decrypting with the RSA private key (RSA_priv_dec) is indeed not implemented (

unsafe extern "C" fn aziot_key_rsa_method_priv_dec(
_flen: std::os::raw::c_int,
_from: *const std::os::raw::c_uchar,
_to: *mut std::os::raw::c_uchar,
_rsa: *mut openssl_sys::RSA,
_padding: std::os::raw::c_int,
) -> std::os::raw::c_int {
// TODO
-1
}

). It would only be used in RSA handshakes, and openssl prefers DH handshakes (as it should) which do not require decrypting the pre-master secret with the private key.
Note that the key exchange algorithm is unrelated to the key algorithm of the certificate. ie the fact that your cert has an RSA key does not mean the key exchange algorithm must be RSA.

What I'm still not sure is what aside from implementing /decrypt I'd need to do to support the ciphers with key exchange RSA (for legacy clients).

Do you really have clients that require RSA key exchange ciphersuites because they don't support DH? I'd really rather not implement RSA_priv_dec in keyd.

Our edge is running in a factory and offers services to third party client applications. At times these software components run on machines that are up to 30 years old and while obviously there is a cut off (e.g. not supporting TLS 1.1) we'd like to offer "good old plain RSA" ciphersuites which is still better than doing no TLS at all.

I'd like to add that the setups with such old machines I've seen so far usually had pretty tight networking setups with hardware firewalls blocking all TCP connections to machines and only allowing outgoing TCP connections from machines to specific "safe" endpoints, so it's not the typical scenario of running a "weak(er)" TLS over the internet.

@arsing arsing changed the title Support for server certificate (TLS 1.2, TLS 1.3) in OpenSSL engine and Key Service Support RSA key exchange methods in OpenSSL engine and Key Service Mar 13, 2023
@quality-leftovers
Copy link
Contributor Author

In case anyone else needs RSA decrypt for some reason I tried to implement it: https://github.com/quality-leftovers/iot-identity-service/tree/feat/rsadec. It seems to be working, luckily almost all stuff needed was already in place so even with my limited rust knowledge I was able to do it.

Only manually tested encrypt/decrypt via the OpenSSL engine yet, though and no automated tests of course :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants