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 #define P11_DEBUG_FLAG P11_DEBUG_TRUST
38 
39 #include "array.h"
40 #include "asn1.h"
41 #include "attrs.h"
42 #include "builder.h"
43 #include "constants.h"
44 #include "debug.h"
45 #include "digest.h"
46 #include "index.h"
47 #include "message.h"
48 #include "oid.h"
49 #include "pkcs11i.h"
50 #include "pkcs11x.h"
51 #include "utf8.h"
52 #include "x509.h"
53 
54 #include <assert.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #ifdef ENABLE_NLS
59 #include <libintl.h>
60 #define _(x) dgettext(PACKAGE_NAME, x)
61 #else
62 #define _(x) (x)
63 #endif
64 
65 struct _p11_builder {
66 	p11_asn1_cache *asn1_cache;
67 	p11_dict *asn1_defs;
68 	int flags;
69 };
70 
71 enum {
72 	NONE = 0,
73 	CREATE = 1 << 0,
74 	MODIFY = 1 << 1,
75 	REQUIRE = 1 << 2,
76 	WANT = 1 << 3,
77 };
78 
79 enum {
80 	NORMAL_BUILD = 0,
81 	GENERATED_CLASS = 1 << 0,
82 };
83 
84 typedef struct {
85 	int build_flags;
86 	struct {
87 		CK_ATTRIBUTE_TYPE type;
88 		int flags;
89 		bool (*validate) (p11_builder *, CK_ATTRIBUTE *);
90 	} attrs[32];
91 	CK_ATTRIBUTE * (*populate) (p11_builder *, p11_index *, CK_ATTRIBUTE *);
92 	CK_RV (*validate) (p11_builder *, CK_ATTRIBUTE *, CK_ATTRIBUTE *);
93 } builder_schema;
94 
95 static node_asn *
decode_or_get_asn1(p11_builder * builder,const char * struct_name,const unsigned char * der,size_t length)96 decode_or_get_asn1 (p11_builder *builder,
97                     const char *struct_name,
98                     const unsigned char *der,
99                     size_t length)
100 {
101 	node_asn *node;
102 
103 	node = p11_asn1_cache_get (builder->asn1_cache, struct_name, der, length);
104 	if (node != NULL)
105 		return node;
106 
107 	node = p11_asn1_decode (builder->asn1_defs, struct_name, der, length, NULL);
108 	if (node != NULL)
109 		p11_asn1_cache_take (builder->asn1_cache, node, struct_name, der, length);
110 
111 	return node;
112 }
113 
114 static unsigned char *
lookup_extension(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert,CK_ATTRIBUTE * public_key,const unsigned char * oid,size_t * ext_len)115 lookup_extension (p11_builder *builder,
116                   p11_index *index,
117                   CK_ATTRIBUTE *cert,
118                   CK_ATTRIBUTE *public_key,
119                   const unsigned char *oid,
120                   size_t *ext_len)
121 {
122 	CK_OBJECT_CLASS klass = CKO_X_CERTIFICATE_EXTENSION;
123 	CK_OBJECT_HANDLE obj;
124 	CK_ATTRIBUTE *attrs;
125 	CK_ATTRIBUTE *label;
126 	void *value;
127 	size_t length;
128 	node_asn *node;
129 
130 	CK_ATTRIBUTE match[] = {
131 		{ CKA_PUBLIC_KEY_INFO, },
132 		{ CKA_OBJECT_ID, (void *)oid, p11_oid_length (oid) },
133 		{ CKA_CLASS, &klass, sizeof (klass) },
134 		{ CKA_INVALID },
135 	};
136 
137 	if (public_key == NULL || public_key->type == CKA_INVALID)
138 		public_key = p11_attrs_find_valid (cert, CKA_PUBLIC_KEY_INFO);
139 
140 	/* Look for an attached certificate extension */
141 	if (public_key != NULL) {
142 		memcpy (match, public_key, sizeof (CK_ATTRIBUTE));
143 		obj = p11_index_find (index, match, -1);
144 		attrs = p11_index_lookup (index, obj);
145 		if (attrs != NULL) {
146 			value = p11_attrs_find_value (attrs, CKA_VALUE, &length);
147 			if (value != NULL) {
148 				node = decode_or_get_asn1 (builder, "PKIX1.Extension", value, length);
149 				if (node == NULL) {
150 					label = p11_attrs_find_valid (attrs, CKA_LABEL);
151 					if (label == NULL)
152 						label = p11_attrs_find_valid (cert, CKA_LABEL);
153 					p11_message (_("%.*s: invalid certificate extension"),
154 							label ? (int)label->ulValueLen : 7,
155 							label ? (char *)label->pValue : "unknown");
156 					return NULL;
157 				}
158 				return p11_asn1_read (node, "extnValue", ext_len);
159 			}
160 		}
161 	}
162 
163 	/* Couldn't find a parsed extension, so look in the current certificate */
164 	value = p11_attrs_find_value (cert, CKA_VALUE, &length);
165 	if (value != NULL) {
166 		node = decode_or_get_asn1 (builder, "PKIX1.Certificate", value, length);
167 		return_val_if_fail (node != NULL, NULL);
168 		return p11_x509_find_extension (node, oid, value, length, ext_len);
169 	}
170 
171 	return NULL;
172 }
173 
174 static CK_OBJECT_HANDLE *
lookup_related(p11_index * index,CK_OBJECT_CLASS klass,CK_ATTRIBUTE * attr)175 lookup_related  (p11_index *index,
176                  CK_OBJECT_CLASS klass,
177                  CK_ATTRIBUTE *attr)
178 {
179 	CK_ATTRIBUTE match[] = {
180 		{ attr->type, attr->pValue, attr->ulValueLen },
181 		{ CKA_CLASS, &klass, sizeof (klass) },
182 		{ CKA_INVALID }
183 	};
184 
185 	return p11_index_find_all (index, match, -1);
186 }
187 
188 p11_builder *
p11_builder_new(int flags)189 p11_builder_new (int flags)
190 {
191 	p11_builder *builder;
192 
193 	builder = calloc (1, sizeof (p11_builder));
194 	return_val_if_fail (builder != NULL, NULL);
195 
196 	builder->asn1_cache = p11_asn1_cache_new ();
197 	if (builder->asn1_cache == NULL) {
198 		p11_builder_free (builder);
199 		return_val_if_reached (NULL);
200 	}
201 	builder->asn1_defs = p11_asn1_cache_defs (builder->asn1_cache);
202 
203 	builder->flags = flags;
204 	return builder;
205 }
206 
207 static int
atoin(const char * p,int digits)208 atoin (const char *p,
209        int digits)
210 {
211 	int ret = 0, base = 1;
212 	while(--digits >= 0) {
213 		if (p[digits] < '0' || p[digits] > '9')
214 			return -1;
215 		ret += (p[digits] - '0') * base;
216 		base *= 10;
217 	}
218 	return ret;
219 }
220 
221 static bool
type_bool(p11_builder * builder,CK_ATTRIBUTE * attr)222 type_bool (p11_builder *builder,
223            CK_ATTRIBUTE *attr)
224 {
225 	return (attr->pValue != NULL &&
226 	        sizeof (CK_BBOOL) == attr->ulValueLen);
227 }
228 
229 static bool
type_ulong(p11_builder * builder,CK_ATTRIBUTE * attr)230 type_ulong (p11_builder *builder,
231             CK_ATTRIBUTE *attr)
232 {
233 	return (attr->pValue != NULL &&
234 	        sizeof (CK_ULONG) == attr->ulValueLen);
235 }
236 
237 static bool
type_utf8(p11_builder * builder,CK_ATTRIBUTE * attr)238 type_utf8 (p11_builder *builder,
239            CK_ATTRIBUTE *attr)
240 {
241 	if (attr->ulValueLen == 0)
242 		return true;
243 	if (attr->pValue == NULL)
244 		return false;
245 	return p11_utf8_validate (attr->pValue, attr->ulValueLen);
246 }
247 
248 static bool
type_date(p11_builder * builder,CK_ATTRIBUTE * attr)249 type_date (p11_builder *builder,
250            CK_ATTRIBUTE *attr)
251 {
252 	CK_DATE *date;
253 	struct tm tm;
254 	struct tm two;
255 
256 	if (attr->ulValueLen == 0)
257 		return true;
258 	if (attr->pValue == NULL || attr->ulValueLen != sizeof (CK_DATE))
259 		return false;
260 
261 	date = attr->pValue;
262 	memset (&tm, 0, sizeof (tm));
263 	tm.tm_year = atoin ((char *)date->year, 4) - 1900;
264 	tm.tm_mon = atoin ((char *)date->month, 2);
265 	tm.tm_mday = atoin ((char *)date->day, 2);
266 
267 	if (tm.tm_year < 0 || tm.tm_mon <= 0 || tm.tm_mday <= 0)
268 		return false;
269 
270 	memcpy (&two, &tm, sizeof (tm));
271 	two.tm_isdst = -1;	// do not perform tz fixup
272 	if (mktime (&two) < 0)
273 		return false;
274 
275 	/* If mktime changed anything, then bad date */
276 	if (tm.tm_year != two.tm_year ||
277 	    tm.tm_mon != two.tm_mon ||
278 	    tm.tm_mday != two.tm_mday)
279 		return false;
280 
281 	return true;
282 }
283 
284 static bool
check_der_struct(p11_builder * builder,const char * struct_name,CK_ATTRIBUTE * attr)285 check_der_struct (p11_builder *builder,
286                   const char *struct_name,
287                   CK_ATTRIBUTE *attr)
288 {
289 	node_asn *asn;
290 
291 	if (attr->ulValueLen == 0)
292 		return true;
293 	if (attr->pValue == NULL)
294 		return false;
295 
296 	asn = p11_asn1_decode (builder->asn1_defs, struct_name,
297 	                       attr->pValue, attr->ulValueLen, NULL);
298 
299 	if (asn == NULL)
300 		return false;
301 
302 	asn1_delete_structure (&asn);
303 	return true;
304 }
305 
306 static bool
type_der_name(p11_builder * builder,CK_ATTRIBUTE * attr)307 type_der_name (p11_builder *builder,
308                CK_ATTRIBUTE *attr)
309 {
310 	return check_der_struct (builder, "PKIX1.Name", attr);
311 }
312 
313 static bool
type_der_serial(p11_builder * builder,CK_ATTRIBUTE * attr)314 type_der_serial (p11_builder *builder,
315                  CK_ATTRIBUTE *attr)
316 {
317 	return check_der_struct (builder, "PKIX1.CertificateSerialNumber", attr);
318 }
319 
320 static bool
type_der_oid(p11_builder * builder,CK_ATTRIBUTE * attr)321 type_der_oid (p11_builder *builder,
322               CK_ATTRIBUTE *attr)
323 {
324 	/* AttributeType is an OBJECT ID */
325 	return check_der_struct (builder, "PKIX1.AttributeType", attr);
326 }
327 
328 static bool
type_der_cert(p11_builder * builder,CK_ATTRIBUTE * attr)329 type_der_cert (p11_builder *builder,
330                CK_ATTRIBUTE *attr)
331 {
332 	return check_der_struct (builder, "PKIX1.Certificate", attr);
333 }
334 
335 static bool
type_der_key(p11_builder * builder,CK_ATTRIBUTE * attr)336 type_der_key (p11_builder *builder,
337               CK_ATTRIBUTE *attr)
338 {
339 	return check_der_struct (builder, "PKIX1.SubjectPublicKeyInfo", attr);
340 }
341 
342 static bool
type_der_ext(p11_builder * builder,CK_ATTRIBUTE * attr)343 type_der_ext (p11_builder *builder,
344               CK_ATTRIBUTE *attr)
345 {
346 	return check_der_struct (builder, "PKIX1.Extension", attr);
347 }
348 
349 static bool
type_false_or_time(p11_builder * builder,CK_ATTRIBUTE * attr)350 type_false_or_time (p11_builder *builder,
351 		    CK_ATTRIBUTE *attr)
352 {
353 	struct tm tm;
354 	struct tm two;
355 	char *value;
356 
357 	if (sizeof (CK_BBOOL) == attr->ulValueLen &&
358 	    *((CK_BBOOL *)attr->pValue) == CK_FALSE)
359 		return true;
360 
361 	value = attr->pValue;
362 
363 	switch (attr->ulValueLen) {
364 	case 13:
365 		/* UTCTime restricted by RFC 5280 4.1.2.5.1, i.e., in
366 		 * the format "YYMMDDHHMMSSZ" */
367 		if (value[attr->ulValueLen - 1] != 'Z')
368 			return false;
369 
370 		tm.tm_year = atoin (value, 2);
371 		if (tm.tm_year < 0)
372 			return false;
373 		if (tm.tm_year >= 50)
374 			tm.tm_year += 1900;
375 		else if (tm.tm_year >= 0)
376 			tm.tm_year += 2000;
377 		value += 2;
378 
379 		break;
380 	case 15:
381 		/* GeneralizedTime restricted by RFC 5280 4.1.2.5.2,
382 		 * i.e., in the form "YYYYMMDDHHMMSSZ" */
383 		if (value[attr->ulValueLen - 1] != 'Z')
384 			return false;
385 
386 		tm.tm_year = atoin (value, 4);
387 		if (tm.tm_year < 0)
388 			return false;
389 		value += 4;
390 
391 		break;
392 	default:
393 		return false;
394 	}
395 
396 	tm.tm_mon = atoin (value, 2);
397 	value += 2;
398 	tm.tm_mday = atoin (value, 2);
399 	value += 2;
400 	tm.tm_hour = atoin (value, 2);
401 	value += 2;
402 	tm.tm_min = atoin (value, 2);
403 	value += 2;
404 	tm.tm_sec = atoin (value, 2);
405 
406 	if (tm.tm_mon <= 0 || tm.tm_mday <= 0 ||
407 	    tm.tm_hour < 0 || tm.tm_min < 0 || tm.tm_sec < 0)
408 		return false;
409 
410 	memcpy (&two, &tm, sizeof (tm));
411 	two.tm_isdst = -1;	/* do not perform tz fixup */
412 
413 	/* If mktime changed anything, then bad time */
414 	if (tm.tm_year != two.tm_year ||
415 	    tm.tm_mon != two.tm_mon ||
416 	    tm.tm_mday != two.tm_mday ||
417 	    tm.tm_hour != two.tm_hour ||
418 	    tm.tm_min != two.tm_min ||
419 	    tm.tm_sec != two.tm_sec)
420 		return false;
421 
422 	return true;
423 }
424 
425 #define COMMON_ATTRS \
426 	{ CKA_CLASS, REQUIRE | CREATE, type_ulong }, \
427 	{ CKA_TOKEN, CREATE | WANT, type_bool }, \
428 	{ CKA_MODIFIABLE, CREATE | WANT, type_bool }, \
429 	{ CKA_PRIVATE, CREATE, type_bool }, \
430 	{ CKA_LABEL, CREATE | MODIFY | WANT, type_utf8 }, \
431 	{ CKA_X_GENERATED, CREATE }, \
432 	{ CKA_X_ORIGIN, NONE } \
433 
434 static CK_ATTRIBUTE *
common_populate(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * unused)435 common_populate (p11_builder *builder,
436                  p11_index *index,
437                  CK_ATTRIBUTE *unused)
438 {
439 	CK_BBOOL tokenv = CK_FALSE;
440 	CK_BBOOL modifiablev = CK_TRUE;
441 	CK_BBOOL privatev = CK_FALSE;
442 	CK_BBOOL generatedv = CK_FALSE;
443 
444 	CK_ATTRIBUTE token = { CKA_TOKEN, &tokenv, sizeof (tokenv), };
445 	CK_ATTRIBUTE privat = { CKA_PRIVATE, &privatev, sizeof (privatev) };
446 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
447 	CK_ATTRIBUTE generated = { CKA_X_GENERATED, &generatedv, sizeof (generatedv) };
448 	CK_ATTRIBUTE label = { CKA_LABEL, "", 0 };
449 
450 	if (builder->flags & P11_BUILDER_FLAG_TOKEN) {
451 		tokenv = CK_TRUE;
452 		modifiablev = CK_FALSE;
453 	}
454 
455 	return p11_attrs_build (NULL, &token, &privat, &modifiable, &label, &generated, NULL);
456 }
457 
458 static void
calc_check_value(const unsigned char * data,size_t length,CK_BYTE * check_value)459 calc_check_value (const unsigned char *data,
460 		  size_t length,
461 		  CK_BYTE *check_value)
462 {
463 	unsigned char checksum[P11_DIGEST_SHA1_LEN];
464 	p11_digest_sha1 (checksum, data, length, NULL);
465 	memcpy (check_value, checksum, 3);
466 }
467 
468 static int
century_for_two_digit_year(int year)469 century_for_two_digit_year (int year)
470 {
471 	time_t now;
472 	struct tm tm;
473 	int century, current;
474 
475 	return_val_if_fail (year >= 0 && year <= 99, -1);
476 
477 	/* Get the current year */
478 	now = time (NULL);
479 	return_val_if_fail (now >= 0, -1);
480 	if (!gmtime_r (&now, &tm))
481 		return_val_if_reached (-1);
482 
483 	current = (tm.tm_year % 100);
484 	century = (tm.tm_year + 1900) - current;
485 
486 	/*
487 	 * Check if it's within 40 years before the
488 	 * current date.
489 	 */
490 	if (current < 40) {
491 		if (year < current)
492 			return century;
493 		if (year > 100 - (40 - current))
494 			return century - 100;
495 	} else {
496 		if (year < current && year > (current - 40))
497 			return century;
498 	}
499 
500 	/*
501 	 * If it's after then adjust for overflows to
502 	 * the next century.
503 	 */
504 	if (year < current)
505 		return century + 100;
506 	else
507 		return century;
508 }
509 
510 static bool
calc_date(node_asn * node,const char * field,CK_DATE * date)511 calc_date (node_asn *node,
512            const char *field,
513            CK_DATE *date)
514 {
515 	node_asn *choice;
516 	char buf[64];
517 	int century;
518 	char *sub;
519 	int year;
520 	int len;
521 	int ret;
522 
523 	if (!node)
524 		return false;
525 
526 	choice = asn1_find_node (node, field);
527 	return_val_if_fail (choice != NULL, false);
528 
529 	len = sizeof (buf) - 1;
530 	ret = asn1_read_value (node, field, buf, &len);
531 	return_val_if_fail (ret == ASN1_SUCCESS, false);
532 
533 	sub = strconcat (field, ".", buf, NULL);
534 
535 	/*
536 	 * So here we take a shortcut and just copy the date from the
537 	 * certificate into the CK_DATE. This doesn't take into account
538 	 * time zones. However the PKCS#11 spec does not say what timezone
539 	 * the dates are in. In the PKCS#11 value have a day resolution,
540 	 * and time zones aren't that critical.
541 	 */
542 
543 	if (strcmp (buf, "generalTime") == 0) {
544 		len = sizeof (buf) - 1;
545 		ret = asn1_read_value (node, sub, buf, &len);
546 		return_val_if_fail (ret == ASN1_SUCCESS, false);
547 		return_val_if_fail (len >= 8, false);
548 
549 		/* Same as first 8 characters of date */
550 		memcpy (date, buf, 8);
551 
552 	} else if (strcmp (buf, "utcTime") == 0) {
553 		len = sizeof (buf) - 1;
554 		ret = asn1_read_value (node, sub, buf, &len);
555 		return_val_if_fail (ret == ASN1_SUCCESS, false);
556 		return_val_if_fail (len >= 6, false);
557 
558 		year = atoin (buf, 2);
559 		return_val_if_fail (year >= 0, false);
560 
561 		century = century_for_two_digit_year (year);
562 		return_val_if_fail (century >= 0 && century <= 9900, false);
563 
564 		snprintf ((char *)date->year, 3, "%02d", century / 100);
565 		memcpy (((char *)date) + 2, buf, 6);
566 
567 	} else {
568 		return_val_if_reached (false);
569 	}
570 
571 	free (sub);
572 	return true;
573 }
574 
575 static bool
calc_element(node_asn * node,const unsigned char * data,size_t length,const char * field,CK_ATTRIBUTE * attr)576 calc_element (node_asn *node,
577 	      const unsigned char *data,
578 	      size_t length,
579 	      const char *field,
580 	      CK_ATTRIBUTE *attr)
581 {
582 	int ret;
583 	int start, end;
584 
585 	if (!node)
586 		return false;
587 
588 	ret = asn1_der_decoding_startEnd (node, data, length, field, &start, &end);
589 	return_val_if_fail (ret == ASN1_SUCCESS, false);
590 	return_val_if_fail (end >= start, false);
591 
592 	attr->pValue = (void *)(data + start);
593 	attr->ulValueLen = (end - start) + 1;
594 	return true;
595 }
596 
597 static bool
is_v1_x509_authority(p11_builder * builder,CK_ATTRIBUTE * cert)598 is_v1_x509_authority (p11_builder *builder,
599                       CK_ATTRIBUTE *cert)
600 {
601 	CK_ATTRIBUTE subject;
602 	CK_ATTRIBUTE issuer;
603 	CK_ATTRIBUTE *value;
604 	char buffer[16];
605 	node_asn *node;
606 	int len;
607 	int ret;
608 
609 	value = p11_attrs_find_valid (cert, CKA_VALUE);
610 	if (value == NULL)
611 		return false;
612 
613 	node = decode_or_get_asn1 (builder, "PKIX1.Certificate",
614 	                           value->pValue, value->ulValueLen);
615 	return_val_if_fail (node != NULL, false);
616 
617 	len = sizeof (buffer);
618 	ret = asn1_read_value (node, "tbsCertificate.version", buffer, &len);
619 
620 	/* The default value */
621 	if (ret == ASN1_ELEMENT_NOT_FOUND) {
622 		ret = ASN1_SUCCESS;
623 		buffer[0] = 0;
624 		len = 1;
625 	}
626 
627 	return_val_if_fail (ret == ASN1_SUCCESS, false);
628 
629 	/*
630 	 * In X.509 version v1 is the integer zero. Two's complement
631 	 * integer, but zero is easy to read.
632 	 */
633 	if (len != 1 || buffer[0] != 0)
634 		return false;
635 
636 	/* Must be self-signed, ie: same subject and issuer */
637 	if (!calc_element (node, value->pValue, value->ulValueLen, "tbsCertificate.subject", &subject))
638 		return_val_if_reached (false);
639 	if (!calc_element (node, value->pValue, value->ulValueLen, "tbsCertificate.issuer", &issuer))
640 		return_val_if_reached (false);
641 	return p11_attr_match_value (&subject, issuer.pValue, issuer.ulValueLen);
642 }
643 
644 static bool
calc_certificate_category(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert,CK_ATTRIBUTE * public_key,CK_ULONG * category)645 calc_certificate_category (p11_builder *builder,
646                            p11_index *index,
647                            CK_ATTRIBUTE *cert,
648                            CK_ATTRIBUTE *public_key,
649                            CK_ULONG *category)
650 {
651 	CK_ATTRIBUTE *label;
652 	unsigned char *ext;
653 	size_t ext_len;
654 	bool is_ca = 0;
655 	bool ret;
656 
657 	/*
658 	 * In the PKCS#11 spec:
659 	 *   0 = unspecified (default value)
660 	 *   1 = token user
661 	 *   2 = authority
662 	 *   3 = other entity
663 	 */
664 
665 	/* See if we have a basic constraints extension */
666 	ext = lookup_extension (builder, index, cert, public_key, P11_OID_BASIC_CONSTRAINTS, &ext_len);
667 	if (ext != NULL) {
668 		ret = p11_x509_parse_basic_constraints (builder->asn1_defs, ext, ext_len, &is_ca);
669 		free (ext);
670 		if (!ret) {
671 			label = p11_attrs_find_valid (cert, CKA_LABEL);
672 			p11_message (_("%.*s: invalid basic constraints certificate extension"),
673 				     label ? (int)label->ulValueLen : 7,
674 				     label ? (char *)label->pValue : _("unknown"));
675 			return false;
676 		}
677 
678 	} else if (is_v1_x509_authority (builder, cert)) {
679 		/*
680 		 * If there is no basic constraints extension, and the CA version is
681 		 * v1, and is self-signed, then we assume this is a certificate authority.
682 		 * So we add a BasicConstraints attached certificate extension
683 		 */
684 		is_ca = 1;
685 
686 	} else if (!p11_attrs_find_valid (cert, CKA_VALUE)) {
687 		/*
688 		 * If we have no certificate value, then this is unknown
689 		 */
690 		*category = 0;
691 		return true;
692 
693 	}
694 
695 	*category = is_ca ? 2 : 3;
696 	return true;
697 }
698 
699 static CK_ATTRIBUTE *
certificate_value_attrs(p11_builder * builder,CK_ATTRIBUTE * attrs,node_asn * node,const unsigned char * der,size_t der_len,CK_ATTRIBUTE * public_key)700 certificate_value_attrs (p11_builder *builder,
701                          CK_ATTRIBUTE *attrs,
702                          node_asn *node,
703                          const unsigned char *der,
704                          size_t der_len,
705                          CK_ATTRIBUTE *public_key)
706 {
707 	unsigned char checksum[P11_DIGEST_SHA1_LEN];
708 	unsigned char *keyid = NULL;
709 	size_t keyid_len;
710 	unsigned char *ext = NULL;
711 	size_t ext_len;
712 	CK_BBOOL falsev = CK_FALSE;
713 	CK_ULONG zero = 0UL;
714 	CK_BYTE checkv[3];
715 	CK_DATE startv;
716 	CK_DATE endv;
717 	char *labelv = NULL;
718 
719 	CK_ATTRIBUTE trusted = { CKA_TRUSTED, &falsev, sizeof (falsev) };
720 	CK_ATTRIBUTE distrusted = { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) };
721 	CK_ATTRIBUTE url = { CKA_URL, "", 0 };
722 	CK_ATTRIBUTE hash_of_subject_public_key = { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, checksum, sizeof (checksum) };
723 	CK_ATTRIBUTE hash_of_issuer_public_key = { CKA_HASH_OF_ISSUER_PUBLIC_KEY, "", 0 };
724 	CK_ATTRIBUTE java_midp_security_domain = { CKA_JAVA_MIDP_SECURITY_DOMAIN, &zero, sizeof (zero) };
725 	CK_ATTRIBUTE check_value = { CKA_CHECK_VALUE, &checkv, sizeof (checkv) };
726 	CK_ATTRIBUTE start_date = { CKA_START_DATE, &startv, sizeof (startv) };
727 	CK_ATTRIBUTE end_date = { CKA_END_DATE, &endv, sizeof (endv) };
728 	CK_ATTRIBUTE subject = { CKA_SUBJECT, };
729 	CK_ATTRIBUTE issuer = { CKA_ISSUER, "", 0 };
730 	CK_ATTRIBUTE serial_number = { CKA_SERIAL_NUMBER, "", 0 };
731 	CK_ATTRIBUTE label = { CKA_LABEL };
732 	CK_ATTRIBUTE id = { CKA_ID, NULL, 0 };
733 
734 	return_val_if_fail (attrs != NULL, NULL);
735 
736 	if (der == NULL)
737 		check_value.type = CKA_INVALID;
738 	else
739 		calc_check_value (der, der_len, checkv);
740 
741 	if (!calc_date (node, "tbsCertificate.validity.notBefore", &startv))
742 		start_date.ulValueLen = 0;
743 	if (!calc_date (node, "tbsCertificate.validity.notAfter", &endv))
744 		end_date.ulValueLen = 0;
745 
746 	if (calc_element (node, der, der_len, "tbsCertificate.subjectPublicKeyInfo", public_key))
747 		public_key->type = CKA_PUBLIC_KEY_INFO;
748 	else
749 		public_key->type = CKA_INVALID;
750 	calc_element (node, der, der_len, "tbsCertificate.issuer.rdnSequence", &issuer);
751 	if (!calc_element (node, der, der_len, "tbsCertificate.subject.rdnSequence", &subject))
752 		subject.type = CKA_INVALID;
753 	calc_element (node, der, der_len, "tbsCertificate.serialNumber", &serial_number);
754 
755 	/* Try to build a keyid from an extension */
756 	if (node) {
757 		ext = p11_x509_find_extension (node, P11_OID_SUBJECT_KEY_IDENTIFIER, der, der_len, &ext_len);
758 		if (ext) {
759 			keyid = p11_x509_parse_subject_key_identifier (builder->asn1_defs, ext,
760 			                                               ext_len, &keyid_len);
761 			id.pValue = keyid;
762 			id.ulValueLen = keyid_len;
763 		}
764 	}
765 
766 	if (!node || !p11_x509_hash_subject_public_key (node, der, der_len, checksum))
767 		hash_of_subject_public_key.ulValueLen = 0;
768 
769 	if (id.pValue == NULL) {
770 		id.pValue = hash_of_subject_public_key.pValue;
771 		id.ulValueLen = hash_of_subject_public_key.ulValueLen;
772 	}
773 
774 	if (node) {
775 		labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
776 		                                  der, der_len, P11_OID_CN);
777 		if (!labelv)
778 			labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
779 			                                  der, der_len, P11_OID_OU);
780 		if (!labelv)
781 			labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
782 			                                  der, der_len, P11_OID_O);
783 	}
784 
785 	if (labelv) {
786 		label.pValue = labelv;
787 		label.ulValueLen = strlen (labelv);
788 	} else {
789 		label.type = CKA_INVALID;
790 	}
791 
792 	attrs = p11_attrs_build (attrs, &trusted, &distrusted, &url, &hash_of_issuer_public_key,
793 	                         &hash_of_subject_public_key, &java_midp_security_domain,
794 	                         &check_value, &start_date, &end_date, &id,
795 	                         &subject, &issuer, &serial_number, &label, public_key,
796 				 NULL);
797 	return_val_if_fail (attrs != NULL, NULL);
798 
799 	free (ext);
800 	free (keyid);
801 	free (labelv);
802 	return attrs;
803 }
804 
805 static CK_ATTRIBUTE *
certificate_populate(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert)806 certificate_populate (p11_builder *builder,
807                       p11_index *index,
808                       CK_ATTRIBUTE *cert)
809 {
810 	CK_ULONG categoryv = 0UL;
811 	CK_ATTRIBUTE *attrs = NULL;
812 	CK_ATTRIBUTE public_key;
813 	node_asn *node = NULL;
814 	unsigned char *der = NULL;
815 	size_t der_len = 0;
816 
817 	CK_ATTRIBUTE category = { CKA_CERTIFICATE_CATEGORY, &categoryv, sizeof (categoryv) };
818 	CK_ATTRIBUTE empty_value = { CKA_VALUE, "", 0 };
819 
820 	attrs = common_populate (builder, index, cert);
821 	return_val_if_fail (attrs != NULL, NULL);
822 
823 	der = p11_attrs_find_value (cert, CKA_VALUE, &der_len);
824 	if (der != NULL)
825 		node = decode_or_get_asn1 (builder, "PKIX1.Certificate", der, der_len);
826 
827 	attrs = certificate_value_attrs (builder, attrs, node, der, der_len, &public_key);
828 	return_val_if_fail (attrs != NULL, NULL);
829 
830 	if (!calc_certificate_category (builder, index, cert, &public_key, &categoryv))
831 		categoryv = 0;
832 
833 	return p11_attrs_build (attrs, &category, &empty_value, NULL);
834 }
835 
836 static bool
have_attribute(CK_ATTRIBUTE * attrs1,CK_ATTRIBUTE * attrs2,CK_ATTRIBUTE_TYPE type)837 have_attribute (CK_ATTRIBUTE *attrs1,
838                 CK_ATTRIBUTE *attrs2,
839                 CK_ATTRIBUTE_TYPE type)
840 {
841 	CK_ATTRIBUTE *attr;
842 
843 	attr = p11_attrs_find (attrs1, type);
844 	if (attr == NULL)
845 		attr = p11_attrs_find (attrs2, type);
846 	return attr != NULL && attr->ulValueLen > 0;
847 }
848 
849 static CK_RV
certificate_validate(p11_builder * builder,CK_ATTRIBUTE * attrs,CK_ATTRIBUTE * merge)850 certificate_validate (p11_builder *builder,
851                       CK_ATTRIBUTE *attrs,
852                       CK_ATTRIBUTE *merge)
853 {
854 	/*
855 	 * In theory we should be validating that in the absence of CKA_VALUE
856 	 * various other fields must be set. However we do not enforce this
857 	 * because we want to be able to have certificates without a value
858 	 * but issuer and serial number, for blocklisting purposes.
859 	 */
860 
861 	if (have_attribute (attrs, merge, CKA_URL)) {
862 		if (!have_attribute (attrs, merge, CKA_HASH_OF_SUBJECT_PUBLIC_KEY)) {
863 			p11_message (_("missing the CKA_HASH_OF_SUBJECT_PUBLIC_KEY attribute"));
864 			return CKR_TEMPLATE_INCONSISTENT;
865 		}
866 
867 		if (!have_attribute (attrs, merge, CKA_HASH_OF_SUBJECT_PUBLIC_KEY)) {
868 			p11_message (_("missing the CKA_HASH_OF_ISSUER_PUBLIC_KEY attribute"));
869 			return CKR_TEMPLATE_INCONSISTENT;
870 		}
871 	}
872 
873 	return CKR_OK;
874 }
875 
876 const static builder_schema certificate_schema = {
877 	NORMAL_BUILD,
878 	{ COMMON_ATTRS,
879 	  { CKA_CERTIFICATE_TYPE, REQUIRE | CREATE, type_ulong },
880 	  { CKA_TRUSTED, CREATE | WANT, type_bool },
881 	  { CKA_X_DISTRUSTED, CREATE | WANT, type_bool },
882 	  { CKA_NSS_MOZILLA_CA_POLICY, CREATE | WANT, type_bool },
883 	  { CKA_NSS_SERVER_DISTRUST_AFTER, CREATE | WANT, type_false_or_time },
884 	  { CKA_NSS_EMAIL_DISTRUST_AFTER, CREATE | WANT, type_false_or_time },
885 	  { CKA_CERTIFICATE_CATEGORY, CREATE | WANT, type_ulong },
886 	  { CKA_CHECK_VALUE, CREATE | WANT, },
887 	  { CKA_START_DATE, CREATE | MODIFY | WANT, type_date },
888 	  { CKA_END_DATE, CREATE | MODIFY | WANT, type_date },
889 	  { CKA_SUBJECT, CREATE | WANT, type_der_name },
890 	  { CKA_ID, CREATE | MODIFY | WANT },
891 	  { CKA_ISSUER, CREATE | MODIFY | WANT, type_der_name },
892 	  { CKA_SERIAL_NUMBER, CREATE | MODIFY | WANT, type_der_serial },
893 	  { CKA_VALUE, CREATE, type_der_cert },
894 	  { CKA_URL, CREATE, type_utf8 },
895 	  { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CREATE },
896 	  { CKA_HASH_OF_ISSUER_PUBLIC_KEY, CREATE },
897 	  { CKA_JAVA_MIDP_SECURITY_DOMAIN, CREATE, type_ulong },
898 	  { CKA_PUBLIC_KEY_INFO, WANT, type_der_key },
899 	  { CKA_INVALID },
900 	}, certificate_populate, certificate_validate,
901 };
902 
903 static CK_ATTRIBUTE *
extension_populate(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * extension)904 extension_populate (p11_builder *builder,
905                     p11_index *index,
906                     CK_ATTRIBUTE *extension)
907 {
908 	unsigned char checksum[P11_DIGEST_SHA1_LEN];
909 	CK_ATTRIBUTE object_id = { CKA_INVALID };
910 	CK_ATTRIBUTE id = { CKA_INVALID };
911 	CK_ATTRIBUTE *attrs = NULL;
912 
913 	void *der;
914 	size_t len;
915 	node_asn *asn;
916 
917 	attrs = common_populate (builder, index, extension);
918 	return_val_if_fail (attrs != NULL, NULL);
919 
920 	if (!p11_attrs_find_valid (attrs, CKA_ID)) {
921 		der = p11_attrs_find_value (extension, CKA_PUBLIC_KEY_INFO, &len);
922 		return_val_if_fail (der != NULL, NULL);
923 
924 		p11_digest_sha1 (checksum, der, len, NULL);
925 		id.pValue = checksum;
926 		id.ulValueLen = sizeof (checksum);
927 		id.type = CKA_ID;
928 	}
929 
930 	/* Pull the object id out of the extension if not present */
931 	if (!p11_attrs_find_valid (attrs, CKA_OBJECT_ID)) {
932 		der = p11_attrs_find_value (extension, CKA_VALUE, &len);
933 		return_val_if_fail (der != NULL, NULL);
934 
935 		asn = decode_or_get_asn1 (builder, "PKIX1.Extension", der, len);
936 		return_val_if_fail (asn != NULL, NULL);
937 
938 		if (calc_element (asn, der, len, "extnID", &object_id))
939 			object_id.type = CKA_OBJECT_ID;
940 	}
941 
942 	attrs = p11_attrs_build (attrs, &object_id, &id, NULL);
943 	return_val_if_fail (attrs != NULL, NULL);
944 
945 	return attrs;
946 }
947 
948 const static builder_schema extension_schema = {
949 	NORMAL_BUILD,
950 	{ COMMON_ATTRS,
951 	  { CKA_VALUE, REQUIRE | CREATE, type_der_ext },
952 	  { CKA_PUBLIC_KEY_INFO, REQUIRE | CREATE, type_der_key },
953 	  { CKA_OBJECT_ID, CREATE | WANT, type_der_oid },
954 	  { CKA_ID, CREATE | MODIFY },
955 	  { CKA_INVALID },
956 	}, extension_populate,
957 };
958 
959 static CK_ATTRIBUTE *
data_populate(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * data)960 data_populate (p11_builder *builder,
961                p11_index *index,
962                CK_ATTRIBUTE *data)
963 {
964 	static const CK_ATTRIBUTE value = { CKA_VALUE, "", 0 };
965 	static const CK_ATTRIBUTE application = { CKA_APPLICATION, "", 0 };
966 	static const CK_ATTRIBUTE object_id = { CKA_OBJECT_ID, "", 0 };
967 	CK_ATTRIBUTE *attrs;
968 
969 	attrs = common_populate (builder, index, data);
970 	return_val_if_fail (attrs != NULL, NULL);
971 
972 	return p11_attrs_build (attrs, &value, &application, &object_id, NULL);
973 }
974 
975 const static builder_schema data_schema = {
976 	NORMAL_BUILD,
977 	{ COMMON_ATTRS,
978 	  { CKA_VALUE, CREATE | MODIFY | WANT },
979 	  { CKA_APPLICATION, CREATE | MODIFY | WANT, type_utf8 },
980 	  { CKA_OBJECT_ID, CREATE | MODIFY | WANT, type_der_oid },
981 	  { CKA_INVALID },
982 	}, data_populate,
983 };
984 
985 const static builder_schema trust_schema = {
986 	GENERATED_CLASS,
987 	{ COMMON_ATTRS,
988 	  { CKA_CERT_SHA1_HASH, CREATE },
989 	  { CKA_CERT_MD5_HASH, CREATE },
990 	  { CKA_ISSUER, CREATE },
991 	  { CKA_SUBJECT, CREATE },
992 	  { CKA_SERIAL_NUMBER, CREATE },
993 	  { CKA_TRUST_SERVER_AUTH, CREATE },
994 	  { CKA_TRUST_CLIENT_AUTH, CREATE },
995 	  { CKA_TRUST_EMAIL_PROTECTION, CREATE },
996 	  { CKA_TRUST_CODE_SIGNING, CREATE },
997 	  { CKA_TRUST_IPSEC_END_SYSTEM, CREATE },
998 	  { CKA_TRUST_IPSEC_TUNNEL, CREATE },
999 	  { CKA_TRUST_IPSEC_USER, CREATE },
1000 	  { CKA_TRUST_TIME_STAMPING, CREATE },
1001 	  { CKA_TRUST_DIGITAL_SIGNATURE, CREATE },
1002 	  { CKA_TRUST_NON_REPUDIATION, CREATE },
1003 	  { CKA_TRUST_KEY_ENCIPHERMENT, CREATE },
1004 	  { CKA_TRUST_DATA_ENCIPHERMENT, CREATE },
1005 	  { CKA_TRUST_KEY_AGREEMENT, CREATE },
1006 	  { CKA_TRUST_KEY_CERT_SIGN, CREATE },
1007 	  { CKA_TRUST_CRL_SIGN, CREATE },
1008 	  { CKA_TRUST_STEP_UP_APPROVED, CREATE },
1009 	  { CKA_ID, CREATE },
1010 	  { CKA_INVALID },
1011 	}, common_populate
1012 };
1013 
1014 const static builder_schema assertion_schema = {
1015 	GENERATED_CLASS,
1016 	{ COMMON_ATTRS,
1017 	  { CKA_X_PURPOSE, REQUIRE | CREATE },
1018 	  { CKA_X_CERTIFICATE_VALUE, CREATE },
1019 	  { CKA_X_ASSERTION_TYPE, REQUIRE | CREATE },
1020 	  { CKA_ISSUER, CREATE },
1021 	  { CKA_SERIAL_NUMBER, CREATE },
1022 	  { CKA_X_PEER, CREATE },
1023 	  { CKA_ID, CREATE },
1024 	  { CKA_INVALID },
1025 	}, common_populate
1026 };
1027 
1028 const static builder_schema builtin_schema = {
1029 	GENERATED_CLASS,
1030 	{ COMMON_ATTRS,
1031 	  { CKA_INVALID },
1032 	}, common_populate
1033 };
1034 
1035 static const char *
value_name(const p11_constant * info,CK_ATTRIBUTE_TYPE type)1036 value_name (const p11_constant *info,
1037             CK_ATTRIBUTE_TYPE type)
1038 {
1039 	const char *name = p11_constant_name (info, type);
1040 	return name ? name : "unknown";
1041 }
1042 
1043 static const char *
type_name(CK_ATTRIBUTE_TYPE type)1044 type_name (CK_ATTRIBUTE_TYPE type)
1045 {
1046 	return value_name (p11_constant_types, type);
1047 }
1048 
1049 static CK_RV
build_for_schema(p11_builder * builder,p11_index * index,const builder_schema * schema,CK_ATTRIBUTE * attrs,CK_ATTRIBUTE * merge,CK_ATTRIBUTE ** extra)1050 build_for_schema (p11_builder *builder,
1051                   p11_index *index,
1052                   const builder_schema *schema,
1053                   CK_ATTRIBUTE *attrs,
1054                   CK_ATTRIBUTE *merge,
1055                   CK_ATTRIBUTE **extra)
1056 {
1057 	CK_BBOOL modifiable;
1058 	CK_ATTRIBUTE *attr;
1059 	bool modifying;
1060 	bool creating;
1061 	bool populate;
1062 	bool loading;
1063 	bool found;
1064 	int flags;
1065 	int i, j;
1066 	CK_RV rv;
1067 
1068 	populate = false;
1069 
1070 	/* Signifies that data is being loaded */
1071 	loading = p11_index_loading (index);
1072 
1073 	/* Signifies that this is being created by a caller, instead of loaded */
1074 	creating = (attrs == NULL && !loading);
1075 
1076 	/* Item is being modified by a caller */
1077 	modifying = (attrs != NULL && !loading);
1078 
1079 	/* This item may not be modifiable */
1080 	if (modifying) {
1081 		if (!p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &modifiable) || !modifiable) {
1082 			p11_message (_("the object is not modifiable"));
1083 			return CKR_ATTRIBUTE_READ_ONLY;
1084 		}
1085 	}
1086 
1087 	if (creating && (builder->flags & P11_BUILDER_FLAG_TOKEN)) {
1088 		if (schema->build_flags & GENERATED_CLASS) {
1089 			p11_message (_("objects of this type cannot be created"));
1090 			return CKR_TEMPLATE_INCONSISTENT;
1091 		}
1092 	}
1093 
1094 	for (i = 0; merge[i].type != CKA_INVALID; i++) {
1095 
1096 		/* Don't validate attribute if not changed */
1097 		attr = p11_attrs_find (attrs, merge[i].type);
1098 		if (attr && p11_attr_equal (attr, merge + i))
1099 			continue;
1100 
1101 		found = false;
1102 		for (j = 0; schema->attrs[j].type != CKA_INVALID; j++) {
1103 			if (schema->attrs[j].type != merge[i].type)
1104 				continue;
1105 
1106 			flags = schema->attrs[j].flags;
1107 			if (creating && !(flags & CREATE)) {
1108 				p11_message (_("the %s attribute cannot be set"),
1109 				             type_name (schema->attrs[j].type));
1110 				return CKR_ATTRIBUTE_READ_ONLY;
1111 			}
1112 			if (modifying && !(flags & MODIFY)) {
1113 				p11_message (_("the %s attribute cannot be changed"),
1114 				             type_name (schema->attrs[j].type));
1115 				return CKR_ATTRIBUTE_READ_ONLY;
1116 			}
1117 			if (!loading && schema->attrs[j].validate != NULL &&
1118 			    !schema->attrs[j].validate (builder, merge + i)) {
1119 				p11_message (_("the %s attribute has an invalid value"),
1120 				             type_name (schema->attrs[j].type));
1121 				return CKR_ATTRIBUTE_VALUE_INVALID;
1122 			}
1123 			found = true;
1124 			break;
1125 		}
1126 
1127 		if (!found) {
1128 			p11_message (_("the %s attribute is not valid for the object"),
1129 			             type_name (merge[i].type));
1130 			return CKR_TEMPLATE_INCONSISTENT;
1131 		}
1132 	}
1133 
1134 	if (attrs == NULL) {
1135 		for (j = 0; schema->attrs[j].type != CKA_INVALID; j++) {
1136 			flags = schema->attrs[j].flags;
1137 			found = false;
1138 
1139 			if ((flags & REQUIRE) || (flags & WANT)) {
1140 				for (i = 0; merge[i].type != CKA_INVALID; i++) {
1141 					if (schema->attrs[j].type == merge[i].type) {
1142 						found = true;
1143 						break;
1144 					}
1145 				}
1146 			}
1147 
1148 			if (!found) {
1149 				if (flags & REQUIRE) {
1150 					p11_message (_("missing the %s attribute"),
1151 					             type_name (schema->attrs[j].type));
1152 					return CKR_TEMPLATE_INCOMPLETE;
1153 				} else if (flags & WANT) {
1154 					populate = true;
1155 				}
1156 			}
1157 		}
1158 	}
1159 
1160 	/* Validate the result, before committing to the change. */
1161 	if (!loading && schema->validate) {
1162 		rv = (schema->validate) (builder, attrs, merge);
1163 		if (rv != CKR_OK)
1164 			return rv;
1165 	}
1166 
1167 	if (populate && schema->populate)
1168 		*extra = schema->populate (builder, index, merge);
1169 
1170 	return CKR_OK;
1171 }
1172 
1173 CK_RV
p11_builder_build(void * bilder,p11_index * index,CK_ATTRIBUTE * attrs,CK_ATTRIBUTE * merge,CK_ATTRIBUTE ** populate)1174 p11_builder_build (void *bilder,
1175                    p11_index *index,
1176                    CK_ATTRIBUTE *attrs,
1177                    CK_ATTRIBUTE *merge,
1178                    CK_ATTRIBUTE **populate)
1179 {
1180 	p11_builder *builder = bilder;
1181 	CK_OBJECT_CLASS klass;
1182 	CK_CERTIFICATE_TYPE type;
1183 	CK_BBOOL token;
1184 
1185 	return_val_if_fail (builder != NULL, CKR_GENERAL_ERROR);
1186 	return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
1187 	return_val_if_fail (merge != NULL, CKR_GENERAL_ERROR);
1188 
1189 	if (!p11_attrs_find_ulong (attrs ? attrs : merge, CKA_CLASS, &klass)) {
1190 		p11_message (_("no CKA_CLASS attribute found"));
1191 		return CKR_TEMPLATE_INCOMPLETE;
1192 	}
1193 
1194 	if (!attrs && p11_attrs_find_bool (merge, CKA_TOKEN, &token)) {
1195 		if (token != ((builder->flags & P11_BUILDER_FLAG_TOKEN) ? CK_TRUE : CK_FALSE)) {
1196 			p11_message (_("cannot create a %s object"), token ? _("token") : _("non-token"));
1197 			return CKR_TEMPLATE_INCONSISTENT;
1198 		}
1199 	}
1200 
1201 	switch (klass) {
1202 	case CKO_CERTIFICATE:
1203 		if (!p11_attrs_find_ulong (attrs ? attrs : merge, CKA_CERTIFICATE_TYPE, &type)) {
1204 			p11_message (_("missing %s on object"), type_name (CKA_CERTIFICATE_TYPE));
1205 			return CKR_TEMPLATE_INCOMPLETE;
1206 		} else if (type == CKC_X_509) {
1207 			return build_for_schema (builder, index, &certificate_schema, attrs, merge, populate);
1208 		} else {
1209 			p11_message (_("%s unsupported %s"), value_name (p11_constant_certs, type),
1210 			             type_name (CKA_CERTIFICATE_TYPE));
1211 			return CKR_TEMPLATE_INCONSISTENT;
1212 		}
1213 
1214 	case CKO_X_CERTIFICATE_EXTENSION:
1215 		return build_for_schema (builder, index, &extension_schema, attrs, merge, populate);
1216 
1217 	case CKO_DATA:
1218 		return build_for_schema (builder, index, &data_schema, attrs, merge, populate);
1219 
1220 	case CKO_NSS_TRUST:
1221 		return build_for_schema (builder, index, &trust_schema, attrs, merge, populate);
1222 
1223 	case CKO_NSS_BUILTIN_ROOT_LIST:
1224 		return build_for_schema (builder, index, &builtin_schema, attrs, merge, populate);
1225 
1226 	case CKO_X_TRUST_ASSERTION:
1227 		return build_for_schema (builder, index, &assertion_schema, attrs, merge, populate);
1228 
1229 	default:
1230 		p11_message (_("%s unsupported object class"),
1231 		             value_name (p11_constant_classes, klass));
1232 		return CKR_TEMPLATE_INCONSISTENT;
1233 	}
1234 }
1235 
1236 void
p11_builder_free(p11_builder * builder)1237 p11_builder_free (p11_builder *builder)
1238 {
1239 	return_if_fail (builder != NULL);
1240 
1241 	p11_asn1_cache_free (builder->asn1_cache);
1242 	free (builder);
1243 }
1244 
1245 p11_asn1_cache *
p11_builder_get_cache(p11_builder * builder)1246 p11_builder_get_cache (p11_builder *builder)
1247 {
1248 	return_val_if_fail (builder != NULL, NULL);
1249 	return builder->asn1_cache;
1250 }
1251 
1252 static CK_ATTRIBUTE *
build_trust_object_ku(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert,CK_ATTRIBUTE * object,CK_TRUST present)1253 build_trust_object_ku (p11_builder *builder,
1254                        p11_index *index,
1255                        CK_ATTRIBUTE *cert,
1256                        CK_ATTRIBUTE *object,
1257                        CK_TRUST present)
1258 {
1259 	unsigned char *data = NULL;
1260 	unsigned int ku = 0;
1261 	size_t length;
1262 	CK_TRUST defawlt;
1263 	CK_ULONG i;
1264 
1265 	struct {
1266 		CK_ATTRIBUTE_TYPE type;
1267 		unsigned int ku;
1268 	} ku_attribute_map[] = {
1269 		{ CKA_TRUST_DIGITAL_SIGNATURE, P11_KU_DIGITAL_SIGNATURE },
1270 		{ CKA_TRUST_NON_REPUDIATION, P11_KU_NON_REPUDIATION },
1271 		{ CKA_TRUST_KEY_ENCIPHERMENT, P11_KU_KEY_ENCIPHERMENT },
1272 		{ CKA_TRUST_DATA_ENCIPHERMENT, P11_KU_DATA_ENCIPHERMENT },
1273 		{ CKA_TRUST_KEY_AGREEMENT, P11_KU_KEY_AGREEMENT },
1274 		{ CKA_TRUST_KEY_CERT_SIGN, P11_KU_KEY_CERT_SIGN },
1275 		{ CKA_TRUST_CRL_SIGN, P11_KU_CRL_SIGN },
1276 		{ CKA_INVALID },
1277 	};
1278 
1279 	CK_ATTRIBUTE attrs[sizeof (ku_attribute_map)];
1280 
1281 	defawlt = present;
1282 
1283 	/* If distrusted, don't even bother looking at extensions */
1284 	if (present != CKT_NSS_NOT_TRUSTED)
1285 		data = lookup_extension (builder, index, cert, NULL, P11_OID_KEY_USAGE, &length);
1286 
1287 	if (data) {
1288 		/*
1289 		 * If the certificate extension was missing, then *all* key
1290 		 * usages are to be set. If the extension was invalid, then
1291 		 * fail safe to none of the key usages.
1292 		 */
1293 		defawlt = CKT_NSS_TRUST_UNKNOWN;
1294 
1295 		if (!p11_x509_parse_key_usage (builder->asn1_defs, data, length, &ku))
1296 			p11_message (_("invalid key usage certificate extension"));
1297 		free (data);
1298 	}
1299 
1300 	for (i = 0; ku_attribute_map[i].type != CKA_INVALID; i++) {
1301 		attrs[i].type = ku_attribute_map[i].type;
1302 		if (data && (ku & ku_attribute_map[i].ku) == ku_attribute_map[i].ku) {
1303 			attrs[i].pValue = &present;
1304 			attrs[i].ulValueLen = sizeof (present);
1305 		} else {
1306 			attrs[i].pValue = &defawlt;
1307 			attrs[i].ulValueLen = sizeof (defawlt);
1308 		}
1309 	}
1310 
1311 	return p11_attrs_buildn (object, attrs, i);
1312 }
1313 
1314 static bool
strv_to_dict(const char ** array,p11_dict ** dict)1315 strv_to_dict (const char **array,
1316               p11_dict **dict)
1317 {
1318 	int i;
1319 
1320 	if (!array) {
1321 		*dict = NULL;
1322 		return true;
1323 	}
1324 
1325 	*dict = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL);
1326 	return_val_if_fail (*dict != NULL, false);
1327 
1328 	for (i = 0; array[i] != NULL; i++) {
1329 		if (!p11_dict_set (*dict, (void *)array[i], (void *)array[i]))
1330 			return_val_if_reached (false);
1331 	}
1332 
1333 	return true;
1334 }
1335 
1336 static CK_ATTRIBUTE *
build_trust_object_eku(CK_ATTRIBUTE * object,CK_TRUST allow,const char ** purposes,const char ** rejects)1337 build_trust_object_eku (CK_ATTRIBUTE *object,
1338                         CK_TRUST allow,
1339                         const char **purposes,
1340                         const char **rejects)
1341 {
1342 	p11_dict *dict_purp;
1343 	p11_dict *dict_rej;
1344 	CK_TRUST neutral;
1345 	CK_TRUST disallow;
1346 	CK_ULONG i;
1347 
1348 	struct {
1349 		CK_ATTRIBUTE_TYPE type;
1350 		const char *oid;
1351 	} eku_attribute_map[] = {
1352 		{ CKA_TRUST_SERVER_AUTH, P11_OID_SERVER_AUTH_STR },
1353 		{ CKA_TRUST_CLIENT_AUTH, P11_OID_CLIENT_AUTH_STR },
1354 		{ CKA_TRUST_CODE_SIGNING, P11_OID_CODE_SIGNING_STR },
1355 		{ CKA_TRUST_EMAIL_PROTECTION, P11_OID_EMAIL_PROTECTION_STR },
1356 		{ CKA_TRUST_IPSEC_END_SYSTEM, P11_OID_IPSEC_END_SYSTEM_STR },
1357 		{ CKA_TRUST_IPSEC_TUNNEL, P11_OID_IPSEC_TUNNEL_STR },
1358 		{ CKA_TRUST_IPSEC_USER, P11_OID_IPSEC_USER_STR },
1359 		{ CKA_TRUST_TIME_STAMPING, P11_OID_TIME_STAMPING_STR },
1360 		{ CKA_INVALID },
1361 	};
1362 
1363 	CK_ATTRIBUTE attrs[sizeof (eku_attribute_map)];
1364 
1365 	if (!strv_to_dict (purposes, &dict_purp) ||
1366 	    !strv_to_dict (rejects, &dict_rej))
1367 		return_val_if_reached (NULL);
1368 
1369 	/* The neutral value is set if an purpose is not present */
1370 	if (allow == CKT_NSS_NOT_TRUSTED)
1371 		neutral = CKT_NSS_NOT_TRUSTED;
1372 
1373 	/* If anything explicitly set, then neutral is unknown */
1374 	else if (purposes || rejects)
1375 		neutral = CKT_NSS_TRUST_UNKNOWN;
1376 
1377 	/* Otherwise neutral will allow any purpose */
1378 	else
1379 		neutral = allow;
1380 
1381 	/* The value set if a purpose is explicitly rejected */
1382 	disallow = CKT_NSS_NOT_TRUSTED;
1383 
1384 	for (i = 0; eku_attribute_map[i].type != CKA_INVALID; i++) {
1385 		attrs[i].type = eku_attribute_map[i].type;
1386 		if (dict_rej && p11_dict_get (dict_rej, eku_attribute_map[i].oid)) {
1387 			attrs[i].pValue = &disallow;
1388 			attrs[i].ulValueLen = sizeof (disallow);
1389 		} else if (dict_purp && p11_dict_get (dict_purp, eku_attribute_map[i].oid)) {
1390 			attrs[i].pValue = &allow;
1391 			attrs[i].ulValueLen = sizeof (allow);
1392 		} else {
1393 			attrs[i].pValue = &neutral;
1394 			attrs[i].ulValueLen = sizeof (neutral);
1395 		}
1396 	}
1397 
1398 	p11_dict_free (dict_purp);
1399 	p11_dict_free (dict_rej);
1400 
1401 	return p11_attrs_buildn (object, attrs, i);
1402 }
1403 
1404 static void
replace_nss_trust_object(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert,CK_BBOOL trust,CK_BBOOL distrust,CK_BBOOL authority,const char ** purposes,const char ** rejects)1405 replace_nss_trust_object (p11_builder *builder,
1406                           p11_index *index,
1407                           CK_ATTRIBUTE *cert,
1408                           CK_BBOOL trust,
1409                           CK_BBOOL distrust,
1410                           CK_BBOOL authority,
1411                           const char **purposes,
1412                           const char **rejects)
1413 {
1414 	CK_ATTRIBUTE *attrs = NULL;
1415 	CK_ATTRIBUTE *match = NULL;
1416 	CK_TRUST allow;
1417 	CK_RV rv;
1418 
1419 	CK_OBJECT_CLASS klassv = CKO_NSS_TRUST;
1420 	CK_BYTE sha1v[P11_DIGEST_SHA1_LEN];
1421 	CK_BYTE md5v[P11_DIGEST_MD5_LEN];
1422 	CK_BBOOL generatedv = CK_FALSE;
1423 	CK_BBOOL falsev = CK_FALSE;
1424 
1425 	CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
1426 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &falsev, sizeof (falsev) };
1427 	CK_ATTRIBUTE generated = { CKA_X_GENERATED, &generatedv, sizeof (generatedv) };
1428 	CK_ATTRIBUTE invalid = { CKA_INVALID, };
1429 
1430 	CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, md5v, sizeof (md5v) };
1431 	CK_ATTRIBUTE sha1_hash = { CKA_CERT_SHA1_HASH, sha1v, sizeof (sha1v) };
1432 
1433 	CK_ATTRIBUTE step_up_approved = { CKA_TRUST_STEP_UP_APPROVED, &falsev, sizeof (falsev) };
1434 
1435 	CK_ATTRIBUTE_PTR label;
1436 	CK_ATTRIBUTE_PTR id;
1437 	CK_ATTRIBUTE_PTR subject;
1438 	CK_ATTRIBUTE_PTR issuer;
1439 	CK_ATTRIBUTE_PTR serial_number;
1440 
1441 	p11_array *array;
1442 	void *value;
1443 	size_t length;
1444 
1445 	issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
1446 	serial_number = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
1447 	value = p11_attrs_find_value (cert, CKA_VALUE, &length);
1448 
1449 	if (!issuer && !serial_number && !value) {
1450 		p11_debug ("can't generate nss trust object for certificate without issuer+serial or value");
1451 		return;
1452 	}
1453 
1454 	if (value == NULL) {
1455 		md5_hash.type = CKA_INVALID;
1456 		sha1_hash.type = CKA_INVALID;
1457 	} else {
1458 		p11_digest_md5 (md5v, value, length, NULL);
1459 		p11_digest_sha1 (sha1v, value, length, NULL);
1460 	}
1461 	if (!issuer)
1462 		issuer = &invalid;
1463 	if (!serial_number)
1464 		serial_number = &invalid;
1465 
1466 	match = p11_attrs_build (NULL, issuer, serial_number, &sha1_hash,
1467 	                         &generated, &klass, NULL);
1468 	return_if_fail (match != NULL);
1469 
1470 	/* If we find a non-generated object, then don't generate */
1471 	if (p11_index_find (index, match, -1)) {
1472 		p11_debug ("not generating nss trust object because one already exists");
1473 		attrs = NULL;
1474 
1475 	} else {
1476 		generatedv = CK_TRUE;
1477 		match = p11_attrs_build (match, &generated, NULL);
1478 		return_if_fail (match != NULL);
1479 
1480 		/* Copy all of the following attributes from certificate */
1481 		id = p11_attrs_find_valid (cert, CKA_ID);
1482 		if (id == NULL)
1483 			id = &invalid;
1484 		subject = p11_attrs_find_valid (cert, CKA_SUBJECT);
1485 		if (subject == NULL)
1486 			subject = &invalid;
1487 		label = p11_attrs_find_valid (cert, CKA_LABEL);
1488 		if (label == NULL)
1489 			label = &invalid;
1490 
1491 		attrs = p11_attrs_dup (match);
1492 		return_if_fail (attrs != NULL);
1493 
1494 		attrs = p11_attrs_build (attrs, &klass, &modifiable, id, label,
1495 		                         subject, issuer, serial_number,
1496 		                         &md5_hash, &sha1_hash, &step_up_approved, NULL);
1497 		return_if_fail (attrs != NULL);
1498 
1499 		/* Calculate the default allow trust */
1500 		if (distrust)
1501 			allow = CKT_NSS_NOT_TRUSTED;
1502 		else if (trust && authority)
1503 			allow = CKT_NSS_TRUSTED_DELEGATOR;
1504 		else if (trust)
1505 			allow = CKT_NSS_TRUSTED;
1506 		else
1507 			allow = CKT_NSS_TRUST_UNKNOWN;
1508 
1509 		attrs = build_trust_object_ku (builder, index, cert, attrs, allow);
1510 		return_if_fail (attrs != NULL);
1511 
1512 		attrs = build_trust_object_eku (attrs, allow, purposes, rejects);
1513 		return_if_fail (attrs != NULL);
1514 	}
1515 
1516 	/* Replace related generated object with this new one */
1517 	array = p11_array_new (NULL);
1518 	p11_array_push (array, attrs);
1519 	rv = p11_index_replace_all (index, match, CKA_INVALID, array);
1520 	return_if_fail (rv == CKR_OK);
1521 	p11_array_free (array);
1522 
1523 	p11_attrs_free (match);
1524 }
1525 
1526 static void
build_assertions(p11_array * array,CK_ATTRIBUTE * cert,CK_X_ASSERTION_TYPE type,const char ** oids)1527 build_assertions (p11_array *array,
1528                   CK_ATTRIBUTE *cert,
1529                   CK_X_ASSERTION_TYPE type,
1530                   const char **oids)
1531 {
1532 	CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
1533 	CK_BBOOL truev = CK_TRUE;
1534 	CK_BBOOL falsev = CK_FALSE;
1535 
1536 	CK_ATTRIBUTE klass = { CKA_CLASS, &assertion, sizeof (assertion) };
1537 	CK_ATTRIBUTE private = { CKA_PRIVATE, &falsev, sizeof (falsev) };
1538 	CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &falsev, sizeof (falsev) };
1539 	CK_ATTRIBUTE assertion_type = { CKA_X_ASSERTION_TYPE, &type, sizeof (type) };
1540 	CK_ATTRIBUTE autogen = { CKA_X_GENERATED, &truev, sizeof (truev) };
1541 	CK_ATTRIBUTE purpose = { CKA_X_PURPOSE, };
1542 	CK_ATTRIBUTE invalid = { CKA_INVALID, };
1543 	CK_ATTRIBUTE certificate_value = { CKA_X_CERTIFICATE_VALUE, };
1544 
1545 	CK_ATTRIBUTE *issuer;
1546 	CK_ATTRIBUTE *serial;
1547 	CK_ATTRIBUTE *value;
1548 	CK_ATTRIBUTE *label;
1549 	CK_ATTRIBUTE *id;
1550 	CK_ATTRIBUTE *attrs;
1551 	int i;
1552 
1553 	if (type == CKT_X_DISTRUSTED_CERTIFICATE) {
1554 		certificate_value.type = CKA_INVALID;
1555 		issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
1556 		serial = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
1557 
1558 		if (!issuer || !serial) {
1559 			p11_debug ("not building negative trust assertion for certificate without serial or issuer");
1560 			return;
1561 		}
1562 
1563 	} else {
1564 		issuer = &invalid;
1565 		serial = &invalid;
1566 		value = p11_attrs_find_valid (cert, CKA_VALUE);
1567 
1568 		if (value == NULL) {
1569 			p11_debug ("not building positive trust assertion for certificate without value");
1570 			return;
1571 		}
1572 
1573 		certificate_value.pValue = value->pValue;
1574 		certificate_value.ulValueLen = value->ulValueLen;
1575 	}
1576 
1577 	label = p11_attrs_find (cert, CKA_LABEL);
1578 	if (label == NULL)
1579 		label = &invalid;
1580 	id = p11_attrs_find (cert, CKA_ID);
1581 	if (id == NULL)
1582 		id = &invalid;
1583 
1584 	for (i = 0; oids[i] != NULL; i++) {
1585 		purpose.pValue = (void *)oids[i];
1586 		purpose.ulValueLen = strlen (oids[i]);
1587 
1588 		attrs = p11_attrs_build (NULL, &klass, &private, &modifiable,
1589 		                         id, label, &assertion_type, &purpose,
1590 		                         issuer, serial, &certificate_value, &autogen, NULL);
1591 		return_if_fail (attrs != NULL);
1592 
1593 		if (!p11_array_push (array, attrs))
1594 			return_if_reached ();
1595 	}
1596 }
1597 
1598 static void
build_trust_assertions(p11_array * positives,p11_array * negatives,CK_ATTRIBUTE * cert,CK_BBOOL trust,CK_BBOOL distrust,CK_BBOOL authority,const char ** purposes,const char ** rejects)1599 build_trust_assertions (p11_array *positives,
1600                         p11_array *negatives,
1601                         CK_ATTRIBUTE *cert,
1602                         CK_BBOOL trust,
1603                         CK_BBOOL distrust,
1604                         CK_BBOOL authority,
1605                         const char **purposes,
1606                         const char **rejects)
1607 {
1608 	const char *all_purposes[] = {
1609 		P11_OID_SERVER_AUTH_STR,
1610 		P11_OID_CLIENT_AUTH_STR,
1611 		P11_OID_CODE_SIGNING_STR,
1612 		P11_OID_EMAIL_PROTECTION_STR,
1613 		P11_OID_IPSEC_END_SYSTEM_STR,
1614 		P11_OID_IPSEC_TUNNEL_STR,
1615 		P11_OID_IPSEC_USER_STR,
1616 		P11_OID_TIME_STAMPING_STR,
1617 		NULL,
1618 	};
1619 
1620 	/* Build assertions for anything that's explicitly rejected */
1621 	if (rejects && negatives) {
1622 		build_assertions (negatives, cert, CKT_X_DISTRUSTED_CERTIFICATE, rejects);
1623 	}
1624 
1625 	if (distrust && negatives) {
1626 		/*
1627 		 * Trust assertions are defficient in that they don't blocklist a certificate
1628 		 * for any purposes. So we just have to go wild and write out a bunch of
1629 		 * assertions for all our known purposes.
1630 		 */
1631 		build_assertions (negatives, cert, CKT_X_DISTRUSTED_CERTIFICATE, all_purposes);
1632 	}
1633 
1634 	/*
1635 	 * TODO: Build pinned certificate assertions. That is, trusted
1636 	 * certificates where not an authority.
1637 	 */
1638 
1639 	if (trust && authority && positives) {
1640 		if (purposes) {
1641 			/* If purposes explicitly set, then anchor for those purposes */
1642 			build_assertions (positives, cert, CKT_X_ANCHORED_CERTIFICATE, purposes);
1643 		} else {
1644 			/* If purposes not-explicitly set, then anchor for all known */
1645 			build_assertions (positives, cert, CKT_X_ANCHORED_CERTIFICATE, all_purposes);
1646 		}
1647 	}
1648 }
1649 
1650 static void
replace_trust_assertions(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert,CK_BBOOL trust,CK_BBOOL distrust,CK_BBOOL authority,const char ** purposes,const char ** rejects)1651 replace_trust_assertions (p11_builder *builder,
1652                           p11_index *index,
1653                           CK_ATTRIBUTE *cert,
1654                           CK_BBOOL trust,
1655                           CK_BBOOL distrust,
1656                           CK_BBOOL authority,
1657                           const char **purposes,
1658                           const char **rejects)
1659 {
1660 	CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
1661 	CK_BBOOL generated = CK_TRUE;
1662 	p11_array *positives = NULL;
1663 	p11_array *negatives = NULL;
1664 	CK_ATTRIBUTE *value;
1665 	CK_ATTRIBUTE *issuer;
1666 	CK_ATTRIBUTE *serial;
1667 	CK_RV rv;
1668 
1669 	CK_ATTRIBUTE match_positive[] = {
1670 		{ CKA_X_CERTIFICATE_VALUE, },
1671 		{ CKA_CLASS, &assertion, sizeof (assertion) },
1672 		{ CKA_X_GENERATED, &generated, sizeof (generated) },
1673 		{ CKA_INVALID }
1674 	};
1675 
1676 	CK_ATTRIBUTE match_negative[] = {
1677 		{ CKA_ISSUER, },
1678 		{ CKA_SERIAL_NUMBER, },
1679 		{ CKA_CLASS, &assertion, sizeof (assertion) },
1680 		{ CKA_X_GENERATED, &generated, sizeof (generated) },
1681 		{ CKA_INVALID }
1682 	};
1683 
1684 	value = p11_attrs_find_valid (cert, CKA_VALUE);
1685 	if (value) {
1686 		positives = p11_array_new (NULL);
1687 		match_positive[0].pValue = value->pValue;
1688 		match_positive[0].ulValueLen = value->ulValueLen;
1689 	}
1690 
1691 	issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
1692 	serial = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
1693 	if (issuer && serial) {
1694 		negatives = p11_array_new (NULL);
1695 		memcpy (match_negative + 0, issuer, sizeof (CK_ATTRIBUTE));
1696 		memcpy (match_negative + 1, serial, sizeof (CK_ATTRIBUTE));
1697 	}
1698 
1699 	build_trust_assertions (positives, negatives, cert, trust, distrust,
1700 	                        authority, purposes, rejects);
1701 
1702 	if (positives) {
1703 		rv = p11_index_replace_all (index, match_positive, CKA_X_PURPOSE, positives);
1704 		return_if_fail (rv == CKR_OK);
1705 		p11_array_free (positives);
1706 	}
1707 
1708 	if (negatives) {
1709 		rv = p11_index_replace_all (index, match_negative, CKA_X_PURPOSE, negatives);
1710 		return_if_fail (rv == CKR_OK);
1711 		p11_array_free (negatives);
1712 	}
1713 }
1714 
1715 static void
remove_trust_and_assertions(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * attrs)1716 remove_trust_and_assertions (p11_builder *builder,
1717                              p11_index *index,
1718                              CK_ATTRIBUTE *attrs)
1719 {
1720 	replace_nss_trust_object (builder, index, attrs,
1721 	                          CK_FALSE, CK_FALSE, CK_FALSE,
1722 	                          NULL, NULL);
1723 	replace_trust_assertions (builder, index, attrs,
1724 	                          CK_FALSE, CK_FALSE, CK_FALSE,
1725 	                          NULL, NULL);
1726 }
1727 
1728 static void
replace_trust_and_assertions(p11_builder * builder,p11_index * index,CK_ATTRIBUTE * cert)1729 replace_trust_and_assertions (p11_builder *builder,
1730                               p11_index *index,
1731                               CK_ATTRIBUTE *cert)
1732 {
1733 	CK_BBOOL trust = CK_FALSE;
1734 	CK_BBOOL distrust = CK_FALSE;
1735 	CK_BBOOL authority = CK_FALSE;
1736 	p11_array *purposes = NULL;
1737 	p11_array *rejects = NULL;
1738 	const char **purposev;
1739 	const char **rejectv;
1740 	CK_ULONG category;
1741 	unsigned char *ext;
1742 	size_t ext_len;
1743 
1744 	/*
1745 	 * We look up all this information in advance, since it's used
1746 	 * by the various adapter objects, and we don't have to parse
1747 	 * it multiple times.
1748 	 */
1749 
1750 	if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &trust))
1751 		trust = CK_FALSE;
1752 	if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &distrust))
1753 		distrust = CK_FALSE;
1754 	if (p11_attrs_find_ulong (cert, CKA_CERTIFICATE_CATEGORY, &category) && category == 2)
1755 		authority = CK_TRUE;
1756 
1757 	if (!distrust) {
1758 		ext = lookup_extension (builder, index, cert, NULL, P11_OID_EXTENDED_KEY_USAGE, &ext_len);
1759 		if (ext != NULL) {
1760 			purposes = p11_x509_parse_extended_key_usage (builder->asn1_defs, ext, ext_len);
1761 			if (purposes == NULL)
1762 				p11_message (_("invalid extended key usage certificate extension"));
1763 			free (ext);
1764 		}
1765 
1766 		ext = lookup_extension (builder, index, cert, NULL, P11_OID_OPENSSL_REJECT, &ext_len);
1767 		if (ext != NULL) {
1768 			rejects = p11_x509_parse_extended_key_usage (builder->asn1_defs, ext, ext_len);
1769 			if (rejects == NULL)
1770 				p11_message (_("invalid reject key usage certificate extension"));
1771 			free (ext);
1772 		}
1773 	}
1774 
1775 	/* null-terminate these arrays and use as strv's */
1776 	purposev = rejectv = NULL;
1777 	if (rejects) {
1778 		if (!p11_array_push (rejects, NULL))
1779 			return_if_reached ();
1780 		rejectv = (const char **)rejects->elem;
1781 	}
1782 	if (purposes) {
1783 		if (!p11_array_push (purposes, NULL))
1784 			return_if_reached ();
1785 		purposev = (const char **)purposes->elem;
1786 	}
1787 
1788 	replace_nss_trust_object (builder, index, cert, trust, distrust,
1789 	                          authority, purposev, rejectv);
1790 	replace_trust_assertions (builder, index, cert, trust, distrust,
1791 	                          authority, purposev, rejectv);
1792 
1793 	p11_array_free (purposes);
1794 	p11_array_free (rejects);
1795 }
1796 
1797 static void
replace_compat_for_cert(p11_builder * builder,p11_index * index,CK_OBJECT_HANDLE handle,CK_ATTRIBUTE * attrs)1798 replace_compat_for_cert (p11_builder *builder,
1799                          p11_index *index,
1800                          CK_OBJECT_HANDLE handle,
1801                          CK_ATTRIBUTE *attrs)
1802 {
1803 	static const CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
1804 	static const CK_CERTIFICATE_TYPE x509 = CKC_X_509;
1805 	CK_ATTRIBUTE *value;
1806 
1807 	CK_ATTRIBUTE match[] = {
1808 		{ CKA_VALUE, },
1809 		{ CKA_CLASS, (void *)&certificate, sizeof (certificate) },
1810 		{ CKA_CERTIFICATE_TYPE, (void *)&x509, sizeof (x509) },
1811 		{ CKA_INVALID }
1812 	};
1813 
1814 	/*
1815 	 * If this certificate is going away, then find duplicate. In this
1816 	 * case all the trust assertions are recalculated with this new
1817 	 * certificate in mind.
1818 	 */
1819 	if (handle == 0) {
1820 		value = p11_attrs_find_valid (attrs, CKA_VALUE);
1821 		if (value != NULL) {
1822 			match[0].pValue = value->pValue;
1823 			match[0].ulValueLen = value->ulValueLen;
1824 			handle = p11_index_find (index, match, -1);
1825 		}
1826 		if (handle != 0)
1827 			attrs = p11_index_lookup (index, handle);
1828 	}
1829 
1830 	if (handle == 0)
1831 		remove_trust_and_assertions (builder, index, attrs);
1832 	else
1833 		replace_trust_and_assertions (builder, index, attrs);
1834 }
1835 
1836 static void
replace_compat_for_ext(p11_builder * builder,p11_index * index,CK_OBJECT_HANDLE handle,CK_ATTRIBUTE * attrs)1837 replace_compat_for_ext (p11_builder *builder,
1838                         p11_index *index,
1839                         CK_OBJECT_HANDLE handle,
1840                         CK_ATTRIBUTE *attrs)
1841 {
1842 
1843 	CK_OBJECT_HANDLE *handles;
1844 	CK_ATTRIBUTE *public_key;
1845 	int i;
1846 
1847 	public_key = p11_attrs_find_valid (attrs, CKA_PUBLIC_KEY_INFO);
1848 	if (public_key == NULL)
1849 		return;
1850 
1851 	handles = lookup_related (index, CKO_CERTIFICATE, public_key);
1852 	for (i = 0; handles && handles[i] != 0; i++) {
1853 		attrs = p11_index_lookup (index, handles[i]);
1854 		replace_trust_and_assertions (builder, index, attrs);
1855 	}
1856 	free (handles);
1857 }
1858 
1859 static void
update_related_category(p11_builder * builder,p11_index * index,CK_OBJECT_HANDLE handle,CK_ATTRIBUTE * attrs)1860 update_related_category (p11_builder *builder,
1861                          p11_index *index,
1862                          CK_OBJECT_HANDLE handle,
1863                          CK_ATTRIBUTE *attrs)
1864 {
1865 	CK_OBJECT_HANDLE *handles;
1866 	CK_ULONG categoryv = 0UL;
1867 	CK_ATTRIBUTE *update;
1868 	CK_ATTRIBUTE *cert;
1869 	CK_ATTRIBUTE *public_key;
1870 	CK_RV rv;
1871 	int i;
1872 
1873 	CK_ATTRIBUTE category[] = {
1874 		{ CKA_CERTIFICATE_CATEGORY, &categoryv, sizeof (categoryv) },
1875 		{ CKA_INVALID, },
1876 	};
1877 
1878 	public_key = p11_attrs_find_valid (attrs, CKA_PUBLIC_KEY_INFO);
1879 	if (public_key == NULL)
1880 		return;
1881 
1882 	/* Find all other objects with this handle */
1883 	handles = lookup_related (index, CKO_CERTIFICATE, public_key);
1884 
1885 	for (i = 0; handles && handles[i] != 0; i++) {
1886 		cert = p11_index_lookup (index, handle);
1887 
1888 		if (calc_certificate_category (builder, index, cert, public_key, &categoryv)) {
1889 			update = p11_attrs_build (NULL, &category, NULL);
1890 			rv = p11_index_update (index, handles[i], update);
1891 			return_if_fail (rv == CKR_OK);
1892 		}
1893 	}
1894 
1895 	free (handles);
1896 }
1897 
1898 void
p11_builder_changed(void * bilder,p11_index * index,CK_OBJECT_HANDLE handle,CK_ATTRIBUTE * attrs)1899 p11_builder_changed (void *bilder,
1900                      p11_index *index,
1901                      CK_OBJECT_HANDLE handle,
1902                      CK_ATTRIBUTE *attrs)
1903 {
1904 	static const CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
1905 	static const CK_OBJECT_CLASS extension = CKO_X_CERTIFICATE_EXTENSION;
1906 	static const CK_CERTIFICATE_TYPE x509 = CKC_X_509;
1907 
1908 	static const CK_ATTRIBUTE match_cert[] = {
1909 		{ CKA_CLASS, (void *)&certificate, sizeof (certificate) },
1910 		{ CKA_CERTIFICATE_TYPE, (void *)&x509, sizeof (x509) },
1911 		{ CKA_INVALID }
1912 	};
1913 
1914 	static const CK_ATTRIBUTE match_eku[] = {
1915 		{ CKA_CLASS, (void *)&extension, sizeof (extension) },
1916 		{ CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE,
1917 		  sizeof (P11_OID_EXTENDED_KEY_USAGE) },
1918 		{ CKA_INVALID }
1919 	};
1920 
1921 	static const CK_ATTRIBUTE match_ku[] = {
1922 		{ CKA_CLASS, (void *)&extension, sizeof (extension) },
1923 		{ CKA_OBJECT_ID, (void *)P11_OID_KEY_USAGE,
1924 		  sizeof (P11_OID_KEY_USAGE) },
1925 		{ CKA_INVALID }
1926 	};
1927 
1928 	static const CK_ATTRIBUTE match_bc[] = {
1929 		{ CKA_CLASS, (void *)&extension, sizeof (extension) },
1930 		{ CKA_OBJECT_ID, (void *)P11_OID_BASIC_CONSTRAINTS,
1931 		  sizeof (P11_OID_BASIC_CONSTRAINTS) },
1932 		{ CKA_INVALID }
1933 	};
1934 
1935 	p11_builder *builder = bilder;
1936 
1937 	return_if_fail (builder != NULL);
1938 	return_if_fail (index != NULL);
1939 	return_if_fail (attrs != NULL);
1940 
1941 	/*
1942 	 * Treat these operations as loading, not modifying/creating, so we get
1943 	 * around many of the rules that govern object creation
1944 	 */
1945 	p11_index_load (index);
1946 
1947 	/* A certificate */
1948 	if (p11_attrs_match (attrs, match_cert)) {
1949 		replace_compat_for_cert (builder, index, handle, attrs);
1950 
1951 	/* An ExtendedKeyUsage extension */
1952 	} else if (p11_attrs_match (attrs, match_eku) ||
1953 	           p11_attrs_match (attrs, match_ku)) {
1954 		replace_compat_for_ext (builder, index, handle, attrs);
1955 
1956 	/* A BasicConstraints extension */
1957 	} else if (p11_attrs_match (attrs, match_bc)) {
1958 		update_related_category (builder, index, handle, attrs);
1959 	}
1960 
1961 	p11_index_finish (index);
1962 }
1963