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