[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