pyqcc’s documentation!

Indices and tables

Device class reference

class pyqcc.cmdctrl.device(interface: str, device_name: str)

Bases: object

QRNG Cmd&Ctrl Device class

This is the class that implements the Cmd&Ctrl protocol for Crypta Labs QRNG devices. Provides the functions to execute device commands.

Parameters:
  • interface (str) – communication interface to use ("serial", "tcp" or "tcpudp")

  • device_name (str) – Device URI (e.g "COM3" or "/dev/ttyUSB0" for serial devices, IP address for tcp/udp for network connected devices)

Raises:

IOError – Unknown interface.

close_comm()

Close the communication interface with the device

command(cmd_code: int, payload=None) bool | bytes | None

Generic command function.

Parameters:
  • cmd_code (int) – Command code.

  • payload (bytes, optional) – Command payload.

Returns:

True if success but the response payload is empty. Response payload bytes if success and response payload present. None if failure.

Return type:

True | dict | None

Raises:
  • ValueError – Command code not valid.

  • RuntimeError – Unexpected byte received from the device.

get_info() dict | None

Read the QRNG device information.

Returns:

If success, it returns a dictionary containing the device info fields (strings):
  • core_version : QRNG core version (int).

  • sw_version : device firmware version (int).

  • serial : serial number (str).

  • hw_info : QRNG device hardware information (str).

If failure, returns None.

Return type:

dict | None

get_statistics() dict | None

Read the QRNG device statistics (since last reset).

Returns:

If success, returns a dictionary containing the statistics fields:
  • generated_bytes : number of random bytes generated.

  • repetition_count_failures : how many times the repetition count health test had failed.

  • adaptive_proportion_failures : how many times the adaptive proportion health test had failed.

  • bitcount_failures : how many times the bitcount health test had failed.

  • speed : QRNG generation speed (bit/s)

  • sensif_average : current QOM output average.

  • ledctrl_level : current light source level (percent).

If failure, returns None.

Return type:

dict | None

get_status() dict | None

Read the QRNG device status.

Returns:

If success, it returns a dictionary containing the status fields:
  • started : QRNG processing started, should be 1 if the QRNG device is operating

  • startup_test_in_progress : startup test not completed

  • voltage_low : QRNG light source auto-calibration failure, the QOM output voltage is too low

  • voltage_high : QRNG light source auto-calibration failure, the QOM output voltage is too high

  • voltage_undefined : The QOM output voltage keeps oscillating beyond auto-calibration control.

  • bitcount : Bit count health test failure present, this is a Crypta Labs custom test on the random data, it checks that the proportion between 1s and 0s in the random data doesn’t exceed a certain threshold

  • repetition_count : Repetition count health test failure present (see NIST SP 800-90B).

  • adaptive_proportion : Adaptive proportion health test failure present (see NIST SP 800-90B).

  • ready_bytes : Number of bytes ready to read.

If failure, returns None.

Return type:

dict | None

read_continuous(length: int) bytes | None

Read data from the QRNG device when the continuous mode is active.

Before calling this function the device must be in continuous mode, see start_continuous()

Parameters:

length (int) – How many bytes to read from the QRNG device. There is no limit to the number of bytes requested as the QRNG device is continuously sending random data.

Returns:

Returns the random bytes received from the device. None if failure.

Return type:

bytes | None

read_signed(length: int) dict | None

Execute one shot signed reading of random data

The asymmetric key used to sign (and verify) the data is different for each specific QRNG device implementations. Check the QRNG device documentation for information on how to extract the public key from the device and check the signature.

Note

Not all the QRNG devices implement the signed read command. Current supported devices: QCicada, FW 5.13 and greater.

Parameters:

length (int) – How many bytes to read from the QRNG device. Like the standard one shot read, the maximum allowed length is the current available bytes on the device, use get_status() method to check how many bytes are available.

Returns:

If success, return a dictionary containing two items:
  • qrnd: random bytes received from the device.

  • signature: bytes containing the raw signature.

Return None if failure.

Return type:

dict | None

start_continuous() bool | None

Start continuous mode.

When this command is issued, the QRNG device starts sending random data on the QRND channel. Then the caller can read the random data using read_continuous() method.

Returns:

True if success, None if failure.

Return type:

True | None

start_one_shot(length: int) bytes | None

Execute one shot reading.

Parameters:

length (int) – how many bytes to read from the QRNG device, the maximum allowed length is the current available bytes on the device, use get_status() to check how many bytes are available.

Returns:

Return an array of size length containing the random data received from the device if success. None if failure.

Return type:

bytes | None

stop() bool | None

Stop continuous mode.

It fails if the continuous mode was not previously started.

Returns:

True if success. None if failure.

Return type:

True | None

update_chunk(data) dict | None

Send firmware image chunk

This function must be called several times after update_init() to send the actual firmware. The caller can check the returned update_status and remaining fields to check the status of the update. Each chunk is maximum UPDATE_MAX_CHUNK bytes. When the update_status field of the returned dictionary is UPDATE_STS_TRANSFER_IN_PROGRESS it means that the device is expecting to receive the remaining part of the firmware and the remaining field indicates how many bytes are left to be transferred. When the firmware is completely transferred the status is UPDATE_STS_TRANSFER_COMPLETED, that means the FW update procedure is complete.

Parameters:

data (bytes) – Firmware image chunk bytes

Returns:

If success, it returns a dictionary containing the update status fields
  • update_status : status of the update

  • remaining : How many bytes left to transfer.

If failure, returns None.

Return type:

dict | None

update_init(image_size) dict | None

Initialize firmware update

Parameters:

image_size (int) – Size of the firmware image (in bytes).

Returns:

If success, it returns a dictionary containing the update status fields:
  • update_status : status of the update, if the update procedure can start it should be UPDATE_STS_READY.

  • remaining : How many bytes left to transfer, this should be the image size.

If failure, returns None.

Return type:

dict | None

Usage examples

In the examples we are using a serial device on COM3, initialized as qccdev and used in the following examples.

Initialize the device

import pyqcc

qccdev = pyqcc.cmdctrl.device("serial","COM3")

Read device info

info = qccdev.get_info()
if(info):
   print("Device info read successful")
   print(" Core version: {}.{}".format(info['core_version'] >> 16, info['core_version'] & 0xffff) )
   print(" SW version: {}.{}".format(info['sw_version'] >> 16, info['sw_version'] & 0xffff) )
   print(" Serial: {}".format(info['serial'].decode("utf-8")))
   print(" HW info: {}".format(info['hw_info'].decode("utf-8")))
else:
   print("Error reading info")

Read device status

status = qccdev.get_status()
if(status):
   print("Device status read successful")
   print(" started: {}".format(status['started']) )
   print(" startup_test_in_progress: {}".format(status['startup_test_in_progress']) )
   print(" voltage_low: {}".format(status['voltage_low']) )
   print(" voltage_high: {}".format(status['voltage_high']) )
   print(" voltage_undefined: {}".format(status['voltage_undefined']) )
   print(" bitcount: {}".format(status['bitcount']) )
   print(" repetition_count: {}".format(status['repetition_count']) )
   print(" adaptive_proportion: {}".format(status['adaptive_proportion']) )
   print(" Ready bytes: {}".format(status['ready_bytes']) )
else:
   print("Error reading status")

Read random bytes in one shot mode

# Read 64 bytes
rnd_bytes = qccdev.start_one_shot(64)
if(rnd_bytes):
   #Print random bytes in hexadecimal format
   print(rnd_bytes.hex())
else:
   print("Error reading random bytes")

Read random bytes in continuous mode

if(qccdev.start_continuous()):
   print("Continuous mode started!")
   # Read 1MB random data
   rnd_bytes = qccdev.read_continuous(1000000)
   if(rnd_bytes):
      #print first and last random bytes
      print("Continuous read success! {:02X}..{:02X}".format(rnd_bytes[0], rnd_bytes[-1]))
   else:
      print("Error continuous read")
   # Stop continuous mode
   if(qccdev.stop()):
      print("Continuous mode Stopped!")
   else:
      print("Stop error!")
else:
   print("Error starting continuous mode")

Command Line Interface

pyqcc-cli is the command line tool (installed with the package) that allows the user to utilise the QRNG device in a simple and intuitive way. See below for the detailed help of the command:

usage: pyqcc-cli [-h] [-i {serial,udp,tcp,tcpudp}] [-d DEVICE] [-s] [-g] [-t] [-r READ_SIZE] [-R SIGNED_READ_SIZE] [-o OUTPUT_FILE] [-a] [--start]
               [--read-block-size READ_BLOCK_SIZE] [--stop] [--info] [--update UPDATE_FILE] [-v]

QRNG Command and Control protocol host utility

optional arguments:
-h, --help            show this help message and exit
-i {serial,udp,tcp,tcpudp}, --interface {serial,udp,tcp,tcpudp}
                        Communication interface (default: serial
-d DEVICE, --device DEVICE
                        Device interface name or IP (default: /dev/ttyACM0)
-s, --get-status      Get current QRNG configuration
-g, --get-config      Get current QRNG configuration
-t, --get-statistics  Get QRNG statistics
-r READ_SIZE, --read READ_SIZE
                        One shot read
-R SIGNED_READ_SIZE, --signed-read SIGNED_READ_SIZE
                        Signed read
-o OUTPUT_FILE, --output-file OUTPUT_FILE
                        Output file (used with -r, --read)
-a, --append          Append to output file (used with -o, --output-file)
--start               Start continuous mode, if -r is used: read in continuous mode
--read-block-size READ_BLOCK_SIZE
                        Read block size, how many bytes read for every cycle (continuous mode only)
--stop                Stop continuous mode
--info                Get device information
--update UPDATE_FILE  FW update, image file
-v, --verbose         Print debug information