Skip to content

Develop support for Atmel crypto engine ATCAECC508A #6104

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

Merged
merged 32 commits into from
Feb 26, 2018

Conversation

mazimkhan
Copy link

@mazimkhan mazimkhan commented Feb 15, 2018

Description

Driver for ATCAECC508A Atmel crypto engine. Datasheet

Status

IN DEVELOPMENT

Sneak Peak state. Do not review. This PR is suppose to target a new feature branch 'feature-opaque-keys'. Hence the CI builds here will fail.
Waiting for 'feature-opaque-keys' branch be created @0xc0170

@mazimkhan
Copy link
Author

@gilles-peskine-arm I havn't finished the documentation. But you can review the code while I finish documentation.

@0xc0170 0xc0170 changed the base branch from master to feature-opaque-keys February 15, 2018 09:24
Copy link

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

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

I mostly reviewed the Mbed TLS, TLS and cryptography-related parts. I didn't review for C++ coding style or Mbed OS integration.

return err;
}

ATCAError ATCADevice::GenPubKey(ATCAKeyID keyId, uint8_t *pk,

Choose a reason for hiding this comment

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

The function name (“generate public key”) makes no sense. Apparently this function retrieves the public key from a slot that contains a key pair. So it should be called something like GetPubKey or ExportPublicKey.

Copy link
Author

Choose a reason for hiding this comment

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

This function indeed generates the Public key from an existing Private in the HW. Please see section 9.7 Point 2 in the datasheet

Choose a reason for hiding this comment

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

Ok. “Generate” has a very specific meaning in cryptography: it means generate at random, not construct from existing data. So please keep the function name if it comes from the datasheet, but use a different word in the explanation. The public key is calculated or reconstructed from the private key, or you could say that it's exported from the device. It's the device's own business whether it just copies a bunch of bits or makes a mathematical calculation to provide the public key, although you may want to document this if it makes an important performance difference.

Copy link
Author

Choose a reason for hiding this comment

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

Changing it to

124     /** Calculate Public key from corresponding Private Key Id in the device
125      *  and output it.

* Key Index (0-7)
* pk_len == 64
*/
ATCAError ATCADevice::GenPrivateKey(ATCAKeyID keyId, uint8_t *pk,

Choose a reason for hiding this comment

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

The output buffer pk contains the public key, right?

return err;
}

ATCAError ATCADevice::Nonce(const uint8_t * message, size_t len)

Choose a reason for hiding this comment

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

Please give this function a better name. It sets a nonce, for what?

Copy link
Author

Choose a reason for hiding this comment

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

These function names are picked to match commands they run on the HW. See section 9.12 for Nonce command in the datasheet

Choose a reason for hiding this comment

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

Ok, thanks. I've looked at the datasheet now. So keep the name, but please do explain what the commands do in the header file.

cmd[1] = 0x03; // Passthrough mode to load input message in TempKey
cmd[2] = 0x00; // Param2 is 0 for Passthrough mode.
cmd[3] = 0x00;
for (size_t i = 0; i < len; i++)

Choose a reason for hiding this comment

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

memcpy(cmd + 4, message, len)?

return ATCA_ERR_NO_ERROR;
}

ATCAError ATCADevice::ResetWatchdog()

Choose a reason for hiding this comment

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

I don't understand the logic of when the watchdog needs to be reset. Please include that in the upcoming documentation.

{
printf("\r\nRunning ssl client...\r\n");
run_ssl_client();
printf("\r\nNote: For SSL client sample to work sample_client.c\r\n"

Choose a reason for hiding this comment

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

Why print this note after running the client (which may or may not have worked)?

Copy link
Author

Choose a reason for hiding this comment

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

Actually this is part of the documentation hence I will remove it.


static TCPSocket * _tcpsocket = NULL;

int mbedtls_net_init()

Choose a reason for hiding this comment

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

How come these functions aren't part of the Mbed TLS integration in Mbed OS?

Copy link
Author

Choose a reason for hiding this comment

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

Can be. But mbed-os offers alternatives to EthernetInterface. Leaving it on developer's choice.

return MBEDTLS_ERR_SSL_WANT_WRITE;
}else if(size < 0){
mbedtls_printf("Socket send error %d\n", size);
return -1;

Choose a reason for hiding this comment

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

This should be an MBEDTLS_ERR_SSL_XXX error code, translated from the error returned by TCPSocket::send.

Same remark in mbedtls_net_recv.


mbedtls_printf( " ok\r\n" );

/* OPTIONAL is not optimal for security,

Choose a reason for hiding this comment

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

obsolete comment

*/
mbedtls_printf( " . Verifying peer X.509 certificate ..." );

if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )

Choose a reason for hiding this comment

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

Since you used VERIFY_REQUIRED above, this call is irrelevant: you already know the verification succeeded. Remove the whole “Verify the server certificate” section.

@mazimkhan
Copy link
Author

ATCAECC508A datasheet

@ciarmcom
Copy link
Member

ARM Internal Ref: IOTSSL-2102

@mazimkhan
Copy link
Author

@0xc0170 can you please add @AndrzejKurek as reviewer.

@0xc0170 0xc0170 requested a review from AndrzejKurek February 20, 2018 11:01

#if MBED_CONF_ATCAECC_APP_ENABLE

/** ATCAECC508A sample config zone data. Required for calculating CRC while

Choose a reason for hiding this comment

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

Please explain where this data is from. Is that a binary blob from a datasheet or from sample code? Or did you write it yourself?

/** ATCAECC508A sample config zone data. Required for calculating CRC while
* locking the config zone.
*/
uint8_t atcaecc508a_sample_config[] = {

Choose a reason for hiding this comment

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

If this is only required to calculate the CRC, it would be better to embed only the CRC here (save code size).

This requires changing the LockCommand interface and can wait until after the demo.

:plt(I2C_SDA, I2C_SCL,
ATCA_ECC_I2C_FREQUENCY,
ATCA_ECC_508A_I2C_ADDR),
device(plt)
{
}

ATCA * ATCA::GetInstance()
ATCADevice * ATCAFactory::GetDevice( ATCAError & err )

Choose a reason for hiding this comment

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

This is one of several methods that return both an error code and some data. They return the data as a return value and the error code through a reference argument. Is this a common pattern in Mbed OS? The opposite pattern (return an error code, use reference arguments for the data) is more common in general.

@@ -17,9 +17,8 @@
#ifndef ATCAECCCONSTANTS_H
#define ATCAECCCONSTANTS_H

/* Datasheet defined constants */
/** Datasheet defined constants */

Choose a reason for hiding this comment

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

This doesn't document the next definition (it documents the next bunch of definitions) so it either it should not be a Doxygen comment, or it should be a Doxygen section start and each definition inside the section should be documented.

*
* @param dev Device driver reference.
* @param keyId Key Id/Slot number in device data zone.
* @param pk Public key buffer with X & Y concatenated.

Choose a reason for hiding this comment

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

Please clarify the description. I don't even know whether pk is an input or an output or what it's used for. The public key is not generated, it's exported.

*
* Currently interface is only defined for sign and verify functions.
*/
class CryptoEngineInterface

Choose a reason for hiding this comment

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

In the Mbed TLS opaque key interface, there are more mandatory methods, I guess they should all be reflected here: get_signature_size (when sign is present), get_bitlen, can_do. (Plus alloc or a setup and free, which I guess are implemented here as a constructor and a destructor which don't need to be declared explicitly.)

Copy link
Author

Choose a reason for hiding this comment

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

I suppose these suggested methods should go in class ATCAKey or in an abstraction of it.
This interface is to the driver that can provide different keys. I will keep it for rework later as I have to think it through.

- Public keys are not stored in the device but generated whenever required.

## ATCAECC508A configuration
The device configuration should be **locked** before use. To achieve demo requirements it is commissioned with a minimilistic configuration. The commissioning can be done using the sample commissioning app contained in the driver code. This app commissions following configuration in the device:

Choose a reason for hiding this comment

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

Should or must be locked?

Explain what “locked” means.

minimilistic → minimalistic

“it is commissioned”: when? What you're describing is actually what the demo expects, so: “it should be commissioned”

```

Modified ```cert_write.exe``` takes parameters ```subject_key``` and ```issuer_key``` formatted in a special way to identify HW keys.
The format is ```remote0COM18```. Here:

Choose a reason for hiding this comment

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

Please put a separator between the parts, e.g. remote:0:COM18 or ///opaque_pk/ATCA/0:COM18

printf ("atca_sign_func called \r\n");

if ( md_alg != MBEDTLS_MD_SHA256 )
return -1;
Copy link
Author

Choose a reason for hiding this comment

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

@gilles-peskine-arm would MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE be a good error here.

Choose a reason for hiding this comment

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

Yes, that's what FEATURE_UNAVAILABLE is for.

@mazimkhan
Copy link
Author

@gilles-peskine-arm incorporated your comments.

Copy link
Contributor

@AndrzejKurek AndrzejKurek left a comment

Choose a reason for hiding this comment

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

Some cosmetic changes for now. Will continue the review tommorow.

/** Rx buffer */
uint8_t rx_buf[ATCA_ECC_MAX_RESP_LEN];
public:
/** Instantiate ATCAECC508A device driver class with paltform reference.
Copy link
Contributor

Choose a reason for hiding this comment

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

paltform -> platform

*/
ATCAError Init();

/** Configure keyID (Slot) as a ECC Private key.
Copy link
Contributor

Choose a reason for hiding this comment

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

a -> an

*/
ATCAError ConfigPrivKey(ATCAKeyID keyId);

/** Configure keyID (Slot) as a ECC Public key.
Copy link
Contributor

Choose a reason for hiding this comment

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

a -> an

ATCAError ConfigCertStore();

/** Lock configuration zone. Configuration zone locking is required
* for using cprypto functions of the device.
Copy link
Contributor

Choose a reason for hiding this comment

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

cprypto -> crypto

*
* @param keyId Key Id of Private slot.
* @param pk Public key output buffer.
* @param pk_buf_len Public key output buffer length.
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix indentation

ATCAError MbedPlatform::Read(uint8_t * buf, size_t len)
{
int status = i2c->read(addr, (char *)buf, len);
//Dump(buf, len, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Debug left


ATCAError MbedPlatform::Write(uint8_t * buf, size_t len)
{
//Dump(buf, len, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Debug left

Copy link
Contributor

Choose a reason for hiding this comment

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

please remove dead code

return (status != 0)?ATCA_ERR_I2C_WRITE_ERROR:ATCA_ERR_NO_ERROR;
}

void MbedPlatform::Dump(uint8_t * buf, size_t len, bool tx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe a debug ifdef?

#include "mbed.h"
#include "ATCAPlatformInterface.h"

#define DEV_DELAY_TPU_MS (100 + 10)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please comment on where do these values come from.


/** Deinit I2C. Particularly useful when ATCAECC508A watchdog timer is to be
* reset. That requires pulling SDA low. Hence requiring a re-init of I2C
* afterwords.
Copy link
Contributor

Choose a reason for hiding this comment

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

afterwords -> afterwards

* boundary is not allowed.
*
* @param address Byte address in data zone. Should be 4 byte aligned.
* @param len input buffer length.
Copy link

@gilles-peskine-arm gilles-peskine-arm Feb 21, 2018

Choose a reason for hiding this comment

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

Mention ≤4 in the parameter description, and state the name of the buffer (data) explicitly.

Copy link

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

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

Ok for the demo.

@mazimkhan
Copy link
Author

/morph build

@mbed-ci
Copy link

mbed-ci commented Feb 26, 2018

Build : FAILURE

Build number : 1251
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6104/

@mazimkhan
Copy link
Author

/morph build

@mbed-ci
Copy link

mbed-ci commented Feb 26, 2018

Build : SUCCESS

Build number : 1253
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6104/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build
/morph mbed2-build

@mazimkhan
Copy link
Author

@0xc0170
AWS-CI uVisor Build & Test - failed due to serial issues. How do we check mbed-ci-generic?

@0xc0170
Copy link
Contributor

0xc0170 commented Feb 26, 2018

AWS-CI uVisor Build & Test - failed due to serial issues. How do we check mbed-ci-generic?

I'll find out about that ci-generic, did not publish the correct status, will be fixed

Copy link
Contributor

@0xc0170 0xc0170 left a comment

Choose a reason for hiding this comment

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

I left few comments that can be applied to multiple files, please review

#include "mbedtls/net_sockets.h"

/* Mbed OS includes */
#include "mbed.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

include what is required instead, we should not include mbed.h here

const char *ip_addr = eth_iface.get_ip_address();
if (ip_addr)
mbedtls_printf("Client IP Address is %s\r\n", ip_addr);
else
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this is mbed OS file, thus should follow the style . Same of the rest of files in features/atcryptoauth

*
* @param us Delay in micro seconds
*/
virtual void SDALow(uint32_t us);
Copy link
Contributor

Choose a reason for hiding this comment

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

methods are lower case - sda_low


/** Mbed implementation of abstract Platform interface.
*/
class MbedPlatform : public ATCAPlatformInterface {
Copy link
Contributor

Choose a reason for hiding this comment

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

why this class has generic name MbedPlatform ? This does not look a generic platform class that can be used outside of this feature?

#ifndef MBEDPLATFORM_H
#define MBEDPLATFORM_H

#include "mbed.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

replace with headers that are needed here

class MbedPlatform : public ATCAPlatformInterface {
private:
/** I2C pin names */
PinName sda;
Copy link
Contributor

Choose a reason for hiding this comment

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

private members starts with _

*
* @return Error code from enum ATCAError.
*/
virtual ATCAError Init();
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need init/deinit, not the job done in constructor/destructor?


ATCAError MbedPlatform::Write(uint8_t * buf, size_t len)
{
//Dump(buf, len, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

please remove dead code

Reset();
}

void Reset(){ _register = 0; }
Copy link
Contributor

Choose a reason for hiding this comment

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

missing any documentation for methods

@mbed-ci
Copy link

mbed-ci commented Feb 26, 2018

@mbed-ci
Copy link

mbed-ci commented Feb 26, 2018

@0xc0170
Copy link
Contributor

0xc0170 commented Feb 26, 2018

Approved, not blocking progress on this feature on its branch (styling changes mostly requested, will be addressed as a new pull request to the branch).

@0xc0170 0xc0170 merged commit 6b303a7 into ARMmbed:feature-opaque-keys Feb 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants