/* * fontconfig/src/fchash.c * * Copyright © 2003 Keith Packard * Copyright © 2013 Red Hat, Inc. * Red Hat Author(s): Akira TAGOH * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. The authors make no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "fcint.h" #include #include #define ROTRN(w, v, n) ((((FcChar32)v) >> n) | (((FcChar32)v) << (w - n))) #define ROTR32(v, n) ROTRN(32, v, n) #define SHR(v, n) (v >> n) #define Ch(x, y, z) ((x & y) ^ (~x & z)) #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) #define SS0(x) (ROTR32(x, 2) ^ ROTR32(x, 13) ^ ROTR32(x, 22)) #define SS1(x) (ROTR32(x, 6) ^ ROTR32(x, 11) ^ ROTR32(x, 25)) #define ss0(x) (ROTR32(x, 7) ^ ROTR32(x, 18) ^ SHR(x, 3)) #define ss1(x) (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10)) static FcChar32 * FcHashInitSHA256Digest (void) { int i; static const FcChar32 h[] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; FcChar32 *ret = malloc (sizeof (FcChar32) * 8); if (!ret) return NULL; for (i = 0; i < 8; i++) ret[i] = h[i]; return ret; } static void FcHashComputeSHA256Digest (FcChar32 *hash, const char *block) { static const FcChar32 k[] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; FcChar32 w[64], i, j, t1, t2; FcChar32 a, b, c, d, e, f, g, h; #define H(n) (hash[n]) a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); f = H(5); g = H(6); h = H(7); for (i = 0; i < 16; i++) { j = (block[(i * 4) + 0] & 0xff) << (8 * 3); j |= (block[(i * 4) + 1] & 0xff) << (8 * 2); j |= (block[(i * 4) + 2] & 0xff) << (8 * 1); j |= (block[(i * 4) + 3] & 0xff); w[i] = j; } for (i = 16; i < 64; i++) w[i] = ss1(w[i - 2]) + w[i - 7] + ss0(w[i - 15]) + w[i - 16]; for (i = 0; i < 64; i++) { t1 = h + SS1(e) + Ch(e, f, g) + k[i] + w[i]; t2 = SS0(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } H(0) += a; H(1) += b; H(2) += c; H(3) += d; H(4) += e; H(5) += f; H(6) += g; H(7) += h; #undef H } static FcChar8 * FcHashSHA256ToString (FcChar32 *hash) { FcChar8 *ret = NULL; static const char hex[] = "0123456789abcdef"; int i, j; if (hash) { ret = malloc (sizeof (FcChar8) * (8 * 8 + 7 + 1)); if (!ret) return NULL; memcpy (ret, "sha256:", 7); #define H(n) hash[n] for (i = 0; i < 8; i++) { FcChar32 v = H(i); for (j = 0; j < 8; j++) ret[7 + (i * 8) + j] = hex[(v >> (28 - j * 4)) & 0xf]; } ret[7 + i * 8] = 0; #undef H free (hash); } return ret; } FcChar8 * FcHashGetSHA256Digest (const FcChar8 *input_strings, size_t len) { size_t i, round_len = len / 64; char block[64]; FcChar32 *ret = FcHashInitSHA256Digest (); if (!ret) return NULL; for (i = 0; i < round_len; i++) { FcHashComputeSHA256Digest (ret, (const char *)&input_strings[i * 64]); } /* padding */ if ((len % 64) != 0) memcpy (block, &input_strings[len / 64], len % 64); memset (&block[len % 64], 0, 64 - (len % 64)); block[len % 64] = 0x80; if ((64 - (len % 64)) < 9) { /* process a block once */ FcHashComputeSHA256Digest (ret, block); memset (block, 0, 64); } /* set input size at the end */ len *= 8; block[63 - 0] = (uint64_t)len & 0xff; block[63 - 1] = ((uint64_t)len >> 8) & 0xff; block[63 - 2] = ((uint64_t)len >> 16) & 0xff; block[63 - 3] = ((uint64_t)len >> 24) & 0xff; block[63 - 4] = ((uint64_t)len >> 32) & 0xff; block[63 - 5] = ((uint64_t)len >> 40) & 0xff; block[63 - 6] = ((uint64_t)len >> 48) & 0xff; block[63 - 7] = ((uint64_t)len >> 56) & 0xff; FcHashComputeSHA256Digest (ret, block); return FcHashSHA256ToString (ret); } FcChar8 * FcHashGetSHA256DigestFromFile (const FcChar8 *filename) { FILE *fp = fopen ((const char *)filename, "rb"); char ibuf[64]; FcChar32 *ret; size_t len; struct stat st; if (!fp) return NULL; if (FcStat (filename, &st)) goto bail0; ret = FcHashInitSHA256Digest (); if (!ret) goto bail0; while (!feof (fp)) { if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64) { uint64_t v; /* add a padding */ memset (&ibuf[len], 0, 64 - len); ibuf[len] = 0x80; if ((64 - len) < 9) { /* process a block once */ FcHashComputeSHA256Digest (ret, ibuf); memset (ibuf, 0, 64); } /* set input size at the end */ v = (long)st.st_size * 8; ibuf[63 - 0] = v & 0xff; ibuf[63 - 1] = (v >> 8) & 0xff; ibuf[63 - 2] = (v >> 16) & 0xff; ibuf[63 - 3] = (v >> 24) & 0xff; ibuf[63 - 4] = (v >> 32) & 0xff; ibuf[63 - 5] = (v >> 40) & 0xff; ibuf[63 - 6] = (v >> 48) & 0xff; ibuf[63 - 7] = (v >> 56) & 0xff; FcHashComputeSHA256Digest (ret, ibuf); break; } else { FcHashComputeSHA256Digest (ret, ibuf); } } fclose (fp); return FcHashSHA256ToString (ret); bail0: fclose (fp); return NULL; } FcChar8 * FcHashGetSHA256DigestFromMemory (const char *fontdata, size_t length) { char ibuf[64]; FcChar32 *ret; size_t i = 0; ret = FcHashInitSHA256Digest (); if (!ret) return NULL; while (i <= length) { if ((length - i) < 64) { uint64_t v; size_t n; /* add a padding */ n = length - i; if (n > 0) memcpy (ibuf, &fontdata[i], n); memset (&ibuf[n], 0, 64 - n); ibuf[n] = 0x80; if ((64 - n) < 9) { /* process a block once */ FcHashComputeSHA256Digest (ret, ibuf); memset (ibuf, 0, 64); } /* set input size at the end */ v = length * 8; ibuf[63 - 0] = v & 0xff; ibuf[63 - 1] = (v >> 8) & 0xff; ibuf[63 - 2] = (v >> 16) & 0xff; ibuf[63 - 3] = (v >> 24) & 0xff; ibuf[63 - 4] = (v >> 32) & 0xff; ibuf[63 - 5] = (v >> 40) & 0xff; ibuf[63 - 6] = (v >> 48) & 0xff; ibuf[63 - 7] = (v >> 56) & 0xff; FcHashComputeSHA256Digest (ret, ibuf); break; } else { FcHashComputeSHA256Digest (ret, &fontdata[i]); } i += 64; } return FcHashSHA256ToString (ret); }