Created
May 1, 2018 09:46
-
-
Save michpappas/cdc983a576c67a92a178b2f70343ae0d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2017, Linaro Ltd and contributors | |
* SPDX-License-Identifier: Apache-2.0 | |
*/ | |
#define S96_AT_STATUS_OK 0x00 | |
#define S96_AT_STATUS_CHECKMAC_FAIL 0x01 | |
#define S96_AT_STATUS_EXEC_ERROR 0x0f | |
#define S96AT_CHALLENGE_LEN 32 | |
#define S96AT_HMAC_LEN 32 | |
#define S96AT_MAC_LEN 32 | |
#define S96AT_NONCE_PASSTHRU_LEN 32 | |
#define S96AT_RANDOM_LEN 32 | |
#define S96AT_SHA_LEN 32 | |
/* Nonce flags */ | |
#define S96AT_FLAG_UPDATE_SEED 0x00 | |
#define S96AT_FLAG_NO_UPDATE_SEED 0x01 | |
/* MAC / CheckMAC / HMAC flags */ | |
#define S96AT_FLAG_USE_OTP_LOW_BYTES 0x00 /* Use OTP[0:7] */ | |
#define S96AT_FLAG_USE_OTP_HIGH_BYTES 0x01 /* Use OTP[8:10] */ | |
#define S96AT_FLAG_USE_SN_LOW_BYTES 0x02 /* Use OTP[2:3] */ | |
#define S96AT_FLAG_USE_SN_HIGH_BYTES 0x04 /* Use OTP[4:7] */ | |
/* Check a MAC generated by ATSHA208A / ATECC508A | |
* | |
* Generates a MAC and compares it with the value stored in the mac buffer. | |
* This is normally used to verify a MAC generated using s96at_get_mac() | |
* during a host-client communication. | |
* | |
* For more information on the input parameters see s96at_get_mac() | |
* | |
* Upon success S96AT_STATUS_OK is returned. A failed comparison | |
* returns S96_STATUS_CHECKMAC_FAIL. | |
*/ | |
int s96at_check_mac(struct io_interface *ioif, uint8_t slotid, | |
uint8_t challenge[S96AT_CHALLENGE_LEN], uint32_t flags, | |
uint8_t random[S96AT_RANDOM_LEN], uint8_t mac[S96AT_MAC_LEN]); | |
/* Derive a key | |
* | |
* Derives a new key by combining the value stored in a slot with a nonce | |
* and storing its SHA256 hash into the target slot. Depending on how the | |
* target slot is configured, this function will use the appropriate input | |
* key: | |
* - For slots configured into Create mode, the parent key is used. | |
* - For slots configured into Rolling mode, the current key is used. | |
* | |
* If required by the configuration, an authorizing MAC is sent along | |
* too. | |
*/ | |
int s96at_derive_key(struct io_interface *ioif, uint8_t slotid); | |
/* Generate a digest | |
* | |
* Generate a SHA-256 digest combining the value stored in TempKey with | |
* a value stored in the device. The input value is defined by the zone | |
* and slot parameters. The value of data must be NULL. | |
* | |
* For keys configured as CheckOnly, it is possible to generate the | |
* digest using the value stored in the data buffer instead of a value | |
* stored in the device. This is normally used to generate euphemeral | |
* keys. When this operation is required, a pointer must be passed to the | |
* data parameter pointing to a buffer that contains the input data. In | |
* this case, the zone and slotid values are ignored. | |
* | |
* In both cases, the generated digest is stored in TempKey and it can | |
* be used to combine the Nonce with an additional value before executing | |
* the MAC / CheckMAC / HMAC commands. | |
*/ | |
int s96at_gen_digest(struct io_interface *ioif, uint8_t zone, uint8_t slotid, | |
uint8_t data[4]); | |
/* Generate an HMAC-SHA256 | |
* | |
* Generates an HMAC-SHA256. The HMAC is generated by first running | |
* Nonce in Random mode to combine the input challenge with a random | |
* number. That number is then combined along with the key stored | |
* in slotid to generate an HMAC. The resulting HMAC and the value | |
* produced by the RNG are written to the mac and random buffers | |
* respectively. | |
* | |
* Flags control whether other intput values should be included in | |
* the hashed message. These are: | |
* | |
* S96AT_FLAG_USE_OTP_LOW_BYTES Use OTP[0:7] | |
* S96AT_FLAG_USE_OTP_HIGH_BYTES Use OTP[8:10] | |
* S96AT_FLAG_USE_SN_LOW_BYTES Use OTP[2:3] | |
* S96AT_FLAG_USE_SN_HIGH_BYTES Use OTP[4:7] | |
* | |
* If challenge is NULL, it is assumed that TempKey has already | |
* been populated and only the MAC command is sent to the device. | |
* | |
* Notice that this function does not execute GenDig after running Nonce. | |
* To achieve that functionality, a Nonce followed by GenMac must be | |
* executed manually to populate TempKey and challenge must be set to NULL. | |
* The random buffer is then not populated. | |
*/ | |
int s96at_get_hmac(struct io_interface *ioif, uint8_t slotid, | |
uint8_t challenge[S96AT_CHALLENGE_LEN], uint32_t flags, | |
uint8_t random[S96AT_RANDOM_LEN], uint8_t hmac[S96AT_HMAC_LEN]); | |
/* Get the lock status of the Config Zone | |
* | |
* Reads the lock status of the Config Zone into lock_config. | |
* Possible values: | |
* - S96AT_LOCK_CONFIG_LOCKED | |
* - S96AT_LOCK_CONFIG_UNLOCKED | |
*/ | |
int s96at_get_lock_config(struct io_interface *ioif, uint8_t *lock_config); | |
/* Get the lock status of the Data Zone | |
* | |
* Reads the lock status of the Data Zone into lock_data. | |
* Possible values: | |
* - S96AT_LOCK_DATA_LOCKED | |
* - S96AT_LOCK_DATA_UNLOCKED | |
*/ | |
int s96at_get_lock_data(struct io_interface *ioif, uint8_t *lock_data); | |
/* Get the lock status of the OTP Zone | |
* | |
* Reads the lock status of the OTP Zone into lock_otp. | |
* Possible values: | |
* - S96AT_LOCK_OTP_LOCKED | |
* - S96AT_LOCK_OTP_UNLOCKED | |
*/ | |
int s96at_get_lock_otp(struct io_interface *ioif, uint8_t *lock_otp); | |
/* Generate a MAC | |
* | |
* Generates a MAC. The MAC is generated by first running Nonce in | |
* Random mode to combine the input challenge with a random number. | |
* That number is then combined along with the key stored in slotid | |
* to generate a MAC. The resulting HMAC and the value produced by | |
* the RNG are written to the mac and random buffers respectively. | |
* | |
* Flags control whether other intput values should be included in | |
* the hashed message. These are: | |
* | |
* S96AT_FLAG_USE_OTP_LOW_BYTES Use OTP[0:7] | |
* S96AT_FLAG_USE_OTP_HIGH_BYTES Use OTP[8:10] | |
* S96AT_FLAG_USE_SN_LOW_BYTES Use OTP[2:3] | |
* S96AT_FLAG_USE_SN_HIGH_BYTES Use OTP[4:7] | |
* | |
* If challenge is NULL, it is assumed that TempKey has already | |
* been populated and only the MAC command is sent to the device. | |
* | |
* Notice that this function does not execute GenDig after running Nonce. | |
* To achieve that functionality, a Nonce followed by GenMac must be | |
* executed manually to populate TempKey and challenge must be set to NULL. | |
* The random buffer is then not populated. | |
*/ | |
int s96at_get_mac(struct io_interface *ioif, uint8_t slotid, | |
uint8_t challenge[S96AT_CHALLENGE_LEN], uint32_t flags, | |
uint8_t random[S96AT_RANDOM_LEN], uint8_t mac[S96AT_MAC_LEN]); | |
/* Generate a nonce | |
* | |
* Generates a nonce. If data is NULL, operate in Pass-Through Mode. | |
* The input value in the data buffer is stored directly in TempKey. | |
* | |
* If data is not NULL then operate in Random Mode, ie combine the | |
* input value with a random number and store the resulting hash | |
* in TempKey. | |
* | |
* When Random Mode is used, the default behaviour is to update | |
* the seed before generating the random number. This behaviour | |
* can be overriden by passing the S96AT_FLAG_NO_UPDATE_SEED flag. | |
* | |
* Stores the value produced by the RNG in buf. | |
*/ | |
int s96at_get_nonce(struct io_interface *ioif, uint8_t data[S96AT_NONCE_PASSTHRU_LEN], | |
uint8_t random[S96AT_RANDOM_LEN], uint32_t flags); | |
/* Get the OTP Mode | |
* | |
* Reads the OTP Mode into otp_mode. Possible values are: | |
* - S96AT_OTP_MODE_CONSUMPTION | |
* - S96AT_OTP_MODE_LEGACY | |
* - S96AT_OTP_MODE_READ_ONLY | |
*/ | |
int s96at_get_otp_mode(struct io_interface *ioif, uint8_t *opt_mode); | |
/* Send Pause command | |
* | |
* Upon receiving the Pause command, devices with Selector byte in the | |
* EEPROM not matching the selector parameter will enter the Idle State. | |
*/ | |
int s96at_pause(struct io_interface *ioif, uint8_t selector); | |
/* Generate a random number | |
* | |
* Random numbers are generated by combining the output of a hardware RNG | |
* with a seed value. The generated number is stored in random buffer. | |
* | |
* Before generating a new number, the interal seed is updated by default. | |
* This can be overriden by passing the S96AT_FLAG_NO_UPDATE_SEED flag. | |
*/ | |
int s96at_get_random(struct io_interface *ioif, | |
/* Get the Serial Number | |
* | |
* Reads the Serial Number into buf. The buffer must be | |
* at least S96AT_SERIALNUM_LEN long. | |
*/ | |
int s96at_get_serialnbr(struct io_interface *ioif, ); | |
/* Generate a hash (SHA-256) | |
* | |
* Input data must have a valid padding as described in FIPS-180: | |
* | |
* https://csrc.nist.gov/publications/detail/fips/180/2/archive/2002-08-01 | |
* | |
* The resulting hash is stored in the hash buffer. | |
*/ | |
int s96at_get_sha(uint8_t *data, size_t size, uint8_t hash[SHA_LEN]); | |
/* Read the Config Zone | |
* | |
* Reads the Config Zone into buf. The buffer must be | |
* at least S96AT_ZONE_CONFIG_SIZE long. | |
*/ | |
int s96at_get_zone_config(uint8_t *buf, size_t size); | |
/* Lock the Config Zone | |
* | |
* Locks the Config Zone. After the configuration is locked, the Data and | |
* OTP areas can be programmed. | |
* | |
* Notice that locking is a one-time operation. | |
*/ | |
int s96at_lock_config(struct io_interface *ioif); | |
/* Lock the Data / OTP Zone | |
* | |
* Locks the Data and OTP Zones. The values of the slots in each zone must | |
* be programmed before locking. Once the Data / OTP zones are locked, the | |
* values stored can be read and written according to the policy specified | |
* in the configuration of each slot. | |
* | |
* Notice that locking is a one-time operation. | |
*/ | |
int s96at_lock_data(struct io_interface *ioif); | |
/* Program the Config Zone | |
* | |
* Programs the Config Zone with the values stored in buf. The buffer must be | |
* of S96AT_CONFIG_SIZE length. | |
*/ | |
int s96at_program_config(struct io_interface *ioif, uint8_t *buf); | |
/* Program the Data Zone | |
* | |
* Programs the Data Zone with the values stored in buf. The buffer must be | |
* of S96AT_DATA_SIZE length. | |
*/ | |
int s96at_program_data(struct io_interface *ioif, uint8_t *buf); | |
/* Program the OTP Zone | |
* | |
* Programs the OTP Zone with the values stored in buf. The buffer must be | |
* of S96AT_OTP_SIZE length. | |
*/ | |
int s96at_program_otp(struct io_interface *ioif, uint8_t *buf); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment