clasn1.c revision 11973:480f5412d630
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
20static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
21const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
22	OID_ExtensionRequest};
23
24static KMF_RETURN
25encode_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
55static void
56free_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
66static void
67free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
68{
69	free_data(&algoid->algorithm);
70	free_data(&algoid->parameters);
71}
72
73static void
74free_decoded_spki(KMF_X509_SPKI *spki)
75{
76	if (spki != NULL) {
77		free_algoid(&spki->algorithm);
78		free_data(&spki->subjectPublicKey);
79	}
80}
81
82static void
83free_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
105static void
106free_validity(KMF_X509_VALIDITY *validity)
107{
108	free_data(&validity->notBefore.time);
109	free_data(&validity->notAfter.time);
110}
111
112static void
113free_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
124static void
125free_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
141static void
142free_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
156static void
157free_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
166static void
167free_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
189static void
190free_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
201static KMF_RETURN
202get_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
246static KMF_RETURN
247get_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	}
315cleanup:
316	if (rv != KMF_OK) {
317		free_algoid(algoid);
318	}
319	kmfber_free(oidasn1, 1);
320
321	return (rv);
322}
323
324static KMF_RETURN
325CopyData(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
337static KMF_RETURN
338encode_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
359KMF_RETURN
360DerEncodeSPKI(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
389static KMF_RETURN
390get_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	}
409cleanup:
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
422KMF_RETURN
423DerEncodeDSASignature(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 */
467KMF_RETURN
468DerEncodeECDSASignature(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 */
479static KMF_RETURN
480convert_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
511KMF_RETURN
512DerDecodeDSASignature(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);
581cleanup:
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
595KMF_RETURN
596DerDecodeECDSASignature(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
602KMF_RETURN
603DerDecodeSPKI(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
623cleanup:
624	if (ret != KMF_OK) {
625		free_decoded_spki(spki);
626	}
627	kmfber_free(asn1, 1);
628
629	return (ret);
630}
631
632KMF_RETURN
633CopySPKI(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;
662cleanup:
663	if (ret != KMF_OK) {
664		if (newspki)
665			free_decoded_spki(newspki);
666	}
667	return (ret);
668}
669
670static KMF_RETURN
671encode_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
687static KMF_RETURN
688get_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
718KMF_RETURN
719AddRDN(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
743cleanup:
744	/* No cleanup needed here */
745	return (ret);
746}
747
748static KMF_RETURN
749encode_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
790cleanup:
791	/* No cleanup needed here */
792
793	return (ret);
794}
795
796
797KMF_RETURN
798CopyRDN(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
861cleanup:
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
880static KMF_RETURN
881get_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
974cleanup:
975	if (ret != KMF_OK) {
976		free_rdn_data(name);
977	}
978	return (ret);
979}
980
981static KMF_RETURN
982set_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
997static KMF_RETURN
998set_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
1014static KMF_RETURN
1015encode_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
1029static KMF_RETURN
1030encode_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	}
1060cleanup:
1061	return (ret);
1062}
1063
1064static KMF_RETURN
1065encode_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
1102cleanup:
1103	kmfber_free(extn, 1);
1104	if (extnvalue != NULL)
1105		kmfber_bvfree(extnvalue);
1106
1107	return (ret);
1108}
1109
1110static KMF_RETURN
1111get_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;
1210cleanup:
1211	if (ret != KMF_OK) {
1212		if (ex != NULL)
1213			free_one_extension(ex);
1214	}
1215
1216	return (ret);
1217}
1218
1219static KMF_RETURN
1220get_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
1260cleanup:
1261	if (ret != KMF_OK)
1262		free_extensions(extns);
1263
1264	return (ret);
1265}
1266
1267KMF_RETURN
1268decode_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
1372cleanup:
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
1387KMF_RETURN
1388DerDecodeTbsCertificate(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
1411cleanup:
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 */
1433KMF_RETURN
1434DerDecodeSignedCertificate(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;
1512cleanup:
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
1528KMF_RETURN
1529DerDecodeExtension(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
1544cleanup:
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
1556KMF_RETURN
1557DerDecodeName(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
1575cleanup:
1576	if (asn1)
1577		kmfber_free(asn1, 1);
1578	return (ret);
1579}
1580
1581KMF_RETURN
1582DerEncodeName(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
1603cleanup:
1604	if (bv)
1605		free(bv);
1606
1607	if (asn1)
1608		kmfber_free(asn1, 1);
1609
1610	return (ret);
1611}
1612
1613static KMF_RETURN
1614encode_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
1686cleanup:
1687	/*
1688	 * Memory cleanup is done in the caller or in the individual
1689	 * encoding routines.
1690	 */
1691
1692	return (ret);
1693}
1694
1695KMF_RETURN
1696DerEncodeTbsCertificate(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
1722cleanup:
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
1735KMF_RETURN
1736DerEncodeSignedCertificate(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
1795cleanup:
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
1808KMF_RETURN
1809ExtractX509CertParts(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
1879cleanup:
1880	if (der)
1881		kmfber_free(der, 1);
1882
1883	if (ret != KMF_OK)
1884		free_data(tbscert);
1885
1886	return (ret);
1887}
1888
1889static KMF_RETURN
1890decode_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
1914static KMF_RETURN
1915decode_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
1960cleanup:
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
1971KMF_RETURN
1972DerDecodeTbsCsr(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
1995cleanup:
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
2006KMF_RETURN
2007DerDecodeSignedCsr(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;
2077cleanup:
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
2096static KMF_RETURN
2097encode_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		}
2156cleanup_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
2180cleanup:
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
2194static KMF_RETURN
2195encode_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
2226cleanup:
2227	return (ret);
2228}
2229
2230KMF_RETURN
2231DerEncodeDSAPrivateKey(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);
2256cleanup:
2257	kmfber_free(asn1, 1);
2258	return (rv);
2259}
2260
2261KMF_RETURN
2262DerEncodeRSAPrivateKey(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);
2294cleanup:
2295	kmfber_free(asn1, 1);
2296	return (rv);
2297}
2298
2299KMF_RETURN
2300DerEncodeECPrivateKey(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
2344cleanup:
2345	kmfber_free(asn1, 1);
2346	return (rv);
2347}
2348
2349
2350KMF_RETURN
2351DerEncodeTbsCsr(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
2378cleanup:
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
2391KMF_RETURN
2392DerEncodeSignedCsr(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
2445cleanup:
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
2458static KMF_RETURN
2459ber_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
2476KMF_RETURN
2477ExtractSPKIData(
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	}
2579cleanup:
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