]> granicus.if.org Git - p11-kit/commitdiff
Add support for using freebl3 for SHA1 and MD5 hashing
authorStef Walter <stef@thewalter.net>
Wed, 10 Jul 2013 12:28:15 +0000 (14:28 +0200)
committerStef Walter <stef@thewalter.net>
Wed, 10 Jul 2013 13:07:55 +0000 (15:07 +0200)
Since we don't want to link freebl3 to libp11-kit.so where it isn't
needed, move the SHA-1 and MD5 digest functionality to the trust/
directory.

17 files changed:
common/hash.c
common/hash.h
common/tests/test-hash.c
configure.ac
doc/manual/p11-kit-devel.xml
trust/Makefile.am
trust/builder.c
trust/digest.c [new file with mode: 0644]
trust/digest.h [new file with mode: 0644]
trust/extract-jks.c
trust/extract-openssl.c
trust/parser.c
trust/tests/Makefile.am
trust/tests/test-builder.c
trust/tests/test-digest.c [new file with mode: 0644]
trust/tests/test-module.c
trust/x509.c

index 9fe3668849ada591b99f67dda109db2a06771f73..68a6d40f7f44bc9dc1c171b0f6c3c1d9c77cc4ea 100644 (file)
 #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
  *
index 09f76467ec0d37df96cc2626502a5a5dfcbf1cdf..41371c669c9d4c27ccfddf4923bf8a70bf57fa2f 100644 (file)
 
 #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,
index c679cad0fe1118917dda726886227097b15f3a52..a12d5a425bee34bbc57c6cbcebaa396e916f72eb 100644 (file)
 
 #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);
index 886d1eb11f47782ce7357195ee76c2156ee0185a..5eb6c2c826576b9d3ee6b7f67e0bfc661a415208 100644 (file)
@@ -185,6 +185,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
 
@@ -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
index 873aff1e32f7697784c75e911abe64fee7d1f719..007118a145fdf6410fe580864abbb41cd80837b8 100644 (file)
@@ -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>
@@ -196,6 +200,13 @@ $ make install
                                        <listitem><para>Enables strict checks during building of p11-kit. All
                                        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
index 58e48891ee01f79b3a214ada784a0d0b5525d85d..ca7e2d748a1ea1a92be0347a236d0af78aeb92cd 100644 (file)
@@ -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 \
index d39890d81996094505880a97b5a6f1905c022b59..fdaae34dc8396741b690af1983c94af3c31c3ea1 100644 (file)
@@ -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 (file)
index 0000000..5cac83a
--- /dev/null
@@ -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 (file)
index 0000000..82d48fe
--- /dev/null
@@ -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_ */
index 987ea261874523d27a9d4e8274196bd105d4706c..8a39cfd86d677cefc8d2b1ae813c4e98cc388024 100644 (file)
@@ -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;
index b7603b0846bdd178bee7cdbc7eb1422ebd59df90..b503b6730e7824bf66b7dd3418e06029c38b85b5 100644 (file)
@@ -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) |
index 3d5bae7e39a55df59f3b5b5b5b32a9b3542dcd6a..97f549d173e9e33f72a8f5be5e36365e6e8d9f27 100644 (file)
@@ -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,
index b0581cb7392ee3011a0764e5497ea631f4ec579a..5a6c9ec91f87b0061bbda1187b201d57869e125d 100644 (file)
@@ -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)
 
index 3f71b140ce85f600489226670e118b5eaddc5803..6f9fdcce39b0e9278ccc59e225d3a1b60447e75b 100644 (file)
@@ -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 (file)
index 0000000..f2cb669
--- /dev/null
@@ -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);
+}
index 33cdd48a5323495c1bbfbba060bea2f25434b334..80747da0046378b39070933f52e5c419e9aeb496 100644 (file)
@@ -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);
 }
 
index 2f81463af8941ca877529d936ef88a3e6cec5377..f49be732cce699c79a2e01b62895c5f094679a8a 100644 (file)
@@ -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;
 }