6005 bootadm update-archive should create/update archive sha-1 hash Reviewed by:...
[unleashed.git] / usr / src / cmd / boot / bootadm / bootadm_digest.c
blob8ff6dd2e121e2704a515f536a4dc8bd0d6f1363d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
30 * Create sha1 hash for file.
33 #include <stdio.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <security/cryptoki.h>
40 #include <cryptoutil.h>
41 #include <locale.h>
42 #include "bootadm.h"
44 #define BUFFERSIZE (1024 * 64)
45 #define RESULTLEN (512)
46 static CK_BYTE buf[BUFFERSIZE];
49 * do_digest - Compute digest of a file. Borrowed from digest.
51 * hSession - session
52 * pmech - ptr to mechanism to be used for digest
53 * fd - file descriptor
54 * pdigest - buffer where digest result is returned
55 * pdigestlen - length of digest buffer on input,
56 * length of result on output
58 static CK_RV
59 do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
60 int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen)
62 CK_RV rv;
63 ssize_t nread;
64 int saved_errno;
66 if ((rv = C_DigestInit(hSession, pmech)) != CKR_OK) {
67 return (rv);
70 while ((nread = read(fd, buf, sizeof (buf))) > 0) {
71 /* Get the digest */
72 rv = C_DigestUpdate(hSession, buf, (CK_ULONG)nread);
73 if (rv != CKR_OK)
74 return (rv);
77 saved_errno = errno; /* for later use */
80 * Perform the C_DigestFinal, even if there is a read error.
81 * Otherwise C_DigestInit will return CKR_OPERATION_ACTIVE
82 * next time it is called (for another file)
85 rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
87 /* result too big to fit? Allocate a bigger buffer */
88 if (rv == CKR_BUFFER_TOO_SMALL) {
89 *pdigest = realloc(*pdigest, *pdigestlen);
91 if (*pdigest == NULL) {
92 int err = errno;
93 bam_print(gettext("realloc: %s\n"), strerror(err));
94 return (CKR_HOST_MEMORY);
97 rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
100 /* There was a read error */
101 if (nread == -1) {
102 bam_print(gettext(
103 "error reading file: %s\n"), strerror(saved_errno));
104 return (CKR_GENERAL_ERROR);
105 } else {
106 return (rv);
111 bootadm_digest(const char *filename, char **result)
113 int fd;
114 CK_RV rv;
115 CK_ULONG slotcount;
116 CK_SLOT_ID slotID;
117 CK_SLOT_ID_PTR pSlotList = NULL;
118 CK_MECHANISM_TYPE mech_type = CKM_SHA_1;
119 CK_MECHANISM_INFO info;
120 CK_MECHANISM mech;
121 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
122 CK_BYTE_PTR resultbuf = NULL;
123 CK_ULONG resultlen;
124 char *resultstr = NULL;
125 int resultstrlen;
126 int i, exitcode;
128 /* Initialize, and get list of slots */
129 rv = C_Initialize(NULL);
130 if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
131 bam_print(gettext(
132 "failed to initialize PKCS #11 framework: %s\n"),
133 pkcs11_strerror(rv));
134 return (BAM_ERROR);
137 /* Get slot count */
138 rv = C_GetSlotList(0, NULL, &slotcount);
139 if (rv != CKR_OK || slotcount == 0) {
140 bam_print(gettext(
141 "failed to find any cryptographic provider: %s\n"),
142 pkcs11_strerror(rv));
143 exitcode = BAM_ERROR;
144 goto cleanup;
147 /* Found at least one slot, allocate memory for slot list */
148 pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
149 if (pSlotList == NULL) {
150 bam_print(gettext("out of memory\n"));
151 exitcode = BAM_ERROR;
152 goto cleanup;
155 /* Get the list of slots */
156 if ((rv = C_GetSlotList(0, pSlotList, &slotcount)) != CKR_OK) {
157 bam_print(gettext(
158 "failed to find any cryptographic provider; "
159 "please check with your system administrator: %s\n"),
160 pkcs11_strerror(rv));
161 exitcode = BAM_ERROR;
162 goto cleanup;
165 /* Find a slot with matching mechanism */
166 for (i = 0; i < slotcount; i++) {
167 slotID = pSlotList[i];
168 rv = C_GetMechanismInfo(slotID, mech_type, &info);
169 if (rv != CKR_OK) {
170 continue; /* to the next slot */
171 } else {
172 if (info.flags & CKF_DIGEST)
173 break;
177 /* Show error if no matching mechanism found */
178 if (i == slotcount) {
179 bam_print(gettext("no cryptographic provider was "
180 "found for sha1\n"));
181 exitcode = BAM_ERROR;
182 goto cleanup;
185 /* Mechanism is supported. Go ahead & open a session */
186 rv = C_OpenSession(slotID, CKF_SERIAL_SESSION,
187 NULL, NULL, &hSession);
189 if (rv != CKR_OK) {
190 bam_print(gettext("can not open PKCS#11 session: %s\n"),
191 pkcs11_strerror(rv));
192 exitcode = BAM_ERROR;
193 goto cleanup;
196 /* Allocate a buffer to store result. */
197 resultlen = RESULTLEN;
198 if ((resultbuf = malloc(resultlen)) == NULL) {
199 bam_print(gettext("out of memory\n"));
200 exitcode = BAM_ERROR;
201 goto cleanup;
204 mech.mechanism = mech_type;
205 mech.pParameter = NULL;
206 mech.ulParameterLen = 0;
207 exitcode = BAM_SUCCESS;
209 if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
210 bam_print(gettext("can not open input file %s\n"), filename);
211 exitcode = BAM_ERROR;
212 goto cleanup;
215 rv = do_digest(hSession, &mech, fd, &resultbuf, &resultlen);
217 if (rv != CKR_OK) {
218 bam_print(gettext("crypto operation failed for "
219 "file %s: %s\n"), filename, pkcs11_strerror(rv));
220 exitcode = BAM_ERROR;
221 goto cleanup;
224 /* Allocate a buffer to store result string */
225 resultstrlen = 2 * resultlen + 1;
226 if ((resultstr = malloc(resultstrlen)) == NULL) {
227 bam_print(gettext("out of memory\n"));
228 exitcode = BAM_ERROR;
229 goto cleanup;
232 tohexstr(resultbuf, resultlen, resultstr, resultstrlen);
234 (void) close(fd);
235 cleanup:
236 if (exitcode == BAM_ERROR) {
237 free(resultstr);
238 resultstr = NULL;
241 free(resultbuf);
242 free(pSlotList);
244 if (hSession != CK_INVALID_HANDLE)
245 (void) C_CloseSession(hSession);
247 (void) C_Finalize(NULL);
249 *result = resultstr;
250 return (exitcode);