lowRISC / lowRISC/opentitan-provisioning
[SKUs] PQC Enablement Status
- Dominant language
- Go
- Stars
- 16
- Forks
- 13
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 18
Description
# OpenTitan Post-Quantum Cryptography (PQC) Provisioning Support Guide
## 1. Summary
As quantum computing architectures advance, classical asymmetric cryptographic primitives—specifically NIST P-256 (ECDSA/ECDH) and RSA-3072—face existential vulnerability. To ensure long-term trust, Silicon Identity integrity, and secure post-manufacture lifecycle management, the OpenTitan provisioning infrastructure is transitioning to **Post-Quantum Cryptography (PQC)** standards aligned with NIST FIPS 203 (ML-KEM) and FIPS 204 (ML-DSA).
This document provides the Silicon Manufacturer with a comprehensive technical inventory of changes implemented across the OpenTitan provisioning ecosystem over the past 12 months. It outlines:
1. **ML-DSA DICE Attestation Certificates:** Endorsing device-generated ML-DSA-87 / ML-DSA-65 / ML-DSA-44 certificates (UDS, CDI_0, CDI_1) via the Silicon Provisioning Manager (SPM) and Provisioning Appliance (PA) ([Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286)).
2. **PQC-Compliant RMA Flow:** Protecting device Return Merchandise Authorization (RMA) unlock tokens and token generation seeds against harvest-now-decrypt-later attacks using a two-layer **Hybrid HPKE** (ML-KEM-768 + ECDH P-256) wrapping scheme ([Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296)).
3. **PQC Transport Security (mTLS):** Securing the gRPC communication channels between Automated Test Equipment (ATE) test stations, Provisioning Appliances (PA), and Silicon Provisioning Managers (SPM) via TLS 1.3 with ML-KEM key exchange (`X25519MLKEM768`) ([Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285)).
4. **Infrastructure Impact Analysis:** Detailed requirements for the Silicon Manufacturer's Hardware Security Modules (HSMs), Certificate Authority (CA) key ceremonies, SPM/PA software appliances, and ATE test floors ([Issue #300](https://github.com/lowRISC/opentitan-provisioning/issues/300), [Issue #299](https://github.com/lowRISC/opentitan-provisioning/issues/299), [Issue #308](https://github.com/lowRISC/opentitan-provisioning/issues/308)).
5. **Enumerated Engineering Tasks for Remaining Work:** Detailed, actionable task specifications for unintegrated components—specifically the ATE C++ client library, buffer limits, and test harnesses ([Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183), [Issue #145](https://github.com/lowRISC/opentitan-provisioning/issues/145)).
---
## 2. End-to-End Architecture Overview
```mermaid
flowchart TB
subgraph ATE_Floor ["Silicon Manufacturer ATE Manufacturing Floor"]
DUT["OpenTitan Silicon (DUT)\n- OTBN PQC Coprocessor\n- ML-DSA UDS Keygen & TBS Cert\n- RMA Token Seed Generation"]
ATE_Harness["ATE Test Station Harness (C++)\n- ate_dll.dll / libate_client.so\n- Personalization Blob Parser (V2 Format - Issue #183)\n- mTLS Client (BoringSSL + X25519MLKEM768 - Issue #285)"]
DUT <-->|"SPI Console / Perso Blob V2\n(Up to 64KB)"| ATE_Harness
end
subgraph PA_Subsystem ["Provisioning Appliance (PA) Boundary"]
PA_Server["PA Service (Go)\n- Load Balancing & Session Mgmt\n- EndorseCerts Bridge (Issue #286)\n- DeriveTokens Bridge (Issue #296)\n- ML-KEM mTLS Server (Issue #285)"]
ATE_Harness <-->|"gRPC over mTLS (TLS 1.3 + ML-KEM-768)\n(pa.proto)"| PA_Server
end
subgraph SPM_Subsystem ["Secure Provisioning Manager (SPM)"]
SPM_Server["SPM Service (Go 1.26)\n- Cert Endorsement Dispatcher (Issue #286)\n- Hybrid HPKE Wrapper (crypto/hpke - Issue #296)\n- Signature Verification Engine"]
PA_Server <-->|"gRPC Internal Channel\n(spm.proto)"| SPM_Server
subgraph HSM_Boundary ["Hardware Security Module (HSM)"]
PK11["PKCS#11 v3.2 Wrapper / SoftHSMv2 / Luna HSM\n- Root CA Keys (ML-DSA / ECDSA - Issue #300)\n- Intermediate CAs (SigningKey/Dice/Mldsa/v0)\n- Hardware Token Seeds (SecHi / SecLo)\n- RSA/AES Wrapping Keys"]
SPM_Server <-->|"PKCS#11 API (CKM_MLDSA, CKM_MLDSA_KEY_PAIR_GEN)"| PK11
end
end
```
### Cryptographic Transition Matrix
| Functional Domain | Classical Primitive (Legacy) | Post-Quantum Primitive (Target) | Hybrid / Interim Mode | Relevant Tracking Issue |
| :--- | :--- | :--- | :--- | :--- |
| **DICE UDS Certificate** | ECDSA NIST P-256 (SHA-256) | **ML-DSA-87 / ML-DSA-65** (FIPS 204) | Dual Certificates (`UDS` + `UDS_MLDSA`) | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| **DICE CA Hierarchy** | ECDSA P-256 Root & Sub CAs | **ML-DSA-87 Root CA & Sub CAs** | Separate Root CAs (`RootCA` & `RootCAMldsa`) | [Issue #300](https://github.com/lowRISC/opentitan-provisioning/issues/300), [Issue #299](https://github.com/lowRISC/opentitan-provisioning/issues/299) |
| **RMA Token Seed Export** | RSA-3072 OAEP / PKCS#1 v1.5 | **ML-KEM-768 / Hybrid HPKE** | **2-Layer Wrapping:** HSM RSA-3072 + SPM Hybrid HPKE (ML-KEM-768 + P-256) | [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
| **ATE <-> PA mTLS Transport**| TLS 1.3 (ECDHE X25519 / P-256) | **TLS 1.3 with ML-KEM-768** | Hybrid `X25519MLKEM768` (BoringSSL & Go crypto/tls) | [Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285) |
| **Perso Blob Framing** | V0 (16-bit header, 4KB max obj) | **V1/V2 (32-bit header, 16MB max obj)** | Header version TLV backwards compatibility | [Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183), [Issue #145](https://github.com/lowRISC/opentitan-provisioning/issues/145) |
---
## 3. Detailed Enumeration of Changes (Past 12 Months)
### 3.1 Subsystem 1: Protocol Buffers & Data Models
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`1652950`](https://github.com/lowRISC/opentitan-provisioning/commit/1652950) | 2026-01-14 | `src/proto/crypto` (`ot-prov`) | `src/proto/crypto/mldsa.proto`
`src/proto/crypto/cert.proto`
`src/proto/crypto/BUILD.bazel` | Defined ML-DSA parameter sets (`MLDSA_44`, `MLDSA_65`, `MLDSA_87`), `MldsaParams`, `MldsaPublicKey`, and `MldsaPrivateKey`. Extended `SigningKeyParams` in `cert.proto` with `oneof key` to include `MldsaParams`. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`2eb9b2b`](https://github.com/lowRISC/opentitan-provisioning/commit/2eb9b2b) | 2026-01-15 | `src/spm/proto`, `src/pa/proto` (`ot-prov`) | `src/spm/proto/spm.proto`
`src/pa/proto/pa.proto`
`src/proto/crypto/cert.proto` | Added RPC schemas and message definitions for ML-DSA signature handling and certificate endorsement. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`7ee7034`](https://github.com/lowRISC/opentitan-provisioning/commit/7ee7034) | 2026-02-27 | Build & Protos (`ot-prov`) | `MODULE.bazel`
`src/proto/BUILD.bazel`
`src/proto/crypto/BUILD.bazel` | Updated `cc_proto_library` rules to `@com_google_protobuf//bazel:cc_proto_library.bzl` and upgraded Go toolchain to 1.26.0 for native HPKE/ML-KEM protobuf handling. | [Issue #283](https://github.com/lowRISC/opentitan-provisioning/issues/283) |
**Key Code Pointer (`src/proto/crypto/mldsa.proto`):**
```protobuf
enum MldsaParameterSets {
MLDSA_PARAMETER_SETS_MLDSA_UNSPECIFIED = 0;
MLDSA_PARAMETER_SETS_MLDSA_44 = 1; // Category 2
MLDSA_PARAMETER_SETS_MLDSA_65 = 2; // Category 3
MLDSA_PARAMETER_SETS_MLDSA_87 = 3; // Category 5 (Default for OpenTitan Root)
}
message MldsaParams {
MldsaParameterSets param_sets = 1;
}
```
---
### 3.2 Subsystem 2: HSM & PKCS#11 Integration Layer
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`3cd5d3e`](https://github.com/lowRISC/opentitan-provisioning/commit/3cd5d3e) | 2026-01-20 | `src/pk11` (`ot-prov`) | `src/pk11/mldsa.go`
`src/pk11/BUILD.bazel` | Introduced stubs and PKCS#11 constants for ML-DSA operations (`CKM_MLDSA = 0x1D`, `CKK_MLDSA = 0x4A`, `CKM_MLDSA_KEY_PAIR_GEN = 0x1C`, `CKA_PARAMETER_SET = 0x61D`). | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`60d6d38`](https://github.com/lowRISC/opentitan-provisioning/commit/60d6d38) | 2026-01-20 | HSM Emulation (`ot-prov`) | `MODULE.bazel`
`src/pk11/mldsa.go` | Added PKCS#11 wrapper implementations for `GenerateMLDSA()`, `SignMLDSA()`, and `VerifyMLDSA()`. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`44f3d7d`](https://github.com/lowRISC/opentitan-provisioning/commit/44f3d7d) | 2026-02-04 | Crypto Toolchain (`ot-prov`) | `MODULE.bazel`
`third_party/openssl/BUILD.openssl.bazel` | Integrated hermetic OpenSSL 3.5.5 build to provide native FIPS 204 (ML-DSA) cryptographic support without host library dependencies. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`7d28a91`](https://github.com/lowRISC/opentitan-provisioning/commit/7d28a91) | 2026-02-24 | SoftHSM Infra (`ot-prov`) | `MODULE.bazel`
`third_party/softhsm2/BUILD.softhsm2.bazel` | Connected SoftHSMv2 build against hermetic OpenSSL 3.5.5 to allow ML-DSA hardware emulation. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`d1a48c9`](https://github.com/lowRISC/opentitan-provisioning/commit/d1a48c9) | 2026-02-24 | `src/pk11` (`ot-prov`) | `src/pk11/mldsa.go`
`src/pk11/object.go` | Added `MLDSASigner` adhering to the standard Go `crypto.Signer` interface. Supported ML-DSA key attributes (`CKA_SIGN`, `CKA_VERIFY`, `CKA_TOKEN`, `CKA_SENSITIVE`). | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`7797086`](https://github.com/lowRISC/opentitan-provisioning/commit/7797086) | 2026-04-29 | SoftHSM (`ot-prov`) | `MODULE.bazel` | Standardized SoftHSMv2 integration on upstream mainline repository. | [Issue #308](https://github.com/lowRISC/opentitan-provisioning/issues/308) |
**Key Code Pointer (`src/pk11/mldsa.go`):**
```go
// SignMLDSA signs a message using ML-DSA via PKCS#11.
func (k PrivateKey) SignMLDSA(message []byte) ([]byte, error) {
mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(CKM_MLDSA, make([]byte, 0))}
if err := k.sess.tok.m.Raw().SignInit(k.sess.raw, mech, k.raw); err != nil {
return nil, newError(err, "could not begin signing operation")
}
return k.sess.tok.m.Raw().Sign(k.sess.raw, message)
}
```
---
### 3.3 Subsystem 3: SPM & PA Services (Certificates & Verification)
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`4082f2e`](https://github.com/lowRISC/opentitan-provisioning/commit/4082f2e) / [`33276fe`](https://github.com/lowRISC/opentitan-provisioning/commit/33276fe) | 2026-02-24 | SPM & PA Services (`ot-prov`) | `src/spm/services/spm.go`
`src/spm/services/se_pk11.go`
`src/spm/services/se.go`
`src/pa/loadtest.go` | Implemented end-to-end ML-DSA certificate endorsement in SPM. Added ASN.1 DER certificate serialization for ML-DSA with OIDs (`2.16.840.1.101.3.4.3.17` for 44, `...18` for 65, `...19` for 87). Added ML-DSA signature verification in `VerifyDeviceData`. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`4741286`](https://github.com/lowRISC/opentitan-provisioning/commit/4741286) | 2026-04-08 | CA Config (`ot-prov`) | `rules/scripts/hsm_ca_sign.sh` | Parameterized Distinguished Names (DN) for Root CAs (`OTPROV_CA_ROOT_C`, `OTPROV_CA_ROOT_O`, `OTPROV_CA_ROOT_CN`), enabling Silicon Manufacturer custom branding in ML-DSA root certificates. | [Issue #300](https://github.com/lowRISC/opentitan-provisioning/issues/300) |
**Key Certificate Handling in SPM (`src/spm/services/se_pk11.go`):**
```go
if params.MldsaAlgorithm != nil {
// MLDSA Signing via HSM
sigBytes, err = key.SignMLDSA(tbs)
if err != nil {
return nil, fmt.Errorf("failed to sign with MLDSA: %v", err)
}
sigType, err = oidFromMLDSAParameterSet(params.MldsaAlgorithm.ParameterSets)
if err != nil {
return nil, fmt.Errorf("failed to get signature algorithm OID: %v", err)
}
}
// Assembles X.509 structure: SEQUENCE { TBSCertificate, AlgorithmIdentifier, BIT STRING signature }
```
---
### 3.4 Subsystem 4: Certificate Generation Tooling (`tbsgen`) & Bazel HSM Rules
Standard tools like OpenSSL 3.0 CLI and Go's `crypto/x509` do not provide out-of-the-box support for generating raw To-Be-Signed (TBS) certificates and assembling them with detached HSM post-quantum signatures. A dedicated tool (`tbsgen`) and Bazel HSM rules were introduced:
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`c0b0d42`](https://github.com/lowRISC/opentitan-provisioning/commit/c0b0d42) | 2026-03-17 | `src/spm/.../tbsgen` (`ot-prov`) | `src/spm/services/testutils/tbsgen.go`
`src/spm/services/testutils/tbsgen/main.go` | Created `tbsgen` CLI tool to generate TBS structures from CSRs, patch SubjectPublicKeyInfo for ML-DSA, and assemble completed certificates from raw HSM signatures. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`2ffd273`](https://github.com/lowRISC/opentitan-provisioning/commit/2ffd273) | 2026-03-17 | Bazel HSM Rules (`ot-prov`) | `rules/hsm.bzl`
`rules/hsmtool.bzl`
`rules/scripts/hsm_ca_sign.sh` | Enhanced HSM Bazel rules: added `hsm_certificate_authority_root_mldsa`, `hsm_certificate_authority_intermediate_mldsa`, and updated `hsm_ca_sign.sh` to integrate `tbsgen` into key ceremony generation. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286), [Issue #301](https://github.com/lowRISC/opentitan-provisioning/issues/301) |
**Key Ceremony Workflow for ML-DSA:**
1. **CSR Generation:** `hsmtool mldsa export-csr --label --subject --output `
2. **TBS Generation:** `tbsgen tbs --csr [--ca-cert ] --output `
3. **HSM Signing:** `hsmtool mldsa sign --label --format raw --output `
4. **Assembly:** `tbsgen assemble --tbs --signature --output `
---
### 3.5 Subsystem 5: Personalization Blob Format V2 & ATE Buffer Sizing
ML-DSA public keys and signatures are substantially larger than classical ECC keys:
- **NIST P-256:** Public Key = 64 bytes, Signature = 64–72 bytes.
- **ML-DSA-87:** Public Key = 2,592 bytes, Signature = 4,627 bytes.
Because of this size increase, the original V0 TLV format (12-bit size field capped at 4,095 bytes) and 4KB buffer limits were inadequate.
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`d7e1076`](https://github.com/lowRISC/opentitan-provisioning/commit/d7e1076) | 2026-02-24 | `src/ate` (`ot-prov`) | `src/ate/ate_api.h`
`src/ate/test_programs/ft.cc` | Increased `kCertificateMaxSize` from ~2KB to **8,192 bytes (8KB)** and `kPersoBlobMaxSize` to **65,536 bytes (64KB)**. | [Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183) |
| [`eba97b6`](https://github.com/lowRISC/opentitan-provisioning/commit/eba97b6) | 2026-02-24 | `src/ate` (`ot-prov`) | `src/ate/ate_perso_blob.h`
`src/ate/ate_perso_blob.cc`
`src/ate/perso_blob.go`
`rules/scripts/hsm_ca_sign.sh` | Introduced **V2 Personalization Blob Format** (`kPersoBlobVersionV1`): uses a 32-bit object header (8-bit type, 24-bit size) supporting payload objects up to 16MB. | [Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183) |
| [`6ff31b3`](https://github.com/lowRISC/opentitan-provisioning/commit/6ff31b3) | 2026-03-10 | `src/ate` (`ot-prov`) | `src/ate/ate_api.h`
`src/ate/ate_perso_blob.cc` | Refactored version enum helpers (`kPersoBlobVersionV0`, `kPersoBlobVersionV1`). | [Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183) |
**Header Structure Comparison:**
```c
// V0 (Legacy 16-bit Header): 4-bit Type, 12-bit Size (Max Object: 4,095 bytes)
typedef uint16_t perso_tlv_object_header_v0_t;
// V1/V2 (32-bit Header): 8-bit Type, 24-bit Size (Max Object: 16,777,215 bytes)
typedef uint32_t perso_tlv_object_header_v1_t;
```
---
### 3.6 Subsystem 6: PQC-Compliant RMA Flow (Hybrid HPKE)
During device personalization, the ATE requests the SPM to derive the RMA unlock token and export a wrapped version of the token generation seed (`TOKEN_SEED_KEYGEN`). If quantum adversaries capture this wrapped seed, they could decrypt it in the future and forge RMA unlock tokens for manufactured chips.
To resolve this without waiting for native HPKE hardware HSM support, a **Two-Layer Hybrid HPKE Wrapping** scheme was implemented in SPM:
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`c481084`](https://github.com/lowRISC/opentitan-provisioning/commit/c481084) | 2026-02-28 | `src/spm` (`ot-prov`) | `src/spm/services/spm.go`
`src/spm/services/skucfg.go` | Added `SecondLayerWrappingMechanism: Hpke`. The HSM first wraps the token seed via RSA-3072; the SPM then encapsulates the ciphertext in an outer Hybrid HPKE envelope (ML-KEM-768 + ECDH P-256 + AES-256-GCM). | [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
| [`7ee7034`](https://github.com/lowRISC/opentitan-provisioning/commit/7ee7034) | 2026-02-27 | Toolchain (`ot-prov`) | `MODULE.bazel`
`go.mod` | Upgraded Go toolchain to version **1.26.0** to leverage native standard library `crypto/hpke` and `crypto/mlkem`. | [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
| [`03c1be7`](https://github.com/lowRISC/opentitan-provisioning/commit/03c1be7) | 2026-02-28 | SKU Config (`ot-prov`) | `config/spm/sku_test_hpke.yml.tmpl`
`util/generate_test_hpke_keys.go`
`tests/run_pa_hpke_loadtest.sh` | Added test HPKE key generation tooling and PA load test harness for HPKE token wrapping. | [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
| [`e464eb7`](https://github.com/lowRISC/opentitan-provisioning/commit/e464eb7) | 2026-03-30 | SKU Config (`ot-prov`) | `config/spm/sku/sival_pqc/BUILD.bazel`
`config/spm/sku_sival_pqc.yml.tmpl` | Consolidated ML-DSA certificates and HPKE RMA wrapping into the unified `sival_pqc` SKU. | [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
**SPM Hybrid HPKE Implementation (`src/spm/services/spm.go`):**
```go
// 1. Parse Classical ECDH P-256 Public Key
ecdhPub, _ := classicalPub.(*ecdsa.PublicKey).ECDH()
// 2. Parse Post-Quantum ML-KEM-768 Public Key
pqEnc, _ := mlkem.NewEncapsulationKey768(pqBytes)
// 3. Create Hybrid HPKE Public Key
hpkeHybridPub, err := hpke.NewHybridPublicKey(pqEnc, ecdhPub)
// 4. Seal Wrapped Seed with Authenticated Encryption
wrappedKey, err = hpke.Seal(
hpkeHybridPub,
hpke.HKDFSHA256(),
hpke.AES256GCM(),
[]byte("token-seed-wrap"),
hsmRsaWrappedKey,
)
```
---
### 3.7 Subsystem 7: PQC mTLS for gRPC Transport Security
To protect network traffic between the ATE test floor client and the PA/SPM backend against passive network interception and decryption by future quantum computers:
| Commit SHA | Date | Component / Repo | Files Changed | Description & Impact | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`e931837`](https://github.com/lowRISC/opentitan-provisioning/commit/e931837) | 2026-01-05 | `src/transport`, `third_party` (`ot-prov`) | `src/transport/grpconn.go`
`src/transport/grpconn_test.go`
`third_party/google/grpc_force_mlkem.patch`
`src/pa/pa_server.go`
`src/spm/spm_server.go` | Upgraded gRPC to v1.68.0 and BoringSSL with ML-KEM support. Patched gRPC C++ TSI layer to enforce key exchange group `"X25519MLKEM768:X25519:P-256"`. Added `EnableMLKEMTLS` in Go transport config. | [Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285) |
| [`0ed2d13`](https://github.com/lowRISC/opentitan-provisioning/commit/0ed2d13) | 2026-01-06 | `src/ate/test_programs` (`ot-prov`) | `src/ate/test_programs/tls_test.cc`
`integration/run_tls_test.sh` | Added standalone C++ mTLS client integration test program to validate ML-KEM TLS handshake against PA servers. | [Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285) |
**gRPC BoringSSL Transport Patch (`third_party/google/grpc_force_mlkem.patch`):**
```cpp
#if defined(OPENSSL_IS_BORINGSSL)
// Explicitly configure supported TLS 1.3 key exchange groups:
if (!SSL_CTX_set1_groups_list(context, "X25519MLKEM768:X25519:P-256")) {
LOG(ERROR) << "Could not set supported groups.";
return TSI_INTERNAL_ERROR;
}
#endif
```
---
### 3.8 Subsystem 8: SKU Definitions & CI Environment
| Commit SHA | Date | Component / Repo | Description | GitHub Ref |
| :--- | :--- | :--- | :--- | :--- |
| [`17a9de6`](https://github.com/lowRISC/opentitan-provisioning/commit/17a9de6) | 2026-03-25 | `ot-prov` | Introduced `OT_PROV_PQ_EN` environment variable to conditionally enable PQC validation in environments with PQC HSM support. | [Issue #308](https://github.com/lowRISC/opentitan-provisioning/issues/308) |
| [`e611941`](https://github.com/lowRISC/opentitan-provisioning/commit/e611941) | 2026-03-25 | `ot-prov` | Standardized ML-DSA root key naming convention to `opentitan-mldsa-ca-root-v0`. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286) |
| [`e464eb7`](https://github.com/lowRISC/opentitan-provisioning/commit/e464eb7) | 2026-03-30 | `ot-prov` | Created reference `sival_pqc` SKU combining ML-DSA Root CA, ML-DSA DICE UDS ICA, and Hybrid HPKE RMA token configuration. | [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286), [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296) |
---
## 4. Silicon Manufacturer Infrastructure Requirements & Impact
To support OpenTitan PQC provisioning in production, the Silicon Manufacturer must review and update four major infrastructure areas:
```
+-----------------------------------------------------------------------------------------+
| SILICON MANUFACTURER INFRASTRUCTURE |
| |
| 1. HSM Infrastructure 2. Provisioning Servers |
| - Firmware upgrade for ML-DSA (FIPS 204) - Go runtime >= 1.26.0 |
| - PKCS#11 v3.2 / vendor mechanism support - OpenSSL >= 3.5.5 |
| - Root & Intermediate ML-DSA Key Ceremonies - SPM Hybrid HPKE Configuration |
| (See Issue #300, #299, #308) (See Issue #296) |
| |
| 3. ATE Test Station Software 4. Network & Security |
| - Update ATE DLL (ate_dll.dll / .so) - TLS 1.3 Key Exchange: |
| - Support Perso Blob V2 format (Issue #183) - X25519MLKEM768 negotiation |
| - Increase RMA wrapped seed buffers (Issue #145) (See Issue #285) |
| - Bandwidth scaling for 64KB |
| personalization frames |
+-----------------------------------------------------------------------------------------+
```
### 4.1 Hardware Security Module (HSM) Requirements
- **Firmware Support:** Production HSMs (e.g., Thales Luna PCIe/Network HSM or Marvell LiquidSecurity) must be updated to firmware versions supporting NIST FIPS 204 (ML-DSA) ([Issue #308](https://github.com/lowRISC/opentitan-provisioning/issues/308)).
- **PKCS#11 Mechanisms:** The PKCS#11 library provided by the HSM vendor must support:
- `CKM_MLDSA_KEY_PAIR_GEN` / `CKM_MLDSA` (or vendor equivalent OIDs).
- Parameter sets for ML-DSA-87 and ML-DSA-65 (`CKA_PARAMETER_SET`).
- **Dual-HSM / Transition Strategy:** If the Silicon Manufacturer's existing production HSMs do not yet have FIPS 204 firmware certification, the SPM supports dual key management where classical keys reside in the hardware HSM and PQC keys reside in a dedicated SoftHSM/vHSM container instance until hardware support is certified.
### 4.2 Key Ceremonies & SKU Configuration
- **Root & Sub-CA Generation:** The Silicon Manufacturer must conduct an updated key ceremony to generate:
1. `opentitan-mldsa-ca-root-v0` (Root CA, ML-DSA-87)
2. `sival_pqc-dice-key-mldsa-v0` (DICE UDS Intermediate CA, ML-DSA-87)
3. `hpke_mlkem.pub` & `hpke_ecdsa.pub.der` (HPKE RMA Token Wrapping Public Keys)
- **Tooling Execution:** Key ceremonies must use the updated `rules/scripts/hsm_ca_sign.sh` script with `tbsgen` and `hsmtool` instead of legacy OpenSSL 1.1/3.0 scripts ([Issue #300](https://github.com/lowRISC/opentitan-provisioning/issues/300), [Issue #299](https://github.com/lowRISC/opentitan-provisioning/issues/299), [Issue #301](https://github.com/lowRISC/opentitan-provisioning/issues/301)).
### 4.3 Provisioning Appliance (PA) and SPM Deployment
- **Go Toolchain:** Servers building and hosting PA/SPM services must use Go **1.26.0 or higher**.
- **Hermetic OpenSSL:** Deployment containers must package the hermetic OpenSSL 3.5.5 build (`third_party/openssl/BUILD.openssl.bazel`).
- **Configuration Templates:** Enable `SecondLayerWrappingMechanism: Hpke` in `sku_.yml` templates and supply valid paths for `HPKEPQPublicKeyPath` and `HPKEClassicalPublicKeyPath` ([Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296)).
### 4.4 ATE Test Station Software & Floor Network
- **DLL Upgrade:** Replace existing `ate_client.dll` / `ate_api.dll` binaries on all ATE testers with the updated build containing V2 blob parsing ([Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183)).
- **SPI Frame Buffer Sizing:** ATE test programs must allocate SPI frame reception buffers sized for V2 blobs (up to **64KB** per DUT vs legacy 4KB).
- **mTLS Network Configuration:** Firewalls, proxies, and load balancers between ATE stations and the PA server must allow TLS 1.3 ClientHello messages containing ML-KEM key share extensions (~1.2KB ClientHello packets) ([Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285)).
---
## 5. Enumerated Engineering Tasks for Remaining Work
While the Go backend services (SPM, PA, `tbsgen`, and SoftHSM layer) have complete PQC support, the **ATE C++ Client Library** (`src/ate/`), the **C API Header** (`ate_api.h`), the **ATE Dynamic Library Interface** (`ate_dll.cc`), and the **ATE Reference Test Program** (`ft.cc`) have unintegrated gaps that prevent end-to-end execution of PQC provisioning on C++ test floors.
The following enumerated tasks capture all remaining work required to achieve full PQC parity in the repository.
```mermaid
gantt
title PQC Enablement: Remaining Engineering Tasks
dateFormat YYYY-MM-DD
section Task 1: C API Header (ate_api.h)
TASK-1.1 Add algorithm_type_t & mldsa_param_set_t :active, task1_1, 2026-08-20, 2d
TASK-1.2 Extend endorse_cert_request_t struct :active, task1_2, 2026-08-22, 2d
section Task 2: ATE C++ Library (ate_dll.cc)
TASK-2.1 Update EndorseCerts() for ML-DSA protos :active, task2_1, 2026-08-24, 3d
TASK-2.2 Update GetCaCerts() label mappings :active, task2_2, 2026-08-27, 2d
section Task 3: Buffer Sizing & HPKE
TASK-3.1 Expand kWrappedSeedMaxSize to 2048B :active, task3_1, 2026-08-29, 2d
TASK-3.2 Validate TokensCopy() for HPKE seeds :active, task3_2, 2026-08-31, 2d
section Task 4: Transport & Test Harness
TASK-4.1 Add runtime ML-KEM options in AteClient :task4_1, 2026-09-02, 2d
TASK-4.2 Update ft.cc for sival_pqc reference flow:task4_2, 2026-09-04, 3d
TASK-4.3 Hardware HSM integration validation :task4_3, 2026-09-07, 4d
```
---
### Task 1: Extend `ate_api.h` with ML-DSA Algorithm Enums & Request Structs
* **Component:** `src/ate/ate_api.h` (`lowRISC/opentitan-provisioning`)
* **Priority:** Critical (Blocking)
* **Related Issues:** [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286)
* **Problem Statement:** `src/ate/ate_api.h` currently only defines `curve_type_t` with `kCurveTypeP256 = 1`. The `endorse_cert_request_t` struct has no field to specify whether a certificate endorsement is for ECDSA or ML-DSA, nor does it specify the ML-DSA parameter set (Category 2/3/5).
* **Technical Specification & Implementation:**
1. Define `signing_algorithm_type_t`:
```c
typedef enum signing_algorithm_type {
kSigningAlgorithmTypeUnspecified = 0,
kSigningAlgorithmTypeEcdsa = 1,
kSigningAlgorithmTypeMldsa = 2,
} signing_algorithm_type_t;
```
2. Define `mldsa_param_set_t`:
```c
typedef enum mldsa_param_set {
kMldsaParamSetUnspecified = 0,
kMldsaParamSet44 = 1,
kMldsaParamSet65 = 2,
kMldsaParamSet87 = 3,
} mldsa_param_set_t;
```
3. Update `endorse_cert_request_t` to support ML-DSA parameters:
```c
typedef struct endorse_cert_request {
signing_algorithm_type_t algorithm_type;
hash_type_t hash_type;
curve_type_t curve_type;
mldsa_param_set_t mldsa_param_set;
signature_encoding_t signature_encoding;
size_t key_label_size;
char key_label[kCertificateKeyLabelMaxSize];
size_t tbs_size;
char tbs[kCertificateMaxSize];
} endorse_cert_request_t;
```
* **Acceptance Criteria:** `src/ate/ate_api.h` compiles cleanly across Linux (`gcc`/`clang`) and Windows (`MSVC`), maintaining binary layout compatibility and proper C linkage.
---
### Task 2: Implement ML-DSA Request Mapping in `ate_dll.cc` (`EndorseCerts`)
* **Component:** `src/ate/ate_dll.cc` (`lowRISC/opentitan-provisioning`)
* **Priority:** Critical (Blocking)
* **Related Issues:** [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286)
* **Problem Statement:** `EndorseCerts()` in `src/ate/ate_dll.cc` (lines 565–595) unconditionally creates `signing_params->mutable_ecdsa_params()`. Supplying an ML-DSA certificate request results in `absl::StatusCode::kInvalidArgument` failure.
* **Technical Specification & Implementation:**
1. Inspect `req_params.algorithm_type` in `EndorseCerts()`:
2. For `kSigningAlgorithmTypeMldsa`, populate `SigningKeyParams_MldsaParams`:
```cpp
if (req_params.algorithm_type == kSigningAlgorithmTypeMldsa) {
auto mldsa_key = signing_params->mutable_mldsa_params();
switch (req_params.mldsa_param_set) {
case kMldsaParamSet44:
mldsa_key->set_param_sets(crypto::mldsa::MLDSA_PARAMETER_SETS_MLDSA_44);
break;
case kMldsaParamSet65:
mldsa_key->set_param_sets(crypto::mldsa::MLDSA_PARAMETER_SETS_MLDSA_65);
break;
case kMldsaParamSet87:
mldsa_key->set_param_sets(crypto::mldsa::MLDSA_PARAMETER_SETS_MLDSA_87);
break;
default:
LOG(ERROR) << "Invalid ML-DSA parameter set: " << req_params.mldsa_param_set;
return static_cast(absl::StatusCode::kInvalidArgument);
}
} else {
// Legacy / Classical ECDSA path
auto ecdsa_key = signing_params->mutable_ecdsa_params();
// ... existing ECDSA curve and hash mapping ...
}
```
* **Acceptance Criteria:** `EndorseCerts()` successfully forwards `EndorseCertsRequest` containing `mldsa_params` to the PA service and unpacks ML-DSA X.509 certificates up to 8KB without error.
---
### Task 3: Expand `kWrappedSeedMaxSize` to 2048 Bytes for Hybrid HPKE RMA Seeds
* **Component:** `src/ate/ate_api.h`, `src/ate/ate_dll.cc` (`lowRISC/opentitan-provisioning`)
* **Priority:** High
* **Related Issues:** [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296), [Issue #145](https://github.com/lowRISC/opentitan-provisioning/issues/145)
* **Problem Statement:** `kWrappedSeedMaxSize` is defined as `384` bytes in `ate_api.h` (matching RSA-3072 ciphertext). When SPM's `SecondLayerWrappingMechanism: Hpke` is enabled, the outer ML-KEM-768 + ECDH P-256 + AES-GCM envelope expands the wrapped seed to **~1,500 bytes**. Invoking `GenerateTokens()` causes `ate_dll.cc` line 343 (`if (s.size() > sizeof(seed.seed))`) to fail with an error.
* **Technical Specification & Implementation:**
1. In `src/ate/ate_api.h`, increase the buffer constant:
```c
enum {
/**
* Maximum wrapped seed size in bytes. Sized to accommodate two-layer
* Hybrid HPKE wrapping (ML-KEM-768 ciphertext + ECDH P-256 + AES-GCM + payload).
*/
kWrappedSeedMaxSize = 2048,
};
```
2. Verify that `wrapped_seed_t` and `TokensCopy()` in `src/ate/ate_dll.cc` handle the 2048-byte allocation cleanly without stack overflow or heap corruption.
* **Acceptance Criteria:** `GenerateTokens()` and `DeriveTokens()` return complete HPKE hybrid wrapped RMA token seeds (~1.5KB) without triggering buffer size violations.
---
### Task 4: Extend CA Certificate Label Mappings in `GetCaCerts()` and `GetCaSubjectKeys()`
* **Component:** `src/ate/ate_dll.cc` (`lowRISC/opentitan-provisioning`)
* **Priority:** Medium
* **Related Issues:** [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286)
* **Problem Statement:** `GetCaCerts()` in `src/ate/ate_dll.cc` (lines 515–535) strictly validates labels against prefixes `"root"` and `"dice"`, assigning fixed labels `OSAT_ROOT_CA` and `OSAT_ICA_DICE`. It rejects ML-DSA labels such as `"root_mldsa"`, `"dice_mldsa"`, and `"ext_mldsa"`.
* **Technical Specification & Implementation:**
1. Update label parsing in `GetCaCerts()`:
```cpp
if (strcmp(labels[i], "root") == 0) {
CopyCertLabel(certs[i], "OSAT_ROOT_CA");
} else if (strcmp(labels[i], "root_mldsa") == 0) {
CopyCertLabel(certs[i], "OSAT_ROOT_CA_MLDSA");
} else if (strcmp(labels[i], "dice") == 0) {
CopyCertLabel(certs[i], "OSAT_ICA_DICE");
} else if (strcmp(labels[i], "dice_mldsa") == 0) {
CopyCertLabel(certs[i], "OSAT_ICA_DICE_MLDSA");
} else if (strcmp(labels[i], "ext") == 0) {
CopyCertLabel(certs[i], "OSAT_ICA_EXT");
} else if (strcmp(labels[i], "ext_mldsa") == 0) {
CopyCertLabel(certs[i], "OSAT_ICA_EXT_MLDSA");
} else {
LOG(ERROR) << "Unknown CA certificate label: " << labels[i];
return static_cast(absl::StatusCode::kInvalidArgument);
}
```
2. Update `GetCaSubjectKeys()` in `ate_dll.cc` to forward ML-DSA label requests (`UDS_MLDSA`, `EXT_MLDSA`) to the PA without error.
* **Acceptance Criteria:** ATE test programs can fetch both classical and ML-DSA Root/Intermediate CA certificates in a single session.
---
### Task 5: Expose Runtime ML-KEM mTLS Configuration in `AteClient`
* **Component:** `src/ate/ate_api.h`, `src/ate/ate_client.h`, `src/ate/ate_client.cc` (`lowRISC/opentitan-provisioning`)
* **Priority:** Medium
* **Related Issues:** [Issue #285](https://github.com/lowRISC/opentitan-provisioning/issues/285)
* **Problem Statement:** ML-KEM key exchange in the C++ gRPC transport is currently forced via a static patch in `third_party/google/grpc_force_mlkem.patch`. The ATE client options struct lacks a runtime configuration field to select or disable ML-KEM mTLS negotiation.
* **Technical Specification & Implementation:**
1. Add `bool enable_mlkem` to `client_options_t` (`ate_api.h`) and `AteClient::Options` (`ate_client.h`).
2. In `AteClient::Create()` (`ate_client.cc`), configure channel arguments to pass custom curve preferences to the underlying BoringSSL security context.
* **Acceptance Criteria:** ATE client can connect to PA servers enforcing ML-KEM TLS 1.3, and gracefully fall back to classical TLS 1.3 cipher suites when connecting to legacy PA deployments.
---
### Task 6: Update FT Reference Test Program (`ft.cc`) for `sival_pqc` End-to-End Flow
* **Component:** `src/ate/test_programs/ft.cc`, `tests/run_ate_test.sh` (`lowRISC/opentitan-provisioning`)
* **Priority:** High (Verification)
* **Related Issues:** [Issue #286](https://github.com/lowRISC/opentitan-provisioning/issues/286), [Issue #296](https://github.com/lowRISC/opentitan-provisioning/issues/296), [Issue #183](https://github.com/lowRISC/opentitan-provisioning/issues/183)
* **Problem Statement:** `src/ate/test_programs/ft.cc` only tests classical ECDSA P-256 certificate chains for `pi01`/`sival`. There is no C++ reference test program verifying the complete ML-DSA endorsement and Hybrid HPKE RMA token provisioning flow.
* **Technical Specification & Implementation:**
1. Update `ft.cc` to parse SKU configuration and detect ML-DSA TBS certificates (`UDS_MLDSA`).
2. Configure `endorse_cert_request_t` with `kSigningAlgorithmTypeMldsa` and `kMldsaParamSet87` for ML-DSA certificates.
3. Request CA certs for `"root_mldsa"` and `"dice_mldsa"` and repack them into the V2 personalization blob using `PackPersoBlob()`.
4. Call `RegisterDevice()` with the Hybrid HPKE wrapped RMA token seed.
5. Add test invocation to `tests/run_ate_test.sh` under `OT_PROV_PQ_EN=true`.
* **Acceptance Criteria:** `bazelisk run //src/ate/test_programs:ft -- --sku=sival_pqc ...` executes against a live PA/SPM instance in CI and succeeds with 0 errors.
---
### Task 7: Physical Hardware HSM Qualification & Latency Benchmarking
* **Component:** Hardware HSM Integration / Nuvoton Production Floor
* **Priority:** High (Production Readiness)
* **Related Issues:** [Issue #308](https://github.com/lowRISC/opentitan-provisioning/issues/308), [Issue #272](https://github.com/lowRISC/opentitan-provisioning/issues/272), [Issue #111](https://github.com/lowRISC/opentitan-provisioning/issues/111)
* **Problem Statement:** ML-DSA endorsement has been validated in CI against SoftHSMv2 and OpenSSL 3.5.5. Production hardware HSMs (e.g. Thales Luna HSM) must be qualified for FIPS 204 throughput and latency on the ATE line.
* **Technical Specification & Implementation:**
1. Load FIPS 204 firmware on target production hardware HSM.
2. Execute key ceremony using `rules/scripts/hsm_ca_sign.sh` and `tbsgen` against the physical HSM token.
3. Execute `run_pa_loadtest.sh` with `--parallel_clients=16 --total_duts=1000 --enable_mldsa=true`.
4. Benchmark per-device ML-DSA signing latency (target: < 50ms per certificate endorsement).
* **Acceptance Criteria:** Hardware HSM executes sustained parallel ML-DSA-87 signing operations with zero session leaks and throughput exceeding manufacturing line requirements (> 3,600 chips/hour).
---
## 6. GitHub Issues & References Matrix
The following table aggregates all relevant GitHub issues from the [`lowRISC/opentitan-provisioning`](https://github.com/lowRISC/opentitan-provisioning/issues) repository tracking PQC features, HSM integration, and test harness infrastructure:
| Issue | Title | Subsystem / Area | Status | Impact / Relationship to PQC |
| :--- | :--- | :--- | :--- | :--- |
| [#286](https://github.com/lowRISC/opentitan-provisioning/issues/286) | *Upgrade SPM module to support ML-DSA-87 certificate signing* | `src/spm`, `src/pk11`, `tbsgen` | **Open** | Primary umbrella issue for ML-DSA DICE certificate endorsement in SPM and PKCS#11 layer. |
| [#285](https://github.com/lowRISC/opentitan-provisioning/issues/285) | *PQC TLS Support in gRPC Clients and Servers* | `src/transport`, `third_party` | **Open** | Primary umbrella issue for ML-KEM mTLS (`X25519MLKEM768`) transport security in gRPC. |
| [#296](https://github.com/lowRISC/opentitan-provisioning/issues/296) | *Add support for encrypting RMA token seeds with PQ algorithm* | `src/spm`, `crypto/hpke` | **Closed** | Tracked and delivered Two-Layer Hybrid HPKE (ML-KEM-768 + ECDH P-256) RMA token wrapping. |
| [#308](https://github.com/lowRISC/opentitan-provisioning/issues/308) | *Re-enable hardware HSM CI tests* | HSM Infrastructure / CI | **Open** | Tracks integration testing and qualification of physical Hardware HSMs for PQC algorithms. |
| [#300](https://github.com/lowRISC/opentitan-provisioning/issues/300) | *Parameterize the DistinguishedName (DN) fields in the Root CA certificates* | `rules/scripts/hsm_ca_sign.sh` | **Closed** | Parameterized Root CA DNs (`OTPROV_CA_ROOT_*`) for Silicon Manufacturer key ceremonies. |
| [#299](https://github.com/lowRISC/opentitan-provisioning/issues/299) | *parameterize cert expiry in hsm_ca_sign.sh* | `rules/scripts/hsm_ca_sign.sh` | **Open** | Tracks certificate validity period customization in key ceremony generation scripts. |
| [#301](https://github.com/lowRISC/opentitan-provisioning/issues/301) | *Remove @lowrisc_opentitan_head//sw/host/hsmtool* | Toolchain / Bazel | **Open** | Hermetic cleanup of Bazel rules and hsmtool binary dependencies. |
| [#283](https://github.com/lowRISC/opentitan-provisioning/issues/283) | *Complete WORKSPACE to bzlmod migration* | Toolchain / Bazel | **Closed** | Enabled Bzlmod toolchains and Go 1.26 for native HPKE / ML-KEM support. |
| [#272](https://github.com/lowRISC/opentitan-provisioning/issues/272) | *[spm] Improve service performance by caching object UIDs* | `src/spm` Performance | **Open** | Caching PKCS#11 object handles to optimize ML-DSA signing throughput on ATE lines. |
| [#183](https://github.com/lowRISC/opentitan-provisioning/issues/183) | *[ate] Add OpenTitan perso_tlv_data.h as an external dependency* | `src/ate`, Perso Blob V2 | **Open** | Alignment of V2 perso blob headers (32-bit headers) between ATE and silicon firmware. |
| [#145](https://github.com/lowRISC/opentitan-provisioning/issues/145) | *potential overflow in function TokensCopy in file ate_dll.cc* | `src/ate/ate_dll.cc` | **Closed** | Historical buffer sizing issue in `ate_dll.cc` related to wrapped token seed copy limits. |
| [#111](https://github.com/lowRISC/opentitan-provisioning/issues/111) | *[doc] document how to run integration tests with Thales Luna HSM* | HSM Documentation | **Closed** | Reference documentation for executing integration tests against Thales Luna HSMs. |
---
## 7. Summary Checklist & Implementation Matrix
| Task ID | Task Description | Target File(s) / Subsystem | Related Issue | Responsible Team | Status |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **TASK-1** | Add ML-DSA Enums & Structs to C API | `src/ate/ate_api.h` | [#286](https://github.com/lowRISC/opentitan-provisioning/issues/286) | SWE / Architecture | **Action Required** |
| **TASK-2** | Implement ML-DSA in `EndorseCerts()` | `src/ate/ate_dll.cc` | [#286](https://github.com/lowRISC/opentitan-provisioning/issues/286) | SWE / Provisioning | **Action Required** |
| **TASK-3** | Expand `kWrappedSeedMaxSize` to 2048B | `src/ate/ate_api.h`, `ate_dll.cc` | [#296](https://github.com/lowRISC/opentitan-provisioning/issues/296), [#145](https://github.com/lowRISC/opentitan-provisioning/issues/145) | SWE / Provisioning | **Action Required** |
| **TASK-4** | Support ML-DSA Labels in `GetCaCerts()` | `src/ate/ate_dll.cc` | [#286](https://github.com/lowRISC/opentitan-provisioning/issues/286) | SWE / Provisioning | **Action Required** |
| **TASK-5** | Expose Runtime ML-KEM Flags in `AteClient`| `src/ate/ate_client.cc`, `ate_api.h` | [#285](https://github.com/lowRISC/opentitan-provisioning/issues/285) | SWE / Transport | **Action Required** |
| **TASK-6** | Update `ft.cc` for `sival_pqc` Reference Flow | `src/ate/test_programs/ft.cc` | [#286](https://github.com/lowRISC/opentitan-provisioning/issues/286), [#296](https://github.com/lowRISC/opentitan-provisioning/issues/296) | SWE / Test Eng | **Action Required** |
| **TASK-7** | Hardware HSM Production Qualification | HSM Infra / `hsm_ca_sign.sh` | [#308](https://github.com/lowRISC/opentitan-provisioning/issues/308), [#111](https://github.com/lowRISC/opentitan-provisioning/issues/111) | Silicon Manufacturer IT / Sec | Pre-Production |
Contributor guide
Assessment
This issue has not been assessed yet.