From patchwork Wed Aug 19 05:46:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30572C433DF for ; Wed, 19 Aug 2020 05:48:02 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EB94920738 for ; Wed, 19 Aug 2020 05:48:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MAvM5INE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EB94920738 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41652 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8Gx7-0000i3-3S for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:48:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50156) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwJ-0007T7-MM for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:11 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:23651 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006h3-Il for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816011; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:content-type:content-type:in-reply-to:in-reply-to: references:references; bh=bz7D+mftS/cers/zOBgICPI4WEK3iloynwwBMWcJU8M=; b=MAvM5INEc6geirb0THTqf9eNCdd1oj7sGJEM/7OltheXNo83l9TgTLGtcrGqUIs2Ck4XSn 982UNRYPsRvsa6vR6DkYKJCeN8jHZa8ATt0+MR9itZDjOy2j0II50TogkAxvksjDCuVhN9 aSN0QnaXQIO7M5nXpIPmUu4rPLitK0M= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-350-yhvHD-iPOWGPQopXDKNoCg-1; Wed, 19 Aug 2020 01:46:49 -0400 X-MC-Unique: yhvHD-iPOWGPQopXDKNoCg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6EB7C1084C85; Wed, 19 Aug 2020 05:46:48 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2DD505C3E0; Wed, 19 Aug 2020 05:46:45 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 60F889AE3; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 02/17] hw: ehci: destroy sglist in error path Date: Wed, 19 Aug 2020 07:46:29 +0200 Message-Id: <20200819054644.30610-3-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.120; envelope-from=kraxel@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 23:05:17 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , Li Qiang , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Li Qiang This may cause resource leak. Signed-off-by: Li Qiang Message-Id: <20200812161712.29361-1-liq3ea@163.com> Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 1495e8f7fab1..58cceacbf83a 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1445,6 +1445,7 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); if (dev == NULL) { ehci_trace_guest_bug(ehci, "no device found"); + qemu_sglist_destroy(&ehci->isgl); return -1; } pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; From patchwork Wed Aug 19 05:46:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276084 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B73C2C433E1 for ; Wed, 19 Aug 2020 05:57:19 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 826F920772 for ; Wed, 19 Aug 2020 05:57:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="cxLMqOux" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 826F920772 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48928 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8H66-0006ar-RZ for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:57:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50310) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwQ-0007lN-QZ for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:18 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:55289 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006iA-NZ for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816016; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RBGqP8EFZYGK8U5Mb1X88W+B9neqleFAVo0mDjdtZo8=; b=cxLMqOuxzBDAdogliKegtrmT7rH4FVaQp2rMHRbabnaLIA/Q50PzY7nbWgrV7rAgtZG/sb 3hg1NtopjV8kqIjuwXYJVcTXSsYVwWC0mT7zRI663+4uFtkx4M8CNB/XLs0hfoRFf3esIC lpxsT9SPJ1U/RY1W0EYWoNJrPEAlPIY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-337-EzwyMOUoN7uiaF0kxollQw-1; Wed, 19 Aug 2020 01:46:54 -0400 X-MC-Unique: EzwyMOUoN7uiaF0kxollQw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1BB7A801ADD; Wed, 19 Aug 2020 05:46:53 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF4C57A1FA; Wed, 19 Aug 2020 05:46:48 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 87F5B1FCE8; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 06/17] docs: Add USB U2F key device documentation Date: Wed, 19 Aug 2020 07:46:33 +0200 Message-Id: <20200819054644.30610-7-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.120; envelope-from=kraxel@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 22:38:38 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley Add USB U2F key device documentation: - USB U2F key device - Building - Using u2f-emulated - Using u2f-passthru - Libu2f-emu Signed-off-by: César Belley Message-id: 20200812094135.20550-3-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- docs/u2f.txt | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/u2f.txt diff --git a/docs/u2f.txt b/docs/u2f.txt new file mode 100644 index 000000000000..f60052882ec3 --- /dev/null +++ b/docs/u2f.txt @@ -0,0 +1,101 @@ +QEMU U2F Key Device Documentation. + +Contents +1. USB U2F key device +2. Building +3. Using u2f-emulated +4. Using u2f-passthru +5. Libu2f-emu + +1. USB U2F key device + +U2F is an open authentication standard that enables relying parties +exposed to the internet to offer a strong second factor option for end +user authentication. + +The standard brings many advantages to both parties, client and server, +allowing to reduce over-reliance on passwords, it increases authentication +security and simplifies passwords. + +The second factor is materialized by a device implementing the U2F +protocol. In case of a USB U2F security key, it is a USB HID device +that implements the U2F protocol. + +In Qemu, the USB U2F key device offers a dedicated support of U2F, allowing +guest USB FIDO/U2F security keys operating in two possible modes: +pass-through and emulated. + +The pass-through mode consists of passing all requests made from the guest +to the physical security key connected to the host machine and vice versa. +In addition, the dedicated pass-through allows to have a U2F security key +shared on several guests which is not possible with a simple host device +assignment pass-through. + +The emulated mode consists of completely emulating the behavior of an +U2F device through software part. Libu2f-emu is used for that. + + +2. Building + +To ensure the build of the u2f-emulated device variant which depends +on libu2f-emu: configuring and building: + + ./configure --enable-u2f && make + + +3. Using u2f-emulated + +To work, an emulated U2F device must have four elements: + * ec x509 certificate + * ec private key + * counter (four bytes value) + * 48 bytes of entropy (random bits) + +To use this type of device, this one has to be configured, and these +four elements must be passed one way or another. + +Assuming that you have a working libu2f-emu installed on the host. +There are three possible ways of configurations: + * ephemeral + * setup directory + * manual + +Ephemeral is the simplest way to configure, it lets the device generate +all the elements it needs for a single use of the lifetime of the device. + + qemu -usb -device u2f-emulated + +Setup directory allows to configure the device from a directory containing +four files: + * certificate.pem: ec x509 certificate + * private-key.pem: ec private key + * counter: counter value + * entropy: 48 bytes of entropy + + qemu -usb -device u2f-emulated,dir=$dir + +Manual allows to configure the device more finely by specifying each +of the elements necessary for the device: + * cert + * priv + * counter + * entropy + + qemu -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4 + + +4. Using u2f-passthru + +On the host specify the u2f-passthru device with a suitable hidraw: + + qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0 + + +5. Libu2f-emu + +The u2f-emulated device uses libu2f-emu for the U2F key emulation. Libu2f-emu +implements completely the U2F protocol device part for all specified +transport given by the FIDO Alliance. + +For more information about libu2f-emu see this page: +https://github.com/MattGorko/libu2f-emu. From patchwork Wed Aug 19 05:46:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276085 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B5CCC433DF for ; Wed, 19 Aug 2020 05:54:33 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 033DC20772 for ; Wed, 19 Aug 2020 05:54:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="K0zdCpex" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 033DC20772 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39994 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8H3Q-0002wd-A7 for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:54:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50314) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwR-0007mW-73 for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:19 -0400 Received: from us-smtp-2.mimecast.com ([205.139.110.61]:20416 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006hm-MR for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816014; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mWZxIiY3QGnt5SuGA0W8f1qGrnG+uHzZfJsnzAfwqVI=; b=K0zdCpexZUDz2Db+GSUL14GEwuvoLOmTCJUSfl+bsGw7IFGmQOMJOn4nF6TSvitSHj116w e3awjyyaKhU4S/VJCAE1RIDXW2vwa0uxA3ixuNPSiDvUA7CX4/PANsj35quR8R/07W0END C0L44j3L6MmnyGLQlnW/NH7OiZ1ZCdM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-134-miF1LhLwOSq50cU4a3yxnw-1; Wed, 19 Aug 2020 01:46:52 -0400 X-MC-Unique: miF1LhLwOSq50cU4a3yxnw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 27D3C1084C85; Wed, 19 Aug 2020 05:46:51 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2FF3F5C882; Wed, 19 Aug 2020 05:46:49 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id A3F7D204B8; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 09/17] hw/usb: Add U2F key passthru mode Date: Wed, 19 Aug 2020 07:46:36 +0200 Message-Id: <20200819054644.30610-10-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.61; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 23:06:33 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley This patch adds the U2F key pass-through mode. The pass-through mode consists of passing all requests made from the guest to the physical security key connected to the host machine and vice versa. In addition, the dedicated pass-through allows to have a U2F security key shared on several guests which is not possible with a simple host device assignment pass-through. The pass-through mode is associated with a device inheriting from u2f-key base. To work, it needs the path to a U2F hidraw, obtained from the Qemu command line, and passed by the user: qemu -usb -device u2f-passthru,hidraw=/dev/hidrawX Autoscan and U2F compatibility checking features are given at the end of the patch series. Signed-off-by: César Belley Message-id: 20200812094135.20550-6-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- hw/usb/u2f-passthru.c | 423 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 hw/usb/u2f-passthru.c diff --git a/hw/usb/u2f-passthru.c b/hw/usb/u2f-passthru.c new file mode 100644 index 000000000000..106b5abf9ecc --- /dev/null +++ b/hw/usb/u2f-passthru.c @@ -0,0 +1,423 @@ +/* + * U2F USB Passthru device. + * + * Copyright (c) 2020 César Belley + * Written by César Belley + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "qemu/main-loop.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/usb.h" +#include "migration/vmstate.h" + +#include "u2f.h" + +#define NONCE_SIZE 8 +#define BROADCAST_CID 0xFFFFFFFF +#define TRANSACTION_TIMEOUT 120000 + +struct transaction { + uint32_t cid; + uint16_t resp_bcnt; + uint16_t resp_size; + + /* Nonce for broadcast isolation */ + uint8_t nonce[NONCE_SIZE]; +}; + +typedef struct U2FPassthruState U2FPassthruState; + +#define CURRENT_TRANSACTIONS_NUM 4 + +struct U2FPassthruState { + U2FKeyState base; + + /* Host device */ + char *hidraw; + int hidraw_fd; + + /* Current Transactions */ + struct transaction current_transactions[CURRENT_TRANSACTIONS_NUM]; + uint8_t current_transactions_start; + uint8_t current_transactions_end; + uint8_t current_transactions_num; + + /* Transaction time checking */ + int64_t last_transaction_time; + QEMUTimer timer; +}; + +#define TYPE_U2F_PASSTHRU "u2f-passthru" +#define PASSTHRU_U2F_KEY(obj) \ + OBJECT_CHECK(U2FPassthruState, (obj), TYPE_U2F_PASSTHRU) + +/* Init packet sizes */ +#define PACKET_INIT_HEADER_SIZE 7 +#define PACKET_INIT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_INIT_HEADER_SIZE) + +/* Cont packet sizes */ +#define PACKET_CONT_HEADER_SIZE 5 +#define PACKET_CONT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_CONT_HEADER_SIZE) + +struct packet_init { + uint32_t cid; + uint8_t cmd; + uint8_t bcnth; + uint8_t bcntl; + uint8_t data[PACKET_INIT_DATA_SIZE]; +} QEMU_PACKED; + +static inline uint32_t packet_get_cid(const void *packet) +{ + return *((uint32_t *)packet); +} + +static inline bool packet_is_init(const void *packet) +{ + return ((uint8_t *)packet)[4] & (1 << 7); +} + +static inline uint16_t packet_init_get_bcnt( + const struct packet_init *packet_init) +{ + uint16_t bcnt = 0; + bcnt |= packet_init->bcnth << 8; + bcnt |= packet_init->bcntl; + + return bcnt; +} + +static void u2f_passthru_reset(U2FPassthruState *key) +{ + timer_del(&key->timer); + qemu_set_fd_handler(key->hidraw_fd, NULL, NULL, key); + key->last_transaction_time = 0; + key->current_transactions_start = 0; + key->current_transactions_end = 0; + key->current_transactions_num = 0; +} + +static void u2f_timeout_check(void *opaque) +{ + U2FPassthruState *key = opaque; + int64_t time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + + if (time > key->last_transaction_time + TRANSACTION_TIMEOUT) { + u2f_passthru_reset(key); + } else { + timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); + } +} + +static int u2f_transaction_get_index(U2FPassthruState *key, uint32_t cid) +{ + for (int i = 0; i < key->current_transactions_num; ++i) { + int index = (key->current_transactions_start + i) + % CURRENT_TRANSACTIONS_NUM; + if (cid == key->current_transactions[index].cid) { + return index; + } + } + return -1; +} + +static struct transaction *u2f_transaction_get(U2FPassthruState *key, + uint32_t cid) +{ + int index = u2f_transaction_get_index(key, cid); + if (index < 0) { + return NULL; + } + return &key->current_transactions[index]; +} + +static struct transaction *u2f_transaction_get_from_nonce(U2FPassthruState *key, + const uint8_t nonce[NONCE_SIZE]) +{ + for (int i = 0; i < key->current_transactions_num; ++i) { + int index = (key->current_transactions_start + i) + % CURRENT_TRANSACTIONS_NUM; + if (key->current_transactions[index].cid == BROADCAST_CID + && memcmp(nonce, key->current_transactions[index].nonce, + NONCE_SIZE) == 0) { + return &key->current_transactions[index]; + } + } + return NULL; +} + +static void u2f_transaction_close(U2FPassthruState *key, uint32_t cid) +{ + int index, next_index; + index = u2f_transaction_get_index(key, cid); + if (index < 0) { + return; + } + next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; + + /* Rearrange to ensure the oldest is at the start position */ + while (next_index != key->current_transactions_end) { + memcpy(&key->current_transactions[index], + &key->current_transactions[next_index], + sizeof(struct transaction)); + + index = next_index; + next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; + } + + key->current_transactions_end = index; + --key->current_transactions_num; + + if (key->current_transactions_num == 0) { + u2f_passthru_reset(key); + } +} + +static void u2f_transaction_add(U2FPassthruState *key, uint32_t cid, + const uint8_t nonce[NONCE_SIZE]) +{ + uint8_t index; + struct transaction *transaction; + + if (key->current_transactions_num >= CURRENT_TRANSACTIONS_NUM) { + /* Close the oldest transaction */ + index = key->current_transactions_start; + transaction = &key->current_transactions[index]; + u2f_transaction_close(key, transaction->cid); + } + + /* Index */ + index = key->current_transactions_end; + key->current_transactions_end = (index + 1) % CURRENT_TRANSACTIONS_NUM; + ++key->current_transactions_num; + + /* Transaction */ + transaction = &key->current_transactions[index]; + transaction->cid = cid; + transaction->resp_bcnt = 0; + transaction->resp_size = 0; + + /* Nonce */ + if (nonce != NULL) { + memcpy(transaction->nonce, nonce, NONCE_SIZE); + } +} + +static void u2f_passthru_read(void *opaque); + +static void u2f_transaction_start(U2FPassthruState *key, + const struct packet_init *packet_init) +{ + int64_t time; + + /* Transaction */ + if (packet_init->cid == BROADCAST_CID) { + u2f_transaction_add(key, packet_init->cid, packet_init->data); + } else { + u2f_transaction_add(key, packet_init->cid, NULL); + } + + /* Time */ + time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + if (key->last_transaction_time == 0) { + qemu_set_fd_handler(key->hidraw_fd, u2f_passthru_read, NULL, key); + timer_init_ms(&key->timer, QEMU_CLOCK_VIRTUAL, u2f_timeout_check, key); + timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); + } + key->last_transaction_time = time; +} + +static void u2f_passthru_recv_from_host(U2FPassthruState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + struct transaction *transaction; + uint32_t cid; + + /* Retrieve transaction */ + cid = packet_get_cid(packet); + if (cid == BROADCAST_CID) { + struct packet_init *packet_init; + if (!packet_is_init(packet)) { + return; + } + packet_init = (struct packet_init *)packet; + transaction = u2f_transaction_get_from_nonce(key, packet_init->data); + } else { + transaction = u2f_transaction_get(key, cid); + } + + /* Ignore no started transaction */ + if (transaction == NULL) { + return; + } + + if (packet_is_init(packet)) { + struct packet_init *packet_init = (struct packet_init *)packet; + transaction->resp_bcnt = packet_init_get_bcnt(packet_init); + transaction->resp_size = PACKET_INIT_DATA_SIZE; + + if (packet_init->cid == BROADCAST_CID) { + /* Nonce checking for legitimate response */ + if (memcmp(transaction->nonce, packet_init->data, NONCE_SIZE) + != 0) { + return; + } + } + } else { + transaction->resp_size += PACKET_CONT_DATA_SIZE; + } + + /* Transaction end check */ + if (transaction->resp_size >= transaction->resp_bcnt) { + u2f_transaction_close(key, cid); + } + u2f_send_to_guest(&key->base, packet); +} + +static void u2f_passthru_read(void *opaque) +{ + U2FPassthruState *key = opaque; + U2FKeyState *base = &key->base; + uint8_t packet[2 * U2FHID_PACKET_SIZE]; + int ret; + + /* Full size base queue check */ + if (base->pending_in_num >= U2FHID_PENDING_IN_NUM) { + return; + } + + ret = read(key->hidraw_fd, packet, sizeof(packet)); + if (ret < 0) { + /* Detach */ + if (base->dev.attached) { + usb_device_detach(&base->dev); + u2f_passthru_reset(key); + } + return; + } + if (ret != U2FHID_PACKET_SIZE) { + return; + } + u2f_passthru_recv_from_host(key, packet); +} + +static void u2f_passthru_recv_from_guest(U2FKeyState *base, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + uint8_t host_packet[U2FHID_PACKET_SIZE + 1]; + ssize_t written; + + if (packet_is_init(packet)) { + u2f_transaction_start(key, (struct packet_init *)packet); + } + + host_packet[0] = 0; + memcpy(host_packet + 1, packet, U2FHID_PACKET_SIZE); + + written = write(key->hidraw_fd, host_packet, sizeof(host_packet)); + if (written != sizeof(host_packet)) { + error_report("%s: Bad written size (req 0x%lx, val 0x%lx)", + TYPE_U2F_PASSTHRU, sizeof(host_packet), written); + } +} + +static void u2f_passthru_unrealize(U2FKeyState *base) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + + u2f_passthru_reset(key); + qemu_close(key->hidraw_fd); +} + +static void u2f_passthru_realize(U2FKeyState *base, Error **errp) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + int fd; + + if (key->hidraw == NULL) { + error_setg(errp, "%s: Missing hidraw", TYPE_U2F_PASSTHRU); + return; + } + + fd = qemu_open(key->hidraw, O_RDWR); + if (fd < 0) { + error_setg(errp, "%s: Failed to open %s", TYPE_U2F_PASSTHRU, + key->hidraw); + return; + } + key->hidraw_fd = fd; + u2f_passthru_reset(key); +} + +static int u2f_passthru_post_load(void *opaque, int version_id) +{ + U2FPassthruState *key = opaque; + u2f_passthru_reset(key); + return 0; +} + +static const VMStateDescription u2f_passthru_vmstate = { + .name = "u2f-key-passthru", + .version_id = 1, + .minimum_version_id = 1, + .post_load = u2f_passthru_post_load, + .fields = (VMStateField[]) { + VMSTATE_U2F_KEY(base, U2FPassthruState), + VMSTATE_END_OF_LIST() + } +}; + +static Property u2f_passthru_properties[] = { + DEFINE_PROP_STRING("hidraw", U2FPassthruState, hidraw), + DEFINE_PROP_END_OF_LIST(), +}; + +static void u2f_passthru_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + U2FKeyClass *kc = U2F_KEY_CLASS(klass); + + kc->realize = u2f_passthru_realize; + kc->unrealize = u2f_passthru_unrealize; + kc->recv_from_guest = u2f_passthru_recv_from_guest; + dc->desc = "QEMU U2F passthrough key"; + dc->vmsd = &u2f_passthru_vmstate; + device_class_set_props(dc, u2f_passthru_properties); +} + +static const TypeInfo u2f_key_passthru_info = { + .name = TYPE_U2F_PASSTHRU, + .parent = TYPE_U2F_KEY, + .instance_size = sizeof(U2FPassthruState), + .class_init = u2f_passthru_class_init +}; + +static void u2f_key_passthru_register_types(void) +{ + type_register_static(&u2f_key_passthru_info); +} + +type_init(u2f_key_passthru_register_types) From patchwork Wed Aug 19 05:46:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276087 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8FA58C433E3 for ; Wed, 19 Aug 2020 05:51:11 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5EE1420772 for ; Wed, 19 Aug 2020 05:51:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IoTFdsbs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5EE1420772 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:57542 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8H0A-000750-KW for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:51:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50238) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwM-0007aP-UU for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:14 -0400 Received: from us-smtp-2.mimecast.com ([205.139.110.61]:33228 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006hL-Lf for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816012; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g3CLSo2EtGQlfx/ug/byoG1oK2g3CL0Ik/QO69B6dSM=; b=IoTFdsbs3bMYQtsozhj3dztMVhhOA4VXtRZDjVKujIiLJizRVyBTO8+Nc2xAZIlB3LY5mW 2rHO6hV9T5IARG/+jdjb6zdIXpUnJPqZhPj7ocioFYYCUyW05tV0YVzakpMzxSMj3a5UBf v722qNXcjQxjJSATgr9zasgMZoIU6rw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-554-S2YMYGqFNa-FtqSHXmq5HA-1; Wed, 19 Aug 2020 01:46:50 -0400 X-MC-Unique: S2YMYGqFNa-FtqSHXmq5HA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ACA8581F02C; Wed, 19 Aug 2020 05:46:49 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 58C3C1014181; Wed, 19 Aug 2020 05:46:49 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id C118431E22; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 12/17] configure: Add USB U2F key device Date: Wed, 19 Aug 2020 07:46:39 +0200 Message-Id: <20200819054644.30610-13-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.61; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 23:06:33 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley Signed-off-by: César Belley Message-id: 20200812094135.20550-9-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- configure | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/configure b/configure index 2acc4d1465f8..3ea5e561ff43 100755 --- a/configure +++ b/configure @@ -447,6 +447,7 @@ trace_file="trace" spice="" rbd="" smartcard="" +u2f="" libusb="" usb_redir="" opengl="" @@ -1390,6 +1391,10 @@ for opt do ;; --enable-smartcard) smartcard="yes" ;; + --disable-u2f) u2f="no" + ;; + --enable-u2f) u2f="yes" + ;; --disable-libusb) libusb="no" ;; --enable-libusb) libusb="yes" @@ -1899,6 +1904,7 @@ disabled with --disable-FEATURE, default is enabled if available: libiscsi iscsi support libnfs nfs support smartcard smartcard support (libcacard) + u2f U2F support (u2f-emu) libusb libusb (for usb passthrough) live-block-migration Block migration in the main migration stream usb-redir usb network redirection support @@ -5250,6 +5256,20 @@ if test "$smartcard" != "no"; then fi fi +# check for u2f support +if test "$u2f" != "no"; then + if $pkg_config --atleast-version=0.0.0 u2f-emu; then + u2f_emu_cflags=$($pkg_config --cflags u2f-emu) + u2f_emu_libs=$($pkg_config --libs u2f-emu) + u2f="yes" + else + if test "$u2f" = "yes"; then + feature_not_found "u2f" "Install u2f-emu" + fi + u2f="no" + fi +fi + # check for libusb if test "$libusb" != "no" ; then if $pkg_config --atleast-version=1.0.13 libusb-1.0; then @@ -6965,6 +6985,7 @@ echo "spice support $spice $(echo_version $spice $spice_protocol_version/$sp echo "rbd support $rbd" echo "xfsctl support $xfs" echo "smartcard support $smartcard" +echo "U2F support $u2f" echo "libusb $libusb" echo "usb net redir $usb_redir" echo "OpenGL support $opengl" @@ -7543,6 +7564,12 @@ if test "$smartcard" = "yes" ; then echo "SMARTCARD_LIBS=$libcacard_libs" >> $config_host_mak fi +if test "$u2f" = "yes" ; then + echo "CONFIG_U2F=y" >> $config_host_mak + echo "U2F_CFLAGS=$u2f_emu_cflags" >> $config_host_mak + echo "U2F_LIBS=$u2f_emu_libs" >> $config_host_mak +fi + if test "$libusb" = "yes" ; then echo "CONFIG_USB_LIBUSB=y" >> $config_host_mak echo "LIBUSB_CFLAGS=$libusb_cflags" >> $config_host_mak From patchwork Wed Aug 19 05:46:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55884C433DF for ; Wed, 19 Aug 2020 05:49:28 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 221DE20738 for ; Wed, 19 Aug 2020 05:49:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IKcMJYxD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 221DE20738 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49310 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8GyV-0003k6-BG for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:49:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50226) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwM-0007Z0-EY for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:14 -0400 Received: from us-smtp-1.mimecast.com ([207.211.31.81]:49165 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006hy-LK for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816015; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LVJjnymdXMKEYEDq70/vjd+4eCBVEbWJifgk2mNGxGc=; b=IKcMJYxDXD6hTOJ+RQq0imIPNRwQKrDhiLWJxGBmyh2k37fKifoB1vZtZoGfxDcwHZ5n76 zGSw+2xzGm3RQwHzIGx+DpRUndIWC/mUi+KC4bH+rUCWV6D3Pm2AiX/z4edhyel/MlRYs6 5Rj9PVT5iWw6LKoXu6vE0qK4GrUMjjg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-433-6-jayw9RO8CGJrqVDZ2FKw-1; Wed, 19 Aug 2020 01:46:51 -0400 X-MC-Unique: 6-jayw9RO8CGJrqVDZ2FKw-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6AD1A1084C91; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1479616D40; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id D304431E31; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 14/17] docs/qdev-device-use.txt: Add USB U2F key to the QDEV devices examples Date: Wed, 19 Aug 2020 07:46:41 +0200 Message-Id: <20200819054644.30610-15-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.81; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/19 01:46:53 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley Signed-off-by: César Belley Message-id: 20200812094135.20550-11-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- docs/qdev-device-use.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index f8d0d2fe297a..9889521e3c07 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -325,6 +325,7 @@ The new way is -device DEVNAME,DEV-OPTS... Details depend on DRIVER: * mouse -device usb-mouse * tablet -device usb-tablet * wacom-tablet -device usb-wacom-tablet +* u2f -device u2f-{emulated,passthru} * braille See "Character Devices" === Watchdog Devices === From patchwork Wed Aug 19 05:46:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 38FCAC433E3 for ; Wed, 19 Aug 2020 05:49:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 08E2F207D3 for ; Wed, 19 Aug 2020 05:49:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="J9WqEWr+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 08E2F207D3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:50082 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8Gyd-00042r-8i for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:49:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50202) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwL-0007Vk-8j for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:13 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:55338 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006iN-L1 for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816016; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1shM/BteYDzoqt55bAtKxjG+b7FJGiLhhC0zV3nwwv0=; b=J9WqEWr+ZWaa7ZSHs1qmCUz4Wc5T7sEUOqzB8UtKysYkayVMhy/OKwunY1RqpY4ZAi6p/A ban7BMrUcNONHYZqUAaD2tppe16BD2R88pZIpm1CMb3FZccRJTgxsyleBygJJerrxR2292 v4T1B+KlswndTbD17hq7Uk2+9jwba8Q= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-88-4ugpm1JGNpGPtO2M4fAzaQ-1; Wed, 19 Aug 2020 01:46:51 -0400 X-MC-Unique: 4ugpm1JGNpGPtO2M4fAzaQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 088EC186A56D; Wed, 19 Aug 2020 05:46:51 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 25C35600DD; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id DC21831E32; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 15/17] scripts: Add u2f-setup-gen script Date: Wed, 19 Aug 2020 07:46:42 +0200 Message-Id: <20200819054644.30610-16-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.120; envelope-from=kraxel@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 23:05:17 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley This patch adds the script used to generate setup directories, needed for the device u2f-emulated configuration in directory mode: python u2f-setup-gen.py $DIR qemu -usb -device u2f-emulated,dir=$DIR Signed-off-by: César Belley Message-id: 20200812094135.20550-12-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- scripts/u2f-setup-gen.py | 170 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100755 scripts/u2f-setup-gen.py diff --git a/scripts/u2f-setup-gen.py b/scripts/u2f-setup-gen.py new file mode 100755 index 000000000000..2122598fed8e --- /dev/null +++ b/scripts/u2f-setup-gen.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# +# Libu2f-emu setup directory generator for USB U2F key emulation. +# +# Copyright (c) 2020 César Belley +# Written by César Belley +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or, at your option, any later version. See the COPYING file in +# the top-level directory. + +import sys +import os +from random import randint +from typing import Tuple + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.serialization import Encoding, \ + NoEncryption, PrivateFormat, PublicFormat +from OpenSSL import crypto + + +def write_setup_dir(dirpath: str, privkey_pem: bytes, cert_pem: bytes, + entropy: bytes, counter: int) -> None: + """ + Write the setup directory. + + Args: + dirpath: The directory path. + key_pem: The private key PEM. + cert_pem: The certificate PEM. + entropy: The 48 bytes of entropy. + counter: The counter value. + """ + # Directory + os.mkdir(dirpath) + + # Private key + with open(f'{dirpath}/private-key.pem', 'bw') as f: + f.write(privkey_pem) + + # Certificate + with open(f'{dirpath}/certificate.pem', 'bw') as f: + f.write(cert_pem) + + # Entropy + with open(f'{dirpath}/entropy', 'wb') as f: + f.write(entropy) + + # Counter + with open(f'{dirpath}/counter', 'w') as f: + f.write(f'{str(counter)}\n') + + +def generate_ec_key_pair() -> Tuple[str, str]: + """ + Generate an ec key pair. + + Returns: + The private and public key PEM. + """ + # Key generation + privkey = ec.generate_private_key(ec.SECP256R1, default_backend()) + pubkey = privkey.public_key() + + # PEM serialization + privkey_pem = privkey.private_bytes(encoding=Encoding.PEM, + format=PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=NoEncryption()) + pubkey_pem = pubkey.public_bytes(encoding=Encoding.PEM, + format=PublicFormat.SubjectPublicKeyInfo) + return privkey_pem, pubkey_pem + + +def generate_certificate(privkey_pem: str, pubkey_pem: str) -> str: + """ + Generate a x509 certificate from a key pair. + + Args: + privkey_pem: The private key PEM. + pubkey_pem: The public key PEM. + + Returns: + The certificate PEM. + """ + # Convert key pair + privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkey_pem) + pubkey = crypto.load_publickey(crypto.FILETYPE_PEM, pubkey_pem) + + # New x509v3 certificate + cert = crypto.X509() + cert.set_version(0x2) + + # Serial number + cert.set_serial_number(randint(1, 2 ** 64)) + + # Before / After + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(4 * (365 * 24 * 60 * 60)) + + # Public key + cert.set_pubkey(pubkey) + + # Subject name and issueer + cert.get_subject().CN = "U2F emulated" + cert.set_issuer(cert.get_subject()) + + # Extensions + cert.add_extensions([ + crypto.X509Extension(b"subjectKeyIdentifier", + False, b"hash", subject=cert), + ]) + cert.add_extensions([ + crypto.X509Extension(b"authorityKeyIdentifier", + False, b"keyid:always", issuer=cert), + ]) + cert.add_extensions([ + crypto.X509Extension(b"basicConstraints", True, b"CA:TRUE") + ]) + + # Signature + cert.sign(privkey, 'sha256') + + return crypto.dump_certificate(crypto.FILETYPE_PEM, cert) + + +def generate_setup_dir(dirpath: str) -> None: + """ + Generates the setup directory. + + Args: + dirpath: The directory path. + """ + # Key pair + privkey_pem, pubkey_pem = generate_ec_key_pair() + + # Certificate + certificate_pem = generate_certificate(privkey_pem, pubkey_pem) + + # Entropy + entropy = os.urandom(48) + + # Counter + counter = 0 + + # Write + write_setup_dir(dirpath, privkey_pem, certificate_pem, entropy, counter) + + +def main() -> None: + """ + Main function + """ + # Dir path + if len(sys.argv) != 2: + sys.stderr.write(f'Usage: {sys.argv[0]} \n') + exit(2) + dirpath = sys.argv[1] + + # Dir non existence + if os.path.exists(dirpath): + sys.stderr.write(f'Directory: {dirpath} already exists.\n') + exit(1) + + generate_setup_dir(dirpath) + + +if __name__ == '__main__': + main() From patchwork Wed Aug 19 05:46:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276086 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9B9CC433DF for ; Wed, 19 Aug 2020 05:53:16 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A6A2D207DA for ; Wed, 19 Aug 2020 05:53:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Zt1svg+e" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A6A2D207DA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:35780 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8H2B-0001FV-Uu for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:53:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50274) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwP-0007gU-0M for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:17 -0400 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:54221 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006ha-My for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816013; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BxuhH6+Drmw5uYT+dWlDJ45CLzXxno4jER49ygELXPk=; b=Zt1svg+er994ibbt1fi47+RmteRBgh5Z2iRjY74oZ52XxAAaASehPAJWIAep1KPmnIZJqD oUJacFUWIyRv7Zyu3DIAZw6ByefuZPglqp12qCcqmCqwUi/87pjBFxnaWQtLJowPH0t5H/ uyLOOyDfuDMqxcvejigEBQGxH3asyS8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-221-LuIgagPZMBuYhb5q8cOr9w-1; Wed, 19 Aug 2020 01:46:51 -0400 X-MC-Unique: LuIgagPZMBuYhb5q8cOr9w-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 976361084C89; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E2DA1014182; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id E6AA331E43; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 16/17] hw/usb: Add U2F device check to passthru mode Date: Wed, 19 Aug 2020 07:46:43 +0200 Message-Id: <20200819054644.30610-17-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.81; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/19 01:46:53 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley This patchs adds a check to verify that the device passed through the hidraw property is a U2F device. The check is done by ensuring that the first values of the report descriptor (USAGE PAGE and USAGE) correspond to those of a U2F device. Signed-off-by: César Belley Message-id: 20200812094135.20550-13-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- hw/usb/u2f-passthru.c | 41 +++++++++++++++++++++++++++++++++++++++++ hw/usb/Makefile.objs | 3 ++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/hw/usb/u2f-passthru.c b/hw/usb/u2f-passthru.c index 106b5abf9ecc..f8771966c747 100644 --- a/hw/usb/u2f-passthru.c +++ b/hw/usb/u2f-passthru.c @@ -34,6 +34,12 @@ #include "u2f.h" +#ifdef CONFIG_LIBUDEV +#include +#endif +#include +#include + #define NONCE_SIZE 8 #define BROADCAST_CID 0xFFFFFFFF #define TRANSACTION_TIMEOUT 120000 @@ -344,6 +350,34 @@ static void u2f_passthru_recv_from_guest(U2FKeyState *base, } } +static bool u2f_passthru_is_u2f_device(int fd) +{ + int ret, rdesc_size; + struct hidraw_report_descriptor rdesc; + const uint8_t u2f_hid_report_desc_header[] = { + 0x06, 0xd0, 0xf1, /* Usage Page (FIDO) */ + 0x09, 0x01, /* Usage (FIDO) */ + }; + + /* Get report descriptor size */ + ret = ioctl(fd, HIDIOCGRDESCSIZE, &rdesc_size); + if (ret < 0 || rdesc_size < sizeof(u2f_hid_report_desc_header)) { + return false; + } + + /* Get report descriptor */ + memset(&rdesc, 0x0, sizeof(rdesc)); + rdesc.size = rdesc_size; + ret = ioctl(fd, HIDIOCGRDESC, &rdesc); + if (ret < 0) { + return false; + } + + /* Header bytes cover specific U2F rdesc values */ + return memcmp(u2f_hid_report_desc_header, rdesc.value, + sizeof(u2f_hid_report_desc_header)) == 0; +} + static void u2f_passthru_unrealize(U2FKeyState *base) { U2FPassthruState *key = PASSTHRU_U2F_KEY(base); @@ -368,6 +402,13 @@ static void u2f_passthru_realize(U2FKeyState *base, Error **errp) key->hidraw); return; } + + if (!u2f_passthru_is_u2f_device(fd)) { + qemu_close(fd); + error_setg(errp, "%s: Passed hidraw does not represent " + "a U2F HID device", TYPE_U2F_PASSTHRU); + return; + } key->hidraw_fd = fd; u2f_passthru_reset(key); } diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 7842a3175f8f..9e7e1f33a51e 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -38,7 +38,8 @@ endif endif ifeq ($(CONFIG_USB_U2F),y) -common-obj-y += u2f.o u2f-passthru.o +common-obj-y += u2f.o +common-obj-$(CONFIG_LINUX) += u2f-passthru.o common-obj-$(CONFIG_U2F) += u2f-emulated.o u2f-emulated.o-cflags = $(U2F_CFLAGS) u2f-emulated.o-libs = $(U2F_LIBS) From patchwork Wed Aug 19 05:46:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 276088 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52949C433E1 for ; Wed, 19 Aug 2020 05:51:04 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 11FD220738 for ; Wed, 19 Aug 2020 05:51:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MH2OFybw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 11FD220738 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56938 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8H03-0006qE-8F for qemu-devel@archiver.kernel.org; Wed, 19 Aug 2020 01:51:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50244) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8GwN-0007bp-Dv for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:15 -0400 Received: from us-smtp-2.mimecast.com ([205.139.110.61]:35043 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k8GwH-0006hj-LJ for qemu-devel@nongnu.org; Wed, 19 Aug 2020 01:47:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1597816014; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Lzhmj//O7v2F3kl+IvlYRmsUEF5FVjCObAdqNJls28=; b=MH2OFybw5KwptDE/3rkacIsS7TbJ807wT6qz5KTlYjhz/pfyUTD3DMlD8mrAJOBMhP2WBi gV3Q/WebTskWKTesGotBrvXhFAqNfSZTuqX5lFgv7fi85GH11KLzh7eSYMLpZHFisFJ4wv 59yu/E0MA/MZbEtt2vWiunPEV729zNw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-560-aljN4Q4ROFCdHHsQfrdjlg-1; Wed, 19 Aug 2020 01:46:52 -0400 X-MC-Unique: aljN4Q4ROFCdHHsQfrdjlg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 15258801AF3; Wed, 19 Aug 2020 05:46:51 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-195.ams2.redhat.com [10.36.112.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id 325381014183; Wed, 19 Aug 2020 05:46:50 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id F2F4931E47; Wed, 19 Aug 2020 07:46:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 17/17] hw/usb: Add U2F device autoscan to passthru mode Date: Wed, 19 Aug 2020 07:46:44 +0200 Message-Id: <20200819054644.30610-18-kraxel@redhat.com> In-Reply-To: <20200819054644.30610-1-kraxel@redhat.com> References: <20200819054644.30610-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.61; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 23:06:33 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?C=C3=A9sar_Belley?= , Gerd Hoffmann , Cleber Rosa , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: César Belley This patch adds an autoscan to let u2f-passthru choose the first U2F device it finds. The autoscan is performed using libudev with an enumeration of all the hidraw devices present on the host. The first device which happens to be a U2F device is taken to do the pass-through. Signed-off-by: César Belley Message-id: 20200812094135.20550-14-cesar.belley@lse.epita.fr Signed-off-by: Gerd Hoffmann --- docs/u2f.txt | 9 ++++ hw/usb/u2f-passthru.c | 113 +++++++++++++++++++++++++++++++++++++----- hw/usb/Makefile.objs | 1 + 3 files changed, 110 insertions(+), 13 deletions(-) diff --git a/docs/u2f.txt b/docs/u2f.txt index f60052882ec3..8f44994818a2 100644 --- a/docs/u2f.txt +++ b/docs/u2f.txt @@ -42,6 +42,10 @@ on libu2f-emu: configuring and building: ./configure --enable-u2f && make +The pass-through mode is built by default on Linux. To take advantage +of the autoscan option it provides, make sure you have a working libudev +installed on the host. + 3. Using u2f-emulated @@ -90,6 +94,11 @@ On the host specify the u2f-passthru device with a suitable hidraw: qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0 +Alternately, the u2f-passthru device can autoscan to take the first +U2F device it finds on the host (this requires a working libudev): + + qemu -usb -device u2f-passthru + 5. Libu2f-emu diff --git a/hw/usb/u2f-passthru.c b/hw/usb/u2f-passthru.c index f8771966c747..1311530ee5ba 100644 --- a/hw/usb/u2f-passthru.c +++ b/hw/usb/u2f-passthru.c @@ -378,6 +378,84 @@ static bool u2f_passthru_is_u2f_device(int fd) sizeof(u2f_hid_report_desc_header)) == 0; } +#ifdef CONFIG_LIBUDEV +static int u2f_passthru_open_from_device(struct udev_device *device) +{ + const char *devnode = udev_device_get_devnode(device); + + int fd = qemu_open(devnode, O_RDWR); + if (fd < 0) { + return -1; + } else if (!u2f_passthru_is_u2f_device(fd)) { + qemu_close(fd); + return -1; + } + return fd; +} + +static int u2f_passthru_open_from_enumerate(struct udev *udev, + struct udev_enumerate *enumerate) +{ + struct udev_list_entry *devices, *entry; + int ret, fd; + + ret = udev_enumerate_scan_devices(enumerate); + if (ret < 0) { + return -1; + } + + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(entry, devices) { + struct udev_device *device; + const char *syspath = udev_list_entry_get_name(entry); + + if (syspath == NULL) { + continue; + } + + device = udev_device_new_from_syspath(udev, syspath); + if (device == NULL) { + continue; + } + + fd = u2f_passthru_open_from_device(device); + udev_device_unref(device); + if (fd >= 0) { + return fd; + } + } + return -1; +} + +static int u2f_passthru_open_from_scan(void) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + int ret, fd = -1; + + udev = udev_new(); + if (udev == NULL) { + return -1; + } + + enumerate = udev_enumerate_new(udev); + if (enumerate == NULL) { + udev_unref(udev); + return -1; + } + + ret = udev_enumerate_add_match_subsystem(enumerate, "hidraw"); + if (ret >= 0) { + fd = u2f_passthru_open_from_enumerate(udev, enumerate); + } + + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return fd; +} +#endif + static void u2f_passthru_unrealize(U2FKeyState *base) { U2FPassthruState *key = PASSTHRU_U2F_KEY(base); @@ -392,22 +470,31 @@ static void u2f_passthru_realize(U2FKeyState *base, Error **errp) int fd; if (key->hidraw == NULL) { +#ifdef CONFIG_LIBUDEV + fd = u2f_passthru_open_from_scan(); + if (fd < 0) { + error_setg(errp, "%s: Failed to find a U2F USB device", + TYPE_U2F_PASSTHRU); + return; + } +#else error_setg(errp, "%s: Missing hidraw", TYPE_U2F_PASSTHRU); return; - } +#endif + } else { + fd = qemu_open(key->hidraw, O_RDWR); + if (fd < 0) { + error_setg(errp, "%s: Failed to open %s", TYPE_U2F_PASSTHRU, + key->hidraw); + return; + } - fd = qemu_open(key->hidraw, O_RDWR); - if (fd < 0) { - error_setg(errp, "%s: Failed to open %s", TYPE_U2F_PASSTHRU, - key->hidraw); - return; - } - - if (!u2f_passthru_is_u2f_device(fd)) { - qemu_close(fd); - error_setg(errp, "%s: Passed hidraw does not represent " - "a U2F HID device", TYPE_U2F_PASSTHRU); - return; + if (!u2f_passthru_is_u2f_device(fd)) { + qemu_close(fd); + error_setg(errp, "%s: Passed hidraw does not represent " + "a U2F HID device", TYPE_U2F_PASSTHRU); + return; + } } key->hidraw_fd = fd; u2f_passthru_reset(key); diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 9e7e1f33a51e..7c0ee92ca47a 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -41,6 +41,7 @@ ifeq ($(CONFIG_USB_U2F),y) common-obj-y += u2f.o common-obj-$(CONFIG_LINUX) += u2f-passthru.o common-obj-$(CONFIG_U2F) += u2f-emulated.o +u2f-passthru.o-libs = $(LIBUDEV_LIBS) u2f-emulated.o-cflags = $(U2F_CFLAGS) u2f-emulated.o-libs = $(U2F_LIBS) endif