Enable enterprise attestation through VendorConfig.
Add a subcommand to enable through pico-tool. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -38,8 +38,8 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
CborParser parser;
|
||||
CborValue map;
|
||||
CborError error = CborNoError;
|
||||
uint64_t subcommand = 0, pinUvAuthProtocol = 0, vendorCommandId = 0, newMinPinLength = 0, vendorParam = 0;
|
||||
CborByteString pinUvAuthParam = { 0 }, vendorAutCt = { 0 };
|
||||
uint64_t subcommand = 0, pinUvAuthProtocol = 0, vendorCommandId = 0, newMinPinLength = 0, vendorParamInt = 0;
|
||||
CborByteString pinUvAuthParam = { 0 }, vendorParamByteString = { 0 };
|
||||
CborCharString minPinLengthRPIDs[32] = { 0 };
|
||||
size_t resp_size = 0, raw_subpara_len = 0, minPinLengthRPIDs_len = 0;
|
||||
CborEncoder encoder;
|
||||
@@ -74,10 +74,10 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
CBOR_FIELD_GET_UINT(vendorCommandId, 2);
|
||||
}
|
||||
else if (subpara == 0x02) {
|
||||
CBOR_FIELD_GET_BYTES(vendorAutCt, 2);
|
||||
CBOR_FIELD_GET_BYTES(vendorParamByteString, 2);
|
||||
}
|
||||
else if (subpara == 0x03) {
|
||||
CBOR_FIELD_GET_UINT(vendorParam, 2);
|
||||
CBOR_FIELD_GET_UINT(vendorParamInt, 2);
|
||||
}
|
||||
}
|
||||
else if (subcommand == 0x03) { // Extensions
|
||||
@@ -147,8 +147,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
vendorCommandId == CTAP_CONFIG_PHY_LED_BTNESS ||
|
||||
vendorCommandId == CTAP_CONFIG_PHY_OPTS);
|
||||
#endif
|
||||
if (vendorCommandId == CTAP_CONFIG_AUT_DISABLE)
|
||||
{
|
||||
if (vendorCommandId == CTAP_CONFIG_AUT_DISABLE){
|
||||
if (!file_has_data(ef_keydev_enc)) {
|
||||
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
|
||||
}
|
||||
@@ -169,7 +168,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
}
|
||||
|
||||
mbedtls_chachapoly_context chatx;
|
||||
int ret = mse_decrypt_ct(vendorAutCt.data, vendorAutCt.len);
|
||||
int ret = mse_decrypt_ct(vendorParamByteString.data, vendorParamByteString.len);
|
||||
if (ret != 0) {
|
||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||
}
|
||||
@@ -177,7 +176,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
uint8_t key_dev_enc[12 + 32 + 16];
|
||||
random_gen(NULL, key_dev_enc, 12);
|
||||
mbedtls_chachapoly_init(&chatx);
|
||||
mbedtls_chachapoly_setkey(&chatx, vendorAutCt.data);
|
||||
mbedtls_chachapoly_setkey(&chatx, vendorParamByteString.data);
|
||||
ret = mbedtls_chachapoly_encrypt_and_tag(&chatx, file_get_size(ef_keydev), key_dev_enc, NULL, 0, file_get_data(ef_keydev), key_dev_enc + 12, key_dev_enc + 12 + file_get_size(ef_keydev));
|
||||
mbedtls_chachapoly_free(&chatx);
|
||||
if (ret != 0) {
|
||||
@@ -193,20 +192,20 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
|
||||
#ifndef ENABLE_EMULATION
|
||||
else if (vendorCommandId == CTAP_CONFIG_PHY_VIDPID) {
|
||||
phy_data.vid = (vendorParam >> 16) & 0xFFFF;
|
||||
phy_data.pid = vendorParam & 0xFFFF;
|
||||
phy_data.vid = (vendorParamInt >> 16) & 0xFFFF;
|
||||
phy_data.pid = vendorParamInt & 0xFFFF;
|
||||
phy_data.vidpid_present = true;
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_PHY_LED_GPIO) {
|
||||
phy_data.led_gpio = (uint8_t)vendorParam;
|
||||
phy_data.led_gpio = (uint8_t)vendorParamInt;
|
||||
phy_data.led_gpio_present = true;
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_PHY_LED_BTNESS) {
|
||||
phy_data.led_brightness = (uint8_t)vendorParam;
|
||||
phy_data.led_brightness = (uint8_t)vendorParamInt;
|
||||
phy_data.led_brightness_present = true;
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_PHY_OPTS) {
|
||||
phy_data.opts = (uint16_t)vendorParam;
|
||||
phy_data.opts = (uint16_t)vendorParamInt;
|
||||
}
|
||||
else {
|
||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||
@@ -215,6 +214,16 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_PROCESSING);
|
||||
}
|
||||
#endif
|
||||
else if (vendorCommandId == CTAP_CONFIG_EA_UPLOAD) {
|
||||
if (vendorParamByteString.present == false) {
|
||||
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
|
||||
}
|
||||
file_t *ef_ee_ea = search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF);
|
||||
if (ef_ee_ea) {
|
||||
file_put_data(ef_ee_ea, vendorParamByteString.data, (uint16_t)vendorParamByteString.len);
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
else {
|
||||
CBOR_ERROR(CTAP2_ERR_INVALID_SUBCOMMAND);
|
||||
}
|
||||
@@ -265,7 +274,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
CBOR_FREE_BYTE_STRING(vendorAutCt);
|
||||
CBOR_FREE_BYTE_STRING(vendorParamByteString);
|
||||
for (size_t i = 0; i < minPinLengthRPIDs_len; i++) {
|
||||
CBOR_FREE_BYTE_STRING(minPinLengthRPIDs[i]);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct {
|
||||
|
||||
#define CTAP_CONFIG_AUT_ENABLE 0x03e43f56b34285e2
|
||||
#define CTAP_CONFIG_AUT_DISABLE 0x1831a40f04a25ed9
|
||||
#define CTAP_CONFIG_EA_UPLOAD 0x66f2a674c29a8dcf
|
||||
#ifndef ENABLE_EMULATION
|
||||
#define CTAP_CONFIG_PHY_VIDPID 0x6fcb19b0cbe3acfa
|
||||
#define CTAP_CONFIG_PHY_LED_BTNESS 0x76a85945985d02fd
|
||||
|
||||
@@ -75,16 +75,17 @@ def get_pki_data(url, data=None, method='GET'):
|
||||
class VendorConfig(Config):
|
||||
class PARAM(IntEnum):
|
||||
VENDOR_COMMAND_ID = 0x01
|
||||
VENDOR_AUT_CT = 0x02
|
||||
VENDOR_PARAM = 0x03
|
||||
VENDOR_PARAM_BYTESTRING = 0x02
|
||||
VENDOR_PARAM_INT = 0x03
|
||||
|
||||
class CMD(IntEnum):
|
||||
CONFIG_AUT_ENABLE = 0x03e43f56b34285e2
|
||||
CONFIG_AUT_DISABLE = 0x1831a40f04a25ed9
|
||||
CONFIG_EA_UPLOAD = 0x66f2a674c29a8dcf
|
||||
CONFIG_PHY_VIDPID = 0x6fcb19b0cbe3acfa
|
||||
CONFIG_PHY_OPTS = 0x969f3b09eceb805f
|
||||
CONFIG_PHY_LED_GPIO = 0x7b392a394de9f948
|
||||
CONFIG_PHY_LED_BTNESS = 0x76a85945985d02fd
|
||||
CONFIG_PHY_LED_GPIO = 0x7b392a394de9f948
|
||||
CONFIG_PHY_OPTS = 0x969f3b09eceb805f
|
||||
|
||||
class RESP(IntEnum):
|
||||
KEY_AGREEMENT = 0x01
|
||||
@@ -97,7 +98,7 @@ class VendorConfig(Config):
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_ENABLE,
|
||||
VendorConfig.PARAM.VENDOR_AUT_CT: ct
|
||||
VendorConfig.PARAM.VENDOR_PARAM_BYTESTRING: ct
|
||||
},
|
||||
)
|
||||
|
||||
@@ -114,7 +115,7 @@ class VendorConfig(Config):
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_PHY_VIDPID,
|
||||
VendorConfig.PARAM.VENDOR_PARAM: (vid & 0xFFFF) << 16 | pid
|
||||
VendorConfig.PARAM.VENDOR_PARAM_INT: (vid & 0xFFFF) << 16 | pid
|
||||
},
|
||||
)
|
||||
|
||||
@@ -123,7 +124,7 @@ class VendorConfig(Config):
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_PHY_LED_GPIO,
|
||||
VendorConfig.PARAM.VENDOR_PARAM: gpio
|
||||
VendorConfig.PARAM.VENDOR_PARAM_INT: gpio
|
||||
},
|
||||
)
|
||||
|
||||
@@ -132,7 +133,7 @@ class VendorConfig(Config):
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_PHY_LED_BTNESS,
|
||||
VendorConfig.PARAM.VENDOR_PARAM: brightness
|
||||
VendorConfig.PARAM.VENDOR_PARAM_INT: brightness
|
||||
},
|
||||
)
|
||||
|
||||
@@ -141,7 +142,16 @@ class VendorConfig(Config):
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_PHY_OPTS,
|
||||
VendorConfig.PARAM.VENDOR_PARAM: opts
|
||||
VendorConfig.PARAM.VENDOR_PARAM_INT: opts
|
||||
},
|
||||
)
|
||||
|
||||
def upload_ea(self, der):
|
||||
self._call(
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
{
|
||||
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_EA_UPLOAD,
|
||||
VendorConfig.PARAM.VENDOR_PARAM_BYTESTRING: der
|
||||
},
|
||||
)
|
||||
|
||||
@@ -242,7 +252,6 @@ class Vendor:
|
||||
DISABLE = 0x02
|
||||
KEY_AGREEMENT = 0x01
|
||||
EA_CSR = 0x01
|
||||
EA_UPLOAD = 0x02
|
||||
|
||||
class RESP(IntEnum):
|
||||
PARAM = 0x01
|
||||
@@ -430,13 +439,7 @@ class Vendor:
|
||||
)[Vendor.RESP.PARAM]
|
||||
|
||||
def upload_ea(self, der):
|
||||
self._call(
|
||||
Vendor.CMD.VENDOR_EA,
|
||||
Vendor.SUBCMD.EA_UPLOAD,
|
||||
{
|
||||
Vendor.PARAM.PARAM: der
|
||||
}
|
||||
)
|
||||
self.vcfg.upload_ea(der)
|
||||
|
||||
def vidpid(self, vid, pid):
|
||||
return self.vcfg.vidpid(vid, pid)
|
||||
@@ -480,6 +483,9 @@ class Vendor:
|
||||
)
|
||||
return { 'free': resp[1], 'used': resp[2], 'total': resp[3], 'files': resp[4], 'size': resp[5] }
|
||||
|
||||
def enable_enterprise_attestation(self):
|
||||
self.vcfg.enable_enterprise_attestation()
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
subparser = parser.add_subparsers(title="commands", dest="command")
|
||||
@@ -492,7 +498,7 @@ def parse_args():
|
||||
parser_backup.add_argument('filename', help='File to save or load the backup.')
|
||||
|
||||
parser_attestation = subparser.add_parser('attestation', help='Manages Enterprise Attestation')
|
||||
parser_attestation.add_argument('subcommand', choices=['csr'])
|
||||
parser_attestation.add_argument('subcommand', choices=['csr','enable'])
|
||||
parser_attestation.add_argument('--filename', help='Uploads the certificate filename to the device as enterprise attestation certificate. If not provided, it will generate an enterprise attestation certificate automatically.')
|
||||
|
||||
parser_phy = subparser.add_parser('phy', help='Set PHY options.')
|
||||
@@ -513,7 +519,7 @@ def parse_args():
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
def secure(vdr, args):
|
||||
def secure(vdr: Vendor, args):
|
||||
if (args.subcommand == 'enable'):
|
||||
vdr.enable_device_aut()
|
||||
elif (args.subcommand == 'unlock'):
|
||||
@@ -521,13 +527,13 @@ def secure(vdr, args):
|
||||
elif (args.subcommand == 'disable'):
|
||||
vdr.disable_device_aut()
|
||||
|
||||
def backup(vdr, args):
|
||||
def backup(vdr: Vendor, args):
|
||||
if (args.subcommand == 'save'):
|
||||
vdr.backup_save(args.filename)
|
||||
elif (args.subcommand == 'load'):
|
||||
vdr.backup_load(args.filename)
|
||||
|
||||
def attestation(vdr, args):
|
||||
def attestation(vdr: Vendor, args):
|
||||
if (args.subcommand == 'csr'):
|
||||
if (args.filename is None):
|
||||
csr = x509.load_der_x509_csr(vdr.csr())
|
||||
@@ -542,8 +548,10 @@ def attestation(vdr, args):
|
||||
except ValueError:
|
||||
cert = x509.load_pem_x509_certificate(dataf)
|
||||
vdr.upload_ea(cert.public_bytes(Encoding.DER))
|
||||
elif (args.subcommand == 'enable'):
|
||||
vdr.enable_enterprise_attestation()
|
||||
|
||||
def phy(vdr, args):
|
||||
def phy(vdr: Vendor, args):
|
||||
val = args.value if 'value' in args else None
|
||||
if (val):
|
||||
if (args.subcommand == 'vidpid'):
|
||||
@@ -567,7 +575,7 @@ def phy(vdr, args):
|
||||
else:
|
||||
print('Command executed successfully. Please, restart your Pico Key.')
|
||||
|
||||
def memory(vdr, args):
|
||||
def memory(vdr: Vendor, args):
|
||||
mem = vdr.memory()
|
||||
print(f'Memory usage:')
|
||||
print(f'\tFree: {mem["free"]/1024:.2f} kilobytes ({mem["free"]*100/mem["total"]:.2f}%)')
|
||||
|
||||
Reference in New Issue
Block a user