[libvirt] adding smartcard support to libvirt
Alon Levy
alevy at redhat.com
Tue Jan 4 09:17:17 UTC 2011
On Mon, Jan 03, 2011 at 11:50:18AM -0700, Eric Blake wrote:
> [adding the public list for feedback on new XML. Background: Alon is
> working on adding some new command line arguments to qemu to make it
> possible to share smartcard access between a host and its virtual
> guests; while this is not upstream yet, libvirt should be prepared to
> handle the new command line options]
>
> [lengthy email; skip to the tail end for a high-level summary of
> proposed XML changes]
>
So my own summary: it's all good, you just mixed the name and id for the
spicevmc. More about the spicevmc below.
> On 12/22/2010 03:00 AM, Alon Levy wrote:
> > On Mon, Dec 20, 2010 at 12:19:42PM -0700, Eric Blake wrote:
> >> I also found the following which also served as a good overview for what
> >> you are proposing to add to qemu:
> >>
> >> http://cgit.freedesktop.org/~alon/qemu/commit/?h=usb_ccid.v9&id=d5484a05
> >
> > Of course, sorry, should have pointed you to that initially. I wrote the
> > ccid.txt one, the other is Robert Relyea's (the author of the libcacard
> > library).
> >
> >>
> >> Right now, I'm thinking of adding a new <smartcard> element under
> >> <devices>. Let me know if this makes sense or needs tweaking; once the
> >> XML is in place, I can then figure out how to map to qemu command lines
> >> pretty easily.
>
> >
> > Ok, so to make a little order: There are three devices being added to qemu,
> > they are:
> > * usb-ccid - this is both a usb device and a ccid bus. The rest of the devices
> > attach to this bus (so they don't care that the bus is actually a usb device
> > itself, same as a PCI device exposing an IDE bus).
> > * ccid-card-emulated - this device uses NSS directly, so it can work in two modes:
> > * no arguments at all - in this case it will look for whatever hardware NSS can
> > access by default. This will depend on the specific host setup, and on the user
> > credentials qemu is running under.
> > * cert1, cert2, cert3 arguments - in this case NSS will look for three certs
> > with the names supplied, and use them instead of any physical hardware. In this case qemu
> > just needs to have those certificates available, and no physical hardware is required.
> > * ccid-card-passthru - this device doesn't rely on NSS at all. Instead it uses a chardevice,
> > and implements the VSCard protocol over it, which is just a simple protocol for remoting
> > the CCID requests (actually it works in the APDU level, so it doesn't care for CCID specifically,
> > but then again if you read the CCID you'll notice the main messages are XferBlock which just passes
> > an APDU along too).
> > Here there are also two basic options, depending on which char device we want to use. Of course you
> > are not limited to these two, you can use any chardevice, but I've been using only these two and
> > I can't think of a use for any other right now:
> > * tcp socket char device - in this case you can use the accompanying libcacard/vscclient program
> > running on another (or the same) machine, it uses NSS in exactly the same ways (certs/hw) as described
> > above for the emulated card (which is of course natural since it is using the same library to do
> > that, libcacard).
> > * spice chardevice - this is a chardevice that uses libspice, which is linked with qemu. spice in
> > turn will use a channel to the client which links with libcacard. This device is available here:
> > http://lists.gnu.org/archive/html/qemu-devel/2010-12/msg01442.html
> > as you can see from that thread, it isn't accepted yet, but anthony told me he wants to schedule
> > vdagent (and by extension, spice chardevice, i.e. spicevmc chardev) talk to qemu community meeting
> > after new years.
> >
> >
> > So I hope you understand that you do in fact need some device, in this
> case
> > the usb-ccid device, it's only the card emulated that uses the
> certificates,
> > not the bus device. The bus device remains the same for all of the various
> > configurations.
> >
>
> Just to restate (to make sure I'm understanding you correctly),
> smartcard support in qemu requires that you enable two things: the
> usb-ccid device, and your choice of the ccid-card-emulated device or the
> ccid-card-passthru device. The ccid-card-emulated device operates in
> two modes, and the ccid-card-passthru device uses a protocol to talk
> through a required associated chardev (where the other end of the
> chardev can operate in two modes, but that's outside of what the guest
> can see; and where two particular chardevs make the most sense).
>
Exactly.
> > So after this lengthy summary, you see that actually the mode tag is good, I guess also the names
> > you set are good.
>
> Picking the right mode names is probably the hardest part of writing new
> XML in a way that can be reused across other hypervisor technologies if
> similar approaches are adopted there, as well as allowing reasonable XML
> additions in the future, which is why I'm opening the feedback to make
> sure it all looks good.
>
> >>> * passthrough from a host attached smartcard reader. (despite
> passthrough in the use
> >>> case name, this is actually done using the ccid-card-emulated device)
> >>
> >> <domain...>
> >> <devices>
> >> <smartcard mode='host'>
> >> <source path='usb-ccid'/>
> >> </smartcard>
> >> </devices>
> >> </domain>
> >>
> >> maps to qemu -usb -device usb-ccid -device ccid-card-emulated
>
> > I don't really grok the "source path='usb-ccid'", unless you just want
> to ensure
> > that this can be replaced with other devices in the future, which in
> this case sounds good to me.
> >
>
> Then <source> isn't quite the right terminology for this. If we ever do
> come up with a future qemu device that can replace usb-ccid while still
> providing everything needed for the ccid-card-emulated device to work,
> then we can augment the XML at that point for choosing how to replace
> the usb-ccid device, but I don't think we need to tie it to <source> for
> the current proposal.
>
> So, this mode can be simplified. In other words, requesting mode='host'
> implies turning on anything in the hypervisor necessary to let the
> hypervisor use NSS access to the host's smartcard support (in qemu's
> case, turning on both the usb-ccid device and the ccid-card-emulated
> device with no arguments). Therefore, mode='host' wouldn't need any
> sub-elements for now.
>
> <domain...>
> <devices>
> <smartcard mode='host'/>
> </devices>
> </domain>
>
Looks good.
> >>> * passthrough from a client via vscclient program (this is done using ccid-card-passthrough
> >>> but with a standard tcp chardevice)
> >>
> >> <domain...>
> >> <devices>
> >> <smartcard mode='certificates'>
> >> <source path='usb-ccid'/>
> >> <certificate id='1' path='cert1'/>
> >> <certificate id='2' path='cert2'/>
> >> <certificate id='3' path='cert3'/>
> >> </smartcard>
> >> </devices>
> >> </domain>
> >>
> >> maps to qemu -usb -device usb-ccid -device
> >>
> ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
> >>
> >> Libvirt will have to ensure that the qemu user has access rights to read
> >> the three certificate files on the host. My idea here is that
> >> mode='certificates' requires an element for the host source, as well as
> >> paths to the three host certificates.
>
> > Also, maybe call certificates mode host-certificates, just to make it
> obvious?
>
> So, here's the updated proposal (again, dropping a <source> element, and
> picking a better mode name):
>
> <domain...>
> <devices>
> <smartcard mode='host-certificates'>
> <certificate id='1' path='cert1'/>
> <certificate id='2' path='cert2'/>
> <certificate id='3' path='cert3'/>
> </smartcard>
> </devices>
> </domain>
>
Looks good.
> >>> * passthrough with spice ('my' use case, -chardev spicevmc,id=smartcard,name=smartcard -device ccid-card-passthru,chardev=smartcard)
> >>
> >> <domain...>
> >> <devices>
> >> <smartcard mode='passthrough' name='smartcard'>
> >> <serial type='smartcard'>
> >> <source path='spicevmc'/>
> >> </serial>
> >> </smartcard>
> >> </devices>
> >> </domain
> >>
> >> maps to qemu -chardev spicevmc,id=smartcard,name=smartcard -device
> >> ccid-card-passthru,chardev=smartcard
>
> >> My idea here is that mode='passthrough' requires a name, which then gets
> >> used to create both the smartcard passthrough device and the backing
> >> chardev device. Then, as a child element, <smartcard> contains any
> >> other valid element that could serve as a top-level device, such as
> >> <serial type='tcp'>.
>
> >>
> >
> > Ok, so this is wrong - there are actually two source paths, if I understand
> > the idea - you would still want to explicitly specify usb-ccid (again, assuming this
> > is a future proofing for changing the underlying device), and the other would be
> > the spicevmc, and it would translate to the following command line:
> >
> > qemu -chardev spicevmc,id=smartcard,name=smartcard -usb -device usb-ccid
> > -device ccud-card-passthru,chardev=smartcard
> >
> > I guess something like:
> >
> > <smartcard mode='passthrough' name='smartcard'>
> > <source path='usb-ccid'/>
> > <serial type='smartcard'>
> > <source path='spicevmc'/>
> > </serial>
> > </smartcard>
>
> So the key point here is that use of the ccid-card-passthru device
> requires a chardev=xyz argument that maps to another existing -chardev
> device. And given that the chardev device in use is essential to the
> smartcard support, I'm proposing that the <smartcard> element require
> the paired chardev device as a sub-element, rather than as a sibling
> element.
>
> Right now, the XML for <devices> allows the following <serial> types:
> dev, file, pipe, unix, tcp, udp, null, stdio, vc, pty
>
> so there's no notion of a type='smartcard'. It looks more like the new
> serial type is 'spicevmc'. And back to my idea of omitting mention of
> usb-ccid in the XML, and refactoring things to avoid dupicate use of
> strings (to make it a bit more obvious which XML aspects impact which
> command-line aspects), that leaves us with:
>
> <domain...>
> <devices>
> <smartcard mode='passthrough' name='xyz'>
> <serial type='spicevmc'/>
> </smartcard>
> </devices>
> </domain>
>
> maps to qemu -chardev spicevmc,id=smartcard,name=xyz -usb -device
> usb-ccid -device ccid-card-passthru,chardev=xyz
>
ok, here you just mixed the id and name. I admit name is a bad, well, name,
but it was already available as a parameter to chardev's (used as the filename
for a file chardev). In the context of a spicevmc chardev the name is actually
what I internally call a subtype. There are two subtypes/names that are valid
currently: vdagent and smartcard. The id attribute is a global qemu tag that
identifies a particular instance, so what needs to match is the chardev id
and the chardev value given to the ccid-card-passthru device:
qemu -chardev spicevmc,name=smartcard,id=xyz -usb -device usb-ccid
-device ccid-card-passthru,chardev=xyz
Which is just what you have above, just name and id interchanged.
> Am I correct that a spicevmc -chardev has to use a fixed id=smartcard
Fixed name, yes.
> but an arbitrary name, and that ccid-card-passthru has to have a
arbitrary id.
> chardev=name that maps to the same name= used for a -chardev? Or is it
To the same id.
> that ccid-card-passthru has to have a chardev=name that maps to the same
> name as a -chardev id=name?
>
Same id. With these corrections - yes.
> And, given the goal that <smartcard mode='passthrough'> then has a child
> element that describes the passthrough device, it also means that I
> would be adding support for a top-level spicevmc chardev device,
> unrelated to smartcards; would this need any additional XML parameters?
>
Right, again sorry for introducing it this way - exactly correct, the spicevmc
is a separate entity. It is a new chardev, this is the chardev suggested last
time I talked to libvirt when I tried to introduce a similarly named device
called spicevmc. So instead of a superficial wrapper around virtio-serial I
am introducing a chardev that can be used to connect to the spice server that
is linked to the qemu process. The parameters for spicevmc are:
id - this is the normal identifier that all chardev's must have.
name - this distinguishes between the use of this chardev internal to spice, it
can be of two values right now as I mentioned, 'vdagent' for use as the vdagent
connection, and 'smartcard' for use by the smartcard channel.
> <domain...>
> <devices>
> <serial type='spicevmc'>
> <!-- anything else needed for a top-level spicevmc chardev? -->
> </serial>
> </devices>
> </domain>
>
<serial type='spicevmc' id='xyz' name='vdagent'/>
<serial type='spicevmc' id='xyz' name='smartcard'/>
?
> >
> >> <domain...>
> >> <devices>
> >> <smartcard mode='passthrough' name='ccid'>
> >> <serial type='tcp'>
> >> <source host='0.0.0.0' port='2001'/>
> >> <protocol type='tcp'/>
> >> </serial>
> >> </smartcard>
> >> </devices>
> >> </domain>
> >>
> >> maps to qemu -chardev
> >> socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device
> >> usb-ccid -device ccid-card-passthru,chardev=ccid
> >>
> >
> > So actually here you got the command line correctly (again, no difference
> > between both ccid-card-passthru uses except for the -chardev created), and
> > I guess I would just add the same usb-ccid specification to your element:
> >
> > <smartcard mode='passthrough' name='ccid'>
> > <source path='usb-ccid'/>
> > <serial type='tcp'>
> > <source host='0.0.0.0' port='2001'/>
> > <protocol type='tcp'/>
> > </serial>
> > </smartcard>
> >
> > btw, I'm guessing the name attribute on the top level (smartcard) element is
> > just a descriptor, like id? or is it something else? does libvirt have
> > id and name, or just name?
>
> My thoughts were that the name attribute of the <smartcard> element
> becomes the string that get reused twice in the qemu command line (once
> in the -chardev name, once I figure out whether that is by the id= or
> the name= field, and once in the -ccid-card-passthru chardev= field).
> This one is a bit easier, since top-level <serial type='tcp'> already
> exists, so I think this one remains:
>
> <domain...>
> <devices>
> <smartcard mode='passthrough' name='ccid'>
> <serial type='tcp'>
> <source host='0.0.0.0' port='2001'/>
> <protocol type='tcp'/>
> </serial>
> </smartcard>
> </devices>
> </domain>
>
So just s/name/id/ there (i.e. id='ccid') and it's good.
>
> >>
> >
> > Ok, so I don't understand exactly what you wanted the name to mean. Unless
> > you meant for it to do exactly what I thought adding a source element side by
> > side with the serial element would do, namely specifying the device (devices)
> > to use, what I called future proofing.
> >
> >>> * emulated with certificates (ccid-card-emulated with proper parameters to use user provided file certificates)
> >>
> >> Since the certificates live in the guest and do not pass through the
> >> qemu command line, my understanding is that libvirt does not see this as
> >> any different from mode='passthrough' above.
> >
> > Yes, I just specified this for completness sake.
> >
>
> In summary, this is my proposal for the new XML; feedback welcome to
> correct anything:
>
> <devices> modifies one existing sub-element (<serial> learns a new
> type='spicevmc' to match qemu's new spicevmc chardev), and adds a new
> sub-element <smartcard>. The new <smartcard> element has a required
> mode attribute, that takes on one of three strings:
>
> <smartcard mode='host'/>
> no other attributes, no sub-elements. Implies that the hypervisor
> exposes whatever devices necessary to the guest to see a smartcard, and
> feeds the smartcard implementation by communicating natively with the
> host smartcard for all needed information (maps to qemu -usb -device
> usb-ccid -device ccid-card-emulated)
>
> <smartcard mode='host-certificates'>
> <certificate id='1' path='cert1'/>
> <certificate id='2' path='cert2'/>
> <certificate id='3' path='cert3'/>
> </smartcard>
> no other attributes, but requires three <certificate> sub-elements.
> Implies that the hypervisor exposes whatever devices necessary to the
> guest to see a smartcard, and that it feeds the smartcard implementation
> with three certificate files living in the host rather than trying to
> talk to a host smartcard (maps to qemu -usb -device usb-ccid -device
> ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3)
>
> <smartcard mode='passthrough' name='xyz'>
> <serial .../>
> </smartcard>
> name attribute is optional but recommended (assuming libvirt can create
> a unique name if none is provided). <serial> sub-element is required,
> with the same form as a normal <serial> sub-element of <devices>, but
> the common uses will be <serial type='tcp'> (existing) or <serial
> type='spicevmc'> (new). Implies that the hypervisor exposes whatever
> devices necessary to the guest to see a smartcard, and that it feeds the
> smartcard implementation via the associated char device (maps to qemu
> -chardev ...,name=xyz -usb -device usb-ccid -device
> ccid-card-passthru,chardev-xyz)
just s/name/id/.
>
> --
> Eric Blake eblake at redhat.com +1-801-349-2682
> Libvirt virtualization library http://libvirt.org
>
More information about the libvir-list
mailing list