github.com/freetocompute/snapd@v0.0.0-20210618182524-2fb355d72fd9/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 25 "github.com/snapcore/snapd/interfaces" 26 "github.com/snapcore/snapd/interfaces/udev" 27 ) 28 29 const u2fDevicesSummary = `allows access to u2f devices` 30 31 const u2fDevicesBaseDeclarationSlots = ` 32 u2f-devices: 33 allow-installation: 34 slot-snap-type: 35 - core 36 deny-auto-connection: true 37 ` 38 39 type u2fDevice struct { 40 Name, VendorIDPattern, ProductIDPattern string 41 } 42 43 // https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules 44 var u2fDevices = []u2fDevice{ 45 { 46 Name: "Yubico YubiKey", 47 VendorIDPattern: "1050", 48 ProductIDPattern: "0113|0114|0115|0116|0120|0121|0200|0402|0403|0406|0407|0410", 49 }, 50 { 51 Name: "Happlink (formerly Plug-Up) Security KEY", 52 VendorIDPattern: "2581", 53 ProductIDPattern: "f1d0", 54 }, 55 { 56 Name: "Neowave Keydo and Keydo AES", 57 VendorIDPattern: "1e0d", 58 ProductIDPattern: "f1d0|f1ae", 59 }, 60 { 61 Name: "HyperSecu HyperFIDO", 62 VendorIDPattern: "096e|2ccf", 63 ProductIDPattern: "0880", 64 }, 65 { 66 Name: "HyperSecu HyperFIDO Pro", 67 VendorIDPattern: "2ccf", 68 ProductIDPattern: "0854", 69 }, 70 { 71 Name: "Feitian ePass FIDO, BioPass FIDO2", 72 VendorIDPattern: "096e", 73 ProductIDPattern: "0850|0852|0853|0854|0856|0858|085a|085b|085d", 74 }, 75 { 76 Name: "JaCarta U2F", 77 VendorIDPattern: "24dc", 78 ProductIDPattern: "0101", 79 }, 80 { 81 Name: "U2F Zero", 82 VendorIDPattern: "10c4", 83 ProductIDPattern: "8acf", 84 }, 85 { 86 Name: "VASCO SeccureClick", 87 VendorIDPattern: "1a44", 88 ProductIDPattern: "00bb", 89 }, 90 { 91 Name: "Bluink Key", 92 VendorIDPattern: "2abe", 93 ProductIDPattern: "1002", 94 }, 95 { 96 Name: "Thetis Key", 97 VendorIDPattern: "1ea8", 98 ProductIDPattern: "f025", 99 }, 100 { 101 Name: "Nitrokey FIDO U2F", 102 VendorIDPattern: "20a0", 103 ProductIDPattern: "4287", 104 }, 105 { 106 Name: "Google Titan U2F", 107 VendorIDPattern: "18d1", 108 ProductIDPattern: "5026", 109 }, 110 { 111 Name: "Tomu board + chopstx U2F + SoloKeys", 112 VendorIDPattern: "0483", 113 ProductIDPattern: "cdab|a2ca", 114 }, 115 { 116 Name: "SoloKeys", 117 VendorIDPattern: "1209", 118 ProductIDPattern: "5070|50b0", 119 }, 120 { 121 Name: "OnlyKey", 122 VendorIDPattern: "1d50", 123 ProductIDPattern: "60fc", 124 }, 125 { 126 Name: "MIRKey", 127 VendorIDPattern: "0483", 128 ProductIDPattern: "a2ac", 129 }, 130 { 131 Name: "Ledger Blue + Nano S + Nano X", 132 VendorIDPattern: "2c97", 133 ProductIDPattern: "0000|0001|0004|0005|0015|1005|1015|4005|4015", 134 }, 135 } 136 137 const u2fDevicesConnectedPlugAppArmor = ` 138 # Description: Allow write access to u2f hidraw devices. 139 140 # Use a glob rule and rely on device cgroup for mediation. 141 /dev/hidraw* rw, 142 143 # char 234-254 are used for dynamic assignment, which u2f devices are 144 /run/udev/data/c23[4-9]:* r, 145 /run/udev/data/c24[0-9]:* r, 146 /run/udev/data/c25[0-4]:* r, 147 148 # misc required accesses 149 /run/udev/data/+power_supply:hid* r, 150 /run/udev/data/c14:[0-9]* r, 151 /sys/devices/**/i2c*/**/report_descriptor r, 152 /sys/devices/**/usb*/**/report_descriptor r, 153 ` 154 155 type u2fDevicesInterface struct { 156 commonInterface 157 } 158 159 func (iface *u2fDevicesInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 160 for _, d := range u2fDevices { 161 spec.TagDevice(fmt.Sprintf("# %s\nSUBSYSTEM==\"hidraw\", KERNEL==\"hidraw*\", ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\"", d.Name, d.VendorIDPattern, d.ProductIDPattern)) 162 } 163 return nil 164 } 165 166 func init() { 167 registerIface(&u2fDevicesInterface{commonInterface{ 168 name: "u2f-devices", 169 summary: u2fDevicesSummary, 170 implicitOnCore: true, 171 implicitOnClassic: true, 172 baseDeclarationSlots: u2fDevicesBaseDeclarationSlots, 173 connectedPlugAppArmor: u2fDevicesConnectedPlugAppArmor, 174 }}) 175 }