use arithmetic::montgomery::*;
use {der, ec, error, pkcs8};
use self::ops::*;
use untrusted;
fn verify_affine_point_is_on_the_curve(
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)
}
fn verify_jacobian_point_is_on_the_curve(ops: &CommonOps, p: &Point)
-> Result<Elem<R>, error::Unspecified> {
let z = ops.point_z(p);
try!(ops.elem_verify_is_not_zero(&z));
let x = ops.point_x(p);
let y = ops.point_y(p);
let z2 = ops.elem_squared(&z);
let z4 = ops.elem_squared(&z2);
let z4_a = ops.elem_product(&z4, &ops.a);
let z6 = ops.elem_product(&z4, &z2);
let z6_b = ops.elem_product(&z6, &ops.b);
try!(verify_affine_point_is_on_the_curve_scaled(ops, (&x, &y), &z4_a,
&z6_b));
Ok(z2)
}
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>) -> Result<(), error::Unspecified> {
let lhs = ops.elem_squared(y);
let mut rhs = ops.elem_squared(x);
ops.elem_add(&mut rhs, a_scaled);
ops.elem_mul(&mut rhs, x);
ops.elem_add(&mut rhs, b_scaled);
if !ops.elems_are_equal(&lhs, &rhs) {
return Err(error::Unspecified);
}
Ok(())
}
pub fn key_pair_from_pkcs8(curve: &ec::Curve, template: &pkcs8::Template,
input: untrusted::Input)
-> Result<ec::KeyPair, error::Unspecified> {
let (ec_private_key, _) = try!(pkcs8::unwrap_key(
template, pkcs8::Version::V1Only, input));
let (private_key, public_key) = try!(ec_private_key.read_all(
error::Unspecified, |input| {
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
let version = try!(der::small_nonnegative_integer(input));
if version != 1 {
return Err(error::Unspecified);
}
let private_key = try!(der::expect_tag_and_get_value(
input, der::Tag::OctetString));
if input.peek(der::Tag::ContextSpecificConstructed0 as u8) {
let actual_alg_id = try!(der::expect_tag_and_get_value(
input, der::Tag::ContextSpecificConstructed0));
if actual_alg_id != template.curve_oid() {
return Err(error::Unspecified);
}
}
let public_key = try!(der::nested(
input, der::Tag::ContextSpecificConstructed1,
error::Unspecified, |input| {
der::bit_string_with_no_unused_bits(input)
}));
Ok((private_key, public_key))
})
}));
key_pair_from_bytes(curve, private_key, public_key)
}
pub fn key_pair_from_bytes(curve: &ec::Curve,
private_key_bytes: untrusted::Input,
public_key_bytes: untrusted::Input)
-> Result<ec::KeyPair, error::Unspecified> {
let private_key = try!(ec::PrivateKey::from_bytes(curve, private_key_bytes));
let mut public_key_check = [0; ec::PUBLIC_KEY_MAX_LEN];
{ let public_key_check = &mut public_key_check[..curve.public_key_len];
try!((curve.public_from_private)(public_key_check, &private_key));
if public_key_bytes != &*public_key_check {
return Err(error::Unspecified);
}
}
Ok(ec::KeyPair {
private_key: private_key,
public_key: public_key_check,
})
}
pub mod curve;
pub mod ecdsa;
pub mod ecdh;
#[macro_use]
#[path = "ops/ops.rs"]
mod ops;
mod private_key;
mod public_key;