Skip to content

Commit 7a97605

Browse files
David WoodhouseDavid Woodhouse
David Woodhouse
authored and
David Woodhouse
committed
Accept PKCS#11 URIs as serialized token/certificate IDs
Signed-off-by: David Woodhouse <[email protected]>
1 parent 3e2c2bd commit 7a97605

File tree

1 file changed

+270
-28
lines changed

1 file changed

+270
-28
lines changed

lib/pkcs11h-serialization.c

Lines changed: 270 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,155 @@ pkcs11h_token_serializeTokenId (
150150
return rv;
151151
}
152152

153-
CK_RV
154-
pkcs11h_token_deserializeTokenId (
153+
static int hexnybble(char c)
154+
{
155+
if (c >= '0' || c <= '9')
156+
return c - '0';
157+
else if (c >= 'A' && c <= 'F')
158+
return c - 'A' + 10;
159+
else if (c >= 'a' && c <= 'f')
160+
return c - 'a' + 10;
161+
else return -1;
162+
}
163+
164+
static CK_RV parse_token_uri_attr (
165+
const char *uri,
166+
size_t urilen,
167+
char *tokstr,
168+
size_t toklen,
169+
size_t *parsed_len
170+
) {
171+
int n1, n2;
172+
size_t orig_toklen = toklen;
173+
174+
while (urilen && toklen > 1) {
175+
if (*uri == '%') {
176+
if (urilen < 3)
177+
return CKR_ATTRIBUTE_VALUE_INVALID;
178+
179+
n1 = hexnybble(uri[1]);
180+
n2 = hexnybble(uri[2]);
181+
if (n1 == -1 || n2 == -1)
182+
return CKR_ATTRIBUTE_VALUE_INVALID;
183+
184+
*tokstr = (n1 << 4) | n2;
185+
uri += 2;
186+
urilen -= 2;
187+
} else {
188+
*tokstr = *uri;
189+
}
190+
tokstr++;
191+
uri++;
192+
toklen--;
193+
urilen--;
194+
tokstr[1] = 0;
195+
}
196+
if (urilen)
197+
return CKR_ATTRIBUTE_VALUE_INVALID;
198+
199+
if (parsed_len)
200+
*parsed_len = orig_toklen - toklen;
201+
202+
return CKR_OK;
203+
}
204+
205+
static CK_RV parse_id_attr (
206+
const char *uri,
207+
size_t urilen,
208+
CK_BYTE_PTR *p_id,
209+
size_t *p_id_len
210+
) {
211+
CK_RV rv;
212+
213+
rv = _pkcs11h_mem_malloc ((void *)p_id, urilen + 1);
214+
if (rv != CKR_OK)
215+
return rv;
216+
217+
return parse_token_uri_attr (uri, urilen, (void *)*p_id, urilen + 1, p_id_len);
218+
}
219+
220+
static CK_RV parse_pkcs11_uri (
221+
OUT pkcs11h_token_id_t token_id,
222+
OUT pkcs11h_certificate_id_t certificate_id,
223+
IN const char * const sz
224+
) {
225+
const char *semicolon, *equals, *p;
226+
227+
_PKCS11H_ASSERT (token_id!=NULL);
228+
_PKCS11H_ASSERT (sz!=NULL);
229+
230+
if (strncmp (sz, "pkcs11:", 7))
231+
return CKR_ATTRIBUTE_VALUE_INVALID;
232+
233+
semicolon = sz + 6;
234+
while (semicolon[0] && semicolon[1]) {
235+
int keylen;
236+
237+
p = semicolon + 1;
238+
semicolon = strchr (p, ';');
239+
if (!semicolon)
240+
semicolon = p + strlen(p);
241+
242+
equals = strchr (p, '=');
243+
if (equals > semicolon)
244+
return CKR_ATTRIBUTE_VALUE_INVALID;
245+
246+
keylen = equals - p;
247+
248+
if (keylen == 5 && !strncmp(p, "model", 5) &&
249+
parse_token_uri_attr(equals + 1, semicolon - equals - 1,
250+
(char *)&token_id->model,
251+
sizeof(token_id->model),
252+
NULL) == CKR_OK)
253+
continue;
254+
else if (keylen == 5 && !strncmp(p, "token", 5) &&
255+
parse_token_uri_attr(equals + 1, semicolon - equals - 1,
256+
(char *)&token_id->label,
257+
sizeof(token_id->label),
258+
NULL) == CKR_OK)
259+
continue;
260+
else if (keylen == 12 && !strncmp(p, "manufacturer", 12) &&
261+
parse_token_uri_attr(equals + 1, semicolon - equals - 1,
262+
(char *)&token_id->manufacturerID,
263+
sizeof(token_id->manufacturerID),
264+
NULL) == CKR_OK)
265+
continue;
266+
else if (keylen == 6 && !strncmp(p, "serial", 6) &&
267+
parse_token_uri_attr(equals + 1, semicolon - equals - 1,
268+
(char *)&token_id->serialNumber,
269+
sizeof(token_id->serialNumber),
270+
NULL) == CKR_OK)
271+
continue;
272+
else if (certificate_id && keylen == 2 && !strncmp(p, "id", 2) &&
273+
parse_id_attr(equals + 1, semicolon - equals - 1,
274+
&certificate_id->attrCKA_ID,
275+
&certificate_id->attrCKA_ID_size) == CKR_OK)
276+
continue;
277+
/* We don't parse object= because the match code doesn't support
278+
matching by label. */
279+
280+
/* Failed to parse PKCS#11 URI element. */
281+
return CKR_ATTRIBUTE_VALUE_INVALID;
282+
}
283+
/* The matching code doesn't support support partial matches; it needs
284+
* *all* of manufacturer, model, serial and label attributes to be
285+
* defined. So reject partial URIs early instead of letting it do the
286+
* wrong thing. We can maybe improve this later. */
287+
if (!token_id->model[0] || !token_id->label[0] ||
288+
!token_id->manufacturerID[0] || !token_id->serialNumber[0]) {
289+
return CKR_ATTRIBUTE_VALUE_INVALID;
290+
}
291+
292+
/* For a certificate ID we need CKA_ID */
293+
if (certificate_id && !certificate_id->attrCKA_ID_size) {
294+
return CKR_ATTRIBUTE_VALUE_INVALID;
295+
}
296+
297+
return CKR_OK;
298+
}
299+
300+
static CK_RV
301+
pkcs11h_token_legacy_deserializeTokenId (
155302
OUT pkcs11h_token_id_t *p_token_id,
156303
IN const char * const sz
157304
) {
@@ -167,18 +314,6 @@ pkcs11h_token_deserializeTokenId (
167314
int e;
168315
CK_RV rv = CKR_FUNCTION_FAILED;
169316

170-
_PKCS11H_ASSERT (p_token_id!=NULL);
171-
_PKCS11H_ASSERT (sz!=NULL);
172-
173-
_PKCS11H_DEBUG (
174-
PKCS11H_LOG_DEBUG2,
175-
"PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
176-
(void *)p_token_id,
177-
sz
178-
);
179-
180-
*p_token_id = NULL;
181-
182317
if (
183318
(rv = _pkcs11h_mem_strdup (
184319
(void *)&_sz,
@@ -284,6 +419,70 @@ pkcs11h_token_deserializeTokenId (
284419
#undef __PKCS11H_TARGETS_NUMBER
285420
}
286421

422+
CK_RV
423+
pkcs11h_token_deserializeTokenId (
424+
OUT pkcs11h_token_id_t *p_token_id,
425+
IN const char * const sz
426+
) {
427+
#define __PKCS11H_TARGETS_NUMBER 4
428+
struct {
429+
char *p;
430+
size_t s;
431+
} targets[__PKCS11H_TARGETS_NUMBER];
432+
433+
pkcs11h_token_id_t token_id = NULL;
434+
CK_RV rv = CKR_FUNCTION_FAILED;
435+
436+
_PKCS11H_ASSERT (p_token_id!=NULL);
437+
_PKCS11H_ASSERT (sz!=NULL);
438+
439+
_PKCS11H_DEBUG (
440+
PKCS11H_LOG_DEBUG2,
441+
"PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
442+
(void *)p_token_id,
443+
sz
444+
);
445+
446+
*p_token_id = NULL;
447+
448+
if (strncmp (sz, "pkcs11:", 7))
449+
return pkcs11h_token_legacy_deserializeTokenId(p_token_id, sz);
450+
451+
if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) {
452+
goto cleanup;
453+
}
454+
455+
if ((rv = parse_pkcs11_uri(token_id, NULL, sz)) != CKR_OK) {
456+
goto cleanup;
457+
}
458+
459+
strncpy (
460+
token_id->display,
461+
token_id->label,
462+
sizeof (token_id->display)
463+
);
464+
465+
*p_token_id = token_id;
466+
token_id = NULL;
467+
468+
rv = CKR_OK;
469+
470+
cleanup:
471+
if (token_id != NULL) {
472+
pkcs11h_token_freeTokenId (token_id);
473+
}
474+
475+
_PKCS11H_DEBUG (
476+
PKCS11H_LOG_DEBUG2,
477+
"PKCS#11: pkcs11h_token_deserializeTokenId return rv=%lu-'%s'",
478+
rv,
479+
pkcs11h_getMessage (rv)
480+
);
481+
482+
return rv;
483+
#undef __PKCS11H_TARGETS_NUMBER
484+
}
485+
287486
#endif /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
288487

289488
#if defined(ENABLE_PKCS11H_CERTIFICATE)
@@ -360,8 +559,8 @@ pkcs11h_certificate_serializeCertificateId (
360559
return rv;
361560
}
362561

363-
CK_RV
364-
pkcs11h_certificate_deserializeCertificateId (
562+
static CK_RV
563+
pkcs11h_certificate_legacy_deserializeCertificateId (
365564
OUT pkcs11h_certificate_id_t * const p_certificate_id,
366565
IN const char * const sz
367566
) {
@@ -370,18 +569,6 @@ pkcs11h_certificate_deserializeCertificateId (
370569
char *p = NULL;
371570
char *_sz = NULL;
372571

373-
_PKCS11H_ASSERT (p_certificate_id!=NULL);
374-
_PKCS11H_ASSERT (sz!=NULL);
375-
376-
*p_certificate_id = NULL;
377-
378-
_PKCS11H_DEBUG (
379-
PKCS11H_LOG_DEBUG2,
380-
"PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
381-
(void *)p_certificate_id,
382-
sz
383-
);
384-
385572
if (
386573
(rv = _pkcs11h_mem_strdup (
387574
(void *)&_sz,
@@ -445,6 +632,61 @@ pkcs11h_certificate_deserializeCertificateId (
445632
_pkcs11h_mem_free ((void *)&_sz);
446633
}
447634

635+
_PKCS11H_DEBUG (
636+
PKCS11H_LOG_DEBUG2,
637+
"PKCS#11: pkcs11h_certificate_legacy_deserializeCertificateId return rv=%lu-'%s'",
638+
rv,
639+
pkcs11h_getMessage (rv)
640+
);
641+
642+
return rv;
643+
644+
}
645+
646+
CK_RV
647+
pkcs11h_certificate_deserializeCertificateId (
648+
OUT pkcs11h_certificate_id_t * const p_certificate_id,
649+
IN const char * const sz
650+
) {
651+
pkcs11h_certificate_id_t certificate_id = NULL;
652+
CK_RV rv = CKR_FUNCTION_FAILED;
653+
654+
_PKCS11H_ASSERT (p_certificate_id!=NULL);
655+
_PKCS11H_ASSERT (sz!=NULL);
656+
657+
*p_certificate_id = NULL;
658+
659+
_PKCS11H_DEBUG (
660+
PKCS11H_LOG_DEBUG2,
661+
"PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
662+
(void *)p_certificate_id,
663+
sz
664+
);
665+
666+
if (strncmp(sz, "pkcs11:", 7))
667+
return pkcs11h_certificate_legacy_deserializeCertificateId (p_certificate_id, sz);
668+
669+
if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) {
670+
goto cleanup;
671+
}
672+
if ((rv = _pkcs11h_token_newTokenId (&certificate_id->token_id)) != CKR_OK) {
673+
goto cleanup;
674+
}
675+
676+
if ((rv= parse_pkcs11_uri(certificate_id->token_id, certificate_id, sz)) != CKR_OK) {
677+
goto cleanup;
678+
}
679+
680+
*p_certificate_id = certificate_id;
681+
certificate_id = NULL;
682+
rv = CKR_OK;
683+
684+
cleanup:
685+
if (certificate_id != NULL) {
686+
pkcs11h_certificate_freeCertificateId (certificate_id);
687+
certificate_id = NULL;
688+
}
689+
448690
_PKCS11H_DEBUG (
449691
PKCS11H_LOG_DEBUG2,
450692
"PKCS#11: pkcs11h_certificate_deserializeCertificateId return rv=%lu-'%s'",

0 commit comments

Comments
 (0)