summaryrefslogtreecommitdiff
path: root/usr/src/cmd/boot
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2015-06-06 11:49:15 +0300
committerRobert Mustacchi <rm@joyent.com>2016-08-04 08:06:16 -0700
commit2dc235874d66f757a3abf5072f6c3fd4ca7d0979 (patch)
tree430ebf0049bb3ec81cf47d3c8f98e475eeee583f /usr/src/cmd/boot
parent60b81b86c4b2eb3a0481176c344f4b6e7a6276fa (diff)
downloadillumos-joyent-2dc235874d66f757a3abf5072f6c3fd4ca7d0979.tar.gz
6005 bootadm update-archive should create/update archive sha-1 hash
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Reviewed by: Albert Lee <trisk@omniti.com> Reviewed by: Andrew Stormont <andyjstormont@gmail.com> Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/cmd/boot')
-rw-r--r--usr/src/cmd/boot/bootadm/Makefile5
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm.c42
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm.h3
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm_digest.c243
-rw-r--r--usr/src/cmd/boot/scripts/create_ramdisk.ksh4
5 files changed, 295 insertions, 2 deletions
diff --git a/usr/src/cmd/boot/bootadm/Makefile b/usr/src/cmd/boot/bootadm/Makefile
index be838e34f7..64616469be 100644
--- a/usr/src/cmd/boot/bootadm/Makefile
+++ b/usr/src/cmd/boot/bootadm/Makefile
@@ -23,13 +23,14 @@
# Use is subject to license terms.
#
# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2016 Toomas Soome <tsoome@me.com>
#
PROG= bootadm
SBINLINKS= $(PROG)
-OBJS= bootadm.o bootadm_upgrade.o bootadm_hyper.o
+OBJS= bootadm.o bootadm_upgrade.o bootadm_hyper.o bootadm_digest.o
SRCS = $(OBJS:.o=.c)
include ../Makefile.com
@@ -38,7 +39,7 @@ include ../Makefile.com
.KEEP_STATE:
LDLIBS_i386= -lfdisk
-LDLIBS += -lnvpair -lgen -ladm -lefi -lscf -lz -lbe -lzfs $(LDLIBS_$(MACH))
+LDLIBS += -lpkcs11 -lcryptoutil -lnvpair -lgen -ladm -lefi -lscf -lz -lbe -lzfs $(LDLIBS_$(MACH))
# Writing into string literals is incorrect. We need to match gcc's
# behavior, which causes us to take SIGSEGV on such a write.
diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c
index ba62ba3d7a..a5a1490a72 100644
--- a/usr/src/cmd/boot/bootadm/bootadm.c
+++ b/usr/src/cmd/boot/bootadm/bootadm.c
@@ -26,6 +26,7 @@
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
*/
/*
@@ -3363,6 +3364,40 @@ to_733(unsigned char *s, unsigned int val)
}
/*
+ * creates sha1 hash of archive
+ */
+static int
+digest_archive(const char *archive)
+{
+ char *archive_hash;
+ char *hash;
+ int ret;
+ FILE *fp;
+
+ (void) asprintf(&archive_hash, "%s.hash", archive);
+ if (archive_hash == NULL)
+ return (BAM_ERROR);
+
+ if ((ret = bootadm_digest(archive, &hash)) == BAM_ERROR) {
+ free(archive_hash);
+ return (ret);
+ }
+
+ fp = fopen(archive_hash, "w");
+ if (fp == NULL) {
+ free(archive_hash);
+ free(hash);
+ return (BAM_ERROR);
+ }
+
+ (void) fprintf(fp, "%s\n", hash);
+ (void) fclose(fp);
+ free(hash);
+ free(archive_hash);
+ return (BAM_SUCCESS);
+}
+
+/*
* Extends the current boot archive without recreating it from scratch
*/
static int
@@ -3495,6 +3530,9 @@ extend_iso_archive(char *archive, char *tempname, char *update_dir)
(void) unlink(tempname);
+ if (digest_archive(archive) == BAM_ERROR && bam_verbose)
+ bam_print("boot archive hashing failed\n");
+
if (flushfs(bam_root) != 0)
sync();
@@ -3623,6 +3661,9 @@ mkisofs_archive(char *root, int what)
get_cachedir(what));
}
+ if (digest_archive(boot_archive) == BAM_ERROR && bam_verbose)
+ bam_print("boot archive hashing failed\n");
+
if (ret == BAM_SUCCESS && bam_verbose)
bam_print("Successfully created %s\n", boot_archive);
@@ -3656,6 +3697,7 @@ create_ramdisk(char *root)
/*
* Else setup command args for create_ramdisk.ksh for the UFS archives
+ * Note: we will not create hash here, CREATE_RAMDISK should create it.
*/
if (bam_verbose)
bam_print("mkisofs not found, creating UFS archive\n");
diff --git a/usr/src/cmd/boot/bootadm/bootadm.h b/usr/src/cmd/boot/bootadm/bootadm.h
index 6d5c5c73ca..b59d860e4e 100644
--- a/usr/src/cmd/boot/bootadm/bootadm.h
+++ b/usr/src/cmd/boot/bootadm/bootadm.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2016 Toomas Soome <tsoome@me.com>.
*/
#ifndef _BOOTADM_H
@@ -188,6 +190,7 @@ extern void unlink_line(menu_t *mp, line_t *lp);
extern void line_free(line_t *lp);
extern char *s_strdup(char *);
extern int is_sparc(void);
+extern int bootadm_digest(const char *, char **);
#define BAM_MAXLINE 8192
diff --git a/usr/src/cmd/boot/bootadm/bootadm_digest.c b/usr/src/cmd/boot/bootadm/bootadm_digest.c
new file mode 100644
index 0000000000..ea95c686e8
--- /dev/null
+++ b/usr/src/cmd/boot/bootadm/bootadm_digest.c
@@ -0,0 +1,243 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
+ */
+
+/*
+ * Create sha1 hash for file.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include <locale.h>
+#include "bootadm.h"
+
+#define BUFFERSIZE (1024 * 64)
+#define RESULTLEN (512)
+static CK_BYTE buf[BUFFERSIZE];
+
+/*
+ * do_digest - Compute digest of a file. Borrowed from digest.
+ *
+ * hSession - session
+ * pmech - ptr to mechanism to be used for digest
+ * fd - file descriptor
+ * pdigest - buffer where digest result is returned
+ * pdigestlen - length of digest buffer on input,
+ * length of result on output
+ */
+static CK_RV
+do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
+ int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen)
+{
+ CK_RV rv;
+ ssize_t nread;
+ int err;
+
+ if ((rv = C_DigestInit(hSession, pmech)) != CKR_OK) {
+ return (rv);
+ }
+
+ while ((nread = read(fd, buf, sizeof (buf))) > 0) {
+ /* Get the digest */
+ rv = C_DigestUpdate(hSession, buf, (CK_ULONG)nread);
+ if (rv != CKR_OK)
+ return (rv);
+ }
+
+ /* There was a read error */
+ if (nread == -1) {
+ err = errno;
+ bam_print(gettext("error reading file: %s\n"), strerror(err));
+ return (CKR_GENERAL_ERROR);
+ }
+
+ rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
+
+ /* result too big to fit? Allocate a bigger buffer */
+ if (rv == CKR_BUFFER_TOO_SMALL) {
+ *pdigest = realloc(*pdigest, *pdigestlen);
+
+ if (*pdigest == NULL) {
+ err = errno;
+ bam_print(gettext("realloc: %s\n"), strerror(err));
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
+ }
+
+ return (rv);
+}
+
+int
+bootadm_digest(const char *filename, char **result)
+{
+ int fd;
+ CK_RV rv;
+ CK_ULONG slotcount;
+ CK_SLOT_ID slotID;
+ CK_SLOT_ID_PTR pSlotList = NULL;
+ CK_MECHANISM_TYPE mech_type = CKM_SHA_1;
+ CK_MECHANISM_INFO info;
+ CK_MECHANISM mech;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_BYTE_PTR resultbuf = NULL;
+ CK_ULONG resultlen;
+ char *resultstr = NULL;
+ int resultstrlen;
+ int i, exitcode;
+
+ /* Initialize, and get list of slots */
+ rv = C_Initialize(NULL);
+ if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+ bam_print(gettext(
+ "failed to initialize PKCS #11 framework: %s\n"),
+ pkcs11_strerror(rv));
+ return (BAM_ERROR);
+ }
+
+ /* Get slot count */
+ rv = C_GetSlotList(0, NULL, &slotcount);
+ if (rv != CKR_OK || slotcount == 0) {
+ bam_print(gettext(
+ "failed to find any cryptographic provider: %s\n"),
+ pkcs11_strerror(rv));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Found at least one slot, allocate memory for slot list */
+ pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
+ if (pSlotList == NULL) {
+ bam_print(gettext("out of memory\n"));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Get the list of slots */
+ if ((rv = C_GetSlotList(0, pSlotList, &slotcount)) != CKR_OK) {
+ bam_print(gettext(
+ "failed to find any cryptographic provider; "
+ "please check with your system administrator: %s\n"),
+ pkcs11_strerror(rv));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Find a slot with matching mechanism */
+ for (i = 0; i < slotcount; i++) {
+ slotID = pSlotList[i];
+ rv = C_GetMechanismInfo(slotID, mech_type, &info);
+ if (rv != CKR_OK) {
+ continue; /* to the next slot */
+ } else {
+ if (info.flags & CKF_DIGEST)
+ break;
+ }
+ }
+
+ /* Show error if no matching mechanism found */
+ if (i == slotcount) {
+ bam_print(gettext("no cryptographic provider was "
+ "found for sha1\n"));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Mechanism is supported. Go ahead & open a session */
+ rv = C_OpenSession(slotID, CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+
+ if (rv != CKR_OK) {
+ bam_print(gettext("can not open PKCS#11 session: %s\n"),
+ pkcs11_strerror(rv));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Allocate a buffer to store result. */
+ resultlen = RESULTLEN;
+ if ((resultbuf = malloc(resultlen)) == NULL) {
+ bam_print(gettext("out of memory\n"));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ mech.mechanism = mech_type;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+ exitcode = BAM_SUCCESS;
+
+ 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;
+ }
+
+ rv = do_digest(hSession, &mech, fd, &resultbuf, &resultlen);
+
+ if (rv != CKR_OK) {
+ bam_print(gettext("crypto operation failed for "
+ "file %s: %s\n"), filename, pkcs11_strerror(rv));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ /* Allocate a buffer to store result string */
+ resultstrlen = 2 * resultlen + 1;
+ if ((resultstr = malloc(resultstrlen)) == NULL) {
+ bam_print(gettext("out of memory\n"));
+ exitcode = BAM_ERROR;
+ goto cleanup;
+ }
+
+ tohexstr(resultbuf, resultlen, resultstr, resultstrlen);
+
+ (void) close(fd);
+cleanup:
+ if (exitcode == BAM_ERROR) {
+ free(resultstr);
+ resultstr = NULL;
+ }
+
+ free(resultbuf);
+ free(pSlotList);
+
+ if (hSession != CK_INVALID_HANDLE)
+ (void) C_CloseSession(hSession);
+
+ (void) C_Finalize(NULL);
+
+ *result = resultstr;
+ return (exitcode);
+}
diff --git a/usr/src/cmd/boot/scripts/create_ramdisk.ksh b/usr/src/cmd/boot/scripts/create_ramdisk.ksh
index abcad516a0..4fec8809a2 100644
--- a/usr/src/cmd/boot/scripts/create_ramdisk.ksh
+++ b/usr/src/cmd/boot/scripts/create_ramdisk.ksh
@@ -20,8 +20,10 @@
# CDDL HEADER END
#
+# Copyright 2016 Toomas Soome <tsoome@me.com>
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+#
#
# Copyright (c) 2014 by Delphix. All rights reserved.
@@ -427,6 +429,8 @@ function create_archive
else
lockfs -f "/$ALT_ROOT" 2>/dev/null
mv "${archive}-new" "$archive"
+ rm -f "$archive.hash"
+ digest -a sha1 "$archive" > "$archive.hash"
lockfs -f "/$ALT_ROOT" 2>/dev/null
fi