1*a512a68cSzrj /*
2*a512a68cSzrj * Copyright (c) 2019 The DragonFly Project. All rights reserved.
3*a512a68cSzrj *
4*a512a68cSzrj * Redistribution and use in source and binary forms, with or without
5*a512a68cSzrj * modification, are permitted provided that the following conditions
6*a512a68cSzrj * are met:
7*a512a68cSzrj * 1. Redistributions of source code must retain the above copyright
8*a512a68cSzrj * notice, this list of conditions and the following disclaimer.
9*a512a68cSzrj * 2. Redistributions in binary form must reproduce the above copyright
10*a512a68cSzrj * notice, this list of conditions and the following disclaimer in the
11*a512a68cSzrj * documentation and/or other materials provided with the distribution.
12*a512a68cSzrj *
13*a512a68cSzrj * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14*a512a68cSzrj * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15*a512a68cSzrj * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16*a512a68cSzrj * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17*a512a68cSzrj * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18*a512a68cSzrj * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
19*a512a68cSzrj * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20*a512a68cSzrj * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21*a512a68cSzrj * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22*a512a68cSzrj * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
23*a512a68cSzrj * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*a512a68cSzrj * SUCH DAMAGE.
25*a512a68cSzrj */
26*a512a68cSzrj
27*a512a68cSzrj #include <sys/types.h>
28*a512a68cSzrj #include <sys/stat.h>
29*a512a68cSzrj #include <errno.h>
30*a512a68cSzrj #include <fcntl.h>
31*a512a68cSzrj #include <stdlib.h>
32*a512a68cSzrj #include <unistd.h>
33*a512a68cSzrj #include <openssl/md5.h>
34*a512a68cSzrj #include <openssl/sha.h>
35*a512a68cSzrj #include <openssl/ripemd.h>
36*a512a68cSzrj
37*a512a68cSzrj #include <stdio.h> /* for FILE in mtree.h */
38*a512a68cSzrj #include "extern.h"
39*a512a68cSzrj
40*a512a68cSzrj /* max(MD5_DIGEST_LENGTH, SHA_DIGEST_LENGTH,
41*a512a68cSzrj SHA256_DIGEST_LENGTH, SHA512_DIGEST_LENGTH,
42*a512a68cSzrj RIPEMD160_DIGEST_LENGTH) * 2 + 1 */
43*a512a68cSzrj #define HEX_DIGEST_LENGTH 129
44*a512a68cSzrj
45*a512a68cSzrj typedef union {
46*a512a68cSzrj MD5_CTX md5;
47*a512a68cSzrj SHA_CTX sha1;
48*a512a68cSzrj SHA256_CTX sha256;
49*a512a68cSzrj SHA512_CTX sha512;
50*a512a68cSzrj RIPEMD160_CTX ripemd160;
51*a512a68cSzrj } DIGEST_CTX;
52*a512a68cSzrj
53*a512a68cSzrj char *
dohash(int flag,const char * filename)54*a512a68cSzrj dohash(int flag, const char *filename)
55*a512a68cSzrj {
56*a512a68cSzrj unsigned char digest[HEX_DIGEST_LENGTH];
57*a512a68cSzrj static const char hex[]="0123456789abcdef";
58*a512a68cSzrj DIGEST_CTX context;
59*a512a68cSzrj void *ctx;
60*a512a68cSzrj unsigned char buffer[4096];
61*a512a68cSzrj char *buf;
62*a512a68cSzrj struct stat st;
63*a512a68cSzrj off_t size;
64*a512a68cSzrj int fd, bytes, i, digest_len;
65*a512a68cSzrj
66*a512a68cSzrj ctx = &context;
67*a512a68cSzrj
68*a512a68cSzrj if (flag == F_MD5)
69*a512a68cSzrj digest_len = MD5_DIGEST_LENGTH;
70*a512a68cSzrj else if (flag == F_RMD160)
71*a512a68cSzrj digest_len = RIPEMD160_DIGEST_LENGTH;
72*a512a68cSzrj else if (flag == F_SHA1)
73*a512a68cSzrj digest_len = SHA_DIGEST_LENGTH;
74*a512a68cSzrj else if (flag == F_SHA256)
75*a512a68cSzrj digest_len = SHA256_DIGEST_LENGTH;
76*a512a68cSzrj else if (flag == F_SHA384)
77*a512a68cSzrj digest_len = SHA384_DIGEST_LENGTH;
78*a512a68cSzrj else if (flag == F_SHA512)
79*a512a68cSzrj digest_len = SHA512_DIGEST_LENGTH;
80*a512a68cSzrj else
81*a512a68cSzrj return NULL;
82*a512a68cSzrj
83*a512a68cSzrj buf = malloc(digest_len * 2 + 1);
84*a512a68cSzrj if (!buf)
85*a512a68cSzrj return NULL;
86*a512a68cSzrj
87*a512a68cSzrj fd = open(filename, O_RDONLY);
88*a512a68cSzrj if (fd < 0)
89*a512a68cSzrj return NULL;
90*a512a68cSzrj if (fstat(fd, &st) < 0) {
91*a512a68cSzrj bytes = -1;
92*a512a68cSzrj goto err;
93*a512a68cSzrj }
94*a512a68cSzrj
95*a512a68cSzrj if (flag == F_MD5)
96*a512a68cSzrj MD5_Init(ctx);
97*a512a68cSzrj else if (flag == F_RMD160)
98*a512a68cSzrj RIPEMD160_Init(ctx);
99*a512a68cSzrj else if (flag == F_SHA1)
100*a512a68cSzrj SHA1_Init(ctx);
101*a512a68cSzrj else if (flag == F_SHA256)
102*a512a68cSzrj SHA256_Init(ctx);
103*a512a68cSzrj else if (flag == F_SHA384)
104*a512a68cSzrj SHA384_Init(ctx);
105*a512a68cSzrj else if (flag == F_SHA512)
106*a512a68cSzrj SHA512_Init(ctx);
107*a512a68cSzrj
108*a512a68cSzrj size = st.st_size;
109*a512a68cSzrj bytes = 0;
110*a512a68cSzrj while (size > 0) {
111*a512a68cSzrj if ((size_t)size > sizeof(buffer))
112*a512a68cSzrj bytes = read(fd, buffer, sizeof(buffer));
113*a512a68cSzrj else
114*a512a68cSzrj bytes = read(fd, buffer, size);
115*a512a68cSzrj if (bytes < 0)
116*a512a68cSzrj break;
117*a512a68cSzrj
118*a512a68cSzrj if (flag == F_MD5)
119*a512a68cSzrj MD5_Update(ctx, buffer, bytes);
120*a512a68cSzrj else if (flag == F_RMD160)
121*a512a68cSzrj RIPEMD160_Update(ctx, buffer, bytes);
122*a512a68cSzrj else if (flag == F_SHA1)
123*a512a68cSzrj SHA1_Update(ctx, buffer, bytes);
124*a512a68cSzrj else if (flag == F_SHA256)
125*a512a68cSzrj SHA256_Update(ctx, buffer, bytes);
126*a512a68cSzrj else if (flag == F_SHA384)
127*a512a68cSzrj SHA384_Update(ctx, buffer, bytes);
128*a512a68cSzrj else if (flag == F_SHA512)
129*a512a68cSzrj SHA512_Update(ctx, buffer, bytes);
130*a512a68cSzrj
131*a512a68cSzrj size -= bytes;
132*a512a68cSzrj }
133*a512a68cSzrj
134*a512a68cSzrj err:
135*a512a68cSzrj close(fd);
136*a512a68cSzrj
137*a512a68cSzrj if (bytes < 0)
138*a512a68cSzrj return NULL;
139*a512a68cSzrj
140*a512a68cSzrj if (flag == F_MD5)
141*a512a68cSzrj MD5_Final(digest, ctx);
142*a512a68cSzrj else if (flag == F_RMD160)
143*a512a68cSzrj RIPEMD160_Final(digest, ctx);
144*a512a68cSzrj else if (flag == F_SHA1)
145*a512a68cSzrj SHA1_Final(digest, ctx);
146*a512a68cSzrj else if (flag == F_SHA256)
147*a512a68cSzrj SHA256_Final(digest, ctx);
148*a512a68cSzrj else if (flag == F_SHA384)
149*a512a68cSzrj SHA384_Final(digest, ctx);
150*a512a68cSzrj else if (flag == F_SHA512)
151*a512a68cSzrj SHA512_Final(digest, ctx);
152*a512a68cSzrj
153*a512a68cSzrj for (i = 0; i < digest_len; i++) {
154*a512a68cSzrj buf[2*i] = hex[digest[i] >> 4];
155*a512a68cSzrj buf[2*i+1] = hex[digest[i] & 0x0f];
156*a512a68cSzrj }
157*a512a68cSzrj buf[digest_len * 2] = '\0';
158*a512a68cSzrj
159*a512a68cSzrj return buf;
160*a512a68cSzrj }
161