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