Exemplo n.º 1
0
def setup_dh_key(selected_cipher: int, private_bytes: bytes):
    if CipherSuite.from_id(selected_cipher).dh_curve in [X448, X25519]:
        return OKPKey(d=private_bytes, crv=CipherSuite.from_id(selected_cipher).dh_curve)
    elif CipherSuite.from_id(selected_cipher).dh_curve in [P256]:
        return EC2Key(d=private_bytes, crv=CipherSuite.from_id(selected_cipher).sign_curve)
    else:
        raise ValueError("Illegal DH keys.")
Exemplo n.º 2
0
def test_responder_finalize(responder, test_vectors):
    responder.msg_1 = MessageOne.decode(test_vectors['S']['message_1'])
    responder.msg_2 = MessageTwo.decode(
        responder.create_message_two(test_vectors['S']['message_1']))
    responder.msg_3 = MessageThree.decode(test_vectors['S']['message_3'])

    decoded = EdhocMessage.decode(
        responder._decrypt(responder.msg_3.ciphertext))
    if KID.identifier in cbor2.loads(test_vectors['I']['cred_id']):
        assert decoded[0] == EdhocMessage.encode_bstr_id(
            cbor2.loads(test_vectors['I']['cred_id'])[KID.identifier])
    else:
        assert decoded[0] == cbor2.loads(test_vectors['I']['cred_id'])
    assert decoded[1] == test_vectors['S']['signature_3']

    if getattr(responder, 'remote_authkey', None) is None:
        warnings.warn(NoRemoteKey())
        return
    c_i, c_r, app_aead, app_hash = responder.finalize(
        test_vectors['S']['message_3'])

    assert c_i == test_vectors['I']['conn_id']
    assert c_r == test_vectors['R']['conn_id']
    assert app_aead == CipherSuite.from_id(
        test_vectors['I']['selected']).app_aead.identifier
    assert app_hash == CipherSuite.from_id(
        test_vectors['I']['selected']).app_hash.identifier
Exemplo n.º 3
0
def test_responder_message2(responder, test_vectors):
    responder.msg_1 = MessageOne.decode(test_vectors['S']['message_1'])

    hash_func = CipherSuite.from_id(
        responder.msg_1.selected_cipher).hash.hash_cls
    crv = CipherSuite.from_id(responder.msg_1.selected_cipher).dh_curve

    assert responder.shared_secret(
        responder.ephemeral_key, OKPKey(x=responder.g_x,
                                        crv=crv)) == test_vectors['S']['g_xy']
    assert responder._prk2e == test_vectors['S']['prk_2e']
    assert responder._prk3e2m == test_vectors['S']['prk_3e2m']
    assert responder.data_2 == test_vectors['S']['data_2']
    assert responder._th2_input == test_vectors['S']['input_th_2']
    assert responder.cred_id == cbor2.loads(test_vectors['R']['cred_id'])
    assert responder.transcript(
        hash_func, responder._th2_input) == test_vectors['S']['th_2']
    assert responder._hkdf2(
        16, 'K_2m', prk=responder._prk3e2m) == test_vectors['S']['k_2m']
    assert responder._hkdf2(
        13, 'IV_2m', prk=responder._prk3e2m) == test_vectors['S']['iv_2m']
    assert responder._mac(responder._hkdf2, 'K_2m', 16, 'IV_2m', 13,
                          responder._th2_input, responder._prk3e2m,
                          responder.aad2_cb) == test_vectors['S']['mac_2']
    assert responder.signature_or_mac2(
        test_vectors['S']['mac_2']) == test_vectors['S']['signature_2']
    assert responder._p_2e == test_vectors['S']['p_2e']
    assert responder._hkdf2(
        len(responder._p_2e), 'KEYSTREAM_2',
        prk=responder._prk2e) == test_vectors['S']['keystream_2']
    assert responder.ciphertext_2 == test_vectors['S']['ciphertext_2']

    assert responder.create_message_two(
        test_vectors['S']['message_1']) == test_vectors['S']['message_2']
Exemplo n.º 4
0
def setup_sign_key(selected_cipher: int, private_bytes: bytes):
    if CipherSuite.from_id(selected_cipher).sign_curve in [Ed448, Ed25519]:
        return OKPKey(d=private_bytes,
                      crv=CipherSuite.from_id(selected_cipher).sign_curve,
                      optional_params={KpAlg: CipherSuite.from_id(selected_cipher).sign_alg})
    elif CipherSuite.from_id(selected_cipher).sign_alg == Es256:
        return EC2Key(d=private_bytes, alg=Es256, crv=CipherSuite.from_id(selected_cipher).sign_curve)
    else:
        raise ValueError("Illegal COSE curve.")
Exemplo n.º 5
0
def test_message1_encode(test_vectors):
    msg = MessageOne(
        method_corr=test_vectors["S"]["method_corr"],
        cipher_suites=[
            CipherSuite.from_id(x) for x in test_vectors["I"]["supported"]
        ],
        selected_cipher=CipherSuite.from_id(test_vectors["I"]["selected"]),
        g_x=test_vectors["I"]["g_x"],
        conn_idi=test_vectors["I"]["conn_id"],
        external_aad=test_vectors["I"]["ad_1"])

    assert msg.encode(
        test_vectors["S"]["corr"]) == test_vectors["S"]["message_1"]
Exemplo n.º 6
0
def test_initiator_finalize(initiator, test_vectors):
    initiator.msg_1 = MessageOne.decode(initiator.create_message_one())
    initiator.msg_2 = MessageTwo.decode(test_vectors['S']['message_2'])
    initiator.msg_3 = MessageThree.decode(
        initiator.create_message_three(test_vectors['S']['message_2']))

    c_i, c_r, app_aead, app_hash = initiator.finalize()

    assert c_i == test_vectors['I']['conn_id']
    assert c_r == test_vectors['R']['conn_id']
    assert app_aead == CipherSuite.from_id(
        test_vectors['I']['selected']).app_aead.identifier
    assert app_hash == CipherSuite.from_id(
        test_vectors['I']['selected']).app_hash.identifier
Exemplo n.º 7
0
def test_initiator_finalize(initiator, test_vectors):
    initiator.msg_1 = MessageOne.decode(initiator.create_message_one())
    initiator.msg_2 = MessageTwo.decode(test_vectors['S']['message_2'])
    if getattr(initiator, 'remote_authkey', None) is None:
        warnings.warn(NoRemoteKey())
        return

    initiator.msg_3 = MessageThree.decode(initiator.create_message_three(test_vectors['S']['message_2']))

    c_i, c_r, app_aead, app_hash = initiator.finalize()

    assert c_i == test_vectors['I']['conn_id']
    assert c_r == test_vectors['R']['conn_id']
    assert app_aead == CipherSuite.from_id(test_vectors['I']['selected']).app_aead.identifier
    assert app_hash == CipherSuite.from_id(test_vectors['I']['selected']).app_hash.identifier
Exemplo n.º 8
0
def responder(ephemeral_responder_key, test_vectors):
    if test_vectors['R']['cred_type'] == 0:
        local_cred = cbor2.loads(test_vectors['R']['cred'])
        local_auth_key = None
    else:
        local_cred = CoseKey.decode(test_vectors['R']['cred'])
        local_auth_key = CoseKey.decode(test_vectors['R']['cred'])

    if test_vectors['I']['cred_type'] == 0:
        remote_cred = cbor2.loads(test_vectors['I']['cred'])
        remote_auth_key = None
    else:
        remote_cred = CoseKey.decode(test_vectors['I']['cred'])
        remote_auth_key = CoseKey.decode(test_vectors['I']['cred'])

    responder = Responder(
        conn_idr=test_vectors["R"]["conn_id"],
        cred_idr=cbor2.loads(test_vectors['R']['cred_id']),
        auth_key=CoseKey.decode(test_vectors['R']['auth_key']),
        cred=(local_cred, local_auth_key),
        supported_ciphers=[
            CipherSuite.from_id(c) for c in test_vectors["R"]["supported"]
        ],
        remote_cred_cb=lambda arg: (remote_cred, remote_auth_key),
        ephemeral_key=ephemeral_responder_key)
    responder.cred_idi = test_vectors['I']['cred_id']
    return responder
Exemplo n.º 9
0
 def cipher_suite(self) -> 'CS':
     if self.msg_1 is None:
         raise EdhocException("Message 1 not received. Cannot derive selected cipher suite.")
     else:
         if not self._verify_cipher_selection(self.msg_1.selected_cipher, self.msg_1.cipher_suites):
             raise EdhocException("Invalid cipher suite setup")
         return CipherSuite.from_id(self.msg_1.selected_cipher)
Exemplo n.º 10
0
def initiator(ephemeral_initiator_key, test_vectors):
    if test_vectors['I']['cred_type'] == 0:
        local_auth_key = None
        local_cred = cbor2.loads(test_vectors['I']['cred'])
    else:
        local_auth_key = CoseKey.decode(test_vectors['I']['cred'])
        local_cred = CoseKey.decode(test_vectors['I']['cred'])

    if test_vectors['R']['cred_type'] == 0:
        remote_auth_key = None
        remote_cred = cbor2.loads(test_vectors['R']['cred'])
    else:
        remote_auth_key = CoseKey.decode(test_vectors['R']['cred'])
        remote_cred = CoseKey.decode(test_vectors['R']['cred'])

    return Initiator(
        corr=test_vectors['S']['corr'],
        method=test_vectors['S']['method'],
        cred=(local_cred, local_auth_key),
        cred_idi=cbor2.loads(test_vectors['I']['cred_id']),
        auth_key=CoseKey.decode(test_vectors['I']['auth_key']),
        selected_cipher=test_vectors['I']['selected'],
        supported_ciphers=[CipherSuite.from_id(c) for c in test_vectors["I"]["supported"]],
        conn_idi=test_vectors['I']['conn_id'],
        remote_cred_cb=lambda x: (remote_cred, remote_auth_key),
        ephemeral_key=ephemeral_initiator_key,
    )
Exemplo n.º 11
0
    def decode(cls, received: bytes) -> 'MessageOne':
        """
        Tries to decode the bytes as an EDHOC MessageOne.

        :param received: Bytes to decode.

        :raises EdhocInvalidMessage: Decoding routine for MessageOne failed.
        :returns: An EDHOC MessageOne object.
        """

        decoded = super().decode(received)

        method_corr = decoded[cls.METHOD_CORR]

        if isinstance(decoded[cls.CIPHERS], int):
            selected_cipher = decoded[cls.CIPHERS]
            supported_ciphers = [decoded[cls.CIPHERS]]
        elif isinstance(decoded[cls.CIPHERS], list):
            selected_cipher = decoded[cls.CIPHERS][0]
            supported_ciphers = decoded[cls.CIPHERS][1:]
        else:
            raise EdhocInvalidMessage("Failed to decode bytes as MessageOne")

        g_x = decoded[cls.G_X]

        if decoded[cls.CONN_ID] != b'':
            if isinstance(decoded[cls.CONN_ID], int):
                conn_idi = EdhocMessage.decode_bstr_id(decoded[cls.CONN_ID])
            else:
                conn_idi = decoded[cls.CONN_ID]
        else:
            conn_idi = b''

        msg = cls(
            method_corr=method_corr,
            selected_cipher=CipherSuite.from_id(selected_cipher),
            cipher_suites=[CipherSuite.from_id(c) for c in supported_ciphers],
            g_x=g_x,
            conn_idi=conn_idi)

        try:
            msg.aad1 = decoded[cls.AAD1]
        except IndexError:
            pass

        return msg
Exemplo n.º 12
0
def test_initiator_message3(initiator, test_vectors):
    initiator.msg_1 = MessageOne.decode(test_vectors['S']['message_1'])
    initiator.msg_2 = MessageTwo.decode(test_vectors['S']['message_2'])

    crv = CipherSuite.from_id(initiator._selected_cipher).dh_curve
    hash_func = CipherSuite.from_id(initiator._selected_cipher).hash.hash_cls

    assert initiator.data_2 == test_vectors['S']['data_2']
    assert initiator._th2_input == test_vectors['S']['input_th_2']
    assert initiator._prk2e == test_vectors['S']['prk_2e']
    assert initiator._prk3e2m == test_vectors['S']['prk_3e2m']
    assert initiator.transcript(hash_func, initiator._th2_input) == test_vectors['S']['th_2']

    assert initiator._decrypt(initiator.msg_2.ciphertext) == test_vectors['S']['p_2e']

    assert initiator.shared_secret(initiator.ephemeral_key, OKPKey(x=initiator.g_y, crv=crv)) == test_vectors['S'][
        'g_xy']
    assert initiator.data_3 == test_vectors['S']['data_3']
    assert initiator._th3_input == test_vectors['S']['input_th_3']
    assert initiator.transcript(hash_func, initiator._th3_input) == test_vectors['S']['th_3']
    assert initiator.cred_id == cbor2.loads(test_vectors['I']['cred_id'])
    assert initiator._prk4x3m == test_vectors['S']['prk_4x3m']
    assert initiator._hkdf3(16, 'K_3m', initiator._prk4x3m) == test_vectors['S']['k_3m']
    assert initiator._hkdf3(13, 'IV_3m', initiator._prk4x3m) == test_vectors['S']['iv_3m']
    assert initiator._mac(
        initiator.cred_idi,
        initiator.cred,
        initiator._hkdf3,
        'K_3m',
        16,
        'IV_3m',
        13,
        initiator._th3_input,
        initiator._prk4x3m,
        initiator.aad2_cb) == test_vectors['S']['mac_3']
    assert initiator.signature_or_mac3(test_vectors['S']['mac_3']) == test_vectors['S']['signature_3']
    assert initiator._p_3ae == test_vectors['S']['p_3ae']
    assert initiator._hkdf3(16, 'K_3ae', initiator._prk3e2m) == test_vectors['S']['k_3ae']
    assert initiator._hkdf3(13, 'IV_3ae', initiator._prk3e2m) == test_vectors['S']['iv_3ae']
    assert initiator.ciphertext_3 == test_vectors['S']['ciphertext_3']

    if initiator.remote_authkey is None:
        warnings.warn(NoRemoteKey())
        return
    assert initiator.create_message_three(test_vectors['S']['message_2']) == test_vectors['S']['message_3']
Exemplo n.º 13
0
def test_message1_decode(test_vectors):
    msg = MessageOne.decode(test_vectors['S']['message_1'])

    assert msg.corr == test_vectors["S"]["corr"]
    assert msg.method == test_vectors["S"]["method"]
    assert msg.cipher_suites == [
        CipherSuite.from_id(x) for x in test_vectors["I"]["supported"]
    ]
    assert msg.selected_cipher.identifier == test_vectors["I"]["selected"]
    assert msg.g_x == test_vectors["I"]["g_x"]
    assert msg.conn_idi == test_vectors['I']['conn_id']
    assert msg.aad1 == test_vectors['I']['ad_1']
Exemplo n.º 14
0
    def _generate_ephemeral_key(self) -> None:
        """
        Generate a new ephemeral key if the key was not already set.

        :return: None
        """

        if self.ephemeral_key is not None:
            return

        chosen_suite = CipherSuite.from_id(self.cipher_suite)

        if chosen_suite.dh_curve in [X25519, X448]:
            self.ephemeral_key = OKPKey.generate_key(crv=chosen_suite.dh_curve)
        else:
            self.ephemeral_key = EC2Key.generate_key(crv=chosen_suite.dh_curve)
Exemplo n.º 15
0
    def __init__(self,
                 corr: Correlation,
                 method: Method,
                 cred: Union[RPK, Certificate],
                 cred_idi: CoseHeaderMap,
                 auth_key: RPK,
                 selected_cipher: Type['CS'],
                 supported_ciphers: List[Type['CS']],
                 remote_cred_cb: Callable[[CoseHeaderMap], Union[Certificate,
                                                                 RPK]],
                 conn_idi: Optional[bytes] = None,
                 aad1_cb: Optional[Callable[..., bytes]] = None,
                 aad2_cb: Optional[Callable[..., bytes]] = None,
                 aad3_cb: Optional[Callable[..., bytes]] = None,
                 ephemeral_key: Optional['CK'] = None):
        """
        Create an EDHOC Initiator.

        :param corr: Correlation value (depends on the transport protocol).
        :param method: EDHOC method type (signatures, static DH or a mix).
        :param cred: The public authentication credentials of the Initiator.
        :param cred_idi: The Initiator's credential identifier (a CBOR encoded COSE header map)
        :param auth_key: The private authentication key (CoseKey) of the Responder.
        :param selected_cipher: Provide the selected cipher.
        :param supported_ciphers: A list of ciphers supported by the Responder.
        :param conn_idi: The connection identifier to be used
        :param remote_cred_cb: A callback that fetches the remote credentials.
        :param aad1_cb: A callback to pass received additional data to the application protocol.
        :param aad2_cb: A callback to pass additional data to the remote endpoint.
        :param aad3_cb: A callback to pass received additional data to the application protocol.
        :param ephemeral_key: Preload an (CoseKey) ephemeral key (if unset a random key will be generated).
        """

        if conn_idi is None:
            conn_idi = os.urandom(1)

        super().__init__(cred, cred_idi, auth_key, supported_ciphers, conn_idi,
                         remote_cred_cb, aad1_cb, aad2_cb, aad3_cb,
                         ephemeral_key)

        self._selected_cipher = CipherSuite.from_id(selected_cipher)
        self._corr = Correlation(corr)
        self._method = Method(method)

        self._cred_idr = None
Exemplo n.º 16
0
def ephemeral_initiator_key(test_vectors):
    return OKPKey(
        x=test_vectors['I']['g_x'],
        d=test_vectors['I']['x'],
        crv=CipherSuite.from_id(test_vectors['I']['selected']).dh_curve)
Exemplo n.º 17
0
def ephemeral_responder_key(test_vectors):
    return OKPKey(
        x=test_vectors['R']['g_y'],
        d=test_vectors['R']['y'],
        crv=CipherSuite.from_id(test_vectors['I']['selected']).dh_curve)