1*ccd81fddSJan Pechanec /* 2*ccd81fddSJan Pechanec * CDDL HEADER START 3*ccd81fddSJan Pechanec * 4*ccd81fddSJan Pechanec * The contents of this file are subject to the terms of the 5*ccd81fddSJan Pechanec * Common Development and Distribution License (the "License"). 6*ccd81fddSJan Pechanec * You may not use this file except in compliance with the License. 7*ccd81fddSJan Pechanec * 8*ccd81fddSJan Pechanec * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*ccd81fddSJan Pechanec * or http://www.opensolaris.org/os/licensing. 10*ccd81fddSJan Pechanec * See the License for the specific language governing permissions 11*ccd81fddSJan Pechanec * and limitations under the License. 12*ccd81fddSJan Pechanec * 13*ccd81fddSJan Pechanec * When distributing Covered Code, include this CDDL HEADER in each 14*ccd81fddSJan Pechanec * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*ccd81fddSJan Pechanec * If applicable, add the following below this CDDL HEADER, with the 16*ccd81fddSJan Pechanec * fields enclosed by brackets "[]" replaced with your own identifying 17*ccd81fddSJan Pechanec * information: Portions Copyright [yyyy] [name of copyright owner] 18*ccd81fddSJan Pechanec * 19*ccd81fddSJan Pechanec * CDDL HEADER END 20*ccd81fddSJan Pechanec * 21*ccd81fddSJan Pechanec * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 22*ccd81fddSJan Pechanec */ 23*ccd81fddSJan Pechanec 24*ccd81fddSJan Pechanec #include <stdio.h> 25*ccd81fddSJan Pechanec #include <stdlib.h> 26*ccd81fddSJan Pechanec #include <string.h> 27*ccd81fddSJan Pechanec #include <sys/types.h> 28*ccd81fddSJan Pechanec #include <sys/wait.h> 29*ccd81fddSJan Pechanec #include <unistd.h> 30*ccd81fddSJan Pechanec #include <strings.h> 31*ccd81fddSJan Pechanec #include <libgen.h> 32*ccd81fddSJan Pechanec #include <pthread.h> 33*ccd81fddSJan Pechanec 34*ccd81fddSJan Pechanec #include <security/cryptoki.h> 35*ccd81fddSJan Pechanec #include <security/pkcs11.h> 36*ccd81fddSJan Pechanec 37*ccd81fddSJan Pechanec #include <cryptoutil.h> 38*ccd81fddSJan Pechanec 39*ccd81fddSJan Pechanec /* PKCS#11 URI prefix and attributes. */ 40*ccd81fddSJan Pechanec #define PK11_URI_PREFIX "pkcs11:" 41*ccd81fddSJan Pechanec #define PK11_TOKEN "token" 42*ccd81fddSJan Pechanec #define PK11_MANUF "manufacturer" 43*ccd81fddSJan Pechanec #define PK11_SERIAL "serial" 44*ccd81fddSJan Pechanec #define PK11_MODEL "model" 45*ccd81fddSJan Pechanec #define PK11_OBJECT "object" 46*ccd81fddSJan Pechanec #define PK11_OBJECTTYPE "objecttype" 47*ccd81fddSJan Pechanec #define PK11_ID "id" 48*ccd81fddSJan Pechanec #define PK11_PINFILE "pinfile" 49*ccd81fddSJan Pechanec 50*ccd81fddSJan Pechanec /* 51*ccd81fddSJan Pechanec * Gets a hexadecimal string of the xx:xx:xx-like format and fills the output 52*ccd81fddSJan Pechanec * buffer with bytes represeting each of the hexadecimal numbers. Returns 0 on 53*ccd81fddSJan Pechanec * error (missing ':', not a hexadecimal character (eg. 'z'), output buffer 54*ccd81fddSJan Pechanec * overflow, etc.), or the number of hexadecimal numbers processed. 55*ccd81fddSJan Pechanec * 56*ccd81fddSJan Pechanec * Returns: 57*ccd81fddSJan Pechanec * 0 58*ccd81fddSJan Pechanec * on failure 59*ccd81fddSJan Pechanec * >0 60*ccd81fddSJan Pechanec * number of bytes returned via the output parameter 61*ccd81fddSJan Pechanec */ 62*ccd81fddSJan Pechanec static int 63*ccd81fddSJan Pechanec read_id(char *str, unsigned char *output, int out_len) 64*ccd81fddSJan Pechanec { 65*ccd81fddSJan Pechanec int i, len, n; 66*ccd81fddSJan Pechanec unsigned int x1, x2; 67*ccd81fddSJan Pechanec 68*ccd81fddSJan Pechanec len = strlen(str); 69*ccd81fddSJan Pechanec (void) memset(output, 0, out_len); 70*ccd81fddSJan Pechanec /* Counter of the processed bytes. */ 71*ccd81fddSJan Pechanec i = 0; 72*ccd81fddSJan Pechanec /* Counter for the used output bytes. */ 73*ccd81fddSJan Pechanec n = 0; 74*ccd81fddSJan Pechanec 75*ccd81fddSJan Pechanec while (i < len) { 76*ccd81fddSJan Pechanec /* We require at least one hexadecimal character. */ 77*ccd81fddSJan Pechanec if (sscanf(str + i, "%1x", &x1) != 1) 78*ccd81fddSJan Pechanec return (0); 79*ccd81fddSJan Pechanec ++i; 80*ccd81fddSJan Pechanec /* And we accept the 2nd one if it is there. */ 81*ccd81fddSJan Pechanec if (sscanf(str + i, "%1x", &x2) == 1) { 82*ccd81fddSJan Pechanec x1 = x1 * 16 + x2; 83*ccd81fddSJan Pechanec ++i; 84*ccd81fddSJan Pechanec } 85*ccd81fddSJan Pechanec 86*ccd81fddSJan Pechanec /* Output buffer overflow? */ 87*ccd81fddSJan Pechanec if ((n + 1) > out_len) 88*ccd81fddSJan Pechanec return (0); 89*ccd81fddSJan Pechanec output[n] = (unsigned char)x1; 90*ccd81fddSJan Pechanec /* Still some bytes to process? */ 91*ccd81fddSJan Pechanec if (i < len) { 92*ccd81fddSJan Pechanec /* ':' is the only acceptable delimiter. */ 93*ccd81fddSJan Pechanec if (str[i] != ':') 94*ccd81fddSJan Pechanec return (0); 95*ccd81fddSJan Pechanec /* Skip ':' */ 96*ccd81fddSJan Pechanec ++i; 97*ccd81fddSJan Pechanec } 98*ccd81fddSJan Pechanec ++n; 99*ccd81fddSJan Pechanec } 100*ccd81fddSJan Pechanec 101*ccd81fddSJan Pechanec return (n); 102*ccd81fddSJan Pechanec } 103*ccd81fddSJan Pechanec 104*ccd81fddSJan Pechanec /* 105*ccd81fddSJan Pechanec * Process the PKCS#11 URI. The function expects an allocated URI structure. The 106*ccd81fddSJan Pechanec * caller is later expected to call pkcs11_free_uri() when the parsed URI is no 107*ccd81fddSJan Pechanec * longer needed. 108*ccd81fddSJan Pechanec * 109*ccd81fddSJan Pechanec * Returns: 110*ccd81fddSJan Pechanec * PK11_URI_OK 111*ccd81fddSJan Pechanec * success 112*ccd81fddSJan Pechanec * PK11_URI_INVALID 113*ccd81fddSJan Pechanec * invalid PKCS#11 URI (one that has the "pkcs11:" prefix but is 114*ccd81fddSJan Pechanec * otherwise incorrectly specified) 115*ccd81fddSJan Pechanec * PK11_MALLOC_ERROR 116*ccd81fddSJan Pechanec * malloc(3C) failed when allocating one of the internal buffers 117*ccd81fddSJan Pechanec * PK11_URI_VALUE_OVERFLOW 118*ccd81fddSJan Pechanec * some attributes in the URI are of the fixed length accroding to 119*ccd81fddSJan Pechanec * the spec. If any of those attributes overflows we report an 120*ccd81fddSJan Pechanec * error 121*ccd81fddSJan Pechanec * PK11_NOT_PKCS11_URI 122*ccd81fddSJan Pechanec * the URI supplied is not the PKCS#11 URI at all (does not have 123*ccd81fddSJan Pechanec * the "pkcs11:" prefix) 124*ccd81fddSJan Pechanec */ 125*ccd81fddSJan Pechanec int 126*ccd81fddSJan Pechanec pkcs11_parse_uri(const char *str, pkcs11_uri_t *uri) 127*ccd81fddSJan Pechanec { 128*ccd81fddSJan Pechanec char *str2, *l1, *l2, *tok, *name; 129*ccd81fddSJan Pechanec 130*ccd81fddSJan Pechanec /* Initialize the structure. */ 131*ccd81fddSJan Pechanec (void) memset(uri, 0, sizeof (pkcs11_uri_t)); 132*ccd81fddSJan Pechanec /* Be really safe. */ 133*ccd81fddSJan Pechanec uri->objecttype_present = B_FALSE; 134*ccd81fddSJan Pechanec 135*ccd81fddSJan Pechanec /* Check that we have the correct PKCS#11 URI prefix. */ 136*ccd81fddSJan Pechanec if (strncmp(str, PK11_URI_PREFIX, strlen(PK11_URI_PREFIX)) != 0) 137*ccd81fddSJan Pechanec return (PK11_NOT_PKCS11_URI); 138*ccd81fddSJan Pechanec /* Dup the string and skip over the prefix then. */ 139*ccd81fddSJan Pechanec if ((str2 = strdup(str + strlen(PK11_URI_PREFIX))) == NULL) 140*ccd81fddSJan Pechanec return (PK11_MALLOC_ERROR); 141*ccd81fddSJan Pechanec 142*ccd81fddSJan Pechanec /* 143*ccd81fddSJan Pechanec * Using strtok_r() would silently skip over multiple semicolons. We 144*ccd81fddSJan Pechanec * must check such situation before moving on. We must also avoid ';' as 145*ccd81fddSJan Pechanec * the first and the last character of the URI. 146*ccd81fddSJan Pechanec */ 147*ccd81fddSJan Pechanec if (strstr(str2, ";;") != NULL || str2[0] == ';' || 148*ccd81fddSJan Pechanec (strlen(str2) > 0 && str2[strlen(str2) - 1] == ';')) 149*ccd81fddSJan Pechanec goto bad_uri; 150*ccd81fddSJan Pechanec 151*ccd81fddSJan Pechanec /* Now parse the URI. */ 152*ccd81fddSJan Pechanec tok = strtok_r(str2, ";", &l1); 153*ccd81fddSJan Pechanec for (; tok != NULL; tok = strtok_r(NULL, ";", &l1)) { 154*ccd81fddSJan Pechanec /* "tok" is not empty so there will be something in "name". */ 155*ccd81fddSJan Pechanec name = strtok_r(tok, "=", &l2); 156*ccd81fddSJan Pechanec /* Check whether there is '=' at all. */ 157*ccd81fddSJan Pechanec if (l2 == NULL) 158*ccd81fddSJan Pechanec goto bad_uri; 159*ccd81fddSJan Pechanec 160*ccd81fddSJan Pechanec /* 161*ccd81fddSJan Pechanec * Fill out the URI structure. We do not accept duplicate 162*ccd81fddSJan Pechanec * attributes. 163*ccd81fddSJan Pechanec */ 164*ccd81fddSJan Pechanec if (strcmp(name, PK11_TOKEN) == 0) { 165*ccd81fddSJan Pechanec /* Check for duplicity. */ 166*ccd81fddSJan Pechanec if (uri->token != NULL) 167*ccd81fddSJan Pechanec goto bad_uri; 168*ccd81fddSJan Pechanec if (strlen(l2) > 32) 169*ccd81fddSJan Pechanec goto value_overflow; 170*ccd81fddSJan Pechanec if ((uri->token = (unsigned char *)strdup(l2)) == NULL) 171*ccd81fddSJan Pechanec goto malloc_failed; 172*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_MANUF) == 0) { 173*ccd81fddSJan Pechanec /* Check for duplicity. */ 174*ccd81fddSJan Pechanec if (uri->manuf != NULL) 175*ccd81fddSJan Pechanec goto bad_uri; 176*ccd81fddSJan Pechanec if (strlen(l2) > 32) 177*ccd81fddSJan Pechanec goto value_overflow; 178*ccd81fddSJan Pechanec if ((uri->manuf = (unsigned char *)strdup(l2)) == NULL) 179*ccd81fddSJan Pechanec goto malloc_failed; 180*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_SERIAL) == 0) { 181*ccd81fddSJan Pechanec /* Check for duplicity. */ 182*ccd81fddSJan Pechanec if (uri->serial != NULL) 183*ccd81fddSJan Pechanec goto bad_uri; 184*ccd81fddSJan Pechanec if (strlen(l2) > 16) 185*ccd81fddSJan Pechanec goto value_overflow; 186*ccd81fddSJan Pechanec if ((uri->serial = (unsigned char *)strdup(l2)) == NULL) 187*ccd81fddSJan Pechanec goto malloc_failed; 188*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_MODEL) == 0) { 189*ccd81fddSJan Pechanec /* Check for duplicity. */ 190*ccd81fddSJan Pechanec if (uri->model != NULL) 191*ccd81fddSJan Pechanec goto bad_uri; 192*ccd81fddSJan Pechanec if (strlen(l2) > 16) 193*ccd81fddSJan Pechanec goto value_overflow; 194*ccd81fddSJan Pechanec if ((uri->model = (unsigned char *)strdup(l2)) == NULL) 195*ccd81fddSJan Pechanec goto malloc_failed; 196*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_ID) == 0) { 197*ccd81fddSJan Pechanec /* Check for duplicity. */ 198*ccd81fddSJan Pechanec if (uri->id_len != 0) 199*ccd81fddSJan Pechanec goto bad_uri; 200*ccd81fddSJan Pechanec /* 201*ccd81fddSJan Pechanec * We can have maximum of PK11_MAX_ID_LEN 2-byte 202*ccd81fddSJan Pechanec * numbers separated by ':'s, like 203*ccd81fddSJan Pechanec * 01:02:0A:FF:... 204*ccd81fddSJan Pechanec */ 205*ccd81fddSJan Pechanec if (strlen(l2) > PK11_MAX_ID_LEN * 2 + 206*ccd81fddSJan Pechanec PK11_MAX_ID_LEN - 1) { 207*ccd81fddSJan Pechanec goto value_overflow; 208*ccd81fddSJan Pechanec } 209*ccd81fddSJan Pechanec if ((uri->id = malloc(PK11_MAX_ID_LEN)) == NULL) 210*ccd81fddSJan Pechanec goto malloc_failed; 211*ccd81fddSJan Pechanec uri->id_len = read_id(l2, uri->id, 212*ccd81fddSJan Pechanec PK11_MAX_ID_LEN); 213*ccd81fddSJan Pechanec if (uri->id_len == 0) 214*ccd81fddSJan Pechanec goto bad_uri; 215*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_OBJECT) == 0) { 216*ccd81fddSJan Pechanec /* Check for duplicity. */ 217*ccd81fddSJan Pechanec if (uri->object != NULL) 218*ccd81fddSJan Pechanec goto bad_uri; 219*ccd81fddSJan Pechanec if (strlen(l2) > PK11_MAX_OBJECT_LEN) 220*ccd81fddSJan Pechanec goto value_overflow; 221*ccd81fddSJan Pechanec if ((uri->object = (unsigned char *)strdup(l2)) == NULL) 222*ccd81fddSJan Pechanec goto malloc_failed; 223*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_OBJECTTYPE) == 0) { 224*ccd81fddSJan Pechanec /* 225*ccd81fddSJan Pechanec * Check for duplicity. objecttype can not be empty, it 226*ccd81fddSJan Pechanec * would not make sense. 227*ccd81fddSJan Pechanec */ 228*ccd81fddSJan Pechanec if (uri->objecttype_present == CK_TRUE) 229*ccd81fddSJan Pechanec goto bad_uri; 230*ccd81fddSJan Pechanec if (strcmp(l2, "public") == 0) 231*ccd81fddSJan Pechanec uri->objecttype = CKO_PUBLIC_KEY; 232*ccd81fddSJan Pechanec else if (strcmp(l2, "private") == 0) 233*ccd81fddSJan Pechanec uri->objecttype = CKO_PRIVATE_KEY; 234*ccd81fddSJan Pechanec else if (strcmp(l2, "cert") == 0) 235*ccd81fddSJan Pechanec uri->objecttype = CKO_CERTIFICATE; 236*ccd81fddSJan Pechanec else if (strcmp(l2, "secretkey") == 0) 237*ccd81fddSJan Pechanec uri->objecttype = CKO_SECRET_KEY; 238*ccd81fddSJan Pechanec else if (strcmp(l2, "data") == 0) 239*ccd81fddSJan Pechanec uri->objecttype = CKO_DATA; 240*ccd81fddSJan Pechanec else 241*ccd81fddSJan Pechanec goto bad_uri; 242*ccd81fddSJan Pechanec uri->objecttype_present = CK_TRUE; 243*ccd81fddSJan Pechanec } else if (strcmp(name, PK11_PINFILE) == 0) 244*ccd81fddSJan Pechanec /* Check for duplicity. */ 245*ccd81fddSJan Pechanec if (uri->pinfile == NULL) { 246*ccd81fddSJan Pechanec if (strlen(l2) > MAXPATHLEN) 247*ccd81fddSJan Pechanec goto value_overflow; 248*ccd81fddSJan Pechanec if ((uri->pinfile = strdup(l2)) == NULL) 249*ccd81fddSJan Pechanec goto malloc_failed; 250*ccd81fddSJan Pechanec /* Empty pinfile makes no sense. */ 251*ccd81fddSJan Pechanec if (uri->pinfile[0] == '\0') 252*ccd81fddSJan Pechanec goto bad_uri; 253*ccd81fddSJan Pechanec } else 254*ccd81fddSJan Pechanec goto bad_uri; 255*ccd81fddSJan Pechanec else 256*ccd81fddSJan Pechanec /* Unknown attribute name. */ 257*ccd81fddSJan Pechanec goto bad_uri; 258*ccd81fddSJan Pechanec } 259*ccd81fddSJan Pechanec 260*ccd81fddSJan Pechanec free(str2); 261*ccd81fddSJan Pechanec return (PK11_URI_OK); 262*ccd81fddSJan Pechanec malloc_failed: 263*ccd81fddSJan Pechanec free(str2); 264*ccd81fddSJan Pechanec pkcs11_free_uri(uri); 265*ccd81fddSJan Pechanec return (PK11_MALLOC_ERROR); 266*ccd81fddSJan Pechanec bad_uri: 267*ccd81fddSJan Pechanec free(str2); 268*ccd81fddSJan Pechanec pkcs11_free_uri(uri); 269*ccd81fddSJan Pechanec return (PK11_URI_INVALID); 270*ccd81fddSJan Pechanec value_overflow: 271*ccd81fddSJan Pechanec free(str2); 272*ccd81fddSJan Pechanec pkcs11_free_uri(uri); 273*ccd81fddSJan Pechanec return (PK11_URI_VALUE_OVERFLOW); 274*ccd81fddSJan Pechanec } 275*ccd81fddSJan Pechanec 276*ccd81fddSJan Pechanec /* 277*ccd81fddSJan Pechanec * Free the PKCS#11 URI structure attributes but do not free the structure 278*ccd81fddSJan Pechanec * itself. 279*ccd81fddSJan Pechanec */ 280*ccd81fddSJan Pechanec void 281*ccd81fddSJan Pechanec pkcs11_free_uri(pkcs11_uri_t *uri) 282*ccd81fddSJan Pechanec { 283*ccd81fddSJan Pechanec if (uri->object != NULL) 284*ccd81fddSJan Pechanec free(uri->object); 285*ccd81fddSJan Pechanec if (uri->token != NULL) 286*ccd81fddSJan Pechanec free(uri->token); 287*ccd81fddSJan Pechanec if (uri->manuf != NULL) 288*ccd81fddSJan Pechanec free(uri->manuf); 289*ccd81fddSJan Pechanec if (uri->serial != NULL) 290*ccd81fddSJan Pechanec free(uri->serial); 291*ccd81fddSJan Pechanec if (uri->model != NULL) 292*ccd81fddSJan Pechanec free(uri->model); 293*ccd81fddSJan Pechanec if (uri->id != NULL) 294*ccd81fddSJan Pechanec free(uri->id); 295*ccd81fddSJan Pechanec if (uri->pinfile != NULL) 296*ccd81fddSJan Pechanec free(uri->pinfile); 297*ccd81fddSJan Pechanec } 298