rust-secp256k1/src/ffi.rs

278 lines
12 KiB
Rust

// Bitcoin secp256k1 bindings
// Written in 2014 by
// Dawid Ciężarkiewicz
// Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! # FFI bindings
//! Direct bindings to the underlying C library functions. These should
//! not be needed for most users.
use std::mem;
use std::hash;
use libc::{c_int, c_uchar, c_uint, c_void, size_t};
/// Flag for context to enable no precomputation
pub const SECP256K1_START_NONE: c_uint = (1 << 0) | 0;
/// Flag for context to enable verification precomputation
pub const SECP256K1_START_VERIFY: c_uint = (1 << 0) | (1 << 8);
/// Flag for context to enable signing precomputation
pub const SECP256K1_START_SIGN: c_uint = (1 << 0) | (1 << 9);
/// Flag for keys to indicate uncompressed serialization format
pub const SECP256K1_SER_UNCOMPRESSED: c_uint = (1 << 1) | 0;
/// Flag for keys to indicate compressed serialization format
pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8);
/// A nonce generation function. Ordinary users of the library
/// never need to see this type; only if you need to control
/// nonce generation do you need to use it. I have deliberately
/// made this hard to do: you have to write your own wrapper
/// around the FFI functions to use it. And it's an unsafe type.
/// Nonces are generated deterministically by RFC6979 by
/// default; there should be no need to ever change this.
pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar,
msg32: *const c_uchar,
key32: *const c_uchar,
algo16: *const c_uchar,
attempt: c_uint,
data: *const c_void);
/// A Secp256k1 context, containing various precomputed values and such
/// needed to do elliptic curve computations. If you create one of these
/// with `secp256k1_context_create` you MUST destroy it with
/// `secp256k1_context_destroy`, or else you will have a memory leak.
#[derive(Clone, Debug)]
#[repr(C)] pub struct Context(c_int);
/// Library-internal representation of a Secp256k1 public key
#[repr(C)]
pub struct PublicKey([c_uchar; 64]);
impl_array_newtype!(PublicKey, c_uchar, 64);
impl_raw_debug!(PublicKey);
impl PublicKey {
/// Create a new (zeroed) public key usable for the FFI interface
pub fn new() -> PublicKey { PublicKey([0; 64]) }
/// Create a new (uninitialized) public key usable for the FFI interface
pub unsafe fn blank() -> PublicKey { mem::uninitialized() }
}
impl hash::Hash for PublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
state.write(&self.0)
}
}
/// Library-internal representation of a Secp256k1 signature
#[repr(C)]
pub struct Signature([c_uchar; 64]);
impl_array_newtype!(Signature, c_uchar, 64);
impl_raw_debug!(Signature);
/// Library-internal representation of a Secp256k1 signature + recovery ID
#[repr(C)]
pub struct RecoverableSignature([c_uchar; 65]);
impl_array_newtype!(RecoverableSignature, c_uchar, 65);
impl_raw_debug!(RecoverableSignature);
impl Signature {
/// Create a new (zeroed) signature usable for the FFI interface
pub fn new() -> Signature { Signature([0; 64]) }
/// Create a new (uninitialized) signature usable for the FFI interface
pub unsafe fn blank() -> Signature { mem::uninitialized() }
}
impl RecoverableSignature {
/// Create a new (zeroed) signature usable for the FFI interface
pub fn new() -> RecoverableSignature { RecoverableSignature([0; 65]) }
/// Create a new (uninitialized) signature usable for the FFI interface
pub unsafe fn blank() -> RecoverableSignature { mem::uninitialized() }
}
/// Library-internal representation of an ECDH shared secret
#[repr(C)]
pub struct SharedSecret([c_uchar; 32]);
impl_array_newtype!(SharedSecret, c_uchar, 32);
impl_raw_debug!(SharedSecret);
impl SharedSecret {
/// Create a new (zeroed) signature usable for the FFI interface
pub fn new() -> SharedSecret { SharedSecret([0; 32]) }
/// Create a new (uninitialized) signature usable for the FFI interface
pub unsafe fn blank() -> SharedSecret { mem::uninitialized() }
}
extern "C" {
pub static secp256k1_nonce_function_rfc6979: NonceFn;
pub static secp256k1_nonce_function_default: NonceFn;
// Contexts
pub fn secp256k1_context_create(flags: c_uint) -> *mut Context;
pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context;
pub fn secp256k1_context_destroy(cx: *mut Context);
pub fn secp256k1_context_randomize(cx: *mut Context,
seed32: *const c_uchar)
-> c_int;
// TODO secp256k1_context_set_illegal_callback
// TODO secp256k1_context_set_error_callback
// (Actually, I don't really want these exposed; if either of these
// are ever triggered it indicates a bug in rust-secp256k1, since
// one goal is to use Rust's type system to eliminate all possible
// bad inputs.)
// Pubkeys
pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey,
input: *const c_uchar, in_len: size_t)
-> c_int;
pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar,
out_len: *mut size_t, pk: *const PublicKey
, compressed: c_uint)
-> c_int;
// Signatures
pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature,
input: *const c_uchar, in_len: size_t)
-> c_int;
pub fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature,
input64: *const c_uchar)
-> c_int;
pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature,
input: *const c_uchar, in_len: size_t)
-> c_int;
pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *const c_uchar,
out_len: *mut size_t, sig: *const Signature)
-> c_int;
pub fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *const c_uchar,
sig: *const Signature)
-> c_int;
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature,
input64: *const c_uchar, recid: c_int)
-> c_int;
pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar,
recid: *mut c_int, sig: *const RecoverableSignature)
-> c_int;
pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature,
input: *const RecoverableSignature)
-> c_int;
pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, out_sig: *mut Signature,
in_sig: *const Signature)
-> c_int;
// ECDSA
pub fn secp256k1_ecdsa_verify(cx: *const Context,
sig: *const Signature,
msg32: *const c_uchar,
pk: *const PublicKey)
-> c_int;
pub fn secp256k1_ecdsa_sign(cx: *const Context,
sig: *mut Signature,
msg32: *const c_uchar,
sk: *const c_uchar,
noncefn: NonceFn,
noncedata: *const c_void)
-> c_int;
pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context,
sig: *mut RecoverableSignature,
msg32: *const c_uchar,
sk: *const c_uchar,
noncefn: NonceFn,
noncedata: *const c_void)
-> c_int;
pub fn secp256k1_ecdsa_recover(cx: *const Context,
pk: *mut PublicKey,
sig: *const RecoverableSignature,
msg32: *const c_uchar)
-> c_int;
// Schnorr
pub fn secp256k1_schnorr_sign(cx: *const Context,
sig64: *mut c_uchar,
msg32: *const c_uchar,
sk: *const c_uchar,
noncefn: NonceFn,
noncedata: *const c_void)
-> c_int;
pub fn secp256k1_schnorr_verify(cx: *const Context,
sig64: *const c_uchar,
msg32: *const c_uchar,
pk: *const PublicKey)
-> c_int;
pub fn secp256k1_schnorr_recover(cx: *const Context,
pk: *mut PublicKey,
sig64: *const c_uchar,
msg32: *const c_uchar)
-> c_int;
// EC
pub fn secp256k1_ec_seckey_verify(cx: *const Context,
sk: *const c_uchar) -> c_int;
pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey,
sk: *const c_uchar) -> c_int;
//TODO secp256k1_ec_privkey_export
//TODO secp256k1_ec_privkey_import
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
sk: *mut c_uchar,
tweak: *const c_uchar)
-> c_int;
pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
pk: *mut PublicKey,
tweak: *const c_uchar)
-> c_int;
pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
sk: *mut c_uchar,
tweak: *const c_uchar)
-> c_int;
pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
pk: *mut PublicKey,
tweak: *const c_uchar)
-> c_int;
pub fn secp256k1_ec_pubkey_combine(cx: *const Context,
out: *mut PublicKey,
ins: *const *const PublicKey,
n: c_int)
-> c_int;
pub fn secp256k1_ecdh(cx: *const Context,
out: *mut SharedSecret,
point: *const PublicKey,
scalar: *const c_uchar)
-> c_int;
}