1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Crrl is a Rust library for cryptographic research.
//!
//! This library implements computations in some finite fields and
//! elliptic curves. It aims at providing efficient and secure
//! (constant-time) implementations, but with portable code, and with a
//! convenient API so that scalars, curve points, and other field
//! elements may be used in straightforward expressions with normal
//! arihtmetic operators.
//!
//! Finite fields are implemented through some customizable types defined
//! in `backend` (a 32-bit and a 64-bit backends are provided, the "right
//! one" is automatically selected, unless overridden by a compile-time
//! feature). The types may support several distinct moduli, chosen
//! through compile-time type parameter.
//!
//! Curve edwards25519 is implemented in the `ed25519` module. The
//! specialized X25519 function is in `x25519`. The prime-order group
//! ristretto255 (internally based on edwards25519) is defined in the
//! `ristretto255` module. NIST curve P-256 (aka "secp256r1" and
//! "prime256v1") is implemented in the `p256` module (with the ECDSA
//! signature algorithm). Double-odd curves jq255e and jq255s are
//! implemented by `jq255e` and `jq255s`, respectively (including
//! signature and key exchange schemes). Secp256k1 is implemented in
//! `secp256k1`. Edwards448 is in `ed448`, while the specialized X448
//! function is in `x448`. The prime-order decaf448 group is implemented
//! in `decaf448`.
//!
//! # Usage
//!
//! The library is "mostly `no_std`". By default, it compiles against the
//! standard library. It can be compiled in `no_std` mode, in which case
//! all functionality is still available, except verification of truncated
//! ECDSA signatures with curve P-256.
//!
//! # Conventions
//!
//! All implemented functions should be strictly constant-time, unless
//! explicitly documented otherwise (non-constant-time functions normally
//! have "vartime" in their name). In order to avoid unwanted side-channel
//! leaks, Booleans are avoided (compilers tend to "optimize" things a bit
//! too eagerly when handling `bool` values). All functions that return or
//! use a potentially secret Boolean value use the `u32` type; the convention
//! is that 0xFFFFFFFF means "true", and 0x00000000 means "false". No other
//! value shall be used, for they would lead to unpredictable results.
//! Similarly, the `Eq` or `PartialEq` traits are not implemented.
//!
//! Algebraic operations on field elements and curve points are performed
//! with the usual operators (e.g. `+`); appropriate traits are defined
//! so that structure types and pointers to structure types can be used
//! more or less interchangeably. Throughout the code, functions that
//! modify the object on which they are called tend to have a name in
//! `set_*()` (e.g. for a curve point `P`, if we want to compute the
//! double of that point, then `P.set_double()` modifies the point
//! structure in place, while `P.double()` leaves `P` unmodified and
//! returns the double as a new structure instance).
//!
//! # Truncated Signatures
//!
//! Apart from standard support for curve operations and signature
//! algorithms, _truncated signatures_ are implemented for both Ed25519
//! (Schnorr signatures over edwards25519) and ECDSA (over P-256). A
//! truncated signature is a shrunk version, by up to 32 bits, of a
//! normal signature; the verification process is then more expensive,
//! though not necessarily intolerably expensive, depending on usage
//! context (the most expensive verification function is for ECDSA on
//! P-256, with maximal 32-bit truncation; in that case, verification
//! cost can be up to about 0.65 seconds on a 500 MHz ARM Cortex A53; but
//! Ed25519 signatures with 32-bit truncation can be verified in less
//! than 0.05 seconds on the same hardware). Signature truncation can be
//! useful in situations with strong I/O constraints, where every data
//! bit counts, but where use of fully standard Ed25519 or ECDSA
//! signature generators is made mandatory because of some regulatory or
//! physical constraints of the signing hardware.
//! 
//! # Performance
//!
//! On an Intel i5-8259U CPU (Coffee Lake core), Ed25519 signatures have
//! been benchmarked at about 51600 cycles for signing, 111000 cycles for
//! verification; these are not bad values, and are competitive or at
//! least within 30% of performance obtained from assembly-optimized
//! implementations on the same hardware. For P-256, signing time is
//! about 125000 cycles, verification is 256000 cycles. For the jq255e
//! curve, signatures are generated in about 54700 cycles, and verified
//! in only 82800 cycles (56200 and 86800, respectively, for jq255s).
//! These figures have been obtained by compiling with Rust 1.59 in
//! release mode, with the flags `-C target-cpu=native`.
//!
//! On an ARM Cortex A53 (RaspberryPi Model 3B), Ed25519 signing was
//! measured at 213000 cycles, verification at 479000 cycles; for P-256,
//! the figures were 389000 and 991000, respectively. With jq255e,
//! signature generation and verification use 241000 and 358000 cycles,
//! respectively (248000 and 369000 for jq255s).
//!
//! No inline assembly is used. On x86-64 architectures, the
//! `_addcarry_u64()` and `_subborrow_u64()` intrinsics are used
//! (from `core::arch::x86_64`); however, plain implementations with
//! no intrinsics are available (and used on, for instance, aarch64).

#![no_std]

#[cfg(all(feature = "alloc", not(feature = "std")))]
#[macro_use]
#[allow(unused_imports)]
extern crate alloc;

#[cfg(feature = "std")]
#[macro_use]
#[allow(unused_imports)]
extern crate std;

#[cfg(all(feature = "alloc", not(feature = "std")))]
#[allow(unused_imports)]
pub(crate) use alloc::vec::Vec;

#[cfg(feature = "std")]
#[allow(unused_imports)]
pub(crate) use std::vec::Vec;

/// The `rand_core` types are re-exported so that users of crrl do not
/// have to worry about using the exact correct version of `rand_core`.
pub use rand_core::{CryptoRng, RngCore, Error as RngError};

#[allow(unused_macros)]
macro_rules! static_assert {
    ($condition:expr) => {
        let _ = &[()][1 - ($condition) as usize];
    }
}

pub mod backend;
pub mod field;

#[cfg(feature = "ed25519")]
pub mod ed25519;

#[cfg(feature = "x25519")]
pub mod x25519;

#[cfg(feature = "ristretto255")]
pub mod ristretto255;

#[cfg(feature = "jq255e")]
pub mod jq255e;

#[cfg(feature = "jq255s")]
pub mod jq255s;

#[cfg(feature = "p256")]
pub mod p256;

#[cfg(feature = "secp256k1")]
pub mod secp256k1;

#[cfg(feature = "ed448")]
pub mod ed448;

#[cfg(feature = "x448")]
pub mod x448;

#[cfg(feature = "decaf448")]
pub mod decaf448;

#[cfg(all(feature = "alloc", feature = "frost"))]
pub mod frost;

#[cfg(feature = "lms")]
pub mod lms;