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