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