Blame glib/gchecksum.c

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