Use stable rustfmt.
This commit is contained in:
parent
9f211157a8
commit
f0d4d21e85
71
build.rs
71
build.rs
@ -335,10 +335,18 @@ struct Target {
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn arch(&self) -> &str { &self.arch }
|
||||
pub fn os(&self) -> &str { &self.os }
|
||||
pub fn env(&self) -> &str { &self.env }
|
||||
pub fn is_debug(&self) -> bool { self.is_debug }
|
||||
pub fn arch(&self) -> &str {
|
||||
&self.arch
|
||||
}
|
||||
pub fn os(&self) -> &str {
|
||||
&self.os
|
||||
}
|
||||
pub fn env(&self) -> &str {
|
||||
&self.env
|
||||
}
|
||||
pub fn is_debug(&self) -> bool {
|
||||
self.is_debug
|
||||
}
|
||||
}
|
||||
|
||||
fn build_c_code(target: &Target, pregenerated: PathBuf, out_dir: &Path) {
|
||||
@ -440,8 +448,13 @@ fn build_c_code(target: &Target, pregenerated: PathBuf, out_dir: &Path) {
|
||||
}
|
||||
|
||||
fn build_library(
|
||||
target: &Target, out_dir: &Path, lib_name: &str, srcs: &[PathBuf], additional_srcs: &[PathBuf],
|
||||
warnings_are_errors: bool, includes_modified: SystemTime,
|
||||
target: &Target,
|
||||
out_dir: &Path,
|
||||
lib_name: &str,
|
||||
srcs: &[PathBuf],
|
||||
additional_srcs: &[PathBuf],
|
||||
warnings_are_errors: bool,
|
||||
includes_modified: SystemTime,
|
||||
) {
|
||||
// Compile all the (dirty) source files into object files.
|
||||
let objs = additional_srcs
|
||||
@ -468,10 +481,10 @@ fn build_library(
|
||||
"macos" => {
|
||||
let _ = c.flag("-fPIC");
|
||||
let _ = c.flag("-Wl,-dead_strip");
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
let _ = c.flag("-Wl,--gc-sections".into());
|
||||
},
|
||||
}
|
||||
}
|
||||
for o in objs {
|
||||
let _ = c.object(o);
|
||||
@ -494,7 +507,10 @@ fn build_library(
|
||||
}
|
||||
|
||||
fn compile(
|
||||
p: &Path, target: &Target, warnings_are_errors: bool, out_dir: &Path,
|
||||
p: &Path,
|
||||
target: &Target,
|
||||
warnings_are_errors: bool,
|
||||
out_dir: &Path,
|
||||
includes_modified: SystemTime,
|
||||
) -> String {
|
||||
let ext = p.extension().unwrap().to_str().unwrap();
|
||||
@ -523,15 +539,20 @@ fn obj_path(out_dir: &Path, src: &Path, obj_ext: &str) -> PathBuf {
|
||||
}
|
||||
|
||||
fn cc(
|
||||
file: &Path, ext: &str, target: &Target, warnings_are_errors: bool, out_dir: &Path,
|
||||
file: &Path,
|
||||
ext: &str,
|
||||
target: &Target,
|
||||
warnings_are_errors: bool,
|
||||
out_dir: &Path,
|
||||
) -> Command {
|
||||
let mut c = cc::Build::new();
|
||||
let _ = c.include("include");
|
||||
match ext {
|
||||
"c" =>
|
||||
"c" => {
|
||||
for f in c_flags(target) {
|
||||
let _ = c.flag(f);
|
||||
},
|
||||
}
|
||||
}
|
||||
"S" => (),
|
||||
e => panic!("Unsupported file extension: {:?}", e),
|
||||
};
|
||||
@ -546,11 +567,11 @@ fn cc(
|
||||
// ``-gfull`` is required for Darwin's |-dead_strip|.
|
||||
("macos", _) => {
|
||||
let _ = c.flag("-gfull");
|
||||
},
|
||||
}
|
||||
(_, "msvc") => (),
|
||||
_ => {
|
||||
let _ = c.flag("-g3");
|
||||
},
|
||||
}
|
||||
};
|
||||
if !target.is_debug() {
|
||||
let _ = c.define("NDEBUG", None);
|
||||
@ -646,7 +667,10 @@ fn sources_for_arch(arch: &str) -> Vec<PathBuf> {
|
||||
}
|
||||
|
||||
fn perlasm_src_dsts(
|
||||
out_dir: &Path, arch: &str, os: Option<&str>, perlasm_format: &str,
|
||||
out_dir: &Path,
|
||||
arch: &str,
|
||||
os: Option<&str>,
|
||||
perlasm_format: &str,
|
||||
) -> Vec<(PathBuf, PathBuf)> {
|
||||
let srcs = sources_for_arch(arch);
|
||||
let mut src_dsts = srcs
|
||||
@ -683,7 +707,9 @@ fn asm_srcs(perlasm_src_dsts: Vec<(PathBuf, PathBuf)>) -> Vec<PathBuf> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn is_perlasm(path: &PathBuf) -> bool { path.extension().unwrap().to_str().unwrap() == "pl" }
|
||||
fn is_perlasm(path: &PathBuf) -> bool {
|
||||
path.extension().unwrap().to_str().unwrap() == "pl"
|
||||
}
|
||||
|
||||
fn asm_path(out_dir: &Path, src: &Path, os: Option<&str>, perlasm_format: &str) -> PathBuf {
|
||||
let src_stem = src.file_stem().expect("source file without basename");
|
||||
@ -695,7 +721,9 @@ fn asm_path(out_dir: &Path, src: &Path, os: Option<&str>, perlasm_format: &str)
|
||||
}
|
||||
|
||||
fn perlasm(
|
||||
src_dst: &[(PathBuf, PathBuf)], arch: &str, perlasm_format: &str,
|
||||
src_dst: &[(PathBuf, PathBuf)],
|
||||
arch: &str,
|
||||
perlasm_format: &str,
|
||||
includes_modified: Option<SystemTime>,
|
||||
) {
|
||||
for (src, dst) in src_dst {
|
||||
@ -744,7 +772,9 @@ fn file_modified(path: &Path) -> SystemTime {
|
||||
.expect("nah")
|
||||
}
|
||||
|
||||
fn get_command(var: &str, default: &str) -> String { std::env::var(var).unwrap_or(default.into()) }
|
||||
fn get_command(var: &str, default: &str) -> String {
|
||||
std::env::var(var).unwrap_or(default.into())
|
||||
}
|
||||
|
||||
fn check_all_files_tracked() {
|
||||
for path in &["crypto", "include", "third_party/fiat"] {
|
||||
@ -757,8 +787,9 @@ fn is_tracked(file: &DirEntry) {
|
||||
let cmp = |f| p == PathBuf::from(f);
|
||||
let tracked = match p.extension().and_then(|p| p.to_str()) {
|
||||
Some("h") | Some("inl") => RING_INCLUDES.iter().any(cmp),
|
||||
Some("c") | Some("S") | Some("asm") =>
|
||||
RING_SRCS.iter().any(|(_, f)| cmp(f)) || RING_TEST_SRCS.iter().any(cmp),
|
||||
Some("c") | Some("S") | Some("asm") => {
|
||||
RING_SRCS.iter().any(|(_, f)| cmp(f)) || RING_TEST_SRCS.iter().any(cmp)
|
||||
}
|
||||
Some("pl") => RING_SRCS.iter().any(|(_, f)| cmp(f)) || RING_PERL_INCLUDES.iter().any(cmp),
|
||||
_ => true,
|
||||
};
|
||||
|
@ -1,13 +1,5 @@
|
||||
edition = "2018"
|
||||
fn_args_density = "Compressed"
|
||||
fn_single_line = true
|
||||
match_arm_blocks = false
|
||||
match_block_trailing_comma = true
|
||||
max_width = 100
|
||||
merge_imports = true
|
||||
newline_style = "Unix"
|
||||
reorder_imports = true
|
||||
trailing_comma = "Vertical"
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
||||
|
64
src/aead.rs
64
src/aead.rs
@ -54,7 +54,8 @@ impl OpeningKey {
|
||||
/// `key_bytes` must be exactly `algorithm.key_len` bytes long.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
algorithm: &'static Algorithm, key_bytes: &[u8],
|
||||
algorithm: &'static Algorithm,
|
||||
key_bytes: &[u8],
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Self {
|
||||
key: Key::new(algorithm, key_bytes)?,
|
||||
@ -63,7 +64,9 @@ impl OpeningKey {
|
||||
|
||||
/// The key's AEAD algorithm.
|
||||
#[inline(always)]
|
||||
pub fn algorithm(&self) -> &'static Algorithm { self.key.algorithm() }
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticates and decrypts (“opens”) data in place.
|
||||
@ -111,7 +114,10 @@ impl OpeningKey {
|
||||
/// does not allow us to have two slices, one mutable and one immutable, that
|
||||
/// reference overlapping memory.)
|
||||
pub fn open_in_place<'a, A: AsRef<[u8]>>(
|
||||
key: &OpeningKey, nonce: Nonce, Aad(aad): Aad<A>, in_prefix_len: usize,
|
||||
key: &OpeningKey,
|
||||
nonce: Nonce,
|
||||
Aad(aad): Aad<A>,
|
||||
in_prefix_len: usize,
|
||||
ciphertext_and_tag_modified_in_place: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], error::Unspecified> {
|
||||
open_in_place_(
|
||||
@ -124,7 +130,10 @@ pub fn open_in_place<'a, A: AsRef<[u8]>>(
|
||||
}
|
||||
|
||||
fn open_in_place_<'a>(
|
||||
key: &OpeningKey, nonce: Nonce, aad: Aad<&[u8]>, in_prefix_len: usize,
|
||||
key: &OpeningKey,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_prefix_len: usize,
|
||||
ciphertext_and_tag_modified_in_place: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], error::Unspecified> {
|
||||
let ciphertext_and_tag_len = ciphertext_and_tag_modified_in_place
|
||||
@ -178,7 +187,8 @@ impl SealingKey {
|
||||
/// Constructs a new sealing key from `key_bytes`.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
algorithm: &'static Algorithm, key_bytes: &[u8],
|
||||
algorithm: &'static Algorithm,
|
||||
key_bytes: &[u8],
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Self {
|
||||
key: Key::new(algorithm, key_bytes)?,
|
||||
@ -187,7 +197,9 @@ impl SealingKey {
|
||||
|
||||
/// The key's AEAD algorithm.
|
||||
#[inline(always)]
|
||||
pub fn algorithm(&self) -> &'static Algorithm { self.key.algorithm() }
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts and signs (“seals”) data in place.
|
||||
@ -208,7 +220,11 @@ impl SealingKey {
|
||||
///
|
||||
/// `aad` is the additional authenticated data, if any.
|
||||
pub fn seal_in_place<A: AsRef<[u8]>>(
|
||||
key: &SealingKey, nonce: Nonce, Aad(aad): Aad<A>, in_out: &mut [u8], out_suffix_capacity: usize,
|
||||
key: &SealingKey,
|
||||
nonce: Nonce,
|
||||
Aad(aad): Aad<A>,
|
||||
in_out: &mut [u8],
|
||||
out_suffix_capacity: usize,
|
||||
) -> Result<usize, error::Unspecified> {
|
||||
seal_in_place_(
|
||||
key,
|
||||
@ -220,7 +236,11 @@ pub fn seal_in_place<A: AsRef<[u8]>>(
|
||||
}
|
||||
|
||||
fn seal_in_place_(
|
||||
key: &SealingKey, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8], out_suffix_capacity: usize,
|
||||
key: &SealingKey,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_out: &mut [u8],
|
||||
out_suffix_capacity: usize,
|
||||
) -> Result<usize, error::Unspecified> {
|
||||
if out_suffix_capacity < key.key.algorithm.tag_len() {
|
||||
return Err(error::Unspecified);
|
||||
@ -248,12 +268,16 @@ pub struct Aad<A: AsRef<[u8]>>(A);
|
||||
impl<A: AsRef<[u8]>> Aad<A> {
|
||||
/// Construct the `Aad` from the given bytes.
|
||||
#[inline]
|
||||
pub fn from(aad: A) -> Self { Aad(aad) }
|
||||
pub fn from(aad: A) -> Self {
|
||||
Aad(aad)
|
||||
}
|
||||
}
|
||||
|
||||
impl Aad<[u8; 0]> {
|
||||
/// Construct an empty `Aad`.
|
||||
pub fn empty() -> Self { Self::from([]) }
|
||||
pub fn empty() -> Self {
|
||||
Self::from([])
|
||||
}
|
||||
}
|
||||
|
||||
/// `OpeningKey` and `SealingKey` are type-safety wrappers around `Key`, which
|
||||
@ -291,7 +315,9 @@ impl Key {
|
||||
|
||||
/// The key's AEAD algorithm.
|
||||
#[inline(always)]
|
||||
fn algorithm(&self) -> &'static Algorithm { self.algorithm }
|
||||
fn algorithm(&self) -> &'static Algorithm {
|
||||
self.algorithm
|
||||
}
|
||||
}
|
||||
|
||||
/// An AEAD Algorithm.
|
||||
@ -332,17 +358,23 @@ const fn max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u6
|
||||
impl Algorithm {
|
||||
/// The length of the key.
|
||||
#[inline(always)]
|
||||
pub fn key_len(&self) -> usize { self.key_len }
|
||||
pub fn key_len(&self) -> usize {
|
||||
self.key_len
|
||||
}
|
||||
|
||||
/// The length of a tag.
|
||||
///
|
||||
/// See also `MAX_TAG_LEN`.
|
||||
#[inline(always)]
|
||||
pub fn tag_len(&self) -> usize { TAG_LEN }
|
||||
pub fn tag_len(&self) -> usize {
|
||||
TAG_LEN
|
||||
}
|
||||
|
||||
/// The length of the nonces.
|
||||
#[inline(always)]
|
||||
pub fn nonce_len(&self) -> usize { NONCE_LEN }
|
||||
pub fn nonce_len(&self) -> usize {
|
||||
NONCE_LEN
|
||||
}
|
||||
}
|
||||
|
||||
derive_debug_via_id!(Algorithm);
|
||||
@ -355,7 +387,9 @@ enum AlgorithmID {
|
||||
}
|
||||
|
||||
impl PartialEq for Algorithm {
|
||||
fn eq(&self, other: &Self) -> bool { self.id == other.id }
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Algorithm {}
|
||||
|
@ -27,7 +27,9 @@ pub(crate) struct Key {
|
||||
impl Key {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
bytes: &[u8], variant: Variant, cpu_features: cpu::Features,
|
||||
bytes: &[u8],
|
||||
variant: Variant,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let key_bits = match variant {
|
||||
Variant::AES_128 => BitLength::from_usize_bits(128),
|
||||
@ -46,7 +48,9 @@ impl Key {
|
||||
Implementation::HWAES => {
|
||||
extern "C" {
|
||||
fn GFp_aes_hw_set_encrypt_key(
|
||||
user_key: *const u8, bits: libc::c_uint, key: &mut AES_KEY,
|
||||
user_key: *const u8,
|
||||
bits: libc::c_uint,
|
||||
key: &mut AES_KEY,
|
||||
) -> ZeroMeansSuccess;
|
||||
}
|
||||
Result::from(unsafe {
|
||||
@ -56,13 +60,15 @@ impl Key {
|
||||
&mut key,
|
||||
)
|
||||
})?;
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||
Implementation::VPAES => {
|
||||
extern "C" {
|
||||
fn GFp_vpaes_set_encrypt_key(
|
||||
user_key: *const u8, bits: libc::c_uint, key: &mut AES_KEY,
|
||||
user_key: *const u8,
|
||||
bits: libc::c_uint,
|
||||
key: &mut AES_KEY,
|
||||
) -> ZeroMeansSuccess;
|
||||
}
|
||||
Result::from(unsafe {
|
||||
@ -72,12 +78,14 @@ impl Key {
|
||||
&mut key,
|
||||
)
|
||||
})?;
|
||||
},
|
||||
}
|
||||
|
||||
_ => {
|
||||
extern "C" {
|
||||
fn GFp_aes_nohw_set_encrypt_key(
|
||||
user_key: *const u8, bits: libc::c_uint, key: &mut AES_KEY,
|
||||
user_key: *const u8,
|
||||
bits: libc::c_uint,
|
||||
key: &mut AES_KEY,
|
||||
) -> ZeroMeansSuccess;
|
||||
}
|
||||
Result::from(unsafe {
|
||||
@ -87,7 +95,7 @@ impl Key {
|
||||
&mut key,
|
||||
)
|
||||
})?;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@ -109,7 +117,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_aes_hw_encrypt(aliasing_const, aliasing_mut, &self.inner);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||
Implementation::VPAES => {
|
||||
@ -119,7 +127,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_vpaes_encrypt(aliasing_const, aliasing_mut, &self.inner);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_ => {
|
||||
extern "C" {
|
||||
@ -128,7 +136,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_aes_nohw_encrypt(aliasing_const, aliasing_mut, &self.inner);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
a
|
||||
@ -143,7 +151,10 @@ impl Key {
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ctr32_encrypt_blocks(
|
||||
&self, in_out: &mut [u8], direction: Direction, ctr: &mut Counter,
|
||||
&self,
|
||||
in_out: &mut [u8],
|
||||
direction: Direction,
|
||||
ctr: &mut Counter,
|
||||
) {
|
||||
let output: *mut u8 = in_out.as_mut_ptr();
|
||||
let in_prefix_len = match direction {
|
||||
@ -163,7 +174,10 @@ impl Key {
|
||||
Implementation::HWAES => {
|
||||
extern "C" {
|
||||
fn GFp_aes_hw_ctr32_encrypt_blocks(
|
||||
input: *const u8, output: *mut u8, blocks: size_t, key: &AES_KEY,
|
||||
input: *const u8,
|
||||
output: *mut u8,
|
||||
blocks: size_t,
|
||||
key: &AES_KEY,
|
||||
ivec: &Counter,
|
||||
);
|
||||
}
|
||||
@ -171,13 +185,16 @@ impl Key {
|
||||
GFp_aes_hw_ctr32_encrypt_blocks(input, output, blocks, &self.inner, ctr);
|
||||
}
|
||||
ctr.increment_by_less_safe(blocks_u32);
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
Implementation::BSAES => {
|
||||
extern "C" {
|
||||
fn GFp_bsaes_ctr32_encrypt_blocks(
|
||||
input: *const u8, output: *mut u8, blocks: size_t, key: &AES_KEY,
|
||||
input: *const u8,
|
||||
output: *mut u8,
|
||||
blocks: size_t,
|
||||
key: &AES_KEY,
|
||||
ivec: &Counter,
|
||||
);
|
||||
}
|
||||
@ -185,13 +202,13 @@ impl Key {
|
||||
GFp_bsaes_ctr32_encrypt_blocks(input, output, blocks, &self.inner, ctr);
|
||||
}
|
||||
ctr.increment_by_less_safe(blocks_u32);
|
||||
},
|
||||
}
|
||||
|
||||
_ => {
|
||||
shift::shift_full_blocks(in_out, in_prefix_len, |input| {
|
||||
self.encrypt_iv_xor_block(ctr.increment(), Block::from(input))
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +232,9 @@ impl Key {
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[must_use]
|
||||
pub(super) fn inner_less_safe(&self) -> &AES_KEY { &self.inner }
|
||||
pub(super) fn inner_less_safe(&self) -> &AES_KEY {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
// Keep this in sync with AES_KEY in aes.h.
|
||||
|
@ -52,7 +52,9 @@ fn init_256(key: &[u8], cpu_features: cpu::Features) -> Result<aead::KeyInner, e
|
||||
}
|
||||
|
||||
fn init(
|
||||
key: &[u8], variant: aes::Variant, cpu_features: cpu::Features,
|
||||
key: &[u8],
|
||||
variant: aes::Variant,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<aead::KeyInner, error::Unspecified> {
|
||||
let aes_key = aes::Key::new(key, variant, cpu_features)?;
|
||||
let gcm_key = gcm::Key::new(aes_key.encrypt_block(Block::zero()), cpu_features);
|
||||
@ -62,14 +64,21 @@ fn init(
|
||||
const CHUNK_BLOCKS: usize = 3 * 1024 / 16;
|
||||
|
||||
fn aes_gcm_seal(
|
||||
key: &aead::KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8],
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_out: &mut [u8],
|
||||
cpu_features: cpu::Features,
|
||||
) -> Tag {
|
||||
aead(key, nonce, aad, in_out, Direction::Sealing, cpu_features)
|
||||
}
|
||||
|
||||
fn aes_gcm_open(
|
||||
key: &aead::KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_prefix_len: usize, in_out: &mut [u8],
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_prefix_len: usize,
|
||||
in_out: &mut [u8],
|
||||
cpu_features: cpu::Features,
|
||||
) -> Tag {
|
||||
aead(
|
||||
@ -84,7 +93,11 @@ fn aes_gcm_open(
|
||||
|
||||
#[inline(always)] // Avoid branching on `direction`.
|
||||
fn aead(
|
||||
key: &aead::KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8], direction: Direction,
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_out: &mut [u8],
|
||||
direction: Direction,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Tag {
|
||||
let Key { aes_key, gcm_key } = match key {
|
||||
@ -185,8 +198,12 @@ fn aead(
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[inline] // Optimize out the match on `direction`.
|
||||
fn integrated_aes_gcm<'a>(
|
||||
aes_key: &aes::Key, gcm_ctx: &mut gcm::Context, in_out: &'a mut [u8], ctr: &mut Counter,
|
||||
direction: Direction, cpu_features: cpu::Features,
|
||||
aes_key: &aes::Key,
|
||||
gcm_ctx: &mut gcm::Context,
|
||||
in_out: &'a mut [u8],
|
||||
ctr: &mut Counter,
|
||||
direction: Direction,
|
||||
cpu_features: cpu::Features,
|
||||
) -> &'a mut [u8] {
|
||||
use libc::size_t;
|
||||
|
||||
@ -198,8 +215,12 @@ fn integrated_aes_gcm<'a>(
|
||||
Direction::Opening { in_prefix_len } => {
|
||||
extern "C" {
|
||||
fn GFp_aesni_gcm_decrypt(
|
||||
input: *const u8, output: *mut u8, len: size_t, key: &aes::AES_KEY,
|
||||
ivec: &mut Counter, gcm: &mut gcm::Context,
|
||||
input: *const u8,
|
||||
output: *mut u8,
|
||||
len: size_t,
|
||||
key: &aes::AES_KEY,
|
||||
ivec: &mut Counter,
|
||||
gcm: &mut gcm::Context,
|
||||
) -> size_t;
|
||||
}
|
||||
unsafe {
|
||||
@ -212,12 +233,16 @@ fn integrated_aes_gcm<'a>(
|
||||
gcm_ctx,
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
Direction::Sealing => {
|
||||
extern "C" {
|
||||
fn GFp_aesni_gcm_encrypt(
|
||||
input: *const u8, output: *mut u8, len: size_t, key: &aes::AES_KEY,
|
||||
ivec: &mut Counter, gcm: &mut gcm::Context,
|
||||
input: *const u8,
|
||||
output: *mut u8,
|
||||
len: size_t,
|
||||
key: &aes::AES_KEY,
|
||||
ivec: &mut Counter,
|
||||
gcm: &mut gcm::Context,
|
||||
) -> size_t;
|
||||
}
|
||||
unsafe {
|
||||
@ -230,7 +255,7 @@ fn integrated_aes_gcm<'a>(
|
||||
gcm_ctx,
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
&mut in_out[processed..]
|
||||
@ -239,7 +264,11 @@ fn integrated_aes_gcm<'a>(
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
#[inline]
|
||||
fn integrated_aes_gcm<'a>(
|
||||
_: &aes::Key, _: &mut gcm::Context, in_out: &'a mut [u8], _: &mut Counter, _: Direction,
|
||||
_: &aes::Key,
|
||||
_: &mut gcm::Context,
|
||||
in_out: &'a mut [u8],
|
||||
_: &mut Counter,
|
||||
_: Direction,
|
||||
_: cpu::Features,
|
||||
) -> &'a mut [u8] {
|
||||
in_out // This doesn't process any of the input so it all remains.
|
||||
|
@ -28,7 +28,9 @@ pub const BLOCK_LEN: usize = 16;
|
||||
|
||||
impl Block {
|
||||
#[inline]
|
||||
pub fn zero() -> Self { Self { subblocks: [0, 0] } }
|
||||
pub fn zero() -> Self {
|
||||
Self { subblocks: [0, 0] }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_u64_le(first: LittleEndian<u64>, second: LittleEndian<u64>) -> Self {
|
||||
@ -59,7 +61,9 @@ impl Block {
|
||||
/// leaving the rest of the block unchanged. Panics if `a` is larger
|
||||
/// than a block.
|
||||
#[inline]
|
||||
pub fn partial_copy_from(&mut self, a: &[u8]) { self.as_mut()[..a.len()].copy_from_slice(a); }
|
||||
pub fn partial_copy_from(&mut self, a: &[u8]) {
|
||||
self.as_mut()[..a.len()].copy_from_slice(a);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bitxor_assign(&mut self, a: Block) {
|
||||
@ -74,28 +78,38 @@ impl Block {
|
||||
|
||||
impl From<&'_ [u8; BLOCK_LEN]> for Block {
|
||||
#[inline]
|
||||
fn from(bytes: &[u8; BLOCK_LEN]) -> Self { unsafe { core::mem::transmute_copy(bytes) } }
|
||||
fn from(bytes: &[u8; BLOCK_LEN]) -> Self {
|
||||
unsafe { core::mem::transmute_copy(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From_<&'_ [u8; 2 * BLOCK_LEN]> for [Block; 2] {
|
||||
#[inline]
|
||||
fn from_(bytes: &[u8; 2 * BLOCK_LEN]) -> Self { unsafe { core::mem::transmute_copy(bytes) } }
|
||||
fn from_(bytes: &[u8; 2 * BLOCK_LEN]) -> Self {
|
||||
unsafe { core::mem::transmute_copy(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8; BLOCK_LEN]> for Block {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8; BLOCK_LEN] { unsafe { core::mem::transmute(self) } }
|
||||
fn as_ref(&self) -> &[u8; BLOCK_LEN] {
|
||||
unsafe { core::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<[u8; BLOCK_LEN]> for Block {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [u8; BLOCK_LEN] { unsafe { core::mem::transmute(self) } }
|
||||
fn as_mut(&mut self) -> &mut [u8; BLOCK_LEN] {
|
||||
unsafe { core::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `AsMut`.
|
||||
impl From_<&mut [Block; 2]> for &mut [u8; 2 * BLOCK_LEN] {
|
||||
#[inline]
|
||||
fn from_(bytes: &mut [Block; 2]) -> Self { unsafe { core::mem::transmute(bytes) } }
|
||||
fn from_(bytes: &mut [Block; 2]) -> Self {
|
||||
unsafe { core::mem::transmute(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -25,7 +25,9 @@ use libc::size_t;
|
||||
pub struct Key([Block; KEY_BLOCKS]);
|
||||
|
||||
impl From<&'_ [u8; KEY_LEN]> for Key {
|
||||
fn from(value: &[u8; KEY_LEN]) -> Self { Self(<[Block; KEY_BLOCKS]>::from_(value)) }
|
||||
fn from(value: &[u8; KEY_LEN]) -> Self {
|
||||
Self(<[Block; KEY_BLOCKS]>::from_(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Key {
|
||||
@ -99,21 +101,29 @@ impl Key {
|
||||
|
||||
#[inline] // Optimize away match on `counter.`
|
||||
unsafe fn encrypt(
|
||||
&self, counter: CounterOrIv, input: *const u8, in_out_len: usize, output: *mut u8,
|
||||
&self,
|
||||
counter: CounterOrIv,
|
||||
input: *const u8,
|
||||
in_out_len: usize,
|
||||
output: *mut u8,
|
||||
) {
|
||||
let iv = match counter {
|
||||
CounterOrIv::Counter(counter) => counter.into(),
|
||||
CounterOrIv::Iv(iv) => {
|
||||
assert!(in_out_len <= 32);
|
||||
iv
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/// XXX: Although this takes an `Iv`, this actually uses it like a
|
||||
/// `Counter`.
|
||||
extern "C" {
|
||||
fn GFp_ChaCha20_ctr32(
|
||||
out: *mut u8, in_: *const u8, in_len: size_t, key: &Key, first_iv: &Iv,
|
||||
out: *mut u8,
|
||||
in_: *const u8,
|
||||
in_len: size_t,
|
||||
key: &Key,
|
||||
first_iv: &Iv,
|
||||
);
|
||||
}
|
||||
|
||||
@ -183,7 +193,12 @@ mod tests {
|
||||
}
|
||||
|
||||
fn chacha20_test_case_inner(
|
||||
key: &Key, nonce: &[u8], ctr: u32, input: &[u8], expected: &[u8], len: usize,
|
||||
key: &Key,
|
||||
nonce: &[u8],
|
||||
ctr: u32,
|
||||
input: &[u8],
|
||||
expected: &[u8],
|
||||
len: usize,
|
||||
in_out_buf: &mut [u8],
|
||||
) {
|
||||
// Straightforward encryption into disjoint buffers is computed
|
||||
|
@ -40,21 +40,29 @@ pub static CHACHA20_POLY1305: aead::Algorithm = aead::Algorithm {
|
||||
|
||||
/// Copies |key| into |ctx_buf|.
|
||||
fn chacha20_poly1305_init(
|
||||
key: &[u8], _todo: cpu::Features,
|
||||
key: &[u8],
|
||||
_todo: cpu::Features,
|
||||
) -> Result<aead::KeyInner, error::Unspecified> {
|
||||
let key: &[u8; chacha::KEY_LEN] = key.try_into_()?;
|
||||
Ok(aead::KeyInner::ChaCha20Poly1305(chacha::Key::from(key)))
|
||||
}
|
||||
|
||||
fn chacha20_poly1305_seal(
|
||||
key: &aead::KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8],
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_out: &mut [u8],
|
||||
cpu_features: cpu::Features,
|
||||
) -> Tag {
|
||||
aead(key, nonce, aad, in_out, Direction::Sealing, cpu_features)
|
||||
}
|
||||
|
||||
fn chacha20_poly1305_open(
|
||||
key: &aead::KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_prefix_len: usize, in_out: &mut [u8],
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
aad: Aad<&[u8]>,
|
||||
in_prefix_len: usize,
|
||||
in_out: &mut [u8],
|
||||
cpu_features: cpu::Features,
|
||||
) -> Tag {
|
||||
aead(
|
||||
@ -71,8 +79,12 @@ pub type Key = chacha::Key;
|
||||
|
||||
#[inline(always)] // Statically eliminate branches on `direction`.
|
||||
fn aead(
|
||||
key: &aead::KeyInner, nonce: Nonce, Aad(aad): Aad<&[u8]>, in_out: &mut [u8],
|
||||
direction: Direction, _todo: cpu::Features,
|
||||
key: &aead::KeyInner,
|
||||
nonce: Nonce,
|
||||
Aad(aad): Aad<&[u8]>,
|
||||
in_out: &mut [u8],
|
||||
direction: Direction,
|
||||
_todo: cpu::Features,
|
||||
) -> Tag {
|
||||
let chacha20_key = match key {
|
||||
aead::KeyInner::ChaCha20Poly1305(key) => key,
|
||||
@ -92,12 +104,12 @@ fn aead(
|
||||
poly1305_update_padded_16(&mut ctx, &in_out[in_prefix_len..]);
|
||||
chacha20_key.encrypt_overlapping(counter, in_out, in_prefix_len);
|
||||
in_out.len() - in_prefix_len
|
||||
},
|
||||
}
|
||||
Direction::Sealing => {
|
||||
chacha20_key.encrypt_in_place(counter, in_out);
|
||||
poly1305_update_padded_16(&mut ctx, in_out);
|
||||
in_out.len()
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
ctx.update_block(
|
||||
|
@ -57,7 +57,9 @@ impl SealingKey {
|
||||
/// `encrypted_packet_length||ciphertext`, where `encrypted_packet_length`
|
||||
/// is encrypted with `K_1` and `ciphertext` is encrypted by `K_2`.
|
||||
pub fn seal_in_place(
|
||||
&self, sequence_number: u32, plaintext_in_ciphertext_out: &mut [u8],
|
||||
&self,
|
||||
sequence_number: u32,
|
||||
plaintext_in_ciphertext_out: &mut [u8],
|
||||
tag_out: &mut [u8; TAG_LEN],
|
||||
) {
|
||||
let mut counter = make_counter(sequence_number);
|
||||
@ -98,7 +100,9 @@ impl OpeningKey {
|
||||
/// Importantly, the result won't be authenticated until `open_in_place` is
|
||||
/// called.
|
||||
pub fn decrypt_packet_length(
|
||||
&self, sequence_number: u32, encrypted_packet_length: [u8; PACKET_LENGTH_LEN],
|
||||
&self,
|
||||
sequence_number: u32,
|
||||
encrypted_packet_length: [u8; PACKET_LENGTH_LEN],
|
||||
) -> [u8; PACKET_LENGTH_LEN] {
|
||||
let mut packet_length = encrypted_packet_length;
|
||||
let counter = make_counter(sequence_number);
|
||||
@ -116,7 +120,10 @@ impl OpeningKey {
|
||||
/// otherwise the contents of `ciphertext_in_plaintext_out` are unspecified
|
||||
/// and must not be used.
|
||||
pub fn open_in_place<'a>(
|
||||
&self, sequence_number: u32, ciphertext_in_plaintext_out: &'a mut [u8], tag: &[u8; TAG_LEN],
|
||||
&self,
|
||||
sequence_number: u32,
|
||||
ciphertext_in_plaintext_out: &'a mut [u8],
|
||||
tag: &[u8; TAG_LEN],
|
||||
) -> Result<&'a [u8], error::Unspecified> {
|
||||
let mut counter = make_counter(sequence_number);
|
||||
|
||||
|
@ -36,7 +36,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_gcm_init_avx(&mut key, &h);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Implementation::CLMUL => {
|
||||
extern "C" {
|
||||
@ -45,7 +45,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_gcm_init_clmul(&mut key, &h);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "arm"))]
|
||||
Implementation::NEON => {
|
||||
@ -55,7 +55,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_gcm_init_neon(&mut key, &h);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Implementation::Fallback => {
|
||||
extern "C" {
|
||||
@ -64,7 +64,7 @@ impl Key {
|
||||
unsafe {
|
||||
GFp_gcm_init_4bit(&mut key, &h);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
key
|
||||
@ -108,47 +108,59 @@ impl Context {
|
||||
Implementation::CLMUL if has_avx_movbe(self.cpu_features) => {
|
||||
extern "C" {
|
||||
fn GFp_gcm_ghash_avx(
|
||||
ctx: &mut Context, h_table: *const GCM128_KEY, inp: *const u8, len: size_t,
|
||||
ctx: &mut Context,
|
||||
h_table: *const GCM128_KEY,
|
||||
inp: *const u8,
|
||||
len: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
GFp_gcm_ghash_avx(self, key_aliasing, input.as_ptr(), input.len());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Implementation::CLMUL => {
|
||||
extern "C" {
|
||||
fn GFp_gcm_ghash_clmul(
|
||||
ctx: &mut Context, h_table: *const GCM128_KEY, inp: *const u8, len: size_t,
|
||||
ctx: &mut Context,
|
||||
h_table: *const GCM128_KEY,
|
||||
inp: *const u8,
|
||||
len: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
GFp_gcm_ghash_clmul(self, key_aliasing, input.as_ptr(), input.len());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "arm"))]
|
||||
Implementation::NEON => {
|
||||
extern "C" {
|
||||
fn GFp_gcm_ghash_neon(
|
||||
ctx: &mut Context, h_table: *const GCM128_KEY, inp: *const u8, len: size_t,
|
||||
ctx: &mut Context,
|
||||
h_table: *const GCM128_KEY,
|
||||
inp: *const u8,
|
||||
len: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
GFp_gcm_ghash_neon(self, key_aliasing, input.as_ptr(), input.len());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Implementation::Fallback => {
|
||||
extern "C" {
|
||||
fn GFp_gcm_ghash_4bit(
|
||||
ctx: &mut Context, h_table: *const GCM128_KEY, inp: *const u8, len: size_t,
|
||||
ctx: &mut Context,
|
||||
h_table: *const GCM128_KEY,
|
||||
inp: *const u8,
|
||||
len: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
GFp_gcm_ghash_4bit(self, key_aliasing, input.as_ptr(), input.len());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +177,7 @@ impl Context {
|
||||
unsafe {
|
||||
GFp_gcm_gmult_clmul(self, key_aliasing);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "arm"))]
|
||||
Implementation::NEON => {
|
||||
@ -175,7 +187,7 @@ impl Context {
|
||||
unsafe {
|
||||
GFp_gcm_gmult_neon(self, key_aliasing);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Implementation::Fallback => {
|
||||
extern "C" {
|
||||
@ -184,7 +196,7 @@ impl Context {
|
||||
unsafe {
|
||||
GFp_gcm_gmult_4bit(self, key_aliasing);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,11 +49,15 @@ impl Nonce {
|
||||
/// Constructs a `Nonce` with the given value, assuming that the value is
|
||||
/// unique for the lifetime of the key it is being used with.
|
||||
#[inline]
|
||||
pub fn assume_unique_for_key(value: [u8; NONCE_LEN]) -> Self { Self(value) }
|
||||
pub fn assume_unique_for_key(value: [u8; NONCE_LEN]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8; NONCE_LEN]> for Nonce {
|
||||
fn as_ref(&self) -> &[u8; NONCE_LEN] { &self.0 }
|
||||
fn as_ref(&self) -> &[u8; NONCE_LEN] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// All the AEADs we support use 96-bit nonces.
|
||||
@ -76,8 +80,12 @@ impl<U32: Layout<u32>> Counter<U32>
|
||||
where
|
||||
u32: From<U32>,
|
||||
{
|
||||
pub fn zero(nonce: Nonce) -> Self { Self::new(nonce, 0) }
|
||||
pub fn one(nonce: Nonce) -> Self { Self::new(nonce, 1) }
|
||||
pub fn zero(nonce: Nonce) -> Self {
|
||||
Self::new(nonce, 0)
|
||||
}
|
||||
pub fn one(nonce: Nonce) -> Self {
|
||||
Self::new(nonce, 1)
|
||||
}
|
||||
|
||||
// Used by `zero()` and by the tests.
|
||||
#[cfg(test)]
|
||||
@ -127,15 +135,21 @@ impl<U32: Layout<u32>> From<Counter<U32>> for Iv
|
||||
where
|
||||
u32: From<U32>,
|
||||
{
|
||||
fn from(counter: Counter<U32>) -> Self { Self(unsafe { counter.block }) }
|
||||
fn from(counter: Counter<U32>) -> Self {
|
||||
Self(unsafe { counter.block })
|
||||
}
|
||||
}
|
||||
|
||||
impl Iv {
|
||||
#[inline]
|
||||
pub fn assume_unique_for_key(a: Block) -> Self { Self(a) }
|
||||
pub fn assume_unique_for_key(a: Block) -> Self {
|
||||
Self(a)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_block_less_safe(self) -> Block { self.0 }
|
||||
pub fn into_block_less_safe(self) -> Block {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Layout<T>: Encoding<T>
|
||||
|
@ -26,7 +26,9 @@ use libc::size_t;
|
||||
pub struct Key([Block; KEY_BLOCKS]);
|
||||
|
||||
impl From<[Block; KEY_BLOCKS]> for Key {
|
||||
fn from(value: [Block; KEY_BLOCKS]) -> Self { Self(value) }
|
||||
fn from(value: [Block; KEY_BLOCKS]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub const KEY_BLOCKS: usize = 2;
|
||||
@ -47,7 +49,10 @@ impl Context {
|
||||
pub fn from_key(Key(key_and_nonce): Key) -> Self {
|
||||
extern "C" {
|
||||
fn GFp_poly1305_blocks(
|
||||
state: &mut Opaque, input: *const u8, len: size_t, should_pad: Pad,
|
||||
state: &mut Opaque,
|
||||
input: *const u8,
|
||||
len: size_t,
|
||||
should_pad: Pad,
|
||||
);
|
||||
fn GFp_poly1305_emit(state: &mut Opaque, tag: &mut Tag, nonce: &Nonce);
|
||||
}
|
||||
@ -84,7 +89,9 @@ impl Context {
|
||||
self.func.blocks(&mut self.opaque, input, Pad::Pad);
|
||||
}
|
||||
|
||||
pub(super) fn finish(mut self) -> Tag { self.func.emit(&mut self.opaque, &self.nonce) }
|
||||
pub(super) fn finish(mut self) -> Tag {
|
||||
self.func.emit(&mut self.opaque, &self.nonce)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -124,7 +131,9 @@ struct Funcs {
|
||||
fn init(state: &mut Opaque, key: DerivedKey, func: &mut Funcs) -> Result<(), error::Unspecified> {
|
||||
extern "C" {
|
||||
fn GFp_poly1305_init_asm(
|
||||
state: &mut Opaque, key: &DerivedKey, out_func: &mut Funcs,
|
||||
state: &mut Opaque,
|
||||
key: &DerivedKey,
|
||||
out_func: &mut Funcs,
|
||||
) -> bssl::Result;
|
||||
}
|
||||
Result::from(unsafe { GFp_poly1305_init_asm(state, &key, func) })
|
||||
@ -179,7 +188,9 @@ mod tests {
|
||||
use crate::{polyfill::convert::*, test};
|
||||
|
||||
#[test]
|
||||
pub fn test_state_layout() { check_state_layout(); }
|
||||
pub fn test_state_layout() {
|
||||
check_state_layout();
|
||||
}
|
||||
|
||||
// Adapted from BoringSSL's crypto/poly1305/poly1305_test.cc.
|
||||
#[test]
|
||||
|
@ -39,7 +39,8 @@ impl HeaderProtectionKey {
|
||||
///
|
||||
/// `key_bytes` must be exactly `algorithm.key_len` bytes long.
|
||||
pub fn new(
|
||||
algorithm: &'static Algorithm, key_bytes: &[u8],
|
||||
algorithm: &'static Algorithm,
|
||||
key_bytes: &[u8],
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Self {
|
||||
inner: (algorithm.init)(key_bytes, cpu::features())?,
|
||||
@ -60,7 +61,9 @@ impl HeaderProtectionKey {
|
||||
|
||||
/// The key's algorithm.
|
||||
#[inline(always)]
|
||||
pub fn algorithm(&self) -> &'static Algorithm { self.algorithm }
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.algorithm
|
||||
}
|
||||
}
|
||||
|
||||
const SAMPLE_LEN: usize = super::TAG_LEN;
|
||||
@ -78,11 +81,15 @@ pub struct Algorithm {
|
||||
impl Algorithm {
|
||||
/// The length of the key.
|
||||
#[inline(always)]
|
||||
pub fn key_len(&self) -> usize { self.key_len }
|
||||
pub fn key_len(&self) -> usize {
|
||||
self.key_len
|
||||
}
|
||||
|
||||
/// The required sample length.
|
||||
#[inline(always)]
|
||||
pub fn sample_len(&self) -> usize { SAMPLE_LEN }
|
||||
pub fn sample_len(&self) -> usize {
|
||||
SAMPLE_LEN
|
||||
}
|
||||
}
|
||||
|
||||
derive_debug_via_id!(Algorithm);
|
||||
@ -95,7 +102,9 @@ enum AlgorithmID {
|
||||
}
|
||||
|
||||
impl PartialEq for Algorithm {
|
||||
fn eq(&self, other: &Self) -> bool { self.id == other.id }
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Algorithm {}
|
||||
|
@ -85,7 +85,9 @@ derive_debug_via_field!(Algorithm, curve);
|
||||
|
||||
impl Eq for Algorithm {}
|
||||
impl PartialEq for Algorithm {
|
||||
fn eq(&self, other: &Algorithm) -> bool { self.curve.id == other.curve.id }
|
||||
fn eq(&self, other: &Algorithm) -> bool {
|
||||
self.curve.id == other.curve.id
|
||||
}
|
||||
}
|
||||
|
||||
/// An ephemeral private key for use (only) with `agree_ephemeral`. The
|
||||
@ -99,7 +101,8 @@ pub struct EphemeralPrivateKey {
|
||||
impl EphemeralPrivateKey {
|
||||
/// Generate a new ephemeral private key for the given algorithm.
|
||||
pub fn generate(
|
||||
alg: &'static Algorithm, rng: &rand::SecureRandom,
|
||||
alg: &'static Algorithm,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let cpu_features = cpu::features();
|
||||
|
||||
@ -123,7 +126,9 @@ impl EphemeralPrivateKey {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn bytes(&self) -> &[u8] { self.private_key.bytes_less_safe() }
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
self.private_key.bytes_less_safe()
|
||||
}
|
||||
}
|
||||
|
||||
/// A public key for key agreement.
|
||||
@ -131,7 +136,9 @@ impl EphemeralPrivateKey {
|
||||
pub struct PublicKey(ec::PublicKey);
|
||||
|
||||
impl AsRef<[u8]> for PublicKey {
|
||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
@ -158,7 +165,9 @@ where
|
||||
|
||||
impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
|
||||
/// Constructs a new `UnparsedPublicKey`.
|
||||
pub fn new(algorithm: &'static Algorithm, bytes: B) -> Self { Self { algorithm, bytes } }
|
||||
pub fn new(algorithm: &'static Algorithm, bytes: B) -> Self {
|
||||
Self { algorithm, bytes }
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs a key agreement with an ephemeral private key and the given public
|
||||
@ -184,7 +193,9 @@ impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
|
||||
/// returns.
|
||||
#[inline]
|
||||
pub fn agree_ephemeral<B: AsRef<[u8]>, F, R, E>(
|
||||
my_private_key: EphemeralPrivateKey, peer_public_key: &UnparsedPublicKey<B>, error_value: E,
|
||||
my_private_key: EphemeralPrivateKey,
|
||||
peer_public_key: &UnparsedPublicKey<B>,
|
||||
error_value: E,
|
||||
kdf: F,
|
||||
) -> Result<R, E>
|
||||
where
|
||||
@ -198,7 +209,9 @@ where
|
||||
}
|
||||
|
||||
fn agree_ephemeral_<F, R, E>(
|
||||
my_private_key: EphemeralPrivateKey, peer_public_key: UnparsedPublicKey<&[u8]>, error_value: E,
|
||||
my_private_key: EphemeralPrivateKey,
|
||||
peer_public_key: UnparsedPublicKey<&[u8]>,
|
||||
error_value: E,
|
||||
kdf: F,
|
||||
) -> Result<R, E>
|
||||
where
|
||||
|
@ -21,7 +21,9 @@ pub struct BitLength(usize);
|
||||
// overflow.
|
||||
impl BitLength {
|
||||
#[inline]
|
||||
pub const fn from_usize_bits(bits: usize) -> Self { Self(bits) }
|
||||
pub const fn from_usize_bits(bits: usize) -> Self {
|
||||
Self(bits)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_usize_bytes(bytes: usize) -> Result<Self, error::Unspecified> {
|
||||
@ -37,7 +39,9 @@ impl BitLength {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_usize_bits(&self) -> usize { self.0 }
|
||||
pub fn as_usize_bits(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
#[inline]
|
||||
|
@ -29,7 +29,7 @@ impl From<Result> for core::result::Result<(), error::Unspecified> {
|
||||
c => {
|
||||
debug_assert_eq!(c, 0, "`bssl::Result` value must be 0 or 1");
|
||||
Err(error::Unspecified)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,9 @@ macro_rules! derive_debug_self_as_ref_hex_bytes {
|
||||
}
|
||||
|
||||
pub(crate) fn write_hex_tuple(
|
||||
fmt: &mut core::fmt::Formatter, type_name: &str, value: &AsRef<[u8]>,
|
||||
fmt: &mut core::fmt::Formatter,
|
||||
type_name: &str,
|
||||
value: &AsRef<[u8]>,
|
||||
) -> Result<(), ::core::fmt::Error> {
|
||||
fmt.debug_tuple(type_name)
|
||||
.field(&HexStr(value.as_ref()))
|
||||
@ -72,7 +74,8 @@ impl core::fmt::Debug for HexStr<'_> {
|
||||
}
|
||||
|
||||
pub(crate) fn write_hex_bytes(
|
||||
fmt: &mut core::fmt::Formatter, bytes: &[u8],
|
||||
fmt: &mut core::fmt::Formatter,
|
||||
bytes: &[u8],
|
||||
) -> Result<(), ::core::fmt::Error> {
|
||||
for byte in bytes {
|
||||
write!(fmt, "{:02x}", byte)?;
|
||||
|
@ -172,7 +172,9 @@ impl Context {
|
||||
|
||||
/// The algorithm that this context is using.
|
||||
#[inline(always)]
|
||||
pub fn algorithm(&self) -> &'static Algorithm { self.algorithm }
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.algorithm
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the digest of `data` using the given digest algorithm.
|
||||
@ -212,7 +214,9 @@ pub struct Digest {
|
||||
impl Digest {
|
||||
/// The algorithm that was used to calculate the digest value.
|
||||
#[inline(always)]
|
||||
pub fn algorithm(&self) -> &'static Algorithm { self.algorithm }
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.algorithm
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Digest {
|
||||
@ -266,7 +270,9 @@ enum AlgorithmID {
|
||||
}
|
||||
|
||||
impl PartialEq for Algorithm {
|
||||
fn eq(&self, other: &Self) -> bool { self.id == other.id }
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Algorithm {}
|
||||
@ -512,7 +518,9 @@ mod tests {
|
||||
use super::super::super::super::digest;
|
||||
|
||||
#[test]
|
||||
fn max_input_test() { super::max_input_test(&digest::$algorithm_name); }
|
||||
fn max_input_test() {
|
||||
super::max_input_test(&digest::$algorithm_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
|
@ -25,13 +25,19 @@ const CHAINING_WORDS: usize = CHAINING_LEN / 4;
|
||||
type W32 = Wrapping<u32>;
|
||||
|
||||
#[inline]
|
||||
fn ch(x: W32, y: W32, z: W32) -> W32 { (x & y) | (!x & z) }
|
||||
fn ch(x: W32, y: W32, z: W32) -> W32 {
|
||||
(x & y) | (!x & z)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parity(x: W32, y: W32, z: W32) -> W32 { x ^ y ^ z }
|
||||
fn parity(x: W32, y: W32, z: W32) -> W32 {
|
||||
x ^ y ^ z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn maj(x: W32, y: W32, z: W32) -> W32 { (x & y) | (x & z) | (y & z) }
|
||||
fn maj(x: W32, y: W32, z: W32) -> W32 {
|
||||
(x & y) | (x & z) | (y & z)
|
||||
}
|
||||
|
||||
/// The main purpose in retaining this is to support legacy protocols and OCSP,
|
||||
/// none of which need a fast SHA-1 implementation.
|
||||
@ -39,7 +45,9 @@ fn maj(x: W32, y: W32, z: W32) -> W32 { (x & y) | (x & z) | (y & z) }
|
||||
/// Unlike SHA-256, SHA-384, and SHA-512,
|
||||
/// there is no assembly language implementation.
|
||||
pub(super) unsafe extern "C" fn block_data_order(
|
||||
state: &mut super::State, data: *const u8, num: size_t,
|
||||
state: &mut super::State,
|
||||
data: *const u8,
|
||||
num: size_t,
|
||||
) {
|
||||
let data = data as *const [[u8; 4]; 16];
|
||||
let blocks = core::slice::from_raw_parts(data, num);
|
||||
|
@ -117,7 +117,8 @@ impl Ed25519KeyPair {
|
||||
/// public key). This also detects any corruption of the public or private
|
||||
/// key.
|
||||
pub fn from_seed_and_public_key(
|
||||
seed: &[u8], public_key: &[u8],
|
||||
seed: &[u8],
|
||||
public_key: &[u8],
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let pair = Self::from_seed_unchecked(seed)?;
|
||||
|
||||
@ -208,20 +209,25 @@ impl Ed25519KeyPair {
|
||||
impl signature::KeyPair for Ed25519KeyPair {
|
||||
type PublicKey = PublicKey;
|
||||
|
||||
fn public_key(&self) -> &Self::PublicKey { &self.public_key }
|
||||
fn public_key(&self) -> &Self::PublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PublicKey([u8; ED25519_PUBLIC_KEY_LEN]);
|
||||
|
||||
impl AsRef<[u8]> for PublicKey {
|
||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
|
||||
fn unwrap_pkcs8(
|
||||
version: pkcs8::Version, input: untrusted::Input,
|
||||
version: pkcs8::Version,
|
||||
input: untrusted::Input,
|
||||
) -> Result<(untrusted::Input, Option<untrusted::Input>), error::KeyRejected> {
|
||||
let (private_key, public_key) = pkcs8::unwrap_key(&PKCS8_TEMPLATE, version, input)?;
|
||||
let private_key = private_key
|
||||
|
@ -39,7 +39,10 @@ pub static ED25519: EdDSAParameters = EdDSAParameters {};
|
||||
|
||||
impl signature::VerificationAlgorithm for EdDSAParameters {
|
||||
fn verify(
|
||||
&self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input,
|
||||
&self,
|
||||
public_key: untrusted::Input,
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let public_key = public_key.as_slice_less_safe();
|
||||
let public_key: &[u8; ELEM_LEN] = public_key.try_into_()?;;
|
||||
@ -71,6 +74,9 @@ impl sealed::Sealed for EdDSAParameters {}
|
||||
|
||||
extern "C" {
|
||||
fn GFp_x25519_ge_double_scalarmult_vartime(
|
||||
r: &mut Point, a_coeff: &Scalar, a: &ExtPoint, b_coeff: &Scalar,
|
||||
r: &mut Point,
|
||||
a_coeff: &Scalar,
|
||||
a: &ExtPoint,
|
||||
b_coeff: &Scalar,
|
||||
);
|
||||
}
|
||||
|
@ -94,7 +94,9 @@ impl ExtPoint {
|
||||
.map(|()| point)
|
||||
}
|
||||
|
||||
pub fn into_encoded_point(self) -> EncodedPoint { encode_point(self.x, self.y, self.z) }
|
||||
pub fn into_encoded_point(self) -> EncodedPoint {
|
||||
encode_point(self.x, self.y, self.z)
|
||||
}
|
||||
|
||||
pub fn invert_vartime(&mut self) {
|
||||
self.x.negate();
|
||||
@ -119,7 +121,9 @@ impl Point {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_encoded_point(self) -> EncodedPoint { encode_point(self.x, self.y, self.z) }
|
||||
pub fn into_encoded_point(self) -> EncodedPoint {
|
||||
encode_point(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_point(x: Elem<T>, y: Elem<T>, z: Elem<T>) -> EncodedPoint {
|
||||
|
@ -46,13 +46,15 @@ fn x25519_check_private_key_bytes(bytes: &[u8]) -> Result<(), error::Unspecified
|
||||
}
|
||||
|
||||
fn x25519_generate_private_key(
|
||||
rng: &rand::SecureRandom, out: &mut [u8],
|
||||
rng: &rand::SecureRandom,
|
||||
out: &mut [u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
rng.fill(out)
|
||||
}
|
||||
|
||||
fn x25519_public_from_private(
|
||||
public_out: &mut [u8], private_key: &ec::Seed,
|
||||
public_out: &mut [u8],
|
||||
private_key: &ec::Seed,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let public_out = public_out.try_into_()?;
|
||||
|
||||
@ -75,7 +77,8 @@ fn x25519_public_from_private(
|
||||
|
||||
extern "C" {
|
||||
fn GFp_x25519_public_from_private_generic(
|
||||
public_key_out: &mut PublicKey, private_key: &PrivateKey,
|
||||
public_key_out: &mut PublicKey,
|
||||
private_key: &PrivateKey,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -86,7 +89,9 @@ fn x25519_public_from_private(
|
||||
}
|
||||
|
||||
fn x25519_ecdh(
|
||||
out: &mut [u8], my_private_key: &ec::Seed, peer_public_key: untrusted::Input,
|
||||
out: &mut [u8],
|
||||
my_private_key: &ec::Seed,
|
||||
peer_public_key: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let cpu_features = my_private_key.cpu_features;
|
||||
let my_private_key = my_private_key.bytes_less_safe().try_into_()?;
|
||||
@ -95,7 +100,9 @@ fn x25519_ecdh(
|
||||
|
||||
#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))]
|
||||
fn scalar_mult(
|
||||
out: &mut ops::EncodedPoint, scalar: &ops::Scalar, point: &ops::EncodedPoint,
|
||||
out: &mut ops::EncodedPoint,
|
||||
scalar: &ops::Scalar,
|
||||
point: &ops::EncodedPoint,
|
||||
cpu_features: cpu::Features,
|
||||
) {
|
||||
#[cfg(target_arch = "arm")]
|
||||
@ -107,7 +114,9 @@ fn x25519_ecdh(
|
||||
|
||||
extern "C" {
|
||||
fn GFp_x25519_scalar_mult_generic(
|
||||
out: &mut ops::EncodedPoint, scalar: &ops::Scalar, point: &ops::EncodedPoint,
|
||||
out: &mut ops::EncodedPoint,
|
||||
scalar: &ops::Scalar,
|
||||
point: &ops::EncodedPoint,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -135,7 +144,9 @@ fn x25519_ecdh(
|
||||
fn x25519_neon(out: &mut ops::EncodedPoint, scalar: &ops::Scalar, point: &ops::EncodedPoint) {
|
||||
extern "C" {
|
||||
fn GFp_x25519_NEON(
|
||||
out: &mut ops::EncodedPoint, scalar: &ops::Scalar, point: &ops::EncodedPoint,
|
||||
out: &mut ops::EncodedPoint,
|
||||
scalar: &ops::Scalar,
|
||||
point: &ops::EncodedPoint,
|
||||
);
|
||||
}
|
||||
unsafe { GFp_x25519_NEON(out, scalar, point) }
|
||||
|
@ -12,8 +12,12 @@ impl KeyPair {
|
||||
Ok(Self { seed, public_key })
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> &PublicKey { &self.public_key }
|
||||
pub fn split(self) -> (Seed, PublicKey) { (self.seed, self.public_key) }
|
||||
pub fn public_key(&self) -> &PublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
pub fn split(self) -> (Seed, PublicKey) {
|
||||
(self.seed, self.public_key)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Seed {
|
||||
@ -24,7 +28,9 @@ pub struct Seed {
|
||||
|
||||
impl Seed {
|
||||
pub(crate) fn generate(
|
||||
curve: &'static Curve, rng: &rand::SecureRandom, cpu_features: cpu::Features,
|
||||
curve: &'static Curve,
|
||||
rng: &rand::SecureRandom,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let mut r = Self {
|
||||
bytes: [0u8; SEED_MAX_BYTES],
|
||||
@ -36,7 +42,9 @@ impl Seed {
|
||||
}
|
||||
|
||||
pub(crate) fn from_bytes(
|
||||
curve: &'static Curve, bytes: untrusted::Input, cpu_features: cpu::Features,
|
||||
curve: &'static Curve,
|
||||
bytes: untrusted::Input,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<Seed, error::Unspecified> {
|
||||
let bytes = bytes.as_slice_less_safe();
|
||||
if curve.elem_scalar_seed_len != bytes.len() {
|
||||
@ -52,7 +60,9 @@ impl Seed {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
pub fn bytes_less_safe(&self) -> &[u8] { &self.bytes[..self.curve.elem_scalar_seed_len] }
|
||||
pub fn bytes_less_safe(&self) -> &[u8] {
|
||||
&self.bytes[..self.curve.elem_scalar_seed_len]
|
||||
}
|
||||
|
||||
pub fn compute_public_key(&self) -> Result<PublicKey, error::Unspecified> {
|
||||
let mut public_key = PublicKey {
|
||||
@ -71,7 +81,9 @@ pub struct PublicKey {
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for PublicKey {
|
||||
fn as_ref(&self) -> &[u8] { &self.bytes[..self.len] }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.bytes[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
/// The maximum length, in bytes, of an encoded public key.
|
||||
|
@ -31,7 +31,8 @@ use untrusted;
|
||||
// y**2 == (x**2 + a)*x + b (mod q)
|
||||
//
|
||||
fn verify_affine_point_is_on_the_curve(
|
||||
ops: &CommonOps, (x, y): (&Elem<R>, &Elem<R>),
|
||||
ops: &CommonOps,
|
||||
(x, y): (&Elem<R>, &Elem<R>),
|
||||
) -> Result<(), error::Unspecified> {
|
||||
verify_affine_point_is_on_the_curve_scaled(ops, (x, y), &ops.a, &ops.b)
|
||||
}
|
||||
@ -46,7 +47,8 @@ fn verify_affine_point_is_on_the_curve(
|
||||
//
|
||||
// This function also verifies that the point is not at infinity.
|
||||
fn verify_jacobian_point_is_on_the_curve(
|
||||
ops: &CommonOps, p: &Point,
|
||||
ops: &CommonOps,
|
||||
p: &Point,
|
||||
) -> Result<Elem<R>, error::Unspecified> {
|
||||
let z = ops.point_z(p);
|
||||
|
||||
@ -133,7 +135,10 @@ fn verify_jacobian_point_is_on_the_curve(
|
||||
// Elliptic Curve Cryptosystems" by Johannes Blömer, Martin Otto, and
|
||||
// Jean-Pierre Seifert.
|
||||
fn verify_affine_point_is_on_the_curve_scaled(
|
||||
ops: &CommonOps, (x, y): (&Elem<R>, &Elem<R>), a_scaled: &Elem<R>, b_scaled: &Elem<R>,
|
||||
ops: &CommonOps,
|
||||
(x, y): (&Elem<R>, &Elem<R>),
|
||||
a_scaled: &Elem<R>,
|
||||
b_scaled: &Elem<R>,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let lhs = ops.elem_squared(y);
|
||||
|
||||
@ -150,7 +155,9 @@ fn verify_affine_point_is_on_the_curve_scaled(
|
||||
}
|
||||
|
||||
pub(crate) fn key_pair_from_pkcs8(
|
||||
curve: &'static ec::Curve, template: &pkcs8::Template, input: untrusted::Input,
|
||||
curve: &'static ec::Curve,
|
||||
template: &pkcs8::Template,
|
||||
input: untrusted::Input,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<ec::KeyPair, error::KeyRejected> {
|
||||
let (ec_private_key, _) = pkcs8::unwrap_key(template, pkcs8::Version::V1Only, input)?;
|
||||
@ -168,7 +175,8 @@ pub(crate) fn key_pair_from_pkcs8(
|
||||
}
|
||||
|
||||
fn key_pair_from_pkcs8_<'a>(
|
||||
template: &pkcs8::Template, input: &mut untrusted::Reader<'a>,
|
||||
template: &pkcs8::Template,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, untrusted::Input<'a>), error::KeyRejected> {
|
||||
let version = der::small_nonnegative_integer(input)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
@ -203,8 +211,10 @@ fn key_pair_from_pkcs8_<'a>(
|
||||
}
|
||||
|
||||
pub(crate) fn key_pair_from_bytes(
|
||||
curve: &'static ec::Curve, private_key_bytes: untrusted::Input,
|
||||
public_key_bytes: untrusted::Input, cpu_features: cpu::Features,
|
||||
curve: &'static ec::Curve,
|
||||
private_key_bytes: untrusted::Input,
|
||||
public_key_bytes: untrusted::Input,
|
||||
cpu_features: cpu::Features,
|
||||
) -> Result<ec::KeyPair, error::KeyRejected> {
|
||||
let seed = ec::Seed::from_bytes(curve, private_key_bytes, cpu_features)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_component())?;
|
||||
|
@ -47,13 +47,15 @@ macro_rules! suite_b_curve {
|
||||
}
|
||||
|
||||
fn $generate_private_key(
|
||||
rng: &rand::SecureRandom, out: &mut [u8],
|
||||
rng: &rand::SecureRandom,
|
||||
out: &mut [u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
ec::suite_b::private_key::generate_private_scalar_bytes($private_key_ops, rng, out)
|
||||
}
|
||||
|
||||
fn $public_from_private(
|
||||
public_out: &mut [u8], private_key: &ec::Seed,
|
||||
public_out: &mut [u8],
|
||||
private_key: &ec::Seed,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
ec::suite_b::private_key::public_from_private($private_key_ops, public_out, private_key)
|
||||
}
|
||||
|
@ -45,7 +45,9 @@ macro_rules! ecdh {
|
||||
};
|
||||
|
||||
fn $ecdh(
|
||||
out: &mut [u8], my_private_key: &ec::Seed, peer_public_key: untrusted::Input,
|
||||
out: &mut [u8],
|
||||
my_private_key: &ec::Seed,
|
||||
peer_public_key: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
ecdh(
|
||||
$private_key_ops,
|
||||
@ -77,8 +79,11 @@ ecdh!(
|
||||
);
|
||||
|
||||
fn ecdh(
|
||||
private_key_ops: &PrivateKeyOps, public_key_ops: &PublicKeyOps, out: &mut [u8],
|
||||
my_private_key: &ec::Seed, peer_public_key: untrusted::Input,
|
||||
private_key_ops: &PrivateKeyOps,
|
||||
public_key_ops: &PublicKeyOps,
|
||||
out: &mut [u8],
|
||||
my_private_key: &ec::Seed,
|
||||
peer_public_key: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
// The NIST SP 800-56Ar2 steps are from section 5.7.1.2 Elliptic Curve
|
||||
// Cryptography Cofactor Diffie-Hellman (ECC CDH) Primitive.
|
||||
|
@ -105,7 +105,7 @@ mod tests {
|
||||
("P-384", "SHA384") => (&p384::PUBLIC_SCALAR_OPS, &digest::SHA384),
|
||||
_ => {
|
||||
panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let num_limbs = ops.public_key_ops.common.num_limbs;
|
||||
|
@ -51,7 +51,9 @@ enum AlgorithmID {
|
||||
derive_debug_via_id!(EcdsaSigningAlgorithm);
|
||||
|
||||
impl PartialEq for EcdsaSigningAlgorithm {
|
||||
fn eq(&self, other: &Self) -> bool { self.id == other.id }
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for EcdsaSigningAlgorithm {}
|
||||
@ -80,7 +82,8 @@ impl EcdsaKeyPair {
|
||||
/// [RFC 5915]: https://tools.ietf.org/html/rfc5915
|
||||
/// [RFC 5958 Section 2]: https://tools.ietf.org/html/rfc5958#section-2
|
||||
pub fn generate_pkcs8(
|
||||
alg: &'static EcdsaSigningAlgorithm, rng: &rand::SecureRandom,
|
||||
alg: &'static EcdsaSigningAlgorithm,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<pkcs8::Document, error::Unspecified> {
|
||||
let private_key = ec::Seed::generate(alg.curve, rng, cpu::features())?;
|
||||
let public_key = private_key.compute_public_key()?;
|
||||
@ -102,7 +105,8 @@ impl EcdsaKeyPair {
|
||||
/// `ECPrivateKey`, if present, must be the same named curve that is in the
|
||||
/// algorithm identifier in the PKCS#8 header.
|
||||
pub fn from_pkcs8(
|
||||
alg: &'static EcdsaSigningAlgorithm, pkcs8: &[u8],
|
||||
alg: &'static EcdsaSigningAlgorithm,
|
||||
pkcs8: &[u8],
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let key_pair = ec::suite_b::key_pair_from_pkcs8(
|
||||
alg.curve,
|
||||
@ -120,7 +124,9 @@ impl EcdsaKeyPair {
|
||||
/// recommended to use `RsaPubeyPair::from_pkcs8()` (with a PKCS#8-encoded
|
||||
/// key) instead.
|
||||
pub fn from_private_key_and_public_key(
|
||||
alg: &'static EcdsaSigningAlgorithm, private_key: &[u8], public_key: &[u8],
|
||||
alg: &'static EcdsaSigningAlgorithm,
|
||||
private_key: &[u8],
|
||||
public_key: &[u8],
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let key_pair = ec::suite_b::key_pair_from_bytes(
|
||||
alg.curve,
|
||||
@ -149,7 +155,9 @@ impl EcdsaKeyPair {
|
||||
/// Returns the signature of the `message` using a random nonce
|
||||
/// generated by `rng`.
|
||||
pub fn sign(
|
||||
&self, rng: &rand::SecureRandom, message: &[u8],
|
||||
&self,
|
||||
rng: &rand::SecureRandom,
|
||||
message: &[u8],
|
||||
) -> Result<signature::Signature, error::Unspecified> {
|
||||
// Step 4 (out of order).
|
||||
let h = digest::digest(self.alg.digest_alg, message);
|
||||
@ -159,7 +167,9 @@ impl EcdsaKeyPair {
|
||||
/// Returns the signature of message digest `h` using a "random" nonce
|
||||
/// generated by `rng`.
|
||||
fn sign_(
|
||||
&self, rng: &rand::SecureRandom, h: digest::Digest,
|
||||
&self,
|
||||
rng: &rand::SecureRandom,
|
||||
h: digest::Digest,
|
||||
) -> Result<signature::Signature, error::Unspecified> {
|
||||
// NSA Suite B Implementer's Guide to ECDSA Section 3.4.1: ECDSA
|
||||
// Signature Generation.
|
||||
@ -237,7 +247,9 @@ impl EcdsaKeyPair {
|
||||
impl signature::KeyPair for EcdsaKeyPair {
|
||||
type PublicKey = PublicKey;
|
||||
|
||||
fn public_key(&self) -> &Self::PublicKey { &self.public_key }
|
||||
fn public_key(&self) -> &Self::PublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@ -246,7 +258,9 @@ pub struct PublicKey(ec::PublicKey);
|
||||
derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
|
||||
impl AsRef<[u8]> for PublicKey {
|
||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
fn format_rs_fixed(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize {
|
||||
@ -406,7 +420,7 @@ mod tests {
|
||||
("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
|
||||
_ => {
|
||||
panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let private_key =
|
||||
@ -443,7 +457,7 @@ mod tests {
|
||||
("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
|
||||
_ => {
|
||||
panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let private_key =
|
||||
|
@ -52,7 +52,10 @@ derive_debug_via_id!(EcdsaVerificationAlgorithm);
|
||||
|
||||
impl signature::VerificationAlgorithm for EcdsaVerificationAlgorithm {
|
||||
fn verify(
|
||||
&self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input,
|
||||
&self,
|
||||
public_key: untrusted::Input,
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let e = {
|
||||
// NSA Guide Step 2: "Use the selected hash function to compute H =
|
||||
@ -71,7 +74,10 @@ impl signature::VerificationAlgorithm for EcdsaVerificationAlgorithm {
|
||||
impl EcdsaVerificationAlgorithm {
|
||||
/// This is intentionally not public.
|
||||
fn verify_digest(
|
||||
&self, public_key: untrusted::Input, e: Scalar, signature: untrusted::Input,
|
||||
&self,
|
||||
public_key: untrusted::Input,
|
||||
e: Scalar,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
// NSA Suite B Implementer's Guide to ECDSA Section 3.4.2.
|
||||
|
||||
@ -137,7 +143,10 @@ impl EcdsaVerificationAlgorithm {
|
||||
// that would be necessary to compute the affine X coordinate.
|
||||
let x = public_key_ops.common.point_x(&product);
|
||||
fn sig_r_equals_x(
|
||||
ops: &PublicScalarOps, r: &Elem<Unencoded>, x: &Elem<R>, z2: &Elem<R>,
|
||||
ops: &PublicScalarOps,
|
||||
r: &Elem<Unencoded>,
|
||||
x: &Elem<R>,
|
||||
z2: &Elem<R>,
|
||||
) -> bool {
|
||||
let cops = ops.public_key_ops.common;
|
||||
let r_jacobian = cops.elem_product(z2, r);
|
||||
@ -162,7 +171,8 @@ impl EcdsaVerificationAlgorithm {
|
||||
impl sealed::Sealed for EcdsaVerificationAlgorithm {}
|
||||
|
||||
fn split_rs_fixed<'a>(
|
||||
ops: &'static ScalarOps, input: &mut untrusted::Reader<'a>,
|
||||
ops: &'static ScalarOps,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, untrusted::Input<'a>), error::Unspecified> {
|
||||
let scalar_len = ops.scalar_bytes_len();
|
||||
let r = input.read_bytes(scalar_len)?;
|
||||
@ -171,7 +181,8 @@ fn split_rs_fixed<'a>(
|
||||
}
|
||||
|
||||
fn split_rs_asn1<'a>(
|
||||
_ops: &'static ScalarOps, input: &mut untrusted::Reader<'a>,
|
||||
_ops: &'static ScalarOps,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, untrusted::Input<'a>), error::Unspecified> {
|
||||
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
|
||||
let r = der::positive_integer(input)?.big_endian_without_leading_zero_as_input();
|
||||
@ -181,7 +192,10 @@ fn split_rs_asn1<'a>(
|
||||
}
|
||||
|
||||
fn twin_mul(
|
||||
ops: &PrivateKeyOps, g_scalar: &Scalar, p_scalar: &Scalar, p_xy: &(Elem<R>, Elem<R>),
|
||||
ops: &PrivateKeyOps,
|
||||
g_scalar: &Scalar,
|
||||
p_scalar: &Scalar,
|
||||
p_xy: &(Elem<R>, Elem<R>),
|
||||
) -> Point {
|
||||
// XXX: Inefficient. TODO: implement interleaved wNAF multiplication.
|
||||
let scaled_g = ops.point_mul_base(g_scalar);
|
||||
@ -309,7 +323,7 @@ mod tests {
|
||||
"P-384" => &ECDSA_P384_SHA384_FIXED,
|
||||
_ => {
|
||||
panic!("Unsupported curve: {}", curve_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let digest = super::super::digest_scalar::digest_bytes_scalar(
|
||||
|
@ -115,7 +115,9 @@ impl CommonOps {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded> { self.elem_product(a, &ONE) }
|
||||
pub fn elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded> {
|
||||
self.elem_product(a, &ONE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>) {
|
||||
@ -124,7 +126,9 @@ impl CommonOps {
|
||||
|
||||
#[inline]
|
||||
pub fn elem_product<EA: Encoding, EB: Encoding>(
|
||||
&self, a: &Elem<EA>, b: &Elem<EB>,
|
||||
&self,
|
||||
a: &Elem<EA>,
|
||||
b: &Elem<EB>,
|
||||
) -> Elem<<(EA, EB) as ProductEncoding>::Output>
|
||||
where
|
||||
(EA, EB): ProductEncoding,
|
||||
@ -133,10 +137,14 @@ impl CommonOps {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elem_square(&self, a: &mut Elem<R>) { unary_op_assign(self.elem_sqr_mont, a); }
|
||||
pub fn elem_square(&self, a: &mut Elem<R>) {
|
||||
unary_op_assign(self.elem_sqr_mont, a);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elem_squared(&self, a: &Elem<R>) -> Elem<R> { unary_op(self.elem_sqr_mont, a) }
|
||||
pub fn elem_squared(&self, a: &Elem<R>) -> Elem<R> {
|
||||
unary_op(self.elem_sqr_mont, a)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool {
|
||||
@ -199,7 +207,9 @@ pub struct PrivateKeyOps {
|
||||
|
||||
impl PrivateKeyOps {
|
||||
#[inline(always)]
|
||||
pub fn point_mul_base(&self, a: &Scalar) -> Point { (self.point_mul_base_impl)(a) }
|
||||
pub fn point_mul_base(&self, a: &Scalar) -> Point {
|
||||
(self.point_mul_base_impl)(a)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn point_mul(&self, p_scalar: &Scalar, (p_x, p_y): &(Elem<R>, Elem<R>)) -> Point {
|
||||
@ -216,7 +226,9 @@ impl PrivateKeyOps {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R> { (self.elem_inv_squared)(a) }
|
||||
pub fn elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R> {
|
||||
(self.elem_inv_squared)(a)
|
||||
}
|
||||
}
|
||||
|
||||
/// Operations and values needed by all operations on public keys (ECDH
|
||||
@ -259,7 +271,9 @@ pub struct ScalarOps {
|
||||
|
||||
impl ScalarOps {
|
||||
// The (maximum) length of a scalar, not including any padding.
|
||||
pub fn scalar_bytes_len(&self) -> usize { self.common.num_limbs * LIMB_BYTES }
|
||||
pub fn scalar_bytes_len(&self) -> usize {
|
||||
self.common.num_limbs * LIMB_BYTES
|
||||
}
|
||||
|
||||
/// Returns the modular inverse of `a` (mod `n`). Panics of `a` is zero,
|
||||
/// because zero isn't invertible.
|
||||
@ -270,7 +284,9 @@ impl ScalarOps {
|
||||
|
||||
#[inline]
|
||||
pub fn scalar_product<EA: Encoding, EB: Encoding>(
|
||||
&self, a: &Scalar<EA>, b: &Scalar<EB>,
|
||||
&self,
|
||||
a: &Scalar<EA>,
|
||||
b: &Scalar<EB>,
|
||||
) -> Scalar<<(EA, EB) as ProductEncoding>::Output>
|
||||
where
|
||||
(EA, EB): ProductEncoding,
|
||||
@ -375,21 +391,25 @@ fn elem_sqr_mul_acc(ops: &CommonOps, acc: &mut Elem<R>, squarings: usize, b: &El
|
||||
|
||||
#[inline]
|
||||
pub fn elem_parse_big_endian_fixed_consttime(
|
||||
ops: &CommonOps, bytes: untrusted::Input,
|
||||
ops: &CommonOps,
|
||||
bytes: untrusted::Input,
|
||||
) -> Result<Elem<Unencoded>, error::Unspecified> {
|
||||
parse_big_endian_fixed_consttime(ops, bytes, AllowZero::Yes, &ops.q.p[..ops.num_limbs])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scalar_parse_big_endian_fixed_consttime(
|
||||
ops: &CommonOps, bytes: untrusted::Input,
|
||||
ops: &CommonOps,
|
||||
bytes: untrusted::Input,
|
||||
) -> Result<Scalar, error::Unspecified> {
|
||||
parse_big_endian_fixed_consttime(ops, bytes, AllowZero::No, &ops.n.limbs[..ops.num_limbs])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scalar_parse_big_endian_variable(
|
||||
ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input,
|
||||
ops: &CommonOps,
|
||||
allow_zero: AllowZero,
|
||||
bytes: untrusted::Input,
|
||||
) -> Result<Scalar, error::Unspecified> {
|
||||
let mut r = Scalar::zero();
|
||||
parse_big_endian_in_range_and_pad_consttime(
|
||||
@ -402,7 +422,9 @@ pub fn scalar_parse_big_endian_variable(
|
||||
}
|
||||
|
||||
pub fn scalar_parse_big_endian_partially_reduced_variable_consttime(
|
||||
ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input,
|
||||
ops: &CommonOps,
|
||||
allow_zero: AllowZero,
|
||||
bytes: untrusted::Input,
|
||||
) -> Result<Scalar, error::Unspecified> {
|
||||
let mut r = Scalar::zero();
|
||||
parse_big_endian_in_range_partially_reduced_and_pad_consttime(
|
||||
@ -415,7 +437,10 @@ pub fn scalar_parse_big_endian_partially_reduced_variable_consttime(
|
||||
}
|
||||
|
||||
fn parse_big_endian_fixed_consttime<M>(
|
||||
ops: &CommonOps, bytes: untrusted::Input, allow_zero: AllowZero, max_exclusive: &[Limb],
|
||||
ops: &CommonOps,
|
||||
bytes: untrusted::Input,
|
||||
allow_zero: AllowZero,
|
||||
max_exclusive: &[Limb],
|
||||
) -> Result<elem::Elem<M, Unencoded>, error::Unspecified> {
|
||||
if bytes.len() != ops.num_limbs * LIMB_BYTES {
|
||||
return Err(error::Unspecified);
|
||||
@ -432,7 +457,11 @@ fn parse_big_endian_fixed_consttime<M>(
|
||||
|
||||
extern "C" {
|
||||
fn LIMBS_add_mod(
|
||||
r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: size_t,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
b: *const Limb,
|
||||
m: *const Limb,
|
||||
num_limbs: size_t,
|
||||
);
|
||||
}
|
||||
|
||||
@ -570,7 +599,8 @@ mod tests {
|
||||
}
|
||||
|
||||
fn elem_div_by_2_test(
|
||||
ops: &CommonOps, elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
ops: &CommonOps,
|
||||
elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
test_file: test::File,
|
||||
) {
|
||||
test::run(test_file, |section, test_case| {
|
||||
@ -615,7 +645,8 @@ mod tests {
|
||||
}
|
||||
|
||||
fn elem_neg_test(
|
||||
ops: &CommonOps, elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
ops: &CommonOps,
|
||||
elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
test_file: test::File,
|
||||
) {
|
||||
test::run(test_file, |section, test_case| {
|
||||
@ -716,7 +747,8 @@ mod tests {
|
||||
// `GFp_p384_scalar_sqr_rep_mont()`.
|
||||
|
||||
fn scalar_square_test(
|
||||
ops: &ScalarOps, sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb),
|
||||
ops: &ScalarOps,
|
||||
sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb),
|
||||
test_file: test::File,
|
||||
) {
|
||||
test::run(test_file, |section, test_case| {
|
||||
@ -912,7 +944,7 @@ mod tests {
|
||||
let (x, y) = match consume_point(ops, test_case, "p") {
|
||||
TestPoint::Infinity => {
|
||||
panic!("can't be inf.");
|
||||
},
|
||||
}
|
||||
TestPoint::Affine(x, y) => (x, y),
|
||||
};
|
||||
let expected_result = consume_point(ops, test_case, "r");
|
||||
@ -932,7 +964,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn point_mul_serialized_test(
|
||||
priv_ops: &PrivateKeyOps, pub_ops: &PublicKeyOps, test_file: test::File,
|
||||
priv_ops: &PrivateKeyOps,
|
||||
pub_ops: &PublicKeyOps,
|
||||
test_file: test::File,
|
||||
) {
|
||||
let cops = pub_ops.common;
|
||||
|
||||
@ -997,7 +1031,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn assert_point_actual_equals_expected(
|
||||
ops: &PrivateKeyOps, actual_point: &Point, expected_point: &TestPoint,
|
||||
ops: &PrivateKeyOps,
|
||||
actual_point: &Point,
|
||||
expected_point: &TestPoint,
|
||||
) {
|
||||
let cops = ops.common;
|
||||
let actual_x = &cops.point_x(&actual_point);
|
||||
@ -1007,7 +1043,7 @@ mod tests {
|
||||
TestPoint::Infinity => {
|
||||
let zero = Elem::zero();
|
||||
assert_elems_are_equal(cops, &actual_z, &zero);
|
||||
},
|
||||
}
|
||||
TestPoint::Affine(expected_x, expected_y) => {
|
||||
let zz_inv = ops.elem_inverse_squared(&actual_z);
|
||||
let x_aff = cops.elem_product(&actual_x, &zz_inv);
|
||||
@ -1019,12 +1055,14 @@ mod tests {
|
||||
|
||||
assert_elems_are_equal(cops, &x_aff, &expected_x);
|
||||
assert_elems_are_equal(cops, &y_aff, &expected_y);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn consume_jacobian_point(
|
||||
ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str,
|
||||
ops: &PrivateKeyOps,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
) -> Point {
|
||||
let input = test_case.consume_string(name);
|
||||
let elems = input.split(", ").collect::<Vec<&str>>();
|
||||
@ -1041,7 +1079,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn consume_affine_point(
|
||||
ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str,
|
||||
ops: &PrivateKeyOps,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
) -> AffinePoint {
|
||||
let input = test_case.consume_string(name);
|
||||
let elems = input.split(", ").collect::<Vec<&str>>();
|
||||
@ -1098,7 +1138,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn assert_limbs_are_equal(
|
||||
ops: &CommonOps, actual: &[Limb; MAX_LIMBS], expected: &[Limb; MAX_LIMBS],
|
||||
ops: &CommonOps,
|
||||
actual: &[Limb; MAX_LIMBS],
|
||||
expected: &[Limb; MAX_LIMBS],
|
||||
) {
|
||||
for i in 0..ops.num_limbs {
|
||||
if actual[i] != expected[i] {
|
||||
@ -1132,7 +1174,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn consume_scalar_mont(
|
||||
ops: &CommonOps, test_case: &mut test::TestCase, name: &str,
|
||||
ops: &CommonOps,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
) -> Scalar<R> {
|
||||
let bytes = test_case.consume_bytes(name);
|
||||
let bytes = untrusted::Input::from(&bytes);
|
||||
@ -1146,7 +1190,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn consume_padded_bytes(
|
||||
ops: &CommonOps, test_case: &mut test::TestCase, name: &str,
|
||||
ops: &CommonOps,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
) -> Vec<u8> {
|
||||
let unpadded_bytes = test_case.consume_bytes(name);
|
||||
let mut bytes = vec![0; (ops.num_limbs * LIMB_BYTES) - unpadded_bytes.len()];
|
||||
|
@ -48,7 +48,8 @@ impl<M, E: Encoding> Elem<M, E> {
|
||||
|
||||
#[inline]
|
||||
pub fn mul_mont<M, EA: Encoding, EB: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &Elem<M, EA>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
|
||||
a: &Elem<M, EA>,
|
||||
b: &Elem<M, EB>,
|
||||
) -> Elem<M, <(EA, EB) as ProductEncoding>::Output>
|
||||
where
|
||||
@ -60,7 +61,8 @@ where
|
||||
// let r = f(a, b); return r;
|
||||
#[inline]
|
||||
pub fn binary_op<M, EA: Encoding, EB: Encoding, ER: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &Elem<M, EA>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
|
||||
a: &Elem<M, EA>,
|
||||
b: &Elem<M, EB>,
|
||||
) -> Elem<M, ER> {
|
||||
let mut r = Elem {
|
||||
@ -75,7 +77,8 @@ pub fn binary_op<M, EA: Encoding, EB: Encoding, ER: Encoding>(
|
||||
// a := f(a, b);
|
||||
#[inline]
|
||||
pub fn binary_op_assign<M, EA: Encoding, EB: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &mut Elem<M, EA>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
|
||||
a: &mut Elem<M, EA>,
|
||||
b: &Elem<M, EB>,
|
||||
) {
|
||||
unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr()) }
|
||||
@ -84,7 +87,8 @@ pub fn binary_op_assign<M, EA: Encoding, EB: Encoding>(
|
||||
// let r = f(a); return r;
|
||||
#[inline]
|
||||
pub fn unary_op<M, E: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), a: &Elem<M, E>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
a: &Elem<M, E>,
|
||||
) -> Elem<M, E> {
|
||||
let mut r = Elem {
|
||||
limbs: [0; MAX_LIMBS],
|
||||
@ -98,7 +102,8 @@ pub fn unary_op<M, E: Encoding>(
|
||||
// a := f(a);
|
||||
#[inline]
|
||||
pub fn unary_op_assign<M, E: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), a: &mut Elem<M, E>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
|
||||
a: &mut Elem<M, E>,
|
||||
) {
|
||||
unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr()) }
|
||||
}
|
||||
@ -106,7 +111,8 @@ pub fn unary_op_assign<M, E: Encoding>(
|
||||
// a := f(a, a);
|
||||
#[inline]
|
||||
pub fn unary_op_from_binary_op_assign<M, E: Encoding>(
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &mut Elem<M, E>,
|
||||
f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
|
||||
a: &mut Elem<M, E>,
|
||||
) {
|
||||
unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), a.limbs.as_ptr()) }
|
||||
}
|
||||
|
@ -180,10 +180,14 @@ fn p256_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
|
||||
// 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f
|
||||
|
||||
#[inline]
|
||||
fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> { binary_op(GFp_p256_scalar_mul_mont, a, b) }
|
||||
fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
|
||||
binary_op(GFp_p256_scalar_mul_mont, a, b)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sqr(a: &Scalar<R>) -> Scalar<R> { unary_op(GFp_p256_scalar_sqr_mont, a) }
|
||||
fn sqr(a: &Scalar<R>) -> Scalar<R> {
|
||||
unary_op(GFp_p256_scalar_sqr_mont, a)
|
||||
}
|
||||
|
||||
// Returns (`a` squared `squarings` times) * `b`.
|
||||
fn sqr_mul(a: &Scalar<R>, squarings: Limb, b: &Scalar<R>) -> Scalar<R> {
|
||||
|
@ -206,11 +206,17 @@ fn p384_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
|
||||
// 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf\
|
||||
// 581a0db248b0a77aecec196accc52971.
|
||||
|
||||
fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> { binary_op(GFp_p384_scalar_mul_mont, a, b) }
|
||||
fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
|
||||
binary_op(GFp_p384_scalar_mul_mont, a, b)
|
||||
}
|
||||
|
||||
fn sqr(a: &Scalar<R>) -> Scalar<R> { binary_op(GFp_p384_scalar_mul_mont, a, a) }
|
||||
fn sqr(a: &Scalar<R>) -> Scalar<R> {
|
||||
binary_op(GFp_p384_scalar_mul_mont, a, a)
|
||||
}
|
||||
|
||||
fn sqr_mut(a: &mut Scalar<R>) { unary_op_from_binary_op_assign(GFp_p384_scalar_mul_mont, a); }
|
||||
fn sqr_mut(a: &mut Scalar<R>) {
|
||||
unary_op_from_binary_op_assign(GFp_p384_scalar_mul_mont, a);
|
||||
}
|
||||
|
||||
// Returns (`a` squared `squarings` times) * `b`.
|
||||
fn sqr_mul(a: &Scalar<R>, squarings: usize, b: &Scalar<R>) -> Scalar<R> {
|
||||
|
@ -26,7 +26,8 @@ use untrusted;
|
||||
|
||||
/// Generates a random scalar in the range [1, n).
|
||||
pub fn random_scalar(
|
||||
ops: &PrivateKeyOps, rng: &rand::SecureRandom,
|
||||
ops: &PrivateKeyOps,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<Scalar, error::Unspecified> {
|
||||
let num_limbs = ops.common.num_limbs;
|
||||
let mut bytes = [0; ec::SCALAR_MAX_BYTES];
|
||||
@ -36,7 +37,9 @@ pub fn random_scalar(
|
||||
}
|
||||
|
||||
pub fn generate_private_scalar_bytes(
|
||||
ops: &PrivateKeyOps, rng: &rand::SecureRandom, out: &mut [u8],
|
||||
ops: &PrivateKeyOps,
|
||||
rng: &rand::SecureRandom,
|
||||
out: &mut [u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
// [NSA Suite B Implementer's Guide to ECDSA] Appendix A.1.2, and
|
||||
// [NSA Suite B Implementer's Guide to NIST SP 800-56A] Appendix B.2,
|
||||
@ -94,7 +97,8 @@ pub fn private_key_as_scalar(ops: &PrivateKeyOps, private_key: &ec::Seed) -> Sca
|
||||
}
|
||||
|
||||
pub fn check_scalar_big_endian_bytes(
|
||||
ops: &PrivateKeyOps, bytes: &[u8],
|
||||
ops: &PrivateKeyOps,
|
||||
bytes: &[u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
debug_assert_eq!(bytes.len(), ops.common.num_limbs * LIMB_BYTES);
|
||||
scalar_from_big_endian_bytes(ops, bytes).map(|_| ())
|
||||
@ -106,7 +110,8 @@ pub fn check_scalar_big_endian_bytes(
|
||||
// valid value, but it might leak small amounts of information about an invalid
|
||||
// value (which constraint it failed).
|
||||
pub fn scalar_from_big_endian_bytes(
|
||||
ops: &PrivateKeyOps, bytes: &[u8],
|
||||
ops: &PrivateKeyOps,
|
||||
bytes: &[u8],
|
||||
) -> Result<Scalar, error::Unspecified> {
|
||||
// [NSA Suite B Implementer's Guide to ECDSA] Appendix A.1.2, and
|
||||
// [NSA Suite B Implementer's Guide to NIST SP 800-56A] Appendix B.2,
|
||||
@ -127,7 +132,9 @@ pub fn scalar_from_big_endian_bytes(
|
||||
}
|
||||
|
||||
pub fn public_from_private(
|
||||
ops: &PrivateKeyOps, public_out: &mut [u8], my_private_key: &ec::Seed,
|
||||
ops: &PrivateKeyOps,
|
||||
public_out: &mut [u8],
|
||||
my_private_key: &ec::Seed,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let elem_and_scalar_bytes = ops.common.num_limbs * LIMB_BYTES;
|
||||
debug_assert_eq!(public_out.len(), 1 + (2 * elem_and_scalar_bytes));
|
||||
@ -142,7 +149,8 @@ pub fn public_from_private(
|
||||
}
|
||||
|
||||
pub fn affine_from_jacobian(
|
||||
ops: &PrivateKeyOps, p: &Point,
|
||||
ops: &PrivateKeyOps,
|
||||
p: &Point,
|
||||
) -> Result<(Elem<R>, Elem<R>), error::Unspecified> {
|
||||
let z = ops.common.point_z(p);
|
||||
|
||||
@ -176,7 +184,10 @@ pub fn affine_from_jacobian(
|
||||
}
|
||||
|
||||
pub fn big_endian_affine_from_jacobian(
|
||||
ops: &PrivateKeyOps, x_out: Option<&mut [u8]>, y_out: Option<&mut [u8]>, p: &Point,
|
||||
ops: &PrivateKeyOps,
|
||||
x_out: Option<&mut [u8]>,
|
||||
y_out: Option<&mut [u8]>,
|
||||
p: &Point,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let (x_aff, y_aff) = affine_from_jacobian(ops, p)?;
|
||||
let num_limbs = ops.common.num_limbs;
|
||||
|
@ -28,7 +28,8 @@ use untrusted;
|
||||
/// [NIST SP 800-56A, revision 2]:
|
||||
/// http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
|
||||
pub fn parse_uncompressed_point(
|
||||
ops: &PublicKeyOps, input: untrusted::Input,
|
||||
ops: &PublicKeyOps,
|
||||
input: untrusted::Input,
|
||||
) -> Result<(Elem<R>, Elem<R>), error::Unspecified> {
|
||||
// NIST SP 800-56A Step 1: "Verify that Q is not the point at infinity.
|
||||
// This can be done by inspection if the point is entered in the standard
|
||||
|
@ -37,17 +37,23 @@ macro_rules! impl_endian {
|
||||
|
||||
impl From<$base> for $endian<$base> {
|
||||
#[inline]
|
||||
fn from(value: $base) -> Self { Self($base::$to_endian(value)) }
|
||||
fn from(value: $base) -> Self {
|
||||
Self($base::$to_endian(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Wrapping<$base>> for $endian<$base> {
|
||||
#[inline]
|
||||
fn from(Wrapping(value): Wrapping<$base>) -> Self { Self($base::$to_endian(value)) }
|
||||
fn from(Wrapping(value): Wrapping<$base>) -> Self {
|
||||
Self($base::$to_endian(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$endian<$base>> for $base {
|
||||
#[inline]
|
||||
fn from($endian(value): $endian<$base>) -> Self { $base::$from_endian(value) }
|
||||
fn from($endian(value): $endian<$base>) -> Self {
|
||||
$base::$from_endian(value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
72
src/error.rs
72
src/error.rs
@ -83,7 +83,9 @@ use std;
|
||||
pub struct Unspecified;
|
||||
|
||||
impl Unspecified {
|
||||
fn description_() -> &'static str { "ring::error::Unspecified" }
|
||||
fn description_() -> &'static str {
|
||||
"ring::error::Unspecified"
|
||||
}
|
||||
}
|
||||
|
||||
// This is required for the implementation of `std::error::Error`.
|
||||
@ -96,17 +98,25 @@ impl core::fmt::Display for Unspecified {
|
||||
#[cfg(feature = "use_heap")]
|
||||
impl std::error::Error for Unspecified {
|
||||
#[inline]
|
||||
fn cause(&self) -> Option<&std::error::Error> { None }
|
||||
fn cause(&self) -> Option<&std::error::Error> {
|
||||
None
|
||||
}
|
||||
|
||||
fn description(&self) -> &str { Self::description_() }
|
||||
fn description(&self) -> &str {
|
||||
Self::description_()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<untrusted::EndOfInput> for Unspecified {
|
||||
fn from(_: untrusted::EndOfInput) -> Self { Unspecified }
|
||||
fn from(_: untrusted::EndOfInput) -> Self {
|
||||
Unspecified
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TryFromSliceError> for Unspecified {
|
||||
fn from(_: TryFromSliceError) -> Self { Unspecified }
|
||||
fn from(_: TryFromSliceError) -> Self {
|
||||
Unspecified
|
||||
}
|
||||
}
|
||||
|
||||
/// An error parsing or validating a key.
|
||||
@ -144,40 +154,64 @@ pub struct KeyRejected(&'static str);
|
||||
|
||||
impl KeyRejected {
|
||||
/// The value returned from <Self as std::error::Error>::description()
|
||||
pub fn description_(&self) -> &'static str { self.0 }
|
||||
pub fn description_(&self) -> &'static str {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub(crate) fn inconsistent_components() -> Self { KeyRejected("InconsistentComponents") }
|
||||
pub(crate) fn inconsistent_components() -> Self {
|
||||
KeyRejected("InconsistentComponents")
|
||||
}
|
||||
|
||||
pub(crate) fn invalid_component() -> Self { KeyRejected("InvalidComponent") }
|
||||
pub(crate) fn invalid_component() -> Self {
|
||||
KeyRejected("InvalidComponent")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn invalid_encoding() -> Self { KeyRejected("InvalidEncoding") }
|
||||
pub(crate) fn invalid_encoding() -> Self {
|
||||
KeyRejected("InvalidEncoding")
|
||||
}
|
||||
|
||||
pub(crate) fn public_key_is_missing() -> Self { KeyRejected("PublicKeyIsMissing") }
|
||||
pub(crate) fn public_key_is_missing() -> Self {
|
||||
KeyRejected("PublicKeyIsMissing")
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
pub(crate) fn too_small() -> Self { KeyRejected("TooSmall") }
|
||||
pub(crate) fn too_small() -> Self {
|
||||
KeyRejected("TooSmall")
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
pub(crate) fn too_large() -> Self { KeyRejected("TooLarge") }
|
||||
pub(crate) fn too_large() -> Self {
|
||||
KeyRejected("TooLarge")
|
||||
}
|
||||
|
||||
pub(crate) fn version_not_supported() -> Self { KeyRejected("VersionNotSupported") }
|
||||
pub(crate) fn version_not_supported() -> Self {
|
||||
KeyRejected("VersionNotSupported")
|
||||
}
|
||||
|
||||
pub(crate) fn wrong_algorithm() -> Self { KeyRejected("WrongAlgorithm") }
|
||||
pub(crate) fn wrong_algorithm() -> Self {
|
||||
KeyRejected("WrongAlgorithm")
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
pub(crate) fn private_modulus_len_not_multiple_of_512_bits() -> Self {
|
||||
KeyRejected("PrivateModulusLenNotMultipleOf512Bits")
|
||||
}
|
||||
|
||||
pub(crate) fn unexpected_error() -> Self { KeyRejected("UnexpectedError") }
|
||||
pub(crate) fn unexpected_error() -> Self {
|
||||
KeyRejected("UnexpectedError")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
impl std::error::Error for KeyRejected {
|
||||
fn cause(&self) -> Option<&std::error::Error> { None }
|
||||
fn cause(&self) -> Option<&std::error::Error> {
|
||||
None
|
||||
}
|
||||
|
||||
fn description(&self) -> &str { self.description_() }
|
||||
fn description(&self) -> &str {
|
||||
self.description_()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
@ -188,5 +222,7 @@ impl std::fmt::Display for KeyRejected {
|
||||
}
|
||||
|
||||
impl From<KeyRejected> for Unspecified {
|
||||
fn from(_: KeyRejected) -> Self { Unspecified }
|
||||
fn from(_: KeyRejected) -> Self {
|
||||
Unspecified
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,9 @@ impl Prk {
|
||||
///
|
||||
/// [HKDF-Expand]: https://tools.ietf.org/html/rfc5869#section-2.3
|
||||
#[inline]
|
||||
pub fn expand<'a>(&'a self, info: &'a [u8]) -> Okm<'a> { Okm { prk: self, info } }
|
||||
pub fn expand<'a>(&'a self, info: &'a [u8]) -> Okm<'a> {
|
||||
Okm { prk: self, info }
|
||||
}
|
||||
}
|
||||
|
||||
/// An HKDF OKM (Output Keying Material)
|
||||
|
15
src/hmac.rs
15
src/hmac.rs
@ -137,7 +137,9 @@ pub struct Tag(digest::Digest);
|
||||
|
||||
impl AsRef<[u8]> for Tag {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// A key to use for HMAC signing.
|
||||
@ -181,7 +183,8 @@ impl Key {
|
||||
/// The key will be `digest_alg.output_len` bytes long, based on the
|
||||
/// recommendation in https://tools.ietf.org/html/rfc2104#section-3.
|
||||
pub fn generate(
|
||||
digest_alg: &'static digest::Algorithm, rng: &rand::SecureRandom,
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let mut key_bytes = [0; digest::MAX_OUTPUT_LEN];
|
||||
let key_bytes = &mut key_bytes[..digest_alg.output_len];
|
||||
@ -279,11 +282,15 @@ impl core::fmt::Debug for Context {
|
||||
impl Context {
|
||||
/// Constructs a new HMAC signing context using the given digest algorithm
|
||||
/// and key.
|
||||
pub fn with_key(signing_key: &Key) -> Self { signing_key.ctx_prototype.clone() }
|
||||
pub fn with_key(signing_key: &Key) -> Self {
|
||||
signing_key.ctx_prototype.clone()
|
||||
}
|
||||
|
||||
/// Updates the HMAC with all the data in `data`. `update` may be called
|
||||
/// zero or more times until `finish` is called.
|
||||
pub fn update(&mut self, data: &[u8]) { self.inner.update(data); }
|
||||
pub fn update(&mut self, data: &[u8]) {
|
||||
self.inner.update(data);
|
||||
}
|
||||
|
||||
/// Finalizes the HMAC calculation and returns the HMAC value. `sign`
|
||||
/// consumes the context so it cannot be (mis-)used after `sign` has been
|
||||
|
@ -42,15 +42,20 @@ pub enum Tag {
|
||||
}
|
||||
|
||||
impl From<Tag> for usize {
|
||||
fn from(tag: Tag) -> Self { tag as Self }
|
||||
fn from(tag: Tag) -> Self {
|
||||
tag as Self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Tag> for u8 {
|
||||
fn from(tag: Tag) -> Self { tag as Self } // XXX: narrowing conversion.
|
||||
fn from(tag: Tag) -> Self {
|
||||
tag as Self
|
||||
} // XXX: narrowing conversion.
|
||||
}
|
||||
|
||||
pub fn expect_tag_and_get_value<'a>(
|
||||
input: &mut untrusted::Reader<'a>, tag: Tag,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
tag: Tag,
|
||||
) -> Result<untrusted::Input<'a>, error::Unspecified> {
|
||||
let (actual_tag, inner) = read_tag_and_get_value(input)?;
|
||||
if usize::from(tag) != usize::from(actual_tag) {
|
||||
@ -78,7 +83,7 @@ pub fn read_tag_and_get_value<'a>(
|
||||
return Err(error::Unspecified); // Not the canonical encoding.
|
||||
}
|
||||
usize::from(second_byte)
|
||||
},
|
||||
}
|
||||
0x82 => {
|
||||
let second_byte = usize::from(input.read_byte()?);
|
||||
let third_byte = usize::from(input.read_byte()?);
|
||||
@ -87,10 +92,10 @@ pub fn read_tag_and_get_value<'a>(
|
||||
return Err(error::Unspecified); // Not the canonical encoding.
|
||||
}
|
||||
combined
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
return Err(error::Unspecified); // We don't support longer lengths.
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let inner = input.read_bytes(length)?;
|
||||
@ -112,7 +117,10 @@ pub fn bit_string_with_no_unused_bits<'a>(
|
||||
// TODO: investigate taking decoder as a reference to reduce generated code
|
||||
// size.
|
||||
pub fn nested<'a, F, R, E: Copy>(
|
||||
input: &mut untrusted::Reader<'a>, tag: Tag, error: E, decoder: F,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
tag: Tag,
|
||||
error: E,
|
||||
decoder: F,
|
||||
) -> Result<R, E>
|
||||
where
|
||||
F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
|
||||
@ -122,7 +130,8 @@ where
|
||||
}
|
||||
|
||||
fn nonnegative_integer<'a>(
|
||||
input: &mut untrusted::Reader<'a>, min_value: u8,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
min_value: u8,
|
||||
) -> Result<untrusted::Input<'a>, error::Unspecified> {
|
||||
// Verify that |input|, which has had any leading zero stripped off, is the
|
||||
// encoding of a value of at least |min_value|.
|
||||
|
@ -36,7 +36,9 @@ impl<'a> Positive<'a> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn big_endian_without_leading_zero_as_input(&self) -> untrusted::Input<'a> { self.0 }
|
||||
pub(crate) fn big_endian_without_leading_zero_as_input(&self) -> untrusted::Input<'a> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Positive<'_> {
|
||||
|
@ -22,16 +22,24 @@ pub(super) struct LengthMeasurement {
|
||||
}
|
||||
|
||||
impl Into<usize> for LengthMeasurement {
|
||||
fn into(self) -> usize { self.len }
|
||||
fn into(self) -> usize {
|
||||
self.len
|
||||
}
|
||||
}
|
||||
|
||||
impl LengthMeasurement {
|
||||
pub fn zero() -> Self { Self { len: 0 } }
|
||||
pub fn zero() -> Self {
|
||||
Self { len: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Accumulator for LengthMeasurement {
|
||||
fn write_byte(&mut self, _value: u8) { self.len += 1; }
|
||||
fn write_bytes(&mut self, value: &[u8]) { self.len += value.len(); }
|
||||
fn write_byte(&mut self, _value: u8) {
|
||||
self.len += 1;
|
||||
}
|
||||
fn write_bytes(&mut self, value: &[u8]) {
|
||||
self.len += value.len();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Writer {
|
||||
@ -56,8 +64,12 @@ impl Into<Box<[u8]>> for Writer {
|
||||
}
|
||||
|
||||
impl Accumulator for Writer {
|
||||
fn write_byte(&mut self, value: u8) { self.bytes.push(value); }
|
||||
fn write_bytes(&mut self, value: &[u8]) { self.bytes.extend(value); }
|
||||
fn write_byte(&mut self, value: u8) {
|
||||
self.bytes.push(value);
|
||||
}
|
||||
fn write_bytes(&mut self, value: &[u8]) {
|
||||
self.bytes.extend(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_copy(accumulator: &mut Accumulator, to_copy: untrusted::Input) {
|
||||
|
21
src/limb.rs
21
src/limb.rs
@ -152,7 +152,10 @@ pub enum AllowZero {
|
||||
/// `AllowZero::Yes`, or [1, m) if `allow_zero` is `AllowZero::No`. `result` is
|
||||
/// padded with zeros to its length.
|
||||
pub fn parse_big_endian_in_range_partially_reduced_and_pad_consttime(
|
||||
input: untrusted::Input, allow_zero: AllowZero, m: &[Limb], result: &mut [Limb],
|
||||
input: untrusted::Input,
|
||||
allow_zero: AllowZero,
|
||||
m: &[Limb],
|
||||
result: &mut [Limb],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
parse_big_endian_and_pad_consttime(input, result)?;
|
||||
limbs_reduce_once_constant_time(result, m);
|
||||
@ -173,7 +176,10 @@ pub fn parse_big_endian_in_range_partially_reduced_and_pad_consttime(
|
||||
/// about a valid value, but it might leak small amounts of information about an
|
||||
/// invalid value (which constraint it failed).
|
||||
pub fn parse_big_endian_in_range_and_pad_consttime(
|
||||
input: untrusted::Input, allow_zero: AllowZero, max_exclusive: &[Limb], result: &mut [Limb],
|
||||
input: untrusted::Input,
|
||||
allow_zero: AllowZero,
|
||||
max_exclusive: &[Limb],
|
||||
result: &mut [Limb],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
parse_big_endian_and_pad_consttime(input, result)?;
|
||||
if limbs_less_than_limbs_consttime(&result, max_exclusive) != LimbMask::True {
|
||||
@ -191,7 +197,8 @@ pub fn parse_big_endian_in_range_and_pad_consttime(
|
||||
/// This attempts to be constant-time with respect to the value but not with
|
||||
/// respect to the length; it is assumed that the length is public knowledge.
|
||||
pub fn parse_big_endian_and_pad_consttime(
|
||||
input: untrusted::Input, result: &mut [Limb],
|
||||
input: untrusted::Input,
|
||||
result: &mut [Limb],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
if input.is_empty() {
|
||||
return Err(error::Unspecified);
|
||||
@ -265,7 +272,9 @@ pub type Window = Limb;
|
||||
/// Panics if `limbs` is empty.
|
||||
#[cfg(feature = "use_heap")]
|
||||
pub fn fold_5_bit_windows<R, I: FnOnce(Window) -> R, F: Fn(R, Window) -> R>(
|
||||
limbs: &[Limb], init: I, fold: F,
|
||||
limbs: &[Limb],
|
||||
init: I,
|
||||
fold: F,
|
||||
) -> R {
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
@ -275,7 +284,9 @@ pub fn fold_5_bit_windows<R, I: FnOnce(Window) -> R, F: Fn(R, Window) -> R>(
|
||||
|
||||
extern "C" {
|
||||
fn LIMBS_window5_split_window(
|
||||
lower_limb: Limb, higher_limb: Limb, index_within_word: BitIndex,
|
||||
lower_limb: Limb,
|
||||
higher_limb: Limb,
|
||||
index_within_word: BitIndex,
|
||||
) -> Window;
|
||||
fn LIMBS_window5_unsplit_window(limb: Limb, index_within_word: BitIndex) -> Window;
|
||||
}
|
||||
|
@ -137,7 +137,10 @@ use core::num::NonZeroU32;
|
||||
/// `derive` panics if `out.len()` is larger than (2**32 - 1) * the digest
|
||||
/// algorithm's output length, per the PBKDF2 specification.
|
||||
pub fn derive(
|
||||
digest_alg: &'static digest::Algorithm, iterations: NonZeroU32, salt: &[u8], secret: &[u8],
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
iterations: NonZeroU32,
|
||||
salt: &[u8],
|
||||
secret: &[u8],
|
||||
out: &mut [u8],
|
||||
) {
|
||||
let output_len = digest_alg.output_len;
|
||||
@ -203,7 +206,10 @@ fn derive_block(secret: &hmac::Key, iterations: NonZeroU32, salt: &[u8], idx: u3
|
||||
/// `verify` panics if `out.len()` is larger than (2**32 - 1) * the digest
|
||||
/// algorithm's output length, per the PBKDF2 specification.
|
||||
pub fn verify(
|
||||
digest_alg: &'static digest::Algorithm, iterations: NonZeroU32, salt: &[u8], secret: &[u8],
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
iterations: NonZeroU32,
|
||||
salt: &[u8],
|
||||
secret: &[u8],
|
||||
previously_derived: &[u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
if previously_derived.is_empty() {
|
||||
|
26
src/pkcs8.rs
26
src/pkcs8.rs
@ -49,9 +49,13 @@ pub(crate) struct Template {
|
||||
|
||||
impl Template {
|
||||
#[inline]
|
||||
fn alg_id_value(&self) -> untrusted::Input { untrusted::Input::from(self.alg_id_value_()) }
|
||||
fn alg_id_value(&self) -> untrusted::Input {
|
||||
untrusted::Input::from(self.alg_id_value_())
|
||||
}
|
||||
|
||||
fn alg_id_value_(&self) -> &[u8] { &self.bytes[self.alg_id_range.start..self.alg_id_range.end] }
|
||||
fn alg_id_value_(&self) -> &[u8] {
|
||||
&self.bytes[self.alg_id_range.start..self.alg_id_range.end]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn curve_oid(&self) -> untrusted::Input {
|
||||
@ -66,7 +70,9 @@ impl Template {
|
||||
///
|
||||
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||
pub(crate) fn unwrap_key<'a>(
|
||||
template: &Template, version: Version, input: untrusted::Input<'a>,
|
||||
template: &Template,
|
||||
version: Version,
|
||||
input: untrusted::Input<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
unwrap_key_(template.alg_id_value(), version, input)
|
||||
}
|
||||
@ -82,7 +88,9 @@ pub(crate) fn unwrap_key<'a>(
|
||||
///
|
||||
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||
pub(crate) fn unwrap_key_<'a>(
|
||||
alg_id: untrusted::Input, version: Version, input: untrusted::Input<'a>,
|
||||
alg_id: untrusted::Input,
|
||||
version: Version,
|
||||
input: untrusted::Input<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
input.read_all(error::KeyRejected::invalid_encoding(), |input| {
|
||||
der::nested(
|
||||
@ -95,7 +103,9 @@ pub(crate) fn unwrap_key_<'a>(
|
||||
}
|
||||
|
||||
fn unwrap_key__<'a>(
|
||||
alg_id: untrusted::Input, version: Version, input: &mut untrusted::Reader<'a>,
|
||||
alg_id: untrusted::Input,
|
||||
version: Version,
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
let actual_version = der::small_nonnegative_integer(input)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
@ -121,7 +131,7 @@ fn unwrap_key__<'a>(
|
||||
(1, Version::V1OrV2) | (1, Version::V2Only) => true,
|
||||
_ => {
|
||||
return Err(error::KeyRejected::version_not_supported());
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)
|
||||
@ -160,7 +170,9 @@ pub struct Document {
|
||||
|
||||
impl AsRef<[u8]> for Document {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] { &self.bytes[..self.len] }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.bytes[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn wrap_key(template: &Template, private_key: &[u8], public_key: &[u8]) -> Document {
|
||||
|
@ -21,10 +21,14 @@ use core;
|
||||
pub mod convert;
|
||||
|
||||
#[inline(always)]
|
||||
pub const fn u64_from_usize(x: usize) -> u64 { x as u64 }
|
||||
pub const fn u64_from_usize(x: usize) -> u64 {
|
||||
x as u64
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn usize_from_u32(x: u32) -> usize { x as usize }
|
||||
pub fn usize_from_u32(x: u32) -> usize {
|
||||
x as usize
|
||||
}
|
||||
|
||||
/// `core::num::Wrapping` doesn't support `rotate_left`.
|
||||
/// There is no usable trait for `rotate_left`, so this polyfill just
|
||||
|
@ -32,7 +32,9 @@ where
|
||||
T: From_<F>,
|
||||
{
|
||||
#[inline]
|
||||
fn into_(self) -> T { T::from_(self) }
|
||||
fn into_(self) -> T {
|
||||
T::from_(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// An approximation of the unstable `core::convert::TryFrom`.
|
||||
@ -59,7 +61,9 @@ where
|
||||
type Error = <T as TryFrom_<F>>::Error;
|
||||
|
||||
#[inline]
|
||||
fn try_into_(self) -> Result<T, Self::Error> { T::try_from_(self) }
|
||||
fn try_into_(self) -> Result<T, Self::Error> {
|
||||
T::try_from_(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -101,7 +105,8 @@ unsafe fn transmute_slice<A, T>(slice: &[T], expected_len: usize) -> Result<&A,
|
||||
}
|
||||
|
||||
unsafe fn transmute_slice_mut<A, T>(
|
||||
slice: &mut [T], expected_len: usize,
|
||||
slice: &mut [T],
|
||||
expected_len: usize,
|
||||
) -> Result<&mut A, TryFromSliceError> {
|
||||
if slice.len() != expected_len {
|
||||
return Err(TryFromSliceError(()));
|
||||
|
14
src/rand.rs
14
src/rand.rs
@ -83,12 +83,16 @@ pub struct SystemRandom;
|
||||
impl SystemRandom {
|
||||
/// Constructs a new `SystemRandom`.
|
||||
#[inline(always)]
|
||||
pub fn new() -> Self { Self }
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl SecureRandom for SystemRandom {
|
||||
#[inline(always)]
|
||||
fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> { fill_impl(dest) }
|
||||
fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
|
||||
fill_impl(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl sealed::Sealed for SystemRandom {}
|
||||
@ -227,7 +231,7 @@ mod urandom {
|
||||
Ok(ref file) => {
|
||||
use std::io::Read;
|
||||
(&*file).read_exact(dest).map_err(|_| error::Unspecified)
|
||||
},
|
||||
}
|
||||
Err(_) => Err(error::Unspecified),
|
||||
}
|
||||
}
|
||||
@ -290,7 +294,9 @@ mod darwin {
|
||||
// For now `rnd` must be `kSecRandomDefault`.
|
||||
#[must_use]
|
||||
fn SecRandomCopyBytes(
|
||||
rnd: &'static SecRandomRef, count: libc::size_t, bytes: *mut u8,
|
||||
rnd: &'static SecRandomRef,
|
||||
count: libc::size_t,
|
||||
bytes: *mut u8,
|
||||
) -> libc::c_int;
|
||||
}
|
||||
}
|
||||
|
@ -73,12 +73,16 @@ struct BoxedLimbs<M> {
|
||||
impl<M> Deref for BoxedLimbs<M> {
|
||||
type Target = [Limb];
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target { &self.limbs }
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.limbs
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> DerefMut for BoxedLimbs<M> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.limbs }
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.limbs
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: `derive(Clone)` after https://github.com/rust-lang/rust/issues/26925
|
||||
@ -121,7 +125,8 @@ impl<M> BoxedLimbs<M> {
|
||||
}
|
||||
|
||||
fn from_be_bytes_padded_less_than(
|
||||
input: untrusted::Input, m: &Modulus<M>,
|
||||
input: untrusted::Input,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let mut r = Self::zero(m.width());
|
||||
limb::parse_big_endian_and_pad_consttime(input, &mut r)?;
|
||||
@ -132,7 +137,9 @@ impl<M> BoxedLimbs<M> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool { limb::limbs_are_zero_constant_time(&self.limbs) == LimbMask::True }
|
||||
fn is_zero(&self) -> bool {
|
||||
limb::limbs_are_zero_constant_time(&self.limbs) == LimbMask::True
|
||||
}
|
||||
|
||||
fn zero(width: Width<M>) -> Self {
|
||||
use std::borrow::ToOwned;
|
||||
@ -301,7 +308,9 @@ impl<M> Modulus<M> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn width(&self) -> Width<M> { self.limbs.width() }
|
||||
fn width(&self) -> Width<M> {
|
||||
self.limbs.width()
|
||||
}
|
||||
|
||||
fn zero<E>(&self) -> Elem<M, E> {
|
||||
Elem {
|
||||
@ -317,7 +326,9 @@ impl<M> Modulus<M> {
|
||||
r
|
||||
}
|
||||
|
||||
pub fn oneRR(&self) -> &One<M, RR> { &self.oneRR }
|
||||
pub fn oneRR(&self) -> &One<M, RR> {
|
||||
&self.oneRR
|
||||
}
|
||||
|
||||
pub fn to_elem<L>(&self, l: &Modulus<L>) -> Elem<L, Unencoded>
|
||||
where
|
||||
@ -390,7 +401,9 @@ impl<M, E> Clone for Elem<M, E> {
|
||||
|
||||
impl<M, E> Elem<M, E> {
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool { self.limbs.is_zero() }
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.limbs.is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, E: ReductionEncoding> Elem<M, E> {
|
||||
@ -414,12 +427,15 @@ impl<M, E: ReductionEncoding> Elem<M, E> {
|
||||
|
||||
impl<M> Elem<M, R> {
|
||||
#[inline]
|
||||
pub fn into_unencoded(self, m: &Modulus<M>) -> Elem<M, Unencoded> { self.decode_once(m) }
|
||||
pub fn into_unencoded(self, m: &Modulus<M>) -> Elem<M, Unencoded> {
|
||||
self.decode_once(m)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Elem<M, Unencoded> {
|
||||
pub fn from_be_bytes_padded(
|
||||
input: untrusted::Input, m: &Modulus<M>,
|
||||
input: untrusted::Input,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Elem {
|
||||
limbs: BoxedLimbs::from_be_bytes_padded_less_than(input, m)?,
|
||||
@ -445,7 +461,9 @@ impl<M> Elem<M, Unencoded> {
|
||||
}
|
||||
|
||||
pub fn elem_mul<M, AF, BF>(
|
||||
a: &Elem<M, AF>, b: Elem<M, BF>, m: &Modulus<M>,
|
||||
a: &Elem<M, AF>,
|
||||
b: Elem<M, BF>,
|
||||
m: &Modulus<M>,
|
||||
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
|
||||
where
|
||||
(AF, BF): ProductEncoding,
|
||||
@ -454,7 +472,9 @@ where
|
||||
}
|
||||
|
||||
fn elem_mul_<M, AF, BF>(
|
||||
a: &Elem<M, AF>, mut b: Elem<M, BF>, m: &PartialModulus<M>,
|
||||
a: &Elem<M, AF>,
|
||||
mut b: Elem<M, BF>,
|
||||
m: &PartialModulus<M>,
|
||||
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
|
||||
where
|
||||
(AF, BF): ProductEncoding,
|
||||
@ -481,7 +501,8 @@ fn elem_mul_by_2<M, AF>(a: &mut Elem<M, AF>, m: &PartialModulus<M>) {
|
||||
}
|
||||
|
||||
pub fn elem_reduced_once<Larger, Smaller: SlightlySmallerModulus<Larger>>(
|
||||
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>,
|
||||
a: &Elem<Larger, Unencoded>,
|
||||
m: &Modulus<Smaller>,
|
||||
) -> Elem<Smaller, Unencoded> {
|
||||
let mut r = a.limbs.clone();
|
||||
assert!(r.len() <= m.limbs.len());
|
||||
@ -497,12 +518,18 @@ pub fn elem_reduced_once<Larger, Smaller: SlightlySmallerModulus<Larger>>(
|
||||
|
||||
#[inline]
|
||||
pub fn elem_reduced<Larger, Smaller: NotMuchSmallerModulus<Larger>>(
|
||||
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>,
|
||||
a: &Elem<Larger, Unencoded>,
|
||||
m: &Modulus<Smaller>,
|
||||
) -> Result<Elem<Smaller, RInverse>, error::Unspecified> {
|
||||
extern "C" {
|
||||
fn GFp_bn_from_montgomery_in_place(
|
||||
r: *mut Limb, num_r: size_t, a: *mut Limb, num_a: size_t, n: *const Limb,
|
||||
num_n: size_t, n0: &N0,
|
||||
r: *mut Limb,
|
||||
num_r: size_t,
|
||||
a: *mut Limb,
|
||||
num_a: size_t,
|
||||
n: *const Limb,
|
||||
num_n: size_t,
|
||||
n0: &N0,
|
||||
) -> bssl::Result;
|
||||
}
|
||||
|
||||
@ -526,7 +553,8 @@ pub fn elem_reduced<Larger, Smaller: NotMuchSmallerModulus<Larger>>(
|
||||
}
|
||||
|
||||
fn elem_squared<M, E>(
|
||||
mut a: Elem<M, E>, m: &PartialModulus<M>,
|
||||
mut a: Elem<M, E>,
|
||||
m: &PartialModulus<M>,
|
||||
) -> Elem<M, <(E, E) as ProductEncoding>::Output>
|
||||
where
|
||||
(E, E): ProductEncoding,
|
||||
@ -539,7 +567,8 @@ where
|
||||
}
|
||||
|
||||
pub fn elem_widen<Larger, Smaller: SmallerModulus<Larger>>(
|
||||
a: Elem<Smaller, Unencoded>, m: &Modulus<Larger>,
|
||||
a: Elem<Smaller, Unencoded>,
|
||||
m: &Modulus<Larger>,
|
||||
) -> Elem<Larger, Unencoded> {
|
||||
let mut r = m.zero();
|
||||
r.limbs[..a.limbs.len()].copy_from_slice(&a.limbs);
|
||||
@ -551,7 +580,11 @@ pub fn elem_add<M, E>(mut a: Elem<M, E>, b: Elem<M, E>, m: &Modulus<M>) -> Elem<
|
||||
extern "C" {
|
||||
// `r` and `a` may alias.
|
||||
fn LIMBS_add_mod(
|
||||
r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: size_t,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
b: *const Limb,
|
||||
m: *const Limb,
|
||||
num_limbs: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -571,7 +604,11 @@ pub fn elem_sub<M, E>(mut a: Elem<M, E>, b: &Elem<M, E>, m: &Modulus<M>) -> Elem
|
||||
extern "C" {
|
||||
// `r` and `a` may alias.
|
||||
fn LIMBS_sub_mod(
|
||||
r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: size_t,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
b: *const Limb,
|
||||
m: *const Limb,
|
||||
num_limbs: size_t,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -637,7 +674,9 @@ impl<M> One<M, RR> {
|
||||
}
|
||||
|
||||
impl<M, E> AsRef<Elem<M, E>> for One<M, E> {
|
||||
fn as_ref(&self) -> &Elem<M, E> { &self.0 }
|
||||
fn as_ref(&self) -> &Elem<M, E> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A non-secret odd positive value in the range
|
||||
@ -647,7 +686,8 @@ pub struct PublicExponent(u64);
|
||||
|
||||
impl PublicExponent {
|
||||
pub fn from_be_bytes(
|
||||
input: untrusted::Input, min_value: u64,
|
||||
input: untrusted::Input,
|
||||
min_value: u64,
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
if input.len() > 5 {
|
||||
return Err(error::KeyRejected::too_large());
|
||||
@ -710,7 +750,9 @@ const PUBLIC_EXPONENT_MAX_VALUE: u64 = (1u64 << 33) - 1;
|
||||
// TODO: The test coverage needs to be expanded, e.g. test with the largest
|
||||
// accepted exponent and with the most common values of 65537 and 3.
|
||||
pub fn elem_exp_vartime<M>(
|
||||
base: Elem<M, Unencoded>, PublicExponent(exponent): PublicExponent, m: &Modulus<M>,
|
||||
base: Elem<M, Unencoded>,
|
||||
PublicExponent(exponent): PublicExponent,
|
||||
m: &Modulus<M>,
|
||||
) -> Elem<M, R> {
|
||||
let base = elem_mul(m.oneRR().as_ref(), base, &m);
|
||||
elem_exp_vartime_(base, exponent, &m.as_partial())
|
||||
@ -760,7 +802,8 @@ pub struct PrivateExponent<M> {
|
||||
|
||||
impl<M> PrivateExponent<M> {
|
||||
pub fn from_be_bytes_padded(
|
||||
input: untrusted::Input, p: &Modulus<M>,
|
||||
input: untrusted::Input,
|
||||
p: &Modulus<M>,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
let dP = BoxedLimbs::from_be_bytes_padded_less_than(input, p)?;
|
||||
|
||||
@ -793,7 +836,9 @@ impl<M: Prime> PrivateExponent<M> {
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
pub fn elem_exp_consttime<M>(
|
||||
base: Elem<M, R>, exponent: &PrivateExponent<M>, m: &Modulus<M>,
|
||||
base: Elem<M, R>,
|
||||
exponent: &PrivateExponent<M>,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
|
||||
use crate::limb::Window;
|
||||
|
||||
@ -807,7 +852,10 @@ pub fn elem_exp_consttime<M>(
|
||||
fn gather<M>(table: &[Limb], i: Window, r: &mut Elem<M, R>) {
|
||||
extern "C" {
|
||||
fn LIMBS_select_512_32(
|
||||
r: *mut Limb, table: *const Limb, num_limbs: size_t, i: Window,
|
||||
r: *mut Limb,
|
||||
table: *const Limb,
|
||||
num_limbs: size_t,
|
||||
i: Window,
|
||||
) -> bssl::Result;
|
||||
}
|
||||
Result::from(unsafe {
|
||||
@ -817,7 +865,11 @@ pub fn elem_exp_consttime<M>(
|
||||
}
|
||||
|
||||
fn power<M>(
|
||||
table: &[Limb], i: Window, mut acc: Elem<M, R>, mut tmp: Elem<M, R>, m: &Modulus<M>,
|
||||
table: &[Limb],
|
||||
i: Window,
|
||||
mut acc: Elem<M, R>,
|
||||
mut tmp: Elem<M, R>,
|
||||
m: &Modulus<M>,
|
||||
) -> (Elem<M, R>, Elem<M, R>) {
|
||||
for _ in 0..WINDOW_BITS {
|
||||
acc = elem_squared(acc, &m.as_partial());
|
||||
@ -872,14 +924,17 @@ pub fn elem_exp_consttime<M>(
|
||||
|
||||
/// Uses Fermat's Little Theorem to calculate modular inverse in constant time.
|
||||
pub fn elem_inverse_consttime<M: Prime>(
|
||||
a: Elem<M, R>, m: &Modulus<M>,
|
||||
a: Elem<M, R>,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
|
||||
elem_exp_consttime(a, &PrivateExponent::for_flt(&m), m)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn elem_exp_consttime<M>(
|
||||
base: Elem<M, R>, exponent: &PrivateExponent<M>, m: &Modulus<M>,
|
||||
base: Elem<M, R>,
|
||||
exponent: &PrivateExponent<M>,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
|
||||
// The x86_64 assembly was written under the assumption that the input data
|
||||
// is aligned to `MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH` bytes, which was/is
|
||||
@ -960,8 +1015,13 @@ pub fn elem_exp_consttime<M>(
|
||||
fn gather_mul_base(table: &[Limb], state: &mut [Limb], n0: &N0, i: Window, num_limbs: usize) {
|
||||
extern "C" {
|
||||
fn GFp_bn_mul_mont_gather5(
|
||||
rp: *mut Limb, ap: *const Limb, table: *const Limb, np: *const Limb, n0: &N0,
|
||||
num: size_t, power: Window,
|
||||
rp: *mut Limb,
|
||||
ap: *const Limb,
|
||||
table: *const Limb,
|
||||
np: *const Limb,
|
||||
n0: &N0,
|
||||
num: size_t,
|
||||
power: Window,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -980,8 +1040,13 @@ pub fn elem_exp_consttime<M>(
|
||||
fn power(table: &[Limb], state: &mut [Limb], n0: &N0, i: Window, num_limbs: usize) {
|
||||
extern "C" {
|
||||
fn GFp_bn_power5(
|
||||
r: *mut Limb, a: *const Limb, table: *const Limb, n: *const Limb, n0: &N0,
|
||||
num: size_t, i: Window,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
table: *const Limb,
|
||||
n: *const Limb,
|
||||
n0: &N0,
|
||||
num: size_t,
|
||||
i: Window,
|
||||
);
|
||||
}
|
||||
unsafe {
|
||||
@ -1033,7 +1098,11 @@ pub fn elem_exp_consttime<M>(
|
||||
|
||||
extern "C" {
|
||||
fn GFp_bn_from_montgomery(
|
||||
r: *mut Limb, a: *const Limb, not_used: *const Limb, n: *const Limb, n0: &N0,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
not_used: *const Limb,
|
||||
n: *const Limb,
|
||||
n0: &N0,
|
||||
num: size_t,
|
||||
) -> bssl::Result;
|
||||
}
|
||||
@ -1057,7 +1126,9 @@ pub fn elem_exp_consttime<M>(
|
||||
|
||||
/// Verified a == b**-1 (mod m), i.e. a**-1 == b (mod m).
|
||||
pub fn verify_inverses_consttime<M>(
|
||||
a: &Elem<M, R>, b: Elem<M, Unencoded>, m: &Modulus<M>,
|
||||
a: &Elem<M, R>,
|
||||
b: Elem<M, Unencoded>,
|
||||
m: &Modulus<M>,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
if elem_mul(a, b, m).is_one() {
|
||||
Ok(())
|
||||
@ -1068,7 +1139,8 @@ pub fn verify_inverses_consttime<M>(
|
||||
|
||||
#[inline]
|
||||
pub fn elem_verify_equal_consttime<M, E>(
|
||||
a: &Elem<M, E>, b: &Elem<M, E>,
|
||||
a: &Elem<M, E>,
|
||||
b: &Elem<M, E>,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
if limb::limbs_equal_limbs_consttime(&a.limbs, &b.limbs) == LimbMask::True {
|
||||
Ok(())
|
||||
@ -1210,7 +1282,12 @@ fn limbs_mont_square(r: &mut [Limb], m: &[Limb], n0: &N0) {
|
||||
extern "C" {
|
||||
// `r` and/or 'a' and/or 'b' may alias.
|
||||
fn GFp_bn_mul_mont(
|
||||
r: *mut Limb, a: *const Limb, b: *const Limb, n: *const Limb, n0: &N0, num_limbs: size_t,
|
||||
r: *mut Limb,
|
||||
a: *const Limb,
|
||||
b: *const Limb,
|
||||
n: *const Limb,
|
||||
n0: &N0,
|
||||
num_limbs: size_t,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1365,14 +1442,18 @@ mod tests {
|
||||
}
|
||||
|
||||
fn consume_elem<M>(
|
||||
test_case: &mut test::TestCase, name: &str, m: &Modulus<M>,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
m: &Modulus<M>,
|
||||
) -> Elem<M, Unencoded> {
|
||||
let value = test_case.consume_bytes(name);
|
||||
Elem::from_be_bytes_padded(untrusted::Input::from(&value), m).unwrap()
|
||||
}
|
||||
|
||||
fn consume_elem_unchecked<M>(
|
||||
test_case: &mut test::TestCase, name: &str, num_limbs: usize,
|
||||
test_case: &mut test::TestCase,
|
||||
name: &str,
|
||||
num_limbs: usize,
|
||||
) -> Elem<M, Unencoded> {
|
||||
let value = consume_nonnegative(test_case, name);
|
||||
let mut limbs = BoxedLimbs::zero(Width {
|
||||
|
@ -33,7 +33,10 @@ pub trait Padding: 'static + Sync + crate::sealed::Sealed + core::fmt::Debug {
|
||||
pub trait RsaEncoding: Padding {
|
||||
#[doc(hidden)]
|
||||
fn encode(
|
||||
&self, m_hash: &digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m_out: &mut [u8],
|
||||
mod_bits: bits::BitLength,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<(), error::Unspecified>;
|
||||
}
|
||||
@ -44,7 +47,10 @@ pub trait RsaEncoding: Padding {
|
||||
/// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
|
||||
pub trait Verification: Padding {
|
||||
fn verify(
|
||||
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m: &mut untrusted::Reader,
|
||||
mod_bits: bits::BitLength,
|
||||
) -> Result<(), error::Unspecified>;
|
||||
}
|
||||
|
||||
@ -63,13 +69,18 @@ pub struct PKCS1 {
|
||||
impl crate::sealed::Sealed for PKCS1 {}
|
||||
|
||||
impl Padding for PKCS1 {
|
||||
fn digest_alg(&self) -> &'static digest::Algorithm { self.digest_alg }
|
||||
fn digest_alg(&self) -> &'static digest::Algorithm {
|
||||
self.digest_alg
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
impl RsaEncoding for PKCS1 {
|
||||
fn encode(
|
||||
&self, m_hash: &digest::Digest, m_out: &mut [u8], _mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m_out: &mut [u8],
|
||||
_mod_bits: bits::BitLength,
|
||||
_rng: &rand::SecureRandom,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
pkcs1_encode(&self, m_hash, m_out);
|
||||
@ -79,7 +90,10 @@ impl RsaEncoding for PKCS1 {
|
||||
|
||||
impl Verification for PKCS1 {
|
||||
fn verify(
|
||||
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m: &mut untrusted::Reader,
|
||||
mod_bits: bits::BitLength,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
// `mod_bits.as_usize_bytes_rounded_up() <=
|
||||
// PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN` is ensured by `verify_rsa_()`.
|
||||
@ -213,14 +227,19 @@ impl crate::sealed::Sealed for PSS {}
|
||||
const MAX_SALT_LEN: usize = digest::MAX_OUTPUT_LEN;
|
||||
|
||||
impl Padding for PSS {
|
||||
fn digest_alg(&self) -> &'static digest::Algorithm { self.digest_alg }
|
||||
fn digest_alg(&self) -> &'static digest::Algorithm {
|
||||
self.digest_alg
|
||||
}
|
||||
}
|
||||
|
||||
impl RsaEncoding for PSS {
|
||||
// Implement padding procedure per EMSA-PSS,
|
||||
// https://tools.ietf.org/html/rfc3447#section-9.1.
|
||||
fn encode(
|
||||
&self, m_hash: &digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m_out: &mut [u8],
|
||||
mod_bits: bits::BitLength,
|
||||
rng: &rand::SecureRandom,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
|
||||
@ -289,7 +308,10 @@ impl Verification for PSS {
|
||||
// RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
|
||||
// where steps 1, 2(a), and 2(b) have been done for us.
|
||||
fn verify(
|
||||
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
|
||||
&self,
|
||||
m_hash: &digest::Digest,
|
||||
m: &mut untrusted::Reader,
|
||||
mod_bits: bits::BitLength,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
|
||||
|
||||
@ -387,7 +409,8 @@ struct PSSMetrics {
|
||||
|
||||
impl PSSMetrics {
|
||||
fn new(
|
||||
digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength,
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
mod_bits: bits::BitLength,
|
||||
) -> Result<PSSMetrics, error::Unspecified> {
|
||||
let em_bits = mod_bits.try_sub_1()?;
|
||||
let em_len = em_bits.as_usize_bytes_rounded_up();
|
||||
@ -426,7 +449,9 @@ impl PSSMetrics {
|
||||
// Mask-generating function MGF1 as described in
|
||||
// https://tools.ietf.org/html/rfc3447#appendix-B.2.1.
|
||||
fn mgf1(
|
||||
digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8],
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
seed: &[u8],
|
||||
mask: &mut [u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let digest_len = digest_alg.output_len;
|
||||
|
||||
@ -446,7 +471,9 @@ fn mgf1(
|
||||
}
|
||||
|
||||
fn pss_digest(
|
||||
digest_alg: &'static digest::Algorithm, m_hash: &digest::Digest, salt: &[u8],
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
m_hash: &digest::Digest,
|
||||
salt: &[u8],
|
||||
) -> digest::Digest {
|
||||
// Fixed prefix.
|
||||
const PREFIX_ZEROS: [u8; 8] = [0u8; 8];
|
||||
|
@ -209,7 +209,7 @@ impl RsaKeyPair {
|
||||
Err(error::Unspecified) => {
|
||||
// TODO: verify `q` and `qInv` are inverses (mod p).
|
||||
((q, q_bits, dQ), (p, p_bits, dP, None))
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// XXX: Some steps are done out of order, but the NIST steps are worded
|
||||
@ -388,7 +388,9 @@ impl RsaKeyPair {
|
||||
impl signature::KeyPair for RsaKeyPair {
|
||||
type PublicKey = RsaSubjectPublicKey;
|
||||
|
||||
fn public_key(&self) -> &Self::PublicKey { &self.public_key }
|
||||
fn public_key(&self) -> &Self::PublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
}
|
||||
|
||||
/// A serialized RSA public key.
|
||||
@ -396,7 +398,9 @@ impl signature::KeyPair for RsaKeyPair {
|
||||
pub struct RsaSubjectPublicKey(Box<[u8]>);
|
||||
|
||||
impl AsRef<[u8]> for RsaSubjectPublicKey {
|
||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
derive_debug_self_as_ref_hex_bytes!(RsaSubjectPublicKey);
|
||||
@ -462,7 +466,8 @@ impl<M: Prime + Clone> PrivatePrime<M> {
|
||||
}
|
||||
|
||||
fn elem_exp_consttime<M, MM>(
|
||||
c: &bigint::Elem<MM>, p: &PrivatePrime<M>,
|
||||
c: &bigint::Elem<MM>,
|
||||
p: &PrivatePrime<M>,
|
||||
) -> Result<bigint::Elem<M>, error::Unspecified>
|
||||
where
|
||||
M: bigint::NotMuchSmallerModulus<MM>,
|
||||
@ -527,7 +532,10 @@ impl RsaKeyPair {
|
||||
/// x86-64, this is done pretty well, but not perfectly. On other
|
||||
/// platforms, it is done less perfectly.
|
||||
pub fn sign(
|
||||
&self, padding_alg: &'static RsaEncoding, rng: &rand::SecureRandom, msg: &[u8],
|
||||
&self,
|
||||
padding_alg: &'static RsaEncoding,
|
||||
rng: &rand::SecureRandom,
|
||||
msg: &[u8],
|
||||
signature: &mut [u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let mod_bits = self.public.n_bits;
|
||||
|
@ -28,8 +28,11 @@ pub struct Key {
|
||||
|
||||
impl Key {
|
||||
pub fn from_modulus_and_exponent(
|
||||
n: untrusted::Input, e: untrusted::Input, n_min_bits: bits::BitLength,
|
||||
n_max_bits: bits::BitLength, e_min_value: u64,
|
||||
n: untrusted::Input,
|
||||
e: untrusted::Input,
|
||||
n_min_bits: bits::BitLength,
|
||||
n_max_bits: bits::BitLength,
|
||||
e_min_value: u64,
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
// This is an incomplete implementation of NIST SP800-56Br1 Section
|
||||
// 6.4.2.2, "Partial Public-Key Validation for RSA." That spec defers
|
||||
@ -79,7 +82,10 @@ impl Key {
|
||||
|
||||
impl signature::VerificationAlgorithm for RsaParameters {
|
||||
fn verify(
|
||||
&self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input,
|
||||
&self,
|
||||
public_key: untrusted::Input,
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let (n, e) = parse_public_key(public_key)?;
|
||||
verify_rsa_(
|
||||
@ -225,7 +231,10 @@ where
|
||||
/// (padding, digest algorithm, key length range, etc.) are used in the
|
||||
/// verification.
|
||||
pub fn verify(
|
||||
&self, params: &RsaParameters, message: &[u8], signature: &[u8],
|
||||
&self,
|
||||
params: &RsaParameters,
|
||||
message: &[u8],
|
||||
signature: &[u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let _ = cpu::features();
|
||||
verify_rsa_(
|
||||
@ -241,7 +250,9 @@ where
|
||||
}
|
||||
|
||||
pub(crate) fn verify_rsa_(
|
||||
params: &RsaParameters, (n, e): (untrusted::Input, untrusted::Input), msg: untrusted::Input,
|
||||
params: &RsaParameters,
|
||||
(n, e): (untrusted::Input, untrusted::Input),
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let max_bits = bits::BitLength::from_usize_bytes(PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN)?;
|
||||
|
@ -330,7 +330,9 @@ impl Signature {
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Signature {
|
||||
fn as_ref(&self) -> &[u8] { &self.value[..self.len] }
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.value[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
/// Key pairs for signing messages (private key and public key).
|
||||
@ -354,7 +356,10 @@ pub trait VerificationAlgorithm: core::fmt::Debug + Sync + sealed::Sealed {
|
||||
/// Verify the signature `signature` of message `msg` with the public key
|
||||
/// `public_key`.
|
||||
fn verify(
|
||||
&self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input,
|
||||
&self,
|
||||
public_key: untrusted::Input,
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified>;
|
||||
}
|
||||
|
||||
@ -406,7 +411,9 @@ impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
|
||||
/// [UnparsedPublicKey::verify()]: UnparsedPublicKey::verify
|
||||
#[deprecated(note = "Use UnparsedPublicKey::verify")]
|
||||
pub fn verify(
|
||||
algorithm: &'static VerificationAlgorithm, public_key: untrusted::Input, msg: untrusted::Input,
|
||||
algorithm: &'static VerificationAlgorithm,
|
||||
public_key: untrusted::Input,
|
||||
msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
UnparsedPublicKey::new(algorithm, public_key.as_slice_less_safe())
|
||||
|
53
src/test.rs
53
src/test.rs
@ -208,18 +208,18 @@ impl TestCase {
|
||||
} else {
|
||||
panic!("Invalid hex escape sequence in string.");
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
panic!("Invalid hex escape sequence in string.");
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Some(b'"') => {
|
||||
if s.next().is_some() {
|
||||
panic!("characters after the closing quote of a quoted string.");
|
||||
}
|
||||
break;
|
||||
},
|
||||
}
|
||||
Some(b) => *b,
|
||||
None => panic!("Missing terminating '\"' in string literal."),
|
||||
};
|
||||
@ -232,7 +232,7 @@ impl TestCase {
|
||||
Ok(s) => s,
|
||||
Err(err_str) => {
|
||||
panic!("{} in {}", err_str, s);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,7 +325,7 @@ where
|
||||
failed = true;
|
||||
Err("Test didn't consume all attributes.")
|
||||
}
|
||||
},
|
||||
}
|
||||
Ok(Err(_)) => Err("Test returned Err(error::Unspecified)."),
|
||||
Err(_) => Err("Test panicked."),
|
||||
};
|
||||
@ -377,7 +377,8 @@ fn from_hex_digit(d: u8) -> Result<u8, String> {
|
||||
}
|
||||
|
||||
fn parse_test_case(
|
||||
current_section: &mut String, lines: &mut Iterator<Item = &str>,
|
||||
current_section: &mut String,
|
||||
lines: &mut Iterator<Item = &str>,
|
||||
) -> Option<TestCase> {
|
||||
let mut attributes = Vec::new();
|
||||
|
||||
@ -396,12 +397,12 @@ fn parse_test_case(
|
||||
// then we're done.
|
||||
None if is_first_line => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
|
||||
// End of the file on a non-empty test cases ends the test case.
|
||||
None => {
|
||||
return Some(TestCase { attributes });
|
||||
},
|
||||
}
|
||||
|
||||
// A blank line ends a test case if the test case isn't empty.
|
||||
Some(ref line) if line.is_empty() => {
|
||||
@ -409,7 +410,7 @@ fn parse_test_case(
|
||||
return Some(TestCase { attributes });
|
||||
}
|
||||
// Ignore leading blank lines.
|
||||
},
|
||||
}
|
||||
|
||||
// Comments start with '#'; ignore them.
|
||||
Some(ref line) if line.starts_with('#') => (),
|
||||
@ -421,7 +422,7 @@ fn parse_test_case(
|
||||
current_section.push_str(line);
|
||||
let _ = current_section.pop();
|
||||
let _ = current_section.remove(0);
|
||||
},
|
||||
}
|
||||
|
||||
Some(ref line) => {
|
||||
is_first_line = false;
|
||||
@ -440,7 +441,7 @@ fn parse_test_case(
|
||||
|
||||
// Checking is_none() ensures we don't accept duplicate keys.
|
||||
attributes.push((String::from(key), String::from(value), false));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -559,15 +560,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn first_err() { err_one(0) }
|
||||
fn first_err() {
|
||||
err_one(0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn middle_err() { err_one(1) }
|
||||
fn middle_err() {
|
||||
err_one(1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn last_err() { err_one(2) }
|
||||
fn last_err() {
|
||||
err_one(2)
|
||||
}
|
||||
|
||||
fn err_one(test_to_fail: usize) {
|
||||
let mut n = 0;
|
||||
@ -585,15 +592,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn first_panic() { panic_one(0) }
|
||||
fn first_panic() {
|
||||
panic_one(0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn middle_panic() { panic_one(1) }
|
||||
fn middle_panic() {
|
||||
panic_one(1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Test failed.")]
|
||||
fn last_panic() { panic_one(2) }
|
||||
fn last_panic() {
|
||||
panic_one(2)
|
||||
}
|
||||
|
||||
fn panic_one(test_to_fail: usize) {
|
||||
let mut n = 0;
|
||||
@ -609,5 +622,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Syntax error: Expected Key = Value.")]
|
||||
fn syntax_error() { test::run(test_file!("test_1_syntax_error_tests.txt"), |_, _| Ok(())); }
|
||||
fn syntax_error() {
|
||||
test::run(test_file!("test_1_syntax_error_tests.txt"), |_, _| Ok(()));
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,14 @@
|
||||
use ring::{aead, error, test, test_file};
|
||||
|
||||
#[test]
|
||||
fn aead_aes_gcm_128() { test_aead(&aead::AES_128_GCM, test_file!("aead_aes_128_gcm_tests.txt")); }
|
||||
fn aead_aes_gcm_128() {
|
||||
test_aead(&aead::AES_128_GCM, test_file!("aead_aes_128_gcm_tests.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aead_aes_gcm_256() { test_aead(&aead::AES_256_GCM, test_file!("aead_aes_256_gcm_tests.txt")); }
|
||||
fn aead_aes_gcm_256() {
|
||||
test_aead(&aead::AES_256_GCM, test_file!("aead_aes_256_gcm_tests.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aead_chacha20_poly1305() {
|
||||
@ -64,7 +68,7 @@ fn test_aead(aead_alg: &'static aead::Algorithm, test_file: test::File) {
|
||||
Some(err) if err == "WRONG_NONCE_LENGTH" => {
|
||||
assert!(aead::Nonce::try_assume_unique_for_key(&nonce).is_err());
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
@ -177,14 +181,14 @@ fn test_aead(aead_alg: &'static aead::Algorithm, test_file: test::File) {
|
||||
None => {
|
||||
assert!(s_result.is_ok());
|
||||
assert_eq!(&plaintext[..], o_result.unwrap());
|
||||
},
|
||||
}
|
||||
Some(ref error) if error == "WRONG_NONCE_LENGTH" => {
|
||||
assert_eq!(Err(error::Unspecified), s_result);
|
||||
assert_eq!(Err(error::Unspecified), o_result);
|
||||
},
|
||||
}
|
||||
Some(error) => {
|
||||
unreachable!("Unexpected error test case: {}", error);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ fn agreement_agree_ephemeral() {
|
||||
})
|
||||
.is_ok()
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
Some(_) => {
|
||||
// In the no-heap mode, some algorithms aren't supported so
|
||||
@ -83,7 +83,7 @@ fn agreement_agree_ephemeral() {
|
||||
kdf_not_called
|
||||
)
|
||||
.is_err());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
@ -96,7 +96,10 @@ fn test_agreement_ecdh_x25519_rfc_iterated() {
|
||||
let mut u = k.clone();
|
||||
|
||||
fn expect_iterated_x25519(
|
||||
expected_result: &str, range: std::ops::Range<usize>, k: &mut Vec<u8>, u: &mut Vec<u8>,
|
||||
expected_result: &str,
|
||||
range: std::ops::Range<usize>,
|
||||
k: &mut Vec<u8>,
|
||||
u: &mut Vec<u8>,
|
||||
) {
|
||||
for _ in range {
|
||||
let new_k = x25519(k, u);
|
||||
@ -160,7 +163,7 @@ fn h(s: &str) -> Vec<u8> {
|
||||
Ok(v) => v,
|
||||
Err(msg) => {
|
||||
panic!("{} in {}", msg, s);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ fn signature_ecdsa_verify_asn1_test() {
|
||||
("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_ASN1,
|
||||
_ => {
|
||||
panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let actual_result =
|
||||
@ -192,7 +192,7 @@ fn signature_ecdsa_verify_fixed_test() {
|
||||
("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_FIXED,
|
||||
_ => {
|
||||
panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let is_valid = expected_result == "P (0 )";
|
||||
|
@ -46,7 +46,7 @@ fn hmac_tests() {
|
||||
Some(digest_alg) => digest_alg,
|
||||
None => {
|
||||
return Ok(());
|
||||
}, // Unsupported digest algorithm
|
||||
} // Unsupported digest algorithm
|
||||
};
|
||||
|
||||
hmac_test_case_inner(digest_alg, &key_value[..], &input[..], &output[..], true)?;
|
||||
@ -63,7 +63,10 @@ fn hmac_tests() {
|
||||
}
|
||||
|
||||
fn hmac_test_case_inner(
|
||||
digest_alg: &'static digest::Algorithm, key_value: &[u8], input: &[u8], output: &[u8],
|
||||
digest_alg: &'static digest::Algorithm,
|
||||
key_value: &[u8],
|
||||
input: &[u8],
|
||||
output: &[u8],
|
||||
is_ok: bool,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let key = hmac::Key::new(digest_alg, key_value);
|
||||
|
@ -34,13 +34,19 @@
|
||||
use ring::{aead::quic, test, test_file};
|
||||
|
||||
#[test]
|
||||
fn quic_aes_128() { test_quic(&quic::AES_128, test_file!("quic_aes_128_tests.txt")); }
|
||||
fn quic_aes_128() {
|
||||
test_quic(&quic::AES_128, test_file!("quic_aes_128_tests.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quic_aes_256() { test_quic(&quic::AES_256, test_file!("quic_aes_256_tests.txt")); }
|
||||
fn quic_aes_256() {
|
||||
test_quic(&quic::AES_256, test_file!("quic_aes_256_tests.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quic_chacha20() { test_quic(&quic::CHACHA20, test_file!("quic_chacha20_tests.txt")); }
|
||||
fn quic_chacha20() {
|
||||
test_quic(&quic::CHACHA20, test_file!("quic_chacha20_tests.txt"));
|
||||
}
|
||||
|
||||
fn test_quic(alg: &'static quic::Algorithm, test_file: test::File) {
|
||||
test_sample_len(alg);
|
||||
|
Loading…
x
Reference in New Issue
Block a user