diff options
| -rw-r--r-- | NK_C_API.cc | 8 | ||||
| -rw-r--r-- | NK_C_API.h | 11 | ||||
| -rw-r--r-- | NitrokeyManager.cc | 27 | ||||
| -rw-r--r-- | device.cc | 77 | ||||
| -rw-r--r-- | libnitrokey/device.h | 18 | 
5 files changed, 116 insertions, 25 deletions
| diff --git a/NK_C_API.cc b/NK_C_API.cc index 1d3fa3a..75c8b97 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -158,6 +158,9 @@ extern "C" {                      case NK_STORAGE:                          model_string = "S";                          break; +                    case NK_LIBREM: +                        model_string = "L"; +                        break;                      case NK_DISCONNECTED:                      default:                          /* no such enum value -- return error code */ @@ -236,6 +239,8 @@ extern "C" {  				    return NK_PRO;  				case DeviceModel::STORAGE:  				    return NK_STORAGE; +				case DeviceModel::LIBREM: +				    return NK_LIBREM;  				default:  				    /* unknown or not connected device */  				    return NK_device_model::NK_DISCONNECTED; @@ -791,6 +796,9 @@ NK_C_API char* NK_get_SD_usage_data_as_string() {  		case DeviceModel::STORAGE:  			target->model = NK_STORAGE;  			break; +		case DeviceModel::LIBREM: +			target->model = NK_LIBREM; +			break;  		default:  			return false;  		} @@ -67,6 +67,9 @@   *         case NK_STORAGE:   *                 printf("a Nitrokey Storage");   *                 break; + *         case NK_LIBREM: + *                 printf("a Librem Key"); + *                 break;   *         default:   *                 printf("an unsupported Nitrokey");   *                 break; @@ -111,7 +114,11 @@ extern "C" {              /**               * Nitrokey Storage.               */ -            NK_STORAGE = 2 +            NK_STORAGE = 2, +            /** +             * Librem Key. +             */ +            NK_LIBREM = 3          };          /** @@ -327,7 +334,7 @@ extern "C" {  	/**  	 * Connect to device of given model. Currently library can be connected only to one device at once. -	 * @param device_model NK_device_model: NK_PRO: Nitrokey Pro, NK_STORAGE: Nitrokey Storage +	 * @param device_model NK_device_model: NK_PRO: Nitrokey Pro, NK_STORAGE: Nitrokey Storage, NK_LIBREM: Librem Key  	 * @return 1 if connected, 0 if wrong model or cannot connect  	 */          NK_C_API int NK_login_enum(enum NK_device_model device_model); diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index 6c26a43..71d156f 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -217,7 +217,12 @@ using nitrokey::misc::strcpyT;              }          } -        auto info_ptr = hid_enumerate(NITROKEY_VID, 0); +	auto vendor_id = NITROKEY_VID; +        auto info_ptr = hid_enumerate(vendor_id, 0); +	if (!info_ptr) { +	  vendor_id = PURISM_VID; +	  info_ptr = hid_enumerate(vendor_id, 0); +	}          auto first_info_ptr = info_ptr;          if (!info_ptr)            return false; @@ -225,7 +230,7 @@ using nitrokey::misc::strcpyT;          misc::Option<DeviceModel> model;          while (info_ptr && !model.has_value()) {              if (path == std::string(info_ptr->path)) { -                model = product_id_to_model(info_ptr->product_id); +                model = product_id_to_model(info_ptr->vendor_id, info_ptr->product_id);              }              info_ptr = info_ptr->next;          } @@ -254,7 +259,8 @@ using nitrokey::misc::strcpyT;      bool NitrokeyManager::connect() {          std::lock_guard<std::mutex> lock(mex_dev_com_manager); -        vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>() }; +        vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>(), +						 make_shared<LibremKey>() };          bool connected = false;          for( auto & d : devices ){              if (d->connect()){ @@ -290,6 +296,9 @@ using nitrokey::misc::strcpyT;              case 'S':                  device = make_shared<Stick20>();                  break; +            case 'L': +                device = make_shared<LibremKey>(); +                break;              default:                  throw std::runtime_error("Unknown model");          } @@ -305,6 +314,9 @@ using nitrokey::misc::strcpyT;              case device::DeviceModel::STORAGE:                  model_string = "S";                  break; +            case device::DeviceModel::LIBREM: +                model_string = "L"; +                break;              default:                  throw std::runtime_error("Unknown model");          } @@ -382,6 +394,7 @@ using nitrokey::misc::strcpyT;      string NitrokeyManager::get_serial_number() {          if (device == nullptr) { return ""; };        switch (device->get_device_model()) { +        case DeviceModel::LIBREM:          case DeviceModel::PRO: {            auto response = GetStatus::CommandTransaction::run(device);            return nitrokey::misc::toHex(response.data().card_serial_u32); @@ -552,6 +565,7 @@ using nitrokey::misc::strcpyT;        strcpyT(payload.slot_name, slot_name);        strcpyT(payload.slot_token_id, token_ID);        switch (device->get_device_model() ){ +        case DeviceModel::LIBREM:          case DeviceModel::PRO: {            payload.slot_counter = hotp_counter;            break; @@ -713,6 +727,7 @@ using nitrokey::misc::strcpyT;      template <typename ProCommand, PasswordKind StoKind>      void NitrokeyManager::change_PIN_general(const char *current_PIN, const char *new_PIN) {          switch (device->get_device_model()){ +            case DeviceModel::LIBREM:              case DeviceModel::PRO:              {                  auto p = get_payload<ProCommand>(); @@ -834,6 +849,7 @@ using nitrokey::misc::strcpyT;      void NitrokeyManager::build_aes_key(const char *admin_password) {          switch (device->get_device_model()) { +            case DeviceModel::LIBREM:              case DeviceModel::PRO: {                  auto p = get_payload<BuildAESKey>();                  strcpyT(p.admin_password, admin_password); @@ -858,6 +874,7 @@ using nitrokey::misc::strcpyT;      void NitrokeyManager::unlock_user_password(const char *admin_password, const char *new_user_password) {        switch (device->get_device_model()){ +        case DeviceModel::LIBREM:          case DeviceModel::PRO: {            auto p = get_payload<stick10::UnlockUserPassword>();            strcpyT(p.admin_password, admin_password); @@ -907,6 +924,7 @@ using nitrokey::misc::strcpyT;        //authorization command is supported for versions equal or below:          auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({                                                 {DeviceModel::PRO, 7}, +                                               {DeviceModel::LIBREM, 7},                                                 {DeviceModel::STORAGE, 53},           });          return get_minor_firmware_version() <= m[device->get_device_model()]; @@ -916,6 +934,7 @@ using nitrokey::misc::strcpyT;          // 320 bit OTP secret is supported by version bigger or equal to:          auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({                                                 {DeviceModel::PRO, 8}, +                                               {DeviceModel::LIBREM, 8},                                                 {DeviceModel::STORAGE, 54},           });          return get_minor_firmware_version() >= m[device->get_device_model()]; @@ -940,6 +959,7 @@ using nitrokey::misc::strcpyT;      uint8_t NitrokeyManager::get_minor_firmware_version(){        switch(device->get_device_model()){ +        case DeviceModel::LIBREM:          case DeviceModel::PRO:{            auto status_p = GetStatus::CommandTransaction::run(device);            return status_p.data().firmware_version_st.minor; //7 or 8 @@ -956,6 +976,7 @@ using nitrokey::misc::strcpyT;      }      uint8_t NitrokeyManager::get_major_firmware_version(){        switch(device->get_device_model()){ +        case DeviceModel::LIBREM:          case DeviceModel::PRO:{            auto status_p = GetStatus::CommandTransaction::run(device);            return status_p.data().firmware_version_st.major; //0 @@ -45,14 +45,33 @@ const uint16_t nitrokey::device::NITROKEY_VID = 0x20a0;  const uint16_t nitrokey::device::NITROKEY_PRO_PID = 0x4108;  const uint16_t nitrokey::device::NITROKEY_STORAGE_PID = 0x4109; +const uint16_t nitrokey::device::PURISM_VID = 0x316d; +const uint16_t nitrokey::device::LIBREM_KEY_PID = 0x4c4b; +  Option<DeviceModel> nitrokey::device::product_id_to_model(uint16_t product_id) { -  switch (product_id) { +    return product_id_to_model(NITROKEY_VID, product_id); +} + +Option<DeviceModel> nitrokey::device::product_id_to_model(uint16_t vendor_id, uint16_t product_id) { +  switch (vendor_id) { +  case NITROKEY_VID: +    switch (product_id) {      case NITROKEY_PRO_PID:        return DeviceModel::PRO;      case NITROKEY_STORAGE_PID:        return DeviceModel::STORAGE;      default:        return {}; +    } +  case PURISM_VID: +    switch (product_id) { +    case LIBREM_KEY_PID: +      return DeviceModel::LIBREM; +    default: +      return {}; +    } +  default: +    return {};    }  } @@ -67,6 +86,9 @@ std::ostream& nitrokey::device::operator<<(std::ostream& stream, DeviceModel mod      case DeviceModel::STORAGE:        stream << "Storage";        break; +    case DeviceModel::LIBREM: +      stream << "Librem"; +      break;      default:        stream << "Unknown";        break; @@ -99,7 +121,9 @@ bool Device::disconnect() {  }  bool Device::_disconnect() { -  LOG(std::string(__FUNCTION__) + std::string(m_model == DeviceModel::PRO ? "PRO" : "STORAGE"), Loglevel::DEBUG_L2); +  LOG(std::string(__FUNCTION__) + +      std::string(m_model == DeviceModel::PRO ? "PRO" : (m_model == DeviceModel::STORAGE ? "STORAGE" : "LIBREM")), +      Loglevel::DEBUG_L2);    LOG(std::string(__FUNCTION__) +  std::string(" *IN* "), Loglevel::DEBUG_L2);    if(mp_devhandle == nullptr) { @@ -204,27 +228,33 @@ int Device::recv(void *packet) {    return status;  } -std::vector<DeviceInfo> Device::enumerate(){ -  auto pInfo = hid_enumerate(NITROKEY_VID, 0); -  auto pInfo_ = pInfo; -  std::vector<DeviceInfo> res; -  while (pInfo != nullptr){ -    auto deviceModel = product_id_to_model(pInfo->product_id); -    if (deviceModel.has_value()) { -      std::string path(pInfo->path); -      std::wstring serialNumberW(pInfo->serial_number); -      std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; -      std::string serialNumber = converter.to_bytes(serialNumberW); -      DeviceInfo info = { deviceModel.value(), path, serialNumber }; -      res.push_back(info); +namespace { +  void add_vendor_devices(std::vector<DeviceInfo>& res, uint16_t vendor_id){ +    auto pInfo = hid_enumerate(vendor_id, 0); +    auto pInfo_ = pInfo; +    while (pInfo != nullptr){ +      auto deviceModel = product_id_to_model(vendor_id, pInfo->product_id); +      if (deviceModel.has_value()) { +	std::string path(pInfo->path); +	std::wstring serialNumberW(pInfo->serial_number); +	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; +	std::string serialNumber = converter.to_bytes(serialNumberW); +	DeviceInfo info = { deviceModel.value(), path, serialNumber }; +	res.push_back(info); +      } +      pInfo = pInfo->next;      } -    pInfo = pInfo->next; -  } -  if (pInfo_ != nullptr){ -    hid_free_enumeration(pInfo_); +    if (pInfo_ != nullptr){ +      hid_free_enumeration(pInfo_); +    }    } +} +std::vector<DeviceInfo> Device::enumerate(){ +  std::vector<DeviceInfo> res; +  ::add_vendor_devices(res, NITROKEY_VID); +  ::add_vendor_devices(res, PURISM_VID);    return res;  } @@ -234,6 +264,8 @@ std::shared_ptr<Device> Device::create(DeviceModel model) {        return std::make_shared<Stick10>();      case DeviceModel::STORAGE:        return std::make_shared<Stick20>(); +    case DeviceModel::LIBREM: +      return std::make_shared<LibremKey>();      default:        return {};    } @@ -305,6 +337,13 @@ Stick20::Stick20():      setDefaultDelay();    } + +LibremKey::LibremKey(): +  Device(PURISM_VID, LIBREM_KEY_PID, DeviceModel::LIBREM, 100ms, 5, 100ms) +  { +    setDefaultDelay(); +  } +  #include <sstream>  #define p(x) ss << #x << " " << x << ", ";  std::string Device::ErrorCounters::get_as_string() { diff --git a/libnitrokey/device.h b/libnitrokey/device.h index d50080d..917e0d0 100644 --- a/libnitrokey/device.h +++ b/libnitrokey/device.h @@ -50,7 +50,8 @@ namespace device {  enum class DeviceModel{      PRO, -    STORAGE +    STORAGE, +    LIBREM  };  std::ostream& operator<<(std::ostream& stream, DeviceModel model); @@ -67,12 +68,21 @@ extern const uint16_t NITROKEY_PRO_PID;   * The USB product ID for the Nitrokey Storage.   */  extern const uint16_t NITROKEY_STORAGE_PID; +/** + * The USB vendor ID for Purism devices. + */ +extern const uint16_t PURISM_VID; +/** + * The USB product ID for the Librem Key. + */ +extern const uint16_t LIBREM_KEY_PID;  /**   * Convert the given USB product ID to a Nitrokey model.  If there is no model   * with that ID, return an absent value.   */  misc::Option<DeviceModel> product_id_to_model(uint16_t product_id); +misc::Option<DeviceModel> product_id_to_model(uint16_t vendor_id, uint16_t product_id);  /**   * Information about a connected device. @@ -219,6 +229,12 @@ class Stick20 : public Device {   public:    Stick20();  }; + +class LibremKey : public Device { + public: +  LibremKey(); +}; +  }  }  #endif | 
