crypto::ec+x86_64 +linux

The crypto::ec module provides implementations for a selection of eliptic curves and their operations.

This is a low-level module which implements cryptographic primitives. Direct use of cryptographic primitives is not recommended for non-experts, as incorrect use of these primitives can easily lead to the introduction of security vulnerabilities. Non-experts are advised to use the high-level operations available in the top-level crypto:: module.

Be advised that Hare's cryptography implementations have not been audited.

Index

Types

type curve = struct {
	// Size in bytes of an encoded point.
	pointsz: size,
	// Returns the order of the subgroup generated by the conventional
	// generator. Unsigned big-endian encoding is used.
	order: *fn() const []u8,
	// Get the conventional generator as an encoded curve point.
	generator: *fn() const []u8,
	// Multiply curve point 'p' by scalar 'x'. The result is stored in 'r'.
	// Returns a value > 0 on success.
	//
	// Point 'p' must be a valid point on the curve subgroup. If this is
	// not the case the function fails with 0 as result.
	//
	// On error the results in 'p' are indeterminate.
	mul: *fn(p: []u8, x: []u8) u32,
	// Multiply the generator by the scalar 'x' and write the result to 'r'.
	//
	// Returns the encoded point length in bytes.
	mulgen: *fn(r: []u8, x: []u8) size,
	// Multiply two curve points ('a' and 'b') by two integers ('x' and 'y')
	// and stores the sum in 'a' ('a' = 'a' * 'x' + 'b' * 'y').
	//
	// If an empty slice is given as 'b', the curve generator is used
	// instead of 'b'.
	//
	// Returns 0 in case of failure. Validates that the provided points are
	// part of the relevant curve subgroup.
	//
	// Returns a value > 0 on success and 0 otherwise.
	muladd: *fn(a: []u8, b: []u8, x: []u8, y: []u8) u32,
	// Generate a private key from given random seed 'rand'. The function
	// may read repeatedly from 'rand' until a suitable key is found.
	//
	// Returns the size of bytes read into 'priv' on success or
	// [[io::error]], if reading from 'rand' failed.
	keygen: *fn(c: *curve, priv: []u8, rand: io::handle) (size | io::error),
};

Errors

type invalid = !void;

Constants

def MAX_COORDBITSZ = 528z;
def MAX_POINTSZ = P521_POINTSZ;
def MAX_SCALARSZ = P521_SCALARSZ;
def P256_POINTSZ = len(P256_G);
def P256_SCALARSZ = len(P256_N);
def P384_POINTSZ = len(P384_G);
def P384_SCALARSZ = len(P384_N);
def P521_POINTSZ = len(P521_G);
def P521_SCALARSZ = len(P521_N);

Globals

const p256: *curve;
const p384: *curve;
const p521: *curve;

Functions

fn keygen(c: *curve, priv: []u8, rand: io::handle) (size | io::error);
fn validate_point(c: *curve, p: []u8) (void | invalid);
fn validate_pointformat(c: *curve, p: []u8) (void | invalid);
fn validate_scalar(c: *curve, n: []u8) (void | invalid);

Types

type curve[link]

type curve = struct {
	// Size in bytes of an encoded point.
	pointsz: size,
	// Returns the order of the subgroup generated by the conventional
	// generator. Unsigned big-endian encoding is used.
	order: *fn() const []u8,
	// Get the conventional generator as an encoded curve point.
	generator: *fn() const []u8,
	// Multiply curve point 'p' by scalar 'x'. The result is stored in 'r'.
	// Returns a value > 0 on success.
	//
	// Point 'p' must be a valid point on the curve subgroup. If this is
	// not the case the function fails with 0 as result.
	//
	// On error the results in 'p' are indeterminate.
	mul: *fn(p: []u8, x: []u8) u32,
	// Multiply the generator by the scalar 'x' and write the result to 'r'.
	//
	// Returns the encoded point length in bytes.
	mulgen: *fn(r: []u8, x: []u8) size,
	// Multiply two curve points ('a' and 'b') by two integers ('x' and 'y')
	// and stores the sum in 'a' ('a' = 'a' * 'x' + 'b' * 'y').
	//
	// If an empty slice is given as 'b', the curve generator is used
	// instead of 'b'.
	//
	// Returns 0 in case of failure. Validates that the provided points are
	// part of the relevant curve subgroup.
	//
	// Returns a value > 0 on success and 0 otherwise.
	muladd: *fn(a: []u8, b: []u8, x: []u8, y: []u8) u32,
	// Generate a private key from given random seed 'rand'. The function
	// may read repeatedly from 'rand' until a suitable key is found.
	//
	// Returns the size of bytes read into 'priv' on success or
	// [[io::error]], if reading from 'rand' failed.
	keygen: *fn(c: *curve, priv: []u8, rand: io::handle) (size | io::error),
};

Interface for common operations over a specific curve.

The encoding of points depends on the curve. For the NIST curves (p256, p384 and p521 the point is required to be uncompressed with a leading byte of value 0x04. The coordinates must be of length 'pointsz' / 2, left padded by 0x0.

Scalar values must be provided in big-endian encoding. They MUST be non zero and less than the order, otherwise result values will be indeterminate and an error code is not guaranteed.

Errors

type invalid[link]

type invalid = !void;

Invalid curve parameter.

Constants

def MAX_COORDBITSZ[link]

def MAX_COORDBITSZ = 528z;

Maxium coordinate size of the modules curves in bits.

def MAX_POINTSZ[link]

def MAX_POINTSZ = P521_POINTSZ;

Maximum size of a point of the modules curves in bytes.

def MAX_SCALARSZ[link]

def MAX_SCALARSZ = P521_SCALARSZ;

Maximum size of a scalar of the modules curves in bytes.

def P256_POINTSZ[link]

def P256_POINTSZ = len(P256_G);

Size of a p256 point in bytes.

def P256_SCALARSZ[link]

def P256_SCALARSZ = len(P256_N);

Size of a p256 scalar in bytes.

def P384_POINTSZ[link]

def P384_POINTSZ = len(P384_G);

Size of a p384 point in bytes.

def P384_SCALARSZ[link]

def P384_SCALARSZ = len(P384_N);

Size of a p384 scalar in bytes.

def P521_POINTSZ[link]

def P521_POINTSZ = len(P521_G);

Size of a p521 point in bytes.

def P521_SCALARSZ[link]

def P521_SCALARSZ = len(P521_N);

Size of a p521 scalar in bytes.

Globals

let p256[link]

const p256: *curve;

A curve implementation of P-256, also known as secp256r1 or prime256v1.

let p384[link]

const p384: *curve;

A curve implementation of P-384, also known as secp384r1;

let p521[link]

const p521: *curve;

A curve implementation of P-521, also known as secp521r1;

Functions

fn keygen[link]

fn keygen(c: *curve, priv: []u8, rand: io::handle) (size | io::error);

Generates a random private key scalar suitable for given curve 'c'. 'rand' must be cryptographic random stream like the one provided by crypto::random::stream.

fn validate_point[link]

fn validate_point(c: *curve, p: []u8) (void | invalid);

Checks if given point is properly encoded and a valid point on given curve 'c'. This operation is quite expensive. Note that in any case point validation will be done on every mul and muladd operation.

fn validate_pointformat[link]

fn validate_pointformat(c: *curve, p: []u8) (void | invalid);

Checks whether the point is encoded in the curves point format. Does NOT check if it is a valid point on the curve. For such point validation use validate_point.

fn validate_scalar[link]

fn validate_scalar(c: *curve, n: []u8) (void | invalid);

Validates if given scalar is less than the curve order and greater then zero.