1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2016 Toomas Soome <tsoome@me.com>
14  * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
15  */
16 
17 /*
18  * Create sha1 hash for file.
19  *
20  * NOTE:  This is hardwired for now, so use libmd's SHA1 for simplicity.
21  */
22 
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <locale.h>
30 #include <sha1.h>
31 #include <cryptoutil.h>
32 #include "bootadm.h"
33 
34 #define	BUFFERSIZE (64 * 1024)
35 static uint8_t buf[BUFFERSIZE];
36 
37 int
bootadm_digest(const char * filename,char ** result)38 bootadm_digest(const char *filename, char **result)
39 {
40 	int fd;
41 	char *resultstr = NULL;
42 	uint8_t *resultbuf;
43 	int resultstrlen, resultlen, exitcode;
44 	SHA1_CTX sha1_ctx;
45 	ssize_t nread;
46 
47 	/* Allocate a buffer to store result. */
48 	resultlen = SHA1_DIGEST_LENGTH;
49 	if ((resultbuf = malloc(resultlen)) == NULL) {
50 		bam_print(gettext("out of memory\n"));
51 		exitcode = BAM_ERROR;
52 		goto cleanup;
53 	}
54 
55 	if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
56 		bam_print(gettext("can not open input file %s\n"), filename);
57 		exitcode = BAM_ERROR;
58 		goto cleanup;
59 	}
60 
61 	SHA1Init(&sha1_ctx);
62 	while ((nread = read(fd, buf, sizeof (buf))) > 0)
63 		SHA1Update(&sha1_ctx, buf, nread);
64 	if (nread == -1) {
65 		bam_print(gettext("error reading file: %s\n"), strerror(errno));
66 		exitcode = BAM_ERROR;
67 		goto cleanup;
68 	}
69 	SHA1Final(resultbuf, &sha1_ctx);
70 
71 	/* Allocate a buffer to store result string */
72 	resultstrlen = 2 * resultlen + 1;	/* Two hex chars per byte. */
73 	if ((resultstr = malloc(resultstrlen)) == NULL) {
74 		bam_print(gettext("out of memory\n"));
75 		exitcode = BAM_ERROR;
76 		goto cleanup;
77 	}
78 
79 	tohexstr(resultbuf, resultlen, resultstr, resultstrlen);
80 	exitcode = BAM_SUCCESS;
81 	(void) close(fd);
82 cleanup:
83 	if (exitcode == BAM_ERROR) {
84 		free(resultstr);
85 		resultstr = NULL;
86 	}
87 
88 	free(resultbuf);
89 
90 	*result = resultstr;
91 	return (exitcode);
92 }
93