Did you know ... Search Documentation:
Pack keynub_licdongle -- prolog/keynub_licdongle.pl
PublicShow source

Verify that a KeyNub dongle is genuine, read and write the license records it holds, use its hardware counters and seal data so that only a dongle can open it.

The pack calls the SDK's flat C API (keynub_licdongle_flat) from the native library, which its foreign module loads at run time on the first call that needs it. Loading this module does not need the native library.

  • Every failed call throws error(keynub_error(Status, Code, Operation, Detail), _): Status is an atom such as no_device, not_genuine or auth_required (unknown for a code this pack does not know), Code the raw status code, Operation the flat API function and Detail the library's diagnostic text, which may be empty. A library that cannot be loaded throws error(keynub_library_error(Message), _).
  • Byte data (records, keys, sealed data) is a list of codes 0..255, as read_file_to_codes/3 with type(binary) returns it. Input may also be a string or atom whose characters are all below 256.
  • Text from the dongle (serials, device paths, record names, detail) is a string; text input may be an atom, string or code list. Library file paths are atoms.
 library_environment_variable(-Name) is det
The environment variable that names the library file.
 library_basename(-File) is det
The library's file name on this operating system.
 set_library_path(+Path) is det
Names the library file to load. Call it before the first dongle call. A process loads the library once; naming a different file after that throws error(keynub_library_error(Message), _).
 loaded_library_path(-Path) is semidet
The path the library was loaded from. Fails before the first call that loads it.
 library_path(-Path) is det
The path in use, or the first candidate while nothing is loaded.
 library_candidates(-Paths) is det
The paths tried, in order: the path given to set_library_path/1, else the file named by KEYNUB_LICDONGLE_FLAT_LIBRARY, else every natives/<platform>/<file> found in the program's folder, the working directory or this module's folder or one of their parents, followed by the bare file name for the system loader.
 library_version(-Version) is det
The native library's version as version(Major, Minor, Patch).
 status_name(?Code, ?Name) is nondet
Name is the atom for the status code Code (licd_status in the SDK's C header).
 status_text(+Code, -Text) is det
Human-readable text for a status code, as a string; needs no dongle.
 devices(-Devices) is det
The attached dongles, as a list of device(Serial, Path).
 is_dongle(@Term) is semidet
True when Term is a dongle from dongle_open/1,2 or dongle_open_path/2, open or closed.
 dongle_open(-Dongle) is det
 dongle_open(+Serial, -Dongle) is det
Opens the dongle with this serial, or the first one found when Serial is empty or not given. The dongle is closed by dongle_close/1, or when it is garbage collected.
 dongle_open_path(+Path, -Dongle) is det
Opens the dongle at this device path (from devices/1).
 dongle_is_open(+Dongle) is semidet
True when dongle_close/1 has not been called on Dongle yet.
 dongle_close(+Dongle) is det
Closes the dongle. Closing it again does nothing; other calls on it throw a keynub_error with status invalid_arg.
 with_dongle(-Dongle, :Goal) is semidet
 with_dongle(+Options, -Dongle, :Goal) is semidet
Opens a dongle, calls Goal as once/1 and closes the dongle on every exit path, exceptions included. Options select the dongle: serial(Serial) or path(Path); without either, the first one found.
 dongle_serial(+Dongle, -Serial) is det
The dongle's serial number (14 hex digits) as a string.
 dongle_info(+Dongle, -Info) is det
Plaintext device information, as a dict with the keys protocol_major, protocol_minor, firmware_major, firmware_minor, firmware_patch and data_capacity, data_free (bytes), and the booleans (true or false) secure_element_ready, provisioned, watchdog_reboot, isolated and write_auth_rotated.
 dongle_verify_genuine(+Dongle) is det
 dongle_verify_genuine(+Dongle, -Serial, -ProvisionedDate) is det
Proves the dongle is genuine: certificate chain to the trusted root plus a live challenge-response. Succeeds only when it is and throws otherwise. Serial is the verified serial; ProvisionedDate is the day the unit was personalised ("YYYY-MM-DD"), or "" when it reports none.
 dongle_genuine(+Dongle) is semidet
The test for a gate: succeeds only when dongle_verify_genuine/1 succeeds. Fails closed: every error makes it fail.
 set_dongle_trust_root(+Dongle, +Der) is det
Overrides the CA root (DER bytes) that dongle_verify_genuine/1 checks against. Applications do not need this: the library embeds the KeyNub production root.
 dongle_last_error(+Dongle, -Detail) is det
Diagnostic detail for the most recent failure on this dongle, as a string; may be empty.
 session_open(+Dongle) is det
Opens an authenticated session; records, counters and app encryption need one.
 session_close(+Dongle) is det
Closes the session.
 with_session(+Dongle, :Goal) is semidet
Opens a session, calls Goal as once/1 and closes the session on every exit path, exceptions included.
 authorize_write(+Dongle, +Key) is det
Elevates the session to the write role with a write-auth key (P-256 PKCS#8 DER bytes).
 rotate_write_key(+Dongle, +Key) is det
Replaces the dongle's write-auth key with Key (P-256 PKCS#8 DER bytes). Call authorize_write/2 first. From the next session on, only the new key elevates.
 dongle_records(+Dongle, -Records) is det
The records on the dongle, as a list of record(Name, Size).
 read_record(+Dongle, +Name, -Bytes) is det
The content of a record, as a list of codes 0..255.
 write_record(+Dongle, +Name, +Bytes) is det
Writes a record, replacing one of the same name. Needs the write role.
 erase_record(+Dongle, +Name) is det
Erases the one record Name. Needs the write role.
 erase_all_records(+Dongle) is det
Erases every record. Needs the write role.
 read_counter(+Dongle, +CounterId, -Value) is det
The value of a hardware monotonic counter.
 increment_counter(+Dongle, +CounterId, -Value) is det
Increments a counter and returns the new value. Needs the write role.
 app_encrypt(+Dongle, +Scope, +Plaintext, -Sealed) is det
Seals Plaintext so that only a dongle can open it: this one (Scope device) or any dongle issued by the same developer (Scope developer). Sealed is a list of codes 0..255.
 app_decrypt(+Dongle, +Sealed, -Plaintext) is det
Opens data sealed with app_encrypt/4. Plaintext is a list of codes 0..255.

Undocumented predicates

The following predicates are exported, but not or incorrectly documented.

 dongle_open(Arg1, Arg2)
 with_dongle(Arg1, Arg2, Arg3)
 dongle_verify_genuine(Arg1, Arg2, Arg3)