BoringSSL Provider

SDK-BSSL-001 v1.0.0 BoringSSL Latest

The Dyber BoringSSL integration provides hardware-accelerated post-quantum cryptography for the millions of applications built on BoringSSL — including Chromium, Android, gRPC, and major cloud-native infrastructure. Unlike OpenSSL's provider model, BoringSSL uses direct API integration, giving you explicit control over PQC operations with the full performance of the QUAC 100 accelerator.

Overview #

BoringSSL is Google's fork of OpenSSL, used as the TLS library for Chromium, Android, CloudFlare's infrastructure, and gRPC. It deliberately removes OpenSSL's provider/engine interfaces in favor of a streamlined, opinionated API surface. The Dyber BoringSSL integration provides a native C library (libquac100_boringssl) that implements ML-KEM, ML-DSA, and QRNG operations through direct function calls and optional EVP method registration, delivering QUAC 100 hardware acceleration without requiring BoringSSL source modifications for most use cases.

FeatureDescription
Library Namelibquac100_boringssl.so / quac100_boringssl.dll
Headerquac100_boringssl.h
BoringSSL VersionLatest (from boringssl.googlesource.com)
ML-KEM SupportML-KEM-512, ML-KEM-768, ML-KEM-1024 (FIPS 203)
ML-DSA SupportML-DSA-44, ML-DSA-65, ML-DSA-87 (FIPS 204)
QRNGHardware quantum random — 500 Mbps conditioned throughput
TLS Hybrid GroupsX25519_ML-KEM-768, P-384_ML-KEM-1024, X25519_ML-KEM-512
ASN.1 EncodingDER/PEM via BoringSSL CBS/CBB primitives
Hardware Acceleration1.4M+ ops/sec with QUAC 100 PCIe card
Software FallbackAutomatic software simulation when hardware unavailable
Build SystemCMake 3.16+, GN (Chromium), Make
C StandardC11 (GCC 9+, Clang 10+, MSVC 2019+)
When to use BoringSSL vs OpenSSL integration: If your application links against BoringSSL (Chromium, Android NDK, gRPC, Envoy, Cloudflare products), use this integration. If your application uses OpenSSL 3.x (NGINX, Apache, curl, most Linux server software), use the OpenSSL Provider instead.

Architecture & Integration Model #

The BoringSSL integration is a shared library that sits alongside BoringSSL, providing PQC functions through a clean C API. Applications call QUAC functions directly for post-quantum operations while continuing to use BoringSSL for classical cryptography. The library automatically detects and uses QUAC 100 hardware when available, falling back to software simulation for development and testing.

Source FilePurpose
quac100_boringssl.hPublic header — all API declarations, constants, key sizes, error codes
quac100_boringssl.cCore initialization, hardware detection, secure memory, self-test, benchmarks
quac100_kem.cML-KEM implementation — keygen, encapsulate, decapsulate for all parameter sets
quac100_sig.cML-DSA implementation — keygen, sign, verify, plus prehash variants (HashML-DSA)
quac100_rand.cQRNG integration — buffered/unbuffered random, health monitoring, entropy seeding
quac100_evp.cEVP_PKEY integration layer — wraps PQC keys in BoringSSL's EVP interface
quac100_tls.cTLS 1.3 hybrid key exchange — X25519+ML-KEM, P-384+ML-KEM group negotiation
quac100_asn1.cASN.1/DER/PEM encoding using BoringSSL's CBS/CBB (SubjectPublicKeyInfo, PKCS#8)
quac100_engine.cLegacy ENGINE shim for older BoringSSL builds that still support ENGINE API
┌─────────────────────────────────────────────────────────────┐
│  Application  (Chromium, gRPC, Envoy, custom app)          │
├─────────────┬───────────────────────┬───────────────────────┤
│  BoringSSL  │  libquac100_boringssl  │  QUAC EVP Methods     │
│  (classical)│  (PQC direct API)      │  (optional wrappers)  │
├─────────────┴───────────────────────┴───────────────────────┤
│  QUAC 100 SDK  (libquac100 — PCIe driver interface)        │
├─────────────────────────────────────────────────────────────┤
│  QUAC 100 Hardware  (PCIe Gen4 x16 Accelerator)            │
└─────────────────────────────────────────────────────────────┘

BoringSSL vs OpenSSL Integration #

BoringSSL and OpenSSL have fundamentally different extensibility models. Understanding the difference is critical for choosing the right integration path.

FeatureOpenSSL 3.x ProviderBoringSSL Integration
Integration ModelDynamic provider (loaded at runtime)Direct API (linked at compile time)
EVP SupportFull EVP_PKEY with automatic dispatchLimited EVP wrapper; prefer direct calls
Algorithm RegistrationAutomatic via provider queryManual — call QUAC_EVP_register()
TLS GroupsProvider-registered groupsRequires BoringSSL source patches for full TLS
Configurationopenssl.cnf directivesCompile-time flags + runtime QUAC_init()
Drop-in ReplacementYes — zero code changesPartial — direct calls for PQC, transparent for classical
Chromium CompatibleNoYes
Android CompatibleNo (Android uses BoringSSL)Yes
gRPC CompatibleNo (gRPC uses BoringSSL)Yes

Building & Installation #

Prerequisites

RequirementVersionNotes
BoringSSLLatestClone from boringssl.googlesource.com/boringssl
CMake3.16+Build system generator
C CompilerGCC 9+, Clang 10+, MSVC 2019+C11 standard required
QUAC 100 SDK1.0+Optional — enables hardware acceleration
Go1.18+Required by BoringSSL's build for peg

Build from Source

# Clone BoringSSL (if not already available)
$ git clone https://boringssl.googlesource.com/boringssl
$ cd boringssl && mkdir build && cd build
$ cmake .. && make -j$(nproc)
$ cd ../..

# Build QUAC BoringSSL integration
$ cd quantacore-sdk/integrations/boringssl
$ mkdir build && cd build

# Without hardware (software-only)
$ cmake .. -DBORINGSSL_ROOT=/path/to/boringssl
$ make -j$(nproc)

# With QUAC 100 hardware acceleration
$ cmake .. \
    -DBORINGSSL_ROOT=/path/to/boringssl \
    -DQUAC_SDK_PATH=/opt/quantacore-sdk
$ make -j$(nproc)

# Install
$ sudo make install

GN Build (Chromium Integration)

For Chromium or other GN-based projects, a BUILD.gn file is provided:

# In your GN project, add to deps:
deps += [ "//third_party/quac100_boringssl" ]

# Copy integration files to third_party/quac100_boringssl/
$ cp quantacore-sdk/integrations/boringssl/* \
     chromium/src/third_party/quac100_boringssl/

Verify Installation

# Check library
$ ls /usr/local/lib/libquac100_boringssl.so
$ ls /usr/local/include/quac100_boringssl.h

# Verify with pkg-config
$ pkg-config --libs quac100-boringssl
-lquac100_boringssl -lssl -lcrypto -lpthread

Initialization & Configuration #

All QUAC functions require initialization before use. The library automatically detects QUAC 100 hardware via PCIe enumeration and falls back to software simulation if unavailable.

#include "quac100_boringssl.h"

int main(void) {
    /* Basic init — auto-detect hardware, fallback to software */
    int ret = QUAC_init();
    if (ret != QUAC_SUCCESS) {
        fprintf(stderr, "Init failed: %s\n", QUAC_get_error_string(ret));
        return 1;
    }

    /* Check hardware status */
    if (QUAC_is_hardware_available()) {
        printf("QUAC 100 hardware acceleration: ENABLED\n");
    } else {
        printf("Running in software simulation mode\n");
    }

    printf("Library version: %s\n", QUAC_version_string());

    /* ... use QUAC functions ... */

    QUAC_cleanup();
    return 0;
}

Extended Initialization

/* Require hardware — fail if not available */
ret = QUAC_init_ex(
    1,  /* use_hardware: 1 = require, 0 = allow fallback */
    0   /* device_index: 0 = first QUAC device         */
);

/* Multi-device: target second QUAC 100 card */
ret = QUAC_init_ex(1, 1);  /* device_index = 1 */

ML-KEM Key Encapsulation #

ML-KEM (Module-Lattice Key Encapsulation Mechanism, FIPS 203) is the primary key exchange primitive for post-quantum TLS. The BoringSSL integration supports all three parameter sets with both hardware-accelerated and software paths.

Key Sizes

Parameter SetSecurity LevelPublic KeySecret KeyCiphertextShared Secret
ML-KEM-512NIST Level 1800 B1,632 B768 B32 B
ML-KEM-768NIST Level 31,184 B2,400 B1,088 B32 B
ML-KEM-1024NIST Level 51,568 B3,168 B1,568 B32 B

Complete KEM Example

#include "quac100_boringssl.h"

/* Allocate buffers using compile-time constants */
uint8_t pk[QUAC_ML_KEM_768_PUBLIC_KEY_BYTES];   /* 1184 bytes */
uint8_t sk[QUAC_ML_KEM_768_SECRET_KEY_BYTES];   /* 2400 bytes */
uint8_t ct[QUAC_ML_KEM_768_CIPHERTEXT_BYTES];   /* 1088 bytes */
uint8_t ss_sender[32], ss_receiver[32];

/* Generate keypair (receiver side) */
int ret = QUAC_KEM_keypair(QUAC_KEM_ML_KEM_768, pk, sk);
assert(ret == QUAC_SUCCESS);

/* Encapsulate (sender side — produces ciphertext + shared secret) */
ret = QUAC_KEM_encaps(QUAC_KEM_ML_KEM_768, ct, ss_sender, pk);
assert(ret == QUAC_SUCCESS);

/* Decapsulate (receiver side — recovers shared secret from ciphertext) */
ret = QUAC_KEM_decaps(QUAC_KEM_ML_KEM_768, ss_receiver, ct, sk);
assert(ret == QUAC_SUCCESS);

/* ss_sender == ss_receiver  (32-byte shared secret) */
assert(memcmp(ss_sender, ss_receiver, 32) == 0);

Dynamic Size Queries

/* Query sizes at runtime for algorithm-agnostic code */
size_t pk_len = QUAC_KEM_public_key_bytes(QUAC_KEM_ML_KEM_768);   /* 1184 */
size_t sk_len = QUAC_KEM_secret_key_bytes(QUAC_KEM_ML_KEM_768);   /* 2400 */
size_t ct_len = QUAC_KEM_ciphertext_bytes(QUAC_KEM_ML_KEM_768);   /* 1088 */
size_t ss_len = QUAC_KEM_shared_secret_bytes(QUAC_KEM_ML_KEM_768); /*   32 */

ML-DSA Digital Signatures #

ML-DSA (Module-Lattice Digital Signature Algorithm, FIPS 204) provides quantum-resistant digital signatures for certificate authentication, code signing, and document integrity verification.

Key & Signature Sizes

Parameter SetSecurity LevelPublic KeySecret KeySignature
ML-DSA-44NIST Level 21,312 B2,560 B2,420 B
ML-DSA-65NIST Level 31,952 B4,032 B3,309 B
ML-DSA-87NIST Level 52,592 B4,896 B4,627 B

Sign & Verify Example

uint8_t pk[QUAC_ML_DSA_65_PUBLIC_KEY_BYTES];  /* 1952 bytes */
uint8_t sk[QUAC_ML_DSA_65_SECRET_KEY_BYTES];  /* 4032 bytes */
uint8_t sig[QUAC_ML_DSA_65_SIGNATURE_BYTES];  /* 3309 bytes */
size_t  sig_len;

/* Generate signing keypair */
int ret = QUAC_SIG_keypair(QUAC_SIG_ML_DSA_65, pk, sk);

/* Sign a message */
const uint8_t *msg = (uint8_t *)"Post-quantum signatures with QUAC 100";
size_t msg_len = strlen((char *)msg);

ret = QUAC_sign(QUAC_SIG_ML_DSA_65, sig, &sig_len, msg, msg_len, sk);
assert(ret == QUAC_SUCCESS);

/* Verify signature */
ret = QUAC_verify(QUAC_SIG_ML_DSA_65, sig, sig_len, msg, msg_len, pk);
if (ret == QUAC_SUCCESS) {
    printf("Signature valid ✓\n");
} else if (ret == QUAC_ERROR_VERIFICATION_FAILED) {
    printf("Signature invalid ✗\n");
}

/* Prehash variant (HashML-DSA) for large messages */
ret = QUAC_sign_prehash(QUAC_SIG_ML_DSA_65, sig, &sig_len, hash, hash_len, sk);
ret = QUAC_verify_prehash(QUAC_SIG_ML_DSA_65, sig, sig_len, hash, hash_len, pk);

QRNG Random Generation #

The QUAC 100 includes a hardware quantum random number generator delivering 500 Mbps of conditioned true random data. The BoringSSL integration provides a buffered interface that seamlessly replaces BoringSSL's RAND_bytes() for applications requiring quantum entropy.

/* Generate random bytes (buffered, high-throughput) */
uint8_t random_data[64];
int ret = QUAC_random_bytes(random_data, sizeof(random_data));

/* Add application entropy (mix with hardware source) */
uint8_t app_seed[32] = { /* application-specific entropy */ };
QUAC_random_seed(app_seed, sizeof(app_seed));

/* Health monitoring */
if (!QUAC_random_health_check()) {
    fprintf(stderr, "WARNING: QRNG health degraded — check hardware\n");
}

/* High-throughput unbuffered (hardware-only, bypasses DRBG) */
uint8_t bulk[1024 * 1024];  /* 1 MB */
ret = QUAC_random_bytes_unbuffered(bulk, sizeof(bulk));

TLS 1.3 Hybrid Key Exchange #

Hybrid key exchange combines a classical algorithm (X25519 or ECDH P-384) with a post-quantum KEM (ML-KEM) in a single TLS 1.3 handshake. This provides security against both classical and quantum adversaries — if either component remains secure, the connection is safe.

Supported Hybrid Groups

GroupGroup IDClassicalPQCCombined PK SizeUse Case
X25519_ML-KEM-7680x6399X25519ML-KEM-7681,216 BRecommended default
P-384_ML-KEM-10240x639AECDH P-384ML-KEM-10241,665 BHigh-security government
X25519_ML-KEM-5120x639BX25519ML-KEM-512832 BBandwidth-constrained

Hybrid Key Exchange API

/* Create hybrid context */
QUAC_HYBRID_CTX *ctx = QUAC_hybrid_ctx_new(QUAC_GROUP_X25519_ML_KEM_768);

/* Generate our keypair (classical + PQC combined) */
int ret = QUAC_hybrid_generate_keypair(ctx);

/* Export our public key to send to peer */
uint8_t my_public[2048];
size_t my_public_len = sizeof(my_public);
ret = QUAC_hybrid_get_public_key(ctx, my_public, &my_public_len);
/* my_public_len == 1216 for X25519_ML-KEM-768 */

/* Set peer's public key (received from TLS handshake) */
ret = QUAC_hybrid_set_peer_public_key(ctx, peer_public, peer_public_len);

/* Derive shared secret */
uint8_t shared_secret[64];
size_t ss_len = sizeof(shared_secret);
ret = QUAC_hybrid_derive(ctx, shared_secret, &ss_len);
/* ss_len == 64  (32 from X25519 + 32 from ML-KEM-768) */

/* Cleanup — secure zeroization of all key material */
QUAC_hybrid_ctx_free(ctx);

TLS Group Registration

/* Register hybrid groups for use in TLS handshakes */
QUAC_TLS_register_groups();

/* Query supported groups */
quac_tls_group_t groups[8];
size_t count = 8;
QUAC_TLS_get_groups(groups, &count);

/* Check individual group support */
if (QUAC_TLS_group_is_supported(QUAC_GROUP_X25519_ML_KEM_768)) {
    printf("X25519_ML-KEM-768 available\n");
}

EVP Integration Layer #

For applications that prefer BoringSSL's EVP_PKEY interface, optional EVP wrappers let you create PQC keys as EVP objects. This enables interoperability with existing key management code that expects EVP_PKEY* handles.

/* Register QUAC algorithms with BoringSSL EVP system */
QUAC_EVP_register();

/* Create EVP_PKEY from ML-KEM keys */
EVP_PKEY *kem_key = QUAC_EVP_PKEY_new_kem(QUAC_KEM_ML_KEM_768, pk, sk);

/* Create EVP_PKEY from ML-DSA keys */
EVP_PKEY *sig_key = QUAC_EVP_PKEY_new_sig(QUAC_SIG_ML_DSA_65, pk, sk);

/* Extract raw keys back from EVP_PKEY */
uint8_t raw_pk[QUAC_KEM_MAX_PUBLIC_KEY_BYTES];
uint8_t raw_sk[QUAC_KEM_MAX_SECRET_KEY_BYTES];
size_t pk_len, sk_len;
QUAC_EVP_PKEY_get_raw_keys(kem_key, raw_pk, &pk_len, raw_sk, &sk_len);

/* Use with existing EVP-based code */
EVP_PKEY_free(kem_key);
EVP_PKEY_free(sig_key);

ASN.1 Key Encoding #

Serialize PQC keys to standard DER and PEM formats for storage, transmission, and interoperability. Uses BoringSSL's native CBS/CBB primitives for encoding efficiency.

/* Encode public key to DER (SubjectPublicKeyInfo) */
uint8_t der[2048];
size_t der_len = sizeof(der);
ret = QUAC_encode_public_key_der(QUAC_KEM_ML_KEM_768, pk, pk_len, der, &der_len);

/* Decode public key from DER */
int alg;
uint8_t decoded_pk[QUAC_KEM_MAX_PUBLIC_KEY_BYTES];
size_t decoded_len = sizeof(decoded_pk);
ret = QUAC_decode_public_key_der(der, der_len, &alg, decoded_pk, &decoded_len);

/* Encode to PEM for human-readable output */
char pem[4096];
size_t pem_len = sizeof(pem);
ret = QUAC_encode_public_key_pem(QUAC_KEM_ML_KEM_768, pk, pk_len, pem, &pem_len);
/* Output: -----BEGIN ML-KEM PUBLIC KEY-----\n<base64>\n-----END ML-KEM PUBLIC KEY----- */

/* Private keys (PKCS#8 format) */
ret = QUAC_encode_private_key_der(QUAC_SIG_ML_DSA_65, sk, sk_len, der, &der_len);
ret = QUAC_encode_private_key_pem(QUAC_SIG_ML_DSA_65, sk, sk_len, pem, &pem_len);

Integration Patterns #

Pattern 1: Direct API (Simplest)

Call QUAC functions directly alongside BoringSSL — the simplest and most performant approach:

#include "quac100_boringssl.h"

int main() {
    QUAC_init();

    /* PQC operations via QUAC */
    uint8_t pk[QUAC_ML_KEM_768_PUBLIC_KEY_BYTES];
    uint8_t sk[QUAC_ML_KEM_768_SECRET_KEY_BYTES];
    QUAC_KEM_keypair(QUAC_KEM_ML_KEM_768, pk, sk);

    /* Classical operations via BoringSSL */
    uint8_t aes_key[32];
    RAND_bytes(aes_key, sizeof(aes_key));

    QUAC_cleanup();
}

Pattern 2: Unified Wrapper

Create a wrapper that routes operations to QUAC (PQC) or BoringSSL (classical) based on algorithm type:

/* my_crypto.h — unified interface */
typedef struct {
    int type;  /* 0=classical, 1=PQC */
    union {
        EVP_PKEY *classical;
        struct { int alg; uint8_t *pk; uint8_t *sk; } pqc;
    };
} MY_KEYPAIR;

MY_KEYPAIR *my_generate_keypair(const char *algorithm);
int         my_sign(MY_KEYPAIR *key, const uint8_t *msg, ...);
int         my_verify(MY_KEYPAIR *key, const uint8_t *msg, ...);

Pattern 3: Modified BoringSSL Build

For fully transparent PQC, patch BoringSSL source to call QUAC functions internally. Key files to modify:

FileModification
crypto/evp/evp.cAdd ML-KEM/ML-DSA to EVP_PKEY types
ssl/ssl_key_share.ccAdd hybrid group key share implementations
ssl/internal.hDefine SSL_GROUP_X25519_MLKEM768 constants
include/openssl/nid.hAdd NIDs for PQC algorithms

NGINX & Envoy Proxy #

For TLS termination proxies that use BoringSSL, the QUAC integration enables PQC key exchange at the edge:

Envoy Proxy (BoringSSL-based)

// Envoy filter — quac100_envoy_filter.cc
static int pqc_ssl_ctx_setup(SSL_CTX *ctx) {
    /* Initialize QUAC */
    QUAC_init();
    QUAC_TLS_register_groups();

    /* Configure hybrid groups — PQC preferred, classical fallback */
    SSL_CTX_set1_groups_list(ctx, "X25519_MLKEM768:X25519:P-256");

    return 1;
}

NGINX with BoringSSL

# Build NGINX against BoringSSL with QUAC integration
$ ./configure \
    --with-openssl=/path/to/boringssl \
    --with-cc-opt="-I/usr/local/include" \
    --with-ld-opt="-L/usr/local/lib -lquac100_boringssl"

# nginx.conf — enable PQC groups
ssl_ecdh_curve X25519_MLKEM768:X25519:P-256;
ssl_protocols TLSv1.3;

Chromium & gRPC #

BoringSSL is the TLS library for both Chromium and gRPC. The QUAC integration enables PQC for these critical infrastructure components.

Chromium Integration

// third_party/quac100_boringssl/BUILD.gn
static_library("quac100_boringssl") {
  sources = [
    "quac100_boringssl.c",
    "quac100_kem.c",
    "quac100_sig.c",
    "quac100_rand.c",
    "quac100_evp.c",
    "quac100_tls.c",
    "quac100_asn1.c",
  ]
  deps = [ "//third_party/boringssl" ]
}

gRPC Channel with PQC

// gRPC C++ — configure PQC channel credentials
#include <grpcpp/grpcpp.h>
#include "quac100_boringssl.h"

auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());

// Enable PQC on the underlying SSL_CTX
grpc::experimental::SetSslRootCertRequestType(
    grpc::experimental::GRPC_SSL_CERTIFICATE_REQUEST_TYPE);

// QUAC groups are registered automatically via QUAC_init()
auto channel = grpc::CreateChannel("server:443", channel_creds);

PQC TLS Client Example #

A complete PQC TLS client demonstrating hybrid key exchange with ML-KEM and ML-DSA certificate verification. Source: examples/pqc_client.c

/* Build and run the PQC TLS client */
$ cd quantacore-sdk/integrations/boringssl/build
$ make pqc_client

/* Connect to a PQC-enabled server */
$ ./pqc_client -h example.com -p 443 -v
QUAC 100 PQC TLS Client v1.0.0
Connecting to example.com:443/
Hardware acceleration: ENABLED
TCP connected.
Performing TLS handshake...

Connection Information:
  TLS Version:  TLSv1.3
  Cipher:       TLS_AES_256_GCM_SHA384
  Key Exchange: X25519_ML-KEM-768 (hybrid)
  Session:      New

/* Skip cert verification for testing */
$ ./pqc_client -h localhost -p 8443 -k

Key client configuration in code:

/* Create SSL context for TLS 1.3 */
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);

/* Enable QUAC PQC support */
quac100_ssl_ctx_enable_pqc(ctx);

/* Set group preference: hybrid first, then classical fallback */
SSL_CTX_set1_groups_list(ctx,
    "X25519_MLKEM768:P256_MLKEM768:MLKEM768:X25519:P-256");

PQC TLS Server Example #

A PQC TLS server with auto-generated ML-DSA certificates. Source: examples/pqc_server.c

/* Build and run with auto-generated ML-DSA cert */
$ ./pqc_server -g -p 8443 -v
QUAC 100 PQC TLS Server v1.0.0
Hardware acceleration: ENABLED
Generating ML-DSA-65 certificate...
Certificate generated successfully.
Listening on port 8443
Test: curl -k https://localhost:8443

/* Run with existing PEM certificate */
$ ./pqc_server -c cert.pem -k key.pem -p 443

/* Use ML-DSA-87 (Level 5) for maximum security */
$ ./pqc_server -g -l 87 -p 8443

The server generates an ML-DSA self-signed certificate at startup, configures hybrid key exchange groups, and serves an HTML page showing the PQC connection details including the negotiated key exchange algorithm and cipher suite.

Algorithm Selection Guide #

ML-KEM — When to Use Each Variant

VariantSecurityBandwidthBest For
ML-KEM-512Level 1LowestIoT, embedded, bandwidth-constrained environments
ML-KEM-768Level 3MediumGeneral purpose — TLS, VPN, most server workloads
ML-KEM-1024Level 5HighestGovernment, military, long-term confidential data

ML-DSA — When to Use Each Variant

VariantSecuritySignature SizeBest For
ML-DSA-44Level 22,420 BHigh-volume verification, fast signature checks
ML-DSA-65Level 33,309 BBalanced — certificates, code signing, general auth
ML-DSA-87Level 54,627 BMaximum security — root certificates, long-lived keys

Performance Benchmarks #

Hardware-accelerated vs software performance for the BoringSSL integration:

AlgorithmOperationSoftware (ops/s)Hardware (ops/s)Speedup
ML-KEM-768Keygen~10,000~500,00050×
ML-KEM-768Encapsulate~15,000~700,00047×
ML-KEM-768Decapsulate~12,000~600,00050×
ML-DSA-65Sign~5,000~200,00040×
ML-DSA-65Verify~8,000~300,00038×
QRNGGenerate~50 MB/s~125 MB/s2.5×

Run Your Own Benchmarks

/* Programmatic benchmarking */
quac_benchmark_result_t results[10];
size_t result_count = 10;

int ret = QUAC_benchmark(QUAC_KEM_ML_KEM_768, 3, results, &result_count);

for (size_t i = 0; i < result_count; i++) {
    printf("%s %s: %.0f ops/sec (%.2f µs/op)\n",
           results[i].algorithm,
           results[i].operation,
           results[i].ops_per_second,
           results[i].microseconds_per_op);
}

/* Command-line benchmark tool */
$ ./bench_quac100_boringssl --algo ml-kem-768 --duration 5

FIPS Self-Test & Integrity #

For FIPS 140-3 compliance, the library includes Known Answer Tests (KAT) and module integrity verification:

/* Run all FIPS self-tests (KATs for ML-KEM and ML-DSA) */
int ret = QUAC_self_test();
if (ret != QUAC_SUCCESS) {
    fprintf(stderr, "FIPS self-test FAILED: %s\n", QUAC_get_error_string(ret));
    exit(1);
}
printf("FIPS self-test: PASSED ✓\n");

/* Verify module binary integrity (HMAC check) */
ret = QUAC_integrity_check();
if (ret != QUAC_SUCCESS) {
    fprintf(stderr, "Integrity check FAILED — library may be tampered\n");
    exit(1);
}
Production FIPS deployment: The self-test runs automatically on first call to QUAC_init() in FIPS mode. If any KAT fails, the library enters an error state and refuses all cryptographic operations until restarted.

Thread Safety #

All public API functions are thread-safe after QUAC_init() completes. Internal state is protected by pthread mutexes, and hardware operations are serialized through the QUAC 100 driver's DMA queue.

Function CategoryThread SafetyNotes
Initialization (QUAC_init)Call once from main threadProtected by mutex; safe to call multiple times (idempotent)
KEM operationsFully thread-safeConcurrent keygen/encaps/decaps from any thread
Signature operationsFully thread-safeConcurrent sign/verify from any thread
QRNGFully thread-safePer-thread buffering for maximum throughput
Hybrid TLS contextsPer-context thread safetyEach QUAC_HYBRID_CTX must be used by one thread at a time
Cleanup (QUAC_cleanup)Call once from main threadAfter all worker threads have finished

Error Handling #

All functions return integer status codes. Use QUAC_get_error_string() for human-readable messages:

CodeConstantDescription
0QUAC_SUCCESSOperation completed successfully
-1QUAC_ERROR_INVALID_ALGORITHMUnknown or unsupported algorithm identifier
-2QUAC_ERROR_INVALID_KEYNULL key pointer or malformed key data
-3QUAC_ERROR_INVALID_SIGNATURESignature format error (wrong length, all zeros)
-4QUAC_ERROR_INVALID_CIPHERTEXTCiphertext format error
-5QUAC_ERROR_BUFFER_TOO_SMALLOutput buffer too small for result
-6QUAC_ERROR_HARDWARE_UNAVAILABLEHardware required but not detected
-7QUAC_ERROR_INTERNALInternal library error (SDK mismatch, driver failure)
-8QUAC_ERROR_NOT_INITIALIZEDCalled before QUAC_init()
-9QUAC_ERROR_MEMORY_ALLOCATIONMemory allocation failed
-10QUAC_ERROR_VERIFICATION_FAILEDSignature verification failed (signature invalid)

Troubleshooting #

Hardware Not Detected

$ lspci | grep QUAC          # Check PCIe device present
$ lsmod | grep quac100       # Check kernel driver loaded
$ ls -la /dev/quac*          # Check device permissions
$ pkg-config --exists quac100 # Check SDK installation

Initialization Failures

ErrorCauseSolution
HARDWARE_UNAVAILABLENo QUAC device or driver not loadedInstall driver, check PCIe seating, or use QUAC_init_ex(0, 0) for software fallback
INTERNALSDK version mismatch with driverUpdate SDK and driver to matching versions
NOT_INITIALIZEDCalled API before QUAC_init()Ensure init is called once at application startup

Debug Logging

# Enable verbose logging via environment variable
$ export QUAC_LOG_LEVEL=debug
$ ./my_app 2>&1 | grep "QUAC"

# Check if hardware path is being used
$ QUAC_LOG_LEVEL=info ./my_app 2>&1 | grep "hardware"
[QUAC] Using hardware acceleration on device 0

Build Issues

ErrorSolution
openssl/ssl.h: No such fileSet -DBORINGSSL_ROOT=/path/to/boringssl in CMake
undefined reference to QUAC_*Link with -lquac100_boringssl
quac100/quac.h: No such fileSet -DQUAC_SDK_PATH=/opt/quantacore-sdk for hardware support
BoringSSL CBS/CBB errorsEnsure BoringSSL is built before the integration library