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