tee_crypto 0.1.4

TEE Crypto Crate.
Documentation
# tee_crypto Design

`tee_crypto` is the Rust cryptographic abstraction layer used by the TEE
stack. It replaces the former mbedtls dependency for TA-facing crypto and
big-number operations while keeping the crate usable in `no_std` kernel and
TA builds.

## Goals

- Provide stable, typed Rust APIs for the algorithms required by `rust-libutee`
  and TEE tests.
- Keep backend dependencies behind small wrapper modules so callers do not
  depend directly on RustCrypto implementation details.
- Preserve `no_std` operation with `alloc` where algorithm outputs require
  owned buffers.
- Provide integration tests from the crate root `tests/` directory so the
  public API is exercised like an external user.

## Module Layout

- `algorithms`: private source directory for cryptographic algorithms and
  primitive wrappers. Callers should use the crate-root public modules listed
  below, such as `tee_crypto::hash`, `tee_crypto::rsa`, and
  `tee_crypto::tee_ops`.
- `aead`: one-shot AEAD APIs for GCM and CCM.
- `block_cipher`: single-block ECB wrappers and static block-cipher metadata.
- `cipher`: one-shot CBC and CTR helpers.
- `ecc`: object-style ECC keypair API.
- `tee_ops::ecc`: stateless TEE-style ECC operations over raw key material,
  including typed byte-component return values. Sign and verify APIs accept
  `DigestBytes` rather than untagged byte slices.
- `hash`: digest wrappers plus `HashAlgorithm` / `HashSpec`
  metadata shared by RSA and ECC selectors. `Digest::finalize()` returns
  `DigestBytes`, which carries both digest bytes and the producing algorithm.
- `md5`: MD5 digest wrapper backed by RustCrypto. It lives outside `hash`
  because it exists for TEE compatibility and should remain visibly separate
  from the preferred hash family wrappers.
- `hkdf`: HKDF extract, expand, and one-shot helpers.
- `mac`: HMAC and CMAC wrappers.
- `material`: algorithm-tagged signatures, ciphertexts, and shared secrets
  used by asymmetric operations.
- `rsa`: object-style RSA keypair/public-key API.
- `tee_ops::rsa`: stateless TEE-style RSA operations over raw key material,
  encodings, hashes, and padding selectors. Sign and verify APIs accept
  `DigestBytes` rather than untagged byte slices.
- `sm2`: object-style SM2 DSA, PKE, and KEP wrappers.
- `asymmetric`: shared asymmetric traits and algorithm-neutral types. It is a
  common API contract, so it stays outside `algorithms`.
- `bytes`: base public, big-endian, secret, and plaintext byte containers.
  Algorithm-tagged asymmetric material lives in `material`; hash output lives
  in `hash`.
- `bignum`: signed and unsigned big-number wrappers backed by `crypto-bigint`.
  This is the TEE arithmetic/MPI compatibility layer, so it stays outside
  `algorithms`.
- `rng`: RNG abstraction aligned with `rand_core` crypto RNG traits. It is a
  provider interface, so it stays outside `algorithms`.
- `streaming_cipher`: mbedtls-like update/final context for block, stream,
  and AEAD algorithms. It is a state-machine compatibility layer and therefore
  stays outside `algorithms`.
- `tee_ops`: operation-level APIs shaped around TEE object attributes and raw
  operation entry points. These functions expose tee_crypto wrapper types,
  typed byte containers, and component structs rather than backend crate key
  types.
- `xts`: XTS mode wrappers for AES and SM4.

Single-file algorithms stay as files under `src/algorithms/` to keep the tree
compact. Directories are reserved for modules with real internal structure,
currently root-level `src/bignum`.

The module root files expose object-style or one-shot Rust APIs. The
`tee_ops` files expose raw stateless operations that are easier for
`rust-libutee` and TEE object attributes to call.

## Semantic Byte Types

Byte buffers that cross public crypto APIs are tagged by purpose:

- `PublicBytes` and `BigEndianBytes` carry public byte strings and integer
  encodings.
- `SecretBytes` and `PlaintextBytes` zeroize owned secret buffers on drop and
  expose secret material only through `expose_secret()` /
  `expose_secret_clone()`. They intentionally do not implement `Deref` or
  `AsRef<[u8]>`, so secret reads remain visible during review.
- `SignatureBytes` records both the signature algorithm and encoding.
- `CiphertextBytes` records the encryption algorithm that produced the
  ciphertext.
- `SharedSecretBytes` records the key-agreement algorithm and zeroizes owned
  shared-secret material on drop. It follows the same explicit
  `expose_secret()` policy as `SecretBytes`.
- `DigestBytes` records the hash algorithm that produced a digest.

This keeps algorithm metadata at the API boundary instead of relying on tuple
position, comments, or caller discipline. `SignatureBytes`,
`CiphertextBytes`, and `SharedSecretBytes` live in `material` because their
algorithm tags are asymmetric-operation contracts. `DigestBytes` lives in
`hash` because it is tied to `HashAlgorithm`. Untagged `Vec<u8>` is still
allowed for external boundary input, raw mathematical results, DER/PKCS blobs,
and backend glue where the byte meaning is already fixed by the enclosing
function.

## Asymmetric API Contracts

Object-style `Signer` / `Verifier` implementations take messages and perform
the algorithm's normal message-signing flow internally.

TEE-style `tee_ops::rsa`, `tee_ops::ecc`, and SM2 raw DSA helpers operate on
precomputed digests. Those functions require `DigestBytes` and verify that the
digest algorithm and output length match the requested hash selector before
calling the backend.

RSA operation APIs expose `RsaKeypair`, `RsaPublic`, or component structs.
Backend-native `rsa::RsaPrivateKey` and `rsa::RsaPublicKey` stay inside
tee_crypto wrappers and are only available to crate-internal glue.

Public key components are strongly typed:

- `RsaPublicComponents` holds modulus `n` and exponent `e`.
- `EccPublicPoint` holds a curve plus affine coordinates.
- `Sm2PublicPoint` holds SM2 affine coordinates.

Callers use accessors such as `point.x()` and `public.n()` rather than matching
field names on a large algorithm-neutral enum.

TEE boundary code is responsible for turning raw input buffers into these
semantic types. Kernel-side helpers in the TEE crypto layer centralize
conversion from TEE algorithm IDs to `DigestBytes`, `SignatureBytes`, and
`CiphertextBytes`.

## Streaming Cipher

`streaming_cipher` is split into:

- `algo.rs`: `StreamingCipherAlgo`, `AlgorithmSpec`, and padding mode metadata.
- `context.rs`: `StreamingCipherCtx` state fields and public state-machine
  methods.
- `mode/`: mode-specific dispatch and processing for block modes, CTR, and
  AEAD.
- `padding.rs`: shared PKCS#7 padding helpers.

The context buffers partial blocks for ECB/CBC, processes CTR immediately, and
uses a single facade for GCM/CCM to match the mbedtls-style operation API used
by existing TEE code.

`StreamingCipherCtx` constructors take a `Direction` enum instead of a boolean
flag. This keeps encrypt/decrypt polarity explicit at call sites and inside
mode dispatch.

## Error Model

All public APIs return `Result<T, CryptoError>` unless they are pure metadata
queries. `CryptoError` uses stable variants such as `InvalidKey`,
`InvalidLength`, `BufferTooSmall`, `InvalidModulus`, and `VerificationFailed`.
Backend failures are represented by `CryptoError::Backend(BackendError)`
instead of formatted strings so higher layers can map errors consistently.

## Algorithm Metadata

Simple wrapper families use declaration macros where the algorithm is mainly a
backend type plus static metadata. For example, `block_cipher` uses one macro
to declare the wrapper type, trait implementation, and `BlockCipherSpec`.

Hash selection uses `HashAlgorithm` and `HashSpec` as the shared metadata
layer. RSA and ECC keep their legacy selector enums for source compatibility,
but expose conversions to the shared selector so future TEE algorithm-id
mapping can be centralized.

More complex algorithms such as RSA, ECC, and SM2 keep explicit code paths
because key formats, padding, hash selection, and backend error handling carry
different semantics.

## Tests

All crate-level tests live in `tee/tee_crypto/tests/` as Cargo integration
tests. They import `tee_crypto` through public APIs, which prevents tests from
accidentally depending on private implementation details.

Shared test helpers live under `tests/common/`. Each integration test compiles
as an independent crate, so helper functions should stay small and tolerate
being used by only a subset of test targets.

## x-kernel integration

The kernel workspace lists `tee/tee_crypto` as a **workspace member** so
developers can run `cargo test -p tee_crypto` and `cargo publish -p tee_crypto`
from the repository root. Runtime dependencies (`tee_kernel`, `devfs`, …) still
resolve **`tee_crypto` from crates.io** via `[workspace.dependencies]`:

```toml
tee_crypto = { version = "0.1", default-features = false }
```

There is no `path = "tee/tee_crypto"` in workspace dependencies, so member
crates do not link the in-tree copy unless patched.

### Standalone crate tests (default for `tee_crypto` changes)

```bash
# from repo root
cargo test -p tee_crypto
cargo test -p tee_crypto --features "pkix,pkix-internal-tests" --lib
cargo test -p tee_crypto --features pkix --test pkix_anchor_nc
cargo test -p tee_crypto --features pkix --test pkix_stitch

# or from the crate directory
cd tee/tee_crypto && cargo test ...
```

See `docs/pkix.md` for PKIX-specific commands.

### Publish to crates.io

```bash
cargo publish -p tee_crypto --registry crates-io --dry-run
```

Run from the **workspace root** (`x-kernel/`), not only from `tee/tee_crypto/`.

### Kernel build against local `tee/tee_crypto`

To exercise in-tree changes through `make build`, `make clippy`, or `make run`,
temporarily add to the **repository root** `Cargo.toml`:

```toml
[patch.crates-io]
tee_crypto = { path = "tee/tee_crypto" }
```

Remove the `[patch.crates-io]` block before merge unless the release intent is
to ship unpublished `tee_crypto` APIs. After publishing a new crates.io
release, bump the workspace `version = "0.1"` constraint only when the kernel
must depend on that release (Cargo resolves the latest compatible `0.1.x`).