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