xref: /illumos-gate/usr/src/lib/libkmf/libkmf/common/certgetsetop.c (revision 24da5b34f49324ed742a340010ed5bd3d4e06625)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <link.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <ber_der.h>
40 #include <kmfapiP.h>
41 #include <libgen.h>
42 #include <cryptoutil.h>
43 
44 KMF_RETURN
45 copy_data(KMF_DATA *dst, KMF_DATA *src)
46 {
47 	KMF_RETURN ret = KMF_OK;
48 
49 	if (dst == NULL || src == NULL)
50 		return (KMF_ERR_BAD_PARAMETER);
51 
52 	dst->Data = malloc(src->Length);
53 	if (dst->Data == NULL)
54 		return (KMF_ERR_MEMORY);
55 
56 	dst->Length = src->Length;
57 	(void) memcpy(dst->Data, src->Data, src->Length);
58 
59 	return (ret);
60 }
61 
62 static KMF_RETURN
63 copy_extension_data(KMF_X509_EXTENSION *dstext,
64 	KMF_X509_EXTENSION *srcext)
65 {
66 	KMF_RETURN ret = KMF_OK;
67 
68 	if (dstext == NULL || srcext == NULL)
69 		return (KMF_ERR_BAD_PARAMETER);
70 
71 	(void) memset(dstext, 0, sizeof (KMF_X509_EXTENSION));
72 
73 	ret = copy_data(&dstext->extnId, &srcext->extnId);
74 	if (ret != KMF_OK)
75 		goto cleanup;
76 
77 	dstext->extnId.Length = srcext->extnId.Length;
78 	dstext->critical = srcext->critical;
79 	dstext->format = srcext->format;
80 
81 	ret = copy_data(&dstext->BERvalue, &srcext->BERvalue);
82 	if (ret != KMF_OK)
83 		goto cleanup;
84 
85 	dstext->value.tagAndValue = malloc(sizeof (KMF_X509EXT_TAGandVALUE));
86 	if (dstext->value.tagAndValue == NULL) {
87 		ret = KMF_ERR_MEMORY;
88 		goto cleanup;
89 	}
90 	(void) memset(dstext->value.tagAndValue, 0,
91 		sizeof (KMF_X509EXT_TAGandVALUE));
92 
93 	ret = copy_data(&dstext->value.tagAndValue->value,
94 			&srcext->value.tagAndValue->value);
95 	if (ret != KMF_OK)
96 		goto cleanup;
97 
98 	dstext->value.tagAndValue->type = srcext->value.tagAndValue->type;
99 
100 cleanup:
101 	if (ret != KMF_OK) {
102 		if (dstext->extnId.Data != NULL)
103 			KMF_FreeData(&dstext->extnId);
104 
105 		if (dstext->BERvalue.Data != NULL)
106 			KMF_FreeData(&dstext->BERvalue);
107 
108 		if (dstext->value.tagAndValue->value.Data == NULL)
109 			KMF_FreeData(&dstext->value.tagAndValue->value);
110 	}
111 
112 	return (ret);
113 }
114 
115 /*
116  * Given a block of DER encoded X.509 certificate data and
117  * an OID for the desired extension, this routine will
118  * parse the cert data and return the data associated with
119  * the extension if it is found.
120  *
121  * RETURNS:
122  *   KMF_OK - if extension found and copied OK.
123  *   KMF_ERR_EXTENSION_NOT_FOUND - extension not found.
124  *   parsing and memory allocation errors are also possible.
125  */
126 KMF_RETURN
127 KMF_GetCertExtensionData(const KMF_DATA *certdata,
128 	KMF_OID *extoid, KMF_X509_EXTENSION *extdata)
129 {
130 	KMF_RETURN ret = KMF_OK;
131 	KMF_X509_CERTIFICATE *cert = NULL;
132 	KMF_X509_EXTENSION *eptr = NULL;
133 	int i, found = 0;
134 
135 	if (certdata == NULL || extoid == NULL || extdata == NULL)
136 		return (KMF_ERR_BAD_PARAMETER);
137 
138 	ret = DerDecodeSignedCertificate(certdata, &cert);
139 	if (ret != KMF_OK)
140 		return (ret);
141 
142 	if (cert->certificate.extensions.numberOfExtensions == 0)
143 		return (KMF_ERR_EXTENSION_NOT_FOUND);
144 
145 	(void) memset((void *)extdata, 0, sizeof (KMF_X509_EXTENSION));
146 	for (i = 0; !found &&
147 	    i < cert->certificate.extensions.numberOfExtensions;
148 	    i++) {
149 		eptr = &cert->certificate.extensions.extensions[i];
150 		if (IsEqualOid(extoid, &eptr->extnId)) {
151 			ret = copy_extension_data(extdata, eptr);
152 			found++;
153 		}
154 	}
155 	if (!found)
156 		ret = KMF_ERR_EXTENSION_NOT_FOUND;
157 
158 	if (cert != NULL) {
159 		KMF_FreeSignedCert(cert);
160 		free(cert);
161 	}
162 
163 	return (ret);
164 }
165 
166 /*
167  * Given a block of DER encoded X.509 certificate data,
168  * search the extensions and return the OIDs for all
169  * extensions marked "critical".
170  *
171  *
172  * RETURNS:
173  *   KMF_OK - if extension found and copied OK.
174  *   parsing and memory allocation errors are also possible.
175  *
176  *   OIDlist - array of KMF_OID records, allocated
177  *             by this function.
178  *   NumOIDs - number of critical extensions found.
179  */
180 KMF_RETURN
181 KMF_GetCertCriticalExtensions(const KMF_DATA *certdata,
182 	KMF_X509_EXTENSION **extlist, int *nextns)
183 {
184 	KMF_RETURN ret = KMF_OK;
185 	KMF_X509_CERTIFICATE *cert;
186 	KMF_X509_EXTENSION *eptr, *elist;
187 	int i;
188 
189 	if (certdata == NULL || extlist == NULL || nextns == NULL)
190 		return (KMF_ERR_BAD_PARAMETER);
191 
192 	*nextns = 0;
193 	*extlist = elist = NULL;
194 	ret = DerDecodeSignedCertificate(certdata, &cert);
195 	if (ret != KMF_OK)
196 		return (ret);
197 
198 	if (cert->certificate.extensions.numberOfExtensions == 0)
199 		return (KMF_ERR_EXTENSION_NOT_FOUND);
200 
201 	for (i = 0; i < cert->certificate.extensions.numberOfExtensions;
202 	    i++) {
203 		eptr = &cert->certificate.extensions.extensions[i];
204 		if (eptr->critical != 0) {
205 			(*nextns)++;
206 			elist = realloc(elist, sizeof (KMF_X509_EXTENSION) *
207 					(*nextns));
208 			if (elist == NULL) {
209 				ret = KMF_ERR_MEMORY;
210 				goto end;
211 			}
212 			ret = copy_extension_data(&elist[(*nextns) - 1],
213 				eptr);
214 			if (ret != KMF_OK)
215 				goto end;
216 		}
217 	}
218 end:
219 	KMF_FreeSignedCert(cert);
220 	free(cert);
221 	if (ret != KMF_OK) {
222 		if (elist != NULL) {
223 			free(elist);
224 			elist = NULL;
225 		}
226 		*nextns = 0;
227 	}
228 	*extlist = elist;
229 
230 	return (ret);
231 }
232 
233 /*
234  * Given a block of DER encoded X.509 certificate data,
235  * search the extensions and return the OIDs for all
236  * extensions NOT marked "critical".
237  *
238  *
239  * RETURNS:
240  *   KMF_OK - if extension found and copied OK.
241  *   parsing and memory allocation errors are also possible.
242  *
243  *   OIDlist - array of KMF_OID records, allocated
244  *             by this function.
245  *   NumOIDs - number of critical extensions found.
246  */
247 KMF_RETURN
248 KMF_GetCertNonCriticalExtensions(const KMF_DATA *certdata,
249 	KMF_X509_EXTENSION **extlist, int *nextns)
250 {
251 	KMF_RETURN ret = KMF_OK;
252 	KMF_X509_CERTIFICATE *cert;
253 	KMF_X509_EXTENSION *eptr, *elist;
254 	int i;
255 
256 	if (certdata == NULL || extlist == NULL || nextns == NULL)
257 		return (KMF_ERR_BAD_PARAMETER);
258 
259 	*nextns = 0;
260 	*extlist = elist = NULL;
261 	ret = DerDecodeSignedCertificate(certdata, &cert);
262 	if (ret != KMF_OK)
263 		return (ret);
264 
265 	if (cert->certificate.extensions.numberOfExtensions == 0)
266 		return (KMF_ERR_EXTENSION_NOT_FOUND);
267 
268 	for (i = 0; i < cert->certificate.extensions.numberOfExtensions;
269 	    i++) {
270 		eptr = &cert->certificate.extensions.extensions[i];
271 		if (eptr->critical == 0) {
272 			(*nextns)++;
273 			elist = realloc(elist, sizeof (KMF_X509_EXTENSION) *
274 					(*nextns));
275 			if (elist == NULL) {
276 				ret = KMF_ERR_MEMORY;
277 				goto end;
278 			}
279 			ret = copy_extension_data(&elist[(*nextns) - 1],
280 				eptr);
281 			if (ret != KMF_OK)
282 				goto end;
283 		}
284 	}
285 end:
286 	KMF_FreeSignedCert(cert);
287 	free(cert);
288 	if (ret != KMF_OK) {
289 		if (elist != NULL) {
290 			free(elist);
291 			elist = NULL;
292 		}
293 		*nextns = 0;
294 	}
295 	*extlist = elist;
296 
297 	return (ret);
298 }
299 
300 /*
301  * If the given certificate data (X.509 DER encoded data)
302  * contains the Key Usage extension, parse that
303  * data and return it in the KMF_X509EXT_BASICCONSTRAINTS
304  * record.
305  *
306  * RETURNS:
307  *  KMF_OK - success
308  *  KMF_ERR_BAD_PARAMETER - input data was bad.
309  *  KMF_ERR_EXTENSION_NOT_FOUND - extension not found.
310  */
311 KMF_RETURN
312 KMF_GetCertKeyUsageExt(const KMF_DATA *certdata,
313 	KMF_X509EXT_KEY_USAGE *keyusage)
314 {
315 	KMF_RETURN ret = KMF_OK;
316 	KMF_X509_EXTENSION extn;
317 
318 	if (certdata == NULL || keyusage == NULL)
319 		return (KMF_ERR_BAD_PARAMETER);
320 
321 	(void) memset(&extn, 0, sizeof (extn));
322 	/*
323 	 * Check standard KeyUsage bits
324 	 */
325 	ret = KMF_GetCertExtensionData(certdata,
326 		(KMF_OID *)&KMFOID_KeyUsage, &extn);
327 
328 	if (ret != KMF_OK) {
329 		goto end;
330 	}
331 	keyusage->critical = (extn.critical != 0);
332 	if (extn.value.tagAndValue->value.Length > 1) {
333 		keyusage->KeyUsageBits =
334 			extn.value.tagAndValue->value.Data[1] << 8;
335 	} else  {
336 		keyusage->KeyUsageBits =
337 			extn.value.tagAndValue->value.Data[0];
338 	}
339 end:
340 	KMF_FreeExtension(&extn);
341 	return (ret);
342 }
343 
344 static KMF_BOOL
345 isEKUPresent(KMF_X509EXT_EKU *ekuptr, KMF_OID *ekuoid)
346 {
347 	int i;
348 
349 	if (ekuptr == NULL || ekuoid == NULL)
350 		return (0);
351 
352 	for (i = 0; i < ekuptr->nEKUs; i++)
353 		if (IsEqualOid(&ekuptr->keyPurposeIdList[i], ekuoid))
354 			return (1);
355 
356 	return (0);
357 }
358 
359 static KMF_RETURN
360 parse_eku_data(const KMF_DATA *asn1data, KMF_X509EXT_EKU *ekuptr)
361 {
362 	KMF_RETURN ret = KMF_OK;
363 	BerElement *asn1 = NULL;
364 	BerValue exdata;
365 	KMF_OID oid;
366 	char *end = NULL;
367 	ber_len_t size;
368 
369 	/*
370 	 * Decode the ASN.1 data for the extension.
371 	 */
372 	exdata.bv_val = (char *)asn1data->Data;
373 	exdata.bv_len = asn1data->Length;
374 
375 	if ((asn1 = kmfder_init(&exdata)) == NULL) {
376 		ret = KMF_ERR_MEMORY;
377 		goto end;
378 	}
379 
380 	/*
381 	 * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
382 	 */
383 	if (kmfber_first_element(asn1, &size, &end) !=
384 		BER_OBJECT_IDENTIFIER) {
385 		ret = KMF_ERR_BAD_CERT_FORMAT;
386 		goto end;
387 	}
388 
389 	/*
390 	 * Count the number of EKU OIDs and store in
391 	 * the array.
392 	 */
393 	while (kmfber_next_element(asn1, &size, end) ==
394 		BER_OBJECT_IDENTIFIER) {
395 
396 		/* Skip over the CONSTRUCTED SET tag */
397 		if (kmfber_scanf(asn1, "D", &oid) == KMFBER_DEFAULT) {
398 			ret = KMF_ERR_BAD_CERT_FORMAT;
399 			goto end;
400 		}
401 		ekuptr->nEKUs++;
402 		ekuptr->keyPurposeIdList = realloc(ekuptr->keyPurposeIdList,
403 				ekuptr->nEKUs * sizeof (KMF_OID));
404 		if (ekuptr->keyPurposeIdList == NULL) {
405 			ret = KMF_ERR_MEMORY;
406 			goto end;
407 		}
408 		ekuptr->keyPurposeIdList[ekuptr->nEKUs - 1] = oid;
409 	}
410 
411 end:
412 	if (asn1 != NULL)
413 		kmfber_free(asn1, 1);
414 
415 	if (ret != KMF_OK) {
416 		if (ekuptr->keyPurposeIdList != NULL) {
417 			free_keyidlist(ekuptr->keyPurposeIdList, ekuptr->nEKUs);
418 			ekuptr->keyPurposeIdList = NULL;
419 			ekuptr->critical = 0;
420 		}
421 	}
422 
423 	return (ret);
424 }
425 
426 KMF_RETURN
427 KMF_GetCertEKU(const KMF_DATA *certdata,
428 	KMF_X509EXT_EKU *ekuptr)
429 {
430 	KMF_RETURN ret = KMF_OK;
431 	KMF_X509_EXTENSION extn;
432 
433 	if (certdata == NULL || ekuptr == NULL)
434 		return (KMF_ERR_BAD_PARAMETER);
435 
436 	(void) memset(&extn, 0, sizeof (KMF_X509_EXTENSION));
437 
438 	ekuptr->nEKUs = 0;
439 	ekuptr->keyPurposeIdList = NULL;
440 	ekuptr->critical = 0;
441 
442 	ret = KMF_GetCertExtensionData(certdata,
443 		(KMF_OID *)&KMFOID_ExtendedKeyUsage, &extn);
444 
445 	if (ret != KMF_OK) {
446 		goto end;
447 	}
448 
449 	ret = parse_eku_data(&extn.BERvalue, ekuptr);
450 
451 end:
452 	KMF_FreeExtension(&extn);
453 
454 	return (ret);
455 }
456 
457 /*
458  * If the given certificate data (X.509 DER encoded data)
459  * contains the Basic Constraints extension, parse that
460  * data and return it in the KMF_X509EXT_BASICCONSTRAINTS
461  * record.
462  *
463  * RETURNS:
464  *  KMF_OK - success
465  *  KMF_ERR_BAD_PARAMETER - input data was bad.
466  *  KMF_ERR_EXTENSION_NOT_FOUND - extension not found.
467  */
468 KMF_RETURN
469 KMF_GetCertBasicConstraintExt(const KMF_DATA *certdata,
470 	KMF_BOOL *critical, KMF_X509EXT_BASICCONSTRAINTS *constraint)
471 {
472 	KMF_RETURN ret = KMF_OK;
473 	KMF_X509_EXTENSION extn;
474 	BerElement *asn1 = NULL;
475 	BerValue exdata;
476 	ber_len_t size;
477 	char *end = NULL;
478 	int tag;
479 
480 	if (certdata == NULL || constraint == NULL || critical == NULL)
481 		return (KMF_ERR_BAD_PARAMETER);
482 
483 	(void) memset(&extn, 0, sizeof (KMF_X509_EXTENSION));
484 	ret = KMF_GetCertExtensionData(certdata,
485 		(KMF_OID *)&KMFOID_BasicConstraints, &extn);
486 
487 	if (ret != KMF_OK) {
488 		goto end;
489 	}
490 
491 	*critical = (extn.critical != 0);
492 
493 	exdata.bv_val = (char *)extn.value.tagAndValue->value.Data;
494 	exdata.bv_len = extn.value.tagAndValue->value.Length;
495 
496 	if ((asn1 = kmfder_init(&exdata)) == NULL) {
497 		ret = KMF_ERR_MEMORY;
498 		goto end;
499 	}
500 
501 	if (kmfber_scanf(asn1, "b", &constraint->cA) == KMFBER_DEFAULT) {
502 		ret = KMF_ERR_BAD_CERT_FORMAT;
503 		goto end;
504 	}
505 	constraint->pathLenConstraintPresent = KMF_FALSE;
506 
507 	tag = kmfber_next_element(asn1, &size, end);
508 	if (tag == BER_INTEGER) {
509 		if (kmfber_scanf(asn1, "i",
510 			&constraint->pathLenConstraint) == KMFBER_DEFAULT) {
511 			ret = KMF_ERR_BAD_CERT_FORMAT;
512 			goto end;
513 		}
514 		constraint->pathLenConstraintPresent = KMF_TRUE;
515 	}
516 end:
517 	KMF_FreeExtension(&extn);
518 	if (asn1 != NULL)
519 		kmfber_free(asn1, 1);
520 
521 	return (ret);
522 }
523 
524 static KMF_X509EXT_POLICYQUALIFIERINFO *
525 get_pqinfo(BerElement *asn1)
526 {
527 	KMF_X509EXT_POLICYQUALIFIERINFO *pqinfo = NULL;
528 	KMF_RETURN ret = KMF_OK;
529 	int tag;
530 	ber_len_t size;
531 	char *end = NULL;
532 
533 	/*
534 	 * Policy Qualifiers may be a list of sequences.
535 	 *
536 	 * PolicyInformation ::= SEQUENCE {
537 	 * 	policyIdentifier   CertPolicyId,
538 	 * 	policyQualifiers   SEQUENCE SIZE (1..MAX) OF
539 	 *			PolicyQualifierInfo OPTIONAL
540 	 * }
541 	 *
542 	 * PolicyQualifierInfo ::= SEQUENCE {
543 	 *	policyQualifierId  PolicyQualifierId,
544 	 *	qualifier	  ANY DEFINED BY policyQualifierId
545 	 * }
546 	 */
547 
548 
549 	/*
550 	 * We already got the CertPolicyId, we just need to
551 	 * find all of the policyQualifiers in the set.
552 	 *
553 	 * Mark the first element of the SEQUENCE and reset the end ptr
554 	 * so the ber/der code knows when to stop looking.
555 	 */
556 	if ((tag = kmfber_first_element(asn1, &size, &end)) !=
557 		BER_CONSTRUCTED_SEQUENCE) {
558 		ret = KMF_ERR_BAD_CERT_FORMAT;
559 		goto end;
560 	}
561 	/* We found a sequence, loop until done */
562 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
563 		BER_CONSTRUCTED_SEQUENCE) {
564 
565 		/* Skip over the CONSTRUCTED SET tag */
566 		if (kmfber_scanf(asn1, "T", &tag) == KMFBER_DEFAULT) {
567 			ret = KMF_ERR_BAD_CERT_FORMAT;
568 			goto end;
569 		}
570 		/*
571 		 * Allocate memory for the Policy Qualifier Info
572 		 */
573 		pqinfo = malloc(sizeof (KMF_X509EXT_POLICYQUALIFIERINFO));
574 		if (pqinfo == NULL) {
575 			ret = KMF_ERR_MEMORY;
576 			goto end;
577 		}
578 		(void) memset((void *)pqinfo, 0,
579 			sizeof (KMF_X509EXT_POLICYQUALIFIERINFO));
580 		/*
581 		 * Read the PolicyQualifier OID
582 		 */
583 		if (kmfber_scanf(asn1, "D",
584 			&pqinfo->policyQualifierId) == KMFBER_DEFAULT) {
585 			ret = KMF_ERR_BAD_CERT_FORMAT;
586 			goto end;
587 		}
588 		/*
589 		 * The OID of the policyQualifierId determines what
590 		 * sort of data comes next.
591 		 */
592 		if (IsEqualOid(&pqinfo->policyQualifierId,
593 			(KMF_OID *)&KMFOID_PKIX_PQ_CPSuri)) {
594 			/*
595 			 * CPS uri must be an IA5STRING
596 			 */
597 			if (kmfber_scanf(asn1, "tl", &tag, &size) ==
598 				KMFBER_DEFAULT || tag != BER_IA5STRING ||
599 				size == 0) {
600 				ret = KMF_ERR_BAD_CERT_FORMAT;
601 				goto end;
602 			}
603 			if ((pqinfo->value.Data = malloc(size)) == NULL) {
604 				ret = KMF_ERR_MEMORY;
605 				goto end;
606 			}
607 			if (kmfber_scanf(asn1, "s", pqinfo->value.Data,
608 				&pqinfo->value.Length) == KMFBER_DEFAULT) {
609 				ret = KMF_ERR_BAD_CERT_FORMAT;
610 				goto end;
611 			}
612 		} else if (IsEqualOid(&pqinfo->policyQualifierId,
613 			(KMF_OID *)&KMFOID_PKIX_PQ_Unotice)) {
614 			if (kmfber_scanf(asn1, "tl", &tag, &size) ==
615 				KMFBER_DEFAULT ||
616 				tag != BER_CONSTRUCTED_SEQUENCE) {
617 				ret = KMF_ERR_BAD_CERT_FORMAT;
618 				goto end;
619 			}
620 			/*
621 			 * For now, just copy the while UserNotice ASN.1
622 			 * blob into the pqinfo data record.
623 			 * TBD - parse it into individual fields.
624 			 */
625 			if ((pqinfo->value.Data = malloc(size)) == NULL) {
626 				ret = KMF_ERR_MEMORY;
627 				goto end;
628 			}
629 			if (kmfber_scanf(asn1, "s", pqinfo->value.Data,
630 				&pqinfo->value.Length) == KMFBER_DEFAULT) {
631 				ret = KMF_ERR_BAD_CERT_FORMAT;
632 				goto end;
633 			}
634 		} else {
635 			ret = KMF_ERR_BAD_CERT_FORMAT;
636 			goto end;
637 		}
638 	}
639 end:
640 	if (ret != KMF_OK) {
641 		if (pqinfo != NULL) {
642 			KMF_FreeData(&pqinfo->value);
643 			KMF_FreeData(&pqinfo->policyQualifierId);
644 			free(pqinfo);
645 			pqinfo = NULL;
646 		}
647 	}
648 	return (pqinfo);
649 }
650 
651 /*
652  * If the given certificate data (X.509 DER encoded data)
653  * contains the Certificate Policies extension, parse that
654  * data and return it in the KMF_X509EXT_CERT_POLICIES
655  * record.
656  *
657  * RETURNS:
658  *  KMF_OK - success
659  *  KMF_ERR_BAD_PARAMETER - input data was bad.
660  *  KMF_ERR_EXTENSION_NOT_FOUND - extension not found.
661  *  parsing and memory allocation errors are also possible.
662  */
663 KMF_RETURN
664 KMF_GetCertPoliciesExt(const KMF_DATA *certdata,
665 	KMF_BOOL *critical, KMF_X509EXT_CERT_POLICIES *extptr)
666 {
667 	KMF_RETURN ret = KMF_OK;
668 	KMF_X509_EXTENSION extn;
669 	KMF_X509EXT_POLICYINFO	*pinfo;
670 	KMF_X509EXT_POLICYQUALIFIERINFO *pqinfo;
671 	BerElement *asn1 = NULL;
672 	BerValue exdata;
673 	ber_len_t size;
674 	char *end = NULL;
675 	int tag;
676 
677 	if (certdata == NULL || critical == NULL || extptr == NULL)
678 		return (KMF_ERR_BAD_PARAMETER);
679 
680 	(void) memset(&extn, 0, sizeof (extn));
681 	ret = KMF_GetCertExtensionData(certdata,
682 		(KMF_OID *)&KMFOID_CertificatePolicies, &extn);
683 
684 	if (ret != KMF_OK) {
685 		goto end;
686 	}
687 
688 	*critical = (extn.critical != 0);
689 
690 	/*
691 	 * Decode the ASN.1 data for the extension.
692 	 */
693 	exdata.bv_val = (char *)extn.BERvalue.Data;
694 	exdata.bv_len = extn.BERvalue.Length;
695 
696 	(void) memset((void *)extptr, 0, sizeof (KMF_X509EXT_CERT_POLICIES));
697 
698 	if ((asn1 = kmfder_init(&exdata)) == NULL) {
699 		ret = KMF_ERR_MEMORY;
700 		goto end;
701 	}
702 
703 	/*
704 	 * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
705 	 */
706 	if ((tag = kmfber_first_element(asn1, &size, &end)) !=
707 		BER_CONSTRUCTED_SEQUENCE) {
708 		ret = KMF_ERR_BAD_CERT_FORMAT;
709 		goto end;
710 	}
711 
712 	/*
713 	 * Collect all of the PolicyInformation SEQUENCES
714 	 *
715 	 * PolicyInformation ::= SEQUENCE {
716 	 * 	policyIdentifier   CertPolicyId,
717 	 * 	policyQualifiers   SEQUENCE SIZE (1..MAX) OF
718 	 *			PolicyQualifierInfo OPTIONAL
719 	 * }
720 	 *
721 	 * Loop over the SEQUENCES of PolicyInfo
722 	 */
723 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
724 		BER_CONSTRUCTED_SEQUENCE) {
725 
726 		/* Skip over the CONSTRUCTED SET tag */
727 		if (kmfber_scanf(asn1, "T", &tag) == KMFBER_DEFAULT) {
728 			ret = KMF_ERR_BAD_CERT_FORMAT;
729 			goto end;
730 		}
731 
732 		pinfo = malloc(sizeof (KMF_X509EXT_POLICYINFO));
733 		if (pinfo == NULL) {
734 			ret = KMF_ERR_MEMORY;
735 			goto end;
736 		}
737 		(void) memset((void *)pinfo, 0,
738 			sizeof (KMF_X509EXT_POLICYINFO));
739 		/*
740 		 * Decode the PolicyInformation SEQUENCE
741 		 */
742 		if ((tag = kmfber_scanf(asn1, "D",
743 			&pinfo->policyIdentifier)) == KMFBER_DEFAULT) {
744 			ret = KMF_ERR_BAD_CERT_FORMAT;
745 			goto end;
746 		}
747 		/*
748 		 * Gather all of the associated PolicyQualifierInfo recs
749 		 */
750 		pqinfo = get_pqinfo(asn1);
751 		if (pqinfo != NULL) {
752 			int cnt =
753 			    pinfo->policyQualifiers.numberOfPolicyQualifiers;
754 			cnt++;
755 			pinfo->policyQualifiers.policyQualifier = realloc(
756 				pinfo->policyQualifiers.policyQualifier,
757 				cnt * sizeof (KMF_X509EXT_POLICYQUALIFIERINFO));
758 			if (pinfo->policyQualifiers.policyQualifier == NULL) {
759 				ret = KMF_ERR_MEMORY;
760 				goto end;
761 			}
762 			pinfo->policyQualifiers.numberOfPolicyQualifiers =
763 				cnt;
764 			pinfo->policyQualifiers.policyQualifier[cnt-1] =
765 				*pqinfo;
766 
767 			free(pqinfo);
768 		}
769 		extptr->numberOfPolicyInfo++;
770 		extptr->policyInfo = realloc(extptr->policyInfo,
771 			extptr->numberOfPolicyInfo *
772 			sizeof (KMF_X509EXT_POLICYINFO));
773 		if (extptr->policyInfo == NULL) {
774 			ret = KMF_ERR_MEMORY;
775 			goto end;
776 		}
777 		extptr->policyInfo[extptr->numberOfPolicyInfo-1] = *pinfo;
778 		free(pinfo);
779 	}
780 
781 
782 end:
783 	KMF_FreeExtension(&extn);
784 	if (asn1 != NULL)
785 		kmfber_free(asn1, 1);
786 	return (ret);
787 }
788 
789 /*
790  * If the given certificate data (X.509 DER encoded data)
791  * contains the Authority Information Access extension, parse that
792  * data and return it in the KMF_X509EXT_AUTHINFOACCESS
793  * record.
794  *
795  * RETURNS:
796  *  KMF_OK - success
797  *  KMF_ERR_BAD_PARAMETER - input data was bad.
798  *  KMF_ERR_EXTENSION_NOT_FOUND - extension not found.
799  */
800 KMF_RETURN
801 KMF_GetCertAuthInfoAccessExt(const KMF_DATA *certdata,
802 	KMF_X509EXT_AUTHINFOACCESS *aia)
803 {
804 	KMF_RETURN ret = KMF_OK;
805 	KMF_X509_EXTENSION extn;
806 	BerElement *asn1 = NULL;
807 	BerValue exdata;
808 	ber_len_t size;
809 	char *end = NULL;
810 	int tag;
811 	KMF_X509EXT_ACCESSDESC *access_info = NULL;
812 
813 	if (certdata == NULL || aia == NULL) {
814 		return (KMF_ERR_BAD_PARAMETER);
815 	}
816 
817 	(void) memset(&extn, 0, sizeof (KMF_X509_EXTENSION));
818 	ret = KMF_GetCertExtensionData(certdata,
819 	    (KMF_OID *)&KMFOID_AuthorityInfoAccess, &extn);
820 
821 	if (ret != KMF_OK) {
822 		goto end;
823 	}
824 
825 	/*
826 	 * Decode the ASN.1 data for the extension.
827 	 */
828 	exdata.bv_val = (char *)extn.BERvalue.Data;
829 	exdata.bv_len = extn.BERvalue.Length;
830 
831 	(void) memset((void *)aia, 0, sizeof (KMF_X509EXT_AUTHINFOACCESS));
832 
833 	if ((asn1 = kmfder_init(&exdata)) == NULL) {
834 		ret = KMF_ERR_MEMORY;
835 		goto end;
836 	}
837 
838 	/*
839 	 * AuthorityInfoAccessSyntax  ::=
840 	 *	SEQUENCE SIZE (1..MAX) OF AccessDescription
841 	 */
842 	if ((tag = kmfber_first_element(asn1, &size, &end)) !=
843 	    BER_CONSTRUCTED_SEQUENCE) {
844 		ret = KMF_ERR_BAD_CERT_FORMAT;
845 		goto end;
846 	}
847 
848 	/*
849 	 * AccessDescription  ::=  SEQUENCE {
850 	 *	accessMethod	OBJECT IDENTIFIER,
851 	 *	accessLocation	GeneralName  }
852 	 */
853 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
854 	    BER_CONSTRUCTED_SEQUENCE) {
855 
856 		/* Skip over the CONSTRUCTED SET tag */
857 		if (kmfber_scanf(asn1, "T", &tag) == KMFBER_DEFAULT) {
858 			ret = KMF_ERR_BAD_CERT_FORMAT;
859 			goto end;
860 		}
861 
862 		access_info = malloc(sizeof (KMF_X509EXT_ACCESSDESC));
863 		if (access_info == NULL) {
864 			ret = KMF_ERR_MEMORY;
865 			goto end;
866 		}
867 
868 		(void) memset((void *)access_info, 0,
869 		    sizeof (KMF_X509EXT_ACCESSDESC));
870 
871 		/*
872 		 * Read the AccessMethod OID
873 		 */
874 		if (kmfber_scanf(asn1, "D",
875 		    &access_info->AccessMethod) == KMFBER_DEFAULT) {
876 			ret = KMF_ERR_BAD_CERT_FORMAT;
877 			goto end;
878 		}
879 
880 		/*
881 		 * The OID of the AccessMethod determines what
882 		 * sort of data comes next.
883 		 */
884 		if (IsEqualOid(&access_info->AccessMethod,
885 		    (KMF_OID *)&KMFOID_PkixAdOcsp)) {
886 			if (kmfber_scanf(asn1, "tl", &tag, &size) ==
887 			    KMFBER_DEFAULT || size == 0) {
888 				ret = KMF_ERR_BAD_CERT_FORMAT;
889 				goto end;
890 			}
891 
892 			/*
893 			 * OCSP uri must be an IA5STRING or a GENNAME_URI
894 			 * with an implicit tag.
895 			 */
896 			if (tag != BER_IA5STRING &&
897 			    tag != (0x80 | GENNAME_URI)) {
898 				ret = KMF_ERR_BAD_CERT_FORMAT;
899 				goto end;
900 			}
901 
902 			if ((access_info->AccessLocation.Data =
903 			    malloc(size)) == NULL) {
904 				ret = KMF_ERR_MEMORY;
905 				goto end;
906 			}
907 
908 			if (kmfber_scanf(asn1, "s",
909 			    access_info->AccessLocation.Data,
910 			    &access_info->AccessLocation.Length) ==
911 				KMFBER_DEFAULT) {
912 				ret = KMF_ERR_BAD_CERT_FORMAT;
913 				goto end;
914 			}
915 		} else if (IsEqualOid(&access_info->AccessMethod,
916 			(KMF_OID *)&KMFOID_PkixAdCaIssuers)) {
917 			/* will be supported later with PKIX */
918 			free(access_info);
919 			access_info = NULL;
920 			continue;
921 		} else {
922 			ret = KMF_ERR_BAD_CERT_FORMAT;
923 			goto end;
924 		}
925 
926 		aia->numberOfAccessDescription++;
927 		aia->AccessDesc = realloc(aia->AccessDesc,
928 		    aia->numberOfAccessDescription *
929 		    sizeof (KMF_X509EXT_ACCESSDESC));
930 
931 		if (aia->AccessDesc == NULL) {
932 			ret = KMF_ERR_MEMORY;
933 			goto end;
934 		}
935 
936 		aia->AccessDesc[aia->numberOfAccessDescription-1] =
937 		    *access_info;
938 		free(access_info);
939 		access_info = NULL;
940 	}
941 
942 end:
943 	KMF_FreeExtension(&extn);
944 	if (access_info != NULL)
945 		free(access_info);
946 	if (asn1 != NULL)
947 		kmfber_free(asn1, 1);
948 	return (ret);
949 
950 }
951 
952 /*
953  * This function parses the name portion of a der-encoded distribution point
954  * returns it in the KMF_CRL_DIST_POINT record.
955  *
956  * The "DistributionPointName" syntax is
957  *
958  *   DistributionPointName ::= CHOICE {
959  *	fullName                [0]     GeneralNames,
960  *	nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
961  *
962  *   GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GerneralName
963  *
964  * Note: for phase 1, we support fullName only.
965  */
966 static KMF_RETURN
967 parse_dp_name(char *dp_der_code, int dp_der_size, KMF_CRL_DIST_POINT *dp)
968 {
969 	KMF_RETURN ret = KMF_OK;
970 	char *url = NULL;
971 	BerElement *asn1 = NULL;
972 	BerValue ber_data;
973 	ber_len_t size;
974 	char *end = NULL;
975 	int tag;
976 	KMF_GENERALNAMES *fullname;
977 
978 	if (dp_der_code == NULL || dp_der_size == 0 || dp == NULL)
979 		return (KMF_ERR_BAD_PARAMETER);
980 
981 	ber_data.bv_val = dp_der_code;
982 	ber_data.bv_len = dp_der_size;
983 	if ((asn1 = kmfder_init(&ber_data)) == NULL)
984 		return (KMF_ERR_BAD_CERT_FORMAT);
985 
986 	tag = kmfber_first_element(asn1, &size, &end);
987 	if (tag != 0xA0 && tag != 0xA1) {
988 		ret = KMF_ERR_BAD_CERT_FORMAT;
989 		goto out;
990 	}
991 
992 	if (tag == 0xA0) { /* fullName */
993 		dp->type = DP_GENERAL_NAME;
994 
995 		fullname = &(dp->name.full_name);
996 		fullname->number = 0;
997 
998 		/* Skip over the explicit tag and size */
999 		(void) kmfber_scanf(asn1, "T", &tag);
1000 
1001 		tag = kmfber_next_element(asn1, &size, end);
1002 		while (tag != KMFBER_DEFAULT &&
1003 		    tag != KMFBER_END_OF_SEQORSET) {
1004 
1005 			if (kmfber_scanf(asn1, "tl", &tag, &size) ==
1006 			    KMFBER_DEFAULT || size == 0) {
1007 				ret = KMF_ERR_BAD_CERT_FORMAT;
1008 				goto out;
1009 			}
1010 
1011 			/* For phase 1, we are interested in a URI name only */
1012 			if (tag != (0x80 | GENNAME_URI)) {
1013 				tag = kmfber_next_element(asn1, &size, end);
1014 				continue;
1015 			}
1016 
1017 			if ((url = malloc(size)) == NULL) {
1018 				ret = KMF_ERR_MEMORY;
1019 				goto out;
1020 			}
1021 
1022 			/* Skip type and len, then read url and save it. */
1023 			if (kmfber_read(asn1, url, 2) != 2) {
1024 				ret = KMF_ERR_BAD_CERT_FORMAT;
1025 				goto out;
1026 			}
1027 
1028 			if (kmfber_read(asn1, url, size) !=
1029 			    (ber_slen_t)size) {
1030 				ret = KMF_ERR_BAD_CERT_FORMAT;
1031 				goto out;
1032 			}
1033 
1034 			fullname->number++;
1035 			fullname->namelist = realloc(fullname->namelist,
1036 			    fullname->number * sizeof (KMF_GENERALNAME));
1037 			if (fullname->namelist == NULL) {
1038 				ret = KMF_ERR_MEMORY;
1039 				goto out;
1040 			}
1041 
1042 			fullname->namelist[fullname->number - 1].choice =
1043 				GENNAME_URI;
1044 			fullname->namelist[fullname->number - 1].name.Length =
1045 				size;
1046 			fullname->namelist[fullname->number - 1].name.Data =
1047 				(unsigned char *)url;
1048 
1049 			/* next */
1050 			tag = kmfber_next_element(asn1, &size, end);
1051 		}
1052 
1053 	} else if (tag == 0xA1) {
1054 		/* "nameRelativeToCRLIssuer" is not supported at phase 1. */
1055 		ret = KMF_ERR_BAD_CERT_FORMAT;
1056 		goto out;
1057 	}
1058 
1059 out:
1060 	if (asn1 != NULL)
1061 		kmfber_free(asn1, 1);
1062 
1063 	if (ret != KMF_OK) {
1064 		free_dp_name(dp);
1065 	}
1066 
1067 	if (ret == KMF_OK && fullname->number == 0) {
1068 		ret = KMF_ERR_EXTENSION_NOT_FOUND;
1069 		if (url != NULL)
1070 			free(url);
1071 	}
1072 
1073 	return (ret);
1074 }
1075 
1076 /*
1077  * This function retrieves the CRL Distribution Points extension data from
1078  * a DER encoded certificate if it contains this extension, parses the
1079  * extension data, and returns it in the KMF_X509EXT_CRLDISTPOINTS record.
1080  */
1081 KMF_RETURN
1082 KMF_GetCertCRLDistributionPointsExt(const KMF_DATA *certdata,
1083 	KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1084 {
1085 	KMF_RETURN ret = KMF_OK;
1086 	KMF_X509_EXTENSION extn;
1087 	BerElement *asn1 = NULL;
1088 	BerValue exdata;
1089 	ber_len_t size;
1090 	char *end = NULL;
1091 	int tag;
1092 	KMF_CRL_DIST_POINT *dp = NULL;
1093 	int i;
1094 
1095 	if (certdata == NULL || crl_dps == NULL) {
1096 		return (KMF_ERR_BAD_PARAMETER);
1097 	}
1098 
1099 	/* Get the ASN.1 data for this extension. */
1100 	(void) memset(&extn, 0, sizeof (KMF_X509_EXTENSION));
1101 	ret = KMF_GetCertExtensionData(certdata,
1102 	    (KMF_OID *)&KMFOID_CrlDistributionPoints, &extn);
1103 	if (ret != KMF_OK) {
1104 		return (ret);
1105 	}
1106 
1107 	/*
1108 	 * Decode the CRLDistributionPoints ASN.1 data. The Syntax for
1109 	 * CRLDistributionPoints is
1110 	 *
1111 	 * CRLDistributionPoints ::=
1112 	 *	SEQUENCE SIZE (1..MAX) OF DistributionPoint
1113 	 *
1114 	 * DistributionPoint ::= SEQUENCE {
1115 	 *	distributionPoint	[0]	DistributionPointName OPTIONAL,
1116 	 *	reasons			[1]	ReasonFlags OPTIONAL,
1117 	 *	cRLIssuer		[2]	GeneralNames OPTIONAL }
1118 	 */
1119 
1120 	exdata.bv_val = (char *)extn.BERvalue.Data;
1121 	exdata.bv_len = extn.BERvalue.Length;
1122 	if ((asn1 = kmfder_init(&exdata)) == NULL) {
1123 		ret = KMF_ERR_MEMORY;
1124 		goto out;
1125 	}
1126 
1127 	if ((tag = kmfber_first_element(asn1, &size, &end)) !=
1128 	    BER_CONSTRUCTED_SEQUENCE) {
1129 		ret = KMF_ERR_BAD_CERT_FORMAT;
1130 		goto out;
1131 	}
1132 
1133 	(void) memset((void *)crl_dps, 0, sizeof (KMF_X509EXT_CRLDISTPOINTS));
1134 
1135 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
1136 	    BER_CONSTRUCTED_SEQUENCE) {
1137 		boolean_t has_name = B_FALSE;
1138 		boolean_t has_issuer = B_FALSE;
1139 
1140 		/* Skip over the CONSTRUCTED SET tag */
1141 		if (kmfber_scanf(asn1, "T", &tag) == KMFBER_DEFAULT) {
1142 			ret = KMF_ERR_BAD_CERT_FORMAT;
1143 			goto out;
1144 		}
1145 
1146 		tag = kmfber_next_element(asn1, &size, end);
1147 		if (tag != 0xA0 && tag != 0xA1 && tag != 0xA2)
1148 			goto out;
1149 
1150 		if ((dp = malloc(sizeof (KMF_CRL_DIST_POINT))) == NULL) {
1151 			ret = KMF_ERR_MEMORY;
1152 			goto out;
1153 		}
1154 		(void) memset((void *)dp, 0, sizeof (KMF_CRL_DIST_POINT));
1155 
1156 		if (tag == 0xA0) { /* distributionPoint Name */
1157 			char *name_der;
1158 			int name_size = size + 2;
1159 
1160 			if ((name_der = malloc(name_size)) == NULL) {
1161 				ret = KMF_ERR_MEMORY;
1162 				free(dp);
1163 				dp = NULL;
1164 				goto out;
1165 			}
1166 
1167 			if (kmfber_read(asn1, name_der, name_size) !=
1168 			    (ber_slen_t)(name_size)) {
1169 				ret = KMF_ERR_BAD_CERT_FORMAT;
1170 				free(name_der);
1171 				free(dp);
1172 				dp = NULL;
1173 				goto out;
1174 			}
1175 			has_name = B_TRUE;
1176 
1177 			ret = parse_dp_name(name_der, name_size, dp);
1178 			free(name_der);
1179 			if (ret != KMF_OK) {
1180 				free(dp);
1181 				dp = NULL;
1182 				goto out;
1183 			}
1184 
1185 			/* next field */
1186 			tag = kmfber_next_element(asn1, &size, end);
1187 		}
1188 
1189 		if (tag == 0XA1) { /* reasons */
1190 			char *bit_string;
1191 			int len;
1192 
1193 			if (kmfber_scanf(asn1, "B", &bit_string, &len) !=
1194 			    BER_BIT_STRING) {
1195 				ret = KMF_ERR_BAD_CERT_FORMAT;
1196 				free(dp);
1197 				dp = NULL;
1198 				goto out;
1199 			}
1200 
1201 			dp->reasons.Length = len / 8;
1202 			if ((dp->reasons.Data = malloc(dp->reasons.Length)) ==
1203 			    NULL) {
1204 				ret = KMF_ERR_MEMORY;
1205 				free(dp);
1206 				dp = NULL;
1207 				goto out;
1208 			}
1209 			(void) memcpy(dp->reasons.Data, (uchar_t *)bit_string,
1210 			    dp->reasons.Length);
1211 
1212 			/* next field */
1213 			tag = kmfber_next_element(asn1, &size, end);
1214 		}
1215 
1216 		if (tag == 0XA2) { /* cRLIssuer */
1217 			char *issuer_der = NULL;
1218 			int issuer_size;
1219 
1220 			/* For cRLIssuer, read the data only at phase 1 */
1221 			issuer_size = size + 2;
1222 			issuer_der = malloc(issuer_size);
1223 			if (issuer_der == NULL) {
1224 				ret = KMF_ERR_MEMORY;
1225 				free(dp);
1226 				dp = NULL;
1227 				goto out;
1228 			}
1229 
1230 			if (kmfber_read(asn1, issuer_der, issuer_size) !=
1231 			    (ber_slen_t)(issuer_size)) {
1232 				free(issuer_der);
1233 				ret = KMF_ERR_BAD_CERT_FORMAT;
1234 				free(dp);
1235 				dp = NULL;
1236 				goto out;
1237 			}
1238 
1239 			has_issuer = B_TRUE;
1240 			free(issuer_der);
1241 		}
1242 
1243 		/* A distribution point cannot have a "reasons" field only. */
1244 		if (has_name == B_FALSE && has_issuer == B_FALSE) {
1245 			ret = KMF_ERR_BAD_CERT_FORMAT;
1246 			free_dp(dp);
1247 			free(dp);
1248 			dp = NULL;
1249 			goto out;
1250 		}
1251 
1252 		/*
1253 		 * Although it is legal that a distributioon point contains
1254 		 * a cRLIssuer field only, with or without "reasons", we will
1255 		 * skip it if the name field is not presented for phase 1.
1256 		 */
1257 		if (has_name == B_FALSE) {
1258 			free_dp(dp);
1259 		} else {
1260 			crl_dps->number++;
1261 			crl_dps->dplist = realloc(crl_dps->dplist,
1262 			    crl_dps->number * sizeof (KMF_CRL_DIST_POINT));
1263 			if (crl_dps->dplist == NULL) {
1264 				ret = KMF_ERR_MEMORY;
1265 				free_dp(dp);
1266 				free(dp);
1267 				dp = NULL;
1268 				goto out;
1269 			}
1270 			crl_dps->dplist[crl_dps->number - 1] = *dp;
1271 			/* free the dp itself since we just used its contents */
1272 		}
1273 		if (dp != NULL) {
1274 			free(dp);
1275 			dp = NULL;
1276 		}
1277 	}
1278 
1279 out:
1280 	KMF_FreeExtension(&extn);
1281 
1282 	if (asn1 != NULL)
1283 		kmfber_free(asn1, 1);
1284 
1285 	if (ret != KMF_OK) {
1286 		for (i = 0; i < crl_dps->number; i++)
1287 			free_dp(&(crl_dps->dplist[i]));
1288 		free(crl_dps->dplist);
1289 	}
1290 
1291 	if (ret == KMF_OK && crl_dps->number == 0) {
1292 		ret = KMF_ERR_BAD_CERT_FORMAT;
1293 	}
1294 
1295 	return (ret);
1296 }
1297 
1298 static KMF_RETURN
1299 KMF_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1300 	KMF_PRINTABLE_ITEM flag, char *resultStr)
1301 {
1302 	KMF_PLUGIN *plugin;
1303 	KMF_RETURN (*getPrintableFn)(void *, const KMF_DATA *,
1304 		KMF_PRINTABLE_ITEM, char *);
1305 	KMF_RETURN ret;
1306 
1307 	CLEAR_ERROR(handle, ret);
1308 	if (ret != KMF_OK)
1309 		return (ret);
1310 
1311 	if (SignedCert == NULL ||
1312 		resultStr == NULL) {
1313 		return (KMF_ERR_BAD_PARAMETER);
1314 	}
1315 
1316 	/*
1317 	 * This framework function is actually implemented in the openssl
1318 	 * plugin library, so we find the function address and call it.
1319 	 */
1320 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1321 	if (plugin == NULL || plugin->dldesc == NULL) {
1322 		return (KMF_ERR_PLUGIN_NOTFOUND);
1323 	}
1324 
1325 	getPrintableFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1326 	    "OpenSSL_CertGetPrintable");
1327 	if (getPrintableFn == NULL) {
1328 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1329 	}
1330 
1331 	return (getPrintableFn(handle, SignedCert, flag, resultStr));
1332 }
1333 
1334 KMF_RETURN
1335 KMF_GetCertVersionString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1336     char **result)
1337 {
1338 	KMF_RETURN ret;
1339 	char *tmpstr;
1340 
1341 	CLEAR_ERROR(handle, ret);
1342 	if (ret != KMF_OK)
1343 		return (ret);
1344 
1345 	if (SignedCert == NULL || result == NULL)
1346 		return (KMF_ERR_BAD_PARAMETER);
1347 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1348 	if (tmpstr == NULL)
1349 		return (KMF_ERR_MEMORY);
1350 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1351 
1352 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_VERSION,
1353 		tmpstr);
1354 
1355 	if (ret == KMF_OK) {
1356 		*result = tmpstr;
1357 	} else {
1358 		free(tmpstr);
1359 		*result = NULL;
1360 	}
1361 
1362 	return (ret);
1363 }
1364 
1365 KMF_RETURN
1366 KMF_GetCertSubjectNameString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1367     char **result)
1368 {
1369 	KMF_RETURN ret;
1370 	char *tmpstr;
1371 
1372 	CLEAR_ERROR(handle, ret);
1373 	if (ret != KMF_OK)
1374 		return (ret);
1375 
1376 	if (SignedCert == NULL || result == NULL)
1377 		return (KMF_ERR_BAD_PARAMETER);
1378 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1379 	if (tmpstr == NULL)
1380 		return (KMF_ERR_MEMORY);
1381 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1382 
1383 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_SUBJECT,
1384 		tmpstr);
1385 
1386 	if (ret == KMF_OK) {
1387 		*result = tmpstr;
1388 	} else {
1389 		free(tmpstr);
1390 		*result = NULL;
1391 	}
1392 
1393 	return (ret);
1394 
1395 }
1396 
1397 KMF_RETURN
1398 KMF_GetCertIssuerNameString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1399     char **result)
1400 {
1401 	KMF_RETURN ret;
1402 	char *tmpstr;
1403 
1404 	CLEAR_ERROR(handle, ret);
1405 	if (ret != KMF_OK)
1406 		return (ret);
1407 
1408 	if (SignedCert == NULL || result == NULL)
1409 		return (KMF_ERR_BAD_PARAMETER);
1410 
1411 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1412 	if (tmpstr == NULL)
1413 		return (KMF_ERR_MEMORY);
1414 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1415 
1416 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_ISSUER,
1417 		tmpstr);
1418 
1419 	if (ret == KMF_OK) {
1420 		*result = tmpstr;
1421 	} else {
1422 		free(tmpstr);
1423 		*result = NULL;
1424 	}
1425 
1426 	return (ret);
1427 }
1428 
1429 KMF_RETURN
1430 KMF_GetCertSerialNumberString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1431     char **result)
1432 {
1433 	KMF_RETURN ret;
1434 	char *tmpstr;
1435 
1436 	CLEAR_ERROR(handle, ret);
1437 	if (ret != KMF_OK)
1438 		return (ret);
1439 
1440 	if (SignedCert == NULL || result == NULL)
1441 		return (KMF_ERR_BAD_PARAMETER);
1442 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1443 	if (tmpstr == NULL)
1444 		return (KMF_ERR_MEMORY);
1445 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1446 
1447 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_SERIALNUM,
1448 		tmpstr);
1449 
1450 	if (ret == KMF_OK) {
1451 		*result = tmpstr;
1452 	} else {
1453 		free(tmpstr);
1454 		*result = NULL;
1455 	}
1456 
1457 	return (ret);
1458 }
1459 
1460 KMF_RETURN
1461 KMF_GetCertStartDateString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1462     char **result)
1463 {
1464 	KMF_RETURN ret;
1465 	char *tmpstr;
1466 
1467 	CLEAR_ERROR(handle, ret);
1468 	if (ret != KMF_OK)
1469 		return (ret);
1470 
1471 	if (SignedCert == NULL || result == NULL)
1472 		return (KMF_ERR_BAD_PARAMETER);
1473 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1474 	if (tmpstr == NULL)
1475 		return (KMF_ERR_MEMORY);
1476 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1477 
1478 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_NOTBEFORE,
1479 		tmpstr);
1480 
1481 	if (ret == KMF_OK) {
1482 		*result = tmpstr;
1483 	} else {
1484 		free(tmpstr);
1485 		*result = NULL;
1486 	}
1487 
1488 	return (ret);
1489 }
1490 
1491 KMF_RETURN
1492 KMF_GetCertEndDateString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1493 	char **result)
1494 {
1495 	KMF_RETURN ret;
1496 	char *tmpstr;
1497 
1498 	CLEAR_ERROR(handle, ret);
1499 	if (ret != KMF_OK)
1500 		return (ret);
1501 
1502 	if (SignedCert == NULL || result == NULL)
1503 		return (KMF_ERR_BAD_PARAMETER);
1504 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1505 	if (tmpstr == NULL)
1506 		return (KMF_ERR_MEMORY);
1507 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1508 
1509 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_NOTAFTER,
1510 		tmpstr);
1511 
1512 	if (ret == KMF_OK) {
1513 		*result = tmpstr;
1514 	} else {
1515 		free(tmpstr);
1516 		*result = NULL;
1517 	}
1518 
1519 	return (ret);
1520 }
1521 
1522 KMF_RETURN
1523 KMF_GetCertPubKeyAlgString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1524     char **result)
1525 {
1526 	KMF_RETURN ret;
1527 	char *tmpstr;
1528 
1529 	CLEAR_ERROR(handle, ret);
1530 	if (ret != KMF_OK)
1531 		return (ret);
1532 
1533 	if (SignedCert == NULL || result == NULL)
1534 		return (KMF_ERR_BAD_PARAMETER);
1535 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1536 	if (tmpstr == NULL)
1537 		return (KMF_ERR_MEMORY);
1538 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1539 
1540 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_PUBKEY_ALG,
1541 		tmpstr);
1542 
1543 	if (ret == KMF_OK) {
1544 		*result = tmpstr;
1545 	} else {
1546 		free(tmpstr);
1547 		*result = NULL;
1548 	}
1549 
1550 	return (ret);
1551 }
1552 
1553 KMF_RETURN
1554 KMF_GetCertSignatureAlgString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1555     char **result)
1556 {
1557 	KMF_RETURN ret;
1558 	char *tmpstr;
1559 
1560 	CLEAR_ERROR(handle, ret);
1561 	if (ret != KMF_OK)
1562 		return (ret);
1563 
1564 	if (SignedCert == NULL || result == NULL)
1565 		return (KMF_ERR_BAD_PARAMETER);
1566 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1567 	if (tmpstr == NULL)
1568 		return (KMF_ERR_MEMORY);
1569 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1570 
1571 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_SIGNATURE_ALG,
1572 		tmpstr);
1573 
1574 	if (ret == KMF_OK) {
1575 		*result = tmpstr;
1576 	} else {
1577 		free(tmpstr);
1578 		*result = NULL;
1579 	}
1580 
1581 	return (ret);
1582 }
1583 
1584 KMF_RETURN
1585 KMF_GetCertPubKeyDataString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1586     char **result)
1587 {
1588 	KMF_RETURN ret;
1589 	char *tmpstr;
1590 
1591 	CLEAR_ERROR(handle, ret);
1592 	if (ret != KMF_OK)
1593 		return (ret);
1594 
1595 	if (SignedCert == NULL || result == NULL)
1596 		return (KMF_ERR_BAD_PARAMETER);
1597 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1598 	if (tmpstr == NULL)
1599 		return (KMF_ERR_MEMORY);
1600 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1601 
1602 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_PUBKEY_DATA,
1603 		tmpstr);
1604 
1605 	if (ret == KMF_OK) {
1606 		*result = tmpstr;
1607 	} else {
1608 		free(tmpstr);
1609 		*result = NULL;
1610 	}
1611 
1612 	return (ret);
1613 }
1614 
1615 KMF_RETURN
1616 KMF_GetCertEmailString(KMF_HANDLE_T handle, const KMF_DATA *SignedCert,
1617 	char **result)
1618 {
1619 	KMF_RETURN ret;
1620 	char *tmpstr;
1621 
1622 	CLEAR_ERROR(handle, ret);
1623 	if (ret != KMF_OK)
1624 		return (ret);
1625 
1626 	if (SignedCert == NULL || result == NULL)
1627 		return (KMF_ERR_BAD_PARAMETER);
1628 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1629 	if (tmpstr == NULL)
1630 		return (KMF_ERR_MEMORY);
1631 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1632 
1633 	ret = KMF_CertGetPrintable(handle, SignedCert, KMF_CERT_EMAIL,
1634 		tmpstr);
1635 
1636 	if (ret == KMF_OK) {
1637 		*result = tmpstr;
1638 	} else {
1639 		free(tmpstr);
1640 		*result = NULL;
1641 	}
1642 
1643 	return (ret);
1644 }
1645 
1646 /*
1647  * Given a certificate (DER Encoded data) and a KMF
1648  * extension identifier constant (e.g. KMF_X509_EXT_*),
1649  * return a human readable interpretation of the
1650  * extension data.
1651  *
1652  * The string will be a maximum of KMF_CERT_PRINTABLE_LEN
1653  * bytes long.  The string is allocated locally and
1654  * must be freed by the caller.
1655  */
1656 KMF_RETURN
1657 KMF_GetCertExtensionString(KMF_HANDLE_T handle, const KMF_DATA *cert,
1658 	KMF_PRINTABLE_ITEM extension, char **result)
1659 {
1660 	KMF_RETURN ret;
1661 	char *tmpstr;
1662 
1663 	CLEAR_ERROR(handle, ret);
1664 	if (ret != KMF_OK)
1665 		return (ret);
1666 
1667 	if (cert == NULL || result == NULL)
1668 		return (KMF_ERR_BAD_PARAMETER);
1669 
1670 	tmpstr = malloc(KMF_CERT_PRINTABLE_LEN);
1671 	if (tmpstr == NULL)
1672 		return (KMF_ERR_MEMORY);
1673 	(void) memset(tmpstr, 0, KMF_CERT_PRINTABLE_LEN);
1674 
1675 	ret = KMF_CertGetPrintable(handle, cert, extension, tmpstr);
1676 
1677 	if (ret == KMF_OK) {
1678 		*result = tmpstr;
1679 	} else {
1680 		free(tmpstr);
1681 		*result = NULL;
1682 	}
1683 
1684 	return (ret);
1685 }
1686 
1687 KMF_RETURN
1688 KMF_GetCertIDData(const KMF_DATA *SignedCert, KMF_DATA *ID)
1689 {
1690 	KMF_RETURN ret;
1691 	KMF_X509_CERTIFICATE *cert = NULL;
1692 
1693 	if (SignedCert == NULL || ID == NULL)
1694 		return (KMF_ERR_BAD_PARAMETER);
1695 
1696 	ret = DerDecodeSignedCertificate(SignedCert, &cert);
1697 	if (ret != KMF_OK)
1698 		return (ret);
1699 
1700 	ret = GetIDFromSPKI(&cert->certificate.subjectPublicKeyInfo, ID);
1701 
1702 	KMF_FreeSignedCert(cert);
1703 	free(cert);
1704 	return (ret);
1705 }
1706 
1707 KMF_RETURN
1708 KMF_GetCertIDString(const KMF_DATA *SignedCert,
1709 	char **idstr)
1710 {
1711 	KMF_RETURN ret;
1712 	KMF_DATA ID = {NULL, 0};
1713 	char tmpstr[256];
1714 	int i;
1715 
1716 	if (SignedCert == NULL || idstr == NULL)
1717 		return (KMF_ERR_BAD_PARAMETER);
1718 
1719 	ret = KMF_GetCertIDData(SignedCert, &ID);
1720 	if (ret != KMF_OK) {
1721 		KMF_FreeData(&ID);
1722 		return (ret);
1723 	}
1724 
1725 	(void) memset(tmpstr, 0, sizeof (tmpstr));
1726 	for (i = 0; i < ID.Length; i++) {
1727 		int len = strlen(tmpstr);
1728 		(void) snprintf(&tmpstr[len], sizeof (tmpstr) -  len,
1729 			"%02x", (uchar_t)ID.Data[i]);
1730 		if ((i+1) < ID.Length)
1731 			(void) strcat(tmpstr, ":");
1732 	}
1733 	*idstr = strdup(tmpstr);
1734 	if ((*idstr) == NULL)
1735 		ret = KMF_ERR_MEMORY;
1736 
1737 	KMF_FreeData(&ID);
1738 
1739 	return (ret);
1740 }
1741 
1742 /*
1743  * This function gets the time_t values of the notbefore and notafter dates
1744  * from a der-encoded certificate.
1745  */
1746 KMF_RETURN
1747 KMF_GetCertValidity(const KMF_DATA *cert, time_t *not_before,
1748     time_t *not_after)
1749 {
1750 	KMF_RETURN rv = KMF_OK;
1751 	KMF_X509_CERTIFICATE *certData = NULL;
1752 	struct tm tm_tmp;
1753 	time_t t_notbefore;
1754 	time_t t_notafter;
1755 	unsigned char *not_before_str;
1756 	unsigned char *not_after_str;
1757 
1758 	if (cert == NULL || not_before == NULL || not_after == NULL)
1759 		return (KMF_ERR_BAD_PARAMETER);
1760 
1761 	rv = DerDecodeSignedCertificate(cert, &certData);
1762 	if (rv != KMF_OK)
1763 		return (rv);
1764 
1765 	/* Get notBefore */
1766 	not_before_str = certData->certificate.validity.notBefore.time.Data;
1767 	if (strptime((const char *)not_before_str, "%y %m %d %H %M %S",
1768 	    &tm_tmp) == NULL) {
1769 		rv = KMF_ERR_VALIDITY_PERIOD;
1770 		goto out;
1771 	}
1772 
1773 	errno = 0;
1774 	if (((t_notbefore = mktime(&tm_tmp)) == (time_t)(-1)) &&
1775 	    errno == EOVERFLOW) {
1776 		rv = KMF_ERR_VALIDITY_PERIOD;
1777 		goto out;
1778 	}
1779 	*not_before = t_notbefore;
1780 
1781 	/* Get notAfter */
1782 	not_after_str = certData->certificate.validity.notAfter.time.Data;
1783 	if (strptime((const char *)not_after_str, "%y %m %d %H %M %S",
1784 	    &tm_tmp) == NULL) {
1785 		rv = KMF_ERR_VALIDITY_PERIOD;
1786 		goto out;
1787 	}
1788 
1789 	errno = 0;
1790 	if (((t_notafter = mktime(&tm_tmp)) == (time_t)(-1)) &&
1791 	    errno == EOVERFLOW) {
1792 		rv = KMF_ERR_VALIDITY_PERIOD;
1793 		goto out;
1794 	}
1795 	*not_after = t_notafter;
1796 
1797 out:
1798 	if (certData != NULL) {
1799 		KMF_FreeSignedCert(certData);
1800 		free(certData);
1801 	}
1802 
1803 	return (rv);
1804 }
1805 
1806 KMF_RETURN
1807 KMF_SetCertPubKey(KMF_HANDLE_T handle,
1808 	KMF_KEY_HANDLE *KMFKey,
1809 	KMF_X509_CERTIFICATE *Cert)
1810 {
1811 	KMF_RETURN ret = KMF_OK;
1812 	KMF_X509_SPKI *spki_ptr;
1813 	KMF_PLUGIN *plugin;
1814 	KMF_DATA KeyData = {NULL, 0};
1815 
1816 	CLEAR_ERROR(handle, ret);
1817 	if (ret != KMF_OK)
1818 		return (ret);
1819 
1820 	if (KMFKey == NULL || Cert == NULL) {
1821 		return (KMF_ERR_BAD_PARAMETER);
1822 	}
1823 
1824 	/* The keystore must extract the pubkey data */
1825 	plugin = FindPlugin(handle, KMFKey->kstype);
1826 	if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) {
1827 		ret = plugin->funclist->EncodePubkeyData(handle,
1828 			KMFKey, &KeyData);
1829 	} else {
1830 		return (KMF_ERR_PLUGIN_NOTFOUND);
1831 	}
1832 
1833 	spki_ptr = &Cert->certificate.subjectPublicKeyInfo;
1834 
1835 	if (KeyData.Data != NULL) {
1836 		ret = DerDecodeSPKI(&KeyData, spki_ptr);
1837 		free(KeyData.Data);
1838 	}
1839 
1840 	return (ret);
1841 }
1842 
1843 KMF_RETURN
1844 KMF_SetCertSubjectName(KMF_X509_CERTIFICATE *CertData,
1845 	KMF_X509_NAME *subject_name_ptr)
1846 {
1847 
1848 	KMF_RETURN rv = KMF_OK;
1849 	KMF_X509_NAME *temp_name_ptr = NULL;
1850 
1851 	if (CertData != NULL && subject_name_ptr != NULL) {
1852 		rv = CopyRDN(subject_name_ptr, &temp_name_ptr);
1853 		if (rv == KMF_OK) {
1854 			CertData->certificate.subject = *temp_name_ptr;
1855 		}
1856 	} else {
1857 		return (KMF_ERR_BAD_PARAMETER);
1858 	}
1859 	return (rv);
1860 }
1861 
1862 KMF_RETURN
1863 set_key_usage_extension(KMF_X509_EXTENSIONS *extns,
1864 	int critical, uint32_t bits)
1865 {
1866 	KMF_RETURN ret = KMF_OK;
1867 	KMF_X509_EXTENSION extn;
1868 	BerElement *asn1 = NULL;
1869 	BerValue *extdata;
1870 	int bitlen, i;
1871 	uint16_t kubits = (uint16_t)(bits & 0x0000ffff);
1872 
1873 	if (extns == NULL)
1874 		return (KMF_ERR_BAD_PARAMETER);
1875 
1876 	(void) memset(&extn, 0, sizeof (extn));
1877 	ret = copy_data(&extn.extnId, (KMF_OID *)&KMFOID_KeyUsage);
1878 	if (ret != KMF_OK)
1879 		return (ret);
1880 	extn.critical = critical;
1881 	extn.format = KMF_X509_DATAFORMAT_ENCODED;
1882 
1883 	for (i = 7; i <= 15 && !(kubits & (1 << i)); i++);
1884 
1885 	bitlen = 16 - i;
1886 
1887 	if ((asn1 = kmfder_alloc()) == NULL)
1888 		return (KMF_ERR_MEMORY);
1889 
1890 	kubits = htons(kubits);
1891 	if (kmfber_printf(asn1, "B", (char *)&kubits, bitlen) == -1) {
1892 		ret = KMF_ERR_ENCODING;
1893 		goto out;
1894 	}
1895 	if (kmfber_flatten(asn1, &extdata) == -1) {
1896 		ret = KMF_ERR_ENCODING;
1897 		goto out;
1898 	}
1899 
1900 	extn.BERvalue.Data = (uchar_t *)extdata->bv_val;
1901 	extn.BERvalue.Length = extdata->bv_len;
1902 
1903 	free(extdata);
1904 
1905 	ret = add_an_extension(extns, &extn);
1906 	if (ret != KMF_OK) {
1907 		free(extn.BERvalue.Data);
1908 	}
1909 out:
1910 	if (asn1 != NULL)
1911 		kmfber_free(asn1, 1);
1912 
1913 	return (ret);
1914 }
1915 
1916 KMF_RETURN
1917 KMF_SetCertKeyUsage(KMF_X509_CERTIFICATE *CertData,
1918 	int critical, uint16_t kubits)
1919 {
1920 	KMF_RETURN ret = KMF_OK;
1921 
1922 	if (CertData == NULL)
1923 		return (KMF_ERR_BAD_PARAMETER);
1924 
1925 	ret = set_key_usage_extension(
1926 		&CertData->certificate.extensions,
1927 		critical, kubits);
1928 
1929 	return (ret);
1930 }
1931 
1932 KMF_RETURN
1933 KMF_SetCertIssuerName(KMF_X509_CERTIFICATE *CertData,
1934 	KMF_X509_NAME *issuer_name_ptr)
1935 {
1936 
1937 	KMF_RETURN rv = KMF_OK;
1938 	KMF_X509_NAME *temp_name_ptr = NULL;
1939 
1940 	if (CertData != NULL && issuer_name_ptr != NULL) {
1941 		rv = CopyRDN(issuer_name_ptr, &temp_name_ptr);
1942 		if (rv == KMF_OK) {
1943 			CertData->certificate.issuer = *temp_name_ptr;
1944 		}
1945 	} else {
1946 		return (KMF_ERR_BAD_PARAMETER);
1947 	}
1948 
1949 	return (rv);
1950 }
1951 
1952 KMF_RETURN
1953 KMF_SetCertSignatureAlgorithm(KMF_X509_CERTIFICATE *CertData,
1954 	KMF_ALGORITHM_INDEX sigAlg)
1955 {
1956 	KMF_OID	*alg;
1957 
1958 	if (CertData == NULL)
1959 		return (KMF_ERR_BAD_PARAMETER);
1960 
1961 	alg = X509_AlgIdToAlgorithmOid(sigAlg);
1962 
1963 	if (alg != NULL) {
1964 		(void) copy_data((KMF_DATA *)
1965 		    &CertData->certificate.signature.algorithm,
1966 		    (KMF_DATA *)alg);
1967 		(void) copy_data(&CertData->certificate.signature.parameters,
1968 		    &CertData->certificate.subjectPublicKeyInfo.algorithm.
1969 		    parameters);
1970 
1971 		(void) copy_data(
1972 		    &CertData->signature.algorithmIdentifier.algorithm,
1973 		    &CertData->certificate.signature.algorithm);
1974 		(void) copy_data(
1975 		    &CertData->signature.algorithmIdentifier.parameters,
1976 		    &CertData->certificate.signature.parameters);
1977 	} else {
1978 		return (KMF_ERR_BAD_PARAMETER);
1979 	}
1980 
1981 	return (KMF_OK);
1982 }
1983 
1984 KMF_RETURN
1985 KMF_SetCertValidityTimes(KMF_X509_CERTIFICATE *CertData,
1986 	time_t notBefore, uint32_t delta)
1987 {
1988 	time_t		clock;
1989 	struct tm	*gmt;
1990 	char 		szNotBefore[256];
1991 	char		szNotAfter[256];
1992 
1993 	if (CertData == NULL)
1994 		return (KMF_ERR_BAD_PARAMETER);
1995 
1996 	/* Set up validity fields */
1997 	if (notBefore == NULL)
1998 		clock = time(NULL);
1999 	else
2000 		clock = notBefore;
2001 
2002 	gmt = gmtime(&clock);  /* valid starting today */
2003 
2004 	/* Build the format in 2 parts so SCCS doesn't get confused */
2005 	(void) strftime(szNotBefore, sizeof (szNotBefore),
2006 		"%y%m%d%H" "%M00Z", gmt);
2007 
2008 	CertData->certificate.validity.notBefore.timeType = BER_UTCTIME;
2009 	CertData->certificate.validity.notBefore.time.Length =
2010 		strlen((char *)szNotBefore);
2011 	CertData->certificate.validity.notBefore.time.Data =
2012 		(uchar_t *)strdup(szNotBefore);
2013 
2014 	clock += delta;
2015 	gmt = gmtime(&clock);
2016 
2017 	/* Build the format in 2 parts so SCCS doesn't get confused */
2018 	(void) strftime(szNotAfter, sizeof (szNotAfter),
2019 		"%y%m%d%H" "%M00Z", gmt);
2020 
2021 	CertData->certificate.validity.notAfter.timeType = BER_UTCTIME;
2022 	CertData->certificate.validity.notAfter.time.Length =
2023 		strlen((char *)szNotAfter);
2024 	CertData->certificate.validity.notAfter.time.Data =
2025 		(uchar_t *)strdup(szNotAfter);
2026 
2027 	return (KMF_OK);
2028 }
2029 
2030 /*
2031  * Utility routine to set Integer values in the Certificate template
2032  * for things like serialNumber and Version. The data structure
2033  * expects pointers, not literal values, so we must allocate
2034  * and copy here.  Don't use memory from the stack since this data
2035  * is freed later and that would be bad.
2036  */
2037 KMF_RETURN
2038 set_integer(KMF_DATA *data, void *value, int length)
2039 {
2040 	if (data == NULL || value == NULL)
2041 		return (KMF_ERR_BAD_PARAMETER);
2042 
2043 	data->Data = malloc(length);
2044 	if (data->Data == NULL)
2045 		return (KMF_ERR_MEMORY);
2046 
2047 	data->Length = length;
2048 	(void) memcpy((void *)data->Data, (const void *)value, length);
2049 
2050 	return (KMF_OK);
2051 }
2052 
2053 static KMF_RETURN
2054 set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
2055 {
2056 	if (data == NULL || bigint == NULL || bigint->len == NULL)
2057 		return (KMF_ERR_BAD_PARAMETER);
2058 
2059 	data->val = malloc(bigint->len);
2060 	if (data->val == NULL)
2061 		return (KMF_ERR_MEMORY);
2062 
2063 	data->len = bigint->len;
2064 
2065 	(void) memcpy((void *)data->val, bigint->val, bigint->len);
2066 
2067 	return (KMF_OK);
2068 
2069 }
2070 
2071 KMF_RETURN
2072 KMF_SetCertSerialNumber(KMF_X509_CERTIFICATE *CertData,
2073 	KMF_BIGINT *serno)
2074 {
2075 	if (CertData == NULL || serno == NULL || serno->len == 0)
2076 		return (KMF_ERR_BAD_PARAMETER);
2077 	return (set_bigint(&CertData->certificate.serialNumber, serno));
2078 }
2079 
2080 KMF_RETURN
2081 KMF_SetCertVersion(KMF_X509_CERTIFICATE *CertData,
2082 	uint32_t version)
2083 {
2084 	if (CertData == NULL)
2085 		return (KMF_ERR_BAD_PARAMETER);
2086 	/*
2087 	 * From RFC 3280:
2088 	 * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
2089 	 */
2090 	if (version != 0 && version != 1 && version != 2)
2091 		return (KMF_ERR_BAD_PARAMETER);
2092 	return (set_integer(&CertData->certificate.version, (void *)&version,
2093 		sizeof (uint32_t)));
2094 }
2095 
2096 KMF_RETURN
2097 KMF_SetCertIssuerAltName(KMF_X509_CERTIFICATE *CertData,
2098 	int critical,
2099 	KMF_GENERALNAMECHOICES nametype,
2100 	char *namedata)
2101 {
2102 	if (CertData == NULL || namedata == NULL)
2103 		return (KMF_ERR_BAD_PARAMETER);
2104 
2105 	return (KMF_SetAltName(
2106 		&CertData->certificate.extensions,
2107 		(KMF_OID *)&KMFOID_IssuerAltName,
2108 		critical, nametype, namedata));
2109 }
2110 
2111 KMF_RETURN
2112 KMF_SetCertSubjectAltName(KMF_X509_CERTIFICATE *CertData,
2113 	int critical,
2114 	KMF_GENERALNAMECHOICES nametype,
2115 	char *namedata)
2116 {
2117 	if (CertData == NULL || namedata == NULL)
2118 		return (KMF_ERR_BAD_PARAMETER);
2119 
2120 	return (KMF_SetAltName(&CertData->certificate.extensions,
2121 		(KMF_OID *)&KMFOID_SubjectAltName,
2122 		critical, nametype, namedata));
2123 }
2124 
2125 KMF_RETURN
2126 KMF_AddCertEKU(KMF_X509_CERTIFICATE *CertData, KMF_OID *ekuOID,
2127 	int critical)
2128 {
2129 	KMF_RETURN ret = KMF_OK;
2130 	KMF_X509_EXTENSION *foundextn;
2131 	KMF_X509_EXTENSION newextn;
2132 	BerElement *asn1 = NULL;
2133 	BerValue *extdata = NULL;
2134 	char *olddata = NULL;
2135 	size_t oldsize = 0;
2136 	KMF_X509EXT_EKU ekudata;
2137 
2138 	if (CertData == NULL || ekuOID == NULL)
2139 		return (KMF_ERR_BAD_PARAMETER);
2140 
2141 	(void) memset(&ekudata, 0, sizeof (KMF_X509EXT_EKU));
2142 	(void) memset(&newextn, 0, sizeof (newextn));
2143 
2144 	foundextn = FindExtn(&CertData->certificate.extensions,
2145 		(KMF_OID *)&KMFOID_ExtendedKeyUsage);
2146 	if (foundextn != NULL) {
2147 		ret = GetSequenceContents(
2148 				(char *)foundextn->BERvalue.Data,
2149 				foundextn->BERvalue.Length,
2150 				&olddata, &oldsize);
2151 		if (ret != KMF_OK)
2152 			goto out;
2153 
2154 		/*
2155 		 * If the EKU is already in the cert, then just return OK.
2156 		 */
2157 		ret = parse_eku_data(&foundextn->BERvalue, &ekudata);
2158 		if (ret == KMF_OK) {
2159 			if (isEKUPresent(&ekudata, ekuOID)) {
2160 				goto out;
2161 			}
2162 		}
2163 	}
2164 	if ((asn1 = kmfder_alloc()) == NULL)
2165 		return (KMF_ERR_MEMORY);
2166 
2167 	if (kmfber_printf(asn1, "{") == -1) {
2168 		ret = KMF_ERR_ENCODING;
2169 		goto out;
2170 	}
2171 
2172 	/* Write the old extension data first */
2173 	if (olddata != NULL && oldsize > 0) {
2174 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
2175 			ret = KMF_ERR_ENCODING;
2176 			goto out;
2177 		}
2178 	}
2179 
2180 	/* Append this EKU OID and close the sequence */
2181 	if (kmfber_printf(asn1, "D}", ekuOID) == -1) {
2182 		ret = KMF_ERR_ENCODING;
2183 		goto out;
2184 	}
2185 
2186 	if (kmfber_flatten(asn1, &extdata) == -1) {
2187 		ret = KMF_ERR_ENCODING;
2188 		goto out;
2189 	}
2190 
2191 	/*
2192 	 * If we are just adding to an existing list of EKU OIDs,
2193 	 * just replace the BER data associated with the found extension.
2194 	 */
2195 	if (foundextn != NULL) {
2196 		free(foundextn->BERvalue.Data);
2197 		foundextn->critical = critical;
2198 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
2199 		foundextn->BERvalue.Length = extdata->bv_len;
2200 	} else {
2201 		ret = copy_data(&newextn.extnId,
2202 			(KMF_DATA *)&KMFOID_ExtendedKeyUsage);
2203 		if (ret != KMF_OK)
2204 			goto out;
2205 		newextn.critical = critical;
2206 		newextn.format = KMF_X509_DATAFORMAT_ENCODED;
2207 		newextn.BERvalue.Data = (uchar_t *)extdata->bv_val;
2208 		newextn.BERvalue.Length = extdata->bv_len;
2209 		ret = KMF_SetCertExtension(CertData, &newextn);
2210 		if (ret != KMF_OK)
2211 			free(newextn.BERvalue.Data);
2212 	}
2213 
2214 out:
2215 	KMF_FreeEKU(&ekudata);
2216 	if (extdata != NULL)
2217 		free(extdata);
2218 
2219 	if (olddata != NULL)
2220 		free(olddata);
2221 
2222 	if (asn1 != NULL)
2223 		kmfber_free(asn1, 1);
2224 
2225 	if (ret != KMF_OK)
2226 		KMF_FreeData(&newextn.extnId);
2227 
2228 	return (ret);
2229 }
2230 
2231 KMF_RETURN
2232 KMF_SetCertExtension(KMF_X509_CERTIFICATE *CertData,
2233 	KMF_X509_EXTENSION *extn)
2234 {
2235 	KMF_RETURN ret = KMF_OK;
2236 	KMF_X509_EXTENSIONS *exts;
2237 
2238 	if (CertData == NULL || extn == NULL)
2239 		return (KMF_ERR_BAD_PARAMETER);
2240 
2241 	exts = &CertData->certificate.extensions;
2242 
2243 	ret = add_an_extension(exts, extn);
2244 
2245 	return (ret);
2246 }
2247 
2248 KMF_RETURN
2249 KMF_SetCertBasicConstraintExt(KMF_X509_CERTIFICATE *CertData,
2250 	KMF_BOOL critical, KMF_X509EXT_BASICCONSTRAINTS *constraint)
2251 {
2252 	KMF_RETURN ret = KMF_OK;
2253 	KMF_X509_EXTENSION extn;
2254 	BerElement *asn1 = NULL;
2255 	BerValue *extdata;
2256 
2257 	if ((CertData == NULL) || (constraint == NULL))
2258 		return (KMF_ERR_BAD_PARAMETER);
2259 
2260 	(void) memset(&extn, 0, sizeof (extn));
2261 	ret = copy_data(&extn.extnId, (KMF_OID *)&KMFOID_BasicConstraints);
2262 	if (ret != KMF_OK)
2263 		return (ret);
2264 	extn.critical = critical;
2265 	extn.format = KMF_X509_DATAFORMAT_ENCODED;
2266 
2267 	if ((asn1 = kmfder_alloc()) == NULL)
2268 		return (KMF_ERR_MEMORY);
2269 
2270 	if (kmfber_printf(asn1, "{") == -1) {
2271 		ret = KMF_ERR_ENCODING;
2272 		goto out;
2273 	}
2274 
2275 	if (kmfber_printf(asn1, "b", constraint->cA) == -1) {
2276 		ret = KMF_ERR_ENCODING;
2277 		goto out;
2278 	}
2279 
2280 	if (constraint->pathLenConstraintPresent) {
2281 		/* Write the pathLenConstraint value */
2282 		if (kmfber_printf(asn1, "i",
2283 			constraint->pathLenConstraint) == -1) {
2284 			ret = KMF_ERR_ENCODING;
2285 			goto out;
2286 		}
2287 	}
2288 
2289 	if (kmfber_printf(asn1, "}") == -1) {
2290 		ret = KMF_ERR_ENCODING;
2291 		goto out;
2292 	}
2293 
2294 	if (kmfber_flatten(asn1, &extdata) == -1) {
2295 		ret = KMF_ERR_ENCODING;
2296 		goto out;
2297 	}
2298 
2299 	extn.BERvalue.Data = (uchar_t *)extdata->bv_val;
2300 	extn.BERvalue.Length = extdata->bv_len;
2301 
2302 	free(extdata);
2303 	ret = KMF_SetCertExtension(CertData, &extn);
2304 	if (ret != KMF_OK) {
2305 		free(extn.BERvalue.Data);
2306 	}
2307 
2308 out:
2309 	if (asn1 != NULL)
2310 		kmfber_free(asn1, 1);
2311 
2312 	return (ret);
2313 }
2314