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]
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.
36 #include <sys/types.h>
39 #include <security/cryptoki.h>
40 #include <cryptoutil.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.
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
59 do_digest(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pmech
,
60 int fd
, CK_BYTE_PTR
*pdigest
, CK_ULONG_PTR pdigestlen
)
66 if ((rv
= C_DigestInit(hSession
, pmech
)) != CKR_OK
) {
70 while ((nread
= read(fd
, buf
, sizeof (buf
))) > 0) {
72 rv
= C_DigestUpdate(hSession
, buf
, (CK_ULONG
)nread
);
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
) {
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 */
103 "error reading file: %s\n"), strerror(saved_errno
));
104 return (CKR_GENERAL_ERROR
);
111 bootadm_digest(const char *filename
, char **result
)
117 CK_SLOT_ID_PTR pSlotList
= NULL
;
118 CK_MECHANISM_TYPE mech_type
= CKM_SHA_1
;
119 CK_MECHANISM_INFO info
;
121 CK_SESSION_HANDLE hSession
= CK_INVALID_HANDLE
;
122 CK_BYTE_PTR resultbuf
= NULL
;
124 char *resultstr
= NULL
;
128 /* Initialize, and get list of slots */
129 rv
= C_Initialize(NULL
);
130 if (rv
!= CKR_OK
&& rv
!= CKR_CRYPTOKI_ALREADY_INITIALIZED
) {
132 "failed to initialize PKCS #11 framework: %s\n"),
133 pkcs11_strerror(rv
));
138 rv
= C_GetSlotList(0, NULL
, &slotcount
);
139 if (rv
!= CKR_OK
|| slotcount
== 0) {
141 "failed to find any cryptographic provider: %s\n"),
142 pkcs11_strerror(rv
));
143 exitcode
= BAM_ERROR
;
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
;
155 /* Get the list of slots */
156 if ((rv
= C_GetSlotList(0, pSlotList
, &slotcount
)) != CKR_OK
) {
158 "failed to find any cryptographic provider; "
159 "please check with your system administrator: %s\n"),
160 pkcs11_strerror(rv
));
161 exitcode
= BAM_ERROR
;
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
);
170 continue; /* to the next slot */
172 if (info
.flags
& CKF_DIGEST
)
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
;
185 /* Mechanism is supported. Go ahead & open a session */
186 rv
= C_OpenSession(slotID
, CKF_SERIAL_SESSION
,
187 NULL
, NULL
, &hSession
);
190 bam_print(gettext("can not open PKCS#11 session: %s\n"),
191 pkcs11_strerror(rv
));
192 exitcode
= BAM_ERROR
;
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
;
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
;
215 rv
= do_digest(hSession
, &mech
, fd
, &resultbuf
, &resultlen
);
218 bam_print(gettext("crypto operation failed for "
219 "file %s: %s\n"), filename
, pkcs11_strerror(rv
));
220 exitcode
= BAM_ERROR
;
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
;
232 tohexstr(resultbuf
, resultlen
, resultstr
, resultstrlen
);
236 if (exitcode
== BAM_ERROR
) {
244 if (hSession
!= CK_INVALID_HANDLE
)
245 (void) C_CloseSession(hSession
);
247 (void) C_Finalize(NULL
);