crypto::rsa+x86_64 +linux

This module provides RSA signature and encryption schemes defined in PKCS #1. The implementation only supports RSA keys with two prime factors. Most of the RSA operations in this module require buffers to perform. Buffer sizes are provided for keys of a default maximum size of 4096-bits. BITSZ may be changed with compiler flags to support bigger keys. MINBITSZ defines the minimum size accordingly.

Public and private keys are stored in byte slices. pubkey_init is used to initialize a public key. privkey_init or privkey_initd is used to initialize a private key, depending on which parameters are available.

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 pkcs1_hashalgo = enum {
	SHA1,
	SHA256, // SHA224, We don't have this one yet
	SHA384,
	SHA512,
	SHA512_224,
	SHA512_256,
};
type privparams = struct {
	// Bit length of the modulus n. If unknown, the modulus can be provided
	// to the init function, which derivces the length.
	nbitlen: size,
	// First prime factor.
	p: []u8,
	// Second prime factor
	q: []u8,
	// First exponent. dp = d mod (p - 1) where d is the private exponent.
	// May be omitted on [[privkey_initd]].
	dp: []u8,
	// Second exponent. dq = d mod (q - 1) where d is the private exponent.
	// May be omitted on [[privkey_initd]].
	dq: []u8,
	// Coefficient. iq = q^-1 mod p.
	iq: []u8,
};
type pubparams = struct {
	// Modulus in big-endian order
	n: []u8,
	// Public exponent in big-endian order
	e: []u8,
};

Errors

type badsig = !void;
type error = !(badsig | errors::overflow | errors::invalid);

Constants

def BITSZ: size = 4096;
def MINBITSZ: size = 1024;
def PKCS1_SIGNBUFSZ: size = PRIVEXP_BUFSZ;
def PKCS1_VERIFYBUFSZ: size = PUBEXP_BUFSZ + BITSZ / 8;
def PRIVKEYSZ: size = 13 + (MAXFACTOR >> 3) * 5;
def PUBKEYSZ: size = 5 + 2 * (BITSZ >> 3);

Functions

fn pkcs1_sign(priv: []u8, msghash: []u8, sig: []u8, algo: pkcs1_hashalgo, buf: []u8) (void | error);
fn pkcs1_verify(pubkey: []u8, msghash: []u8, sig: []u8, algo: pkcs1_hashalgo, buf: []u8) (void | error);
fn privkey_init(privkey: []u8, x: privparams, n: []u8...) (size | error);
fn privkey_initd(privkey: []u8, x: privparams, d: []u8, n: []u8...) (size | error);
fn privkey_nbitlen(privkey: []u8) size;
fn privkey_nsize(privkey: []u8) size;
fn privkey_params(privkey: []u8) privparams;
fn pubkey_init(pubkey: []u8, x: pubparams) (size | error);
fn pubkey_nbitlen(pubkey: []u8) size;
fn pubkey_params(pubkey: []u8) pubparams;
fn strerror(err: error) str;

Types

type pkcs1_hashalgo[link]

type pkcs1_hashalgo = enum {
	SHA1,
	SHA256, // SHA224, We don't have this one yet
	SHA384,
	SHA512,
	SHA512_224,
	SHA512_256,
};

Supported hash algorithms for pkcs1_sign and pkcs1_verify.

type privparams[link]

type privparams = struct {
	// Bit length of the modulus n. If unknown, the modulus can be provided
	// to the init function, which derivces the length.
	nbitlen: size,
	// First prime factor.
	p: []u8,
	// Second prime factor
	q: []u8,
	// First exponent. dp = d mod (p - 1) where d is the private exponent.
	// May be omitted on [[privkey_initd]].
	dp: []u8,
	// Second exponent. dq = d mod (q - 1) where d is the private exponent.
	// May be omitted on [[privkey_initd]].
	dq: []u8,
	// Coefficient. iq = q^-1 mod p.
	iq: []u8,
};

RSA key parameters for initializing private keys with privkey_init. If the private exponent d is available, privkey_initd may be used, which derives 'dp' and 'dq'. All big integer values are in big-endian order.

type pubparams[link]

type pubparams = struct {
	// Modulus in big-endian order
	n: []u8,
	// Public exponent in big-endian order
	e: []u8,
};

RSA key parameters for initializing public keys with pubkey_init.

Errors

type badsig[link]

type badsig = !void;

Signature verification failed.

type error[link]

type error = !(badsig | errors::overflow | errors::invalid);

A tagged union of all RSA error types.

Constants

def BITSZ[link]

def BITSZ: size = 4096;

The default bit size of RSA keys is 4096-bit. Used as base for buffer sizes.

def MINBITSZ[link]

def MINBITSZ: size = 1024;

The minimum bit size of RSA keys used only for validation during key init. The default value is 1024-bit.

def PKCS1_SIGNBUFSZ[link]

def PKCS1_SIGNBUFSZ: size = PRIVEXP_BUFSZ;

Required buffer size for pkcs1_sign.

def PKCS1_VERIFYBUFSZ[link]

def PKCS1_VERIFYBUFSZ: size = PUBEXP_BUFSZ + BITSZ / 8;

Required buffer size for pkcs1_verify.

def PRIVKEYSZ[link]

def PRIVKEYSZ: size = 13 + (MAXFACTOR >> 3) * 5;

Size required to store a private key of BITSZ length.

def PUBKEYSZ[link]

def PUBKEYSZ: size = 5 + 2 * (BITSZ >> 3);

Size required to store a public key of BITSZ length.

Functions

fn pkcs1_sign[link]

fn pkcs1_sign(priv: []u8, msghash: []u8, sig: []u8, algo: pkcs1_hashalgo, buf: []u8) (void | error);

Signs a message hash 'msghash' using the PKCS#1 V1.5 signature scheme. The signature will be written to 'sig' which must be in the the size of the modulus n (see privkey_nsize). 'algo' defines the hash algorithm 'msghash' was created with.

A temporary buffer 'buf' of size PKCS1_SIGNBUFSZ must be provided.

fn pkcs1_verify[link]

fn pkcs1_verify(pubkey: []u8, msghash: []u8, sig: []u8, algo: pkcs1_hashalgo, buf: []u8) (void | error);

Verifies a PKCS#1 v1.5 signature given a public key 'pubkey', the message hash 'msghash', the signature 'sig' and the hash algorithm 'algo'. 'algo' must reflect the hash algorithm 'sig' was created with.

A temporary buffer 'buf' of size PKCS1_VERIFYBUFSZ must be provided.

fn privkey_init[link]

fn privkey_init(privkey: []u8, x: privparams, n: []u8...) (size | error);

Initializes the private key 'privkey' using the values from 'x'. 'nbitlen' of 'x' may be omitted, if the modulus 'n' is passed. All other values of 'x' must be present. If 'x' is missing 'dp' and 'dq' use privkey_initd.

In case of invalid parameters or if the key is too small, errors::invalid is returned. If the key does not fit 'privkey', errors::overflow is returned. On success the number of bytes written to 'privkey' is returned.

fn privkey_initd[link]

fn privkey_initd(privkey: []u8, x: privparams, d: []u8, n: []u8...) (size | error);

Initializes the private key 'privkey' using the values from 'x' and the secret exponent 'd'. 'dp' and 'dq' will be derived from 'p' and 'q' of 'x'. 'nbitlen' of 'x' may be omitted, if the modulus 'n' is passed. 'x' must provide 'iq'.

In case of invalid parameters or if the key is too small, errors::invalid is returned. If the key does not fit 'privkey', errors::overflow is returned. On success the number of bytes written to 'privkey' is returend.

fn privkey_nbitlen[link]

fn privkey_nbitlen(privkey: []u8) size;

Returns the length of the modulus 'n'.

fn privkey_nsize[link]

fn privkey_nsize(privkey: []u8) size;

Returns the number of bytes that are required to store a value modulo 'n'.

fn privkey_params[link]

fn privkey_params(privkey: []u8) privparams;

Returns the private key parameters borrowed from 'privkey'.

fn pubkey_init[link]

fn pubkey_init(pubkey: []u8, x: pubparams) (size | error);

Initializes a public key from given pubparams 'x'. The data format of 'pubkey' is subject to change and must not be used to serialize the key. PUBKEYSZ defines the required size to store a key of BITSZ.

If given key does not fit into 'pubkey' or is too small, errors::overflow is returned. Returns errors::invalid, if given key parameters are invalid. Returns the number of bytes written to 'pubkey' on success.

fn pubkey_nbitlen[link]

fn pubkey_nbitlen(pubkey: []u8) size;

Returns the length of the modulus 'n' of given public key.

fn pubkey_params[link]

fn pubkey_params(pubkey: []u8) pubparams;

Returns the public key parameters, borrowed from given 'pubkey'.

fn strerror[link]

fn strerror(err: error) str;

Converts an error into a human-friendly string representation.