1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
use io;
// Maxium coordinate size of the modules curves in bits.
export def MAX_COORDBITSZ = 528z;
// Maximum size of a point of the modules curves in bytes.
export def MAX_POINTSZ = P521_POINTSZ;
// Maximum size of a scalar of the modules curves in bytes.
export def MAX_SCALARSZ = P521_SCALARSZ;
// Interface for common operations over a specific curve.
//
// The encoding of points (e.g. public keys for dsa and dh) depends on the curve.
// For the NIST curves ([[p256]], [[p384]] and [[p521]]) the point is required
// to be stored according to the uncompressed format defined in RFC 8422 Chapter
// 5.4.1. That means with a leading byte of value 0x04 that indicates the
// format. Followed by the x and y coordinates, which must be of length
// [[pointsz]] / 2, left padded by 0.
//
// Scalar values (e.g. private keys for dsa and dh) must be provided in
// big-endian encoding and left-padded to fill the indicated space. They MUST be
// non-zero and less than the curve order, otherwise result values will be
// indeterminate and an error code is not guaranteed. The function [[scalarsz]]
// will return the encoded scalar size of any curve implemented by this module.
export 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, // XXX: change to const []u8, when possible
// Get the conventional generator as an encoded curve point.
generator: *fn () const []u8, // XXX: change to const []u8, when possible
// Multiply curve point 'p' by scalar 'x'. The result is stored in 'r'.
// Returns 1 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 1 on success.
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),
};
// Returns the encoded size of any point of curve 'c'.
export fn pointsz(c: *curve) size = c.pointsz;
// Returns the encoded size of any scalar of curve 'c'.
export fn scalarsz(c: *curve) size = len(c.order());
// Invalid curve parameter.
export type invalid = !void;
|