1 /*
2  * Copyright (C) 2012 Red Hat Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *     * Redistributions of source code must retain the above
9  *       copyright notice, this list of conditions and the
10  *       following disclaimer.
11  *     * Redistributions in binary form must reproduce the
12  *       above copyright notice, this list of conditions and
13  *       the following disclaimer in the documentation and/or
14  *       other materials provided with the distribution.
15  *     * The names of contributors to this software may not be
16  *       used to endorse or promote products derived from this
17  *       software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30  * DAMAGE.
31  *
32  * Author: Stef Walter <stefw@redhat.com>
33  */
34 
35 #include "config.h"
36 
37 #include "array.h"
38 #include "asn1.h"
39 #include "attrs.h"
40 #define P11_DEBUG_FLAG P11_DEBUG_TRUST
41 #include "debug.h"
42 #include "dict.h"
43 #include "digest.h"
44 #include "message.h"
45 #include "module.h"
46 #include "oid.h"
47 #include "parser.h"
48 #include "path.h"
49 #include "pem.h"
50 #include "pkcs11x.h"
51 #include "persist.h"
52 #include "types.h"
53 #include "x509.h"
54 
55 #include <libtasn1.h>
56 
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 
60 #include <assert.h>
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <unistd.h>
67 
68 #ifdef ENABLE_NLS
69 #include <libintl.h>
70 #define _(x) dgettext(PACKAGE_NAME, x)
71 #else
72 #define _(x) (x)
73 #endif
74 
75 struct _p11_parser {
76 	p11_asn1_cache *asn1_cache;
77 	p11_dict *asn1_defs;
78 	bool asn1_owned;
79 	p11_persist *persist;
80 	char *basename;
81 	p11_array *parsed;
82 	p11_array *formats;
83 	int flags;
84 };
85 
86 #define ID_LENGTH P11_DIGEST_SHA1_LEN
87 
88 typedef int (* parser_func)   (p11_parser *parser,
89                                const unsigned char *data,
90                                size_t length);
91 
92 static CK_ATTRIBUTE *
populate_trust(p11_parser * parser,CK_ATTRIBUTE * attrs)93 populate_trust (p11_parser *parser,
94                 CK_ATTRIBUTE *attrs)
95 {
96 	CK_BBOOL trustedv;
97 	CK_BBOOL distrustv;
98 
99 	CK_ATTRIBUTE trusted = { CKA_TRUSTED, &trustedv, sizeof (trustedv) };
100 	CK_ATTRIBUTE distrust = { CKA_X_DISTRUSTED, &distrustv, sizeof (distrustv) };
101 
102 	/*
103 	 * If we're are parsing an anchor location, then warn about any ditsrusted
104 	 * certificates there, but don't go ahead and automatically make them
105 	 * trusted anchors.
106 	 */
107 	if (parser->flags & P11_PARSE_FLAG_ANCHOR) {
108 		if (p11_attrs_find_bool (attrs, CKA_X_DISTRUSTED, &distrustv) && distrustv) {
109 			p11_message (_("certificate with distrust in location for anchors: %s"), parser->basename);
110 			return attrs;
111 
112 		}
113 
114 		trustedv = CK_TRUE;
115 		distrustv = CK_FALSE;
116 
117 	/*
118 	 * If we're parsing a blocklist location, then force all certificates to
119 	 * be distrusted, regardless of whether they contain anchor information.
120 	 */
121 	} else if (parser->flags & P11_PARSE_FLAG_BLOCKLIST) {
122 		if (p11_attrs_find_bool (attrs, CKA_TRUSTED, &trustedv) && trustedv)
123 			p11_message (_("overriding trust for anchor in blocklist: %s"), parser->basename);
124 
125 		trustedv = CK_FALSE;
126 		distrustv = CK_TRUE;
127 
128 	/*
129 	 * If the location doesn't have a flag, then fill in trust attributes
130 	 * if they are missing: neither an anchor or blocklist.
131 	 */
132 	} else {
133 		trustedv = CK_FALSE;
134 		distrustv = CK_FALSE;
135 
136 		if (p11_attrs_find_valid (attrs, CKA_TRUSTED))
137 			trusted.type = CKA_INVALID;
138 		if (p11_attrs_find_valid (attrs, CKA_X_DISTRUSTED))
139 			distrust.type = CKA_INVALID;
140 	}
141 
142 	return p11_attrs_build (attrs, &trusted, &distrust, NULL);
143 }
144 
145 static void
sink_object(p11_parser * parser,CK_ATTRIBUTE * attrs)146 sink_object (p11_parser *parser,
147              CK_ATTRIBUTE *attrs)
148 {
149 	CK_OBJECT_CLASS klass;
150 
151 	if (p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
152 	    klass == CKO_CERTIFICATE) {
153 		attrs = populate_trust (parser, attrs);
154 		return_if_fail (attrs != NULL);
155 	}
156 
157 	if (!p11_array_push (parser->parsed, attrs))
158 		return_if_reached ();
159 }
160 
161 static CK_ATTRIBUTE *
certificate_attrs(p11_parser * parser,const unsigned char * der,size_t der_len)162 certificate_attrs (p11_parser *parser,
163                    const unsigned char *der,
164                    size_t der_len)
165 {
166 	CK_OBJECT_CLASS klassv = CKO_CERTIFICATE;
167 	CK_CERTIFICATE_TYPE x509 = CKC_X_509;
168 	CK_BBOOL modifiablev = CK_FALSE;
169 
170 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
171 	CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
172 	CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) };
173 	CK_ATTRIBUTE value = { CKA_VALUE, (void *)der, der_len };
174 
175 	return p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, NULL);
176 }
177 
178 int
p11_parser_format_x509(p11_parser * parser,const unsigned char * data,size_t length)179 p11_parser_format_x509 (p11_parser *parser,
180                         const unsigned char *data,
181                         size_t length)
182 {
183 	char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
184 	CK_ATTRIBUTE *attrs;
185 	CK_ATTRIBUTE *value;
186 	node_asn *cert;
187 
188 	cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, length, message);
189 	if (cert == NULL)
190 		return P11_PARSE_UNRECOGNIZED;
191 
192 	attrs = certificate_attrs (parser, data, length);
193 	return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
194 
195 	value = p11_attrs_find_valid (attrs, CKA_VALUE);
196 	return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
197 	p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
198 	                     value->pValue, value->ulValueLen);
199 
200 	sink_object (parser, attrs);
201 	return P11_PARSE_SUCCESS;
202 }
203 
204 static CK_ATTRIBUTE *
extension_attrs(p11_parser * parser,CK_ATTRIBUTE * public_key_info,const char * oid_str,const unsigned char * oid_der,bool critical,const unsigned char * value,int length)205 extension_attrs (p11_parser *parser,
206                  CK_ATTRIBUTE *public_key_info,
207                  const char *oid_str,
208                  const unsigned char *oid_der,
209                  bool critical,
210                  const unsigned char *value,
211                  int length)
212 {
213 	CK_OBJECT_CLASS klassv = CKO_X_CERTIFICATE_EXTENSION;
214 	CK_BBOOL modifiablev = CK_FALSE;
215 
216 	CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
217 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
218 	CK_ATTRIBUTE oid = { CKA_OBJECT_ID, (void *)oid_der, p11_oid_length (oid_der) };
219 
220 	CK_ATTRIBUTE *attrs;
221 	node_asn *dest;
222 	unsigned char *der;
223 	size_t len;
224 	int ret;
225 
226 	attrs = p11_attrs_build (NULL, public_key_info, &klass, &modifiable, &oid, NULL);
227 	return_val_if_fail (attrs != NULL, NULL);
228 
229 	dest = p11_asn1_create (parser->asn1_defs, "PKIX1.Extension");
230 	return_val_if_fail (dest != NULL, NULL);
231 
232 	ret = asn1_write_value (dest, "extnID", oid_str, 1);
233 	return_val_if_fail (ret == ASN1_SUCCESS, NULL);
234 
235 	if (critical)
236 		ret = asn1_write_value (dest, "critical", "TRUE", 1);
237 	return_val_if_fail (ret == ASN1_SUCCESS, NULL);
238 
239 	ret = asn1_write_value (dest, "extnValue", value, length);
240 	return_val_if_fail (ret == ASN1_SUCCESS, NULL);
241 
242 	der = p11_asn1_encode (dest, &len);
243 	return_val_if_fail (der != NULL, NULL);
244 
245 	attrs = p11_attrs_take (attrs, CKA_VALUE, der, len);
246 	return_val_if_fail (attrs != NULL, NULL);
247 
248 	/* An opmitization so that the builder can get at this without parsing */
249 	p11_asn1_cache_take (parser->asn1_cache, dest, "PKIX1.Extension", der, len);
250 	return attrs;
251 }
252 
253 static CK_ATTRIBUTE *
attached_attrs(p11_parser * parser,CK_ATTRIBUTE * public_key_info,const char * oid_str,const unsigned char * oid_der,bool critical,node_asn * ext)254 attached_attrs (p11_parser *parser,
255                 CK_ATTRIBUTE *public_key_info,
256                 const char *oid_str,
257                 const unsigned char *oid_der,
258                 bool critical,
259                 node_asn *ext)
260 {
261 	CK_ATTRIBUTE *attrs;
262 	unsigned char *der;
263 	size_t len;
264 
265 	der = p11_asn1_encode (ext, &len);
266 	return_val_if_fail (der != NULL, NULL);
267 
268 	attrs = extension_attrs (parser, public_key_info, oid_str, oid_der,
269 	                         critical, der, len);
270 	return_val_if_fail (attrs != NULL, NULL);
271 
272 	free (der);
273 	return attrs;
274 }
275 
276 static p11_dict *
load_seq_of_oid_str(node_asn * node,const char * seqof)277 load_seq_of_oid_str (node_asn *node,
278                      const char *seqof)
279 {
280 	p11_dict *oids;
281 	char field[128];
282 	char *oid;
283 	size_t len;
284 	int i;
285 
286 	oids = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
287 
288 	for (i = 1; ; i++) {
289 		if (snprintf (field, sizeof (field), "%s.?%u", seqof, i) < 0)
290 			return_val_if_reached (NULL);
291 
292 		oid = p11_asn1_read (node, field, &len);
293 		if (oid == NULL)
294 			break;
295 
296 		if (!p11_dict_set (oids, oid, oid))
297 			return_val_if_reached (NULL);
298 	}
299 
300 	return oids;
301 }
302 
303 static CK_ATTRIBUTE *
attached_eku_attrs(p11_parser * parser,CK_ATTRIBUTE * public_key_info,const char * oid_str,const unsigned char * oid_der,bool critical,p11_dict * oid_strs)304 attached_eku_attrs (p11_parser *parser,
305                     CK_ATTRIBUTE *public_key_info,
306                     const char *oid_str,
307                     const unsigned char *oid_der,
308                     bool critical,
309                     p11_dict *oid_strs)
310 {
311 	CK_ATTRIBUTE *attrs;
312 	p11_dictiter iter;
313 	node_asn *dest;
314 	int count = 0;
315 	void *value;
316 	int ret;
317 
318 	dest = p11_asn1_create (parser->asn1_defs, "PKIX1.ExtKeyUsageSyntax");
319 	return_val_if_fail (dest != NULL, NULL);
320 
321 	p11_dict_iterate (oid_strs, &iter);
322 	while (p11_dict_next (&iter, NULL, &value)) {
323 		ret = asn1_write_value (dest, "", "NEW", 1);
324 		return_val_if_fail (ret == ASN1_SUCCESS, NULL);
325 
326 		ret = asn1_write_value (dest, "?LAST", value, -1);
327 		return_val_if_fail (ret == ASN1_SUCCESS, NULL);
328 
329 		count++;
330 	}
331 
332 	/*
333 	 * If no oids have been written, then we have to put in a reserved
334 	 * value, due to the way that ExtendedKeyUsage is defined in RFC 5280.
335 	 * There must be at least one purpose. This is important since *not*
336 	 * having an ExtendedKeyUsage is very different than having one without
337 	 * certain usages.
338 	 *
339 	 * We account for this in p11_parse_extended_key_usage(). However for
340 	 * most callers this should not matter, as they only check whether a
341 	 * given purpose is present, and don't make assumptions about ones
342 	 * that they don't know about.
343 	 */
344 
345 	if (count == 0) {
346 		ret = asn1_write_value (dest, "", "NEW", 1);
347 		return_val_if_fail (ret == ASN1_SUCCESS, NULL);
348 
349 		ret = asn1_write_value (dest, "?LAST", P11_OID_RESERVED_PURPOSE_STR, -1);
350 		return_val_if_fail (ret == ASN1_SUCCESS, NULL);
351 	}
352 
353 
354 	attrs = attached_attrs (parser, public_key_info, oid_str, oid_der, critical, dest);
355 	asn1_delete_structure (&dest);
356 
357 	return attrs;
358 }
359 
360 static CK_ATTRIBUTE *
build_openssl_extensions(p11_parser * parser,CK_ATTRIBUTE * cert,CK_ATTRIBUTE * public_key_info,node_asn * aux,const unsigned char * aux_der,size_t aux_len)361 build_openssl_extensions (p11_parser *parser,
362                           CK_ATTRIBUTE *cert,
363                           CK_ATTRIBUTE *public_key_info,
364                           node_asn *aux,
365                           const unsigned char *aux_der,
366                           size_t aux_len)
367 {
368 	CK_BBOOL trusted = CK_FALSE;
369 	CK_BBOOL distrust = CK_FALSE;
370 
371 	CK_ATTRIBUTE trust_attrs[] = {
372 		{ CKA_TRUSTED, &trusted, sizeof (trusted) },
373 		{ CKA_X_DISTRUSTED, &distrust, sizeof (distrust) },
374 		{ CKA_INVALID },
375 	};
376 
377 	CK_ATTRIBUTE *attrs;
378 	p11_dict *trust = NULL;
379 	p11_dict *reject = NULL;
380 	p11_dictiter iter;
381 	void *key;
382 	int start;
383 	int end;
384 	int ret;
385 	int num;
386 
387 	/*
388 	 * This will load an empty list if there is no OPTIONAL trust field.
389 	 * OpenSSL assumes that for a TRUSTED CERTIFICATE a missing trust field
390 	 * is identical to untrusted for all purposes.
391 	 *
392 	 * This is different from ExtendedKeyUsage, where a missing certificate
393 	 * extension means that it is trusted for all purposes.
394 	 */
395 	trust = load_seq_of_oid_str (aux, "trust");
396 
397 	ret = asn1_number_of_elements (aux, "reject", &num);
398 	return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
399 	if (ret == ASN1_SUCCESS)
400 		reject = load_seq_of_oid_str (aux, "reject");
401 
402 	/* Remove all rejected oids from the trust set */
403 	if (trust && reject) {
404 		p11_dict_iterate (reject, &iter);
405 		while (p11_dict_next (&iter, &key, NULL))
406 			p11_dict_remove (trust, key);
407 	}
408 
409 	/*
410 	 * The trust field (or lack of it) becomes a standard ExtKeyUsageSyntax.
411 	 *
412 	 * critical: require that this is enforced
413 	 */
414 
415 	if (trust) {
416 		attrs = attached_eku_attrs (parser, public_key_info,
417 		                            P11_OID_EXTENDED_KEY_USAGE_STR,
418 		                            P11_OID_EXTENDED_KEY_USAGE,
419 		                            true, trust);
420 		return_val_if_fail (attrs != NULL, NULL);
421 		sink_object (parser, attrs);
422 	}
423 
424 	/*
425 	 * For the reject field we use a custom defined extension. We track this
426 	 * for completeness, although the above ExtendedKeyUsage extension handles
427 	 * this data fine. See oid.h for more details. It uses ExtKeyUsageSyntax structure.
428 	 *
429 	 * non-critical: non-standard, and also covered by trusts
430 	 */
431 
432 	if (reject && p11_dict_size (reject) > 0) {
433 		attrs = attached_eku_attrs (parser, public_key_info,
434 		                            P11_OID_OPENSSL_REJECT_STR,
435 		                            P11_OID_OPENSSL_REJECT,
436 		                            false, reject);
437 		return_val_if_fail (attrs != NULL, NULL);
438 		sink_object (parser, attrs);
439 	}
440 
441 	/*
442 	 * OpenSSL model blocklists as anchors with all purposes being removed/rejected,
443 	 * we account for that here. If there is an ExtendedKeyUsage without any
444 	 * useful purposes, then treat like a blocklist.
445 	 */
446 	if (trust && p11_dict_size (trust) == 0) {
447 		trusted = CK_FALSE;
448 		distrust = CK_TRUE;
449 
450 	/*
451 	 * Otherwise a 'TRUSTED CERTIFICATE' in an input directory is enough to
452 	 * mark this as a trusted certificate.
453 	 */
454 	} else if (trust && p11_dict_size (trust) > 0) {
455 		trusted = CK_TRUE;
456 		distrust = CK_FALSE;
457 	}
458 
459 	/*
460 	 * OpenSSL model blocklists as anchors with all purposes being removed/rejected,
461 	 * we account for that here. If there is an ExtendedKeyUsage without any
462 	 * useful purposes, then treat like a blocklist.
463 	 */
464 
465 	cert = p11_attrs_merge (cert, p11_attrs_dup (trust_attrs), true);
466 	return_val_if_fail (cert != NULL, NULL);
467 
468 	p11_dict_free (trust);
469 	p11_dict_free (reject);
470 
471 	/*
472 	 * For the keyid field we use the SubjectKeyIdentifier extension. It
473 	 * is already in the correct form, an OCTET STRING.
474 	 *
475 	 * non-critical: as recommended in RFC 5280
476 	 */
477 
478 	ret = asn1_der_decoding_startEnd (aux, aux_der, aux_len, "keyid", &start, &end);
479 	return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
480 
481 	if (ret == ASN1_SUCCESS) {
482 		attrs = extension_attrs (parser, public_key_info,
483 		                         P11_OID_SUBJECT_KEY_IDENTIFIER_STR,
484 		                         P11_OID_SUBJECT_KEY_IDENTIFIER,
485 		                         false, aux_der + start, (end - start) + 1);
486 		return_val_if_fail (attrs != NULL, NULL);
487 		sink_object (parser, attrs);
488 	}
489 
490 
491 	return cert;
492 }
493 
494 static int
parse_openssl_trusted_certificate(p11_parser * parser,const unsigned char * data,size_t length)495 parse_openssl_trusted_certificate (p11_parser *parser,
496                                    const unsigned char *data,
497                                    size_t length)
498 {
499 	char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
500 	CK_ATTRIBUTE *attrs;
501 	CK_ATTRIBUTE public_key_info = { CKA_PUBLIC_KEY_INFO };
502 	CK_ATTRIBUTE *value;
503 	char *label = NULL;
504 	node_asn *cert;
505 	node_asn *aux = NULL;
506 	ssize_t cert_len;
507 	size_t len;
508 	int start;
509 	int end;
510 	int ret;
511 
512 	/*
513 	 * This OpenSSL format is weird. It's just two DER structures
514 	 * placed end to end without any wrapping SEQ. So calculate the
515 	 * length of the first DER TLV we see and try to parse that as
516 	 * the X.509 certificate.
517 	 */
518 
519 	cert_len = p11_asn1_tlv_length (data, length);
520 	if (cert_len <= 0)
521 		return P11_PARSE_UNRECOGNIZED;
522 
523 	cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, cert_len, message);
524 	if (cert == NULL)
525 		return P11_PARSE_UNRECOGNIZED;
526 
527 	/* OpenSSL sometimes outputs TRUSTED CERTIFICATE format without the CertAux supplement */
528 	if (cert_len < length) {
529 		aux = p11_asn1_decode (parser->asn1_defs, "OPENSSL.CertAux", data + cert_len,
530 		                       length - cert_len, message);
531 		if (aux == NULL) {
532 			asn1_delete_structure (&cert);
533 			return P11_PARSE_UNRECOGNIZED;
534 		}
535 	}
536 
537 	attrs = certificate_attrs (parser, data, cert_len);
538 	return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
539 
540 	/* Cache the parsed certificate ASN.1 for later use by the builder */
541 	value = p11_attrs_find_valid (attrs, CKA_VALUE);
542 	return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
543 
544 	/* Pull out the subject public key info */
545 	ret = asn1_der_decoding_startEnd (cert, data, cert_len,
546 	                                  "tbsCertificate.subjectPublicKeyInfo", &start, &end);
547 	return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
548 
549 	public_key_info.pValue = (char *)data + start;
550 	public_key_info.ulValueLen = (end - start) + 1;
551 
552 	p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
553 	                     value->pValue, value->ulValueLen);
554 
555 	/* Pull the label out of the CertAux */
556 	if (aux) {
557 		len = 0;
558 		label = p11_asn1_read (aux, "alias", &len);
559 		if (label != NULL) {
560 			attrs = p11_attrs_take (attrs, CKA_LABEL, label, strlen (label));
561 			return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
562 		}
563 
564 		attrs = build_openssl_extensions (parser, attrs, &public_key_info, aux,
565 		                                  data + cert_len, length - cert_len);
566 		return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
567 	}
568 
569 	sink_object (parser, attrs);
570 	asn1_delete_structure (&aux);
571 
572 	return P11_PARSE_SUCCESS;
573 }
574 
575 static void
on_pem_block(const char * type,const unsigned char * contents,size_t length,void * user_data)576 on_pem_block (const char *type,
577               const unsigned char *contents,
578               size_t length,
579               void *user_data)
580 {
581 	p11_parser *parser = user_data;
582 	int ret;
583 
584 	if (strcmp (type, "CERTIFICATE") == 0) {
585 		ret = p11_parser_format_x509 (parser, contents, length);
586 
587 	} else if (strcmp (type, "TRUSTED CERTIFICATE") == 0) {
588 		ret = parse_openssl_trusted_certificate (parser, contents, length);
589 
590 	} else {
591 		p11_debug ("Saw unsupported or unrecognized PEM block of type %s", type);
592 		ret = P11_PARSE_SUCCESS;
593 	}
594 
595 	if (ret != P11_PARSE_SUCCESS)
596 		p11_message (_("Couldn't parse PEM block of type %s"), type);
597 }
598 
599 int
p11_parser_format_pem(p11_parser * parser,const unsigned char * data,size_t length)600 p11_parser_format_pem (p11_parser *parser,
601                        const unsigned char *data,
602                        size_t length)
603 {
604 	int num;
605 
606 	num = p11_pem_parse ((const char *)data, length, on_pem_block, parser);
607 
608 	if (num == 0)
609 		return P11_PARSE_UNRECOGNIZED;
610 
611 	return P11_PARSE_SUCCESS;
612 }
613 
614 int
p11_parser_format_persist(p11_parser * parser,const unsigned char * data,size_t length)615 p11_parser_format_persist (p11_parser *parser,
616                            const unsigned char *data,
617                            size_t length)
618 {
619 	CK_BBOOL modifiablev = CK_TRUE;
620 	CK_ATTRIBUTE *attrs;
621 	p11_array *objects;
622 	bool ret;
623 	int i;
624 
625 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
626 
627 	if (!p11_persist_magic (data, length))
628 		return P11_PARSE_UNRECOGNIZED;
629 
630 	if (!parser->persist) {
631 		parser->persist = p11_persist_new ();
632 		return_val_if_fail (parser->persist != NULL, P11_PARSE_UNRECOGNIZED);
633 	}
634 
635 	objects = p11_array_new (NULL);
636 	return_val_if_fail (objects != NULL, P11_PARSE_FAILURE);
637 
638 	ret = p11_persist_read (parser->persist, parser->basename, data, length, objects);
639 	if (ret) {
640 		if (!p11_persist_is_generated (data, length))
641 			modifiablev = CK_FALSE;
642 		for (i = 0; i < objects->num; i++) {
643 			attrs = p11_attrs_build (objects->elem[i], &modifiable, NULL);
644 			sink_object (parser, attrs);
645 		}
646 	}
647 
648 	p11_array_free (objects);
649 	return ret ? P11_PARSE_SUCCESS : P11_PARSE_UNRECOGNIZED;
650 }
651 
652 p11_parser *
p11_parser_new(p11_asn1_cache * asn1_cache)653 p11_parser_new (p11_asn1_cache *asn1_cache)
654 {
655 	p11_parser parser = { 0, };
656 
657 	if (asn1_cache == NULL) {
658 		parser.asn1_owned = true;
659 		parser.asn1_defs = p11_asn1_defs_load ();
660 	} else {
661 		parser.asn1_defs = p11_asn1_cache_defs (asn1_cache);
662 		parser.asn1_cache = asn1_cache;
663 		parser.asn1_owned = false;
664 	}
665 
666 	parser.parsed = p11_array_new (p11_attrs_free);
667 	return_val_if_fail (parser.parsed != NULL, NULL);
668 
669 	return memdup (&parser, sizeof (parser));
670 }
671 
672 void
p11_parser_free(p11_parser * parser)673 p11_parser_free (p11_parser *parser)
674 {
675 	return_if_fail (parser != NULL);
676 	p11_persist_free (parser->persist);
677 	p11_array_free (parser->parsed);
678 	p11_array_free (parser->formats);
679 	if (parser->asn1_owned)
680 		p11_dict_free (parser->asn1_defs);
681 	free (parser);
682 }
683 
684 p11_array *
p11_parser_parsed(p11_parser * parser)685 p11_parser_parsed (p11_parser *parser)
686 {
687 	return_val_if_fail (parser != NULL, NULL);
688 	return parser->parsed;
689 }
690 
691 void
p11_parser_formats(p11_parser * parser,...)692 p11_parser_formats (p11_parser *parser,
693                     ...)
694 {
695 	p11_array *formats;
696 	parser_func func;
697 	va_list va;
698 
699 	formats = p11_array_new (NULL);
700 	return_if_fail (formats != NULL);
701 
702 	va_start (va, parser);
703 	for (;;) {
704 		func = va_arg (va, parser_func);
705 		if (func == NULL)
706 			break;
707 		if (!p11_array_push (formats, func)) {
708 			va_end (va);
709 			return_if_reached ();
710 		}
711 	}
712 	va_end (va);
713 
714 	p11_array_free (parser->formats);
715 	parser->formats = formats;
716 }
717 
718 int
p11_parse_memory(p11_parser * parser,const char * filename,int flags,const unsigned char * data,size_t length)719 p11_parse_memory (p11_parser *parser,
720                   const char *filename,
721                   int flags,
722                   const unsigned char *data,
723                   size_t length)
724 {
725 	int ret = P11_PARSE_UNRECOGNIZED;
726 	char *base;
727 	int i;
728 
729 	return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
730 	return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
731 	return_val_if_fail (parser->formats != NULL, P11_PARSE_FAILURE);
732 
733 	p11_array_clear (parser->parsed);
734 	base = p11_path_base (filename);
735 	parser->basename = base;
736 	parser->flags = flags;
737 
738 	for (i = 0; ret == P11_PARSE_UNRECOGNIZED && i < parser->formats->num; i++)
739 		ret = ((parser_func)parser->formats->elem[i]) (parser, data, length);
740 
741 	p11_asn1_cache_flush (parser->asn1_cache);
742 
743 	free (base);
744 	parser->basename = NULL;
745 	parser->flags = 0;
746 
747 	return ret;
748 }
749 
750 int
p11_parse_file(p11_parser * parser,const char * filename,struct stat * sb,int flags)751 p11_parse_file (p11_parser *parser,
752                 const char *filename,
753                 struct stat *sb,
754                 int flags)
755 {
756 	p11_mmap *map;
757 	void *data;
758 	size_t size;
759 	int ret;
760 
761 	return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
762 	return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
763 
764 	map = p11_mmap_open (filename, sb, &data, &size);
765 	if (map == NULL) {
766 		p11_message_err (errno, _("couldn't open and map file: %s"), filename);
767 		return P11_PARSE_FAILURE;
768 	}
769 
770 	ret = p11_parse_memory (parser, filename, flags, data, size);
771 
772 	p11_mmap_close (map);
773 	return ret;
774 }
775