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
read_id(char * str,unsigned char * output,int out_len)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
pkcs11_parse_uri(const char * str,pkcs11_uri_t * uri)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
pkcs11_free_uri(pkcs11_uri_t * uri)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