Beispiel #1
0
/**
 * Store calculated hash into the given array.
 *
 * @param ctx the algorithm context containing current hashing state
 * @param result calculated hash in binary form
 */
void md5_final(md5_ctx *ctx, unsigned char result[16])
{
  unsigned index = ((unsigned)ctx->length & 63) >> 2;
  unsigned shift = ((unsigned)ctx->length & 3) * 8;

  /* pad message and run for last block */

  /* append the byte 0x80 to the message */
  ctx->message[index]   &= ~(0xFFFFFFFF << shift);
  ctx->message[index++] ^= 0x80 << shift;

  /* if no room left in the message to store 64-bit message length */
  if(index > 14) {
    /* then fill the rest with zeros and process it */
    while(index < 16) {
      ctx->message[index++] = 0;
    }
    md5_process_block(ctx->hash, ctx->message);
    index = 0;
  }
  while(index < 14) {
    ctx->message[index++] = 0;
  }
  ctx->message[14] = (unsigned)(ctx->length << 3);
  ctx->message[15] = (unsigned)(ctx->length >> 29);
  md5_process_block(ctx->hash, ctx->message);

  le32_copy(result, &ctx->hash, 16);
}
Beispiel #2
0
void md5_finish(md5_ctx_t *p) {
	md5_inc_processed(p, p->pos);

	// size should be in bits
	p->processed[1] <<= 3;
	p->processed[1] |= (p->processed[0] >> 29) & 7;
	p->processed[0] <<= 3;

	p->buf[p->pos++] = 0x80;

	if (p->pos > 56) {
		while (p->pos < BLOCK_SIZE)
			p->buf[p->pos++] = 0x00;
		md5_process_block(p, (uint32*)p->buf);
		p->pos = 0;
	}

	while (p->pos < 56)
		p->buf[p->pos++] = 0x00;

	/* append size */
	p->buf[p->pos++] = p->processed[0];
	p->buf[p->pos++] = p->processed[0] >> 8;
	p->buf[p->pos++] = p->processed[0] >> 16;
	p->buf[p->pos++] = p->processed[0] >> 24;
	p->buf[p->pos++] = p->processed[1];
	p->buf[p->pos++] = p->processed[1] >> 8;
	p->buf[p->pos++] = p->processed[1] >> 16;
	p->buf[p->pos++] = p->processed[1] >> 24;

	md5_process_block(p, (uint32*)p->buf);

	// put complited md5 hash into buf
	p->buf[ 0] = (byte)(p->d[0]);
	p->buf[ 1] = (byte)(p->d[0]>>8);
	p->buf[ 2] = (byte)(p->d[0]>>16);
	p->buf[ 3] = (byte)(p->d[0]>>24);
	p->buf[ 4] = (byte)(p->d[1]);
	p->buf[ 5] = (byte)(p->d[1]>>8);
	p->buf[ 6] = (byte)(p->d[1]>>16);
	p->buf[ 7] = (byte)(p->d[1]>>24);
	p->buf[ 8] = (byte)(p->d[2]);
	p->buf[ 9] = (byte)(p->d[2]>>8);
	p->buf[10] = (byte)(p->d[2]>>16);
	p->buf[11] = (byte)(p->d[2]>>24);
	p->buf[12] = (byte)(p->d[3]);
	p->buf[13] = (byte)(p->d[3]>>8);
	p->buf[14] = (byte)(p->d[3]>>16);
	p->buf[15] = (byte)(p->d[3]>>24);
}
Beispiel #3
0
int
hmac_md5 (const void *key, size_t keylen,
          const void *in, size_t inlen, void *resbuf)
{
  struct md5_ctx inner;
  struct md5_ctx outer;
  char optkeybuf[16];
  char block[64];
  char innerhash[16];

  /* Reduce the key's size, so that it becomes <= 64 bytes large.  */

  if (keylen > 64)
    {
      struct md5_ctx keyhash;

      md5_init_ctx (&keyhash);
      md5_process_bytes (key, keylen, &keyhash);
      md5_finish_ctx (&keyhash, optkeybuf);

      key = optkeybuf;
      keylen = 16;
    }

  /* Compute INNERHASH from KEY and IN.  */

  md5_init_ctx (&inner);

  memset (block, IPAD, sizeof (block));
  memxor (block, key, keylen);

  md5_process_block (block, 64, &inner);
  md5_process_bytes (in, inlen, &inner);

  md5_finish_ctx (&inner, innerhash);

  /* Compute result from KEY and INNERHASH.  */

  md5_init_ctx (&outer);

  memset (block, OPAD, sizeof (block));
  memxor (block, key, keylen);

  md5_process_block (block, 64, &outer);
  md5_process_bytes (innerhash, 16, &outer);

  md5_finish_ctx (&outer, resbuf);

  return 0;
}
Beispiel #4
0
/* find the initial vector required to evilize FILE, return it in
   IV. Returns 0 on success, 1 if crib was not found. */
static int find_iv(FILE *fin, unsigned int IV[4]) {
  struct md5_ctx ctx;
  char buf[64];
  int r;
  int i;

  md5_init_ctx(&ctx);

  while (1) {
    r = fread(buf, 1, 64, fin);
    if (r < 64) {
      return 1;
    }
    for (i=0; i<64; i++) {
      if (memcmp(buf, crib+i, 64) == 0) {
	goto crib_found;
      }
    }
    md5_process_block(buf, 64, &ctx);
  }
 crib_found:
  /* find md5 collision for the given ctx initial value */

  IV[0] = ctx.A;
  IV[1] = ctx.B;
  IV[2] = ctx.C;
  IV[3] = ctx.D;
  return 0;
}
Beispiel #5
0
void md5_process(md5_ctx_t *p, const unsigned char *data, unsigned size) {
	if (p->pos) {
		uint n = BLOCK_SIZE - p->pos;
		if (n > size)
			n = size;
		memcpy(p->buf+p->pos, data, n);
		p->pos += n;
		data += n;
		size -= n;
		if (p->pos == BLOCK_SIZE) {
			md5_process_block(p, (uint32*)p->buf);
			md5_inc_processed(p, BLOCK_SIZE);
			p->pos = 0;
		}
	}
	while (size >= BLOCK_SIZE) {
		md5_process_block(p, (uint32*)data);
		md5_inc_processed(p, BLOCK_SIZE);
		data += BLOCK_SIZE;
		size -= BLOCK_SIZE;
	}
	memcpy(p->buf, data, size);
	p->pos = size;
}
Beispiel #6
0
/**
 * Calculate message hash.
 * Can be called repeatedly with chunks of the message to be hashed.
 *
 * @param ctx the algorithm context containing current hashing state
 * @param msg message chunk
 * @param size length of the message chunk
 */
void md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size)
{
  unsigned index = (unsigned)ctx->length & 63;
  ctx->length += size;

  /* fill partial block */
  if(index) {
    unsigned left = md5_block_size - index;
    le32_copy((char*)ctx->message + index, msg, (size < left ? size : left));
    if(size < left) return;

    /* process partial block */
    md5_process_block(ctx->hash, ctx->message);
    msg  += left;
    size -= left;
  }
  while(size >= md5_block_size) {
    unsigned* aligned_message_block;
    if( IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg) ) {
      /* the most common case is processing a 32-bit aligned message 
         on a little-endian CPU without copying it */
      aligned_message_block = (unsigned*)msg;
    } else {
      le32_copy(ctx->message, msg, md5_block_size);
      aligned_message_block = ctx->message;
    }

    md5_process_block(ctx->hash, aligned_message_block);
    msg  += md5_block_size;
    size -= md5_block_size;
  }
  if(size) {
    /* save leftovers */
    le32_copy(ctx->message, msg, size);
  }
}
Beispiel #7
0
/* This code is based on code in md5.c in GNU textutils. */
static size_t
init_from_stream(FILE *stream, size_t max_size)
{
    char buffer[BLOCKSIZE + 72];
    size_t sum, block_size, total;

    ENTER("");

    if (max_size <= 0)
    {
        LEAVE("max_size is 0 or less, skipping stream");
        return 0;
    }

    total = 0;

    /* Iterate over file contents. */
    while (1)
    {
        /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
         * computation function processes the whole buffer so that with the
         * next round of the loop another block can be read.  */
        size_t n;
        sum = 0;

        if (max_size < BLOCKSIZE)
            block_size = max_size;
        else
            block_size = BLOCKSIZE;

        /* Read block.  Take care for partial reads.  */
        do
        {
            n = fread (buffer + sum, 1, block_size - sum, stream);

            sum += n;
        }
        while (sum < block_size && n != 0);

        max_size -= sum;

        if (n == 0 && ferror (stream))
        {
            LEAVE("error while reading stream");
            return total;
        }

        /* If end of file or max_size is reached, end the loop. */
        if ((n == 0) || (max_size == 0))
            break;

        /* Process buffer with BLOCKSIZE bytes.  Note that
         * BLOCKSIZE % 64 == 0  */
        md5_process_block (buffer, BLOCKSIZE, &guid_context);

        total += sum;
    }

    /* Add the last bytes if necessary.  */
    if (sum > 0)
    {
        md5_process_bytes (buffer, sum, &guid_context);
        total += sum;
    }

    LEAVE("");
    return total;
}
Beispiel #8
0
static void
dosum (struct md5_ctx *ctx, const char *file)
{
  FILE *f;
  char buffer[BLOCKSIZE + 72];
  size_t sum;

  f = fopen (file, "rb");
  if (!f)
    {
      fprintf (stderr, "opening %s: %s\n", file, xstrerror (errno));
      exit (1);
    }

  /* Some executable formats have timestamps in the first 16 bytes, yuck.  */
  if (fseek (f, 16, SEEK_SET) != 0)
     {
      fprintf (stderr, "seeking in %s: %s\n", file, xstrerror (errno));
      exit (1);
    }

  /* Iterate over full file contents.  */
  while (1)
    {
      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
	 computation function processes the whole buffer so that with the
	 next round of the loop another block can be read.  */
      size_t n;
      sum = 0;

      /* Read block.  Take care for partial reads.  */
      do
	{
	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, f);

	  sum += n;
	}
      while (sum < BLOCKSIZE && n != 0);
      if (n == 0 && ferror (f))
        exit (1);

      /* If end of file is reached, end the loop.  */
      if (n == 0)
	break;

      /* Process buffer with BLOCKSIZE bytes.  Note that
			BLOCKSIZE % 64 == 0
       */
      md5_process_block (buffer, BLOCKSIZE, ctx);
    }

  /* Add the last bytes if necessary.  */
  if (sum > 0)
    md5_process_bytes (buffer, sum, ctx);

  if (fclose (f) != 0)
     {
      fprintf (stderr, "reading %s: %s\n", file, xstrerror (errno));
      exit (1);
    }
}