QNX Cryptography Library

QNX SDP8.0QNX OS System Security GuideAPIConfiguration

The QNX cryptography library (qcrypto library) is a generic cryptographic shim layer that provides a consistent API to the various cryptographic primitives offered by third-party libraries.

The library's unified API provides a configurable plugin system that allows a system integrator to choose a cryptography provider without re-writing software. It is designed to maximize interoperability between library implementations by providing configuration parameters that allow systems to switch to the cryptographic backend of their choice.

The qcrypto library also enforces a certain level of security by following best practices where possible to ensure that users of the library use appropriate security parameters and key lengths. The sources for security best practices include the following information:

Using qcrypto

The following components are needed to run qcrypto on a system:

  • libqcrypto.so.1
  • a system configuration file that allows the system integrator to configure which cryptography providers the system uses (see Configuration file)
  • one of the qcrypto plugin binaries listed below

Features that use qcrypto

  • QNX Trusted Disk (see the entry for fs-qtd.so in the Utilities Reference)
  • Power-Safe filesystem (see the entry for fs-qnx6.so in the Utilities Reference)
  • random (see the entry for random in the Utilities Reference)

Dynamically loading the qcrypto library

If you need to support dynamically loading the cryptography library at runtime instead of linking to it directly, link your binary with libqcrypto_dyn.so and call qcrypto_load() to safely load the library before calling the other APIs. (The qcrypto_unload() function unloads it.) This dynamic shim layer is transparent and the API calls are identical in both libraries.

Supported algorithms

The qcrypto library framework allows you to add newer algorithms to a system using plugins. The algorithms that each plugin supports depends entirely on which algorithms the third-party cryptography library supports. In some cases, to encourage users to avoid using insecure primitives, qcrypto has purposefully avoided adding support for algorithms that are considered obsolete and unsafe. Some other algorithms require careful consideration when you define certain values, such as the initialization vector in many AES modes.

Algorithm naming

The qcrypto library tries to use uniform and unambiguous naming for algorithms. All algorithm names are lowercase ASCII strings and, where possible, the common naming used by RFCs. For example:
  • AES 128 CBC Cipher — aes-128-cbc
  • SHA512 Digest — sha512
  • RSA with SHA256 digest — rsa-with-sha256

Plugins

The qcrypto library uses plugins to interface with different cryptographic providers. Currently, the library provides the following plugins. See the documentation for each plugin for details:Plugins are provided by libraries that use the following naming format:
qcrypto-plugin.so

For example, qcrypto-openssl-3.so and qcrypto-certicom.so.

The qcrypto library allows you to create custom plugins. For more information, see Adding cryptographic primitives.

Supported cryptographic primitives

The qcrypto library APIs include functions for working with the following cryptographic primitives:

Initialization

You need to initialize the library before you can successfully call any other algorithm functions. Use qcrypto_init() to initialize the qcrypto library and qcrypto_uninit() to un-initialize it.

Using algorithms

After the library is initialized, the following steps are the usual work flow for using cryptographic primitives:
  1. Use a qcrypto_*_request() function to get an instance of the desired algorithm (e.g., qcrypto_cipher_request()).
  2. Manipulate the primitive using the qcrypto functions defined for it.
  3. Call qcrypto_release_ctx() when you no longer need the algorithm.
The same work flow applies to handling cryptographic keys, whether you are generating them for the first time or loading them from memory or files. See the section that discusses each of the various supported cryptographic primitives for examples of how to use them.

Reusing an algorithm instance

An instance of an algorithm (a context) can be reused if the caller reinitializes it using its initialization function. Reinitializing allows you to reuse an instance without clearing memory all the time and may improve performance.

Requesting an algorithm

When you call qcrypto_*_request(), the function searches for the specified algorithm.
  • If a tag value is specified, it searches plugins in the order they are defined (first the plugin with the internal tag value that qcrypto_init() creates, then plugins in the configuration file) for a matching tag value (wildcard tags (*) match anything).
  • If a tag value is not provided (tag = NULL), it searches plugins in the order they are defined using the tag value __progname (see the __progname entry in the C Library Reference).
If a matching tag isn't found or the algorithm is not found in a matching plugin, the algorithm resolution fails.

For more information on how tags work with requests, see Tags in the Configuration file section.

Error handling and logging

Use qcrypto_strerror() to retrieve the textual representation of qcrypto library error codes.

By default, logging prints errors and other conditions to slogger2 and is handled by QNX helper logging functionality (libqh). For additional logging options, see the QNX Helpers Developer's Guide.

Error codes

For the error codes that the qcrypto library uses and returns, see QNX cryptography library error codes.

General functions

The qcrypto library provides the following general-purpose and cryptography-related functions:

Selecting the buffer size

The qcrypto_*_final() functions (e.g., qcrypto_cipher_final()) take pointers to a buffer for a value and its size. When buffer is NULL, the function returns the size of the data it wants to write in size and allows the caller to allocate a buffer large enough for the data. This type of call is useful for data like key values, which can vary widely in size, unlike digests, which have known, fixed lengths.

Page updated: