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]
21 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <sys/types.h>
34 #include <security/cryptoki.h>
35 #include <security/pkcs11.h>
37 #include <cryptoutil.h>
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"
48 #define PK11_PINFILE "pinfile"
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.
60 * number of bytes returned via the output parameter
63 read_id(char *str
, unsigned char *output
, int out_len
)
69 (void) memset(output
, 0, out_len
);
70 /* Counter of the processed bytes. */
72 /* Counter for the used output bytes. */
76 /* We require at least one hexadecimal character. */
77 if (sscanf(str
+ i
, "%1x", &x1
) != 1)
80 /* And we accept the 2nd one if it is there. */
81 if (sscanf(str
+ i
, "%1x", &x2
) == 1) {
86 /* Output buffer overflow? */
87 if ((n
+ 1) > out_len
)
89 output
[n
] = (unsigned char)x1
;
90 /* Still some bytes to process? */
92 /* ':' is the only acceptable delimiter. */
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
113 * invalid PKCS#11 URI (one that has the "pkcs11:" prefix but is
114 * otherwise incorrectly specified)
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
121 * PK11_NOT_PKCS11_URI
122 * the URI supplied is not the PKCS#11 URI at all (does not have
123 * the "pkcs11:" prefix)
126 pkcs11_parse_uri(const char *str
, pkcs11_uri_t
*uri
)
128 char *str2
, *l1
, *l2
, *tok
, *name
;
130 /* Initialize the structure. */
131 (void) memset(uri
, 0, sizeof (pkcs11_uri_t
));
132 /* Be really safe. */
133 uri
->objecttype_present
= B_FALSE
;
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
);
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.
147 if (strstr(str2
, ";;") != NULL
|| str2
[0] == ';' ||
148 (strlen(str2
) > 0 && str2
[strlen(str2
) - 1] == ';'))
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. */
161 * Fill out the URI structure. We do not accept duplicate
164 if (strcmp(name
, PK11_TOKEN
) == 0) {
165 /* Check for duplicity. */
166 if (uri
->token
!= NULL
)
170 if ((uri
->token
= (unsigned char *)strdup(l2
)) == NULL
)
172 } else if (strcmp(name
, PK11_MANUF
) == 0) {
173 /* Check for duplicity. */
174 if (uri
->manuf
!= NULL
)
178 if ((uri
->manuf
= (unsigned char *)strdup(l2
)) == NULL
)
180 } else if (strcmp(name
, PK11_SERIAL
) == 0) {
181 /* Check for duplicity. */
182 if (uri
->serial
!= NULL
)
186 if ((uri
->serial
= (unsigned char *)strdup(l2
)) == NULL
)
188 } else if (strcmp(name
, PK11_MODEL
) == 0) {
189 /* Check for duplicity. */
190 if (uri
->model
!= NULL
)
194 if ((uri
->model
= (unsigned char *)strdup(l2
)) == NULL
)
196 } else if (strcmp(name
, PK11_ID
) == 0) {
197 /* Check for duplicity. */
198 if (uri
->id_len
!= 0)
201 * We can have maximum of PK11_MAX_ID_LEN 2-byte
202 * numbers separated by ':'s, like
205 if (strlen(l2
) > PK11_MAX_ID_LEN
* 2 +
206 PK11_MAX_ID_LEN
- 1) {
209 if ((uri
->id
= malloc(PK11_MAX_ID_LEN
)) == NULL
)
211 uri
->id_len
= read_id(l2
, uri
->id
,
213 if (uri
->id_len
== 0)
215 } else if (strcmp(name
, PK11_OBJECT
) == 0) {
216 /* Check for duplicity. */
217 if (uri
->object
!= NULL
)
219 if (strlen(l2
) > PK11_MAX_OBJECT_LEN
)
221 if ((uri
->object
= (unsigned char *)strdup(l2
)) == NULL
)
223 } else if (strcmp(name
, PK11_OBJECTTYPE
) == 0) {
225 * Check for duplicity. objecttype can not be empty, it
226 * would not make sense.
228 if (uri
->objecttype_present
== CK_TRUE
)
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
;
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
)
248 if ((uri
->pinfile
= strdup(l2
)) == NULL
)
250 /* Empty pinfile makes no sense. */
251 if (uri
->pinfile
[0] == '\0')
256 /* Unknown attribute name. */
261 return (PK11_URI_OK
);
264 pkcs11_free_uri(uri
);
265 return (PK11_MALLOC_ERROR
);
268 pkcs11_free_uri(uri
);
269 return (PK11_URI_INVALID
);
272 pkcs11_free_uri(uri
);
273 return (PK11_URI_VALUE_OVERFLOW
);
277 * Free the PKCS#11 URI structure attributes but do not free the structure
281 pkcs11_free_uri(pkcs11_uri_t
*uri
)