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
40KMF_RETURN
41copy_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
65KMF_RETURN
66copy_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
103cleanup:
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 */
129KMF_RETURN
130kmf_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	}
159end:
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 */
184KMF_RETURN
185kmf_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
230end:
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 */
264KMF_RETURN
265kmf_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	}
290end:
291	kmf_free_extn(&extn);
292	return (ret);
293}
294
295KMF_BOOL
296is_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
310KMF_RETURN
311parse_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
361end:
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
376KMF_RETURN
377kmf_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
401end:
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 */
418KMF_RETURN
419kmf_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	}
466end:
467	kmf_free_extn(&extn);
468	if (asn1 != NULL)
469		kmfber_free(asn1, 1);
470
471	return (ret);
472}
473
474static KMF_X509EXT_POLICYQUALIFIERINFO *
475get_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	}
589end:
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 */
613KMF_RETURN
614kmf_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
731end:
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 */
749KMF_RETURN
750kmf_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
891end:
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 */
915static KMF_RETURN
916parse_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
1008out:
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 */
1030KMF_RETURN
1031kmf_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
1228out:
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
1247static KMF_RETURN
1248KMF_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
1282KMF_RETURN
1283kmf_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
1314KMF_RETURN
1315kmf_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
1346KMF_RETURN
1347kmf_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
1378KMF_RETURN
1379kmf_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
1409KMF_RETURN
1410kmf_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
1440KMF_RETURN
1441kmf_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
1471KMF_RETURN
1472kmf_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
1502KMF_RETURN
1503kmf_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
1533KMF_RETURN
1534kmf_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
1564KMF_RETURN
1565kmf_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 */
1604KMF_RETURN
1605kmf_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
1635KMF_RETURN
1636kmf_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
1655KMF_RETURN
1656kmf_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 */
1694KMF_RETURN
1695kmf_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
1745out:
1746	if (certData != NULL) {
1747		kmf_free_signed_cert(certData);
1748		free(certData);
1749	}
1750
1751	return (rv);
1752}
1753
1754KMF_RETURN
1755kmf_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
1791KMF_RETURN
1792kmf_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
1810KMF_RETURN
1811set_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	}
1859out:
1860	if (asn1 != NULL)
1861		kmfber_free(asn1, 1);
1862
1863	return (ret);
1864}
1865
1866KMF_RETURN
1867kmf_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
1881KMF_RETURN
1882kmf_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
1901KMF_RETURN
1902kmf_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
1933KMF_RETURN
1934kmf_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 == 0)
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 */
1986KMF_RETURN
1987set_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
2002static KMF_RETURN
2003set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
2004{
2005	if (data == NULL || bigint == NULL || bigint->len == 0)
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
2020KMF_RETURN
2021kmf_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
2029KMF_RETURN
2030kmf_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
2045KMF_RETURN
2046kmf_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
2058KMF_RETURN
2059kmf_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
2071KMF_RETURN
2072kmf_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
2158out:
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
2175KMF_RETURN
2176kmf_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
2192KMF_RETURN
2193kmf_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
2252out:
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 */
2263KMF_RETURN
2264KMF_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
2270KMF_RETURN
2271KMF_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
2277KMF_RETURN
2278KMF_GetCertIDString(const KMF_DATA *SignedCert,	char **idstr)
2279{
2280	return (kmf_get_cert_id_str(SignedCert, idstr));
2281}
2282