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
  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 }