xref: /titanic_50/usr/src/lib/libkmf/ber_der/common/clasn1.c (revision b86efd96f8acd85ddaa930a2f0c1d664237e4aaf)
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 
44 static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
45 const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
46 	OID_ExtensionRequest};
47 
48 static KMF_RETURN
49 encode_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 
75 static void
76 free_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 
86 static void
87 free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
88 {
89 	free_data(&algoid->algorithm);
90 	free_data(&algoid->parameters);
91 }
92 
93 static void
94 free_decoded_spki(KMF_X509_SPKI *spki)
95 {
96 	if (spki != NULL) {
97 		free_algoid(&spki->algorithm);
98 		free_data(&spki->subjectPublicKey);
99 	}
100 }
101 
102 static void
103 free_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 
125 static void
126 free_validity(KMF_X509_VALIDITY *validity)
127 {
128 	free_data(&validity->notBefore.time);
129 	free_data(&validity->notAfter.time);
130 }
131 
132 static void
133 free_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 
144 static void
145 free_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 
161 static void
162 free_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 
176 static void
177 free_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 
186 static void
187 free_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 
209 static void
210 free_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 
221 static KMF_RETURN
222 get_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 	}
271 cleanup:
272 	if (ret != KMF_OK) {
273 		free_algoid(algoid);
274 	}
275 
276 	return (ret);
277 }
278 
279 static KMF_RETURN
280 CopyData(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 
292 static KMF_RETURN
293 encode_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 
310 KMF_RETURN
311 DerEncodeSPKI(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 
340 static KMF_RETURN
341 get_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 	}
360 cleanup:
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 
372 KMF_RETURN
373 DerEncodeDSASignature(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 
415 KMF_RETURN
416 DerDecodeDSASignature(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 
448 cleanup:
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 
462 KMF_RETURN
463 DerDecodeSPKI(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 
483 cleanup:
484 	if (ret != KMF_OK) {
485 		free_decoded_spki(spki);
486 	}
487 	kmfber_free(asn1, 1);
488 
489 	return (ret);
490 }
491 
492 KMF_RETURN
493 CopySPKI(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;
522 cleanup:
523 	if (ret != KMF_OK) {
524 		if (newspki)
525 			free_decoded_spki(newspki);
526 	}
527 	return (ret);
528 }
529 
530 static KMF_RETURN
531 encode_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 
547 static KMF_RETURN
548 get_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 
578 KMF_RETURN
579 AddRDN(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 
603 cleanup:
604 	/* No cleanup needed here */
605 	return (ret);
606 }
607 
608 static KMF_RETURN
609 encode_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 
650 cleanup:
651 	/* No cleanup needed here */
652 
653 	return (ret);
654 }
655 
656 
657 KMF_RETURN
658 CopyRDN(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 
721 cleanup:
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 
740 static KMF_RETURN
741 get_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 
835 cleanup:
836 	if (ret != KMF_OK) {
837 		free_rdn_data(name);
838 	}
839 	return (ret);
840 }
841 
842 static KMF_RETURN
843 set_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 
858 static KMF_RETURN
859 set_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 
875 static KMF_RETURN
876 encode_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 
890 static KMF_RETURN
891 encode_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 	}
921 cleanup:
922 	return (ret);
923 }
924 
925 static KMF_RETURN
926 encode_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 
963 cleanup:
964 	kmfber_free(extn, 1);
965 	if (extnvalue != NULL)
966 		kmfber_bvfree(extnvalue);
967 
968 	return (ret);
969 }
970 
971 static KMF_RETURN
972 get_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;
1071 cleanup:
1072 	if (ret != KMF_OK) {
1073 		if (ex != NULL)
1074 			free_one_extension(ex);
1075 	}
1076 
1077 	return (ret);
1078 }
1079 
1080 static KMF_RETURN
1081 get_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 
1121 cleanup:
1122 	if (ret != KMF_OK)
1123 		free_extensions(extns);
1124 
1125 	return (ret);
1126 }
1127 
1128 KMF_RETURN
1129 decode_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 
1233 cleanup:
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 
1248 KMF_RETURN
1249 DerDecodeTbsCertificate(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 
1272 cleanup:
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  */
1294 KMF_RETURN
1295 DerDecodeSignedCertificate(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;
1373 cleanup:
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 
1389 KMF_RETURN
1390 DerDecodeExtension(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 
1405 cleanup:
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 
1417 KMF_RETURN
1418 DerDecodeName(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 
1436 cleanup:
1437 	if (asn1)
1438 		kmfber_free(asn1, 1);
1439 	return (ret);
1440 }
1441 
1442 KMF_RETURN
1443 DerEncodeName(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 
1464 cleanup:
1465 	if (bv)
1466 		free(bv);
1467 
1468 	if (asn1)
1469 		kmfber_free(asn1, 1);
1470 
1471 	return (ret);
1472 }
1473 
1474 static KMF_RETURN
1475 encode_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 
1546 cleanup:
1547 	/*
1548 	 * Memory cleanup is done in the caller or in the individual
1549 	 * encoding routines.
1550 	 */
1551 
1552 	return (ret);
1553 }
1554 
1555 KMF_RETURN
1556 DerEncodeTbsCertificate(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 
1582 cleanup:
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 
1595 KMF_RETURN
1596 DerEncodeSignedCertificate(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 
1655 cleanup:
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 
1668 KMF_RETURN
1669 ExtractX509CertParts(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 
1739 cleanup:
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  */
1766 KMF_RETURN
1767 GetKeyFromSpki(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;
1806 cleanup:
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 
1833 static KMF_RETURN
1834 decode_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 
1858 static KMF_RETURN
1859 decode_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 
1904 cleanup:
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 
1915 KMF_RETURN
1916 DerDecodeTbsCsr(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 
1939 cleanup:
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 
1950 KMF_RETURN
1951 DerDecodeSignedCsr(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;
2021 cleanup:
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 
2040 static KMF_RETURN
2041 encode_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 		}
2100 cleanup_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 
2124 cleanup:
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 
2138 static KMF_RETURN
2139 encode_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 
2171 cleanup:
2172 	return (ret);
2173 }
2174 
2175 KMF_RETURN
2176 DerEncodeDSAPrivateKey(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);
2201 cleanup:
2202 	kmfber_free(asn1, 1);
2203 	return (rv);
2204 }
2205 
2206 KMF_RETURN
2207 DerEncodeRSAPrivateKey(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);
2239 cleanup:
2240 	kmfber_free(asn1, 1);
2241 	return (rv);
2242 }
2243 
2244 
2245 KMF_RETURN
2246 DerEncodeTbsCsr(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 
2273 cleanup:
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 
2286 KMF_RETURN
2287 DerEncodeSignedCsr(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 
2340 cleanup:
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 
2353 KMF_RETURN
2354 ExtractSPKIData(
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 	}
2441 cleanup:
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