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

Added all missing ops listed in Service API that Mbed Crypto support … #48

Merged

Conversation

sbailey-arm
Copy link
Contributor

@sbailey-arm sbailey-arm commented Jul 28, 2020

…(plus some it doesn't) found here.

The goal of this PR is to add all operations listed in the Single-part Service API table that are currently supported by Mbed Crypto. Since there are more than a couple of additions, here is a breakdown:

psa_key_derivation_output_key - supported, added, *
psa_copy_key - supported, added
psa_purge_key - unsupported, added
psa_hash_compute - supported, added
psa_hash_compare - supported, added
psa_mac_compute - unspported, added, ***
psa_mac_verify - unsupported, added, ***
psa_cipher_encrypt - unsupported, not added
psa_cipher_decrypt - unsupported, not added
psa_aead_encrypt - supported, added, ***
psa_aead_decrypt - supported, added, ***
psa_sign_message - unsupported, not added
psa_verify_message - unsupported, not added
psa_key_derivation_key_agreement - supported, added, *, **
psa_raw_key_agreement - supported, added

supported/unsupported - whether Mbed Crypto has support for this operation
added/not added - whether the operation has been added to psa-crypto in this PR

* - these don't actually appear to be single-part operations and probably shouldn't be in that Single-part operation API table. However, psa_key_derivation_output_key was almost complete before @hug-dev and I realised that so I completed them anyway.
** - psa_key_derivation_key_agreement appears as a separate operation in the API table. I took a different approach with it. It looks like just another input step so I've integrated it into the psa_key_derivation_output_key operation.

To give a quick overview of what goes on with key derivation in the PSA spec, you have to create an operation struct and then call multiple input functions on it in order to give the operation data (either byte buffer or a key) to use at each step
in the derivation process (which steps you need to provide data for and the format required is dependant on the derivation algorithm. After you've set it up, you call psa_key_derivation_output_key to perform the actual derivation.

The general design of this particular multi-part operation is instead of having the user call multiple 'sub' operations, they provide all of the data upfront. A benefit of this is you can check before the operation is called
whether the correct data for the requested algorithm has been provided (or rather, you can't call it without providing the correct data). It started with just allowing byte buffers or key IDs, but as I mentioned, I expanded
it to include data required for a key agreement too.

*** - There is a potential problem with a truncated MAC. Creating a truncated MAC with the C macro is unspecified if 'mac_length is too small or too large for the specified MAC algorithm.'. The requirements for mac_length are 'This must be at most the full length of the MAC and must be at least an implementation-specified minimum. The implementation-specified minimum must not be zero.'.

The first requirement (must be at most the full length of the algorithm) should be easy enough to look up, but I can't find any indicators as to the min value that Mbed Crypto supports. The tests indicate that this value is 1, but I can't see any documentation for it.

We also don't currently do any checking on the values a user could put into our Mac::Truncated enum struct, which is what is passed to the macro. We could declare a separate Truncated struct, make the members private (outside of psa-crypto) to force users to use Truncated::new where we could do a runtime check on length, and have the enum hold that struct, but we still don't have anything to check against

The same is true for Aead. This should perhaps be listed as an issue, but since I noticed it yesterday and the PR was ready, I included it here.

Signed-off-by: Samuel Bailey [email protected]

@ionut-arm
Copy link
Member

While this one is somewhat okay, I strongly recommend adding them in smaller groups in the other repos, large PRs are very difficult to review.

@sbailey-arm sbailey-arm force-pushed the add-all-missing-operations branch 2 times, most recently from 63ea5a9 to a6d032d Compare July 28, 2020 10:34
@sbailey-arm
Copy link
Contributor Author

While this one is somewhat okay, I strongly recommend adding them in smaller groups in the other repos, large PRs are very difficult to review.

Ok. I was asked if it'd be possible to do them in one to make it easier to review, but perhaps this is a bit overboard...! I'll cut them up into smaller groups in the rest of the repos to make them more bitesize (infact @joechrisellis might be taking on some of the operations (e.g. the hash operations) too).

@sbailey-arm sbailey-arm marked this pull request as ready for review July 28, 2020 10:50
@ionut-arm
Copy link
Member

My problem with large PRs is summarised by:

But then again, everyone has their style of reviewing! If the change is really simple it could work, I guess

@sbailey-arm
Copy link
Contributor Author

My problem with large PRs is summarised by:

But then again, everyone has their style of reviewing! If the change is really simple it could work, I guess

Yep I see your point 😄. Maybe I should try reviewing some PRs 😅! Anyway, these changes shouldn't be too complex (if the multi-part ops are, let me know and I'll pull them out) and I'll split it up for the rest of the repos 🙂.

.to_result()?;
operation.alg.apply_inputs_to_op(&mut op)
} {
operation.abort(op)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should abort on every possible exit step once we did the init?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key derivation setup, input bytes and input key state that if they return an error, you have to call abort.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. That would mean that we have to add abort calls above in psa_key_derivation_setup fails

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should do already, I think? The call to psa_key_derivation_setup and to apply_inputs_to_op (that method sort out calling the correct input functions) are wrapped in the same block that listens for an error. I was going to do it separately, then realised I could block them together.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the error line 238, can't we escape the function without abort if we leave it at:

.to_result()?

?

Comment on lines 501 to 509
/// Enumeration of supported input data for different input steps
#[derive(Debug, Clone)]
pub enum Input<'a> {
/// Byte input for key derivation
Bytes(&'a [u8]),
/// Key input for key derivation
Key(Id),
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used only in key derivation operations or also somewhere else? If not it is maybe better located inside the key derivation file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It already is 🤔. Not sure how it ended up in both! I've removed the one in algorithm.rs

fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_FULL_LENGTH_MAC(alg) {
Ok(Mac::FullLength(alg.try_into()?))
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if alg is not a MAC algorithm? What if it is a RSA algorithm for example? Do we need to check if it is a MAC algorithm, truncated or not before?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit confused what you mean here. If it ends up in this method to begin with, it has to be a MAC algorithm, otherwise the code above this method isn't working correctly. The block starting on line 544 (the TryFrom<psa_crypto_sys::psa_algorithm_t> for Algorithm is what directs MAC algorithms to this particular method.

Copy link
Member

@ionut-arm ionut-arm Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has to be a MAC algorithm

impls are "public", though - if someone has a psa_algorithm_t and they do Mac::try_from(alg), this gets called, regardless of what that alg was. You can throw in a PSA_ALG_IS_MAC to begin with

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see what you mean. There should be a fail case for TryFrom, otherwise you'd use From.

Mac::Truncated {
mac_alg: alg,
mac_length: length,
// The following call is NOT currently checked. If length is invalid, the return of this call is unspecified
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to restrict the Truncated instances to only the safe ones. Probably in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed 🙂.

// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0

//! # PSA Operation types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it the good title 🕵️ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to PSA Key Derivation Operation Types.

};
let mut handle_for_new_key = 0;

let mut op: psa_crypto_sys::psa_key_derivation_operation_t = operation.clone().try_into()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could operation be Copy? Is it that big?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for not implementing Copy on this was to stop the user ending up with an operation that they could use after it was aborted. The current way it is setup, once the user calls the key derivation operation, they cannot use that operation again.

When you call abort of the C struct, it resets it to default values, which are not 'valid'. I didn't want to make the types on operation Option<T> as I don't think it fits, so there is no way to reset the Rust operation struct, you have to start again, specifying the inputs you want at each stage for whatever algorithm you're using.

Another way of doing it would be to allow the user to keep their operation struct and re-use it. Its just with the abort in Mbed Crypto, I was trying to replicate it. Now that I think about it, I can't think of a reason why it shouldn't be done like that.

This is more of a Rust thing but I find that clone a bit annoying. I played around with making the TryFrom method take a reference, but then it got upset when I had the abort there as there was still a living borrow. I get why its complaining, but I know the borrow isn't used (e.g. stored) for use after TryFrom returns!

Copy link
Member

@ionut-arm ionut-arm Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to stop the user ending up with an operation that they could use after it was aborted.

They can still clone it, right? An alternative is to implement your own internal clone that's only visible to this crate.

Or a TryFrom<&KeyDerivationOperation> if that's possible, I think that's a thing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or a TryFrom<&KeyDerivationOperation> if that's possible, I think that's a thing

That's what I was referring to in this comment. You can have a TryFrom with a borrow, but that doesn't solve this problem ☹️.

This is more of a Rust thing but I find that clone a bit annoying. I played around with making the TryFrom method take a reference, but then it got upset when I had the abort there as there was still a living borrow. I get why its complaining, but I know the borrow isn't used (e.g. stored) for use after TryFrom returns!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen for the slices when cloning? Will that make deep copies of them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm good question. Slice doesn't seem to implement Clone. It could copy the reference but then you could end up with a dangling pointer, which Rust doesn't allow 🤔.

)
})
.to_result()?;
operation.abort(op)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as previously, do you think we need to abort on every exit path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. If you look at the last key derivation step, you have to call abort to clean up its resources.

/// let my_key = key_management::generate(attributes, None).unwrap();
/// let my_key_copy = key_management::copy_key(my_key, attributes, None);
/// ```
pub fn copy_key(key_id_to_copy: Id, attributes: Attributes, id: Option<u32>) -> Result<Id> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When thinking about it, we removed the "key" from all function names: this should probably be copy. Similar for export_key above, it should maybe be export. And purge below.

Comment on lines 400 to 405
/*
pub fn purge_key(key_id: Id) -> Result<()> {
initialized()?;
let handle = key_id.handle()?;
Status::from(psa_crypto_sys::psa_purge_key(handle)).to_result()
}*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to still keep the function but have an empty implementation for now? Using a log to notice it, with the same comment that you have above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've commented out the code and the example so now all it does is use the error macro. Is this what you meant?

/// # sign_message: true,
/// # ..Default::default()
/// # },
/// # permitted_algorithms: Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256}).into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have a From<FullLength> implementation on FullLengthMac to directly do:

FullLengthMac::Hmac{hash_alg: Hash::Sha256}.into()

Copy link
Member

@hug-dev hug-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for your work, that is amazing. I put some comments to start a discussion but I really appreciate the care you took making things look nice.

I have reviewed the last 8 files, I believe @ionut-arm will review the 7 first.

/// Key derivation algorithm and inputs
pub alg: KeyDerivationWithInputs<'a>,
/// Maximum capacity of a key derivation operation
pub capacity: Option<usize>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the specs I can read:

For some algorithms, this step is mandatory because the output depends on the maximum capacity.

If we know for which ones this is mandatory, we can force it for them and leave it as Option for the other ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did look into doing exactly that but couldn't find any documentation that states for which algorithms capacity is mandatory 😞.

/// Salt, used in the "extract" step. It is optional; if omitted, the derivation uses an empty salt.
/// Typically a direct input, can also be a key of type `RawData`.
salt: Option<Input<'a>>,
/// Secret, used in the "extract" step. Must be `Input::Key(Id)` if used with `psa_key_derivation_output_key`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You write in multiple places:

Must be Input::Key(Id) if used with psa_key_derivation_output_key

Would there be a way to force that in the type system?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't think of a clean way of doing it. An option would be to have it as a parameter on the method to force Input::Key(Id) but that seems a bit janky. I can have another think about it after everything else is sorted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow... KeyDerivationOperation is only usable with psa_key_derivation_output_key - or is there more to come?


/// Enumeration of the step of a key derivation.
#[derive(Debug, Clone, Copy)]
pub enum DerivationStep {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be Step 🧹

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about this one - not sure if Step is so common a term in this kind of context to be fully clear what it means without the Derivation part of the name

/// HKDF algorithm.
Hkdf {
/// A hash algorithm to use
hash_alg: Hash,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the hash alg actually used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When converting to FullLengthMac::Hkdf as it takes a hash algorithm (as does the C macro to build a Hkdf derivation algorithm).

let close_handle_res = key_id.close_handle(key_handle);
let final_mac_verify_res = match mac_verify_res {
Status::Success => Ok(true),
Status::Error(Error::InvalidSignature) => Ok(false), // Indicates operation successful but compare did not match
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is an InvalidSignature error, it could make sense to just return Result<()> from this function!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally did that but thought since the operation is 'successful' in the event of an InvalidSignature error, it should tell the user that the operation completed successfully but the comparison did not match. I guess it doesn't actually matter that much and just returning the error is slightly simpler 🤔.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess Result<Result<()>> is more correct, but fugly

#[derive(Debug, Clone)]
pub struct KeyDerivationOperation<'a> {
/// Key derivation algorithm and inputs
pub alg: KeyDerivationWithInputs<'a>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alg could be named inputs, KeyDerivationWithInputs could be named Inputs


/// Key derivation operation for deriving keys from existing sources
#[derive(Debug, Clone)]
pub struct KeyDerivationOperation<'a> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still about naming: would it be nicer if this file is named key_derivation and this structure Operation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, the shorter file name still conveys what's there. Just calling it Operation could be confusing for people if they have multiple different types of Operation in the same place, but they can just rename it themselves in the import statement.

Copy link
Member

@ionut-arm ionut-arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes, it's really good to have the whole API exposed in Rust! 🚀

I'll review the files that Hugues went over next, but it looks like he spotted pretty much everything 😂

Comment on lines 122 to 123
shim_PSA_ALG_IS_FULL_LENGTH_MAC (psa_algorithm_t alg) {
return PSA_ALG_IS_BLOCK_CIPHER_MAC (alg);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a copy-pasta error or are cipher MACs defined to be full-length only? I can't see anything in that sense in the spec

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that is an error. The conversion code is going to need re-jigging if we don't have access to a macro that does something like the name of this one suggests 🤔.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a macro PSA_ALG_FULL_LENGTH_MAC that converts any MAC algorithm (truncated or not) to its full length version - you could return something like PSA_ALG_FULL_LENGTH_MAC(alg) == alg?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, that's nice an elegant!

Comment on lines 8 to 47
pub fn PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(aead_alg: psa_algorithm_t) -> usize {
const TAG_LENGTH_MASK: u8 = 0b00111111; // tag lengths are 6 bits in length
const PSA_V1_0_0_TAG_LENGTH_START_BIT: u32 = 16; // tag length at bit position [21:16]

let pre_mask_tag_length = aead_alg >> PSA_V1_0_0_TAG_LENGTH_START_BIT;

(pre_mask_tag_length as u8 & TAG_LENGTH_MASK) as usize
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a simple test just below this?

Comment on lines 81 to 83
Status::Success => Ok(true),
Status::Error(Error::InvalidSignature) => Ok(false), // Indicates operation successful but compare did not match
Status::Error(error) => Err(error),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is this expected? As in, to differentiate between InvalidSignature and other errors, as I'm assuming that's the reason for returning a bool.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to return Result<()> as with the other occurrence above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you 👀 ? Sorry if you did not push everything yet 😅

Comment on lines 55 to 60
/// # use psa_crypto::operations::hash::{hash_compute, hash_compare};
/// # use psa_crypto::types::algorithm::Hash;
/// # const MESSAGE: [u8; 32] = [
/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
/// # ];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why these are "hidden" here but similar lines are visible in the AEAD examples?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really! I'm not sure which bits should be hidden and which shouldn't. I was trying to make all 'obvious' code hidden with the less obvious code not. However, what 'obvious' actually means will depend on who you ask. E.g. I tried to make sure the bits that took a while to get working (e.g. correct key types, sizes, policy flags and algorithms) weren't hidden.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to hide the actual values/buffers, as the type really isn't something unusual or hard to grasp. Maybe the imports are actually useful is someone wants to just copy-paste code straight from the example, but yeah, really not sure.

As long as they're consistent, choose whatever makes sense to you!

/// let length = aead::aead_encrypt(my_key, alg, &NONCE, &ADDITIONAL_DATA, &INPUT_DATA, &mut output_buffer).unwrap();
/// output_buffer.resize(length, 0);
/// ```
pub fn aead_encrypt(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Hugues suggested - these are already namespaced, you can just call them encrypt, decrypt - similarly for the hash ones


let pre_mask_tag_length = aead_alg >> PSA_V1_0_0_TAG_LENGTH_START_BIT;

(pre_mask_tag_length as u8 & TAG_LENGTH_MASK) as usize
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a need for converting to u8 since you convert to usize immediately after? I think just & TAG_LENGTH_MASK is enough to keep only the lowest 6 bits set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally had that but compiler said no -

14 |     (pre_mask_tag_length & TAG_LENGTH_MASK) as usize
   |                            ^^^^^^^^^^^^^^^ expected `u32`, found `u8`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if you make const TAG_LENGTH_MASK: u32 = 0b111111 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works

@ionut-arm
Copy link
Member

Actually, a more primordial question - no tests?

Comment on lines 259 to 264
pub(crate) fn abort(
self,
mut op: psa_crypto_sys::psa_key_derivation_operation_t,
) -> Result<()> {
Status::from(unsafe { psa_crypto_sys::psa_key_derivation_abort(&mut op) }).to_result()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a method (instead of just a function on the type)? self isn't used anywhere, it would remove your need to clone the instance in some places

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it consumes self, stopping the user from trying to reuse something that has been cleared. Think it might be better just to do it like attributes, let the user keep their un-cleared Rust operation struct while clearing the C version. I think it deviates from the PSA spec as the struct is supposed to be cleared (and we can't do that for reasons already mentioned) but I can't think of any major problem with it.

@sbailey-arm
Copy link
Contributor Author

I've pulled key_derivation out of the PR and will make it a separate one.

@sbailey-arm
Copy link
Contributor Author

Actually, a more primordial question - no tests?

Not yet. Didn't want to make this PR even bigger, but can add them here if required.

@ionut-arm
Copy link
Member

Not yet. Didn't want to make this PR even bigger, but can add them here if required.

No, another PR with tests makes sense

// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
#![allow(non_snake_case)]
/// Additional functionality required that Mbed Crypto does not provide
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is "PSA Crypto" does not provide?
Also it might be good to rename this file extra.rs. utils.rs often ends up being a pot-pourri of non-sorted things 😃

Comment on lines 81 to 83
Status::Success => Ok(true),
Status::Error(Error::InvalidSignature) => Ok(false), // Indicates operation successful but compare did not match
Status::Error(error) => Err(error),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you 👀 ? Sorry if you did not push everything yet 😅

/// mac.resize(size, 0);
/// assert!(verify_mac(my_key, mac_alg, &MESSAGE, &mac));
/// ```
pub fn verify_mac(key_id: Id, mac_alg: Mac, input_message: &[u8], expected_mac: &[u8]) -> Result<bool> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this also should return Result<()>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, sorry, I have changed these but my virtual machine has been taking the last few days off, must have been in its saved state which was lost. I'll re-change them 🙂

).to_result();
let close_handle_res = key_id.close_handle(key_handle);
mac_verify_res?;
close_handle_res
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can this even compile ❓ Isn't close_handle_res of type Result<()>?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it's not added as a module because Mbed Crypto does not support it!

Copy link
Member

@hug-dev hug-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Let it in!!

@hug-dev hug-dev merged commit 8130857 into parallaxsecond:master Aug 4, 2020
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

Successfully merging this pull request may close these issues.

3 participants