Skip to main content

ic_cipher/
lib.rs

1//! # ic-cipher — block ciphers, stream ciphers, and AEADs
2//!
3//! Pure-Rust, `no_std`, dependency-free implementations of AES (FIPS 197),
4//! the SP 800-38A confidentiality modes, AES-GCM (SP 800-38D), and the
5//! RFC 8439 ChaCha20-Poly1305 suite.
6//!
7//! ```
8//! use ic_cipher::Aes256Gcm;
9//! use ic_core::traits::Aead;
10//!
11//! let cipher = Aes256Gcm::new(&[0x2a; 32])?;
12//! let mut buf = *b"ship it";
13//! let mut tag = [0u8; 16];
14//! cipher.seal_detached(&[0u8; 12], b"context", &mut buf, &mut tag)?;
15//! cipher.open_detached(&[0u8; 12], b"context", &mut buf, &tag)?;
16//! assert_eq!(&buf, b"ship it");
17//! # Ok::<(), ic_core::Error>(())
18//! ```
19//!
20//! ## Backend status
21//!
22//! AES computes its S-box algebraically and GHASH multiplies without tables, so
23//! neither touches a key-dependent memory address — the cache-timing channel
24//! that table-driven AES leaves open is closed by construction.
25//!
26//! Three backends sit behind the same traits, chosen by the CPU and never by
27//! key material: AES-NI with PCLMULQDQ on x86-64, the ARMv8 crypto extensions
28//! behind a feature, and a portable one everywhere else. The portable AES path
29//! is bitsliced for encryption — four blocks at a time in transposed form, at
30//! roughly the rate of RustCrypto's fixsliced implementation. Decryption is
31//! not bitsliced and runs a byte at a time, which is correct and slow; the
32//! modes that move volume (CTR, GCM, GCM-SIV) only encrypt.
33//!
34//! `ic_ontology::runtime::backend()` reports which one is active, so an agent
35//! can decide whether a workload belongs here.
36#![cfg_attr(not(feature = "std"), no_std)]
37#![deny(missing_docs)]
38// Every unsafe operation inside an unsafe fn must be marked explicitly, so the
39// SIMD backends cannot smuggle one in under the function signature.
40#![forbid(unsafe_op_in_unsafe_fn)]
41// And unsafe may only appear where a CPU intrinsic is being called, which is
42// what the allowances below mark. Everywhere else in this crate -- the modes,
43// the key wrapping, the field arithmetic -- it is a compile error.
44#![deny(unsafe_code)]
45#![warn(clippy::all)]
46
47// AES-NI and the ARMv8 crypto extensions, behind runtime detection.
48#[allow(unsafe_code)]
49pub mod aes;
50
51// AVX2 for the ChaCha20 keystream, behind runtime detection.
52#[allow(unsafe_code)]
53pub mod chacha;
54#[cfg(all(target_arch = "x86_64", feature = "std"))]
55// The carry-less multiply instruction.
56#[allow(unsafe_code)]
57mod clmul;
58// GHASH via CLMUL when the CPU has it.
59#[allow(unsafe_code)]
60pub mod gcm;
61pub mod gcm_siv;
62pub mod gf;
63pub mod keywrap;
64pub mod modes;
65pub mod polyval;
66pub mod shamir;
67
68pub use aes::{Aes128, Aes192, Aes256};
69pub use chacha::{chacha20_xor, ChaCha20Poly1305, Poly1305};
70pub use gcm::{Aes128Gcm, Aes192Gcm, Aes256Gcm, GcmLimits};
71pub use gcm_siv::{Aes128GcmSiv, Aes256GcmSiv};
72pub use keywrap::{Aes128Kw, Aes128Kwp, Aes192Kw, Aes192Kwp, Aes256Kw, Aes256Kwp};
73pub use modes::{cbc_decrypt, cbc_encrypt, ctr_xor, pkcs7_pad, pkcs7_unpad};
74
75/// Ontology identifiers for the AEADs this crate provides.
76pub const AEAD_IDS: &[&str] = &[
77    "aes-128-gcm",
78    "aes-192-gcm",
79    "aes-256-gcm",
80    "chacha20-poly1305",
81];
82
83/// Ontology identifiers for the raw block ciphers this crate provides.
84pub const BLOCK_CIPHER_IDS: &[&str] = &["aes-128", "aes-192", "aes-256"];