Ejemplo n.º 1
0
def fuzz():
    jsonrpc_url = sys.argv[1] if len(
        sys.argv) > 1 else "http://localhost:8000/json/"
    trustee_proxy = JsonRpcProxy(
        url=jsonrpc_url,
        response_error_handler=status_slugs_response_error_handler)

    for i in range(100):
        keychain_uid = generate_uuid0()
        key_cipher_algo = random.choice(SUPPORTED_ASYMMETRIC_KEY_ALGOS)
        print("Fetching key of type %s... " % key_cipher_algo, end="")
        trustee_proxy.fetch_public_key(keychain_uid=keychain_uid,
                                       key_algo=key_cipher_algo)
        print("DONE")
def test_jsonrpc_trustee_signature(live_server):
    jsonrpc_url = _get_trustee_jsonrpc_url(live_server)

    trustee_proxy = JsonRpcProxy(
        url=jsonrpc_url,
        response_error_handler=status_slugs_response_error_handler)

    keychain_uid = generate_uuid0()
    payload_signature_algo = "DSA_DSS"
    secret = get_random_bytes(101)
    secret_too_big = get_random_bytes(150)

    public_key_signature_pem = trustee_proxy.fetch_public_key(
        keychain_uid=keychain_uid, key_algo=payload_signature_algo)
    public_key_signature = load_asymmetric_key_from_pem_bytestring(
        key_pem=public_key_signature_pem, key_algo=payload_signature_algo)

    signature = trustee_proxy.get_message_signature(
        keychain_uid=keychain_uid,
        message=secret,
        signature_algo=payload_signature_algo)

    with pytest.raises(ValidationError, match="too big"):
        trustee_proxy.get_message_signature(
            keychain_uid=keychain_uid,
            message=secret_too_big,
            signature_algo=payload_signature_algo,
        )

    verify_message_signature(
        message=secret,
        signature=signature,
        key=public_key_signature,
        signature_algo=payload_signature_algo,
    )

    signature["signature_value"] += b"xyz"
    with pytest.raises(SignatureVerificationError,
                       match="not authentic|Incorrect signature"):
        verify_message_signature(
            message=secret,
            signature=signature,
            key=public_key_signature,
            signature_algo=payload_signature_algo,
        )
def test_jsonrpc_trustee_request_decryption_authorization_for_normal_keys(
        live_server):
    jsonrpc_url = jsonrpc_url = _get_trustee_jsonrpc_url(live_server)

    trustee_proxy = JsonRpcProxy(
        url=jsonrpc_url,
        response_error_handler=status_slugs_response_error_handler)

    key_cipher_algo = "RSA_OAEP"

    with freeze_time(
    ) as frozen_datetime:  # TEST AUTHORIZATION REQUEST HANDLING

        keychain_uid1 = generate_uuid0()
        keychain_uid2 = generate_uuid0()
        keychain_uid3 = generate_uuid0()
        keychain_uid4 = generate_uuid0()
        keychain_uid_unexisting = generate_uuid0()

        all_keypair_identifiers = [
            dict(keychain_uid=keychain_uid1, key_algo=key_cipher_algo),
            dict(keychain_uid=keychain_uid2, key_algo=key_cipher_algo),
            dict(keychain_uid=keychain_uid3, key_algo=key_cipher_algo),
            dict(keychain_uid=keychain_uid4, key_algo=key_cipher_algo),
            dict(keychain_uid=keychain_uid_unexisting,
                 key_algo=key_cipher_algo),
        ]

        public_key_pem = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid1, key_algo=key_cipher_algo)
        assert public_key_pem
        assert not _fetch_key_object_or_raise(
            keychain_uid=keychain_uid1,
            key_algo=key_cipher_algo).decryption_authorized_at

        # Non-pregenerated keys don't have that field set!
        assert not _fetch_key_object_or_raise(
            keychain_uid=keychain_uid1, key_algo=key_cipher_algo).attached_at

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=[], request_message="I want decryption!")
        assert result["success_count"] == 0
        assert result["too_old_count"] == 0
        assert result["not_found_count"] == 0

        frozen_datetime.tick(delta=timedelta(minutes=2))

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=all_keypair_identifiers,
            request_message="I want decryption!",
        )
        assert result["success_count"] == 1
        assert result["too_old_count"] == 0
        assert (result["not_found_count"] == 4
                )  # keychain_uid2 and keychain_uid3 not created yet

        old_decryption_authorized_at = _fetch_key_object_or_raise(
            keychain_uid=keychain_uid1,
            key_algo=key_cipher_algo).decryption_authorized_at
        assert old_decryption_authorized_at

        public_key_pem = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid2, key_algo=key_cipher_algo)
        assert public_key_pem
        public_key_pem = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid3, key_algo=key_cipher_algo)
        assert public_key_pem

        frozen_datetime.tick(delta=timedelta(minutes=4))

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=all_keypair_identifiers,
            request_message="I want decryption!",
        )
        assert result["success_count"] == 2
        assert result["too_old_count"] == 1
        assert result["not_found_count"] == 2

        assert (_fetch_key_object_or_raise(
            keychain_uid=keychain_uid1,
            key_algo=key_cipher_algo).decryption_authorized_at ==
                old_decryption_authorized_at)  # Unchanged
        assert _fetch_key_object_or_raise(
            keychain_uid=keychain_uid2,
            key_algo=key_cipher_algo).decryption_authorized_at
        assert _fetch_key_object_or_raise(
            keychain_uid=keychain_uid3,
            key_algo=key_cipher_algo).decryption_authorized_at

        with pytest.raises(KeyDoesNotExist, match="not found"):
            _fetch_key_object_or_raise(keychain_uid=keychain_uid_unexisting,
                                       key_algo=key_cipher_algo)

        public_key_pem = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid4, key_algo=key_cipher_algo)
        assert public_key_pem

        frozen_datetime.tick(delta=timedelta(minutes=6))

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=all_keypair_identifiers,
            request_message="I want decryption!",
        )
        assert result["success_count"] == 0
        assert result["too_old_count"] == 4
        assert result["not_found_count"] == 1

        assert (_fetch_key_object_or_raise(
            keychain_uid=keychain_uid1,
            key_algo=key_cipher_algo).decryption_authorized_at ==
                old_decryption_authorized_at)  # Unchanged

    del all_keypair_identifiers
def test_jsonrpc_trustee_request_decryption_authorization_for_free_keys(
        live_server):
    jsonrpc_url = jsonrpc_url = _get_trustee_jsonrpc_url(live_server)

    trustee_proxy = JsonRpcProxy(
        url=jsonrpc_url,
        response_error_handler=status_slugs_response_error_handler)

    keychain_uid_free = generate_uuid0()
    free_key_algo1 = "RSA_OAEP"
    free_key_algo2 = "ECC_DSS"
    free_key_algo3 = "DSA_DSS"

    all_requested_keypair_identifiers = [
        dict(keychain_uid=keychain_uid_free, key_algo=free_key_algo1),
        dict(keychain_uid=keychain_uid_free, key_algo=free_key_algo2),
    ]

    sql_keystore = SqlKeystore()

    with freeze_time(
    ) as frozen_datetime:  # TEST RELATION WITH FREE KEYS ATTACHMENT

        for i in range(3):  # Generate 1 free keypair per type
            has_generated = generate_free_keypair_for_least_provisioned_key_algo(
                keystore=sql_keystore,
                max_free_keys_per_algo=1,
                key_algos=[free_key_algo1, free_key_algo2, free_key_algo3])
            assert has_generated

        keys_generated_before_datetime = timezone.now()

        public_key_pem1 = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo1)
        assert public_key_pem1

        # This key will not have early-enough request for authorization
        public_key_pem3 = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo3)
        assert public_key_pem3

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=all_requested_keypair_identifiers,
            request_message="I want early decryption!",
        )
        assert result["success_count"] == 1
        assert result["too_old_count"] == 0
        assert result[
            "not_found_count"] == 1  # free_key_algo2 is not attached yet

        frozen_datetime.tick(delta=timedelta(minutes=6))

        public_key_pem2 = trustee_proxy.fetch_public_key(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo2)
        assert public_key_pem2

        result = trustee_proxy.request_decryption_authorization(
            keypair_identifiers=all_requested_keypair_identifiers,
            request_message="I want later decryption!",
        )
        assert result[
            "success_count"] == 1  # It's attachment time which counts!
        assert result["too_old_count"] == 1  # First key is too old now
        assert result["not_found_count"] == 0

        keypair_obj = TrusteeKeypair.objects.get(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo1)
        assert keypair_obj.created_at <= keys_generated_before_datetime
        assert keypair_obj.attached_at
        assert keypair_obj.decryption_authorized_at
        first_authorized_at = keypair_obj.decryption_authorized_at

        keypair_obj = TrusteeKeypair.objects.get(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo2)
        assert keypair_obj.created_at <= keys_generated_before_datetime
        assert keypair_obj.attached_at
        assert keypair_obj.decryption_authorized_at
        assert keypair_obj.decryption_authorized_at >= first_authorized_at + timedelta(
            minutes=5)

        keypair_obj = TrusteeKeypair.objects.get(
            keychain_uid=keychain_uid_free, key_algo=free_key_algo3)
        assert keypair_obj.created_at <= keys_generated_before_datetime
        assert keypair_obj.attached_at
        assert not keypair_obj.decryption_authorized_at  # Never requested
def test_jsonrpc_trustee_decryption_authorization_flags(live_server):
    jsonrpc_url = _get_trustee_jsonrpc_url(live_server)

    trustee_proxy = JsonRpcProxy(
        url=jsonrpc_url,
        response_error_handler=status_slugs_response_error_handler)

    keychain_uid = generate_uuid0()
    keychain_uid_bad = generate_uuid0()
    key_cipher_algo = "RSA_OAEP"
    secret = get_random_bytes(101)

    public_encryption_key_pem = trustee_proxy.fetch_public_key(
        keychain_uid=keychain_uid, key_algo=key_cipher_algo)
    public_encryption_key = load_asymmetric_key_from_pem_bytestring(
        key_pem=public_encryption_key_pem, key_algo=key_cipher_algo)

    cipherdict = _encrypt_via_rsa_oaep(
        plaintext=secret, key_dict=dict(key=public_encryption_key))

    def _attempt_decryption():
        return trustee_proxy.decrypt_with_private_key(
            keychain_uid=keychain_uid,
            cipher_algo=key_cipher_algo,
            cipherdict=cipherdict,
        )

    with freeze_time() as frozen_datetime:
        with pytest.raises(AuthorizationError,
                           match="Decryption not authorized"):
            _attempt_decryption()

        keypair_obj = TrusteeKeypair.objects.get(keychain_uid=keychain_uid,
                                                 key_algo=key_cipher_algo)
        keypair_obj.decryption_authorized_at = timezone.now() + timedelta(
            hours=2)
        keypair_obj.save()

        with pytest.raises(
                AuthorizationError,
                match="Decryption authorization is only valid from"):
            _attempt_decryption()  # Too early

        frozen_datetime.tick(delta=timedelta(hours=3))

        decrypted = _attempt_decryption()
        assert decrypted == secret  # It works!

        with pytest.raises(KeyDoesNotExist, match="not found"):
            trustee_proxy.decrypt_with_private_key(
                keychain_uid=keychain_uid_bad,
                cipher_algo=key_cipher_algo,
                cipherdict=cipherdict,
            )

        cipherdict["digest_list"].append(b"aaabbbccc")
        with pytest.raises(DecryptionError,
                           match="Ciphertext with incorrect length"):
            trustee_proxy.decrypt_with_private_key(
                keychain_uid=keychain_uid,
                cipher_algo=key_cipher_algo,
                cipherdict=cipherdict,
            )

        frozen_datetime.tick(delta=timedelta(
            hours=24))  # We hardcode DECRYPTION_AUTHORIZATION_LIFESPAN_H here

        with pytest.raises(
                AuthorizationError,
                match="Decryption authorization is only valid from"):
            _attempt_decryption(
            )  # Too late, cipherdict is not even used so no ValueError

        keypair_obj.decryption_authorized_at = None
        keypair_obj.save()

        with pytest.raises(AuthorizationError,
                           match="Decryption not authorized"):
            _attempt_decryption()  # No more authorization at all