1/*- mdXhl.c
2 * SPDX-License-Identifier: Beerware
3 *
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 */
11
12#include <sys/cdefs.h>
13__FBSDID("$FreeBSD$");
14
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#include <unistd.h>
19
20#include <errno.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24#include "mdX.h"
25
26char *
27MDXEnd(MDX_CTX *ctx, char *buf)
28{
29	int i;
30	unsigned char digest[LENGTH];
31	static const char hex[]="0123456789abcdef";
32
33	if (!buf)
34		buf = malloc(2*LENGTH + 1);
35	if (!buf)
36		return 0;
37	MDXFinal(digest, ctx);
38	for (i = 0; i < LENGTH; i++) {
39		buf[i+i] = hex[digest[i] >> 4];
40		buf[i+i+1] = hex[digest[i] & 0x0f];
41	}
42	buf[i+i] = '\0';
43	return buf;
44}
45
46char *
47MDXFd(int fd, char *buf)
48{
49	return MDXFdChunk(fd, buf, 0, 0);
50}
51
52char *
53MDXFdChunk(int fd, char *buf, off_t ofs, off_t len)
54{
55	unsigned char buffer[16*1024];
56	MDX_CTX ctx;
57	struct stat stbuf;
58	int readrv, e;
59	off_t remain;
60
61	if (len < 0) {
62		errno = EINVAL;
63		return NULL;
64	}
65
66	MDXInit(&ctx);
67	if (ofs != 0) {
68		errno = 0;
69		if (lseek(fd, ofs, SEEK_SET) != ofs ||
70		    (ofs == -1 && errno != 0)) {
71			readrv = -1;
72			goto error;
73		}
74	}
75	remain = len;
76	readrv = 0;
77	while (len == 0 || remain > 0) {
78		if (len == 0 || remain > sizeof(buffer))
79			readrv = read(fd, buffer, sizeof(buffer));
80		else
81			readrv = read(fd, buffer, remain);
82		if (readrv <= 0)
83			break;
84		MDXUpdate(&ctx, buffer, readrv);
85		remain -= readrv;
86	}
87error:
88	if (readrv < 0)
89		return NULL;
90	return (MDXEnd(&ctx, buf));
91}
92
93char *
94MDXFile(const char *filename, char *buf)
95{
96	return (MDXFileChunk(filename, buf, 0, 0));
97}
98
99char *
100MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len)
101{
102	char *ret;
103	int e, fd;
104
105	fd = open(filename, O_RDONLY);
106	if (fd < 0)
107		return NULL;
108	ret = MDXFdChunk(fd, buf, ofs, len);
109	e = errno;
110	close (fd);
111	errno = e;
112	return ret;
113}
114
115char *
116MDXData (const void *data, unsigned int len, char *buf)
117{
118	MDX_CTX ctx;
119
120	MDXInit(&ctx);
121	MDXUpdate(&ctx,data,len);
122	return (MDXEnd(&ctx, buf));
123}
124
125#ifdef WEAK_REFS
126/* When building libmd, provide weak references. Note: this is not
127   activated in the context of compiling these sources for internal
128   use in libcrypt.
129 */
130#undef MDXEnd
131__weak_reference(_libmd_MDXEnd, MDXEnd);
132#undef MDXFile
133__weak_reference(_libmd_MDXFile, MDXFile);
134#undef MDXFileChunk
135__weak_reference(_libmd_MDXFileChunk, MDXFileChunk);
136#undef MDXData
137__weak_reference(_libmd_MDXData, MDXData);
138#endif
139