packages feed

crypton-2.1.7: cbits/tests/perf/throughput.c

/* Throughput of the primitives that have an accelerated implementation, one
 * per process so that a caller can ask for them one at a time.
 *
 * Prints MB/s over 16 KiB.  The state is set up once and the same buffer run
 * through it, which is the shape `openssl speed` measures and the shape the
 * README's tables are in.
 *
 * This is here to be compared with itself -- see run.sh -- and not to be
 * quoted.  A number from a CI runner is a number from whichever machine the
 * job landed on.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>

#include "crypton_aes.h"
#include "crypton_sha1.h"
#include "crypton_sha256.h"
#include "crypton_sha512.h"
#include "crypton_sha3.h"
#include "crypton_chacha.h"
#include "crypton_poly1305.h"

#define LEN 16384
#define REPS 12

static uint8_t inb[LEN], outb[LEN + 64];
static uint64_t sink;

static double now_us(void)
{
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return ts.tv_sec * 1e6 + ts.tv_nsec / 1e3;
}

static void bench_gcm(int keybits, int iters)
{
	aes_key key;
	aes_gcm gcm;
	uint8_t kb[32], iv[12], tag[16];
	int i;
	for (i = 0; i < 32; i++) kb[i] = (uint8_t)(i * 7);
	for (i = 0; i < 12; i++) iv[i] = (uint8_t)(i + 3);
	crypton_aes_initkey(&key, kb, keybits / 8);
	crypton_aes_gcm_init(&gcm, &key, iv, 12);
	for (i = 0; i < iters; i++) {
		crypton_aes_gcm_encrypt(outb, &gcm, &key, inb, LEN);
		sink += outb[i & 1023];
	}
	crypton_aes_gcm_finish(tag, &gcm, &key);
	sink += tag[0];
}

static void bench_chachapoly(int iters)
{
	crypton_chacha_context ctx;
	poly1305_ctx pctx;
	poly1305_key pkey;
	poly1305_mac mac;
	uint8_t kb[32], iv[12];
	int i;
	for (i = 0; i < 32; i++) kb[i] = (uint8_t)(i * 5);
	for (i = 0; i < 12; i++) iv[i] = (uint8_t)(i + 1);
	memcpy(&pkey, kb, sizeof(pkey));
	for (i = 0; i < iters; i++) {
		crypton_chacha_init(&ctx, 20, 32, kb, 12, iv);
		crypton_chacha_combine(outb, &ctx, inb, LEN);
		crypton_poly1305_init(&pctx, &pkey);
		crypton_poly1305_update(&pctx, outb, LEN);
		crypton_poly1305_finalize(mac, &pctx);
		sink += mac[0] + outb[i & 1023];
	}
}

static void bench_sha1(int iters)
{
	struct sha1_ctx c;
	uint8_t out[20];
	int i;
	for (i = 0; i < iters; i++) {
		crypton_sha1_init(&c);
		crypton_sha1_update(&c, inb, LEN);
		crypton_sha1_finalize(&c, out);
		sink += out[0];
	}
}

static void bench_sha256(int iters)
{
	struct sha256_ctx c;
	uint8_t out[32];
	int i;
	for (i = 0; i < iters; i++) {
		crypton_sha256_init(&c);
		crypton_sha256_update(&c, inb, LEN);
		crypton_sha256_finalize(&c, out);
		sink += out[0];
	}
}

static void bench_sha512(int iters)
{
	struct sha512_ctx c;
	uint8_t out[64];
	int i;
	for (i = 0; i < iters; i++) {
		crypton_sha512_init(&c);
		crypton_sha512_update(&c, inb, LEN);
		crypton_sha512_finalize(&c, out);
		sink += out[0];
	}
}

static void bench_sha3(int iters)
{
	/* sha3_ctx ends in a flexible array the caller provides room for. */
	uint8_t raw[SHA3_CTX_BUF_MAX_SIZE];
	struct sha3_ctx *c = (struct sha3_ctx *)raw;
	uint8_t out[32];
	int i;
	for (i = 0; i < iters; i++) {
		crypton_sha3_init(c, 256);
		crypton_sha3_update(c, inb, LEN);
		crypton_sha3_finalize(c, 256, out);
		sink += out[0];
	}
}

int main(int argc, char **argv)
{
	const char *algo = argc > 1 ? argv[1] : "sha256";
	int iters = 2000, r, i;
	double best = 1e30;

	for (i = 0; i < LEN; i++) inb[i] = (uint8_t)(i * 17 + 3);

	for (r = 0; r < REPS; r++) {
		double t0 = now_us(), t1;
		if      (!strcmp(algo, "aes128gcm"))  bench_gcm(128, iters);
		else if (!strcmp(algo, "aes256gcm"))  bench_gcm(256, iters);
		else if (!strcmp(algo, "chachapoly")) bench_chachapoly(iters);
		else if (!strcmp(algo, "sha1"))       bench_sha1(iters);
		else if (!strcmp(algo, "sha256"))     bench_sha256(iters);
		else if (!strcmp(algo, "sha512"))     bench_sha512(iters);
		else if (!strcmp(algo, "sha3-256"))   bench_sha3(iters);
		else { fprintf(stderr, "unknown algo %s\n", algo); return 2; }
		t1 = now_us();
		if (r > 1 && t1 - t0 < best) best = t1 - t0;
	}
	if (sink == 0) return 3;
	printf("%.1f\n", (double)LEN * iters / best);   /* bytes/us == MB/s */
	return 0;
}