root/usr/src/cmd/boot/bootadm/bootadm_digest.c
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2016 Toomas Soome <tsoome@me.com>
 * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
 */

/*
 * Create sha1 hash for file.
 *
 * NOTE:  This is hardwired for now, so use libmd's SHA1 for simplicity.
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <locale.h>
#include <sha1.h>
#include <cryptoutil.h>
#include "bootadm.h"

#define BUFFERSIZE (64 * 1024)
static uint8_t buf[BUFFERSIZE];

int
bootadm_digest(const char *filename, char **result)
{
        int fd;
        char *resultstr = NULL;
        uint8_t *resultbuf;
        int resultstrlen, resultlen, exitcode;
        SHA1_CTX sha1_ctx;
        ssize_t nread;

        /* Allocate a buffer to store result. */
        resultlen = SHA1_DIGEST_LENGTH;
        if ((resultbuf = malloc(resultlen)) == NULL) {
                bam_print(gettext("out of memory\n"));
                exitcode = BAM_ERROR;
                goto cleanup;
        }

        if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
                bam_print(gettext("can not open input file %s\n"), filename);
                exitcode = BAM_ERROR;
                goto cleanup;
        }

        SHA1Init(&sha1_ctx);
        while ((nread = read(fd, buf, sizeof (buf))) > 0)
                SHA1Update(&sha1_ctx, buf, nread);
        if (nread == -1) {
                bam_print(gettext("error reading file: %s\n"), strerror(errno));
                exitcode = BAM_ERROR;
                goto cleanup;
        }
        SHA1Final(resultbuf, &sha1_ctx);

        /* Allocate a buffer to store result string */
        resultstrlen = 2 * resultlen + 1;       /* Two hex chars per byte. */
        if ((resultstr = malloc(resultstrlen)) == NULL) {
                bam_print(gettext("out of memory\n"));
                exitcode = BAM_ERROR;
                goto cleanup;
        }

        tohexstr(resultbuf, resultlen, resultstr, resultstrlen);
        exitcode = BAM_SUCCESS;
        (void) close(fd);
cleanup:
        if (exitcode == BAM_ERROR) {
                free(resultstr);
                resultstr = NULL;
        }

        free(resultbuf);

        *result = resultstr;
        return (exitcode);
}