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