clasn1.c revision 3089:8ddeb2ace8aa
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 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 *
25 *
26 * File: CLASN1.C
27 *
28 * Copyright (c) 1995-1999 Intel Corporation. All rights reserved.
29 *
30 */
31
32#pragma ident	"%Z%%M%	%I%	%E% SMI"
33
34#include <strings.h>
35#include <kmftypes.h>
36#include <ber_der.h>
37#include <kmfapi.h>
38#include <kmfapiP.h>
39
40#include <stdio.h>
41
42#define	DSA_RAW_SIG_LEN	40
43
44static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
45const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
46	OID_ExtensionRequest};
47
48static KMF_RETURN
49encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
50{
51	KMF_RETURN ret = KMF_OK;
52
53	if (kmfber_printf(asn1, "{D", &algoid->algorithm) == -1) {
54		ret = KMF_ERR_BAD_CERT_FORMAT;
55	}
56	if (algoid->parameters.Data == NULL ||
57		algoid->parameters.Length == 0) {
58		if (kmfber_printf(asn1, "n}") == -1)
59			return (KMF_ERR_BAD_CERT_FORMAT);
60	} else {
61		/*
62		 * The algorithm data can be anything, so we just write it
63		 * straight into the buffer.  It is already DER encoded.
64		 */
65		(void) kmfber_write(asn1, (char *)algoid->parameters.Data,
66			algoid->parameters.Length, 0);
67		if (kmfber_printf(asn1, "}") == -1) {
68			ret = KMF_ERR_BAD_CERT_FORMAT;
69		}
70	}
71
72	return (ret);
73}
74
75static void
76free_data(KMF_DATA *data)
77{
78	if (data == NULL || data->Data == NULL)
79		return;
80
81	free(data->Data);
82	data->Data = NULL;
83	data->Length = 0;
84}
85
86static void
87free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
88{
89	free_data(&algoid->algorithm);
90	free_data(&algoid->parameters);
91}
92
93static void
94free_decoded_spki(KMF_X509_SPKI *spki)
95{
96	if (spki != NULL) {
97		free_algoid(&spki->algorithm);
98		free_data(&spki->subjectPublicKey);
99	}
100}
101
102static void
103free_rdn_data(KMF_X509_NAME *name)
104{
105	KMF_X509_RDN 		*newrdn = NULL;
106	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
107	int i, j;
108
109	if (name && name->numberOfRDNs) {
110		for (i = 0; i < name->numberOfRDNs; i++) {
111			newrdn = &name->RelativeDistinguishedName[i];
112			for (j = 0; j < newrdn->numberOfPairs; j++) {
113				av = &newrdn->AttributeTypeAndValue[j];
114				free_data(&av->type);
115				free_data(&av->value);
116			}
117			free(newrdn->AttributeTypeAndValue);
118		}
119		free(name->RelativeDistinguishedName);
120		name->numberOfRDNs = 0;
121		name->RelativeDistinguishedName = NULL;
122	}
123}
124
125static void
126free_validity(KMF_X509_VALIDITY *validity)
127{
128	free_data(&validity->notBefore.time);
129	free_data(&validity->notAfter.time);
130}
131
132static void
133free_one_extension(KMF_X509_EXTENSION *exptr)
134{
135	free_data(&exptr->extnId);
136	free_data(&exptr->BERvalue);
137
138	if (exptr->value.tagAndValue) {
139		free_data(&exptr->value.tagAndValue->value);
140		free(exptr->value.tagAndValue);
141	}
142}
143
144static void
145free_extensions(KMF_X509_EXTENSIONS *extns)
146{
147	int i;
148	KMF_X509_EXTENSION *exptr;
149
150	if (extns && extns->numberOfExtensions > 0) {
151		for (i = 0; i < extns->numberOfExtensions; i++) {
152			exptr = &extns->extensions[i];
153			free_one_extension(exptr);
154		}
155		free(extns->extensions);
156		extns->numberOfExtensions = 0;
157		extns->extensions = NULL;
158	}
159}
160
161static void
162free_tbscsr(KMF_TBS_CSR *tbscsr)
163{
164	if (tbscsr) {
165		free_data(&tbscsr->version);
166
167		free_rdn_data(&tbscsr->subject);
168
169		free_decoded_spki(&tbscsr->subjectPublicKeyInfo);
170
171		free_extensions(&tbscsr->extensions);
172	}
173}
174
175
176static void
177free_bigint(KMF_BIGINT *bn)
178{
179	if (bn != NULL && bn->val != NULL) {
180		free(bn->val);
181		bn->val = NULL;
182		bn->len = 0;
183	}
184}
185
186static void
187free_tbscert(KMF_X509_TBS_CERT *tbscert)
188{
189	if (tbscert) {
190		free_data(&tbscert->version);
191		free_bigint(&tbscert->serialNumber);
192		free_algoid(&tbscert->signature);
193
194		free_rdn_data(&tbscert->issuer);
195		free_rdn_data(&tbscert->subject);
196
197		free_validity(&tbscert->validity);
198
199		free_data(&tbscert->issuerUniqueIdentifier);
200		free_data(&tbscert->subjectUniqueIdentifier);
201		free_decoded_spki(&tbscert->subjectPublicKeyInfo);
202		free_extensions(&tbscert->extensions);
203
204		free_data(&tbscert->issuerUniqueIdentifier);
205		free_data(&tbscert->subjectUniqueIdentifier);
206	}
207}
208
209static void
210free_decoded_cert(KMF_X509_CERTIFICATE *certptr)
211{
212	if (!certptr)
213		return;
214
215	free_tbscert(&certptr->certificate);
216
217	free_algoid(&certptr->signature.algorithmIdentifier);
218	free_data(&certptr->signature.encrypted);
219}
220
221static KMF_RETURN
222get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
223{
224	KMF_RETURN ret = KMF_OK;
225	ber_tag_t tag, newtag;
226	ber_len_t size;
227	BerValue AlgOID = {NULL, 0};
228
229	tag = kmfber_next_element(asn1, &size, NULL);
230	if (tag != BER_CONSTRUCTED_SEQUENCE)
231		return (KMF_ERR_BAD_CERT_FORMAT);
232
233	if ((tag = kmfber_scanf(asn1, "{Dt", &AlgOID, &newtag)) == -1) {
234		return (KMF_ERR_BAD_CERT_FORMAT);
235	}
236	algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val;
237	algoid->algorithm.Length = AlgOID.bv_len;
238
239	if (newtag == BER_NULL) {
240		(void) kmfber_scanf(asn1, "n}");
241		algoid->parameters.Data = NULL;
242		algoid->parameters.Length = 0;
243	} else {
244		/* Peek at the tag and length bytes */
245		if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
246			ret = KMF_ERR_BAD_CERT_FORMAT;
247			goto cleanup;
248		}
249
250		/*
251		 * We need to read the tag and the length bytes too,
252		 * so adjust the size.
253		 */
254		size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
255		algoid->parameters.Data = malloc(size);
256		if (algoid->parameters.Data == NULL) {
257			ret = KMF_ERR_MEMORY;
258			goto cleanup;
259		}
260		/* read the raw data into the Algoritm params area. */
261		if (kmfber_read(asn1, (char *)algoid->parameters.Data,
262			size) == -1) {
263			ret = KMF_ERR_BAD_CERT_FORMAT;
264			goto cleanup;
265		}
266		algoid->parameters.Length = size;
267		if ((tag = kmfber_scanf(asn1, "}")) == -1) {
268			ret = KMF_ERR_BAD_CERT_FORMAT;
269		}
270	}
271cleanup:
272	if (ret != KMF_OK) {
273		free_algoid(algoid);
274	}
275
276	return (ret);
277}
278
279static KMF_RETURN
280CopyData(KMF_DATA *src, KMF_DATA *dst)
281{
282	if (src && dst && src->Data != NULL && src->Length > 0) {
283		dst->Length = src->Length;
284		dst->Data = malloc(sizeof (dst->Length));
285		if (dst->Data == NULL)
286			return (KMF_ERR_MEMORY);
287		(void) memcpy(dst->Data, src->Data, src->Length);
288	}
289	return (KMF_OK);
290}
291
292static KMF_RETURN
293encode_spki(BerElement *asn1, KMF_X509_SPKI *spki)
294{
295	KMF_RETURN ret = KMF_OK;
296
297	if (kmfber_printf(asn1, "{") == -1)
298		return (KMF_ERR_BAD_CERT_FORMAT);
299
300	if ((ret = encode_algoid(asn1, &spki->algorithm)) != KMF_OK)
301		return (ret);
302
303	if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data,
304				spki->subjectPublicKey.Length * 8) == -1)
305		return (KMF_ERR_BAD_CERT_FORMAT);
306
307	return (ret);
308}
309
310KMF_RETURN
311DerEncodeSPKI(KMF_X509_SPKI *spki, KMF_DATA *EncodedSPKI)
312{
313	KMF_RETURN ret = KMF_OK;
314	BerElement *asn1;
315	BerValue *result;
316
317	if (spki == NULL || EncodedSPKI == NULL)
318		return (KMF_ERR_BAD_PARAMETER);
319
320	if ((asn1 = kmfder_alloc()) == NULL)
321		return (KMF_ERR_MEMORY);
322
323	if ((ret = encode_spki(asn1, spki)) != KMF_OK) {
324		return (ret);
325	}
326
327	if (kmfber_flatten(asn1, &result) == -1) {
328		kmfber_free(asn1, 1);
329		return (KMF_ERR_ENCODING);
330	}
331
332	EncodedSPKI->Data = (uchar_t *)result->bv_val;
333	EncodedSPKI->Length = result->bv_len;
334
335	free(result);
336	kmfber_free(asn1, 1);
337	return (KMF_OK);
338}
339
340static KMF_RETURN
341get_spki(BerElement *asn1, KMF_X509_SPKI *spki)
342{
343	KMF_RETURN ret = KMF_OK;
344	char *bitstr = NULL;
345	ber_len_t size;
346
347	if (kmfber_scanf(asn1, "{") == -1)
348		return (KMF_ERR_BAD_CERT_FORMAT);
349
350	if ((ret = get_algoid(asn1, &spki->algorithm)) != KMF_OK)
351		return (ret);
352
353	if (kmfber_scanf(asn1, "B}", &bitstr, &size) == BER_BIT_STRING) {
354		spki->subjectPublicKey.Data = (uchar_t *)bitstr;
355		spki->subjectPublicKey.Length = size / 8;
356	} else {
357		ret = KMF_ERR_BAD_CERT_FORMAT;
358		goto cleanup;
359	}
360cleanup:
361	if (ret != KMF_OK) {
362		if (bitstr != NULL)
363			free(bitstr);
364		spki->subjectPublicKey.Data = NULL;
365		spki->subjectPublicKey.Length = 0;
366
367		free_algoid(&spki->algorithm);
368	}
369	return (ret);
370}
371
372KMF_RETURN
373DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
374{
375	BerElement *asn1;
376	BerValue *buf;
377	int n;
378
379	if (rawdata == NULL || signature == NULL)
380		return (KMF_ERR_BAD_PARAMETER);
381
382	if (rawdata->Data == NULL || rawdata->Length != DSA_RAW_SIG_LEN)
383		return (KMF_ERR_BAD_PARAMETER);
384
385	asn1 = kmfder_alloc();
386	if (asn1 == NULL)
387		return (KMF_ERR_MEMORY);
388
389	/*
390	 * The DSA signature is the concatenation of 2 SHA-1 hashed
391	 * bignum values.
392	 */
393	n = DSA_RAW_SIG_LEN/2;
394	if (kmfber_printf(asn1, "{II}",
395			rawdata->Data, n,
396			&rawdata->Data[n], n) == -1) {
397		kmfber_free(asn1, 1);
398		return (KMF_ERR_MEMORY);
399	}
400
401	if (kmfber_flatten(asn1, &buf) == -1) {
402		kmfber_free(asn1, 1);
403		return (KMF_ERR_ENCODING);
404	}
405
406	signature->Data = (uchar_t *)buf->bv_val;
407	signature->Length = buf->bv_len;
408
409	kmfber_free(asn1, 1);
410	free(buf);
411
412	return (KMF_OK);
413}
414
415KMF_RETURN
416DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
417{
418	KMF_RETURN ret = KMF_OK;
419	BerElement *asn1 = NULL;
420	BerValue buf, *R = NULL, *S = NULL;
421
422	buf.bv_val = (char *)encoded->Data;
423	buf.bv_len = encoded->Length;
424
425	if (encoded == NULL || encoded->Data == NULL ||
426	    signature == NULL)
427		return (KMF_ERR_BAD_PARAMETER);
428
429	signature->Data = NULL;
430	signature->Length = 0;
431
432	if ((asn1 = kmfder_init(&buf)) == NULL)
433		return (KMF_ERR_MEMORY);
434
435	if (kmfber_scanf(asn1, "{II}", &R, &S) == -1) {
436		ret = KMF_ERR_BAD_PARAMETER;
437		goto cleanup;
438	}
439	signature->Length = R->bv_len + S->bv_len;
440	signature->Data = malloc(signature->Length);
441	if (signature->Data == NULL)  {
442		ret = KMF_ERR_MEMORY;
443		goto cleanup;
444	}
445	(void) memcpy(signature->Data, R->bv_val, R->bv_len);
446	(void) memcpy(&signature->Data[R->bv_len], S->bv_val, S->bv_len);
447
448cleanup:
449	if (R && R->bv_val)
450		free(R->bv_val);
451	if (S && S->bv_val)
452		free(S->bv_val);
453
454	if (S) free(S);
455	if (R) free(R);
456
457	if (asn1) kmfber_free(asn1, 1);
458
459	return (ret);
460}
461
462KMF_RETURN
463DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki)
464{
465	KMF_RETURN ret = KMF_OK;
466	BerElement *asn1;
467	BerValue bv;
468
469	if (EncodedSPKI == NULL || EncodedSPKI->Data == NULL ||
470		spki == NULL)
471		return (KMF_ERR_BAD_PARAMETER);
472
473	(void) memset(spki, 0, sizeof (KMF_X509_SPKI));
474
475	bv.bv_val = (char *)EncodedSPKI->Data;
476	bv.bv_len = EncodedSPKI->Length;
477
478	if ((asn1 = kmfder_init(&bv)) == NULL)
479		return (KMF_ERR_MEMORY);
480
481	ret = get_spki(asn1, spki);
482
483cleanup:
484	if (ret != KMF_OK) {
485		free_decoded_spki(spki);
486	}
487	kmfber_free(asn1, 1);
488
489	return (ret);
490}
491
492KMF_RETURN
493CopySPKI(KMF_X509_SPKI *src,
494		KMF_X509_SPKI **dest)
495{
496	KMF_RETURN ret = KMF_OK;
497	KMF_X509_SPKI *newspki;
498
499	*dest = NULL;
500
501	newspki = malloc(sizeof (KMF_X509_SPKI));
502	if (newspki == NULL)
503		return (KMF_ERR_MEMORY);
504	(void) memset(newspki, 0, sizeof (KMF_X509_SPKI));
505
506	ret = CopyData(&src->algorithm.algorithm,
507		&newspki->algorithm.algorithm);
508	if (ret != KMF_OK)
509		goto cleanup;
510
511	ret = CopyData(&src->algorithm.parameters,
512			&newspki->algorithm.parameters);
513	if (ret != KMF_OK)
514		goto cleanup;
515
516	ret = CopyData(&src->subjectPublicKey,
517		&newspki->subjectPublicKey);
518	if (ret != KMF_OK)
519		goto cleanup;
520
521	*dest = newspki;
522cleanup:
523	if (ret != KMF_OK) {
524		if (newspki)
525			free_decoded_spki(newspki);
526	}
527	return (ret);
528}
529
530static KMF_RETURN
531encode_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
532{
533	int ret;
534
535	ret = kmfber_printf(asn1, "{tsts}",
536			validity->notBefore.timeType,
537			validity->notBefore.time.Data,
538			validity->notAfter.timeType,
539			validity->notAfter.time.Data);
540
541	if (ret == -1)
542		return (KMF_ERR_BAD_CERT_FORMAT);
543
544	return (KMF_OK);
545}
546
547static KMF_RETURN
548get_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
549{
550	KMF_RETURN ret = KMF_OK;
551	int tag;
552	int t1, t2;
553	ber_len_t size;
554	char *t1str, *t2str;
555
556	(void) memset(validity, 0, sizeof (KMF_X509_VALIDITY));
557
558	tag = kmfber_next_element(asn1, &size, NULL);
559	if (tag != BER_CONSTRUCTED_SEQUENCE) {
560		return (KMF_ERR_BAD_CERT_FORMAT);
561	}
562
563	if (kmfber_scanf(asn1, "{tata}", &t1, &t1str, &t2, &t2str) == -1) {
564		return (KMF_ERR_BAD_CERT_FORMAT);
565	}
566
567	validity->notBefore.timeType = t1;
568	validity->notBefore.time.Data = (uchar_t *)t1str;
569	validity->notBefore.time.Length = strlen(t1str);
570
571	validity->notAfter.timeType = t2;
572	validity->notAfter.time.Data = (uchar_t *)t2str;
573	validity->notAfter.time.Length = strlen(t2str);
574
575	return (ret);
576}
577
578KMF_RETURN
579AddRDN(KMF_X509_NAME *name, KMF_X509_RDN *newrdn)
580{
581	KMF_RETURN ret = KMF_OK;
582	KMF_X509_RDN *rdnslot = NULL;
583
584	/* Add new RDN record to existing list */
585	name->numberOfRDNs++;
586	name->RelativeDistinguishedName =
587			realloc(name->RelativeDistinguishedName,
588			name->numberOfRDNs * sizeof (KMF_X509_RDN));
589
590	if (name->RelativeDistinguishedName == NULL) {
591		ret = KMF_ERR_MEMORY;
592		goto cleanup;
593	}
594	rdnslot = &name->RelativeDistinguishedName[name->numberOfRDNs-1];
595
596	if (newrdn) {
597		(void) memcpy(rdnslot, newrdn, sizeof (KMF_X509_RDN));
598	} else {
599		rdnslot->numberOfPairs = 0;
600		rdnslot->AttributeTypeAndValue = NULL;
601	}
602
603cleanup:
604	/* No cleanup needed here */
605	return (ret);
606}
607
608static KMF_RETURN
609encode_rdn(BerElement *asn1, KMF_X509_NAME *name)
610{
611	KMF_RETURN ret = KMF_OK;
612	KMF_X509_TYPE_VALUE_PAIR *attrtvpair = NULL;
613	int i;
614	KMF_X509_RDN *rdn;
615
616	if (kmfber_printf(asn1, "{") == -1) {
617		ret = KMF_ERR_MEMORY;
618		goto cleanup;
619	}
620
621	for (i = 0; i < name->numberOfRDNs; i++) {
622		if (kmfber_printf(asn1, "[") == -1) {
623			ret = KMF_ERR_MEMORY;
624			goto cleanup;
625		}
626		rdn = &name->RelativeDistinguishedName[i];
627		attrtvpair = rdn->AttributeTypeAndValue;
628
629		if (rdn->numberOfPairs > 0) {
630			if (kmfber_printf(asn1, "{Dto}",
631				&attrtvpair->type,
632				attrtvpair->valueType,
633				attrtvpair->value.Data,
634				attrtvpair->value.Length) == -1) {
635				ret = KMF_ERR_MEMORY;
636				goto cleanup;
637			}
638		}
639		if (kmfber_printf(asn1, "]") == -1) {
640			ret = KMF_ERR_MEMORY;
641			goto cleanup;
642		}
643	}
644
645	if (kmfber_printf(asn1, "}") == -1) {
646		ret = KMF_ERR_MEMORY;
647		goto cleanup;
648	}
649
650cleanup:
651	/* No cleanup needed here */
652
653	return (ret);
654}
655
656
657KMF_RETURN
658CopyRDN(KMF_X509_NAME *srcname, KMF_X509_NAME **destname)
659{
660	KMF_RETURN ret = KMF_OK;
661	KMF_X509_NAME 		*newname = NULL;
662	KMF_X509_RDN 		*rdn, *dstrdn;
663	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
664	KMF_X509_TYPE_VALUE_PAIR *srcav = NULL;
665	KMF_X509_TYPE_VALUE_PAIR *dstav = NULL;
666	int i, j;
667
668	newname = malloc(sizeof (KMF_X509_NAME));
669	if (newname == NULL)
670		return (KMF_ERR_MEMORY);
671	(void) memset(newname, 0, sizeof (KMF_X509_NAME));
672
673	newname->numberOfRDNs = srcname->numberOfRDNs;
674	newname->RelativeDistinguishedName = malloc(newname->numberOfRDNs *
675			sizeof (KMF_X509_RDN));
676	if (newname->RelativeDistinguishedName == NULL) {
677		free(newname);
678		return (KMF_ERR_MEMORY);
679	}
680	/* Copy each RDN in the list */
681	for (i = 0; i < newname->numberOfRDNs; i++) {
682		rdn = &srcname->RelativeDistinguishedName[i];
683
684		dstrdn = &newname->RelativeDistinguishedName[i];
685		(void) memset(dstrdn, 0, sizeof (KMF_X509_RDN));
686
687		dstrdn->numberOfPairs = rdn->numberOfPairs;
688		if (dstrdn->numberOfPairs > 0) {
689			av = malloc(dstrdn->numberOfPairs *
690				sizeof (KMF_X509_TYPE_VALUE_PAIR));
691			if (av == NULL) {
692				ret = KMF_ERR_MEMORY;
693				goto cleanup;
694			}
695			(void) memset(av, 0, dstrdn->numberOfPairs *
696				sizeof (KMF_X509_TYPE_VALUE_PAIR));
697
698			dstrdn->AttributeTypeAndValue = av;
699			if (av == NULL) {
700				ret = KMF_ERR_MEMORY;
701				goto cleanup;
702			}
703			/* Copy each A/V pair in the list */
704			for (j = 0; j < dstrdn->numberOfPairs; j++) {
705				srcav = &rdn->AttributeTypeAndValue[j];
706				dstav = &dstrdn->AttributeTypeAndValue[j];
707				if ((ret = CopyData(&srcav->type,
708					&dstav->type)) != KMF_OK)
709					goto cleanup;
710				dstav->valueType = srcav->valueType;
711				if ((ret = CopyData(&srcav->value,
712					&dstav->value)) != KMF_OK)
713					goto cleanup;
714			}
715		} else {
716			dstrdn->AttributeTypeAndValue = NULL;
717		}
718	}
719	*destname = newname;
720
721cleanup:
722	if (ret != KMF_OK) {
723		if (newname)
724			free_rdn_data(newname);
725
726		free(newname);
727		*destname = NULL;
728	}
729	return (ret);
730}
731
732#define	VALID_DIRECTORYSTRING_TAG(t) ( \
733	(t == BER_UTF8_STRING) || \
734	(t == BER_PRINTABLE_STRING) || \
735	(t == BER_IA5STRING) || \
736	(t == BER_T61STRING) || \
737	(t == BER_BMP_STRING) || \
738	(t == BER_UNIVERSAL_STRING))
739
740static KMF_RETURN
741get_rdn(BerElement *asn1, KMF_X509_NAME *name)
742{
743	KMF_RETURN ret = KMF_OK;
744	ber_len_t size;
745	char *end;
746	int tag;
747	BerValue AttrOID;
748	char *AttrValue = NULL;
749	KMF_X509_TYPE_VALUE_PAIR *newpair = NULL;
750	KMF_X509_RDN 		newrdn;
751
752	/*
753	 * AttributeType	::=  OBJECT IDENTIFIER
754	 * AttributeValue	::=  ANY
755	 *
756	 * AttributeTypeAndValue	::=  SEQUENCE {
757	 *	type    AttributeType,
758	 *	value   AttributeValue }
759	 *
760	 * Name ::= CHOICE { -- only one possibility for now --
761	 * 		rdnSequence  RDNSequence }
762	 *
763	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
764	 *
765	 * DistinguishedName ::=   RDNSequence
766	 *
767	 * RelativeDistinguishedName  ::=
768	 *		 SET SIZE (1 .. MAX) OF AttributeTypeAndValue
769	 *
770	 */
771
772	name->numberOfRDNs = 0;
773	name->RelativeDistinguishedName = NULL;
774
775	/* Get the beginning of the RDN Set and a ptr to the end */
776	tag = kmfber_first_element(asn1, &size, &end);
777	if (tag != BER_CONSTRUCTED_SET) {
778		ret = KMF_ERR_BAD_CERT_FORMAT;
779		goto cleanup;
780	}
781
782	/* Walk through the individual SET items until the "end" is reached */
783	while ((tag = kmfber_next_element(asn1, &size, end)) ==
784		BER_CONSTRUCTED_SET) {
785		/* Skip over the SET tag */
786		if (kmfber_scanf(asn1, "T", &tag) == -1) {
787			ret = KMF_ERR_BAD_CERT_FORMAT;
788			break;
789		}
790
791		/* An "empty" set member means we tack on an empty node */
792		if (size == 0) {
793			if ((ret = AddRDN(name, NULL)) != KMF_OK)
794				goto cleanup;
795			continue;
796		}
797
798		/* Attr OID and peek at the next tag and field length */
799		if (kmfber_scanf(asn1, "{Dtl", &AttrOID, &tag, &size) == -1) {
800			ret = KMF_ERR_BAD_CERT_FORMAT;
801			break;
802		}
803
804		if (!(VALID_DIRECTORYSTRING_TAG(tag))) {
805			ret = KMF_ERR_BAD_CERT_FORMAT;
806			break;
807		}
808
809		if (kmfber_scanf(asn1, "a}]", &AttrValue) == -1) {
810			ret = KMF_ERR_BAD_CERT_FORMAT;
811			break;
812		}
813
814		/* Allocate a new name/value pair record */
815		newpair = malloc(sizeof (KMF_X509_TYPE_VALUE_PAIR));
816		if (newpair == NULL) {
817			ret = KMF_ERR_MEMORY;
818			break;
819		}
820		(void) memset(newpair, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
821		newpair->type.Data = (uchar_t *)AttrOID.bv_val;
822		newpair->type.Length = AttrOID.bv_len;
823		newpair->valueType = tag; /* what kind of string is it? */
824		newpair->value.Data = (uchar_t *)AttrValue;
825		newpair->value.Length = strlen(AttrValue);
826
827		(void) memset(&newrdn, 0, sizeof (KMF_X509_RDN));
828		newrdn.numberOfPairs = 1;
829		newrdn.AttributeTypeAndValue = newpair;
830
831		if ((ret = AddRDN(name, &newrdn)) != KMF_OK)
832			break;
833	}
834
835cleanup:
836	if (ret != KMF_OK) {
837		free_rdn_data(name);
838	}
839	return (ret);
840}
841
842static KMF_RETURN
843set_der_integer(KMF_DATA *data, int value)
844{
845	if (data == NULL)
846		return (KMF_ERR_BAD_PARAMETER);
847
848	data->Data = malloc(sizeof (int));
849	if (data->Data == NULL)
850		return (KMF_ERR_MEMORY);
851
852	data->Length = sizeof (int);
853	(void) memcpy((void *)data->Data, (const void *)&value, sizeof (int));
854
855	return (KMF_OK);
856}
857
858static KMF_RETURN
859set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
860{
861	if (data == NULL || bigint == NULL)
862		return (KMF_ERR_BAD_PARAMETER);
863
864	data->val = malloc(bigint->len);
865	if (data->val == NULL)
866		return (KMF_ERR_MEMORY);
867
868	data->len = bigint->len;
869	(void) memcpy((void *)data->val, (const void *)bigint->val,
870		bigint->len);
871
872	return (KMF_OK);
873}
874
875static KMF_RETURN
876encode_uniqueid(BerElement *asn1, int tag, KMF_DATA *id)
877{
878	KMF_RETURN ret = KMF_OK;
879	uint32_t len;
880
881	len = kmfber_calc_taglen(BER_BIT_STRING) +
882		kmfber_calc_lenlen(id->Length * 8) + id->Length;
883	if (kmfber_printf(asn1, "TlB", tag, len,
884		id->Data, id->Length * 8) == -1)
885		return (KMF_ERR_BAD_CERT_FORMAT);
886
887	return (ret);
888}
889
890static KMF_RETURN
891encode_extension_list(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
892{
893	KMF_RETURN ret = KMF_OK;
894	int i;
895
896	for (i = 0; i < extns->numberOfExtensions; i++) {
897		BerValue v;
898		v.bv_val = (char *)extns->extensions[i].extnId.Data;
899		v.bv_len = extns->extensions[i].extnId.Length;
900
901		if (kmfber_printf(asn1, "{D", &v) == -1)  {
902			ret = KMF_ERR_ENCODING;
903			goto cleanup;
904		}
905
906		if (extns->extensions[i].critical) {
907			if (kmfber_printf(asn1, "b",
908				extns->extensions[i].critical) == -1) {
909				ret = KMF_ERR_ENCODING;
910				goto cleanup;
911			}
912		}
913
914		if (kmfber_printf(asn1, "o}",
915			extns->extensions[i].BERvalue.Data,
916			extns->extensions[i].BERvalue.Length) == -1) {
917			ret = KMF_ERR_ENCODING;
918			goto cleanup;
919		}
920	}
921cleanup:
922	return (ret);
923}
924
925static KMF_RETURN
926encode_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
927{
928	KMF_RETURN ret = KMF_OK;
929	BerElement *extn = NULL;
930	BerValue *extnvalue = NULL;
931
932	extn = kmfder_alloc();
933	if (extn == NULL)
934		return (KMF_ERR_MEMORY);
935
936	if (kmfber_printf(extn, "{") == -1) {
937		ret = KMF_ERR_ENCODING;
938		goto cleanup;
939	}
940
941	ret = encode_extension_list(extn, extns);
942
943	if (kmfber_printf(extn, "}") == -1) {
944		ret = KMF_ERR_ENCODING;
945		goto cleanup;
946	}
947
948	if (kmfber_flatten(extn, &extnvalue) == -1) {
949		ret = KMF_ERR_MEMORY;
950		goto cleanup;
951	}
952
953	if (kmfber_printf(asn1, "Tl", 0xA3, extnvalue->bv_len) == -1) {
954		ret = KMF_ERR_BAD_CERT_FORMAT;
955		goto cleanup;
956	}
957
958	if (kmfber_write(asn1, extnvalue->bv_val, extnvalue->bv_len, 0) == -1) {
959		ret = KMF_ERR_BAD_CERT_FORMAT;
960		goto cleanup;
961	}
962
963cleanup:
964	kmfber_free(extn, 1);
965	if (extnvalue != NULL)
966		kmfber_bvfree(extnvalue);
967
968	return (ret);
969}
970
971static KMF_RETURN
972get_one_extension(BerElement *asn1, KMF_X509_EXTENSION **retex, char *end)
973{
974	KMF_RETURN ret = KMF_OK;
975	ber_len_t size;
976	int  critical, tag;
977	KMF_X509_EXTENSION *ex = NULL;
978	BerValue extOID;
979	BerValue extValue;
980	BerElement *extnber = NULL;
981
982	if (kmfber_scanf(asn1, "T", &tag) == -1) {
983		ret = KMF_ERR_BAD_CERT_FORMAT;
984		goto cleanup;
985	}
986
987	tag = kmfber_next_element(asn1, &size, end);
988	if (tag != BER_OBJECT_IDENTIFIER) {
989		ret = KMF_ERR_BAD_CERT_FORMAT;
990		goto cleanup;
991	}
992	if (kmfber_scanf(asn1, "D", &extOID) == -1) {
993		ret = KMF_ERR_BAD_CERT_FORMAT;
994		goto cleanup;
995	}
996
997	tag = kmfber_next_element(asn1, &size, end);
998	if (tag != BER_BOOLEAN) {
999		critical = 0;
1000		if (tag != BER_OCTET_STRING)
1001			goto cleanup;
1002	} else {
1003		if (kmfber_scanf(asn1, "b", &critical) == -1)
1004			goto cleanup;
1005	}
1006
1007	tag = kmfber_next_element(asn1, &size, end);
1008	if (tag != BER_OCTET_STRING)  {
1009		ret = KMF_ERR_BAD_CERT_FORMAT;
1010		goto cleanup;
1011	}
1012	if (kmfber_scanf(asn1, "o", &extValue) == -1)  {
1013		ret = KMF_ERR_BAD_CERT_FORMAT;
1014		goto cleanup;
1015	}
1016
1017	/* allocate a new Extension record */
1018	ex = malloc(sizeof (KMF_X509_EXTENSION));
1019	if (ex == NULL) {
1020		ret = KMF_ERR_MEMORY;
1021		goto cleanup;
1022	}
1023	(void) memset(ex, 0, sizeof (ex));
1024
1025	ex->extnId.Data = (uchar_t *)extOID.bv_val;
1026	ex->extnId.Length = extOID.bv_len;
1027	ex->critical = critical;
1028	ex->format = KMF_X509_DATAFORMAT_ENCODED;
1029	ex->BERvalue.Data = (uchar_t *)extValue.bv_val;
1030	ex->BERvalue.Length = extValue.bv_len;
1031
1032	/* Tag and value is a little tricky */
1033	ex->value.tagAndValue = malloc(sizeof (KMF_X509EXT_TAGandVALUE));
1034	if (ex->value.tagAndValue == NULL) {
1035		ret = KMF_ERR_MEMORY;
1036		goto cleanup;
1037	}
1038	(void) memset(ex->value.tagAndValue, 0,
1039		sizeof (KMF_X509EXT_TAGandVALUE));
1040
1041	/* Parse the Extension value field */
1042	extnber = kmfder_init(&extValue);
1043	if (extnber == NULL) {
1044		ret = KMF_ERR_MEMORY;
1045		goto cleanup;
1046	}
1047
1048	/* Get the tag and length of the extension field */
1049	if (kmfber_scanf(extnber, "tl", &tag, &size) == -1) {
1050		ret = KMF_ERR_BAD_CERT_FORMAT;
1051		goto cleanup;
1052	}
1053
1054	if (kmfber_scanf(extnber, "T", &tag) == -1) {
1055		ret = KMF_ERR_BAD_CERT_FORMAT;
1056		goto cleanup;
1057	}
1058
1059	ex->value.tagAndValue->value.Data = malloc(size);
1060	ex->value.tagAndValue->value.Length = size;
1061	size = kmfber_read(extnber,
1062		(char *)ex->value.tagAndValue->value.Data, size);
1063	if (size != ex->value.tagAndValue->value.Length) {
1064		ret = KMF_ERR_BAD_CERT_FORMAT;
1065		goto cleanup;
1066	}
1067	kmfber_free(extnber, 1);
1068	ex->value.tagAndValue->type = tag;
1069
1070	*retex = ex;
1071cleanup:
1072	if (ret != KMF_OK) {
1073		if (ex != NULL)
1074			free_one_extension(ex);
1075	}
1076
1077	return (ret);
1078}
1079
1080static KMF_RETURN
1081get_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
1082{
1083	KMF_RETURN ret = KMF_OK;
1084	ber_len_t size;
1085	char *end = NULL;
1086	KMF_X509_EXTENSION *ex = NULL;
1087
1088	/*
1089	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
1090	 *
1091	 * Extension  ::=  SEQUENCE  {
1092	 *	extnID		OBJECT IDENTIFIER,
1093	 *	critical	BOOLEAN DEFAULT FALSE,
1094	 *	extnValue	OCTET STRING  }
1095	 *
1096	 * { {{D}Bo}, ... }
1097	 */
1098	if (kmfber_first_element(asn1, &size, &end) !=
1099		BER_CONSTRUCTED_SEQUENCE)
1100		return (KMF_ERR_BAD_CERT_FORMAT);
1101
1102	while (kmfber_next_element(asn1, &size, end) ==
1103		BER_CONSTRUCTED_SEQUENCE) {
1104		ret = get_one_extension(asn1, &ex, end);
1105		if (ret != KMF_OK)
1106			goto cleanup;
1107
1108		extns->numberOfExtensions++;
1109		extns->extensions = realloc(extns->extensions,
1110			extns->numberOfExtensions *
1111			sizeof (KMF_X509_EXTENSION));
1112		if (extns->extensions == NULL) {
1113			ret = KMF_ERR_MEMORY;
1114			break;
1115		}
1116
1117		extns->extensions[extns->numberOfExtensions-1] = *ex;
1118		free(ex);
1119	}
1120
1121cleanup:
1122	if (ret != KMF_OK)
1123		free_extensions(extns);
1124
1125	return (ret);
1126}
1127
1128KMF_RETURN
1129decode_tbscert_data(BerElement *asn1,
1130	KMF_X509_TBS_CERT **signed_cert_ptr_ptr)
1131{
1132	KMF_RETURN ret = KMF_OK;
1133	KMF_X509_TBS_CERT	*tbscert = NULL;
1134	int tag, version;
1135	struct berval *bvserno = NULL;
1136	KMF_BIGINT serno;
1137
1138	if (kmfber_scanf(asn1, "{t", &tag) == -1) {
1139		ret = KMF_ERR_BAD_CERT_FORMAT;
1140		goto cleanup;
1141	}
1142
1143	/* Version number is optional */
1144	if (tag == 0xA0) {
1145		if (kmfber_scanf(asn1, "Ti", &tag, &version) == -1) {
1146			ret = KMF_ERR_BAD_CERT_FORMAT;
1147			goto cleanup;
1148		}
1149	} else {
1150		version = 0; /* DEFAULT v1 (0) */
1151	}
1152
1153	/* Now get the serial number, it is not optional */
1154	if (kmfber_scanf(asn1, "I", &bvserno) == -1) {
1155		ret = KMF_ERR_BAD_CERT_FORMAT;
1156		goto cleanup;
1157	} else {
1158		serno.val = (uchar_t *)bvserno->bv_val;
1159		serno.len = bvserno->bv_len;
1160	}
1161
1162	tbscert = malloc(sizeof (KMF_X509_TBS_CERT));
1163	if (!tbscert) {
1164		ret = KMF_ERR_MEMORY;
1165		goto cleanup;
1166	}
1167
1168	(void) memset(tbscert, 0, sizeof (KMF_X509_TBS_CERT));
1169
1170	if ((ret = set_der_integer(&tbscert->version, version)) != KMF_OK)
1171		goto cleanup;
1172
1173	if ((ret = set_bigint(&tbscert->serialNumber, &serno)) != KMF_OK)
1174		goto cleanup;
1175
1176	if ((ret = get_algoid(asn1, &tbscert->signature)) != KMF_OK)
1177		goto cleanup;
1178
1179	if ((ret = get_rdn(asn1, &tbscert->issuer)) != KMF_OK)
1180		goto cleanup;
1181
1182	if ((ret = get_validity(asn1, &tbscert->validity)) != KMF_OK)
1183		goto cleanup;
1184
1185	if ((ret = get_rdn(asn1, &tbscert->subject)) != KMF_OK)
1186		goto cleanup;
1187
1188	if ((ret = get_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
1189		goto cleanup;
1190
1191	/* Check for the optional fields */
1192	tbscert->extensions.numberOfExtensions = 0;
1193	tbscert->extensions.extensions = NULL;
1194
1195	while ((kmfber_scanf(asn1, "t", &tag)) != -1 &&
1196			(tag == 0xA1 || tag == 0xA2 || tag == 0xA3)) {
1197		char *optfield;
1198		ber_len_t len;
1199
1200		/* consume the tag and length */
1201		(void) kmfber_scanf(asn1, "T", &tag);
1202		switch (tag) {
1203			case 0xA1:
1204				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
1205					BER_BIT_STRING) {
1206					ret = KMF_ERR_BAD_CERT_FORMAT;
1207					goto cleanup;
1208				}
1209				tbscert->issuerUniqueIdentifier.Data =
1210					(uchar_t *)optfield;
1211				tbscert->issuerUniqueIdentifier.Length =
1212					len / 8;
1213				break;
1214			case 0xA2:
1215				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
1216					BER_BIT_STRING) {
1217					ret = KMF_ERR_BAD_CERT_FORMAT;
1218					goto cleanup;
1219				}
1220				tbscert->subjectUniqueIdentifier.Data =
1221					(uchar_t *)optfield;
1222				tbscert->subjectUniqueIdentifier.Length =
1223					len / 8;
1224				break;
1225			case 0xA3:
1226			ret = get_extensions(asn1, &tbscert->extensions);
1227			break;
1228		}
1229	}
1230
1231	*signed_cert_ptr_ptr = tbscert;
1232
1233cleanup:
1234	if (bvserno != NULL) {
1235		free(bvserno->bv_val);
1236		free(bvserno);
1237	}
1238	if (ret != KMF_OK) {
1239		if (tbscert) {
1240			free_tbscert(tbscert);
1241			free(tbscert);
1242		}
1243		*signed_cert_ptr_ptr = NULL;
1244	}
1245	return (ret);
1246}
1247
1248KMF_RETURN
1249DerDecodeTbsCertificate(const KMF_DATA *Value,
1250	KMF_X509_TBS_CERT **tbscert)
1251{
1252	KMF_RETURN ret = KMF_OK;
1253	BerElement *asn1 = NULL;
1254	BerValue 	rawcert;
1255	KMF_X509_TBS_CERT *newcert = NULL;
1256
1257	if (!tbscert || !Value || !Value->Data || !Value->Length)
1258		return (KMF_ERR_BAD_PARAMETER);
1259
1260	rawcert.bv_val = (char *)Value->Data;
1261	rawcert.bv_len = Value->Length;
1262
1263	if ((asn1 = kmfder_init(&rawcert)) == NULL)
1264		return (KMF_ERR_MEMORY);
1265
1266	ret = decode_tbscert_data(asn1, &newcert);
1267	if (ret != KMF_OK)
1268		goto cleanup;
1269
1270	*tbscert = newcert;
1271
1272cleanup:
1273	if (ret != KMF_OK) {
1274		if (newcert)
1275			free_tbscert(newcert);
1276		*tbscert = NULL;
1277	}
1278	kmfber_free(asn1, 1);
1279
1280	return (ret);
1281}
1282
1283/*
1284 * Name: DerDecodeSignedCertificate
1285 *
1286 * Description:
1287 * DER decodes the encoded X509 certificate
1288 *
1289 * Parameters:
1290 * Value (input): DER encoded object that shd be decoded
1291 *
1292 * signed_cert_ptr_ptr (output) : Decoded KMF_X509_CERTIFICATE object
1293 */
1294KMF_RETURN
1295DerDecodeSignedCertificate(const KMF_DATA *Value,
1296	KMF_X509_CERTIFICATE **signed_cert_ptr_ptr)
1297{
1298	KMF_RETURN ret = KMF_OK;
1299	BerElement *asn1 = NULL;
1300	BerValue 	rawcert;
1301	ber_tag_t	tag;
1302	ber_len_t	size;
1303	char		*end = NULL;
1304	char		*signature;
1305	KMF_X509_TBS_CERT	*tbscert = NULL;
1306	KMF_X509_CERTIFICATE *certptr = NULL;
1307
1308	if (!signed_cert_ptr_ptr || !Value || !Value->Data || !Value->Length)
1309		return (KMF_ERR_BAD_PARAMETER);
1310
1311	rawcert.bv_val = (char *)Value->Data;
1312	rawcert.bv_len = Value->Length;
1313
1314	if ((asn1 = kmfder_init(&rawcert)) == NULL)
1315		return (KMF_ERR_MEMORY);
1316
1317	if (kmfber_first_element(asn1, &size, &end) !=
1318		BER_CONSTRUCTED_SEQUENCE) {
1319		ret = KMF_ERR_BAD_CERT_FORMAT;
1320		goto cleanup;
1321	}
1322
1323	certptr = malloc(sizeof (KMF_X509_CERTIFICATE));
1324	if (certptr == NULL) {
1325		ret = KMF_ERR_MEMORY;
1326		goto cleanup;
1327	}
1328	(void) memset(certptr, 0, sizeof (KMF_X509_CERTIFICATE));
1329
1330	ret = decode_tbscert_data(asn1, &tbscert);
1331	if (ret != KMF_OK)
1332		goto cleanup;
1333
1334	certptr->certificate = *tbscert;
1335	free(tbscert);
1336	tbscert = NULL;
1337
1338	/*
1339	 * The signature data my not be present yet.
1340	 */
1341	if ((ret = get_algoid(asn1,
1342		&certptr->signature.algorithmIdentifier)) == KMF_OK) {
1343
1344		/* Check to see if the cert has a signature yet */
1345		if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
1346			/* Finally, get the encrypted signature BITSTRING */
1347			if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
1348				ret = KMF_ERR_BAD_CERT_FORMAT;
1349				goto cleanup;
1350			}
1351			if (tag != BER_BIT_STRING) {
1352				ret = KMF_ERR_BAD_CERT_FORMAT;
1353				goto cleanup;
1354			}
1355			if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
1356				ret = KMF_ERR_BAD_CERT_FORMAT;
1357				goto cleanup;
1358			}
1359			certptr->signature.encrypted.Data =
1360				(uchar_t *)signature;
1361			certptr->signature.encrypted.Length = size / 8;
1362		} else {
1363			certptr->signature.encrypted.Data = NULL;
1364			certptr->signature.encrypted.Length = 0;
1365		}
1366	} else {
1367		(void) memset(&certptr->signature, 0,
1368			sizeof (certptr->signature));
1369		ret = KMF_OK;
1370	}
1371
1372	*signed_cert_ptr_ptr = certptr;
1373cleanup:
1374	if (ret != KMF_OK) {
1375		if (certptr) {
1376			free_decoded_cert(certptr);
1377			free(certptr);
1378		}
1379
1380		*signed_cert_ptr_ptr = NULL;
1381	}
1382	if (asn1)
1383		kmfber_free(asn1, 1);
1384
1385	return (ret);
1386
1387}
1388
1389KMF_RETURN
1390DerDecodeExtension(KMF_DATA *Data, KMF_X509_EXTENSION **extn)
1391{
1392	KMF_RETURN ret = KMF_OK;
1393	BerElement *asn1 = NULL;
1394	BerValue bv;
1395
1396	bv.bv_val = (char *)Data->Data;
1397	bv.bv_len = Data->Length;
1398
1399	asn1 = kmfder_init(&bv);
1400	if (asn1 == NULL)
1401		return (KMF_ERR_MEMORY);
1402
1403	ret = get_one_extension(asn1, extn, NULL);
1404
1405cleanup:
1406	if (ret != KMF_OK) {
1407		if (*extn != NULL) {
1408			free(*extn);
1409		}
1410		*extn = NULL;
1411	}
1412
1413	kmfber_free(asn1, 1);
1414	return (ret);
1415}
1416
1417KMF_RETURN
1418DerDecodeName(KMF_DATA *encodedname, KMF_X509_NAME *name)
1419{
1420	KMF_RETURN ret = KMF_OK;
1421	BerElement *asn1 = NULL;
1422	BerValue  bv;
1423
1424	bv.bv_val = (char *)encodedname->Data;
1425	bv.bv_len = encodedname->Length;
1426
1427	asn1 = kmfder_init(&bv);
1428	if (asn1 == NULL)
1429		return (KMF_ERR_MEMORY);
1430
1431	(void) memset((void *)name, 0, sizeof (KMF_X509_NAME));
1432
1433	if ((ret = get_rdn(asn1, name)) != KMF_OK)
1434		goto cleanup;
1435
1436cleanup:
1437	if (asn1)
1438		kmfber_free(asn1, 1);
1439	return (ret);
1440}
1441
1442KMF_RETURN
1443DerEncodeName(KMF_X509_NAME *name, KMF_DATA *encodedname)
1444{
1445	KMF_RETURN ret = KMF_OK;
1446	BerElement *asn1 = NULL;
1447	BerValue  *bv = NULL;
1448
1449	asn1 = kmfder_alloc();
1450	if (asn1 == NULL)
1451		return (KMF_ERR_MEMORY);
1452
1453	if ((ret = encode_rdn(asn1, name)) != KMF_OK)
1454		goto cleanup;
1455
1456	if (kmfber_flatten(asn1, &bv) == -1) {
1457		ret = KMF_ERR_BAD_CERT_FORMAT;
1458		goto cleanup;
1459	}
1460
1461	encodedname->Data = (uchar_t *)bv->bv_val;
1462	encodedname->Length = bv->bv_len;
1463
1464cleanup:
1465	if (bv)
1466		free(bv);
1467
1468	if (asn1)
1469		kmfber_free(asn1, 1);
1470
1471	return (ret);
1472}
1473
1474static KMF_RETURN
1475encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert)
1476{
1477	KMF_RETURN ret = KMF_OK;
1478	uint32_t version;
1479
1480	/* version should be 4 bytes or less */
1481	if (tbscert->version.Length > sizeof (int))
1482		return (KMF_ERR_BAD_CERT_FORMAT);
1483
1484	(void) memcpy(&version, tbscert->version.Data,
1485		tbscert->version.Length);
1486
1487	/* Start the sequence and add the version */
1488	if (kmfber_printf(asn1, "{Tli", 0xA0, 3, version) == -1) {
1489		ret = KMF_ERR_BAD_CERT_FORMAT;
1490		goto cleanup;
1491	}
1492	/* Write the serial number */
1493	if (kmfber_printf(asn1, "I",
1494		(char *)tbscert->serialNumber.val,
1495		(size_t)tbscert->serialNumber.len) == -1) {
1496		ret = KMF_ERR_BAD_CERT_FORMAT;
1497		goto cleanup;
1498	}
1499
1500	if ((ret = encode_algoid(asn1, &tbscert->signature)) != KMF_OK)
1501		goto cleanup;
1502
1503	/* Encode the Issuer RDN */
1504	if ((ret = encode_rdn(asn1, &tbscert->issuer)) != KMF_OK)
1505		goto cleanup;
1506
1507	/* Encode the Validity fields */
1508	if ((ret = encode_validity(asn1, &tbscert->validity)) != KMF_OK)
1509		goto cleanup;
1510
1511	/* Encode the Subject RDN */
1512	if ((ret = encode_rdn(asn1, &tbscert->subject)) != KMF_OK)
1513		goto cleanup;
1514
1515	/* Encode the Subject Public Key Info */
1516	if ((ret = encode_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
1517		goto cleanup;
1518
1519	/* Optional field:  issuer Unique ID */
1520	if (tbscert->issuerUniqueIdentifier.Length > 0) {
1521		if ((ret = encode_uniqueid(asn1, 0xA1,
1522			&tbscert->issuerUniqueIdentifier)) != KMF_OK)
1523			goto cleanup;
1524	}
1525
1526	/* Optional field:  Subject Unique ID */
1527	if (tbscert->subjectUniqueIdentifier.Length > 0) {
1528		if ((ret = encode_uniqueid(asn1, 0xA2,
1529			&tbscert->subjectUniqueIdentifier)) != KMF_OK)
1530			goto cleanup;
1531	}
1532
1533	/* Optional field: Certificate Extensions */
1534	if (tbscert->extensions.numberOfExtensions > 0) {
1535		if ((ret = encode_extensions(asn1,
1536			&tbscert->extensions)) != KMF_OK)
1537			goto cleanup;
1538	}
1539
1540	/* Close out the TBSCert sequence */
1541	if (kmfber_printf(asn1, "}") == -1) {
1542		ret = KMF_ERR_BAD_CERT_FORMAT;
1543		goto cleanup;
1544	}
1545
1546cleanup:
1547	/*
1548	 * Memory cleanup is done in the caller or in the individual
1549	 * encoding routines.
1550	 */
1551
1552	return (ret);
1553}
1554
1555KMF_RETURN
1556DerEncodeTbsCertificate(KMF_X509_TBS_CERT *tbs_cert_ptr,
1557	KMF_DATA *enc_tbs_cert_ptr)
1558{
1559	KMF_RETURN ret;
1560	BerElement *asn1 = NULL;
1561	BerValue  *tbsdata = NULL;
1562
1563	asn1 = kmfder_alloc();
1564	if (asn1 == NULL)
1565		return (KMF_ERR_MEMORY);
1566
1567	enc_tbs_cert_ptr->Data = NULL;
1568	enc_tbs_cert_ptr->Length = 0;
1569
1570	ret = encode_tbs_cert(asn1, tbs_cert_ptr);
1571	if (ret != KMF_OK)
1572		goto cleanup;
1573
1574	if (kmfber_flatten(asn1, &tbsdata) == -1) {
1575		ret = KMF_ERR_MEMORY;
1576		goto cleanup;
1577	}
1578
1579	enc_tbs_cert_ptr->Data = (uchar_t *)tbsdata->bv_val;
1580	enc_tbs_cert_ptr->Length = tbsdata->bv_len;
1581
1582cleanup:
1583	if (ret != KMF_OK)
1584		free_data(enc_tbs_cert_ptr);
1585
1586	if (asn1 != NULL)
1587		kmfber_free(asn1, 1);
1588
1589	if (tbsdata)
1590		free(tbsdata);
1591
1592	return (ret);
1593}
1594
1595KMF_RETURN
1596DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr,
1597	KMF_DATA *encodedcert)
1598{
1599	KMF_RETURN ret = KMF_OK;
1600	KMF_X509_TBS_CERT *tbscert = NULL;
1601	KMF_X509_SIGNATURE		*signature = NULL;
1602	BerElement	*asn1 = NULL;
1603	BerValue 	*tbsdata = NULL;
1604
1605	if (signed_cert_ptr == NULL || encodedcert == NULL)
1606		return (KMF_ERR_BAD_PARAMETER);
1607
1608	encodedcert->Data = NULL;
1609	encodedcert->Length = 0;
1610
1611	tbscert = &signed_cert_ptr->certificate;
1612	signature = &signed_cert_ptr->signature;
1613
1614	asn1 = kmfder_alloc();
1615	if (asn1 == NULL)
1616		return (KMF_ERR_MEMORY);
1617
1618	/* Start outer X509 Certificate SEQUENCE */
1619	if (kmfber_printf(asn1, "{") == -1) {
1620		ret = KMF_ERR_BAD_CERT_FORMAT;
1621		goto cleanup;
1622	}
1623
1624	if ((ret = encode_tbs_cert(asn1, tbscert)) != KMF_OK) {
1625		ret = KMF_ERR_BAD_CERT_FORMAT;
1626		goto cleanup;
1627	}
1628
1629	/* Add the Algorithm & Signature Sequence */
1630	if ((ret = encode_algoid(asn1,
1631		&signature->algorithmIdentifier)) != KMF_OK)
1632		goto cleanup;
1633
1634	if (signature->encrypted.Length > 0) {
1635		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
1636			signature->encrypted.Length * 8) == -1) {
1637			ret = KMF_ERR_BAD_CERT_FORMAT;
1638			goto cleanup;
1639		}
1640	}
1641
1642	if (kmfber_printf(asn1, "}") == -1) {
1643		ret = KMF_ERR_BAD_CERT_FORMAT;
1644		goto cleanup;
1645	}
1646
1647	if (kmfber_flatten(asn1, &tbsdata) == -1) {
1648		ret = KMF_ERR_MEMORY;
1649		goto cleanup;
1650	}
1651
1652	encodedcert->Data = (uchar_t *)tbsdata->bv_val;
1653	encodedcert->Length = tbsdata->bv_len;
1654
1655cleanup:
1656	if (ret != KMF_OK)
1657		free_data(encodedcert);
1658
1659	if (tbsdata)
1660		free(tbsdata);
1661
1662	if (asn1)
1663		kmfber_free(asn1, 1);
1664
1665	return (ret);
1666}
1667
1668KMF_RETURN
1669ExtractX509CertParts(KMF_DATA *x509cert, KMF_DATA *tbscert,
1670		KMF_DATA *signature)
1671{
1672	KMF_RETURN ret = KMF_OK;
1673	BerElement *der = NULL;
1674	BerValue x509;
1675	ber_tag_t tag;
1676	ber_len_t size;
1677
1678	if (tbscert == NULL || x509cert == NULL)
1679		return (KMF_ERR_BAD_PARAMETER);
1680
1681	x509.bv_val = (char *)x509cert->Data;
1682	x509.bv_len = x509cert->Length;
1683
1684	der = kmfder_init(&x509);
1685	if (der == NULL)
1686		return (KMF_ERR_MEMORY);
1687
1688	/* Skip over the overall Sequence tag to get at the TBS Cert data */
1689	if (kmfber_scanf(der, "Tl", &tag, &size) == -1) {
1690		ret = KMF_ERR_BAD_CERT_FORMAT;
1691		goto cleanup;
1692	}
1693	if (tag != BER_CONSTRUCTED_SEQUENCE) {
1694		ret = KMF_ERR_BAD_CERT_FORMAT;
1695		goto cleanup;
1696	}
1697
1698	/*
1699	 * Since we are extracting a copy of the ENCODED bytes, we
1700	 * must make sure to also include the bytes for the tag and
1701	 * the length fields for the CONSTRUCTED SEQUENCE (TBSCert).
1702	 */
1703	size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
1704
1705	tbscert->Data = malloc(size);
1706	if (tbscert->Data == NULL) {
1707		ret = KMF_ERR_MEMORY;
1708		goto cleanup;
1709	}
1710	tbscert->Length = size;
1711
1712	/* The der data ptr is now set to the start of the TBS cert sequence */
1713	size = kmfber_read(der, (char *)tbscert->Data, tbscert->Length);
1714	if (size != tbscert->Length) {
1715		ret = KMF_ERR_BAD_CERT_FORMAT;
1716		goto cleanup;
1717	}
1718
1719	if (signature != NULL) {
1720		KMF_X509_ALGORITHM_IDENTIFIER algoid;
1721		if ((ret = get_algoid(der, &algoid)) != KMF_OK)
1722			goto cleanup;
1723		free_algoid(&algoid);
1724
1725		if (kmfber_scanf(der, "tl", &tag, &size) != BER_BIT_STRING) {
1726			ret = KMF_ERR_BAD_CERT_FORMAT;
1727			goto cleanup;
1728		}
1729		/* Now get the signature data */
1730		if (kmfber_scanf(der, "B", (char **)&signature->Data,
1731			(ber_len_t *)&signature->Length) == -1) {
1732			ret = KMF_ERR_BAD_CERT_FORMAT;
1733			goto cleanup;
1734		}
1735		/* convert bitstring length to bytes */
1736		signature->Length = signature->Length / 8;
1737	}
1738
1739cleanup:
1740	if (der)
1741		kmfber_free(der, 1);
1742
1743	if (ret != KMF_OK)
1744		free_data(tbscert);
1745
1746	return (ret);
1747}
1748
1749/*
1750 * Name: GetKeyFromSpki
1751 *
1752 * Description:
1753 * This function parses the KMF_X509_SPKI into its
1754 * key and parameter components based on the key generation algorithm.
1755 * NOTE:  Currently, it only checks for the RSA and DSA algorithms.
1756 *	The RSA algorithm is equivalent to the default behavior.
1757 *	All other algorithms will default to the parameters = NULL and the
1758 *	key data equal to whatever is in the CSSM_KEY structure for the key
1759 *
1760 * Parameters:
1761 * AlgId (input) : Algorithm identifier
1762 * SpkiPtr (input): SPKI structure that contains the key
1763 * key_ptr(output): The output key
1764 *
1765 */
1766KMF_RETURN
1767GetKeyFromSpki(KMF_ALGORITHM_INDEX AlgId,
1768	KMF_X509_SPKI *SpkiPtr,
1769	KMF_DATA **key_ptr)
1770{
1771	KMF_RETURN ret = KMF_OK;
1772	BerElement *asn1;
1773	BerValue *encodedkey = NULL;
1774
1775	if (!key_ptr || !SpkiPtr) {
1776		return (KMF_ERR_BAD_PARAMETER);
1777	}
1778	*key_ptr = NULL;
1779
1780	switch (AlgId) {
1781		case KMF_ALGID_DSA:
1782			asn1 = kmfder_alloc();
1783			if (asn1 == NULL) {
1784				return (KMF_ERR_MEMORY);
1785			}
1786
1787			if ((ret = encode_spki(asn1, SpkiPtr)) != KMF_OK) {
1788				ret = KMF_ERR_MEMORY;
1789				goto cleanup;
1790			}
1791
1792			if (kmfber_flatten(asn1, &encodedkey) == -1) {
1793				ret = KMF_ERR_MEMORY;
1794				goto cleanup;
1795			}
1796
1797			*key_ptr = malloc(sizeof (KMF_DATA));
1798
1799			if (!*key_ptr) {
1800				ret = KMF_ERR_MEMORY;
1801				goto cleanup;
1802			}
1803
1804			(*key_ptr)->Length = encodedkey->bv_len;
1805			(*key_ptr)->Data = (uchar_t *)encodedkey->bv_val;
1806cleanup:
1807			kmfber_free(asn1, 1);
1808			if (encodedkey)
1809				free(encodedkey);
1810		break;
1811		default: /* RSA */
1812			*key_ptr = malloc(sizeof (KMF_DATA));
1813
1814			if (!*key_ptr) {
1815				return (KMF_ERR_MEMORY);
1816			}
1817			(*key_ptr)->Length = SpkiPtr->subjectPublicKey.Length;
1818			(*key_ptr)->Data = malloc((*key_ptr)->Length);
1819
1820			if (!(*key_ptr)->Data) {
1821				free(*key_ptr);
1822				*key_ptr = NULL;
1823				return (KMF_ERR_MEMORY);
1824			}
1825			(void) memcpy((*key_ptr)->Data,
1826				SpkiPtr->subjectPublicKey.Data,
1827				(*key_ptr)->Length);
1828			return (ret);
1829	}
1830	return (ret);
1831}
1832
1833static KMF_RETURN
1834decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
1835{
1836	KMF_RETURN ret = KMF_OK;
1837	BerValue oid;
1838
1839	if (kmfber_scanf(asn1, "{D", &oid) == -1) {
1840		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
1841	}
1842
1843	/* We only understand extension requests in a CSR */
1844	if (memcmp(oid.bv_val, extension_request_oid.Data,
1845		oid.bv_len) != 0) {
1846		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
1847	}
1848
1849	if (kmfber_scanf(asn1, "[") == -1) {
1850		return (KMF_ERR_ENCODING);
1851	}
1852	ret = get_extensions(asn1, extns);
1853
1854
1855	return (ret);
1856}
1857
1858static KMF_RETURN
1859decode_tbscsr_data(BerElement *asn1,
1860	KMF_TBS_CSR **signed_csr_ptr_ptr)
1861{
1862	KMF_RETURN ret = KMF_OK;
1863	KMF_TBS_CSR	*tbscsr = NULL;
1864	char *end = NULL;
1865	uint32_t version;
1866	ber_tag_t tag;
1867	ber_len_t size;
1868
1869	/* Now get the version number, it is not optional */
1870	if (kmfber_scanf(asn1, "{i", &version) == -1) {
1871		ret = KMF_ERR_BAD_CERT_FORMAT;
1872		goto cleanup;
1873	}
1874
1875	tbscsr = malloc(sizeof (KMF_TBS_CSR));
1876	if (!tbscsr) {
1877		ret = KMF_ERR_MEMORY;
1878		goto cleanup;
1879	}
1880
1881	(void) memset(tbscsr, 0, sizeof (KMF_TBS_CSR));
1882
1883	if ((ret = set_der_integer(&tbscsr->version, version)) != KMF_OK)
1884		goto cleanup;
1885
1886	if ((ret = get_rdn(asn1, &tbscsr->subject)) != KMF_OK)
1887		goto cleanup;
1888
1889	if ((ret = get_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
1890		goto cleanup;
1891
1892	/* Check for the optional fields (attributes) */
1893	if (kmfber_next_element(asn1, &size, end) == 0xA0) {
1894		if (kmfber_scanf(asn1, "Tl", &tag, &size) == -1) {
1895			ret = KMF_ERR_ENCODING;
1896			goto cleanup;
1897		}
1898
1899		ret = decode_csr_extensions(asn1, &tbscsr->extensions);
1900	}
1901	if (ret == KMF_OK)
1902		*signed_csr_ptr_ptr = tbscsr;
1903
1904cleanup:
1905	if (ret != KMF_OK) {
1906		if (tbscsr) {
1907			free_tbscsr(tbscsr);
1908			free(tbscsr);
1909		}
1910		*signed_csr_ptr_ptr = NULL;
1911	}
1912	return (ret);
1913}
1914
1915KMF_RETURN
1916DerDecodeTbsCsr(const KMF_DATA *Value,
1917	KMF_TBS_CSR **tbscsr)
1918{
1919	KMF_RETURN ret = KMF_OK;
1920	BerElement *asn1 = NULL;
1921	BerValue 	rawcsr;
1922	KMF_TBS_CSR *newcsr = NULL;
1923
1924	if (!tbscsr || !Value || !Value->Data || !Value->Length)
1925		return (KMF_ERR_BAD_PARAMETER);
1926
1927	rawcsr.bv_val = (char *)Value->Data;
1928	rawcsr.bv_len = Value->Length;
1929
1930	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
1931		return (KMF_ERR_MEMORY);
1932
1933	ret = decode_tbscsr_data(asn1, &newcsr);
1934	if (ret != KMF_OK)
1935		goto cleanup;
1936
1937	*tbscsr = newcsr;
1938
1939cleanup:
1940	if (ret != KMF_OK) {
1941		if (newcsr)
1942			free_tbscsr(newcsr);
1943		*tbscsr = NULL;
1944	}
1945	kmfber_free(asn1, 1);
1946
1947	return (ret);
1948}
1949
1950KMF_RETURN
1951DerDecodeSignedCsr(const KMF_DATA *Value,
1952	KMF_CSR_DATA **signed_csr_ptr_ptr)
1953{
1954	KMF_RETURN ret = KMF_OK;
1955	BerElement *asn1 = NULL;
1956	BerValue 	rawcsr;
1957	int			tag;
1958	ber_len_t	size;
1959	char		*end = NULL;
1960	char		*signature;
1961	KMF_TBS_CSR	*tbscsr = NULL;
1962	KMF_CSR_DATA *csrptr = NULL;
1963
1964	if (!signed_csr_ptr_ptr || !Value || !Value->Data || !Value->Length)
1965		return (KMF_ERR_BAD_PARAMETER);
1966
1967	rawcsr.bv_val = (char *)Value->Data;
1968	rawcsr.bv_len = Value->Length;
1969
1970	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
1971		return (KMF_ERR_MEMORY);
1972
1973	if (kmfber_first_element(asn1, &size, &end) !=
1974		BER_CONSTRUCTED_SEQUENCE) {
1975		ret = KMF_ERR_BAD_CERT_FORMAT;
1976		goto cleanup;
1977	}
1978
1979	csrptr = malloc(sizeof (KMF_CSR_DATA));
1980	if (csrptr == NULL) {
1981		ret = KMF_ERR_MEMORY;
1982		goto cleanup;
1983	}
1984	(void) memset(csrptr, 0, sizeof (KMF_CSR_DATA));
1985
1986	ret = decode_tbscsr_data(asn1, &tbscsr);
1987	if (ret != KMF_OK)
1988		goto cleanup;
1989
1990	csrptr->csr = *tbscsr;
1991	free(tbscsr);
1992	tbscsr = NULL;
1993
1994	if ((ret = get_algoid(asn1,
1995		&csrptr->signature.algorithmIdentifier)) != KMF_OK)
1996		goto cleanup;
1997
1998	/* Check to see if the cert has a signature yet */
1999	if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
2000		/* Finally, get the encrypted signature BITSTRING */
2001		if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
2002			ret = KMF_ERR_BAD_CERT_FORMAT;
2003			goto cleanup;
2004		}
2005		if (tag != BER_BIT_STRING) {
2006			ret = KMF_ERR_BAD_CERT_FORMAT;
2007			goto cleanup;
2008		}
2009		if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
2010			ret = KMF_ERR_BAD_CERT_FORMAT;
2011			goto cleanup;
2012		}
2013		csrptr->signature.encrypted.Data = (uchar_t *)signature;
2014		csrptr->signature.encrypted.Length = size / 8;
2015	} else {
2016		csrptr->signature.encrypted.Data = NULL;
2017		csrptr->signature.encrypted.Length = 0;
2018	}
2019
2020	*signed_csr_ptr_ptr = csrptr;
2021cleanup:
2022	if (ret != KMF_OK) {
2023		free_tbscsr(&csrptr->csr);
2024		free_algoid(&csrptr->signature.algorithmIdentifier);
2025		if (csrptr->signature.encrypted.Data)
2026			free(csrptr->signature.encrypted.Data);
2027
2028		if (csrptr)
2029			free(csrptr);
2030
2031		*signed_csr_ptr_ptr = NULL;
2032	}
2033	if (asn1)
2034		kmfber_free(asn1, 1);
2035
2036	return (ret);
2037
2038}
2039
2040static KMF_RETURN
2041encode_csr_extensions(BerElement *asn1, KMF_TBS_CSR *tbscsr)
2042{
2043	KMF_RETURN ret = KMF_OK;
2044	int attlen = 0;
2045	BerElement *extnasn1 = NULL;
2046	BerValue *extnvalue = NULL;
2047
2048	/* Optional field: CSR attributes and extensions */
2049	if (tbscsr->extensions.numberOfExtensions > 0) {
2050		if (kmfber_printf(asn1, "T", 0xA0) == -1) {
2051			ret = KMF_ERR_ENCODING;
2052			goto cleanup;
2053		}
2054	} else {
2055		/* No extensions or attributes to encode */
2056		return (KMF_OK);
2057	}
2058
2059	/*
2060	 * attributes [0] Attributes
2061	 * Attributes := SET OF Attribute
2062	 * Attribute  := SEQUENCE {
2063	 *   { ATTRIBUTE ID
2064	 *	values SET SIZE(1..MAX) of ATTRIBUTE
2065	 *   }
2066	 *
2067	 * Ex: { ExtensionRequest OID [ { {extn1 } , {extn2 } } ] }
2068	 */
2069
2070	/*
2071	 * Encode any extensions and add to the attributes section.
2072	 */
2073	if (tbscsr->extensions.numberOfExtensions > 0) {
2074		extnasn1 = kmfder_alloc();
2075		if (extnasn1 == NULL) {
2076			ret = KMF_ERR_MEMORY;
2077			goto cleanup;
2078		}
2079
2080		if (kmfber_printf(extnasn1, "{D[{",
2081			&extension_request_oid) == -1) {
2082			ret = KMF_ERR_ENCODING;
2083			goto cleanup_1;
2084		}
2085
2086		if ((ret = encode_extension_list(extnasn1,
2087			&tbscsr->extensions)) != KMF_OK) {
2088			goto cleanup_1;
2089		}
2090
2091		if (kmfber_printf(extnasn1, "}]}") == -1) {
2092			ret = KMF_ERR_ENCODING;
2093			goto cleanup_1;
2094		}
2095
2096		if (kmfber_flatten(extnasn1, &extnvalue) == -1) {
2097			ret = KMF_ERR_MEMORY;
2098			goto cleanup_1;
2099		}
2100cleanup_1:
2101		kmfber_free(extnasn1, 1);
2102
2103		if (ret == KMF_OK)
2104			/* Add 2 bytes to cover the tag and the length */
2105			attlen = extnvalue->bv_len;
2106	}
2107	if (ret != KMF_OK)
2108		goto cleanup;
2109
2110	if (kmfber_printf(asn1, "l", attlen) == -1) {
2111		ret = KMF_ERR_ENCODING;
2112		goto cleanup;
2113	}
2114
2115	/* Write the actual encoded extensions */
2116	if (extnvalue != NULL && extnvalue->bv_val != NULL) {
2117		if (kmfber_write(asn1, extnvalue->bv_val,
2118			extnvalue->bv_len, 0) == -1) {
2119			ret = KMF_ERR_ENCODING;
2120			goto cleanup;
2121		}
2122	}
2123
2124cleanup:
2125	/*
2126	 * Memory cleanup is done in the caller or in the individual
2127	 * encoding routines.
2128	 */
2129	if (extnvalue) {
2130		if (extnvalue->bv_val)
2131			free(extnvalue->bv_val);
2132		free(extnvalue);
2133	}
2134
2135	return (ret);
2136}
2137
2138static KMF_RETURN
2139encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr)
2140{
2141	KMF_RETURN ret = KMF_OK;
2142	uint32_t version;
2143
2144	/* Start the version */
2145	(void) memcpy(&version, tbscsr->version.Data,
2146		tbscsr->version.Length);
2147
2148	if (kmfber_printf(asn1, "{i", &version) == -1) {
2149		ret = KMF_ERR_BAD_CERT_FORMAT;
2150		goto cleanup;
2151	}
2152
2153	/* Encode the Subject RDN */
2154	if ((ret = encode_rdn(asn1, &tbscsr->subject)) != KMF_OK)
2155		goto cleanup;
2156
2157	/* Encode the Subject Public Key Info */
2158	if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
2159		goto cleanup;
2160
2161
2162	if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK)
2163		goto cleanup;
2164
2165	/* Close out the TBSCert sequence */
2166	if (kmfber_printf(asn1, "}") == -1) {
2167		ret = KMF_ERR_BAD_CERT_FORMAT;
2168		goto cleanup;
2169	}
2170
2171cleanup:
2172	return (ret);
2173}
2174
2175KMF_RETURN
2176DerEncodeDSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_DSA_KEY *dsa)
2177{
2178	KMF_RETURN rv = KMF_OK;
2179	BerElement *asn1 = NULL;
2180	BerValue  *dsadata = NULL;
2181
2182	asn1 = kmfder_alloc();
2183	if (asn1 == NULL)
2184		return (KMF_ERR_MEMORY);
2185
2186	if (kmfber_printf(asn1, "I",
2187		dsa->value.val, dsa->value.len) == -1) {
2188		rv = KMF_ERR_MEMORY;
2189		goto cleanup;
2190	}
2191
2192	if (kmfber_flatten(asn1, &dsadata) == -1) {
2193		rv = KMF_ERR_MEMORY;
2194		goto cleanup;
2195	}
2196
2197	encodedkey->Data = (uchar_t *)dsadata->bv_val;
2198	encodedkey->Length = dsadata->bv_len;
2199
2200	free(dsadata);
2201cleanup:
2202	kmfber_free(asn1, 1);
2203	return (rv);
2204}
2205
2206KMF_RETURN
2207DerEncodeRSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_RSA_KEY *rsa)
2208{
2209	KMF_RETURN rv = KMF_OK;
2210	BerElement *asn1 = NULL;
2211	uchar_t ver = 0;
2212	BerValue  *rsadata = NULL;
2213
2214	asn1 = kmfder_alloc();
2215	if (asn1 == NULL)
2216		return (KMF_ERR_MEMORY);
2217
2218	if (kmfber_printf(asn1, "{IIIIIIIII}",
2219		&ver, 1,
2220		rsa->mod.val, rsa->mod.len,
2221		rsa->pubexp.val, rsa->pubexp.len,
2222		rsa->priexp.val, rsa->priexp.len,
2223		rsa->prime1.val, rsa->prime1.len,
2224		rsa->prime2.val, rsa->prime2.len,
2225		rsa->exp1.val, rsa->exp1.len,
2226		rsa->exp2.val, rsa->exp2.len,
2227		rsa->coef.val, rsa->coef.len) == -1)
2228		goto cleanup;
2229
2230	if (kmfber_flatten(asn1, &rsadata) == -1) {
2231		rv = KMF_ERR_MEMORY;
2232		goto cleanup;
2233	}
2234
2235	encodedkey->Data = (uchar_t *)rsadata->bv_val;
2236	encodedkey->Length = rsadata->bv_len;
2237
2238	free(rsadata);
2239cleanup:
2240	kmfber_free(asn1, 1);
2241	return (rv);
2242}
2243
2244
2245KMF_RETURN
2246DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr,
2247	KMF_DATA *enc_tbs_csr_ptr)
2248{
2249	KMF_RETURN ret;
2250	BerValue  *tbsdata = NULL;
2251	BerElement *asn1 = NULL;
2252
2253	asn1 = kmfder_alloc();
2254
2255	enc_tbs_csr_ptr->Data = NULL;
2256	enc_tbs_csr_ptr->Length = 0;
2257
2258	if (asn1 == NULL)
2259		return (KMF_ERR_MEMORY);
2260
2261	ret = encode_tbs_csr(asn1, tbs_csr_ptr);
2262	if (ret != KMF_OK)
2263		goto cleanup;
2264
2265	if (kmfber_flatten(asn1, &tbsdata) == -1) {
2266		ret = KMF_ERR_MEMORY;
2267		goto cleanup;
2268	}
2269
2270	enc_tbs_csr_ptr->Data = (uchar_t *)tbsdata->bv_val;
2271	enc_tbs_csr_ptr->Length = tbsdata->bv_len;
2272
2273cleanup:
2274	if (ret != KMF_OK)
2275		free_data(enc_tbs_csr_ptr);
2276
2277	if (asn1 != NULL)
2278		kmfber_free(asn1, 1);
2279
2280	if (tbsdata)
2281		free(tbsdata);
2282
2283	return (ret);
2284}
2285
2286KMF_RETURN
2287DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr,
2288	KMF_DATA *encodedcsr)
2289{
2290	KMF_RETURN ret = KMF_OK;
2291	KMF_TBS_CSR *tbscsr = NULL;
2292	KMF_X509_SIGNATURE		*signature = NULL;
2293	BerElement	*asn1 = NULL;
2294	BerValue 	*tbsdata = NULL;
2295
2296	if (signed_csr_ptr == NULL)
2297		return (KMF_ERR_BAD_PARAMETER);
2298
2299	tbscsr = &signed_csr_ptr->csr;
2300	signature = &signed_csr_ptr->signature;
2301
2302	asn1 = kmfder_alloc();
2303	if (asn1 == NULL)
2304		return (KMF_ERR_MEMORY);
2305
2306	/* Start outer CSR SEQUENCE */
2307	if (kmfber_printf(asn1, "{") == -1) {
2308		ret = KMF_ERR_BAD_CERT_FORMAT;
2309		goto cleanup;
2310	}
2311
2312	ret = encode_tbs_csr(asn1, tbscsr);
2313
2314	/* Add the Algorithm & Signature Sequence */
2315	if ((ret = encode_algoid(asn1,
2316		&signature->algorithmIdentifier)) != KMF_OK)
2317		goto cleanup;
2318
2319	if (signature->encrypted.Length > 0) {
2320		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
2321			signature->encrypted.Length * 8) == -1) {
2322			ret = KMF_ERR_BAD_CERT_FORMAT;
2323			goto cleanup;
2324		}
2325	}
2326
2327	if (kmfber_printf(asn1, "}") == -1) {
2328		ret = KMF_ERR_BAD_CERT_FORMAT;
2329		goto cleanup;
2330	}
2331
2332	if (kmfber_flatten(asn1, &tbsdata) == -1) {
2333		ret = KMF_ERR_MEMORY;
2334		goto cleanup;
2335	}
2336
2337	encodedcsr->Data = (uchar_t *)tbsdata->bv_val;
2338	encodedcsr->Length = tbsdata->bv_len;
2339
2340cleanup:
2341	if (ret != KMF_OK) {
2342		free_data(encodedcsr);
2343	}
2344
2345	if (tbsdata)
2346		free(tbsdata);
2347
2348	if (asn1)
2349		kmfber_free(asn1, 1);
2350	return (ret);
2351}
2352
2353KMF_RETURN
2354ExtractSPKIData(
2355	const KMF_X509_SPKI *pKey,
2356	KMF_ALGORITHM_INDEX AlgorithmId,
2357	KMF_DATA *pKeyParts,
2358	uint32_t *uNumKeyParts)
2359{
2360	KMF_RETURN ret = KMF_OK;
2361	BerElement *asn1 = NULL;
2362	BerValue 	*P, *Q, *G, *Mod, *Exp, *PubKey;
2363	BerValue	PubKeyParams, PubKeyData;
2364
2365	if (pKeyParts == NULL || uNumKeyParts == NULL || pKey == NULL)
2366		return (KMF_ERR_BAD_PARAMETER);
2367
2368	switch (AlgorithmId) {
2369	    case KMF_ALGID_DSA:
2370	    case KMF_ALGID_SHA1WithDSA:
2371		/* First, get the parameters from the algorithm definition */
2372		PubKeyParams.bv_val = (char *)pKey->algorithm.parameters.Data;
2373		PubKeyParams.bv_len = pKey->algorithm.parameters.Length;
2374		if ((asn1 = kmfder_init(&PubKeyParams)) == NULL)
2375			return (KMF_ERR_MEMORY);
2376
2377		if (kmfber_scanf(asn1, "{III}", &P, &Q, &G) == -1) {
2378			kmfber_free(asn1, 1);
2379			return (KMF_ERR_BAD_KEY_FORMAT);
2380		}
2381		pKeyParts[KMF_DSA_PRIME].Data = (uchar_t *)P->bv_val;
2382		pKeyParts[KMF_DSA_PRIME].Length = P->bv_len;
2383		pKeyParts[KMF_DSA_SUB_PRIME].Data = (uchar_t *)Q->bv_val;
2384		pKeyParts[KMF_DSA_SUB_PRIME].Length = Q->bv_len;
2385		pKeyParts[KMF_DSA_BASE].Data = (uchar_t *)G->bv_val;
2386		pKeyParts[KMF_DSA_BASE].Length = G->bv_len;
2387
2388		free(P);
2389		free(Q);
2390		free(G);
2391		kmfber_free(asn1, 1);
2392
2393		/* Get the PubKey data */
2394		PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
2395		PubKeyData.bv_len = pKey->subjectPublicKey.Length;
2396		if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
2397			ret = KMF_ERR_MEMORY;
2398			goto cleanup;
2399		}
2400		PubKey = NULL;
2401		if (kmfber_scanf(asn1, "I", &PubKey) == -1) {
2402			ret = KMF_ERR_BAD_KEY_FORMAT;
2403			goto cleanup;
2404		}
2405		pKeyParts[KMF_DSA_PUBLIC_VALUE].Data =
2406			(uchar_t *)PubKey->bv_val;
2407		pKeyParts[KMF_DSA_PUBLIC_VALUE].Length = PubKey->bv_len;
2408
2409		free(PubKey);
2410
2411		*uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS;
2412		break;
2413
2414	    case KMF_ALGID_RSA:
2415	    case KMF_ALGID_MD2WithRSA:
2416	    case KMF_ALGID_MD5WithRSA:
2417	    case KMF_ALGID_SHA1WithRSA:
2418		PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
2419		PubKeyData.bv_len = pKey->subjectPublicKey.Length;
2420		if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
2421			ret = KMF_ERR_MEMORY;
2422			goto cleanup;
2423		}
2424		if (kmfber_scanf(asn1, "{II}", &Mod, &Exp) == -1) {
2425			ret = KMF_ERR_BAD_KEY_FORMAT;
2426			goto cleanup;
2427		}
2428		pKeyParts[KMF_RSA_MODULUS].Data = (uchar_t *)Mod->bv_val;
2429		pKeyParts[KMF_RSA_MODULUS].Length = Mod->bv_len;
2430		pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Data =
2431			(uchar_t *)Exp->bv_val;
2432		pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Length = Exp->bv_len;
2433		*uNumKeyParts = KMF_NUMBER_RSA_PUBLIC_KEY_PARTS;
2434
2435		free(Mod);
2436		free(Exp);
2437		break;
2438	    default:
2439		return (KMF_ERR_BAD_PARAMETER);
2440	}
2441cleanup:
2442	if (ret != KMF_OK) {
2443		int i;
2444		for (i = 0; i < *uNumKeyParts; i++)
2445			free_data(&pKeyParts[i]);
2446	}
2447	if (asn1 != NULL) {
2448		kmfber_free(asn1, 1);
2449	}
2450
2451	return (ret);
2452}
2453