Blame glib/glib/gchecksum.c

Packit db3073
/* gchecksum.h - data hashing functions
Packit db3073
 *
Packit db3073
 * Copyright (C) 2007  Emmanuele Bassi  <ebassi@gnome.org>
Packit db3073
 *
Packit db3073
 * This library is free software; you can redistribute it and/or
Packit db3073
 * modify it under the terms of the GNU Library General Public
Packit db3073
 * License as published by the Free Software Foundation; either
Packit db3073
 * version 2 of the License, or (at your option) any later version.
Packit db3073
 *
Packit db3073
 * This library is distributed in the hope that it will be useful,
Packit db3073
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit db3073
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit db3073
 * Library General Public License for more details.
Packit db3073
 *
Packit db3073
 * You should have received a copy of the GNU Library General Public
Packit db3073
 * License along with this library; if not, write to the
Packit db3073
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit db3073
 * Boston, MA 02111-1307, USA.
Packit db3073
 */
Packit db3073
Packit db3073
#include "config.h"
Packit db3073
Packit db3073
#include <string.h>
Packit db3073
Packit db3073
#include "gchecksum.h"
Packit db3073
Packit db3073
#include "gslice.h"
Packit db3073
#include "gmem.h"
Packit db3073
#include "gstrfuncs.h"
Packit db3073
#include "gtestutils.h"
Packit db3073
#include "gtypes.h"
Packit db3073
#include "glibintl.h"
Packit db3073
Packit db3073
Packit db3073
/**
Packit db3073
 * SECTION:checksum
Packit db3073
 * @title: Data Checksums
Packit db3073
 * @short_description: computes the checksum for data
Packit db3073
 *
Packit db3073
 * GLib provides a generic API for computing checksums (or "digests")
Packit db3073
 * for a sequence of arbitrary bytes, using various hashing algorithms
Packit db3073
 * like MD5, SHA-1 and SHA-256. Checksums are commonly used in various
Packit db3073
 * environments and specifications.
Packit db3073
 *
Packit db3073
 * GLib supports incremental checksums using the GChecksum data
Packit db3073
 * structure, by calling g_checksum_update() as long as there's data
Packit db3073
 * available and then using g_checksum_get_string() or
Packit db3073
 * g_checksum_get_digest() to compute the checksum and return it either
Packit db3073
 * as a string in hexadecimal form, or as a raw sequence of bytes. To
Packit db3073
 * compute the checksum for binary blobs and NUL-terminated strings in
Packit db3073
 * one go, use the convenience functions g_compute_checksum_for_data()
Packit db3073
 * and g_compute_checksum_for_string(), respectively.
Packit db3073
 *
Packit db3073
 * Support for checksums has been added in GLib 2.16
Packit db3073
 **/
Packit db3073
Packit db3073
#define IS_VALID_TYPE(type)     ((type) >= G_CHECKSUM_MD5 && (type) <= G_CHECKSUM_SHA256)
Packit db3073
Packit db3073
/* The fact that these are lower case characters is part of the ABI */
Packit db3073
static const gchar hex_digits[] = "0123456789abcdef";
Packit db3073
Packit db3073
#define MD5_DATASIZE    64
Packit db3073
#define MD5_DIGEST_LEN  16
Packit db3073
Packit db3073
typedef struct
Packit db3073
{
Packit db3073
  guint32 buf[4];
Packit db3073
  guint32 bits[2];
Packit db3073
Packit db3073
  union {
Packit db3073
    guchar data[MD5_DATASIZE];
Packit db3073
    guint32 data32[MD5_DATASIZE / 4];
Packit db3073
  } u;
Packit db3073
Packit db3073
  guchar digest[MD5_DIGEST_LEN];
Packit db3073
} Md5sum;
Packit db3073
Packit db3073
#define SHA1_DATASIZE   64
Packit db3073
#define SHA1_DIGEST_LEN 20
Packit db3073
Packit db3073
typedef struct
Packit db3073
{
Packit db3073
  guint32 buf[5];
Packit db3073
  guint32 bits[2];
Packit db3073
Packit db3073
  /* we pack 64 unsigned chars into 16 32-bit unsigned integers */
Packit db3073
  guint32 data[16];
Packit db3073
Packit db3073
  guchar digest[SHA1_DIGEST_LEN];
Packit db3073
} Sha1sum;
Packit db3073
Packit db3073
#define SHA256_DATASIZE         64
Packit db3073
#define SHA256_DIGEST_LEN       32
Packit db3073
Packit db3073
typedef struct
Packit db3073
{
Packit db3073
  guint32 buf[8];
Packit db3073
  guint32 bits[2];
Packit db3073
Packit db3073
  guint8 data[SHA256_DATASIZE];
Packit db3073
Packit db3073
  guchar digest[SHA256_DIGEST_LEN];
Packit db3073
} Sha256sum;
Packit db3073
Packit db3073
struct _GChecksum
Packit db3073
{
Packit db3073
  GChecksumType type;
Packit db3073
Packit db3073
  gchar *digest_str;
Packit db3073
Packit db3073
  union {
Packit db3073
    Md5sum md5;
Packit db3073
    Sha1sum sha1;
Packit db3073
    Sha256sum sha256;
Packit db3073
  } sum;
Packit db3073
};
Packit db3073
Packit db3073
/* we need different byte swapping functions because MD5 expects buffers
Packit db3073
 * to be little-endian, while SHA1 and SHA256 expect them in big-endian
Packit db3073
 * form.
Packit db3073
 */
Packit db3073
Packit db3073
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
Packit db3073
#define md5_byte_reverse(buffer,length)
Packit db3073
#else
Packit db3073
/* assume that the passed buffer is integer aligned */
Packit db3073
static inline void
Packit db3073
md5_byte_reverse (guchar *buffer,
Packit db3073
                  gulong  length)
Packit db3073
{
Packit db3073
  guint32 bit;
Packit db3073
Packit db3073
  do
Packit db3073
    {
Packit db3073
      bit = (guint32) ((unsigned) buffer[3] << 8 | buffer[2]) << 16 |
Packit db3073
                      ((unsigned) buffer[1] << 8 | buffer[0]);
Packit db3073
      * (guint32 *) buffer = bit;
Packit db3073
      buffer += 4;
Packit db3073
    }
Packit db3073
  while (--length);
Packit db3073
}
Packit db3073
#endif /* G_BYTE_ORDER == G_LITTLE_ENDIAN */
Packit db3073
Packit db3073
#if G_BYTE_ORDER == G_BIG_ENDIAN
Packit db3073
#define sha_byte_reverse(buffer,length)
Packit db3073
#else
Packit db3073
static inline void
Packit db3073
sha_byte_reverse (guint32 *buffer,
Packit db3073
                  gint     length)
Packit db3073
{
Packit db3073
  length /= sizeof (guint32);
Packit db3073
  while (length--)
Packit db3073
    {
Packit db3073
      *buffer = GUINT32_SWAP_LE_BE (*buffer);
Packit db3073
      ++buffer;
Packit db3073
    }
Packit db3073
}
Packit db3073
#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
Packit db3073
Packit db3073
static gchar *
Packit db3073
digest_to_string (guint8 *digest,
Packit db3073
                  gsize   digest_len)
Packit db3073
{
Packit db3073
  gint len = digest_len * 2;
Packit db3073
  gint i;
Packit db3073
  gchar *retval;
Packit db3073
Packit db3073
  retval = g_new (gchar, len + 1);
Packit db3073
Packit db3073
  for (i = 0; i < digest_len; i++)
Packit db3073
    {
Packit db3073
      guint8 byte = digest[i];
Packit db3073
Packit db3073
      retval[2 * i] = hex_digits[byte >> 4];
Packit db3073
      retval[2 * i + 1] = hex_digits[byte & 0xf];
Packit db3073
    }
Packit db3073
Packit db3073
  retval[len] = 0;
Packit db3073
Packit db3073
  return retval;
Packit db3073
}
Packit db3073
Packit db3073
/*
Packit db3073
 * MD5 Checksum
Packit db3073
 */
Packit db3073
Packit db3073
/* This MD5 digest computation is based on the equivalent code
Packit db3073
 * written by Colin Plumb. It came with this notice:
Packit db3073
 *
Packit db3073
 * This code implements the MD5 message-digest algorithm.
Packit db3073
 * The algorithm is due to Ron Rivest.  This code was
Packit db3073
 * written by Colin Plumb in 1993, no copyright is claimed.
Packit db3073
 * This code is in the public domain; do with it what you wish.
Packit db3073
 *
Packit db3073
 * Equivalent code is available from RSA Data Security, Inc.
Packit db3073
 * This code has been tested against that, and is equivalent,
Packit db3073
 * except that you don't need to include two pages of legalese
Packit db3073
 * with every copy.
Packit db3073
 */
Packit db3073
Packit db3073
static void
Packit db3073
md5_sum_init (Md5sum *md5)
Packit db3073
{
Packit db3073
  /* arbitrary constants */
Packit db3073
  md5->buf[0] = 0x67452301;
Packit db3073
  md5->buf[1] = 0xefcdab89;
Packit db3073
  md5->buf[2] = 0x98badcfe;
Packit db3073
  md5->buf[3] = 0x10325476;
Packit db3073
Packit db3073
  md5->bits[0] = md5->bits[1] = 0;
Packit db3073
}
Packit db3073
Packit db3073
/*
Packit db3073
 * The core of the MD5 algorithm, this alters an existing MD5 hash to
Packit db3073
 * reflect the addition of 16 longwords of new data.  md5_sum_update()
Packit db3073
 * blocks the data and converts bytes into longwords for this routine.
Packit db3073
 */
Packit db3073
static void
Packit db3073
md5_transform (guint32       buf[4],
Packit db3073
               guint32 const in[16])
Packit db3073
{
Packit db3073
  register guint32 a, b, c, d;
Packit db3073
Packit db3073
/* The four core functions - F1 is optimized somewhat */
Packit db3073
#define F1(x, y, z)     (z ^ (x & (y ^ z)))
Packit db3073
#define F2(x, y, z)     F1 (z, x, y)
Packit db3073
#define F3(x, y, z)     (x ^ y ^ z)
Packit db3073
#define F4(x, y, z)     (y ^ (x | ~z))
Packit db3073
Packit db3073
/* This is the central step in the MD5 algorithm. */
Packit db3073
#define md5_step(f, w, x, y, z, data, s) \
Packit db3073
        ( w += f (x, y, z) + data,  w = w << s | w >> (32 - s),  w += x )
Packit db3073
Packit db3073
  a = buf[0];
Packit db3073
  b = buf[1];
Packit db3073
  c = buf[2];
Packit db3073
  d = buf[3];
Packit db3073
Packit db3073
  md5_step (F1, a, b, c, d, in[0]  + 0xd76aa478,  7);
Packit db3073
  md5_step (F1, d, a, b, c, in[1]  + 0xe8c7b756, 12);
Packit db3073
  md5_step (F1, c, d, a, b, in[2]  + 0x242070db, 17);
Packit db3073
  md5_step (F1, b, c, d, a, in[3]  + 0xc1bdceee, 22);
Packit db3073
  md5_step (F1, a, b, c, d, in[4]  + 0xf57c0faf,  7);
Packit db3073
  md5_step (F1, d, a, b, c, in[5]  + 0x4787c62a, 12);
Packit db3073
  md5_step (F1, c, d, a, b, in[6]  + 0xa8304613, 17);
Packit db3073
  md5_step (F1, b, c, d, a, in[7]  + 0xfd469501, 22);
Packit db3073
  md5_step (F1, a, b, c, d, in[8]  + 0x698098d8,  7);
Packit db3073
  md5_step (F1, d, a, b, c, in[9]  + 0x8b44f7af, 12);
Packit db3073
  md5_step (F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
Packit db3073
  md5_step (F1, b, c, d, a, in[11] + 0x895cd7be, 22);
Packit db3073
  md5_step (F1, a, b, c, d, in[12] + 0x6b901122,  7);
Packit db3073
  md5_step (F1, d, a, b, c, in[13] + 0xfd987193, 12);
Packit db3073
  md5_step (F1, c, d, a, b, in[14] + 0xa679438e, 17);
Packit db3073
  md5_step (F1, b, c, d, a, in[15] + 0x49b40821, 22);
Packit db3073
        
Packit db3073
  md5_step (F2, a, b, c, d, in[1]  + 0xf61e2562,  5);
Packit db3073
  md5_step (F2, d, a, b, c, in[6]  + 0xc040b340,  9);
Packit db3073
  md5_step (F2, c, d, a, b, in[11] + 0x265e5a51, 14);
Packit db3073
  md5_step (F2, b, c, d, a, in[0]  + 0xe9b6c7aa, 20);
Packit db3073
  md5_step (F2, a, b, c, d, in[5]  + 0xd62f105d,  5);
Packit db3073
  md5_step (F2, d, a, b, c, in[10] + 0x02441453,  9);
Packit db3073
  md5_step (F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
Packit db3073
  md5_step (F2, b, c, d, a, in[4]  + 0xe7d3fbc8, 20);
Packit db3073
  md5_step (F2, a, b, c, d, in[9]  + 0x21e1cde6,  5);
Packit db3073
  md5_step (F2, d, a, b, c, in[14] + 0xc33707d6,  9);
Packit db3073
  md5_step (F2, c, d, a, b, in[3]  + 0xf4d50d87, 14);
Packit db3073
  md5_step (F2, b, c, d, a, in[8]  + 0x455a14ed, 20);
Packit db3073
  md5_step (F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
Packit db3073
  md5_step (F2, d, a, b, c, in[2]  + 0xfcefa3f8,  9);
Packit db3073
  md5_step (F2, c, d, a, b, in[7]  + 0x676f02d9, 14);
Packit db3073
  md5_step (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
Packit db3073
Packit db3073
  md5_step (F3, a, b, c, d, in[5]  + 0xfffa3942,  4);
Packit db3073
  md5_step (F3, d, a, b, c, in[8]  + 0x8771f681, 11);
Packit db3073
  md5_step (F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
Packit db3073
  md5_step (F3, b, c, d, a, in[14] + 0xfde5380c, 23);
Packit db3073
  md5_step (F3, a, b, c, d, in[1]  + 0xa4beea44,  4);
Packit db3073
  md5_step (F3, d, a, b, c, in[4]  + 0x4bdecfa9, 11);
Packit db3073
  md5_step (F3, c, d, a, b, in[7]  + 0xf6bb4b60, 16);
Packit db3073
  md5_step (F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
Packit db3073
  md5_step (F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
Packit db3073
  md5_step (F3, d, a, b, c, in[0]  + 0xeaa127fa, 11);
Packit db3073
  md5_step (F3, c, d, a, b, in[3]  + 0xd4ef3085, 16);
Packit db3073
  md5_step (F3, b, c, d, a, in[6]  + 0x04881d05, 23);
Packit db3073
  md5_step (F3, a, b, c, d, in[9]  + 0xd9d4d039,  4);
Packit db3073
  md5_step (F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
Packit db3073
  md5_step (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
Packit db3073
  md5_step (F3, b, c, d, a, in[2]  + 0xc4ac5665, 23);
Packit db3073
Packit db3073
  md5_step (F4, a, b, c, d, in[0]  + 0xf4292244,  6);
Packit db3073
  md5_step (F4, d, a, b, c, in[7]  + 0x432aff97, 10);
Packit db3073
  md5_step (F4, c, d, a, b, in[14] + 0xab9423a7, 15);
Packit db3073
  md5_step (F4, b, c, d, a, in[5]  + 0xfc93a039, 21);
Packit db3073
  md5_step (F4, a, b, c, d, in[12] + 0x655b59c3,  6);
Packit db3073
  md5_step (F4, d, a, b, c, in[3]  + 0x8f0ccc92, 10);
Packit db3073
  md5_step (F4, c, d, a, b, in[10] + 0xffeff47d, 15);
Packit db3073
  md5_step (F4, b, c, d, a, in[1]  + 0x85845dd1, 21);
Packit db3073
  md5_step (F4, a, b, c, d, in[8]  + 0x6fa87e4f,  6);
Packit db3073
  md5_step (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
Packit db3073
  md5_step (F4, c, d, a, b, in[6]  + 0xa3014314, 15);
Packit db3073
  md5_step (F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
Packit db3073
  md5_step (F4, a, b, c, d, in[4]  + 0xf7537e82,  6);
Packit db3073
  md5_step (F4, d, a, b, c, in[11] + 0xbd3af235, 10);
Packit db3073
  md5_step (F4, c, d, a, b, in[2]  + 0x2ad7d2bb, 15);
Packit db3073
  md5_step (F4, b, c, d, a, in[9]  + 0xeb86d391, 21);
Packit db3073
Packit db3073
  buf[0] += a;
Packit db3073
  buf[1] += b;
Packit db3073
  buf[2] += c;
Packit db3073
  buf[3] += d;
Packit db3073
Packit db3073
#undef F1
Packit db3073
#undef F2
Packit db3073
#undef F3
Packit db3073
#undef F4
Packit db3073
#undef md5_step
Packit db3073
}
Packit db3073
Packit db3073
static void
Packit db3073
md5_sum_update (Md5sum       *md5,
Packit db3073
                const guchar *data,
Packit db3073
                gsize         length)
Packit db3073
{
Packit db3073
  guint32 bit;
Packit db3073
Packit db3073
  bit = md5->bits[0];
Packit db3073
  md5->bits[0] = bit + ((guint32) length << 3);
Packit db3073
Packit db3073
  /* carry from low to high */
Packit db3073
  if (md5->bits[0] < bit)
Packit db3073
    md5->bits[1] += 1;
Packit db3073
Packit db3073
  md5->bits[1] += length >> 29;
Packit db3073
Packit db3073
  /* bytes already in Md5sum->u.data */
Packit db3073
  bit = (bit >> 3) & 0x3f;
Packit db3073
Packit db3073
  /* handle any leading odd-sized chunks */
Packit db3073
  if (bit)
Packit db3073
    {
Packit db3073
      guchar *p = md5->u.data + bit;
Packit db3073
Packit db3073
      bit = MD5_DATASIZE - bit;
Packit db3073
      if (length < bit)
Packit db3073
        {
Packit db3073
          memcpy (p, data, length);
Packit db3073
          return;
Packit db3073
        }
Packit db3073
Packit db3073
      memcpy (p, data, bit);
Packit db3073
Packit db3073
      md5_byte_reverse (md5->u.data, 16);
Packit db3073
      md5_transform (md5->buf, md5->u.data32);
Packit db3073
Packit db3073
      data += bit;
Packit db3073
      length -= bit;
Packit db3073
    }
Packit db3073
Packit db3073
  /* process data in 64-byte chunks */
Packit db3073
  while (length >= MD5_DATASIZE)
Packit db3073
    {
Packit db3073
      memcpy (md5->u.data, data, MD5_DATASIZE);
Packit db3073
Packit db3073
      md5_byte_reverse (md5->u.data, 16);
Packit db3073
      md5_transform (md5->buf, md5->u.data32);
Packit db3073
Packit db3073
      data += MD5_DATASIZE;
Packit db3073
      length -= MD5_DATASIZE;
Packit db3073
    }
Packit db3073
Packit db3073
  /* handle any remaining bytes of data */
Packit db3073
  memcpy (md5->u.data, data, length);
Packit db3073
}
Packit db3073
Packit db3073
/* closes a checksum */
Packit db3073
static void
Packit db3073
md5_sum_close (Md5sum *md5)
Packit db3073
{
Packit db3073
  guint count;
Packit db3073
  guchar *p;
Packit db3073
Packit db3073
  /* Compute number of bytes mod 64 */
Packit db3073
  count = (md5->bits[0] >> 3) & 0x3F;
Packit db3073
Packit db3073
  /* Set the first char of padding to 0x80.
Packit db3073
   * This is safe since there is always at least one byte free
Packit db3073
   */
Packit db3073
  p = md5->u.data + count;
Packit db3073
  *p++ = 0x80;
Packit db3073
Packit db3073
  /* Bytes of padding needed to make 64 bytes */
Packit db3073
  count = MD5_DATASIZE - 1 - count;
Packit db3073
Packit db3073
  /* Pad out to 56 mod 64 */
Packit db3073
  if (count < 8)
Packit db3073
    {
Packit db3073
      /* Two lots of padding:  Pad the first block to 64 bytes */
Packit db3073
      memset (p, 0, count);
Packit db3073
Packit db3073
      md5_byte_reverse (md5->u.data, 16);
Packit db3073
      md5_transform (md5->buf, md5->u.data32);
Packit db3073
Packit db3073
      /* Now fill the next block with 56 bytes */
Packit db3073
      memset (md5->u.data, 0, MD5_DATASIZE - 8);
Packit db3073
    }
Packit db3073
  else
Packit db3073
    {
Packit db3073
      /* Pad block to 56 bytes */
Packit db3073
      memset (p, 0, count - 8);
Packit db3073
    }
Packit db3073
Packit db3073
  md5_byte_reverse (md5->u.data, 14);
Packit db3073
Packit db3073
  /* Append length in bits and transform */
Packit db3073
  md5->u.data32[14] = md5->bits[0];
Packit db3073
  md5->u.data32[15] = md5->bits[1];
Packit db3073
Packit db3073
  md5_transform (md5->buf, md5->u.data32);
Packit db3073
  md5_byte_reverse ((guchar *) md5->buf, 4);
Packit db3073
Packit db3073
  memcpy (md5->digest, md5->buf, 16);
Packit db3073
Packit db3073
  /* Reset buffers in case they contain sensitive data */
Packit db3073
  memset (md5->buf, 0, sizeof (md5->buf));
Packit db3073
  memset (md5->u.data, 0, sizeof (md5->u.data));
Packit db3073
}
Packit db3073
Packit db3073
static gchar *
Packit db3073
md5_sum_to_string (Md5sum *md5)
Packit db3073
{
Packit db3073
  return digest_to_string (md5->digest, MD5_DIGEST_LEN);
Packit db3073
}
Packit db3073
Packit db3073
static void
Packit db3073
md5_sum_digest (Md5sum *md5,
Packit db3073
                guint8 *digest)
Packit db3073
{
Packit db3073
  gint i;
Packit db3073
Packit db3073
  for (i = 0; i < MD5_DIGEST_LEN; i++)
Packit db3073
    digest[i] = md5->digest[i];
Packit db3073
}
Packit db3073
Packit db3073
/*
Packit db3073
 * SHA-1 Checksum
Packit db3073
 */
Packit db3073
Packit db3073
/* The following implementation comes from D-Bus dbus-sha.c. I've changed
Packit db3073
 * it to use GLib types and to work more like the MD5 implementation above.
Packit db3073
 * I left the comments to have an history of this code.
Packit db3073
 *      -- Emmanuele Bassi, ebassi@gnome.org
Packit db3073
 */
Packit db3073
Packit db3073
/* The following comments have the history of where this code
Packit db3073
 * comes from. I actually copied it from GNet in GNOME CVS.
Packit db3073
 * - hp@redhat.com
Packit db3073
 */
Packit db3073
Packit db3073
/*
Packit db3073
 *  sha.h : Implementation of the Secure Hash Algorithm
Packit db3073
 *
Packit db3073
 * Part of the Python Cryptography Toolkit, version 1.0.0
Packit db3073
 *
Packit db3073
 * Copyright (C) 1995, A.M. Kuchling
Packit db3073
 *
Packit db3073
 * Distribute and use freely; there are no restrictions on further
Packit db3073
 * dissemination and usage except those imposed by the laws of your
Packit db3073
 * country of residence.
Packit db3073
 *
Packit db3073
 */
Packit db3073
Packit db3073
/* SHA: NIST's Secure Hash Algorithm */
Packit db3073
Packit db3073
/* Based on SHA code originally posted to sci.crypt by Peter Gutmann
Packit db3073
   in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
Packit db3073
   Modified to test for endianness on creation of SHA objects by AMK.
Packit db3073
   Also, the original specification of SHA was found to have a weakness
Packit db3073
   by NSA/NIST.  This code implements the fixed version of SHA.
Packit db3073
*/
Packit db3073
Packit db3073
/* Here's the first paragraph of Peter Gutmann's posting:
Packit db3073
Packit db3073
The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
Packit db3073
SHA, thanks to Jim Gillogly and an anonymous contributor for the information on
Packit db3073
what's changed in the new version.  The fix is a simple change which involves
Packit db3073
adding a single rotate in the initial expansion function.  It is unknown
Packit db3073
whether this is an optimal solution to the problem which was discovered in the
Packit db3073
SHA or whether it's simply a bandaid which fixes the problem with a minimum of
Packit db3073
effort (for example the reengineering of a great many Capstone chips).
Packit db3073
*/
Packit db3073
Packit db3073
static void
Packit db3073
sha1_sum_init (Sha1sum *sha1)
Packit db3073
{
Packit db3073
  /* initialize constants */
Packit db3073
  sha1->buf[0] = 0x67452301L;
Packit db3073
  sha1->buf[1] = 0xEFCDAB89L;
Packit db3073
  sha1->buf[2] = 0x98BADCFEL;
Packit db3073
  sha1->buf[3] = 0x10325476L;
Packit db3073
  sha1->buf[4] = 0xC3D2E1F0L;
Packit db3073
Packit db3073
  /* initialize bits */
Packit db3073
  sha1->bits[0] = sha1->bits[1] = 0;
Packit db3073
}
Packit db3073
Packit db3073
/* The SHA f()-functions. */
Packit db3073
Packit db3073
#define f1(x,y,z)       (z ^ (x & (y ^ z)))             /* Rounds  0-19 */
Packit db3073
#define f2(x,y,z)       (x ^ y ^ z)                     /* Rounds 20-39 */
Packit db3073
#define f3(x,y,z)       (( x & y) | (z & (x | y)))      /* Rounds 40-59 */
Packit db3073
#define f4(x,y,z)       (x ^ y ^ z)                     /* Rounds 60-79 */
Packit db3073
Packit db3073
/* The SHA Mysterious Constants */
Packit db3073
#define K1  0x5A827999L                                 /* Rounds  0-19 */
Packit db3073
#define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
Packit db3073
#define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
Packit db3073
#define K4  0xCA62C1D6L                                 /* Rounds 60-79 */
Packit db3073
Packit db3073
/* 32-bit rotate left - kludged with shifts */
Packit db3073
#define ROTL(n,X) (((X) << n ) | ((X) >> (32 - n)))
Packit db3073
Packit db3073
/* The initial expanding function.  The hash function is defined over an
Packit db3073
   80-word expanded input array W, where the first 16 are copies of the input
Packit db3073
   data, and the remaining 64 are defined by
Packit db3073
Packit db3073
        W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]
Packit db3073
Packit db3073
   This implementation generates these values on the fly in a circular
Packit db3073
   buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
Packit db3073
   optimization.
Packit db3073
Packit db3073
   The updated SHA changes the expanding function by adding a rotate of 1
Packit db3073
   bit.  Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
Packit db3073
   for this information */
Packit db3073
Packit db3073
#define expand(W,i) (W[ i & 15 ] = ROTL (1, (W[ i       & 15] ^ \
Packit db3073
                                             W[(i - 14) & 15] ^ \
Packit db3073
                                             W[(i -  8) & 15] ^ \
Packit db3073
                                             W[(i -  3) & 15])))
Packit db3073
Packit db3073
Packit db3073
/* The prototype SHA sub-round.  The fundamental sub-round is:
Packit db3073
Packit db3073
        a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
Packit db3073
        b' = a;
Packit db3073
        c' = ROTL( 30, b );
Packit db3073
        d' = c;
Packit db3073
        e' = d;
Packit db3073
Packit db3073
   but this is implemented by unrolling the loop 5 times and renaming the
Packit db3073
   variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
Packit db3073
   This code is then replicated 20 times for each of the 4 functions, using
Packit db3073
   the next 20 values from the W[] array each time */
Packit db3073
Packit db3073
#define subRound(a, b, c, d, e, f, k, data) \
Packit db3073
   (e += ROTL (5, a) + f(b, c, d) + k + data, b = ROTL (30, b))
Packit db3073
Packit db3073
static void
Packit db3073
sha1_transform (guint32  buf[5],
Packit db3073
                guint32  in[16])
Packit db3073
{
Packit db3073
  guint32 A, B, C, D, E;
Packit db3073
Packit db3073
  A = buf[0];
Packit db3073
  B = buf[1];
Packit db3073
  C = buf[2];
Packit db3073
  D = buf[3];
Packit db3073
  E = buf[4];
Packit db3073
Packit db3073
  /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
Packit db3073
  subRound (A, B, C, D, E, f1, K1, in[0]);
Packit db3073
  subRound (E, A, B, C, D, f1, K1, in[1]);
Packit db3073
  subRound (D, E, A, B, C, f1, K1, in[2]);
Packit db3073
  subRound (C, D, E, A, B, f1, K1, in[3]);
Packit db3073
  subRound (B, C, D, E, A, f1, K1, in[4]);
Packit db3073
  subRound (A, B, C, D, E, f1, K1, in[5]);
Packit db3073
  subRound (E, A, B, C, D, f1, K1, in[6]);
Packit db3073
  subRound (D, E, A, B, C, f1, K1, in[7]);
Packit db3073
  subRound (C, D, E, A, B, f1, K1, in[8]);
Packit db3073
  subRound (B, C, D, E, A, f1, K1, in[9]);
Packit db3073
  subRound (A, B, C, D, E, f1, K1, in[10]);
Packit db3073
  subRound (E, A, B, C, D, f1, K1, in[11]);
Packit db3073
  subRound (D, E, A, B, C, f1, K1, in[12]);
Packit db3073
  subRound (C, D, E, A, B, f1, K1, in[13]);
Packit db3073
  subRound (B, C, D, E, A, f1, K1, in[14]);
Packit db3073
  subRound (A, B, C, D, E, f1, K1, in[15]);
Packit db3073
  subRound (E, A, B, C, D, f1, K1, expand (in, 16));
Packit db3073
  subRound (D, E, A, B, C, f1, K1, expand (in, 17));
Packit db3073
  subRound (C, D, E, A, B, f1, K1, expand (in, 18));
Packit db3073
  subRound (B, C, D, E, A, f1, K1, expand (in, 19));
Packit db3073
Packit db3073
  subRound (A, B, C, D, E, f2, K2, expand (in, 20));
Packit db3073
  subRound (E, A, B, C, D, f2, K2, expand (in, 21));
Packit db3073
  subRound (D, E, A, B, C, f2, K2, expand (in, 22));
Packit db3073
  subRound (C, D, E, A, B, f2, K2, expand (in, 23));
Packit db3073
  subRound (B, C, D, E, A, f2, K2, expand (in, 24));
Packit db3073
  subRound (A, B, C, D, E, f2, K2, expand (in, 25));
Packit db3073
  subRound (E, A, B, C, D, f2, K2, expand (in, 26));
Packit db3073
  subRound (D, E, A, B, C, f2, K2, expand (in, 27));
Packit db3073
  subRound (C, D, E, A, B, f2, K2, expand (in, 28));
Packit db3073
  subRound (B, C, D, E, A, f2, K2, expand (in, 29));
Packit db3073
  subRound (A, B, C, D, E, f2, K2, expand (in, 30));
Packit db3073
  subRound (E, A, B, C, D, f2, K2, expand (in, 31));
Packit db3073
  subRound (D, E, A, B, C, f2, K2, expand (in, 32));
Packit db3073
  subRound (C, D, E, A, B, f2, K2, expand (in, 33));
Packit db3073
  subRound (B, C, D, E, A, f2, K2, expand (in, 34));
Packit db3073
  subRound (A, B, C, D, E, f2, K2, expand (in, 35));
Packit db3073
  subRound (E, A, B, C, D, f2, K2, expand (in, 36));
Packit db3073
  subRound (D, E, A, B, C, f2, K2, expand (in, 37));
Packit db3073
  subRound (C, D, E, A, B, f2, K2, expand (in, 38));
Packit db3073
  subRound (B, C, D, E, A, f2, K2, expand (in, 39));
Packit db3073
Packit db3073
  subRound (A, B, C, D, E, f3, K3, expand (in, 40));
Packit db3073
  subRound (E, A, B, C, D, f3, K3, expand (in, 41));
Packit db3073
  subRound (D, E, A, B, C, f3, K3, expand (in, 42));
Packit db3073
  subRound (C, D, E, A, B, f3, K3, expand (in, 43));
Packit db3073
  subRound (B, C, D, E, A, f3, K3, expand (in, 44));
Packit db3073
  subRound (A, B, C, D, E, f3, K3, expand (in, 45));
Packit db3073
  subRound (E, A, B, C, D, f3, K3, expand (in, 46));
Packit db3073
  subRound (D, E, A, B, C, f3, K3, expand (in, 47));
Packit db3073
  subRound (C, D, E, A, B, f3, K3, expand (in, 48));
Packit db3073
  subRound (B, C, D, E, A, f3, K3, expand (in, 49));
Packit db3073
  subRound (A, B, C, D, E, f3, K3, expand (in, 50));
Packit db3073
  subRound (E, A, B, C, D, f3, K3, expand (in, 51));
Packit db3073
  subRound (D, E, A, B, C, f3, K3, expand (in, 52));
Packit db3073
  subRound (C, D, E, A, B, f3, K3, expand (in, 53));
Packit db3073
  subRound (B, C, D, E, A, f3, K3, expand (in, 54));
Packit db3073
  subRound (A, B, C, D, E, f3, K3, expand (in, 55));
Packit db3073
  subRound (E, A, B, C, D, f3, K3, expand (in, 56));
Packit db3073
  subRound (D, E, A, B, C, f3, K3, expand (in, 57));
Packit db3073
  subRound (C, D, E, A, B, f3, K3, expand (in, 58));
Packit db3073
  subRound (B, C, D, E, A, f3, K3, expand (in, 59));
Packit db3073
Packit db3073
  subRound (A, B, C, D, E, f4, K4, expand (in, 60));
Packit db3073
  subRound (E, A, B, C, D, f4, K4, expand (in, 61));
Packit db3073
  subRound (D, E, A, B, C, f4, K4, expand (in, 62));
Packit db3073
  subRound (C, D, E, A, B, f4, K4, expand (in, 63));
Packit db3073
  subRound (B, C, D, E, A, f4, K4, expand (in, 64));
Packit db3073
  subRound (A, B, C, D, E, f4, K4, expand (in, 65));
Packit db3073
  subRound (E, A, B, C, D, f4, K4, expand (in, 66));
Packit db3073
  subRound (D, E, A, B, C, f4, K4, expand (in, 67));
Packit db3073
  subRound (C, D, E, A, B, f4, K4, expand (in, 68));
Packit db3073
  subRound (B, C, D, E, A, f4, K4, expand (in, 69));
Packit db3073
  subRound (A, B, C, D, E, f4, K4, expand (in, 70));
Packit db3073
  subRound (E, A, B, C, D, f4, K4, expand (in, 71));
Packit db3073
  subRound (D, E, A, B, C, f4, K4, expand (in, 72));
Packit db3073
  subRound (C, D, E, A, B, f4, K4, expand (in, 73));
Packit db3073
  subRound (B, C, D, E, A, f4, K4, expand (in, 74));
Packit db3073
  subRound (A, B, C, D, E, f4, K4, expand (in, 75));
Packit db3073
  subRound (E, A, B, C, D, f4, K4, expand (in, 76));
Packit db3073
  subRound (D, E, A, B, C, f4, K4, expand (in, 77));
Packit db3073
  subRound (C, D, E, A, B, f4, K4, expand (in, 78));
Packit db3073
  subRound (B, C, D, E, A, f4, K4, expand (in, 79));
Packit db3073
Packit db3073
  /* Build message digest */
Packit db3073
  buf[0] += A;
Packit db3073
  buf[1] += B;
Packit db3073
  buf[2] += C;
Packit db3073
  buf[3] += D;
Packit db3073
  buf[4] += E;
Packit db3073
}
Packit db3073
Packit db3073
#undef K1
Packit db3073
#undef K2
Packit db3073
#undef K3
Packit db3073
#undef K4
Packit db3073
#undef f1
Packit db3073
#undef f2
Packit db3073
#undef f3
Packit db3073
#undef f4
Packit db3073
#undef ROTL
Packit db3073
#undef expand
Packit db3073
#undef subRound
Packit db3073
Packit db3073
static void
Packit db3073
sha1_sum_update (Sha1sum      *sha1,
Packit db3073
                 const guchar *buffer,
Packit db3073
                 gsize         count)
Packit db3073
{
Packit db3073
  guint32 tmp;
Packit db3073
  guint dataCount;
Packit db3073
Packit db3073
  /* Update bitcount */
Packit db3073
  tmp = sha1->bits[0];
Packit db3073
  if ((sha1->bits[0] = tmp + ((guint32) count << 3) ) < tmp)
Packit db3073
    sha1->bits[1] += 1;             /* Carry from low to high */
Packit db3073
  sha1->bits[1] += count >> 29;
Packit db3073
Packit db3073
  /* Get count of bytes already in data */
Packit db3073
  dataCount = (guint) (tmp >> 3) & 0x3F;
Packit db3073
Packit db3073
  /* Handle any leading odd-sized chunks */
Packit db3073
  if (dataCount)
Packit db3073
    {
Packit db3073
      guchar *p = (guchar *) sha1->data + dataCount;
Packit db3073
Packit db3073
      dataCount = SHA1_DATASIZE - dataCount;
Packit db3073
      if (count < dataCount)
Packit db3073
        {
Packit db3073
          memcpy (p, buffer, count);
Packit db3073
          return;
Packit db3073
        }
Packit db3073
Packit db3073
      memcpy (p, buffer, dataCount);
Packit db3073
Packit db3073
      sha_byte_reverse (sha1->data, SHA1_DATASIZE);
Packit db3073
      sha1_transform (sha1->buf, sha1->data);
Packit db3073
Packit db3073
      buffer += dataCount;
Packit db3073
      count -= dataCount;
Packit db3073
    }
Packit db3073
Packit db3073
  /* Process data in SHA1_DATASIZE chunks */
Packit db3073
  while (count >= SHA1_DATASIZE)
Packit db3073
    {
Packit db3073
      memcpy (sha1->data, buffer, SHA1_DATASIZE);
Packit db3073
Packit db3073
      sha_byte_reverse (sha1->data, SHA1_DATASIZE);
Packit db3073
      sha1_transform (sha1->buf, sha1->data);
Packit db3073
Packit db3073
      buffer += SHA1_DATASIZE;
Packit db3073
      count -= SHA1_DATASIZE;
Packit db3073
    }
Packit db3073
Packit db3073
  /* Handle any remaining bytes of data. */
Packit db3073
  memcpy (sha1->data, buffer, count);
Packit db3073
}
Packit db3073
Packit db3073
/* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern
Packit db3073
   1 0* (64-bit count of bits processed, MSB-first) */
Packit db3073
static void
Packit db3073
sha1_sum_close (Sha1sum *sha1)
Packit db3073
{
Packit db3073
  gint count;
Packit db3073
  guchar *data_p;
Packit db3073
Packit db3073
  /* Compute number of bytes mod 64 */
Packit db3073
  count = (gint) ((sha1->bits[0] >> 3) & 0x3f);
Packit db3073
Packit db3073
  /* Set the first char of padding to 0x80.  This is safe since there is
Packit db3073
     always at least one byte free */
Packit db3073
  data_p = (guchar *) sha1->data + count;
Packit db3073
  *data_p++ = 0x80;
Packit db3073
Packit db3073
  /* Bytes of padding needed to make 64 bytes */
Packit db3073
  count = SHA1_DATASIZE - 1 - count;
Packit db3073
Packit db3073
  /* Pad out to 56 mod 64 */
Packit db3073
  if (count < 8)
Packit db3073
    {
Packit db3073
      /* Two lots of padding:  Pad the first block to 64 bytes */
Packit db3073
      memset (data_p, 0, count);
Packit db3073
Packit db3073
      sha_byte_reverse (sha1->data, SHA1_DATASIZE);
Packit db3073
      sha1_transform (sha1->buf, sha1->data);
Packit db3073
Packit db3073
      /* Now fill the next block with 56 bytes */
Packit db3073
      memset (sha1->data, 0, SHA1_DATASIZE - 8);
Packit db3073
    }
Packit db3073
  else
Packit db3073
    {
Packit db3073
      /* Pad block to 56 bytes */
Packit db3073
      memset (data_p, 0, count - 8);
Packit db3073
    }
Packit db3073
Packit db3073
  /* Append length in bits and transform */
Packit db3073
  sha1->data[14] = sha1->bits[1];
Packit db3073
  sha1->data[15] = sha1->bits[0];
Packit db3073
Packit db3073
  sha_byte_reverse (sha1->data, SHA1_DATASIZE - 8);
Packit db3073
  sha1_transform (sha1->buf, sha1->data);
Packit db3073
  sha_byte_reverse (sha1->buf, SHA1_DIGEST_LEN);
Packit db3073
Packit db3073
  memcpy (sha1->digest, sha1->buf, SHA1_DIGEST_LEN);
Packit db3073
Packit db3073
  /* Reset buffers in case they contain sensitive data */
Packit db3073
  memset (sha1->buf, 0, sizeof (sha1->buf));
Packit db3073
  memset (sha1->data, 0, sizeof (sha1->data));
Packit db3073
}
Packit db3073
Packit db3073
static gchar *
Packit db3073
sha1_sum_to_string (Sha1sum *sha1)
Packit db3073
{
Packit db3073
  return digest_to_string (sha1->digest, SHA1_DIGEST_LEN);
Packit db3073
}
Packit db3073
Packit db3073
static void
Packit db3073
sha1_sum_digest (Sha1sum *sha1,
Packit db3073
                 guint8  *digest)
Packit db3073
{
Packit db3073
  gint i;
Packit db3073
Packit db3073
  for (i = 0; i < SHA1_DIGEST_LEN; i++)
Packit db3073
    digest[i] = sha1->digest[i];
Packit db3073
}
Packit db3073
Packit db3073
/*
Packit db3073
 * SHA-256 Checksum
Packit db3073
 */
Packit db3073
Packit db3073
/* adapted from the SHA256 implementation in gsk/src/hash/gskhash.c.
Packit db3073
 *
Packit db3073
 * Copyright (C) 2006 Dave Benson
Packit db3073
 * Released under the terms of the GNU Lesser General Public License
Packit db3073
 */
Packit db3073
Packit db3073
static void
Packit db3073
sha256_sum_init (Sha256sum *sha256)
Packit db3073
{
Packit db3073
  sha256->buf[0] = 0x6a09e667;
Packit db3073
  sha256->buf[1] = 0xbb67ae85;
Packit db3073
  sha256->buf[2] = 0x3c6ef372;
Packit db3073
  sha256->buf[3] = 0xa54ff53a;
Packit db3073
  sha256->buf[4] = 0x510e527f;
Packit db3073
  sha256->buf[5] = 0x9b05688c;
Packit db3073
  sha256->buf[6] = 0x1f83d9ab;
Packit db3073
  sha256->buf[7] = 0x5be0cd19;
Packit db3073
Packit db3073
  sha256->bits[0] = sha256->bits[1] = 0;
Packit db3073
}
Packit db3073
Packit db3073
#define GET_UINT32(n,b,i)               G_STMT_START{   \
Packit db3073
    (n) = ((guint32) (b)[(i)    ] << 24)                \
Packit db3073
        | ((guint32) (b)[(i) + 1] << 16)                \
Packit db3073
        | ((guint32) (b)[(i) + 2] <<  8)                \
Packit db3073
        | ((guint32) (b)[(i) + 3]      ); } G_STMT_END
Packit db3073
Packit db3073
#define PUT_UINT32(n,b,i)               G_STMT_START{   \
Packit db3073
    (b)[(i)    ] = (guint8) ((n) >> 24);                \
Packit db3073
    (b)[(i) + 1] = (guint8) ((n) >> 16);                \
Packit db3073
    (b)[(i) + 2] = (guint8) ((n) >>  8);                \
Packit db3073
    (b)[(i) + 3] = (guint8) ((n)      ); } G_STMT_END
Packit db3073
Packit db3073
static void
Packit db3073
sha256_transform (guint32      buf[8],
Packit db3073
                  guint8 const data[64])
Packit db3073
{
Packit db3073
  guint32 temp1, temp2, W[64];
Packit db3073
  guint32 A, B, C, D, E, F, G, H;
Packit db3073
Packit db3073
  GET_UINT32 (W[0],  data,  0);
Packit db3073
  GET_UINT32 (W[1],  data,  4);
Packit db3073
  GET_UINT32 (W[2],  data,  8);
Packit db3073
  GET_UINT32 (W[3],  data, 12);
Packit db3073
  GET_UINT32 (W[4],  data, 16);
Packit db3073
  GET_UINT32 (W[5],  data, 20);
Packit db3073
  GET_UINT32 (W[6],  data, 24);
Packit db3073
  GET_UINT32 (W[7],  data, 28);
Packit db3073
  GET_UINT32 (W[8],  data, 32);
Packit db3073
  GET_UINT32 (W[9],  data, 36);
Packit db3073
  GET_UINT32 (W[10], data, 40);
Packit db3073
  GET_UINT32 (W[11], data, 44);
Packit db3073
  GET_UINT32 (W[12], data, 48);
Packit db3073
  GET_UINT32 (W[13], data, 52);
Packit db3073
  GET_UINT32 (W[14], data, 56);
Packit db3073
  GET_UINT32 (W[15], data, 60);
Packit db3073
Packit db3073
#define SHR(x,n)        ((x & 0xFFFFFFFF) >> n)
Packit db3073
#define ROTR(x,n)       (SHR (x,n) | (x << (32 - n)))
Packit db3073
Packit db3073
#define S0(x) (ROTR (x, 7) ^ ROTR (x,18) ^  SHR (x, 3))
Packit db3073
#define S1(x) (ROTR (x,17) ^ ROTR (x,19) ^  SHR (x,10))
Packit db3073
#define S2(x) (ROTR (x, 2) ^ ROTR (x,13) ^ ROTR (x,22))
Packit db3073
#define S3(x) (ROTR (x, 6) ^ ROTR (x,11) ^ ROTR (x,25))
Packit db3073
Packit db3073
#define F0(x,y,z) ((x & y) | (z & (x | y)))
Packit db3073
#define F1(x,y,z) (z ^ (x & (y ^ z)))
Packit db3073
Packit db3073
#define R(t)    (W[t] = S1(W[t -  2]) + W[t -  7] + \
Packit db3073
                        S0(W[t - 15]) + W[t - 16])
Packit db3073
Packit db3073
#define P(a,b,c,d,e,f,g,h,x,K)          G_STMT_START {  \
Packit db3073
        temp1 = h + S3(e) + F1(e,f,g) + K + x;          \
Packit db3073
        temp2 = S2(a) + F0(a,b,c);                      \
Packit db3073
        d += temp1; h = temp1 + temp2; } G_STMT_END
Packit db3073
Packit db3073
  A = buf[0];
Packit db3073
  B = buf[1];
Packit db3073
  C = buf[2];
Packit db3073
  D = buf[3];
Packit db3073
  E = buf[4];
Packit db3073
  F = buf[5];
Packit db3073
  G = buf[6];
Packit db3073
  H = buf[7];
Packit db3073
Packit db3073
  P (A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
Packit db3073
  P (H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
Packit db3073
  P (G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
Packit db3073
  P (F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
Packit db3073
  P (E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
Packit db3073
  P (D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
Packit db3073
  P (C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
Packit db3073
  P (B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
Packit db3073
  P (A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
Packit db3073
  P (H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
Packit db3073
  P (G, H, A, B, C, D, E, F, W[10], 0x243185BE);
Packit db3073
  P (F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
Packit db3073
  P (E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
Packit db3073
  P (D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
Packit db3073
  P (C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
Packit db3073
  P (B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(24), 0x983E5152);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(31), 0x14292967);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(35), 0x53380D13);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(36), 0x650A7354);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(39), 0x92722C85);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(44), 0xD192E819);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(45), 0xD6990624);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(47), 0x106AA070);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(50), 0x2748774C);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
Packit db3073
  P (A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
Packit db3073
  P (H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
Packit db3073
  P (G, H, A, B, C, D, E, F, R(58), 0x84C87814);
Packit db3073
  P (F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
Packit db3073
  P (E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
Packit db3073
  P (D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
Packit db3073
  P (C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
Packit db3073
  P (B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
Packit db3073
Packit db3073
#undef SHR
Packit db3073
#undef ROTR
Packit db3073
#undef S0
Packit db3073
#undef S1
Packit db3073
#undef S2
Packit db3073
#undef S3
Packit db3073
#undef F0
Packit db3073
#undef F1
Packit db3073
#undef R
Packit db3073
#undef P
Packit db3073
Packit db3073
  buf[0] += A;
Packit db3073
  buf[1] += B;
Packit db3073
  buf[2] += C;
Packit db3073
  buf[3] += D;
Packit db3073
  buf[4] += E;
Packit db3073
  buf[5] += F;
Packit db3073
  buf[6] += G;
Packit db3073
  buf[7] += H;
Packit db3073
}
Packit db3073
Packit db3073
static void
Packit db3073
sha256_sum_update (Sha256sum    *sha256,
Packit db3073
                   const guchar *buffer,
Packit db3073
                   gsize         length)
Packit db3073
{
Packit db3073
  guint32 left, fill;
Packit db3073
  const guint8 *input = buffer;
Packit db3073
Packit db3073
  if (length == 0)
Packit db3073
    return;
Packit db3073
Packit db3073
  left = sha256->bits[0] & 0x3F;
Packit db3073
  fill = 64 - left;
Packit db3073
Packit db3073
  sha256->bits[0] += length;
Packit db3073
  sha256->bits[0] &= 0xFFFFFFFF;
Packit db3073
Packit db3073
  if (sha256->bits[0] < length)
Packit db3073
      sha256->bits[1]++;
Packit db3073
Packit db3073
  if (left > 0 && length >= fill)
Packit db3073
    {
Packit db3073
      memcpy ((sha256->data + left), input, fill);
Packit db3073
Packit db3073
      sha256_transform (sha256->buf, sha256->data);
Packit db3073
      length -= fill;
Packit db3073
      input += fill;
Packit db3073
Packit db3073
      left = 0;
Packit db3073
    }
Packit db3073
Packit db3073
  while (length >= SHA256_DATASIZE)
Packit db3073
    {
Packit db3073
      sha256_transform (sha256->buf, input);
Packit db3073
Packit db3073
      length -= 64;
Packit db3073
      input += 64;
Packit db3073
    }
Packit db3073
Packit db3073
  if (length)
Packit db3073
    memcpy (sha256->data + left, input, length);
Packit db3073
}
Packit db3073
Packit db3073
static guint8 sha256_padding[64] =
Packit db3073
{
Packit db3073
 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db3073
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db3073
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db3073
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db3073
};
Packit db3073
Packit db3073
static void
Packit db3073
sha256_sum_close (Sha256sum *sha256)
Packit db3073
{
Packit db3073
  guint32 last, padn;
Packit db3073
  guint32 high, low;
Packit db3073
  guint8 msglen[8];
Packit db3073
Packit db3073
  high = (sha256->bits[0] >> 29)
Packit db3073
       | (sha256->bits[1] <<  3);
Packit db3073
  low  = (sha256->bits[0] <<  3);
Packit db3073
Packit db3073
  PUT_UINT32 (high, msglen, 0);
Packit db3073
  PUT_UINT32 (low, msglen, 4);
Packit db3073
Packit db3073
  last = sha256->bits[0] & 0x3F;
Packit db3073
  padn = (last < 56) ? (56 - last) : (120 - last);
Packit db3073
Packit db3073
  sha256_sum_update (sha256, sha256_padding, padn);
Packit db3073
  sha256_sum_update (sha256, msglen, 8);
Packit db3073
Packit db3073
  PUT_UINT32 (sha256->buf[0], sha256->digest,  0);
Packit db3073
  PUT_UINT32 (sha256->buf[1], sha256->digest,  4);
Packit db3073
  PUT_UINT32 (sha256->buf[2], sha256->digest,  8);
Packit db3073
  PUT_UINT32 (sha256->buf[3], sha256->digest, 12);
Packit db3073
  PUT_UINT32 (sha256->buf[4], sha256->digest, 16);
Packit db3073
  PUT_UINT32 (sha256->buf[5], sha256->digest, 20);
Packit db3073
  PUT_UINT32 (sha256->buf[6], sha256->digest, 24);
Packit db3073
  PUT_UINT32 (sha256->buf[7], sha256->digest, 28);
Packit db3073
}
Packit db3073
Packit db3073
#undef PUT_UINT32
Packit db3073
#undef GET_UINT32
Packit db3073
Packit db3073
static gchar *
Packit db3073
sha256_sum_to_string (Sha256sum *sha256)
Packit db3073
{
Packit db3073
  return digest_to_string (sha256->digest, SHA256_DIGEST_LEN);
Packit db3073
}
Packit db3073
Packit db3073
static void
Packit db3073
sha256_sum_digest (Sha256sum *sha256,
Packit db3073
                   guint8    *digest)
Packit db3073
{
Packit db3073
  gint i;
Packit db3073
Packit db3073
  for (i = 0; i < SHA256_DIGEST_LEN; i++)
Packit db3073
    digest[i] = sha256->digest[i];
Packit db3073
}
Packit db3073
Packit db3073
Packit db3073
/*
Packit db3073
 * Public API
Packit db3073
 */
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_type_get_length:
Packit db3073
 * @checksum_type: a #GChecksumType
Packit db3073
 *
Packit db3073
 * Gets the length in bytes of digests of type @checksum_type
Packit db3073
 *
Packit db3073
 * Return value: the checksum length, or -1 if @checksum_type is
Packit db3073
 * not supported.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
gssize
Packit db3073
g_checksum_type_get_length (GChecksumType checksum_type)
Packit db3073
{
Packit db3073
  gssize len = -1;
Packit db3073
Packit db3073
  switch (checksum_type)
Packit db3073
    {
Packit db3073
    case G_CHECKSUM_MD5:
Packit db3073
      len = MD5_DIGEST_LEN;
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA1:
Packit db3073
      len = SHA1_DIGEST_LEN;
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA256:
Packit db3073
      len = SHA256_DIGEST_LEN;
Packit db3073
      break;
Packit db3073
    default:
Packit db3073
      len = -1;
Packit db3073
      break;
Packit db3073
    }
Packit db3073
Packit db3073
  return len;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_new:
Packit db3073
 * @checksum_type: the desired type of checksum
Packit db3073
 *
Packit db3073
 * Creates a new #GChecksum, using the checksum algorithm @checksum_type.
Packit db3073
 * If the @checksum_type is not known, %NULL is returned.
Packit db3073
 * A #GChecksum can be used to compute the checksum, or digest, of an
Packit db3073
 * arbitrary binary blob, using different hashing algorithms.
Packit db3073
 *
Packit db3073
 * A #GChecksum works by feeding a binary blob through g_checksum_update()
Packit db3073
 * until there is data to be checked; the digest can then be extracted
Packit db3073
 * using g_checksum_get_string(), which will return the checksum as a
Packit db3073
 * hexadecimal string; or g_checksum_get_digest(), which will return a
Packit db3073
 * vector of raw bytes. Once either g_checksum_get_string() or
Packit db3073
 * g_checksum_get_digest() have been called on a #GChecksum, the checksum
Packit db3073
 * will be closed and it won't be possible to call g_checksum_update()
Packit db3073
 * on it anymore.
Packit db3073
 *
Packit db3073
 * Return value: the newly created #GChecksum, or %NULL.
Packit db3073
 *   Use g_checksum_free() to free the memory allocated by it.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
GChecksum *
Packit db3073
g_checksum_new (GChecksumType checksum_type)
Packit db3073
{
Packit db3073
  GChecksum *checksum;
Packit db3073
Packit db3073
  if (! IS_VALID_TYPE (checksum_type))
Packit db3073
    return NULL;
Packit db3073
Packit db3073
  checksum = g_slice_new0 (GChecksum);
Packit db3073
  checksum->type = checksum_type;
Packit db3073
Packit db3073
  g_checksum_reset (checksum);
Packit db3073
Packit db3073
  return checksum;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_reset:
Packit db3073
 * @checksum: the #GChecksum to reset
Packit db3073
 *
Packit db3073
 * Resets the state of the @checksum back to its initial state.
Packit db3073
 *
Packit db3073
 * Since: 2.18
Packit db3073
 **/
Packit db3073
void
Packit db3073
g_checksum_reset (GChecksum *checksum)
Packit db3073
{
Packit db3073
  g_return_if_fail (checksum != NULL);
Packit db3073
Packit db3073
  g_free (checksum->digest_str);
Packit db3073
  checksum->digest_str = NULL;
Packit db3073
Packit db3073
  switch (checksum->type)
Packit db3073
    {
Packit db3073
    case G_CHECKSUM_MD5:
Packit db3073
      md5_sum_init (&(checksum->sum.md5));
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA1:
Packit db3073
      sha1_sum_init (&(checksum->sum.sha1));
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA256:
Packit db3073
      sha256_sum_init (&(checksum->sum.sha256));
Packit db3073
      break;
Packit db3073
    default:
Packit db3073
      g_assert_not_reached ();
Packit db3073
      break;
Packit db3073
    }
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_copy:
Packit db3073
 * @checksum: the #GChecksum to copy
Packit db3073
 *
Packit db3073
 * Copies a #GChecksum. If @checksum has been closed, by calling
Packit db3073
 * g_checksum_get_string() or g_checksum_get_digest(), the copied
Packit db3073
 * checksum will be closed as well.
Packit db3073
 *
Packit db3073
 * Return value: the copy of the passed #GChecksum. Use g_checksum_free()
Packit db3073
 *   when finished using it.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
GChecksum *
Packit db3073
g_checksum_copy (const GChecksum *checksum)
Packit db3073
{
Packit db3073
  GChecksum *copy;
Packit db3073
Packit db3073
  g_return_val_if_fail (checksum != NULL, NULL);
Packit db3073
Packit db3073
  copy = g_slice_new (GChecksum);
Packit db3073
  *copy = *checksum;
Packit db3073
Packit db3073
  copy->digest_str = g_strdup (checksum->digest_str);
Packit db3073
Packit db3073
  return copy;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_free:
Packit db3073
 * @checksum: a #GChecksum
Packit db3073
 *
Packit db3073
 * Frees the memory allocated for @checksum.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
void
Packit db3073
g_checksum_free (GChecksum *checksum)
Packit db3073
{
Packit db3073
  if (G_LIKELY (checksum))
Packit db3073
    {
Packit db3073
      g_free (checksum->digest_str);
Packit db3073
Packit db3073
      g_slice_free (GChecksum, checksum);
Packit db3073
    }
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_update:
Packit db3073
 * @checksum: a #GChecksum
Packit db3073
 * @data: buffer used to compute the checksum
Packit db3073
 * @length: size of the buffer, or -1 if it is a null-terminated string.
Packit db3073
 *
Packit db3073
 * Feeds @data into an existing #GChecksum. The checksum must still be
Packit db3073
 * open, that is g_checksum_get_string() or g_checksum_get_digest() must
Packit db3073
 * not have been called on @checksum.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
void
Packit db3073
g_checksum_update (GChecksum    *checksum,
Packit db3073
                   const guchar *data,
Packit db3073
                   gssize        length)
Packit db3073
{
Packit db3073
  g_return_if_fail (checksum != NULL);
Packit db3073
  g_return_if_fail (length == 0 || data != NULL);
Packit db3073
Packit db3073
  if (length < 0)
Packit db3073
    length = strlen ((const gchar *) data);
Packit db3073
Packit db3073
  if (checksum->digest_str)
Packit db3073
    {
Packit db3073
      g_warning ("The checksum `%s' has been closed and cannot be updated "
Packit db3073
                 "anymore.",
Packit db3073
                 checksum->digest_str);
Packit db3073
      return;
Packit db3073
    }
Packit db3073
Packit db3073
  switch (checksum->type)
Packit db3073
    {
Packit db3073
    case G_CHECKSUM_MD5:
Packit db3073
      md5_sum_update (&(checksum->sum.md5), data, length);
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA1:
Packit db3073
      sha1_sum_update (&(checksum->sum.sha1), data, length);
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA256:
Packit db3073
      sha256_sum_update (&(checksum->sum.sha256), data, length);
Packit db3073
      break;
Packit db3073
    default:
Packit db3073
      g_assert_not_reached ();
Packit db3073
      break;
Packit db3073
    }
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_get_string:
Packit db3073
 * @checksum: a #GChecksum
Packit db3073
 *
Packit db3073
 * Gets the digest as an hexadecimal string.
Packit db3073
 *
Packit db3073
 * Once this function has been called the #GChecksum can no longer be
Packit db3073
 * updated with g_checksum_update().
Packit db3073
 *
Packit db3073
 * The hexadecimal characters will be lower case.
Packit db3073
 *
Packit db3073
 * Return value: the hexadecimal representation of the checksum. The
Packit db3073
 *   returned string is owned by the checksum and should not be modified
Packit db3073
 *   or freed.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
const gchar *
Packit db3073
g_checksum_get_string (GChecksum *checksum)
Packit db3073
{
Packit db3073
  gchar *str = NULL;
Packit db3073
Packit db3073
  g_return_val_if_fail (checksum != NULL, NULL);
Packit db3073
Packit db3073
  if (checksum->digest_str)
Packit db3073
    return checksum->digest_str;
Packit db3073
Packit db3073
  switch (checksum->type)
Packit db3073
    {
Packit db3073
    case G_CHECKSUM_MD5:
Packit db3073
      md5_sum_close (&(checksum->sum.md5));
Packit db3073
      str = md5_sum_to_string (&(checksum->sum.md5));
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA1:
Packit db3073
      sha1_sum_close (&(checksum->sum.sha1));
Packit db3073
      str = sha1_sum_to_string (&(checksum->sum.sha1));
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA256:
Packit db3073
      sha256_sum_close (&(checksum->sum.sha256));
Packit db3073
      str = sha256_sum_to_string (&(checksum->sum.sha256));
Packit db3073
      break;
Packit db3073
    default:
Packit db3073
      g_assert_not_reached ();
Packit db3073
      break;
Packit db3073
    }
Packit db3073
Packit db3073
  checksum->digest_str = str;
Packit db3073
Packit db3073
  return checksum->digest_str;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_checksum_get_digest:
Packit db3073
 * @checksum: a #GChecksum
Packit db3073
 * @buffer: output buffer
Packit db3073
 * @digest_len: an inout parameter. The caller initializes it to the size of @buffer.
Packit db3073
 *   After the call it contains the length of the digest.
Packit db3073
 *
Packit db3073
 * Gets the digest from @checksum as a raw binary vector and places it
Packit db3073
 * into @buffer. The size of the digest depends on the type of checksum.
Packit db3073
 *
Packit db3073
 * Once this function has been called, the #GChecksum is closed and can
Packit db3073
 * no longer be updated with g_checksum_update().
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
void
Packit db3073
g_checksum_get_digest (GChecksum  *checksum,
Packit db3073
                       guint8     *buffer,
Packit db3073
                       gsize      *digest_len)
Packit db3073
{
Packit db3073
  gboolean checksum_open = FALSE;
Packit db3073
  gchar *str = NULL;
Packit db3073
  gsize len;
Packit db3073
Packit db3073
  g_return_if_fail (checksum != NULL);
Packit db3073
Packit db3073
  len = g_checksum_type_get_length (checksum->type);
Packit db3073
  g_return_if_fail (*digest_len >= len);
Packit db3073
Packit db3073
  checksum_open = !!(checksum->digest_str == NULL);
Packit db3073
Packit db3073
  switch (checksum->type)
Packit db3073
    {
Packit db3073
    case G_CHECKSUM_MD5:
Packit db3073
      if (checksum_open)
Packit db3073
        {
Packit db3073
          md5_sum_close (&(checksum->sum.md5));
Packit db3073
          str = md5_sum_to_string (&(checksum->sum.md5));
Packit db3073
        }
Packit db3073
      md5_sum_digest (&(checksum->sum.md5), buffer);
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA1:
Packit db3073
      if (checksum_open)
Packit db3073
        {
Packit db3073
          sha1_sum_close (&(checksum->sum.sha1));
Packit db3073
          str = sha1_sum_to_string (&(checksum->sum.sha1));
Packit db3073
        }
Packit db3073
      sha1_sum_digest (&(checksum->sum.sha1), buffer);
Packit db3073
      break;
Packit db3073
    case G_CHECKSUM_SHA256:
Packit db3073
      if (checksum_open)
Packit db3073
        {
Packit db3073
          sha256_sum_close (&(checksum->sum.sha256));
Packit db3073
          str = sha256_sum_to_string (&(checksum->sum.sha256));
Packit db3073
        }
Packit db3073
      sha256_sum_digest (&(checksum->sum.sha256), buffer);
Packit db3073
      break;
Packit db3073
    default:
Packit db3073
      g_assert_not_reached ();
Packit db3073
      break;
Packit db3073
    }
Packit db3073
Packit db3073
  if (str)
Packit db3073
    checksum->digest_str = str;
Packit db3073
Packit db3073
  *digest_len = len;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_compute_checksum_for_data:
Packit db3073
 * @checksum_type: a #GChecksumType
Packit db3073
 * @data: binary blob to compute the digest of
Packit db3073
 * @length: length of @data
Packit db3073
 *
Packit db3073
 * Computes the checksum for a binary @data of @length. This is a
Packit db3073
 * convenience wrapper for g_checksum_new(), g_checksum_get_string()
Packit db3073
 * and g_checksum_free().
Packit db3073
 *
Packit db3073
 * The hexadecimal string returned will be in lower case.
Packit db3073
 *
Packit db3073
 * Return value: the digest of the binary data as a string in hexadecimal.
Packit db3073
 *   The returned string should be freed with g_free() when done using it.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
gchar *
Packit db3073
g_compute_checksum_for_data (GChecksumType  checksum_type,
Packit db3073
                             const guchar  *data,
Packit db3073
                             gsize          length)
Packit db3073
{
Packit db3073
  GChecksum *checksum;
Packit db3073
  gchar *retval;
Packit db3073
Packit db3073
  g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL);
Packit db3073
  g_return_val_if_fail (length == 0 || data != NULL, NULL);
Packit db3073
Packit db3073
  checksum = g_checksum_new (checksum_type);
Packit db3073
  if (!checksum)
Packit db3073
    return NULL;
Packit db3073
Packit db3073
  g_checksum_update (checksum, data, length);
Packit db3073
  retval = g_strdup (g_checksum_get_string (checksum));
Packit db3073
  g_checksum_free (checksum);
Packit db3073
Packit db3073
  return retval;
Packit db3073
}
Packit db3073
Packit db3073
/**
Packit db3073
 * g_compute_checksum_for_string:
Packit db3073
 * @checksum_type: a #GChecksumType
Packit db3073
 * @str: the string to compute the checksum of
Packit db3073
 * @length: the length of the string, or -1 if the string is null-terminated.
Packit db3073
 *
Packit db3073
 * Computes the checksum of a string.
Packit db3073
 *
Packit db3073
 * The hexadecimal string returned will be in lower case.
Packit db3073
 *
Packit db3073
 * Return value: the checksum as a hexadecimal string. The returned string
Packit db3073
 *   should be freed with g_free() when done using it.
Packit db3073
 *
Packit db3073
 * Since: 2.16
Packit db3073
 */
Packit db3073
gchar *
Packit db3073
g_compute_checksum_for_string (GChecksumType  checksum_type,
Packit db3073
                               const gchar   *str,
Packit db3073
                               gssize         length)
Packit db3073
{
Packit db3073
  g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL);
Packit db3073
  g_return_val_if_fail (length == 0 || str != NULL, NULL);
Packit db3073
Packit db3073
  if (length < 0)
Packit db3073
    length = strlen (str);
Packit db3073
Packit db3073
  return g_compute_checksum_for_data (checksum_type, (const guchar *) str, length);
Packit db3073
}