github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/u2f_devices.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package builtin
    21  
    22  import (
    23  	"fmt"
    24  	"github.com/snapcore/snapd/interfaces"
    25  	"github.com/snapcore/snapd/interfaces/udev"
    26  )
    27  
    28  const u2fDevicesSummary = `allows access to u2f devices`
    29  
    30  const u2fDevicesBaseDeclarationSlots = `
    31    u2f-devices:
    32      allow-installation:
    33        slot-snap-type:
    34          - core
    35      deny-auto-connection: true
    36  `
    37  
    38  type u2fDevice struct {
    39  	Name, VendorIDPattern, ProductIDPattern string
    40  }
    41  
    42  // https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules
    43  var u2fDevices = []u2fDevice{
    44  	{
    45  		Name:             "Yubico YubiKey",
    46  		VendorIDPattern:  "1050",
    47  		ProductIDPattern: "0113|0114|0115|0116|0120|0200|0402|0403|0406|0407|0410",
    48  	},
    49  	{
    50  		Name:             "Happlink (formerly Plug-Up) Security KEY",
    51  		VendorIDPattern:  "2581",
    52  		ProductIDPattern: "f1d0",
    53  	},
    54  	{
    55  		Name:             "Neowave Keydo and Keydo AES",
    56  		VendorIDPattern:  "1e0d",
    57  		ProductIDPattern: "f1d0|f1ae",
    58  	},
    59  	{
    60  		Name:             "HyperSecu HyperFIDO",
    61  		VendorIDPattern:  "096e|2ccf",
    62  		ProductIDPattern: "0880",
    63  	},
    64  	{
    65  		Name:             "Feitian ePass FIDO, BioPass FIDO2",
    66  		VendorIDPattern:  "096e",
    67  		ProductIDPattern: "0850|0852|0853|0854|0856|0858|085a|085b|085d",
    68  	},
    69  	{
    70  		Name:             "JaCarta U2F",
    71  		VendorIDPattern:  "24dc",
    72  		ProductIDPattern: "0101",
    73  	},
    74  	{
    75  		Name:             "U2F Zero",
    76  		VendorIDPattern:  "10c4",
    77  		ProductIDPattern: "8acf",
    78  	},
    79  	{
    80  		Name:             "VASCO SeccureClick",
    81  		VendorIDPattern:  "1a44",
    82  		ProductIDPattern: "00bb",
    83  	},
    84  	{
    85  		Name:             "Bluink Key",
    86  		VendorIDPattern:  "2abe",
    87  		ProductIDPattern: "1002",
    88  	},
    89  	{
    90  		Name:             "Thetis Key",
    91  		VendorIDPattern:  "1ea8",
    92  		ProductIDPattern: "f025",
    93  	},
    94  	{
    95  		Name:             "Nitrokey FIDO U2F",
    96  		VendorIDPattern:  "20a0",
    97  		ProductIDPattern: "4287",
    98  	},
    99  	{
   100  		Name:             "Google Titan U2F",
   101  		VendorIDPattern:  "18d1",
   102  		ProductIDPattern: "5026",
   103  	},
   104  	{
   105  		Name:             "Tomu board + chopstx U2F + SoloKeys",
   106  		VendorIDPattern:  "0483",
   107  		ProductIDPattern: "cdab|a2ca",
   108  	},
   109  	{
   110  		Name:             "SoloKeys",
   111  		VendorIDPattern:  "1209",
   112  		ProductIDPattern: "5070|50b0",
   113  	},
   114  }
   115  
   116  const u2fDevicesConnectedPlugAppArmor = `
   117  # Description: Allow write access to u2f hidraw devices.
   118  
   119  # Use a glob rule and rely on device cgroup for mediation.
   120  /dev/hidraw* rw,
   121  
   122  # char 234-254 are used for dynamic assignment, which u2f devices are
   123  /run/udev/data/c23[4-9]:* r,
   124  /run/udev/data/c24[0-9]:* r,
   125  /run/udev/data/c25[0-4]:* r,
   126  
   127  # misc required accesses
   128  /run/udev/data/+power_supply:hid* r,
   129  /run/udev/data/c14:[0-9]* r,
   130  /sys/devices/**/i2c*/**/report_descriptor r,
   131  /sys/devices/**/usb*/**/report_descriptor r,
   132  `
   133  
   134  type u2fDevicesInterface struct {
   135  	commonInterface
   136  }
   137  
   138  func (iface *u2fDevicesInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   139  	for _, d := range u2fDevices {
   140  		spec.TagDevice(fmt.Sprintf("# %s\nSUBSYSTEM==\"hidraw\", KERNEL==\"hidraw*\", ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\"", d.Name, d.VendorIDPattern, d.ProductIDPattern))
   141  	}
   142  	return nil
   143  }
   144  
   145  func init() {
   146  	registerIface(&u2fDevicesInterface{commonInterface{
   147  		name:                  "u2f-devices",
   148  		summary:               u2fDevicesSummary,
   149  		implicitOnCore:        true,
   150  		implicitOnClassic:     true,
   151  		baseDeclarationSlots:  u2fDevicesBaseDeclarationSlots,
   152  		connectedPlugAppArmor: u2fDevicesConnectedPlugAppArmor,
   153  		reservedForOS:         true,
   154  	}})
   155  }