summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/hash.c502
-rw-r--r--common/hash.h20
-rw-r--r--common/tests/test-hash.c92
-rw-r--r--configure.ac33
-rw-r--r--doc/manual/p11-kit-devel.xml11
-rw-r--r--trust/Makefile.am4
-rw-r--r--trust/builder.c16
-rw-r--r--trust/digest.c632
-rw-r--r--trust/digest.h60
-rw-r--r--trust/extract-jks.c14
-rw-r--r--trust/extract-openssl.c10
-rw-r--r--trust/parser.c4
-rw-r--r--trust/tests/Makefile.am9
-rw-r--r--trust/tests/test-builder.c6
-rw-r--r--trust/tests/test-digest.c143
-rw-r--r--trust/tests/test-module.c10
-rw-r--r--trust/x509.c4
17 files changed, 922 insertions, 648 deletions
diff --git a/common/hash.c b/common/hash.c
index 9fe3668..68a6d40 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -39,508 +39,6 @@
#include <stdint.h>
#include <string.h>
-#define SHA1_BLOCK_LENGTH 64U
-
-typedef struct {
- uint32_t state[5];
- uint32_t count[2];
- unsigned char buffer[SHA1_BLOCK_LENGTH];
-} sha1_t;
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/*@{*/
-/*!
- * blk0() and blk() perform the initial expand.
- * I got the idea of expanding during the round function from SSLeay
- */
-#if !defined(WORDS_BIGENDIAN)
-# define blk0(i) \
- (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
- | (rol(block->l[i], 8) & 0x00FF00FF))
-#else
-# define blk0(i) block->l[i]
-#endif
-#define blk(i) \
- (block->l[i & 15] = rol(block->l[(i + 13) & 15] \
- ^ block->l[(i + 8) & 15] \
- ^ block->l[(i + 2) & 15] \
- ^ block->l[i & 15], 1))
-
-/*@}*/
-/*@{*/
-/*!
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- */
-#define R0(v,w,x,y,z,i) \
- z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
- w = rol(w, 30);
-#define R1(v,w,x,y,z,i) \
- z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
- w = rol(w, 30);
-#define R2(v,w,x,y,z,i) \
- z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
- w = rol(w, 30);
-#define R3(v,w,x,y,z,i) \
- z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
- w = rol(w, 30);
-#define R4(v,w,x,y,z,i) \
- z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
- w = rol(w, 30);
-
-/*@}*/
-
-typedef union {
- unsigned char c[64];
- unsigned int l[16];
-} CHAR64LONG16;
-
-/*!
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
-static void
-transform_sha1 (uint32_t state[5],
- const unsigned char buffer[64])
-{
- uint32_t a, b, c, d, e;
- CHAR64LONG16 *block;
- CHAR64LONG16 workspace;
-
- assert (buffer != NULL);
- assert (state != NULL);
-
- block = &workspace;
- (void)memcpy(block, buffer, 64);
-
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
-
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
-
- /* Wipe variables */
- a = b = c = d = e = 0;
- /* Avoid compiler warnings
- POST(a); POST(b); POST(c); POST(d); POST(e);
- */
-}
-
-
-/*!
- * isc_sha1_init - Initialize new context
- */
-static void
-sha1_init (sha1_t *context)
-{
- assert (context != NULL);
-
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = 0;
- context->count[1] = 0;
-}
-
-static void
-sha1_invalidate (sha1_t *context)
-{
- memset (context, 0, sizeof (sha1_t));
-}
-
-/*!
- * Run your data through this.
- */
-static void
-sha1_update(sha1_t *context,
- const unsigned char *data,
- unsigned int len)
-{
- unsigned int i, j;
-
- assert (context != 0);
- assert (data != 0);
-
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1] += (len >> 29) + 1;
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- (void)memcpy(&context->buffer[j], data, (i = 64 - j));
- transform_sha1 (context->state, context->buffer);
- for (; i + 63 < len; i += 64)
- transform_sha1 (context->state, &data[i]);
- j = 0;
- } else {
- i = 0;
- }
-
- (void)memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/*!
- * Add padding and return the message digest.
- */
-
-static const unsigned char final_200 = 128;
-static const unsigned char final_0 = 0;
-
-static void
-sha1_final (sha1_t *context,
- unsigned char *digest)
-{
- unsigned int i;
- unsigned char finalcount[8];
-
- assert (digest != 0);
- assert (context != 0);
-
- for (i = 0; i < 8; i++) {
- /* Endian independent */
- finalcount[i] = (unsigned char)
- ((context->count[(i >= 4 ? 0 : 1)]
- >> ((3 - (i & 3)) * 8)) & 255);
- }
-
- sha1_update(context, &final_200, 1);
- while ((context->count[0] & 504) != 448)
- sha1_update(context, &final_0, 1);
- /* The next Update should cause a transform_sha1() */
- sha1_update(context, finalcount, 8);
-
- if (digest) {
- for (i = 0; i < 20; i++)
- digest[i] = (unsigned char)
- ((context->state[i >> 2]
- >> ((3 - (i & 3)) * 8)) & 255);
- }
-
- memset (context, 0, sizeof (sha1_t));
-}
-
-void
-p11_hash_sha1 (unsigned char *hash,
- const void *input,
- size_t length,
- ...)
-{
- va_list va;
- sha1_t sha1;
-
- sha1_init (&sha1);
-
- va_start (va, length);
- while (input != NULL) {
- sha1_update (&sha1, input, length);
- input = va_arg (va, const void *);
- if (input)
- length = va_arg (va, size_t);
- }
- va_end (va);
-
- sha1_final (&sha1, hash);
- sha1_invalidate (&sha1);
-}
-
-
-/*! \file
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-typedef struct {
- uint32_t buf[4];
- uint32_t bytes[2];
- uint32_t in[16];
-} md5_t;
-
-static void
-byteSwap (uint32_t *buf,
- unsigned words)
-{
- unsigned char *p = (unsigned char *)buf;
-
- do {
- *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
- ((unsigned)p[1] << 8 | p[0]);
- p += 4;
- } while (--words);
-}
-
-/*!
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-static void
-md5_init(md5_t *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bytes[0] = 0;
- ctx->bytes[1] = 0;
-}
-
-static void
-md5_invalidate(md5_t *ctx)
-{
- memset(ctx, 0, sizeof(md5_t));
-}
-
-/*@{*/
-/*! The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-/*@}*/
-
-/*! This is the central step in the MD5 algorithm. */
-#define MD5STEP(f,w,x,y,z,in,s) \
- (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
-
-/*!
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void
-transform_md5 (uint32_t buf[4],
- uint32_t const in[16])
-{
- register uint32_t a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-/*!
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-static void
-md5_update (md5_t *ctx,
- const unsigned char *buf,
- unsigned int len)
-{
- uint32_t t;
-
- /* Update byte count */
-
- t = ctx->bytes[0];
- if ((ctx->bytes[0] = t + len) < t)
- ctx->bytes[1]++; /* Carry from low to high */
-
- t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
- if (t > len) {
- memcpy((unsigned char *)ctx->in + 64 - t, buf, len);
- return;
- }
- /* First chunk is an odd size */
- memcpy((unsigned char *)ctx->in + 64 - t, buf, t);
- byteSwap(ctx->in, 16);
- transform_md5 (ctx->buf, ctx->in);
- buf += t;
- len -= t;
-
- /* Process data in 64-byte chunks */
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteSwap(ctx->in, 16);
- transform_md5(ctx->buf, ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
- memcpy(ctx->in, buf, len);
-}
-
-/*!
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-static void
-md5_final(md5_t *ctx,
- unsigned char *digest)
-{
- int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
- unsigned char *p = (unsigned char *)ctx->in + count;
-
- /* Set the first char of padding to 0x80. There is always room. */
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 56 bytes (-8..55) */
- count = 56 - 1 - count;
-
- if (count < 0) { /* Padding forces an extra block */
- memset(p, 0, count + 8);
- byteSwap(ctx->in, 16);
- transform_md5(ctx->buf, ctx->in);
- p = (unsigned char *)ctx->in;
- count = 56;
- }
- memset(p, 0, count);
- byteSwap(ctx->in, 14);
-
- /* Append length in bits and transform */
- ctx->in[14] = ctx->bytes[0] << 3;
- ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
- transform_md5(ctx->buf, ctx->in);
-
- byteSwap(ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(md5_t)); /* In case it's sensitive */
-}
-
-void
-p11_hash_md5 (unsigned char *hash,
- const void *input,
- size_t length,
- ...)
-{
- va_list va;
- md5_t md5;
-
- md5_init (&md5);
-
- va_start (va, length);
- while (input) {
- md5_update (&md5, input, length);
- input = va_arg (va, const void *);
- if (input)
- length = va_arg (va, size_t);
- }
- va_end (va);
-
- md5_final (&md5, hash);
- md5_invalidate (&md5);
-}
-
/* This code is based on the public domain MurmurHash3 from Austin Appleby:
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
*
diff --git a/common/hash.h b/common/hash.h
index 09f7646..41371c6 100644
--- a/common/hash.h
+++ b/common/hash.h
@@ -37,26 +37,6 @@
#include "compat.h"
-/*
- * The SHA-1 and MD5 digests here are used for checksums in legacy
- * protocols. We don't use them in cryptographic contexts at all.
- * These particular algorithms would be poor choices for that.
- */
-
-#define P11_HASH_MD5_LEN 16
-
-void p11_hash_md5 (unsigned char *hash,
- const void *input,
- size_t length,
- ...) GNUC_NULL_TERMINATED;
-
-#define P11_HASH_SHA1_LEN 20
-
-void p11_hash_sha1 (unsigned char *hash,
- const void *input,
- size_t length,
- ...) GNUC_NULL_TERMINATED;
-
#define P11_HASH_MURMUR3_LEN 4
void p11_hash_murmur3 (void *hash,
diff --git a/common/tests/test-hash.c b/common/tests/test-hash.c
index c679cad..a12d5a4 100644
--- a/common/tests/test-hash.c
+++ b/common/tests/test-hash.c
@@ -43,95 +43,6 @@
#include "hash.h"
-const char *sha1_input[] = {
- "abc",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- NULL
-};
-
-const char *sha1_checksum[] = {
- "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D",
- "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1",
- NULL
-};
-
-static void
-test_sha1 (void)
-{
- unsigned char checksum[P11_HASH_SHA1_LEN];
- size_t len;
- int i;
-
- for (i = 0; sha1_input[i] != NULL; i++) {
- memset (checksum, 0, sizeof (checksum));
- len = strlen (sha1_input[i]);
-
- p11_hash_sha1 (checksum, sha1_input[i], len, NULL);
- assert (memcmp (sha1_checksum[i], checksum, P11_HASH_SHA1_LEN) == 0);
-
- if (len > 6) {
- p11_hash_sha1 (checksum, sha1_input[i], 6, sha1_input[i] + 6, len - 6, NULL);
- assert (memcmp (sha1_checksum[i], checksum, P11_HASH_SHA1_LEN) == 0);
- }
- }
-}
-
-static void
-test_sha1_long (void)
-{
- unsigned char checksum[P11_HASH_SHA1_LEN];
- char *expected = "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F";
- char *input;
-
- input = malloc (1000000);
- assert (input != NULL);
- memset (input, 'a', 1000000);
-
- p11_hash_sha1 (checksum, input, 1000000, NULL);
- assert (memcmp (expected, checksum, P11_HASH_SHA1_LEN) == 0);
-
- free (input);
-}
-
-const char *md5_input[] = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- NULL
-};
-
-const char *md5_checksum[] = {
- "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
- "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61",
- "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72",
- "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0",
- "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b",
- NULL
-};
-
-static void
-test_md5 (void)
-{
- unsigned char checksum[P11_HASH_MD5_LEN];
- size_t len;
- int i;
-
- for (i = 0; md5_input[i] != NULL; i++) {
- memset (checksum, 0, sizeof (checksum));
- len = strlen (md5_input[i]);
-
- p11_hash_md5 (checksum, md5_input[i], len, NULL);
- assert (memcmp (md5_checksum[i], checksum, P11_HASH_MD5_LEN) == 0);
-
- if (len > 5) {
- p11_hash_md5 (checksum, md5_input[i], 5, md5_input[i] + 5, len - 5, NULL);
- assert (memcmp (md5_checksum[i], checksum, P11_HASH_MD5_LEN) == 0);
- }
- }
-}
-
static void
test_murmur3 (void)
{
@@ -189,9 +100,6 @@ int
main (int argc,
char *argv[])
{
- p11_test (test_sha1, "/hash/sha1");
- p11_test (test_sha1_long, "/hash/sha1-long");
- p11_test (test_md5, "/hash/md5");
p11_test (test_murmur3, "/hash/murmur3");
p11_test (test_murmur3_incr, "/hash/murmur3-incr");
return p11_test_run (argc, argv);
diff --git a/configure.ac b/configure.ac
index 886d1eb..5eb6c2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -186,6 +186,38 @@ fi
AM_CONDITIONAL(WITH_FFI, test "$with_libffi" = "yes")
# --------------------------------------------------------------------
+# Hash implementation
+
+AC_ARG_WITH([hash-impl],
+ AS_HELP_STRING([--with-hash-impl=@<:@freebl/internal@:>@],
+ [Choose the hash implementation to use])
+)
+
+AS_IF([test "$with_hash_impl" = ""], [with_hash_impl=internal])
+
+AS_CASE([$with_hash_impl],
+ [freebl], [
+ AC_CHECK_LIB(freebl3, NSSLOW_Init,
+ [
+ HASH_LIBS=-lfreebl3
+ AC_DEFINE_UNQUOTED(WITH_FREEBL, 1, [Use freebl for hash implementation])
+ ],
+ AC_MSG_ERROR([could not find the freebl3 library])
+ )
+ ],
+
+ [internal], [
+ HASH_LIBS=
+ ],
+
+ [
+ AC_MSG_ERROR([unsupported hash impl: $with_hash_impl])
+ ]
+)
+
+AC_SUBST(HASH_LIBS)
+
+# --------------------------------------------------------------------
# Trust Module
AC_ARG_ENABLE([trust-module],
@@ -483,6 +515,7 @@ AC_MSG_NOTICE([build options:
With libtasn1 dependency: $with_libtasn1
With libffi: $with_libffi
+ With hash implementation: $with_hash_impl
Build trust module: $enable_trust_module
Trust module paths: $trust_status
diff --git a/doc/manual/p11-kit-devel.xml b/doc/manual/p11-kit-devel.xml
index 873aff1..007118a 100644
--- a/doc/manual/p11-kit-devel.xml
+++ b/doc/manual/p11-kit-devel.xml
@@ -160,6 +160,10 @@ $ make install
dependency.</para></listitem>
<listitem><para><command>libtasn1</command> is required to build the trust
module and code that interacts with certificates.</para></listitem>
+ <listitem><para><command>freebl3</command> (developed as part of the NSS
+ code base) is an optional dependency that may be used to meet policy
+ requirements of system builders. Enabling this dependency provides no other
+ advantage.</para></listitem>
</itemizedlist>
</section>
@@ -197,6 +201,13 @@ $ make install
compiler warnings become errors.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--with-hash-impl=freebl</option></term>
+ <listitem><para>Instead of using internal hash code, link to the freebl3
+ library and use its hash implementations. The only advantage this brings is to
+ meet the policy requirements of system builders.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--with-libtasn1</option>, <option>--without-libtasn1</option></term>
<listitem><para>Build with a dependency on the libtasn1 library. This dependency
allows the trust policy module to be built as well as other code that interacts with
diff --git a/trust/Makefile.am b/trust/Makefile.am
index 58e4889..ca7e2d7 100644
--- a/trust/Makefile.am
+++ b/trust/Makefile.am
@@ -31,6 +31,7 @@ libtrust_data_la_SOURCES = \
MODULE_SRCS = \
builder.c builder.h \
+ digest.c digest.h \
index.c index.h \
parser.c parser.h \
persist.c persist.h \
@@ -56,6 +57,7 @@ p11_kit_trust_la_LIBADD = \
$(top_builddir)/common/libp11-library.la \
$(top_builddir)/common/libp11-common.la \
$(LIBTASN1_LIBS) \
+ $(HASH_LIBS) \
$(NULL)
p11_kit_trust_la_LDFLAGS = \
@@ -81,6 +83,7 @@ trust_LDADD = \
$(top_builddir)/common/libp11-tool.la \
$(LTLIBINTL) \
$(LIBTASN1_LIBS) \
+ $(HASH_LIBS) \
$(NULL)
trust_CFLAGS = \
@@ -93,6 +96,7 @@ trust_SOURCES = \
anchor.c anchor.h \
parser.c parser.h \
persist.c persist.h \
+ digest.c digest.h \
extract.c extract.h \
extract-info.c \
extract-jks.c \
diff --git a/trust/builder.c b/trust/builder.c
index d39890d..fdaae34 100644
--- a/trust/builder.c
+++ b/trust/builder.c
@@ -42,7 +42,7 @@
#include "builder.h"
#include "constants.h"
#include "debug.h"
-#include "hash.h"
+#include "digest.h"
#include "index.h"
#include "message.h"
#include "oid.h"
@@ -363,8 +363,8 @@ calc_check_value (const unsigned char *data,
size_t length,
CK_BYTE *check_value)
{
- unsigned char checksum[P11_HASH_SHA1_LEN];
- p11_hash_sha1 (checksum, data, length, NULL);
+ unsigned char checksum[P11_DIGEST_SHA1_LEN];
+ p11_digest_sha1 (checksum, data, length, NULL);
memcpy (check_value, checksum, 3);
}
@@ -602,7 +602,7 @@ certificate_value_attrs (CK_ATTRIBUTE *attrs,
size_t der_len,
CK_ATTRIBUTE *public_key)
{
- unsigned char checksum[P11_HASH_SHA1_LEN];
+ unsigned char checksum[P11_DIGEST_SHA1_LEN];
CK_BBOOL falsev = CK_FALSE;
CK_ULONG zero = 0UL;
CK_BYTE checkv[3];
@@ -1278,8 +1278,8 @@ replace_nss_trust_object (p11_builder *builder,
CK_RV rv;
CK_OBJECT_CLASS klassv = CKO_NSS_TRUST;
- CK_BYTE sha1v[P11_HASH_SHA1_LEN];
- CK_BYTE md5v[P11_HASH_MD5_LEN];
+ CK_BYTE sha1v[P11_DIGEST_SHA1_LEN];
+ CK_BYTE md5v[P11_DIGEST_MD5_LEN];
CK_BBOOL generatedv = CK_FALSE;
CK_BBOOL falsev = CK_FALSE;
@@ -1316,8 +1316,8 @@ replace_nss_trust_object (p11_builder *builder,
md5_hash.type = CKA_INVALID;
sha1_hash.type = CKA_INVALID;
} else {
- p11_hash_md5 (md5v, value, length, NULL);
- p11_hash_sha1 (sha1v, value, length, NULL);
+ p11_digest_md5 (md5v, value, length, NULL);
+ p11_digest_sha1 (sha1v, value, length, NULL);
}
if (!issuer)
issuer = &invalid;
diff --git a/trust/digest.c b/trust/digest.c
new file mode 100644
index 0000000..5cac83a
--- /dev/null
+++ b/trust/digest.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * SHA-1 in C
+ * \author By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ * \verbatim
+ * Test Vectors
+ * "abc"
+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ * \endverbatim
+ */
+
+#include "config.h"
+
+#include "digest.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef WITH_FREEBL
+
+/*
+ * NSS freebl3 has awkward headers not provided by appropriate packages
+ * in many cases. So put these defines here inline. freebl3 seems completely
+ * undocumented anyway. If you think this is a hack, then you guessed right.
+ *
+ * If you want a stable p11-kit without worries, use the builtin SHA1 and MD5
+ * implementations. They're not used for crypto anyway. If you need p11-kit to
+ * tick the "doesn't implement own crypto" checkbox, then the you're signing
+ * up for this hack.
+ */
+
+typedef enum {
+ HASH_AlgMD5 = 2,
+ HASH_AlgSHA1 = 3,
+} HASH_HashType;
+
+typedef struct NSSLOWInitContextStr NSSLOWInitContext;
+typedef struct NSSLOWHASHContextStr NSSLOWHASHContext;
+
+NSSLOWInitContext *NSSLOW_Init(void);
+NSSLOWHASHContext *NSSLOWHASH_NewContext(
+ NSSLOWInitContext *initContext,
+ HASH_HashType hashType);
+void NSSLOWHASH_Begin(NSSLOWHASHContext *context);
+void NSSLOWHASH_Update(NSSLOWHASHContext *context,
+ const unsigned char *buf,
+ unsigned int len);
+void NSSLOWHASH_End(NSSLOWHASHContext *context,
+ unsigned char *buf,
+ unsigned int *ret, unsigned int len);
+void NSSLOWHASH_Destroy(NSSLOWHASHContext *context);
+
+#endif /* WITH_FREEBL3 */
+
+#define SHA1_BLOCK_LENGTH 64U
+
+typedef struct {
+ uint32_t state[5];
+ uint32_t count[2];
+ unsigned char buffer[SHA1_BLOCK_LENGTH];
+} sha1_t;
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*@{*/
+/*!
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#if !defined(WORDS_BIGENDIAN)
+# define blk0(i) \
+ (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+ | (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+# define blk0(i) block->l[i]
+#endif
+#define blk(i) \
+ (block->l[i & 15] = rol(block->l[(i + 13) & 15] \
+ ^ block->l[(i + 8) & 15] \
+ ^ block->l[(i + 2) & 15] \
+ ^ block->l[i & 15], 1))
+
+/*@}*/
+/*@{*/
+/*!
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
+ w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+ w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+ w = rol(w, 30);
+
+/*@}*/
+
+typedef union {
+ unsigned char c[64];
+ unsigned int l[16];
+} CHAR64LONG16;
+
+/*!
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+static void
+transform_sha1 (uint32_t state[5],
+ const unsigned char buffer[64])
+{
+ uint32_t a, b, c, d, e;
+ CHAR64LONG16 *block;
+ CHAR64LONG16 workspace;
+
+ assert (buffer != NULL);
+ assert (state != NULL);
+
+ block = &workspace;
+ (void)memcpy(block, buffer, 64);
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+ /* Avoid compiler warnings
+ POST(a); POST(b); POST(c); POST(d); POST(e);
+ */
+}
+
+
+/*!
+ * isc_sha1_init - Initialize new context
+ */
+static void
+sha1_init (sha1_t *context)
+{
+ assert (context != NULL);
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = 0;
+ context->count[1] = 0;
+}
+
+static void
+sha1_invalidate (sha1_t *context)
+{
+ memset (context, 0, sizeof (sha1_t));
+}
+
+/*!
+ * Run your data through this.
+ */
+static void
+sha1_update(sha1_t *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ assert (context != 0);
+ assert (data != 0);
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1] += (len >> 29) + 1;
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ (void)memcpy(&context->buffer[j], data, (i = 64 - j));
+ transform_sha1 (context->state, context->buffer);
+ for (; i + 63 < len; i += 64)
+ transform_sha1 (context->state, &data[i]);
+ j = 0;
+ } else {
+ i = 0;
+ }
+
+ (void)memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/*!
+ * Add padding and return the message digest.
+ */
+
+static const unsigned char final_200 = 128;
+static const unsigned char final_0 = 0;
+
+static void
+sha1_final (sha1_t *context,
+ unsigned char *digest)
+{
+ unsigned int i;
+ unsigned char finalcount[8];
+
+ assert (digest != 0);
+ assert (context != 0);
+
+ for (i = 0; i < 8; i++) {
+ /* Endian independent */
+ finalcount[i] = (unsigned char)
+ ((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3 - (i & 3)) * 8)) & 255);
+ }
+
+ sha1_update(context, &final_200, 1);
+ while ((context->count[0] & 504) != 448)
+ sha1_update(context, &final_0, 1);
+ /* The next Update should cause a transform_sha1() */
+ sha1_update(context, finalcount, 8);
+
+ if (digest) {
+ for (i = 0; i < 20; i++)
+ digest[i] = (unsigned char)
+ ((context->state[i >> 2]
+ >> ((3 - (i & 3)) * 8)) & 255);
+ }
+
+ memset (context, 0, sizeof (sha1_t));
+}
+
+#ifdef WITH_FREEBL
+
+static bool
+nss_slow_hash (HASH_HashType type,
+ unsigned char *hash,
+ unsigned int hash_len,
+ const void *input,
+ size_t length,
+ va_list va)
+{
+ NSSLOWHASHContext *ctx;
+ unsigned int len;
+
+ ctx = NSSLOWHASH_NewContext(NSSLOW_Init (), type);
+ if (ctx == NULL)
+ return false;
+
+ NSSLOWHASH_Begin (ctx);
+ while (input != NULL) {
+ NSSLOWHASH_Update (ctx, input, length);
+ input = va_arg (va, const void *);
+ if (input)
+ length = va_arg (va, size_t);
+ }
+ NSSLOWHASH_End (ctx, hash, &len, hash_len);
+ assert (len == hash_len);
+ NSSLOWHASH_Destroy (ctx);
+ return true;
+}
+
+#endif /* WITH_FREEBL */
+
+void
+p11_digest_sha1 (unsigned char *hash,
+ const void *input,
+ size_t length,
+ ...)
+{
+ va_list va;
+ sha1_t sha1;
+
+#ifdef WITH_FREEBL
+ bool ret;
+
+ va_start (va, length);
+ ret = nss_slow_hash (HASH_AlgSHA1, hash, P11_DIGEST_SHA1_LEN, input, length, va);
+ va_end (va);
+
+ if (ret)
+ return;
+#endif
+
+ sha1_init (&sha1);
+
+ va_start (va, length);
+ while (input != NULL) {
+ sha1_update (&sha1, input, length);
+ input = va_arg (va, const void *);
+ if (input)
+ length = va_arg (va, size_t);
+ }
+ va_end (va);
+
+ sha1_final (&sha1, hash);
+ sha1_invalidate (&sha1);
+}
+
+
+/*! \file
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+typedef struct {
+ uint32_t buf[4];
+ uint32_t bytes[2];
+ uint32_t in[16];
+} md5_t;
+
+static void
+byteSwap (uint32_t *buf,
+ unsigned words)
+{
+ unsigned char *p = (unsigned char *)buf;
+
+ do {
+ *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+ ((unsigned)p[1] << 8 | p[0]);
+ p += 4;
+ } while (--words);
+}
+
+/*!
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+static void
+md5_init(md5_t *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+static void
+md5_invalidate(md5_t *ctx)
+{
+ memset(ctx, 0, sizeof(md5_t));
+}
+
+/*@{*/
+/*! The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+/*@}*/
+
+/*! This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*!
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+transform_md5 (uint32_t buf[4],
+ uint32_t const in[16])
+{
+ register uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*!
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+static void
+md5_update (md5_t *ctx,
+ const unsigned char *buf,
+ unsigned int len)
+{
+ uint32_t t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len) {
+ memcpy((unsigned char *)ctx->in + 64 - t, buf, len);
+ return;
+ }
+ /* First chunk is an odd size */
+ memcpy((unsigned char *)ctx->in + 64 - t, buf, t);
+ byteSwap(ctx->in, 16);
+ transform_md5 (ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteSwap(ctx->in, 16);
+ transform_md5(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/*!
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+static void
+md5_final(md5_t *ctx,
+ unsigned char *digest)
+{
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ unsigned char *p = (unsigned char *)ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0) { /* Padding forces an extra block */
+ memset(p, 0, count + 8);
+ byteSwap(ctx->in, 16);
+ transform_md5(ctx->buf, ctx->in);
+ p = (unsigned char *)ctx->in;
+ count = 56;
+ }
+ memset(p, 0, count);
+ byteSwap(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ transform_md5(ctx->buf, ctx->in);
+
+ byteSwap(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(md5_t)); /* In case it's sensitive */
+}
+
+void
+p11_digest_md5 (unsigned char *hash,
+ const void *input,
+ size_t length,
+ ...)
+{
+ va_list va;
+ md5_t md5;
+
+#ifdef WITH_FREEBL
+ bool ret;
+
+ va_start (va, length);
+ ret = nss_slow_hash (HASH_AlgMD5, hash, P11_DIGEST_MD5_LEN, input, length, va);
+ va_end (va);
+
+ if (ret)
+ return;
+#endif
+
+ md5_init (&md5);
+
+ va_start (va, length);
+ while (input) {
+ md5_update (&md5, input, length);
+ input = va_arg (va, const void *);
+ if (input)
+ length = va_arg (va, size_t);
+ }
+ va_end (va);
+
+ md5_final (&md5, hash);
+ md5_invalidate (&md5);
+}
diff --git a/trust/digest.h b/trust/digest.h
new file mode 100644
index 0000000..82d48fe
--- /dev/null
+++ b/trust/digest.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#ifndef P11_DIGEST_H_
+#define P11_DIGEST_H_
+
+#include "compat.h"
+
+/*
+ * The SHA-1 and MD5 digests here are used for checksums in legacy
+ * protocols. We don't use them in cryptographic contexts at all.
+ * These particular algorithms would be poor choices for that.
+ */
+
+#define P11_DIGEST_MD5_LEN 16
+
+void p11_digest_md5 (unsigned char *hash,
+ const void *input,
+ size_t length,
+ ...) GNUC_NULL_TERMINATED;
+
+#define P11_DIGEST_SHA1_LEN 20
+
+void p11_digest_sha1 (unsigned char *hash,
+ const void *input,
+ size_t length,
+ ...) GNUC_NULL_TERMINATED;
+
+#endif /* P11_DIGEST_H_ */
diff --git a/trust/extract-jks.c b/trust/extract-jks.c
index 987ea26..8a39cfd 100644
--- a/trust/extract-jks.c
+++ b/trust/extract-jks.c
@@ -39,7 +39,7 @@
#include "compat.h"
#include "debug.h"
#include "extract.h"
-#include "hash.h"
+#include "digest.h"
#include "message.h"
#include "save.h"
@@ -299,13 +299,13 @@ prepare_jks_buffer (P11KitIter *iter,
* as the password for this keyed digest.
*/
length = buffer->len;
- digest = p11_buffer_append (buffer, P11_HASH_SHA1_LEN);
+ digest = p11_buffer_append (buffer, P11_DIGEST_SHA1_LEN);
return_val_if_fail (digest != NULL, false);
- p11_hash_sha1 (digest,
- "\000c\000h\000a\000n\000g\000e\000i\000t", 16, /* default password */
- "Mighty Aphrodite", 16, /* go figure */
- buffer->data, length,
- NULL);
+ p11_digest_sha1 (digest,
+ "\000c\000h\000a\000n\000g\000e\000i\000t", 16, /* default password */
+ "Mighty Aphrodite", 16, /* go figure */
+ buffer->data, length,
+ NULL);
return_val_if_fail (p11_buffer_ok (buffer), false);
return true;
diff --git a/trust/extract-openssl.c b/trust/extract-openssl.c
index b7603b0..b503b67 100644
--- a/trust/extract-openssl.c
+++ b/trust/extract-openssl.c
@@ -40,8 +40,8 @@
#include "compat.h"
#include "debug.h"
#include "dict.h"
+#include "digest.h"
#include "extract.h"
-#include "hash.h"
#include "message.h"
#include "oid.h"
#include "path.h"
@@ -530,7 +530,7 @@ p11_openssl_canon_name_der (p11_dict *asn1_defs,
static char *
symlink_for_subject_hash (p11_extract_info *ex)
{
- unsigned char md[P11_HASH_SHA1_LEN];
+ unsigned char md[P11_DIGEST_SHA1_LEN];
p11_buffer der;
CK_ATTRIBUTE *subject;
unsigned long hash;
@@ -545,7 +545,7 @@ symlink_for_subject_hash (p11_extract_info *ex)
return_val_if_fail (der.data != NULL, NULL);
if (p11_openssl_canon_name_der (ex->asn1_defs, &der)) {
- p11_hash_sha1 (md, der.data, der.len, NULL);
+ p11_digest_sha1 (md, der.data, der.len, NULL);
hash = (
((unsigned long)md[0] ) | ((unsigned long)md[1] << 8L) |
@@ -563,7 +563,7 @@ symlink_for_subject_hash (p11_extract_info *ex)
static char *
symlink_for_subject_old_hash (p11_extract_info *ex)
{
- unsigned char md[P11_HASH_MD5_LEN];
+ unsigned char md[P11_DIGEST_MD5_LEN];
CK_ATTRIBUTE *subject;
unsigned long hash;
char *linkname;
@@ -572,7 +572,7 @@ symlink_for_subject_old_hash (p11_extract_info *ex)
if (!subject)
return NULL;
- p11_hash_md5 (md, subject->pValue, subject->ulValueLen, NULL);
+ p11_digest_md5 (md, subject->pValue, subject->ulValueLen, NULL);
hash = (
((unsigned long)md[0] ) | ((unsigned long)md[1] << 8L) |
diff --git a/trust/parser.c b/trust/parser.c
index 3d5bae7..97f549d 100644
--- a/trust/parser.c
+++ b/trust/parser.c
@@ -40,7 +40,7 @@
#define P11_DEBUG_FLAG P11_DEBUG_TRUST
#include "debug.h"
#include "dict.h"
-#include "hash.h"
+#include "digest.h"
#include "message.h"
#include "module.h"
#include "oid.h"
@@ -75,7 +75,7 @@ struct _p11_parser {
int flags;
};
-#define ID_LENGTH P11_HASH_SHA1_LEN
+#define ID_LENGTH P11_DIGEST_SHA1_LEN
typedef int (* parser_func) (p11_parser *parser,
const unsigned char *data,
diff --git a/trust/tests/Makefile.am b/trust/tests/Makefile.am
index b0581cb..5a6c9ec 100644
--- a/trust/tests/Makefile.am
+++ b/trust/tests/Makefile.am
@@ -20,7 +20,8 @@ noinst_LTLIBRARIES = \
libtrust-test.la
libtrust_test_la_SOURCES = \
- test-trust.c test-trust.h
+ test-trust.c test-trust.h \
+ $(TRUST)/digest.c
LDADD = \
$(top_builddir)/trust/libtrust-testable.la \
@@ -31,9 +32,11 @@ LDADD = \
$(top_builddir)/common/libp11-test.la \
$(top_builddir)/common/libp11-common.la \
$(LIBTASN1_LIBS) \
+ $(HASH_LIBS) \
$(NULL)
CHECK_PROGS = \
+ test-digest \
test-persist \
test-index \
test-parser \
@@ -67,7 +70,9 @@ noinst_PROGRAMS = \
frob_nss_trust_LDADD = \
$(top_builddir)/common/libp11-common.la \
- $(top_builddir)/p11-kit/libp11-kit.la
+ $(top_builddir)/p11-kit/libp11-kit.la \
+ $(HASH_LIBS) \
+ $(NULL)
TESTS = $(CHECK_PROGS)
diff --git a/trust/tests/test-builder.c b/trust/tests/test-builder.c
index 3f71b14..6f9fdcc 100644
--- a/trust/tests/test-builder.c
+++ b/trust/tests/test-builder.c
@@ -42,8 +42,8 @@
#include "attrs.h"
#include "builder.h"
-#include "hash.h"
#include "debug.h"
+#include "digest.h"
#include "index.h"
#include "message.h"
#include "oid.h"
@@ -184,7 +184,7 @@ test_build_certificate (void)
static void
test_build_certificate_empty (void)
{
- unsigned char checksum[P11_HASH_SHA1_LEN];
+ unsigned char checksum[P11_DIGEST_SHA1_LEN];
CK_ULONG domain = 0;
CK_ULONG category = 0;
@@ -221,7 +221,7 @@ test_build_certificate_empty (void)
CK_ATTRIBUTE *extra;
CK_RV rv;
- p11_hash_sha1 (checksum, test_cacert3_ca_der, sizeof (test_cacert3_ca_der), NULL);
+ p11_digest_sha1 (checksum, test_cacert3_ca_der, sizeof (test_cacert3_ca_der), NULL);
attrs = NULL;
extra = NULL;
diff --git a/trust/tests/test-digest.c b/trust/tests/test-digest.c
new file mode 100644
index 0000000..f2cb669
--- /dev/null
+++ b/trust/tests/test-digest.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@gnome.org>
+ */
+
+#include "config.h"
+#include "test.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "digest.h"
+
+const char *sha1_input[] = {
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ NULL
+};
+
+const char *sha1_checksum[] = {
+ "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D",
+ "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1",
+ NULL
+};
+
+static void
+test_sha1 (void)
+{
+ unsigned char checksum[P11_DIGEST_SHA1_LEN];
+ size_t len;
+ int i;
+
+ for (i = 0; sha1_input[i] != NULL; i++) {
+ memset (checksum, 0, sizeof (checksum));
+ len = strlen (sha1_input[i]);
+
+ p11_digest_sha1 (checksum, sha1_input[i], len, NULL);
+ assert (memcmp (sha1_checksum[i], checksum, P11_DIGEST_SHA1_LEN) == 0);
+
+ if (len > 6) {
+ p11_digest_sha1 (checksum, sha1_input[i], 6, sha1_input[i] + 6, len - 6, NULL);
+ assert (memcmp (sha1_checksum[i], checksum, P11_DIGEST_SHA1_LEN) == 0);
+ }
+ }
+}
+
+static void
+test_sha1_long (void)
+{
+ unsigned char checksum[P11_DIGEST_SHA1_LEN];
+ char *expected = "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F";
+ char *input;
+
+ input = malloc (1000000);
+ assert (input != NULL);
+ memset (input, 'a', 1000000);
+
+ p11_digest_sha1 (checksum, input, 1000000, NULL);
+ assert (memcmp (expected, checksum, P11_DIGEST_SHA1_LEN) == 0);
+
+ free (input);
+}
+
+const char *md5_input[] = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ NULL
+};
+
+const char *md5_checksum[] = {
+ "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
+ "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61",
+ "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72",
+ "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0",
+ "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b",
+ NULL
+};
+
+static void
+test_md5 (void)
+{
+ unsigned char checksum[P11_DIGEST_MD5_LEN];
+ size_t len;
+ int i;
+
+ for (i = 0; md5_input[i] != NULL; i++) {
+ memset (checksum, 0, sizeof (checksum));
+ len = strlen (md5_input[i]);
+
+ p11_digest_md5 (checksum, md5_input[i], len, NULL);
+ assert (memcmp (md5_checksum[i], checksum, P11_DIGEST_MD5_LEN) == 0);
+
+ if (len > 5) {
+ p11_digest_md5 (checksum, md5_input[i], 5, md5_input[i] + 5, len - 5, NULL);
+ assert (memcmp (md5_checksum[i], checksum, P11_DIGEST_MD5_LEN) == 0);
+ }
+ }
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ p11_test (test_sha1, "/digest/sha1");
+ p11_test (test_sha1_long, "/digest/sha1-long");
+ p11_test (test_md5, "/digest/md5");
+ return p11_test_run (argc, argv);
+}
diff --git a/trust/tests/test-module.c b/trust/tests/test-module.c
index 33cdd48..80747da 100644
--- a/trust/tests/test-module.c
+++ b/trust/tests/test-module.c
@@ -43,7 +43,7 @@
#include <string.h>
#include "attrs.h"
-#include "hash.h"
+#include "digest.h"
#include "library.h"
#include "path.h"
#include "parser.h"
@@ -485,8 +485,8 @@ check_trust_object_hashes (CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE trust,
CK_ATTRIBUTE *cert)
{
- unsigned char sha1[P11_HASH_SHA1_LEN];
- unsigned char md5[P11_HASH_MD5_LEN];
+ unsigned char sha1[P11_DIGEST_SHA1_LEN];
+ unsigned char md5[P11_DIGEST_MD5_LEN];
unsigned char check[128];
CK_ATTRIBUTE *value;
CK_RV rv;
@@ -503,10 +503,10 @@ check_trust_object_hashes (CK_SESSION_HANDLE session,
value = p11_attrs_find_valid (cert, CKA_VALUE);
assert_ptr_not_null (value);
- p11_hash_md5 (check, value->pValue, value->ulValueLen, NULL);
+ p11_digest_md5 (check, value->pValue, value->ulValueLen, NULL);
assert (memcmp (md5, check, sizeof (md5)) == 0);
- p11_hash_sha1 (check, value->pValue, value->ulValueLen, NULL);
+ p11_digest_sha1 (check, value->pValue, value->ulValueLen, NULL);
assert (memcmp (sha1, check, sizeof (sha1)) == 0);
}
diff --git a/trust/x509.c b/trust/x509.c
index 2f81463..f49be73 100644
--- a/trust/x509.c
+++ b/trust/x509.c
@@ -37,7 +37,7 @@
#include "asn1.h"
#define P11_DEBUG_FLAG P11_DEBUG_TRUST
#include "debug.h"
-#include "hash.h"
+#include "digest.h"
#include "oid.h"
#include "utf8.h"
#include "x509.h"
@@ -108,7 +108,7 @@ p11_x509_calc_keyid (node_asn *cert,
return_val_if_fail (ret == ASN1_SUCCESS, false);
return_val_if_fail (end >= start, false);
- p11_hash_sha1 (keyid, (der + start), (end - start) + 1, NULL);
+ p11_digest_sha1 (keyid, (der + start), (end - start) + 1, NULL);
return true;
}