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