Color scheme: Light
You are here: start » en » Documentation » Post-Quantum Cryptography » WvdS Crypto Service overview » Reference » L4Re binary protocol

L4Re binary protocol

This page describes, byte for byte, every message the L4Re form accepts and sends. It applies to protocol version 1. The header file l4re/pub/include/wvds_crypto.h is authoritative; this page summarizes it and adds service behavior that the header alone doesn't tell you.

Transport

Requests and responses travel through DataspaceEndpoint. The service registers under the IPC name CRYPTO_SVC and expects the caller under CRYPTO_CLI; each side's shared region is 64 KiB.

StepWhoCall
Send requestclientadd_new_req(id, type, address, length); by convention, type is the request type from the header
Read and release requestservicereads the message and calls free_peer_req for every request, accepted or rejected
Send responseserviceadd_new_req with the same id and IPC type 0x80
Read and release responseclientevaluates the header and calls free_peer_req

The id matches a response to its request. You choose it; keep it unique among outstanding requests. The IPC type of a response is always 0x80, errors included. Whether a response is an error is determined only by the req_type field of the message header.

Message header

Every message starts with 16 bytes. All numbers are little-endian.

OffsetLengthFieldContent
04magic0x43525950, on the wire 50 59 52 43
41version1
51req_typerequest or response type, see below
62flags0; the service ignores this field
84key_idkey ID, 0 if the request needs no key
124payload_lenlength of the payload that follows the header

Before processing anything, the service checks that:

  • The message is at least 16 bytes and at most 16 bytes plus 64 KiB long.
  • magic and version match.
  • payload_len is no more than 65,536 and equals the message length minus 16.

The service drops an empty or oversized message without a response. If the message is shorter than the header, the header is wrong, or payload_len doesn't match, it responds with WVDS_ERR_INVALID_HEADER.

Request types

ValueNamekey_idServed
0x01WVDS_REQ_AES_GCM_ENCRYPTAES keyyes
0x02WVDS_REQ_AES_GCM_DECRYPTAES keyyes
0x03WVDS_REQ_CHACHA20_ENCRYPTChaCha20 keyonly with the chacha20 build feature
0x04WVDS_REQ_CHACHA20_DECRYPTChaCha20 keyonly with the chacha20 build feature
0x10WVDS_REQ_ML_DSA_SIGNML-DSA keyyes
0x11WVDS_REQ_ML_DSA_VERIFY0yes
0x12WVDS_REQ_ML_DSA_KEYGEN0yes
0x20WVDS_REQ_ML_KEM_ENCAP0yes
0x21WVDS_REQ_ML_KEM_DECAPML-KEM keyyes
0x22WVDS_REQ_ML_KEM_KEYGEN0yes
0x30, 0x31WVDS_REQ_SLH_DSA_SIGN, …_VERIFY–reserved
0x40, 0x41WVDS_REQ_LMS_SIGN, …_VERIFY–reserved
0x50WVDS_REQ_DERIVE_KEY0yes
0x51WVDS_REQ_IMPORT_KEY–reserved
0x52WVDS_REQ_EXPORT_KEYkey pairyes
0x80WVDS_REQ_RESPONSEas in the requestresponse
0xFFWVDS_REQ_ERROR0error response

The service answers reserved and not-built-in types with WVDS_ERR_INVALID_REQ_TYPE.

A request that needs a ChaCha20 key can't succeed today: no request type creates such a key. The same applies to AES; see Keys and key storage.

Payload by request

Length fields inside the payload are 4 bytes, little-endian. “Rest” means all bytes up to the end of the payload.

AES-GCM

TypeRequestResponse
0x01nonce (12) · AAD length (4) · AAD · plaintext (rest)nonce (12) · tag (16) · ciphertext (rest)
0x02nonce (12) · tag (16) · AAD length (4) · AAD · ciphertext (rest)plaintext (rest)

The caller supplies the nonce. A nonce the service has already seen for this key among the last 1024 results in WVDS_ERR_ENCRYPTION_FAILED. ChaCha20 (0x03, 0x04) uses the same layouts.

ML-DSA

TypeRequestResponse
0x12level (1)key ID (4) · public key (rest)
0x10level (1) · message (rest)signature (rest)
0x11level (1) · key length (4) · public key · signature length (4) · signature · message (rest)result (1): 1 valid, 0 invalid

Levels: 2 = ML-DSA-44, 3 = ML-DSA-65, 5 = ML-DSA-87. For 0x10, the service signs only the message; the level byte isn't part of it, and the service takes the level from the key. For 0x12, the response header's key_id field also carries the new key ID.

An invalid signature isn't an error response; it's a response with result 0. If the public key can't be used, the service responds with WVDS_ERR_VERIFICATION_FAILED.

ML-KEM

TypeRequestResponse
0x22level (1)key ID (4) · public key (rest)
0x20level (1) · public key (rest)shared secret (32) · ciphertext (rest)
0x21ciphertext (rest)shared secret (32)

Levels: 1 = ML-KEM-512, 3 = ML-KEM-768, 5 = ML-KEM-1024.

Key derivation and public keys

TypeRequestResponse
0x50salt length (4) · salt · info length (4) · info · output length (4) · IKM (rest)derived key (output length)
0x52no payloadpublic key (rest)

For 0x50, key_id must be 0, the IKM must not be empty, and the output length must not exceed 1024 bytes. 0x52 returns the public key of an ML-DSA or ML-KEM key; for any other key, the service responds with WVDS_ERR_KEY_NOT_FOUND.

Sizes

Parameter setPublic keySignature or ciphertext
ML-DSA-4413122420
ML-DSA-6519523309
ML-DSA-8725924627
ML-KEM-512800768
ML-KEM-76811841088
ML-KEM-102415681568

All values are in bytes; the header defines them as constants, such as WVDS_ML_DSA_65_SIG_SIZE.

Error response

A header with req_type = 0xFF and key_id = 0, followed by:

OffsetLengthContent
04error code
44message length
8restmessage, UTF-8, for diagnostics only

For the error codes, see Error codes. Evaluate the code, not the message; the wording can change.

Requests that get no response

If the caller exceeds 60,000 requests in 60 seconds, the service drops further requests without a response, so a flood doesn't trigger a second flood. It still releases the request's shared memory. Give every request a timeout on the calling side.

en/wiki/pqcrypt/svc/reference/l4re-binary-protocol.txt · Last modified: by Wolfgang van der Stille