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