@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Alistair Crooks <agc@NetBSD.org>
+ * Copyright (c) 2013,2015 Alistair Crooks <agc@NetBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,232 +86,248 @@
/*****/
static void
-wrap_sha1_init(void *v)
+wrap_md5_init(void *v)
{
- SHA1Init(v);
+ MD5Init(v);
}
static void
-wrap_md5_init(void *v)
+wrap_md5_update(void *v, const void *data, unsigned len)
{
- MD5Init(v);
+ MD5Update(v, (const uint8_t *)data, len);
}
static void
-wrap_sha256_init(void *v)
+wrap_md5_final(uint8_t *raw, void *v)
{
- SHA256_Init(v);
+ MD5Final(raw, v);
}
+/*****/
+
static void
-wrap_sha512_init(void *v)
+wrap_sha1_init(void *v)
{
- SHA512_Init(v);
+ SHA1Init(v);
}
static void
-wrap_rmd160_init(void *v)
+wrap_sha1_update(void *v, const void *data, unsigned len)
{
- RMD160Init(v);
+ SHA1Update(v, (const uint8_t *)data, len);
}
static void
-wrap_crc32c_init(void *v)
+wrap_sha1_final(uint8_t *raw, void *v)
{
- crc32c_init(v);
+ SHA1Final(raw, v);
}
+/*****/
+
static void
-wrap_tiger_init(void *v)
+wrap_sha256_init(void *v)
{
- TIGER_Init(v);
+ SHA256_Init(v);
}
static void
-wrap_tiger2_init(void *v)
+wrap_sha256_update(void *v, const void *data, unsigned len)
{
- TIGER2_Init(v);
+ SHA256_Update(v, (const uint8_t *)data, len);
}
static void
-wrap_blake2_init(void *v)
+wrap_sha256_final(uint8_t *raw, void *v)
{
- blake2b_init(v, 64);
+ SHA256_Final(raw, v);
}
+/*****/
+
static void
-wrap_whirlpool_init(void *v)
+wrap_sha512_init(void *v)
{
- whirlpool_init(v);
+ SHA512_Init(v);
}
static void
-wrap_keccak224_init(void *v)
+wrap_sha512_update(void *v, const void *data, unsigned len)
{
- KECCAK_Init(v, 224);
+ SHA512_Update(v, (const uint8_t *)data, len);
}
static void
-wrap_keccak256_init(void *v)
+wrap_sha512_final(uint8_t *raw, void *v)
{
- KECCAK_Init(v, 256);
+ SHA512_Final(raw, v);
}
+/*****/
+
static void
-wrap_keccak384_init(void *v)
+wrap_rmd160_init(void *v)
{
- KECCAK_Init(v, 384);
+ RMD160Init(v);
}
static void
-wrap_keccak512_init(void *v)
+wrap_rmd160_update(void *v, const void *data, unsigned len)
{
- KECCAK_Init(v, 512);
+ RMD160Update(v, (const uint8_t *)data, len);
}
static void
-wrap_size_init(void *v)
+wrap_rmd160_final(uint8_t *raw, void *v)
{
- memset(v, 0x0, sizeof(uint64_t));
+ RMD160Final(raw, v);
}
/*****/
static void
-wrap_md5_update(void *v, const char *data, unsigned len)
+wrap_crc32c_init(void *v)
{
- MD5Update(v, (const uint8_t *)data, len);
+ crc32c_init(v);
}
static void
-wrap_sha1_update(void *v, const char *data, unsigned len)
+wrap_crc32c_update(void *v, const void *data, unsigned len)
{
- SHA1Update(v, (const uint8_t *)data, len);
+ crc32c_update(v, (const uint8_t *)data, len);
}
static void
-wrap_sha256_update(void *v, const char *data, unsigned len)
+wrap_crc32c_final(uint8_t *raw, void *v)
{
- SHA256_Update(v, (const uint8_t *)data, len);
+ crc32c_final((ctx32_t *)(void *)raw, v);
}
-static void
-wrap_sha512_update(void *v, const char *data, unsigned len)
-{
- SHA512_Update(v, (const uint8_t *)data, len);
-}
+/*****/
static void
-wrap_rmd160_update(void *v, const char *data, unsigned len)
+wrap_tiger_init(void *v)
{
- RMD160Update(v, (const uint8_t *)data, len);
+ TIGER_Init(v);
}
static void
-wrap_crc32c_update(void *v, const char *data, unsigned len)
+wrap_tiger2_init(void *v)
{
- crc32c_update(v, (const uint8_t *)data, len);
+ TIGER2_Init(v);
}
static void
-wrap_tiger_update(void *v, const char *data, unsigned len)
+wrap_tiger_update(void *v, const void *data, unsigned len)
{
TIGER_Update(v, (const uint8_t *)data, len);
}
static void
-wrap_blake2_update(void *v, const char *data, unsigned len)
+wrap_tiger_final(uint8_t *raw, void *v)
{
- blake2b_update(v, (const uint8_t *)data, (uint64_t)len);
+ TIGER_Final(raw, v);
}
+/*****/
+
static void
-wrap_whirlpool_update(void *v, const char *data, unsigned len)
+wrap_blake2_init(void *v)
{
- whirlpool_update(v, (const uint8_t *)data, len);
+ blake2b_init(v, 64);
}
static void
-wrap_keccak_update(void *v, const char *data, unsigned len)
+wrap_blake2_update(void *v, const void *data, unsigned len)
{
- /* number of bits for keccak */
- KECCAK_Update(v, (const uint8_t *)data, (uint64_t)(len * 8));
+ blake2b_update(v, (const uint8_t *)data, (uint64_t)len);
}
static void
-wrap_size_update(void *v, const char *data, unsigned len)
+wrap_blake2_final(uint8_t *raw, void *v)
{
- uint64_t n;
-
- USE_ARG(data);
- memcpy(&n, v, sizeof(n));
- n += len;
- memcpy(v, &n, sizeof(n));
+ blake2b_final(v, raw, 64);
}
/*****/
static void
-wrap_sha1_final(uint8_t *raw, void *v)
+wrap_whirlpool_init(void *v)
{
- SHA1Final(raw, v);
+ whirlpool_init(v);
}
static void
-wrap_sha256_final(uint8_t *raw, void *v)
+wrap_whirlpool_update(void *v, const void *data, unsigned len)
{
- SHA256_Final(raw, v);
+ whirlpool_update(v, (const uint8_t *)data, len);
}
static void
-wrap_sha512_final(uint8_t *raw, void *v)
+wrap_whirlpool_final(uint8_t *raw, void *v)
{
- SHA512_Final(raw, v);
+ whirlpool_finalize((char *)raw, v);
}
+/*****/
+
static void
-wrap_rmd160_final(uint8_t *raw, void *v)
+wrap_keccak224_init(void *v)
{
- RMD160Final(raw, v);
+ KECCAK_Init(v, 224);
}
static void
-wrap_md5_final(uint8_t *raw, void *v)
+wrap_keccak256_init(void *v)
{
- MD5Final(raw, v);
+ KECCAK_Init(v, 256);
}
static void
-wrap_crc32c_final(uint8_t *raw, void *v)
+wrap_keccak384_init(void *v)
{
- crc32c_final((ctx32_t *)(void *)raw, v);
+ KECCAK_Init(v, 384);
}
static void
-wrap_tiger_final(uint8_t *raw, void *v)
+wrap_keccak512_init(void *v)
{
- TIGER_Final(raw, v);
+ KECCAK_Init(v, 512);
}
static void
-wrap_blake2_final(uint8_t *raw, void *v)
+wrap_keccak_update(void *v, const void *data, unsigned len)
{
- blake2b_final(v, raw, 64);
+ /* number of bits for keccak */
+ KECCAK_Update(v, (const uint8_t *)data, (uint64_t)(len * 8));
}
static void
-wrap_whirlpool_final(uint8_t *raw, void *v)
+wrap_keccak_final(uint8_t *raw, void *v)
{
- whirlpool_finalize((char *)raw, v);
+ KECCAK_Final(v, raw);
}
+/*****/
+
static void
-wrap_keccak_final(uint8_t *raw, void *v)
+wrap_size_init(void *v)
{
- KECCAK_Final(v, raw);
+ memset(v, 0x0, sizeof(uint64_t));
}
static void
+wrap_size_update(void *v, const void *data, unsigned len)
+{
+ uint64_t n;
+
+ USE_ARG(data);
+ memcpy(&n, v, sizeof(n));
+ n += len;
+ memcpy(v, &n, sizeof(n));
+}
+
+static void
wrap_size_final(uint8_t *raw, void *v)
{
const int indian = 1;
@@ -332,6 +348,34 @@
/*****/
+static void
+wrap_null_init(void *v)
+{
+ USE_ARG(v);
+}
+
+static void
+wrap_null_update(void *v, const void *data, unsigned len)
+{
+ USE_ARG(v);
+ USE_ARG(data);
+ USE_ARG(len);
+}
+
+static void
+wrap_null_final(uint8_t *raw, void *v)
+{
+ USE_ARG(raw);
+ USE_ARG(v);
+}
+
+/*****/
+
+#define COMBINE_CONCAT 0x0
+#define COMBINE_COMB4P 0x1
+#define COMBINE_HASH 0x2
+#define COMBINE_XOR 0x3
+
/* digest algorithm struct */
typedef struct Alg {
const char *name; /* digest name */
@@ -341,30 +385,38 @@
mg_initfunc_t init; /* digest init function */
mg_updatefunc_t update; /* digest update function */
mg_finalfunc_t final; /* digest final function */
+ uint32_t combiner; /* combination type */
} Alg;
static const Alg algs[] = {
- { "MD5", 3, sizeof(MD5_CTX), 16, wrap_md5_init, wrap_md5_update, wrap_md5_final },
- { "SHA1", 4, sizeof(SHA1_CTX), 20, wrap_sha1_init, wrap_sha1_update, wrap_sha1_final },
- { "SHA256", 6, sizeof(SHA256_CTX), 32, wrap_sha256_init, wrap_sha256_update, wrap_sha256_final },
- { "SHA512", 6, sizeof(SHA512_CTX), 64, wrap_sha512_init, wrap_sha512_update, wrap_sha512_final },
- { "BLAKE2", 6, sizeof(BLAKE2_CTX), 64, wrap_blake2_init, wrap_blake2_update, wrap_blake2_final },
- { "RMD160", 6, sizeof(RMD160_CTX), 20, wrap_rmd160_init, wrap_rmd160_update, wrap_rmd160_final },
- { "RIPEMD160", 9, sizeof(RMD160_CTX), 20, wrap_rmd160_init, wrap_rmd160_update, wrap_rmd160_final },
- { "CRC32C", 6, sizeof(ctx32_t), 4, wrap_crc32c_init, wrap_crc32c_update, wrap_crc32c_final },
- { "TIGER2", 6, sizeof(TIGER_CTX), 24, wrap_tiger2_init, wrap_tiger_update, wrap_tiger_final },
- { "TIGER", 5, sizeof(TIGER_CTX), 24, wrap_tiger_init, wrap_tiger_update, wrap_tiger_final },
- { "WHIRLPOOL", 9, sizeof(whirlpool_context_t), 64, wrap_whirlpool_init, wrap_whirlpool_update, wrap_whirlpool_final },
- { "SHA3-224", 8, sizeof(KECCAK_CTX), 28, wrap_keccak224_init, wrap_keccak_update, wrap_keccak_final },
- { "SHA3-256", 8, sizeof(KECCAK_CTX), 32, wrap_keccak256_init, wrap_keccak_update, wrap_keccak_final },
- { "SHA3-384", 8, sizeof(KECCAK_CTX), 48, wrap_keccak384_init, wrap_keccak_update, wrap_keccak_final },
- { "SHA3-512", 8, sizeof(KECCAK_CTX), 64, wrap_keccak512_init, wrap_keccak_update, wrap_keccak_final },
- { "KECCAK-224", 10, sizeof(KECCAK_CTX), 28, wrap_keccak224_init, wrap_keccak_update, wrap_keccak_final },
- { "KECCAK-256", 10, sizeof(KECCAK_CTX), 32, wrap_keccak256_init, wrap_keccak_update, wrap_keccak_final },
- { "KECCAK-384", 10, sizeof(KECCAK_CTX), 48, wrap_keccak384_init, wrap_keccak_update, wrap_keccak_final },
- { "KECCAK-512", 10, sizeof(KECCAK_CTX), 64, wrap_keccak512_init, wrap_keccak_update, wrap_keccak_final },
- { "SIZE", 4, sizeof(uint64_t), 8, wrap_size_init, wrap_size_update, wrap_size_final },
- { NULL, 0, 0, 0, NULL, NULL, NULL}
+ { "MD5", 3, sizeof(MD5_CTX), 16, wrap_md5_init, wrap_md5_update, wrap_md5_final, 0 },
+ { "SHA1", 4, sizeof(SHA1_CTX), 20, wrap_sha1_init, wrap_sha1_update, wrap_sha1_final, 0 },
+ { "SHA256", 6, sizeof(SHA256_CTX), 32, wrap_sha256_init, wrap_sha256_update, wrap_sha256_final, 0 },
+ { "SHA512", 6, sizeof(SHA512_CTX), 64, wrap_sha512_init, wrap_sha512_update, wrap_sha512_final, 0 },
+ { "BLAKE2", 6, sizeof(BLAKE2_CTX), 64, wrap_blake2_init, wrap_blake2_update, wrap_blake2_final, 0 },
+ { "RMD160", 6, sizeof(RMD160_CTX), 20, wrap_rmd160_init, wrap_rmd160_update, wrap_rmd160_final, 0 },
+ { "RIPEMD160", 9, sizeof(RMD160_CTX), 20, wrap_rmd160_init, wrap_rmd160_update, wrap_rmd160_final, 0 },
+ { "CRC32C", 6, sizeof(ctx32_t), 4, wrap_crc32c_init, wrap_crc32c_update, wrap_crc32c_final, 0 },
+ { "TIGER2", 6, sizeof(TIGER_CTX), 24, wrap_tiger2_init, wrap_tiger_update, wrap_tiger_final, 0 },
+ { "TIGER", 5, sizeof(TIGER_CTX), 24, wrap_tiger_init, wrap_tiger_update, wrap_tiger_final, 0 },
+ { "WHIRLPOOL", 9, sizeof(whirlpool_context_t), 64, wrap_whirlpool_init, wrap_whirlpool_update, wrap_whirlpool_final, 0 },
+ { "SHA3-224", 8, sizeof(KECCAK_CTX), 28, wrap_keccak224_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "SHA3-256", 8, sizeof(KECCAK_CTX), 32, wrap_keccak256_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "SHA3-384", 8, sizeof(KECCAK_CTX), 48, wrap_keccak384_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "SHA3-512", 8, sizeof(KECCAK_CTX), 64, wrap_keccak512_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "KECCAK-224", 10, sizeof(KECCAK_CTX), 28, wrap_keccak224_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "KECCAK-256", 10, sizeof(KECCAK_CTX), 32, wrap_keccak256_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "KECCAK-384", 10, sizeof(KECCAK_CTX), 48, wrap_keccak384_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "KECCAK-512", 10, sizeof(KECCAK_CTX), 64, wrap_keccak512_init, wrap_keccak_update, wrap_keccak_final, 0 },
+ { "SIZE", 4, sizeof(uint64_t), 8, wrap_size_init, wrap_size_update, wrap_size_final, 0 },
+ { "COMBCONCAT", 10, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_CONCAT },
+ { "CONCAT", 6, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_CONCAT },
+ { "COMB4P", 6, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_COMB4P },
+ { "COMBHASH", 8, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_HASH },
+ { "HASH", 4, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_HASH },
+ { "COMBXOR", 7, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_XOR },
+ { "XOR", 3, 0, 0, wrap_null_init, wrap_null_update, wrap_null_final, COMBINE_XOR },
+ { NULL, 0, 0, 0, NULL, NULL, NULL, 0}
};
/* find an algorithm in the table above */
@@ -393,16 +445,18 @@
*from = 0;
while (multigest->r && len > 0) {
match[0].rm_so = *from;
- match[0].rm_eo = len;
+ match[0].rm_eo = (regoff_t)len;
if (regexec(multigest->r, data, 2, match, REG_STARTEND) != 0) {
break;
}
for (d = multigest->digs, i = 0 ; i < multigest->digc ; i++, d++) {
- (*d->update)(&multigest->ctx[d->ctxoff], &data[*from],
- (unsigned)(match[0].rm_so - *from));
- if (multigest->repllen) {
- (*d->update)(&multigest->ctx[d->ctxoff], multigest->repl,
- multigest->repllen);
+ if (d->rawsize) {
+ (*d->update)(&multigest->ctx[d->ctxoff], &data[*from],
+ (unsigned)(match[0].rm_so - *from));
+ if (multigest->repllen) {
+ (*d->update)(&multigest->ctx[d->ctxoff], multigest->repl,
+ multigest->repllen);
+ }
}
}
*from = match[0].rm_eo;
@@ -413,6 +467,64 @@
return 1;
}
+/* xor the contents of two buffers together */
+static void
+xorbuf(uint8_t *out, uint8_t *in1, uint8_t *in2, size_t size)
+{
+ uint32_t j;
+
+ for (j = 0 ; j < size ; j++) {
+ out[j] = in1[j] ^ in2[j];
+ }
+}
+
+/* a round of comb4p combination */
+static int
+comb4p_round(multigest_t *m, uint8_t *out, uint8_t *in, multigest_dig_t *d1, multigest_dig_t *d2, uint32_t r)
+{
+ const int indian = 1;
+ uint32_t b2;
+ uint32_t b4;
+ uint8_t h1[4096];
+ uint8_t h2[4096];
+
+ if (*(const char *)(const void *)&indian) {
+ /* little endian - convert to bg endian) */
+ b2 = (r & 0x00ff0000);
+ b4 = (r & 0x000000ff);
+ r = (r & 0xff00ff00) | (b2 >> 16) | (b4 << 16);
+ }
+ (*d1->update)(&m->ctx[d1->ctxoff], (const char *)&r, sizeof(r));
+ (*d2->update)(&m->ctx[d2->ctxoff], (const char *)&r, sizeof(r));
+ (*d1->update)(&m->ctx[d1->ctxoff], (const char *)in, (unsigned)d1->rawsize);
+ (*d2->update)(&m->ctx[d2->ctxoff], (const char *)in, (unsigned)d2->rawsize);
+ (*d1->final)(h1, &m->ctx[d1->ctxoff]);
+ xorbuf(out, out, h1, d1->rawsize);
+ (*d2->final)(h2, &m->ctx[d2->ctxoff]);
+ xorbuf(out, out, h2, d2->rawsize);
+ return 1;
+}
+
+/* point d1 and d2 at the first 2 digests found */
+static int
+find_digests(multigest_t *m, multigest_dig_t **d1, multigest_dig_t **d2)
+{
+ multigest_dig_t *d;
+ uint32_t i;
+
+ *d1 = *d2 = NULL;
+ for (d = m->digs, i = 0 ; i < m->digc ; i++, d++) {
+ if (d->rawsize) {
+ if (*d1) {
+ *d2 = d;
+ return 1;
+ }
+ *d1 = d;
+ }
+ }
+ return 0;
+}
+
/***************************************************************************/
/* create a new struct and return it */
@@ -427,6 +539,8 @@
multigest_init(multigest_t *multigest, const char *algname)
{
multigest_dig_t *d;
+ multigest_dig_t *d1;
+ multigest_dig_t *d2;
const Alg *alg;
uint32_t ctxoff;
uint32_t i;
@@ -444,6 +558,9 @@
fprintf(stderr, "no such algorithm '%.10s'\n", algname);
break;
}
+ if (alg->combiner) {
+ multigest->combiner = alg->combiner;
+ }
if (ctxoff + alg->ctxsize >= multigest->ctxsize) {
if ((newv = realloc(multigest->ctx, multigest->ctxsize + 4096)) == NULL) {
fprintf(stderr, "multigest_init: allocation issues\n");
@@ -466,6 +583,32 @@
}
multigest->digc += 1;
}
+ switch (multigest->combiner) {
+ case COMBINE_CONCAT:
+ multigest->outsize = multigest->rawsize;
+ break;
+ case COMBINE_COMB4P:
+ if (!find_digests(multigest, &d1, &d2)) {
+ fprintf(stderr, "multigest: comb4p < 2 digests\n");
+ return 0;
+ }
+ multigest->outsize = d1->rawsize * 2;
+ break;
+ case COMBINE_XOR:
+ if (!find_digests(multigest, &d1, &d2)) {
+ fprintf(stderr, "multigest: xor < 2 digests\n");
+ return 0;
+ }
+ multigest->outsize = d1->rawsize;
+ break;
+ case COMBINE_HASH:
+ if (!find_digests(multigest, &d1, &d2)) {
+ fprintf(stderr, "multigest: hash < 2 digests\n");
+ return 0;
+ }
+ multigest->outsize = d1->rawsize;
+ break;
+ }
return 1;
}
fprintf(stderr, "!multigest || !algname\n");
@@ -493,50 +636,94 @@
/* update the digest with the input */
void
-multigest_update(multigest_t *multigest, const char *data, size_t len)
+multigest_update(multigest_t *multigest, const void *vdata, size_t len)
{
multigest_dig_t *d;
+ const char *data = (const char *)vdata;
uint32_t i;
int64_t from;
if (multigest && data) {
normalise(multigest, data, len, &from);
for (d = multigest->digs, i = 0 ; i < multigest->digc ; i++, d++) {
- (*d->update)(&multigest->ctx[d->ctxoff], &data[from], (unsigned)(len - from));
+ if (d->rawsize) {
+ (*d->update)(&multigest->ctx[d->ctxoff], &data[from], (unsigned)(len - (unsigned)from));
+ }
}
}
}
/* finalise the digest */
void
-multigest_final(multigest_t *multigest, uint8_t *raw)
+multigest_final(multigest_t *m, uint8_t *raw)
{
- multigest_dig_t *d;
+ multigest_dig_t *d1;
+ multigest_dig_t *d2;
uint32_t rawoff;
uint32_t i;
+ uint8_t h1[4096];
+ uint8_t h2[4096];
- if (multigest && raw) {
- rawoff = 0;
- for (d = multigest->digs, i = 0 ; i < multigest->digc ; i++, d++) {
- (*d->final)(&raw[rawoff], &multigest->ctx[d->ctxoff]);
- rawoff += (uint32_t)d->rawsize;
+ if (m && raw) {
+ switch(m->combiner) {
+ case COMBINE_COMB4P:
+ if (!find_digests(m, &d1, &d2)) {
+ return;
+ }
+ memset(h1, 0x0, sizeof(h1));
+ memset(h2, 0x0, sizeof(h2));
+ (*d1->final)(h1, &m->ctx[d1->ctxoff]);
+ (*d2->final)(h2, &m->ctx[d2->ctxoff]);
+ xorbuf(h1, h1, h2, d2->rawsize);
+ comb4p_round(m, h2, h1, d1, d2, 1);
+ comb4p_round(m, h1, h2, d1, d2, 2);
+ memcpy(raw, h1, d1->rawsize);
+ memcpy(&raw[d1->rawsize], h2, d2->rawsize);
+ break;
+ case COMBINE_CONCAT:
+ rawoff = 0;
+ for (d1 = m->digs, i = 0 ; i < m->digc ; i++, d1++) {
+ if (d1->rawsize) {
+ (*d1->final)(&raw[rawoff], &m->ctx[d1->ctxoff]);
+ rawoff += (uint32_t)d1->rawsize;
+ }
+ }
+ break;
+ case COMBINE_HASH:
+ if (!find_digests(m, &d1, &d2)) {
+ return;
+ }
+ (*d2->final)(h2, &m->ctx[d2->ctxoff]);
+ (*d1->update)(&m->ctx[d1->ctxoff], h2, (unsigned)d1->rawsize);
+ (*d1->final)(raw, &m->ctx[d1->ctxoff]);
+ break;
+ case COMBINE_XOR:
+ if (!find_digests(m, &d1, &d2)) {
+ return;
+ }
+ (*d2->final)(h2, &m->ctx[d2->ctxoff]);
+ (*d1->final)(h1, &m->ctx[d1->ctxoff]);
+ xorbuf(raw, h1, h2, m->outsize);
+ break;
+ default:
+ break;
}
}
}
/* run sed on data and then digest it */
uint8_t *
-multigest_data(const char *alg, const char *data, size_t size, uint8_t *raw, const char *pat, const char *repl)
+multigest_data(const char *alg, const void *data, size_t size, uint8_t *raw, const char *pat, const char *repl)
{
- multigest_t s;
+ multigest_t m;
if (data && alg && raw) {
- memset(&s, 0x0, sizeof(s));
- multigest_init(&s, alg);
- multigest_add_subst(&s, pat, repl);
- multigest_update(&s, data, size);
- multigest_final(&s, raw);
- multigest_free(&s);
+ memset(&m, 0x0, sizeof(m));
+ multigest_init(&m, alg);
+ multigest_add_subst(&m, pat, repl);
+ multigest_update(&m, data, size);
+ multigest_final(&m, raw);
+ multigest_free(&m);
return raw;
}
return NULL;
@@ -549,6 +736,7 @@
static const char *hexes = "0123456789abcdef";
const char *p[2];
const char *i;
+ uint8_t num;
char *o;
for (i = in, o = out ; (size_t)(o - out) < osize - 1 && (size_t)(i - in) < isize && *i ; o++) {
@@ -557,7 +745,8 @@
(p[1] = strchr(hexes, i[2])) == NULL) {
break;
}
- *o = ((char)(p[0] - hexes) * 16) + (p[1] - hexes);
+ num = (uint8_t)((p[0] - hexes) << 4) | (uint8_t)(p[1] - hexes);
+ *o = (char)num;
i += 3;
} else {
*o = *i++;
@@ -586,14 +775,14 @@
algname += 1;
}
}
- return (int)(rawsize + rawsize + 1);
+ return (int)(rawsize + rawsize);
}
/* return the size of output array we'll need */
uint32_t
multigest_get_rawsize(multigest_t *multigest)
{
- return (multigest) ? (uint32_t)multigest->rawsize : 0;
+ return (multigest) ? (uint32_t)multigest->outsize : 0;
}
/* return the size of output array we'll need for the alg names */
@@ -637,6 +826,7 @@
const char *f, const char *sub, const char *sep, const char *format)
{
const Alg *alg;
+ size_t outsize;
size_t rawsize;
size_t i;
FILE *fp;
@@ -665,16 +855,19 @@
fprintf(fp, ") = ");
}
}
- for (rawsize = 0 ; *algname ; rawsize += alg->rawsize) {
+ outsize = multigest_algs_rawsize(algname);
+ for (rawsize = 0 ; *algname && rawsize < outsize ; rawsize += alg->rawsize) {
if ((alg = findalg(algname)) == NULL) {
break;
}
- for (i = 0 ; i < alg->rawsize ; i++) {
- fprintf(fp, "%02hhx", raw[rawsize + i]);
+ if (!alg->combiner) {
+ for (i = 0 ; i < alg->rawsize ; i++) {
+ fprintf(fp, "%02hhx", raw[rawsize + i]);
+ }
+ if (sep) {
+ fprintf(fp, "%s", sep);
+ }
}
- if (sep) {
- fprintf(fp, "%s", sep);
- }
algname += alg->namelen;
if (*algname == ',') {
algname += 1;
@@ -708,11 +901,11 @@
return 0;
}
fstat(fileno(fp), &st);
- size = st.st_size;
+ size = (size_t)st.st_size;
mapped = mmap(NULL, size, PROT_READ, MAP_SHARED, fileno(fp), 0);
if (mapped == MAP_FAILED) {
mapped = calloc(1, MB(1));
- for (cc = 0 ; cc < size ; cc += rc) {
+ for (cc = 0 ; cc < size ; cc += (size_t)rc) {
if ((rc = read(fileno(fp), mapped, MB(1))) <= 0) {
break;
}
@@ -724,7 +917,7 @@
munmap(mapped, size);
}
fclose(fp);
- multigest_final(&m, raw);
+ multigest_final(&m, raw);
multigest_free(&m);
return raw;
}