Add missing #include <sys/statvfs.h> in fcstat.c
[platform/upstream/fontconfig.git] / src / fchash.c
1 /*
2  * fontconfig/src/fchash.c
3  *
4  * Copyright © 2003 Keith Packard
5  * Copyright © 2013 Red Hat, Inc.
6  * Red Hat Author(s): Akira TAGOH
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the name of the author(s) not be used in
13  * advertising or publicity pertaining to distribution of the software without
14  * specific, written prior permission.  The authors make no
15  * representations about the suitability of this software for any purpose.  It
16  * is provided "as is" without express or implied warranty.
17  *
18  * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20  * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24  * PERFORMANCE OF THIS SOFTWARE.
25  */
26 #include "fcint.h"
27 #include <stdio.h>
28 #include <string.h>
29
30 #define ROTRN(w, v, n)  ((((FcChar32)v) >> n) | (((FcChar32)v) << (w - n)))
31 #define ROTR32(v, n)    ROTRN(32, v, n)
32 #define SHR(v, n)       (v >> n)
33 #define Ch(x, y, z)     ((x & y) ^ (~x & z))
34 #define Maj(x, y, z)    ((x & y) ^ (x & z) ^ (y & z))
35 #define SS0(x)          (ROTR32(x, 2) ^ ROTR32(x, 13) ^ ROTR32(x, 22))
36 #define SS1(x)          (ROTR32(x, 6) ^ ROTR32(x, 11) ^ ROTR32(x, 25))
37 #define ss0(x)          (ROTR32(x, 7) ^ ROTR32(x, 18) ^ SHR(x, 3))
38 #define ss1(x)          (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10))
39
40
41 static FcChar32 *
42 FcHashInitSHA256Digest (void)
43 {
44     int i;
45     static const FcChar32 h[] = {
46         0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
47         0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
48     };
49     FcChar32 *ret = malloc (sizeof (FcChar32) * 8);
50
51     if (!ret)
52         return NULL;
53
54     for (i = 0; i < 8; i++)
55         ret[i] = h[i];
56
57     return ret;
58 }
59
60 static void
61 FcHashComputeSHA256Digest (FcChar32   *hash,
62                            const char *block)
63 {
64     static const FcChar32 k[] = {
65         0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
66         0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
67         0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
68         0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
69         0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
70         0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
71         0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
72         0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
73         0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
74         0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
75         0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
76         0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
77         0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
78         0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
79         0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
80         0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
81     };
82     FcChar32 w[64], i, j, t1, t2;
83     FcChar32 a, b, c, d, e, f, g, h;
84
85 #define H(n)    (hash[n])
86
87     a = H(0);
88     b = H(1);
89     c = H(2);
90     d = H(3);
91     e = H(4);
92     f = H(5);
93     g = H(6);
94     h = H(7);
95
96     for (i = 0; i < 16; i++)
97     {
98         j =  (block[(i * 4) + 0] & 0xff) << (8 * 3);
99         j |= (block[(i * 4) + 1] & 0xff) << (8 * 2);
100         j |= (block[(i * 4) + 2] & 0xff) << (8 * 1);
101         j |= (block[(i * 4) + 3] & 0xff);
102         w[i] = j;
103     }
104     for (i = 16; i < 64; i++)
105         w[i] = ss1(w[i - 2]) + w[i - 7] + ss0(w[i - 15]) + w[i - 16];
106
107     for (i = 0; i < 64; i++)
108     {
109         t1 = h + SS1(e) + Ch(e, f, g) + k[i] + w[i];
110         t2 = SS0(a) + Maj(a, b, c);
111         h = g;
112         g = f;
113         f = e;
114         e = d + t1;
115         d = c;
116         c = b;
117         b = a;
118         a = t1 + t2;
119     }
120
121     H(0) += a;
122     H(1) += b;
123     H(2) += c;
124     H(3) += d;
125     H(4) += e;
126     H(5) += f;
127     H(6) += g;
128     H(7) += h;
129
130 #undef H
131 }
132
133 static FcChar8 *
134 FcHashSHA256ToString (FcChar32 *hash)
135 {
136     FcChar8 *ret = NULL;
137     static const char hex[] = "0123456789abcdef";
138     int i, j;
139
140     if (hash)
141     {
142         ret = malloc (sizeof (FcChar8) * (8 * 8 + 7 + 1));
143         if (!ret)
144             return NULL;
145         memcpy (ret, "sha256:", 7);
146 #define H(n)    hash[n]
147         for (i = 0; i < 8; i++)
148         {
149             FcChar32 v = H(i);
150
151             for (j = 0; j < 8; j++)
152                 ret[7 + (i * 8) + j] = hex[(v >> (28 - j * 4)) & 0xf];
153         }
154         ret[7 + i * 8] = 0;
155 #undef H
156         free (hash);
157     }
158
159     return ret;
160 }
161
162 FcChar8 *
163 FcHashGetSHA256Digest (const FcChar8 *input_strings,
164                        size_t         len)
165 {
166     size_t i, round_len = len / 64;
167     char block[64];
168     FcChar32 *ret = FcHashInitSHA256Digest ();
169
170     if (!ret)
171         return NULL;
172
173     for (i = 0; i < round_len; i++)
174     {
175         FcHashComputeSHA256Digest (ret, (const char *)&input_strings[i * 64]);
176     }
177     /* padding */
178     if ((len % 64) != 0)
179         memcpy (block, &input_strings[len / 64], len % 64);
180     memset (&block[len % 64], 0, 64 - (len % 64));
181     block[len % 64] = 0x80;
182     if ((64 - (len % 64)) < 9)
183     {
184         /* process a block once */
185         FcHashComputeSHA256Digest (ret, block);
186         memset (block, 0, 64);
187     }
188     /* set input size at the end */
189     len *= 8;
190     block[63 - 0] =  (uint64_t)len        & 0xff;
191     block[63 - 1] = ((uint64_t)len >>  8) & 0xff;
192     block[63 - 2] = ((uint64_t)len >> 16) & 0xff;
193     block[63 - 3] = ((uint64_t)len >> 24) & 0xff;
194     block[63 - 4] = ((uint64_t)len >> 32) & 0xff;
195     block[63 - 5] = ((uint64_t)len >> 40) & 0xff;
196     block[63 - 6] = ((uint64_t)len >> 48) & 0xff;
197     block[63 - 7] = ((uint64_t)len >> 56) & 0xff;
198     FcHashComputeSHA256Digest (ret, block);
199
200     return FcHashSHA256ToString (ret);
201 }
202
203 FcChar8 *
204 FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
205 {
206     FILE *fp = fopen ((const char *)filename, "rb");
207     char ibuf[64];
208     FcChar32 *ret;
209     size_t len;
210     struct stat st;
211
212     if (!fp)
213         return NULL;
214
215     if (FcStat (filename, &st))
216         goto bail0;
217
218     ret = FcHashInitSHA256Digest ();
219     if (!ret)
220         goto bail0;
221
222     while (!feof (fp))
223     {
224         if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64)
225         {
226             uint64_t v;
227
228             /* add a padding */
229             memset (&ibuf[len], 0, 64 - len);
230             ibuf[len] = 0x80;
231             if ((64 - len) < 9)
232             {
233                 /* process a block once */
234                 FcHashComputeSHA256Digest (ret, ibuf);
235                 memset (ibuf, 0, 64);
236             }
237             /* set input size at the end */
238             v = (long)st.st_size * 8;
239             ibuf[63 - 0] =  v        & 0xff;
240             ibuf[63 - 1] = (v >>  8) & 0xff;
241             ibuf[63 - 2] = (v >> 16) & 0xff;
242             ibuf[63 - 3] = (v >> 24) & 0xff;
243             ibuf[63 - 4] = (v >> 32) & 0xff;
244             ibuf[63 - 5] = (v >> 40) & 0xff;
245             ibuf[63 - 6] = (v >> 48) & 0xff;
246             ibuf[63 - 7] = (v >> 56) & 0xff;
247             FcHashComputeSHA256Digest (ret, ibuf);
248             break;
249         }
250         else
251         {
252             FcHashComputeSHA256Digest (ret, ibuf);
253         }
254     }
255     fclose (fp);
256
257     return FcHashSHA256ToString (ret);
258
259 bail0:
260     fclose (fp);
261
262     return NULL;
263 }
264
265 FcChar8 *
266 FcHashGetSHA256DigestFromMemory (const char *fontdata,
267                                  size_t      length)
268 {
269     char ibuf[64];
270     FcChar32 *ret;
271     size_t i = 0;
272
273     ret = FcHashInitSHA256Digest ();
274     if (!ret)
275         return NULL;
276
277     while (i <= length)
278     {
279         if ((length - i) < 64)
280         {
281             uint64_t v;
282             size_t n;
283
284             /* add a padding */
285             n = length - i;
286             if (n > 0)
287                 memcpy (ibuf, &fontdata[i], n);
288             memset (&ibuf[n], 0, 64 - n);
289             ibuf[n] = 0x80;
290             if ((64 - n) < 9)
291             {
292                 /* process a block once */
293                 FcHashComputeSHA256Digest (ret, ibuf);
294                 memset (ibuf, 0, 64);
295             }
296             /* set input size at the end */
297             v = length * 8;
298             ibuf[63 - 0] =  v        & 0xff;
299             ibuf[63 - 1] = (v >>  8) & 0xff;
300             ibuf[63 - 2] = (v >> 16) & 0xff;
301             ibuf[63 - 3] = (v >> 24) & 0xff;
302             ibuf[63 - 4] = (v >> 32) & 0xff;
303             ibuf[63 - 5] = (v >> 40) & 0xff;
304             ibuf[63 - 6] = (v >> 48) & 0xff;
305             ibuf[63 - 7] = (v >> 56) & 0xff;
306             FcHashComputeSHA256Digest (ret, ibuf);
307             break;
308         }
309         else
310         {
311             FcHashComputeSHA256Digest (ret, &fontdata[i]);
312         }
313         i += 64;
314     }
315
316     return FcHashSHA256ToString (ret);
317 }