Exemple #1
0
def public_key_digest(nonce, public_key):
    config_data = bytearray(128)
    assert Status.ATCA_SUCCESS == atcab_read_config_zone(config_data)
    config = Atecc608Config.from_buffer(config_data)
    nonce = calc_nonce(mode=0x03, zero=0x0000, num_in=nonce)

    pubkey_digest = calc_genkey_pubkey_digest(mode=0x10,
                                              key_id=rotating_key_slot,
                                              public_key=public_key,
                                              temp_key=nonce,
                                              sn=ctypes_to_bytes(config.SN03) +
                                              ctypes_to_bytes(config.SN48),
                                              other_data=b'\x00' * 3)

    msg_digest, other_data = calc_sign_internal_digest(
        mode=0x00,
        key_id=authority_key_slot,
        temp_key=pubkey_digest,
        temp_key_key_id=rotating_key_slot,
        temp_key_source_flag=
        1,  # Device nonce in internally generated random number
        temp_key_gendig_data=False,
        temp_key_genkey_data=True,
        temp_key_no_mac=False,
        config=config,
        for_invalidate=False)
    return msg_digest
Exemple #2
0
def public_key_validate_invalidate(validation_status,perform_on_device=True):
    is_verified = AtcaReference(False)
    config_data = bytearray(128)
    nonce = os.urandom(32)
    public_key = bytearray(64)

    if(perform_on_device == True):
        assert atcab_read_pubkey(rotating_key_slot,public_key) == ATCA_SUCCESS
    else:
        rotating_private_key = get_rotating_key()
        public_key = rotating_private_key.public_key().public_bytes(encoding=Encoding.X962, format=PublicFormat.UncompressedPoint)[1:]

    validation_authority_key = get_validating_authority_key()

    assert ATCA_SUCCESS == atcab_read_config_zone(config_data)
    config = Atecc608Config.from_buffer(config_data)
    if(perform_on_device == True):
        assert ATCA_SUCCESS == atcab_nonce(nonce)

    nonce = calc_nonce(mode=0x03, zero=0x0000, num_in=nonce)

    pubkey_digest = calc_genkey_pubkey_digest(
        mode=0x10,
        key_id=rotating_key_slot,
        public_key=public_key,
        temp_key=nonce,
        sn=ctypes_to_bytes(config.SN03) + ctypes_to_bytes(config.SN48),
        other_data=b'\x00'*3
    )

    msg_digest,other_data = calc_sign_internal_digest(
        mode=0x00,
        key_id=authority_key_slot,
        temp_key=pubkey_digest,
        temp_key_key_id=rotating_key_slot,
        temp_key_source_flag=1,  # Device nonce in internally generated random number
        temp_key_gendig_data=False,
        temp_key_genkey_data=True,
        temp_key_no_mac=False,
        config=config,
        for_invalidate=validation_status
    )

    # Note that other_data is ignored and not required for this mode
    public_key = bytearray(64)
    if(perform_on_device == True):
        atcab_genkey_base(mode=0x10, key_id=rotating_key_slot, other_data=b'\x00'*3, public_key=public_key)


    signature = sign_host(msg_digest,validation_authority_key)

    if(perform_on_device == True):
        if(validation_status == True):
            assert atcab_verify_invalidate(rotating_key_slot,signature, other_data, is_verified) == ATCA_SUCCESS
        else:
            assert atcab_verify_validate(rotating_key_slot,signature, other_data, is_verified) == ATCA_SUCCESS
    else:
        is_verified = True
    return is_verified,nonce,signature
Exemple #3
0
def calc_sign_internal_digest(mode,
                              key_id,
                              temp_key,
                              temp_key_key_id,
                              temp_key_source_flag,
                              temp_key_gendig_data,
                              temp_key_genkey_data,
                              temp_key_no_mac,
                              config,
                              for_invalidate=False):
    """
    Replicate the internal message digest calculations of the Sign command in
    sign internal mode.
    """
    # TODO: Doesn't work for ATECC108A
    if mode & 0x80:
        raise ValueError('Invalid mode, not internal sign')
    if len(temp_key) != 32:
        raise ValueError('temp_key must be 32 bytes')
    msg = b''
    msg += temp_key
    msg += b'\x41'  # Sign Opcode
    msg += struct.pack('B', mode)
    msg += struct.pack('<H', key_id)
    msg += ctypes_to_bytes(config.SlotConfig[temp_key_key_id])
    msg += ctypes_to_bytes(config.KeyConfig[temp_key_key_id])
    temp_key_flags = 0
    if temp_key_key_id < 0 or temp_key_key_id > 15:
        raise ValueError('temp_key_key_id must be 0 to 15')
    if temp_key_gendig_data and temp_key_genkey_data:
        raise ValueError(
            'temp_key_gendig_data and temp_key_genkey_data are mutually exclusive and both can not be true'
        )
    temp_key_flags += temp_key_key_id
    temp_key_flags += (1 << 4) if temp_key_source_flag else 0
    temp_key_flags += (1 << 5) if temp_key_gendig_data else 0
    temp_key_flags += (1 << 6) if temp_key_genkey_data else 0
    temp_key_flags += (1 << 7) if temp_key_no_mac else 0
    msg += struct.pack('B', temp_key_flags)
    msg += b'\x00' * 2
    is_full_sn = bool(mode & 0x40)
    sn = ctypes_to_bytes(config.SN03) + ctypes_to_bytes(config.SN48)
    msg += sn[8:9]
    msg += sn[4:8] if is_full_sn else b'\x00' * 4
    msg += sn[0:2]
    msg += sn[2:4] if is_full_sn else b'\x00' * 2
    msg += b'\x01' if config.SlotLocked & (1 << temp_key_key_id) else b'\x00'
    msg += b'\x01' if for_invalidate else b'\x00'
    msg += b'\x00'
    other_data = bytearray()
    other_data.extend(msg[33:43])
    other_data.extend(msg[44:48])
    other_data.extend(msg[50:55])

    return sha256(msg).digest(), other_data
Exemple #4
0
def key_attestation(dev_name, attestation_key_slot, key_slot):
    """Demo the key attestation flow"""

    print('Setup: Establish Trust with Attestation Key')

    wrapper = TextWrapper(width=70,
                          initial_indent='    ',
                          subsequent_indent='    ')
    print(
        wrapper.fill(
            'The verifier (entity requesting key attestation) needs to trust the'
            ' attestation key in the device for this process to work. This could'
            ' be as simple as reading and storing the attestation public keys in'
            ' a trusted environment (e.g. during manufacturing). The verifier also'
            ' needs to know the expected configuration and state of the key/slot'
            ' being attested.'))

    print('\n    Reading attestation public key from slot {}:'.format(
        attestation_key_slot))
    attestation_public_key = bytearray(64)
    assert ATCA_SUCCESS == atcab_get_pubkey(key_id=attestation_key_slot,
                                            public_key=attestation_public_key)
    print(convert_ec_pub_to_pem(attestation_public_key))

    print('\n    Read configuration:')
    config = read_config(dev_name)
    print(pretty_print_hex(ctypes_to_bytes(config), indent='    '))

    if config.LockConfig == 0x55:
        raise RuntimeError(
            'Config zone must be locked for this example to run')
    if config.LockValue == 0x55:
        raise RuntimeError('Data zone muct be locked for this example to run')

    print('\nVERIFIER: Send key attestation request')
    print('    Generate verifier challenge/nonce:')
    verifier_nonce = os.urandom(20)
    print(pretty_print_hex(verifier_nonce, indent='    '))

    print('\nDEVICE: Generate key attestation signature')
    print(
        wrapper.fill(
            'Generate attestation nonce in TempKey from verifier and internal'
            ' device nonces.'))
    device_nonce = bytearray(32)
    assert ATCA_SUCCESS == atcab_nonce_rand(num_in=verifier_nonce,
                                            rand_out=device_nonce)
    print('\n    Device nonce:')
    print(pretty_print_hex(device_nonce, indent='    '))

    print('\n' + wrapper.fill(
        'Create a PubKey digest using the GenKey command with the Digest mode'
        ' (0x08). This special mode combines TempKey (attestation nonce) with'
        ' the public key being attested using SHA256 and stores the resulting'
        ' digest back into TempKey.'))
    # Note that other_data is ignored and not required for this mode
    public_key = bytearray(64)
    assert ATCA_SUCCESS == atcab_genkey_base(mode=0x08,
                                             key_id=key_slot,
                                             other_data=b'\x00' * 3,
                                             public_key=public_key)
    print('\n    Public key being attested from slot {}:'.format(key_slot))
    print(convert_ec_pub_to_pem(public_key))

    print('\n' + wrapper.fill(
        'Use attestation key to sign (Sign command in internal mode) a message'
        ' including the PubKey digest in TempKey with additional slot/key'
        ' configuration and state information.'))
    signature = bytearray(64)
    assert ATCA_SUCCESS == atcab_sign_internal(key_id=attestation_key_slot,
                                               is_invalidate=False,
                                               is_full_sn=False,
                                               signature=signature)
    print('\n    Key attestation signature:')
    print(pretty_print_hex(signature, indent='    '))

    print('\nVERIFIER: Validate key attestation signature')
    print(
        wrapper.fill(
            'The verifier has now has the data from the device required to'
            ' perform key attestation. This includes the public key being'
            ' attested, device nonce, key/slot configuration and state, and'
            ' attestation signature. The verifier will need to build the'
            ' attestation message from this information and verify it against the'
            ' signature and the trusted attestation public key.'))
    print('\n    Calculate attestation nonce from verifier and device nonces:')
    nonce = calc_nonce(mode=0x00,
                       zero=0x0000,
                       num_in=verifier_nonce,
                       rand_out=device_nonce)
    print(pretty_print_hex(nonce, indent='    '))

    print('\n    Calculate PubKey digest:')
    pubkey_digest = calc_genkey_pubkey_digest(mode=0x08,
                                              key_id=key_slot,
                                              public_key=public_key,
                                              temp_key=nonce,
                                              sn=ctypes_to_bytes(config.SN03) +
                                              ctypes_to_bytes(config.SN48))
    print(pretty_print_hex(pubkey_digest, indent='    '))

    print('\n    Calculate the internal sign message digest:')
    msg_digest = calc_sign_internal_digest(
        mode=0x00,
        key_id=attestation_key_slot,
        temp_key=pubkey_digest,
        temp_key_key_id=key_slot,
        temp_key_source_flag=
        0,  # Device nonce in internally generated random number
        temp_key_gendig_data=False,
        temp_key_genkey_data=True,
        temp_key_no_mac=False,
        config=config)
    print(pretty_print_hex(msg_digest, indent='    '))

    print('\n    Verifying signature:')

    attestation_public_key = ec.EllipticCurvePublicNumbers(
        curve=ec.SECP256R1(),
        x=int_from_bytes(attestation_public_key[0:32], byteorder='big'),
        y=int_from_bytes(attestation_public_key[32:64], byteorder='big'),
    ).public_key(default_backend())

    r = int_from_bytes(signature[0:32], byteorder='big', signed=False)
    s = int_from_bytes(signature[32:64], byteorder='big', signed=False)
    attestation_public_key.verify(signature=utils.encode_dss_signature(r, s),
                                  data=msg_digest,
                                  signature_algorithm=ec.ECDSA(
                                      utils.Prehashed(hashes.SHA256())))
    print('    SUCCESS! Key has been attested.')
Exemple #5
0
def test_device_serial_number_from_def(config, definition, vector):
    config = config(**definition)
    sernum = ctypes_to_bytes(config.SN03) + ctypes_to_bytes(config.SN48)
    assert sernum == bytes(vector)
Exemple #6
0
def test_device_config_from_vector(config, vector):
    assert ctypes_to_bytes(config.from_buffer(vector)) == bytes(vector)
Exemple #7
0
def test_device_config_from_def(config, definition, vector):
    assert ctypes_to_bytes(config(**definition)) == bytes(vector)