-
Notifications
You must be signed in to change notification settings - Fork 52
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
P256 keys using Secure Enclave and Android StrongBox #245
P256 keys using Secure Enclave and Android StrongBox #245
Conversation
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.
Nice 👍
Will the is_hardware_backed also be exposed over FFI?
include/libaries_askar.h
Outdated
* id is an optional argument only required for hardware-bound keys | ||
*/ | ||
ErrorCode askar_key_generate(FfiStr alg, | ||
int8_t hardware_backed, |
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.
Instead of marking something as hardware_backed, should this be a more generic parameters so it's a bit more ready for future changes? E.g. "key_backend" which can take a value of secure_env
, or something like strongbox
? I foresee us using the same capabilities for cloud HSM, with possibly multiple backends configured, and it might be nice to make it a backend rather than strictly hardware_backed?
Just a thought, this approach seems fine as well
8949028
to
13a66c8
Compare
In credo we sign based on the public key, will that also be possible with the hardware keys? Or do we need to pass the key id specifically? |
Do you have an example of this code? If I can check which path it takes I can see whether it'll work or not. I don't think we can go from a public key to storage and get the HSM key. Software keys are stored as a JWK, but for secure element keys I chose to store just the id. If this is a very strong requirement I could do something like: {
"id": "CUSTOM_USER_DEFINED_ID",
"public_key_base58": "bla..."
} instead of the id alone. |
Could we make the id the public key? Or is it generated by the secure enclave? this is the code in Credo, we fetch the key based on the publicKeyBase58: https://github.com/openwallet-foundation/credo-ts/blob/8f49d84d52143bd9136cebd502bd9d10b5881463/packages/askar/src/wallet/AskarBaseWallet.ts#L214 If we can't do that, it will require A LOT of effort in Credo, as we would have to introduce a new concept of keyIds (which is a good thing probably), but it will be a big breaking chagne as we pass a |
In Credo we store the key using publicKeyBase58 as its name (id). Does this new approach prevent us from specifying the id we want when creating a key in hardware? |
Yes! The name is not equal to the underlying Secure Element id, they are separate identifiers.
We can defer it for now, and possibly introduce it later, but it is not required.
No it does not. It will work exactly the same as before. |
Okay perfect, sounds good :) |
@@ -14,9 +43,11 @@ pub struct KeyParams { | |||
|
|||
/// An optional external reference for the key | |||
#[serde(default, rename = "ref", skip_serializing_if = "Option::is_none")] | |||
pub reference: Option<String>, | |||
pub reference: Option<KeyReference>, |
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 expected that the reference field would be something like "secure_element:{key_id}" and the data field would be empty in this case, but I suppose this works too and might be better for indexing keys.
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 am not too set on either approach. I can leave it as-is or change it to w/e is your preferred method.
askar-crypto/src/alg/any.rs
Outdated
fn generate_with_rng(alg: KeyAlg, rng: impl KeyMaterial) -> Result<Self, Error>; | ||
|
||
/// Generate a new key with an id for the given key algorithm. | ||
fn generate_with_id(alg: KeyAlg, id: &str) -> Result<Self, Error>; |
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 seems to be restricted to hardware backed keys, and the naming doesn't really reflect that for me. Do we need to accept the ID as an argument or could it just be generated automatically?
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.
Right now the id is generated in the FFI layer. I could also defer this to askar-crypto
where I replace generate_any_with_id
with generate_any_hardware
and generate the id there. This would also remove the uuid
dependency from aries-askar
, but would introduce it into askar-crypto
.
I will implement it like this, but also open to other suggestions.
src/ffi/key.rs
Outdated
KeyBackend::Software => LocalKey::generate_with_rng(alg, ephemeral != 0), | ||
KeyBackend::SecureElement => { | ||
let id = Uuid::new_v4().to_string(); | ||
LocalKey::generate_with_id(alg, &id, ephemeral != 0) |
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.
Is it appropriate to support 'ephemeral' for these keys?
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.
Is it appropriate to support 'ephemeral' for these keys?
The underlying library does not yet implement the deletion of keys, so ATM not really no. Once it is there, it would be fine imo to support it. Otherwise we would also have to create a new FFI function for it or make it an optional argument.
Looks great so far, maybe there would be a need to inspect what backends are supported by Askar for the current platform? |
Yes that should be quite easy based on the feature flags. I will add it to |
bd315cc
to
9e9ae56
Compare
CI is finally finished so it is ready. |
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
9e9ae56
to
c4425f2
Compare
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
e64a60e
to
8b64450
Compare
test('supported backends', () => { | ||
const backends = ariesAskarNodeJS.keyGetSupportedBackends() | ||
|
||
expect(backends.length).toStrictEqual(1) | ||
expect(backends).toStrictEqual(expect.arrayContaining(['software'])) | ||
}) |
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.
Maybe it should also support returning which backends are supported for which key, but I'm als fine to add that in the future
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.
Yeah that would be a good one. A bit more difficult to check dynamically, but it should be fine to track that statically.
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.
LGTM. Maybe @andrewwhitehead can also give a final ✅ if everythings looks ok?
81a925b
into
openwallet-foundation:main
This PR contains the functionality to add support for hardware-backed P256 keys on iOS and Android Using iOS Secure Enclave and Android StrongBox. This is done by using the secure-env library. iOS is accessed via
Security.framework
and Android via JNI. Using these features you must build the library withmobile_secure_element
oraskar-crypto
directly withp256_hardware
.During the implementation I ran into some issues due to
askar-crypto
beingno_std
. because of this I made therng: impl KeyMaterial
optional as well as theid: &str
. My initial intention was to create a structure or enum forKeyGenOps
, but due to not always having access to an allocator I could not leverageBox
and dynamic dispatch. If there are any solutions for this, I would be happy to change the current implementation.askar-crypto
now also has a method to get the key by id. Which tiesaskar-crypto
directly to storage, but I could not find any other way of doing this due to the nature of Secure Elements.Over FFI, when supplying anid
toaskar_key_generate
, the key will be created on hardware. This seems a bit too implicit for me. My next approach would be generate a random id,uuid
or something and simply pass in a boolean forhardware_backed
.Implemented that we generate an id now for secure element keys and the user just has to provide
hardware_backed
argument over FFI as an i8.Still in draft for now, as I have to do some testing.
Will also include an updated python wrapper (only software as key_backend allowed) and an updated node.js wrapper. React Native will be done in #247 as that will also include the React Native Example app and move to pnpm.