Metadata-Version: 2.4
Name: swtpm_cert_manager
Version: 0.3.0
Summary: A comprehensive tool for analyzing and manipulating SWTPM state files to manage TPM certificates
Home-page: https://github.com/sergio-correia/swtpm-cert-manager
Author: Sergio Correia
Author-email: Sergio Correia <scorreia@redhat.com>
Maintainer-email: Sergio Correia <scorreia@redhat.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/sergio-correia/swtpm-cert-manager
Project-URL: Bug Reports, https://github.com/sergio-correia/swtpm-cert-manager/issues
Project-URL: Source, https://github.com/sergio-correia/swtpm-cert-manager
Project-URL: Documentation, https://github.com/sergio-correia/swtpm-cert-manager#readme
Keywords: tpm,swtpm,certificates,x509,cryptography,testing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: System :: Hardware
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=3.4.8
Requires-Dist: pyasn1>=0.4.8
Requires-Dist: pyasn1-modules>=0.2.8
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov>=2.0; extra == "dev"
Requires-Dist: coverage>=6.0; extra == "dev"
Requires-Dist: ruff>=0.11; extra == "dev"
Requires-Dist: ty; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"
Provides-Extra: all
Requires-Dist: swtpm_cert_manager[dev]; extra == "all"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# SWTPM Certificate Manager

A tool for generating intentionally malformed TPM EK certificates for
testing certificate validation in [Keylime](https://keylime.dev/) and
other TPM-based attestation systems.

## Problem

Real-world TPM EK certificates from vendors like Nuvoton and
STMicroelectronics contain DER encoding issues that strict X.509
parsers reject. Python's `cryptography` library (v35+) rejects these
with errors like `InvalidSetOrdering` or `ExtraData`, while OpenSSL
accepts them. Keylime needs to handle both paths -- this tool generates
test certificates that reproduce these vendor-specific malformations.

## Malformation Types

| Type | Vendor | Description |
|------|--------|-------------|
| `invalid-set-ordering` | Nuvoton | DN SET attributes in non-canonical DER order |
| `extra-data` | STMicro | 0xFF NV RAM padding after the DER SEQUENCE |
| `none` | -- | Valid certificate (for positive testing) |

## Installation

```bash
pip install .
# or in development mode:
pip install -e ".[dev]"
```

On Fedora/RHEL via COPR:

```bash
dnf copr enable scorreia/keylime
dnf install swtpm-cert-manager
```

### Requirements

- Python >= 3.9
- `cryptography` >= 3.4.8
- OpenSSL (for verification)

## Usage

### Generate Malformed Certificates

The primary use is as a `create_certs_tool` for `swtpm_setup`:

```bash
swtpm_setup --tpm2 --tpmstate /tmp/tpm-state \
    --config /usr/share/swtpm-cert-manager/swtpm_setup_malformed.conf \
    --createek --create-ek-cert --create-platform-cert --overwrite
```

Direct CLI usage:

```bash
# Generate with InvalidSetOrdering (default)
swtpm-cert-malformed --type ek --ek <hex-public-key> --dir /tmp/certs \
    --signkey /var/lib/swtpm-localca/signkey.pem \
    --issuercert /var/lib/swtpm-localca/issuercert.pem

# Generate with ExtraData padding
swtpm-cert-malformed --type ek --ek <hex-public-key> --dir /tmp/certs \
    --malformation extra-data

# Generate a valid (non-malformed) certificate
swtpm-cert-malformed --type ek --ek <hex-public-key> --dir /tmp/certs \
    --malformation none

# Enable debug output
swtpm-cert-malformed --type ek --ek <hex-public-key> --dir /tmp/certs \
    --verbose
```

### Validate Certificates

Check that a certificate has the expected malformation properties:

```bash
# Validate InvalidSetOrdering cert
swtpm-cert-validate cert.der \
    --ca-cert /var/lib/swtpm-localca/issuercert.pem \
    --malformation invalid-set-ordering

# Validate ExtraData cert
swtpm-cert-validate cert.der --malformation extra-data

# Validate a correct cert
swtpm-cert-validate cert.der --malformation none
```

The validator checks:
1. `python-cryptography` rejects (or accepts) the cert as expected
2. OpenSSL can parse the cert
3. OpenSSL can verify the signature chain (if `--ca-cert` is provided)

### Python API

```python
from swtpm_cert_manager import (
    build_ek_certificate,
    inject_invalid_set_ordering,
    inject_extra_data,
    validate_cert,
)
from cryptography.hazmat.primitives.asymmetric import rsa

# Load CA key
from swtpm_cert_manager.certificate_utils import load_swtpm_private_key
ca_key = load_swtpm_private_key("/var/lib/swtpm-localca/signkey.pem")

# Generate a TPM public key (or use the real one from swtpm_setup)
pub_key = rsa.generate_private_key(65537, 2048).public_key()

# Build a valid certificate
cert_der = build_ek_certificate(
    "/var/lib/swtpm-localca/issuercert.pem",
    ca_key, pub_key, serial=1, key_type="rsa",
)

# Inject a malformation
malformed = inject_invalid_set_ordering(cert_der, ca_key)
# or: malformed = inject_extra_data(cert_der)

# Validate
validate_cert("cert.der", ca_cert_path="/path/to/ca.pem",
              malformation="invalid-set-ordering")
```

## How It Works

1. **Build** a valid X.509 EK certificate from scratch using
   `cryptography.x509.CertificateBuilder` with a multi-valued RDN
   (single SET with CN+O+C attributes)
2. **Inject** the selected malformation into the DER bytes:
   - `InvalidSetOrdering`: reverse the ATV order within the subject
     DN's SET, then re-sign with the CA key
   - `ExtraData`: append 0xFF padding bytes after the SEQUENCE
3. The result is a certificate that OpenSSL accepts but
   `python-cryptography` rejects with the specific vendor error

## Keylime Integration

This tool is used by Keylime's integration tests to verify that
Keylime correctly handles TPM EK certificates with DER encoding
issues. The test infrastructure:

1. Installs `swtpm-cert-manager` via RPM
2. Configures `swtpm_setup` to use `swtpm-cert-malformed` as the
   `create_certs_tool`
3. Creates a TPM emulator with a malformed EK certificate
4. Runs attestation tests verifying Keylime's `ek-openssl-verify`
   fallback script handles the malformed cert correctly

See the `examples/swtpm_setup_malformed.conf` for the swtpm_setup
configuration.

## Development

```bash
# Install in development mode
pip install -e ".[dev]"

# Run tests
make test

# Run linting and type checking
make lint
make type-check

# Run all quality checks
make all-checks

# Format code
make format
```

### Pre-commit Hooks

```bash
pre-commit install
pre-commit run --all-files
```

## License

MIT
