xref: /onnv-gate/usr/src/lib/libkmf/ber_der/common/clasn1.c (revision 11973:480f5412d630)
13089Swyllys /*
2*11973Swyllys.ingersoll@sun.com  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
33089Swyllys  * Use is subject to license terms.
43433Shaimay  */
53433Shaimay /*
63089Swyllys  * Copyright (c) 1995-1999 Intel Corporation. All rights reserved.
73089Swyllys  */
83089Swyllys 
93089Swyllys #include <strings.h>
103089Swyllys #include <kmftypes.h>
113089Swyllys #include <ber_der.h>
12*11973Swyllys.ingersoll@sun.com #include <kmfber_int.h>
133089Swyllys #include <kmfapi.h>
143089Swyllys #include <kmfapiP.h>
153089Swyllys 
163089Swyllys #include <stdio.h>
173089Swyllys 
183089Swyllys #define	DSA_RAW_SIG_LEN	40
193089Swyllys 
203089Swyllys static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
213089Swyllys const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
223089Swyllys 	OID_ExtensionRequest};
233089Swyllys 
243089Swyllys static KMF_RETURN
encode_algoid(BerElement * asn1,KMF_X509_ALGORITHM_IDENTIFIER * algoid,boolean_t encode_params)25*11973Swyllys.ingersoll@sun.com encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid,
26*11973Swyllys.ingersoll@sun.com     boolean_t encode_params)
273089Swyllys {
283089Swyllys 	KMF_RETURN ret = KMF_OK;
293089Swyllys 
303089Swyllys 	if (kmfber_printf(asn1, "{D", &algoid->algorithm) == -1) {
313089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
323089Swyllys 	}
33*11973Swyllys.ingersoll@sun.com 	if (!encode_params) {
34*11973Swyllys.ingersoll@sun.com 		if (kmfber_printf(asn1, "}") == -1)
35*11973Swyllys.ingersoll@sun.com 			return (KMF_ERR_BAD_CERT_FORMAT);
36*11973Swyllys.ingersoll@sun.com 	} else if (algoid->parameters.Data == NULL ||
375221Swyllys 	    algoid->parameters.Length == 0) {
383089Swyllys 		if (kmfber_printf(asn1, "n}") == -1)
393089Swyllys 			return (KMF_ERR_BAD_CERT_FORMAT);
403089Swyllys 	} else {
413089Swyllys 		/*
423089Swyllys 		 * The algorithm data can be anything, so we just write it
433089Swyllys 		 * straight into the buffer.  It is already DER encoded.
443089Swyllys 		 */
453089Swyllys 		(void) kmfber_write(asn1, (char *)algoid->parameters.Data,
465221Swyllys 		    algoid->parameters.Length, 0);
473089Swyllys 		if (kmfber_printf(asn1, "}") == -1) {
483089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
493089Swyllys 		}
503089Swyllys 	}
513089Swyllys 
523089Swyllys 	return (ret);
533089Swyllys }
543089Swyllys 
553089Swyllys static void
free_data(KMF_DATA * data)563089Swyllys free_data(KMF_DATA *data)
573089Swyllys {
583089Swyllys 	if (data == NULL || data->Data == NULL)
593089Swyllys 		return;
603089Swyllys 
613089Swyllys 	free(data->Data);
623089Swyllys 	data->Data = NULL;
633089Swyllys 	data->Length = 0;
643089Swyllys }
653089Swyllys 
663089Swyllys static void
free_algoid(KMF_X509_ALGORITHM_IDENTIFIER * algoid)673089Swyllys free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
683089Swyllys {
693089Swyllys 	free_data(&algoid->algorithm);
703089Swyllys 	free_data(&algoid->parameters);
713089Swyllys }
723089Swyllys 
733089Swyllys static void
free_decoded_spki(KMF_X509_SPKI * spki)743089Swyllys free_decoded_spki(KMF_X509_SPKI *spki)
753089Swyllys {
763089Swyllys 	if (spki != NULL) {
773089Swyllys 		free_algoid(&spki->algorithm);
783089Swyllys 		free_data(&spki->subjectPublicKey);
793089Swyllys 	}
803089Swyllys }
813089Swyllys 
823089Swyllys static void
free_rdn_data(KMF_X509_NAME * name)833089Swyllys free_rdn_data(KMF_X509_NAME *name)
843089Swyllys {
853089Swyllys 	KMF_X509_RDN 		*newrdn = NULL;
863089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
873089Swyllys 	int i, j;
883089Swyllys 
893089Swyllys 	if (name && name->numberOfRDNs) {
903089Swyllys 		for (i = 0; i < name->numberOfRDNs; i++) {
913089Swyllys 			newrdn = &name->RelativeDistinguishedName[i];
923089Swyllys 			for (j = 0; j < newrdn->numberOfPairs; j++) {
933089Swyllys 				av = &newrdn->AttributeTypeAndValue[j];
943089Swyllys 				free_data(&av->type);
953089Swyllys 				free_data(&av->value);
963089Swyllys 			}
973089Swyllys 			free(newrdn->AttributeTypeAndValue);
983089Swyllys 		}
993089Swyllys 		free(name->RelativeDistinguishedName);
1003089Swyllys 		name->numberOfRDNs = 0;
1013089Swyllys 		name->RelativeDistinguishedName = NULL;
1023089Swyllys 	}
1033089Swyllys }
1043089Swyllys 
1053089Swyllys static void
free_validity(KMF_X509_VALIDITY * validity)1063089Swyllys free_validity(KMF_X509_VALIDITY *validity)
1073089Swyllys {
1083089Swyllys 	free_data(&validity->notBefore.time);
1093089Swyllys 	free_data(&validity->notAfter.time);
1103089Swyllys }
1113089Swyllys 
1123089Swyllys static void
free_one_extension(KMF_X509_EXTENSION * exptr)1133089Swyllys free_one_extension(KMF_X509_EXTENSION *exptr)
1143089Swyllys {
1153089Swyllys 	free_data(&exptr->extnId);
1163089Swyllys 	free_data(&exptr->BERvalue);
1173089Swyllys 
1183089Swyllys 	if (exptr->value.tagAndValue) {
1193089Swyllys 		free_data(&exptr->value.tagAndValue->value);
1203089Swyllys 		free(exptr->value.tagAndValue);
1213089Swyllys 	}
1223089Swyllys }
1233089Swyllys 
1243089Swyllys static void
free_extensions(KMF_X509_EXTENSIONS * extns)1253089Swyllys free_extensions(KMF_X509_EXTENSIONS *extns)
1263089Swyllys {
1273089Swyllys 	int i;
1283089Swyllys 	KMF_X509_EXTENSION *exptr;
1293089Swyllys 
1303089Swyllys 	if (extns && extns->numberOfExtensions > 0) {
1313089Swyllys 		for (i = 0; i < extns->numberOfExtensions; i++) {
1323089Swyllys 			exptr = &extns->extensions[i];
1333089Swyllys 			free_one_extension(exptr);
1343089Swyllys 		}
1353089Swyllys 		free(extns->extensions);
1363089Swyllys 		extns->numberOfExtensions = 0;
1373089Swyllys 		extns->extensions = NULL;
1383089Swyllys 	}
1393089Swyllys }
1403089Swyllys 
1413089Swyllys static void
free_tbscsr(KMF_TBS_CSR * tbscsr)1423089Swyllys free_tbscsr(KMF_TBS_CSR *tbscsr)
1433089Swyllys {
1443089Swyllys 	if (tbscsr) {
1453089Swyllys 		free_data(&tbscsr->version);
1463089Swyllys 
1473089Swyllys 		free_rdn_data(&tbscsr->subject);
1483089Swyllys 
1493089Swyllys 		free_decoded_spki(&tbscsr->subjectPublicKeyInfo);
1503089Swyllys 
1513089Swyllys 		free_extensions(&tbscsr->extensions);
1523089Swyllys 	}
1533089Swyllys }
1543089Swyllys 
1553089Swyllys 
1563089Swyllys static void
free_bigint(KMF_BIGINT * bn)1573089Swyllys free_bigint(KMF_BIGINT *bn)
1583089Swyllys {
1593089Swyllys 	if (bn != NULL && bn->val != NULL) {
1603089Swyllys 		free(bn->val);
1613089Swyllys 		bn->val = NULL;
1623089Swyllys 		bn->len = 0;
1633089Swyllys 	}
1643089Swyllys }
1653089Swyllys 
1663089Swyllys static void
free_tbscert(KMF_X509_TBS_CERT * tbscert)1673089Swyllys free_tbscert(KMF_X509_TBS_CERT *tbscert)
1683089Swyllys {
1693089Swyllys 	if (tbscert) {
1703089Swyllys 		free_data(&tbscert->version);
1713089Swyllys 		free_bigint(&tbscert->serialNumber);
1723089Swyllys 		free_algoid(&tbscert->signature);
1733089Swyllys 
1743089Swyllys 		free_rdn_data(&tbscert->issuer);
1753089Swyllys 		free_rdn_data(&tbscert->subject);
1763089Swyllys 
1773089Swyllys 		free_validity(&tbscert->validity);
1783089Swyllys 
1793089Swyllys 		free_data(&tbscert->issuerUniqueIdentifier);
1803089Swyllys 		free_data(&tbscert->subjectUniqueIdentifier);
1813089Swyllys 		free_decoded_spki(&tbscert->subjectPublicKeyInfo);
1823089Swyllys 		free_extensions(&tbscert->extensions);
1833089Swyllys 
1843089Swyllys 		free_data(&tbscert->issuerUniqueIdentifier);
1853089Swyllys 		free_data(&tbscert->subjectUniqueIdentifier);
1863089Swyllys 	}
1873089Swyllys }
1883089Swyllys 
1893089Swyllys static void
free_decoded_cert(KMF_X509_CERTIFICATE * certptr)1903089Swyllys free_decoded_cert(KMF_X509_CERTIFICATE *certptr)
1913089Swyllys {
1923089Swyllys 	if (!certptr)
1933089Swyllys 		return;
1943089Swyllys 
1953089Swyllys 	free_tbscert(&certptr->certificate);
1963089Swyllys 
1973089Swyllys 	free_algoid(&certptr->signature.algorithmIdentifier);
1983089Swyllys 	free_data(&certptr->signature.encrypted);
1993089Swyllys }
2003089Swyllys 
2013089Swyllys static KMF_RETURN
get_sequence_data(BerElement * asn1,BerValue * seqdata)202*11973Swyllys.ingersoll@sun.com get_sequence_data(BerElement *asn1, BerValue *seqdata)
203*11973Swyllys.ingersoll@sun.com {
204*11973Swyllys.ingersoll@sun.com 	ber_tag_t tag;
205*11973Swyllys.ingersoll@sun.com 	ber_len_t size;
206*11973Swyllys.ingersoll@sun.com 
207*11973Swyllys.ingersoll@sun.com 	tag = kmfber_next_element(asn1, &size, NULL);
208*11973Swyllys.ingersoll@sun.com 	if (tag == BER_OBJECT_IDENTIFIER) {
209*11973Swyllys.ingersoll@sun.com 		/* The whole block is the OID. */
210*11973Swyllys.ingersoll@sun.com 		size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
211*11973Swyllys.ingersoll@sun.com 		seqdata->bv_val = malloc(size);
212*11973Swyllys.ingersoll@sun.com 		if (seqdata->bv_val == NULL) {
213*11973Swyllys.ingersoll@sun.com 			return (KMF_ERR_MEMORY);
214*11973Swyllys.ingersoll@sun.com 		}
215*11973Swyllys.ingersoll@sun.com 		/* read the raw data into the Algoritm params area. */
216*11973Swyllys.ingersoll@sun.com 		if (kmfber_read(asn1, seqdata->bv_val, size) ==
217*11973Swyllys.ingersoll@sun.com 		    -1) {
218*11973Swyllys.ingersoll@sun.com 			return (KMF_ERR_BAD_CERT_FORMAT);
219*11973Swyllys.ingersoll@sun.com 		}
220*11973Swyllys.ingersoll@sun.com 		seqdata->bv_len = size;
221*11973Swyllys.ingersoll@sun.com 		return (KMF_OK);
222*11973Swyllys.ingersoll@sun.com 	} else if (tag != BER_CONSTRUCTED_SEQUENCE)
223*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_BAD_CERT_FORMAT);
224*11973Swyllys.ingersoll@sun.com 
225*11973Swyllys.ingersoll@sun.com 	if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
226*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_BAD_CERT_FORMAT);
227*11973Swyllys.ingersoll@sun.com 	}
228*11973Swyllys.ingersoll@sun.com 	/*
229*11973Swyllys.ingersoll@sun.com 	 * We need to read the tag and the length bytes too,
230*11973Swyllys.ingersoll@sun.com 	 * so adjust the size.
231*11973Swyllys.ingersoll@sun.com 	 */
232*11973Swyllys.ingersoll@sun.com 	size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
233*11973Swyllys.ingersoll@sun.com 	seqdata->bv_val = malloc(size);
234*11973Swyllys.ingersoll@sun.com 	if (seqdata->bv_val == NULL) {
235*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
236*11973Swyllys.ingersoll@sun.com 	}
237*11973Swyllys.ingersoll@sun.com 	/* read the raw data into the Algoritm params area. */
238*11973Swyllys.ingersoll@sun.com 	if (kmfber_read(asn1, seqdata->bv_val, size) ==
239*11973Swyllys.ingersoll@sun.com 	    -1) {
240*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_BAD_CERT_FORMAT);
241*11973Swyllys.ingersoll@sun.com 	}
242*11973Swyllys.ingersoll@sun.com 	seqdata->bv_len = size;
243*11973Swyllys.ingersoll@sun.com 	return (KMF_OK);
244*11973Swyllys.ingersoll@sun.com }
245*11973Swyllys.ingersoll@sun.com 
246*11973Swyllys.ingersoll@sun.com static KMF_RETURN
get_algoid(BerElement * asn1,KMF_X509_ALGORITHM_IDENTIFIER * algoid)2473089Swyllys get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
2483089Swyllys {
249*11973Swyllys.ingersoll@sun.com 	KMF_RETURN rv = KMF_OK;
250*11973Swyllys.ingersoll@sun.com 	ber_tag_t tag;
2513089Swyllys 	ber_len_t size;
252*11973Swyllys.ingersoll@sun.com 	BerValue algoid_data;
253*11973Swyllys.ingersoll@sun.com 	BerValue AlgOID;
254*11973Swyllys.ingersoll@sun.com 	BerElement *oidasn1 = NULL;
255*11973Swyllys.ingersoll@sun.com 
256*11973Swyllys.ingersoll@sun.com 	/* Read the entire OID seq into it's own data block */
257*11973Swyllys.ingersoll@sun.com 	rv = get_sequence_data(asn1, &algoid_data);
258*11973Swyllys.ingersoll@sun.com 	if (rv != KMF_OK)
259*11973Swyllys.ingersoll@sun.com 		return (rv);
260*11973Swyllys.ingersoll@sun.com 
261*11973Swyllys.ingersoll@sun.com 	/* Now parse just this block so we don't overrun */
262*11973Swyllys.ingersoll@sun.com 	if ((oidasn1 = kmfder_init(&algoid_data)) == NULL)
263*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
264*11973Swyllys.ingersoll@sun.com 	tag = kmfber_next_element(oidasn1, &size, NULL);
265*11973Swyllys.ingersoll@sun.com 	if (tag == BER_OBJECT_IDENTIFIER) {
266*11973Swyllys.ingersoll@sun.com 		algoid->algorithm.Data = (uchar_t *)algoid_data.bv_val;
267*11973Swyllys.ingersoll@sun.com 		algoid->algorithm.Length = algoid_data.bv_len;
268*11973Swyllys.ingersoll@sun.com 		algoid->parameters.Data = NULL;
269*11973Swyllys.ingersoll@sun.com 		algoid->parameters.Length = 0;
270*11973Swyllys.ingersoll@sun.com 		kmfber_free(oidasn1, 1);
271*11973Swyllys.ingersoll@sun.com 		return (KMF_OK);
272*11973Swyllys.ingersoll@sun.com 	}
273*11973Swyllys.ingersoll@sun.com 
274*11973Swyllys.ingersoll@sun.com 	if ((tag = kmfber_scanf(oidasn1, "{D", &AlgOID)) == -1) {
275*11973Swyllys.ingersoll@sun.com 		kmfber_free(oidasn1, 1);
2763089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
2773089Swyllys 	}
2783089Swyllys 	algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val;
2793089Swyllys 	algoid->algorithm.Length = AlgOID.bv_len;
2803089Swyllys 
281*11973Swyllys.ingersoll@sun.com 	tag = kmfber_next_element(oidasn1, &size, NULL);
282*11973Swyllys.ingersoll@sun.com 	if (tag == BER_NULL) {
283*11973Swyllys.ingersoll@sun.com 		(void) kmfber_scanf(oidasn1, "n}");
284*11973Swyllys.ingersoll@sun.com 		algoid->parameters.Data = NULL;
285*11973Swyllys.ingersoll@sun.com 		algoid->parameters.Length = 0;
286*11973Swyllys.ingersoll@sun.com 	} else if (tag == KMFBER_END_OF_SEQORSET || tag == KMFBER_DEFAULT) {
287*11973Swyllys.ingersoll@sun.com 		/* close sequence, we are done with Algoid */
2883089Swyllys 		algoid->parameters.Data = NULL;
2893089Swyllys 		algoid->parameters.Length = 0;
2903089Swyllys 	} else {
291*11973Swyllys.ingersoll@sun.com 		/* The rest of the data is the algorithm parameters */
292*11973Swyllys.ingersoll@sun.com 		if ((kmfber_scanf(oidasn1, "tl", &tag, &size)) == -1) {
293*11973Swyllys.ingersoll@sun.com 			rv = KMF_ERR_BAD_CERT_FORMAT;
2943089Swyllys 			goto cleanup;
2953089Swyllys 		}
2963089Swyllys 
2973089Swyllys 		/*
2983089Swyllys 		 * We need to read the tag and the length bytes too,
2993089Swyllys 		 * so adjust the size.
3003089Swyllys 		 */
3013089Swyllys 		size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
3023089Swyllys 		algoid->parameters.Data = malloc(size);
3033089Swyllys 		if (algoid->parameters.Data == NULL) {
304*11973Swyllys.ingersoll@sun.com 			rv = KMF_ERR_MEMORY;
3053089Swyllys 			goto cleanup;
3063089Swyllys 		}
3073089Swyllys 		/* read the raw data into the Algoritm params area. */
308*11973Swyllys.ingersoll@sun.com 		if (kmfber_read(oidasn1, (char *)algoid->parameters.Data,
3095221Swyllys 		    size) == -1) {
310*11973Swyllys.ingersoll@sun.com 			rv = KMF_ERR_BAD_CERT_FORMAT;
3113089Swyllys 			goto cleanup;
3123089Swyllys 		}
3133089Swyllys 		algoid->parameters.Length = size;
3143089Swyllys 	}
3153089Swyllys cleanup:
316*11973Swyllys.ingersoll@sun.com 	if (rv != KMF_OK) {
3173089Swyllys 		free_algoid(algoid);
3183089Swyllys 	}
319*11973Swyllys.ingersoll@sun.com 	kmfber_free(oidasn1, 1);
320*11973Swyllys.ingersoll@sun.com 
321*11973Swyllys.ingersoll@sun.com 	return (rv);
3223089Swyllys }
3233089Swyllys 
3243089Swyllys static KMF_RETURN
CopyData(KMF_DATA * src,KMF_DATA * dst)3253089Swyllys CopyData(KMF_DATA *src, KMF_DATA *dst)
3263089Swyllys {
3273089Swyllys 	if (src && dst && src->Data != NULL && src->Length > 0) {
3283089Swyllys 		dst->Length = src->Length;
3293991Shaimay 		dst->Data = malloc(dst->Length);
3303089Swyllys 		if (dst->Data == NULL)
3313089Swyllys 			return (KMF_ERR_MEMORY);
3323089Swyllys 		(void) memcpy(dst->Data, src->Data, src->Length);
3333089Swyllys 	}
3343089Swyllys 	return (KMF_OK);
3353089Swyllys }
3363089Swyllys 
3373089Swyllys static KMF_RETURN
encode_spki(BerElement * asn1,KMF_X509_SPKI * spki)3383089Swyllys encode_spki(BerElement *asn1, KMF_X509_SPKI *spki)
3393089Swyllys {
3403089Swyllys 	KMF_RETURN ret = KMF_OK;
3413089Swyllys 
3423089Swyllys 	if (kmfber_printf(asn1, "{") == -1)
3433089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
3443089Swyllys 
345*11973Swyllys.ingersoll@sun.com 	/*
346*11973Swyllys.ingersoll@sun.com 	 * The SPKI is the only place where algorithm parameters
347*11973Swyllys.ingersoll@sun.com 	 * should be encoded.
348*11973Swyllys.ingersoll@sun.com 	 */
349*11973Swyllys.ingersoll@sun.com 	if ((ret = encode_algoid(asn1, &spki->algorithm, TRUE)) != KMF_OK)
3503089Swyllys 		return (ret);
3513089Swyllys 
3523089Swyllys 	if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data,
3535221Swyllys 	    spki->subjectPublicKey.Length * 8) == -1)
3543089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
3553089Swyllys 
3563089Swyllys 	return (ret);
3573089Swyllys }
3583089Swyllys 
3593089Swyllys KMF_RETURN
DerEncodeSPKI(KMF_X509_SPKI * spki,KMF_DATA * EncodedSPKI)3603089Swyllys DerEncodeSPKI(KMF_X509_SPKI *spki, KMF_DATA *EncodedSPKI)
3613089Swyllys {
3623089Swyllys 	KMF_RETURN ret = KMF_OK;
3633089Swyllys 	BerElement *asn1;
3643089Swyllys 	BerValue *result;
3653089Swyllys 
3663089Swyllys 	if (spki == NULL || EncodedSPKI == NULL)
3673089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3683089Swyllys 
3693089Swyllys 	if ((asn1 = kmfder_alloc()) == NULL)
3703089Swyllys 		return (KMF_ERR_MEMORY);
3713089Swyllys 
3723089Swyllys 	if ((ret = encode_spki(asn1, spki)) != KMF_OK) {
3733089Swyllys 		return (ret);
3743089Swyllys 	}
3753089Swyllys 
3763089Swyllys 	if (kmfber_flatten(asn1, &result) == -1) {
3773089Swyllys 		kmfber_free(asn1, 1);
3783089Swyllys 		return (KMF_ERR_ENCODING);
3793089Swyllys 	}
3803089Swyllys 
3813089Swyllys 	EncodedSPKI->Data = (uchar_t *)result->bv_val;
3823089Swyllys 	EncodedSPKI->Length = result->bv_len;
3833089Swyllys 
3843089Swyllys 	free(result);
3853089Swyllys 	kmfber_free(asn1, 1);
3863089Swyllys 	return (KMF_OK);
3873089Swyllys }
3883089Swyllys 
3893089Swyllys static KMF_RETURN
get_spki(BerElement * asn1,KMF_X509_SPKI * spki)3903089Swyllys get_spki(BerElement *asn1, KMF_X509_SPKI *spki)
3913089Swyllys {
3923089Swyllys 	KMF_RETURN ret = KMF_OK;
3933089Swyllys 	char *bitstr = NULL;
3943089Swyllys 	ber_len_t size;
3953089Swyllys 
3963089Swyllys 	if (kmfber_scanf(asn1, "{") == -1)
3973089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
3983089Swyllys 
3993089Swyllys 	if ((ret = get_algoid(asn1, &spki->algorithm)) != KMF_OK)
4003089Swyllys 		return (ret);
4013089Swyllys 
4023089Swyllys 	if (kmfber_scanf(asn1, "B}", &bitstr, &size) == BER_BIT_STRING) {
4033089Swyllys 		spki->subjectPublicKey.Data = (uchar_t *)bitstr;
4043089Swyllys 		spki->subjectPublicKey.Length = size / 8;
4053089Swyllys 	} else {
4063089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
4073089Swyllys 		goto cleanup;
4083089Swyllys 	}
4093089Swyllys cleanup:
4103089Swyllys 	if (ret != KMF_OK) {
4113089Swyllys 		if (bitstr != NULL)
4123089Swyllys 			free(bitstr);
4133089Swyllys 		spki->subjectPublicKey.Data = NULL;
4143089Swyllys 		spki->subjectPublicKey.Length = 0;
4153089Swyllys 
4163089Swyllys 		free_algoid(&spki->algorithm);
4173089Swyllys 	}
4183089Swyllys 	return (ret);
4193089Swyllys }
4203089Swyllys 
421*11973Swyllys.ingersoll@sun.com 
4223089Swyllys KMF_RETURN
DerEncodeDSASignature(KMF_DATA * rawdata,KMF_DATA * signature)4233089Swyllys DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
4243089Swyllys {
4253089Swyllys 	BerElement *asn1;
4263089Swyllys 	BerValue *buf;
4273089Swyllys 	int n;
4283089Swyllys 
4293089Swyllys 	if (rawdata == NULL || signature == NULL)
4303089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
4313089Swyllys 
432*11973Swyllys.ingersoll@sun.com 	if (rawdata->Data == NULL || rawdata->Length == 0)
4333089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
4343089Swyllys 
4353089Swyllys 	asn1 = kmfder_alloc();
4363089Swyllys 	if (asn1 == NULL)
4373089Swyllys 		return (KMF_ERR_MEMORY);
4383089Swyllys 
4393089Swyllys 	/*
440*11973Swyllys.ingersoll@sun.com 	 * The [EC]DSA signature is the concatenation of 2
4413089Swyllys 	 * bignum values.
4423089Swyllys 	 */
443*11973Swyllys.ingersoll@sun.com 	n = rawdata->Length/2;
4443089Swyllys 	if (kmfber_printf(asn1, "{II}",
4455221Swyllys 	    rawdata->Data, n, &rawdata->Data[n], n) == -1) {
4463089Swyllys 		kmfber_free(asn1, 1);
4473089Swyllys 		return (KMF_ERR_MEMORY);
4483089Swyllys 	}
4493089Swyllys 
4503089Swyllys 	if (kmfber_flatten(asn1, &buf) == -1) {
4513089Swyllys 		kmfber_free(asn1, 1);
4523089Swyllys 		return (KMF_ERR_ENCODING);
4533089Swyllys 	}
4543089Swyllys 
4553089Swyllys 	signature->Data = (uchar_t *)buf->bv_val;
4563089Swyllys 	signature->Length = buf->bv_len;
4573089Swyllys 
4583089Swyllys 	kmfber_free(asn1, 1);
4593089Swyllys 	free(buf);
4603089Swyllys 
4613089Swyllys 	return (KMF_OK);
4623089Swyllys }
4633089Swyllys 
464*11973Swyllys.ingersoll@sun.com /*
465*11973Swyllys.ingersoll@sun.com  * ECDSA and DSA encode signatures the same way.
466*11973Swyllys.ingersoll@sun.com  */
467*11973Swyllys.ingersoll@sun.com KMF_RETURN
DerEncodeECDSASignature(KMF_DATA * rawdata,KMF_DATA * signature)468*11973Swyllys.ingersoll@sun.com DerEncodeECDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
469*11973Swyllys.ingersoll@sun.com {
470*11973Swyllys.ingersoll@sun.com 	return (DerEncodeDSASignature(rawdata, signature));
471*11973Swyllys.ingersoll@sun.com }
472*11973Swyllys.ingersoll@sun.com 
473*11973Swyllys.ingersoll@sun.com /*
474*11973Swyllys.ingersoll@sun.com  * Convert a signed DSA sig to a fixed-length unsigned one.
475*11973Swyllys.ingersoll@sun.com  * This is necessary because DER encoding seeks to use the
476*11973Swyllys.ingersoll@sun.com  * minimal amount of bytes but we need a full 20 byte DSA
477*11973Swyllys.ingersoll@sun.com  * value with leading 0x00 bytes.
478*11973Swyllys.ingersoll@sun.com  */
479*11973Swyllys.ingersoll@sun.com static KMF_RETURN
convert_signed_to_fixed(BerValue * src,BerValue * dst)480*11973Swyllys.ingersoll@sun.com convert_signed_to_fixed(BerValue *src, BerValue *dst)
481*11973Swyllys.ingersoll@sun.com {
482*11973Swyllys.ingersoll@sun.com 	int cnt;
483*11973Swyllys.ingersoll@sun.com 	char *p;
484*11973Swyllys.ingersoll@sun.com 	if (dst->bv_len > src->bv_len) {
485*11973Swyllys.ingersoll@sun.com 		cnt = dst->bv_len - src->bv_len;
486*11973Swyllys.ingersoll@sun.com 		/* prepend with leading 0s */
487*11973Swyllys.ingersoll@sun.com 		(void) memset(dst->bv_val, 0x00, cnt);
488*11973Swyllys.ingersoll@sun.com 		(void) memcpy(dst->bv_val + cnt, src->bv_val,
489*11973Swyllys.ingersoll@sun.com 		    src->bv_len);
490*11973Swyllys.ingersoll@sun.com 		return (KMF_OK);
491*11973Swyllys.ingersoll@sun.com 	}
492*11973Swyllys.ingersoll@sun.com 	if (dst->bv_len == src->bv_len) {
493*11973Swyllys.ingersoll@sun.com 		(void) memcpy(dst->bv_val, src->bv_val,
494*11973Swyllys.ingersoll@sun.com 		    dst->bv_len);
495*11973Swyllys.ingersoll@sun.com 		return (KMF_OK);
496*11973Swyllys.ingersoll@sun.com 	}
497*11973Swyllys.ingersoll@sun.com 	/*
498*11973Swyllys.ingersoll@sun.com 	 * src is larger than dest, strip leading 0s.
499*11973Swyllys.ingersoll@sun.com 	 * This should not be necessary, but do it just in case.
500*11973Swyllys.ingersoll@sun.com 	 */
501*11973Swyllys.ingersoll@sun.com 	cnt = src->bv_len - dst->bv_len;
502*11973Swyllys.ingersoll@sun.com 	p = src->bv_val;
503*11973Swyllys.ingersoll@sun.com 	while (cnt-- > 0) {
504*11973Swyllys.ingersoll@sun.com 		if (*p++ != 0x00)
505*11973Swyllys.ingersoll@sun.com 			return (KMF_ERR_ENCODING);
506*11973Swyllys.ingersoll@sun.com 	}
507*11973Swyllys.ingersoll@sun.com 	(void) memcpy(dst->bv_val, p, dst->bv_len);
508*11973Swyllys.ingersoll@sun.com 	return (KMF_OK);
509*11973Swyllys.ingersoll@sun.com }
510*11973Swyllys.ingersoll@sun.com 
5113089Swyllys KMF_RETURN
DerDecodeDSASignature(KMF_DATA * encoded,KMF_DATA * signature)5123089Swyllys DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
5133089Swyllys {
5143089Swyllys 	KMF_RETURN ret = KMF_OK;
5153089Swyllys 	BerElement *asn1 = NULL;
5163089Swyllys 	BerValue buf, *R = NULL, *S = NULL;
517*11973Swyllys.ingersoll@sun.com 	BerValue fixedR, fixedS;
5183089Swyllys 
5193089Swyllys 	buf.bv_val = (char *)encoded->Data;
5203089Swyllys 	buf.bv_len = encoded->Length;
5213089Swyllys 
5223089Swyllys 	if (encoded == NULL || encoded->Data == NULL ||
5233089Swyllys 	    signature == NULL)
5243089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
5253089Swyllys 
5263089Swyllys 	signature->Data = NULL;
5273089Swyllys 	signature->Length = 0;
5283089Swyllys 
5293089Swyllys 	if ((asn1 = kmfder_init(&buf)) == NULL)
5303089Swyllys 		return (KMF_ERR_MEMORY);
5313089Swyllys 
5323089Swyllys 	if (kmfber_scanf(asn1, "{II}", &R, &S) == -1) {
5333089Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
5343089Swyllys 		goto cleanup;
5353089Swyllys 	}
5363089Swyllys 	signature->Length = R->bv_len + S->bv_len;
537*11973Swyllys.ingersoll@sun.com 	/*
538*11973Swyllys.ingersoll@sun.com 	 * If either of the values had a leading 0 lopped off
539*11973Swyllys.ingersoll@sun.com 	 * they will be 1 byte short and need to be adjusted below.
540*11973Swyllys.ingersoll@sun.com 	 * The stripping is correct as per ASN.1 rules.
541*11973Swyllys.ingersoll@sun.com 	 *
542*11973Swyllys.ingersoll@sun.com 	 * We don't know the exact length that the R and S values
543*11973Swyllys.ingersoll@sun.com 	 * must be, it depends on the signature algorithm and,
544*11973Swyllys.ingersoll@sun.com 	 * in the case of EC, the curve used. So instead of
545*11973Swyllys.ingersoll@sun.com 	 * checking for a specific length, we just check to see
546*11973Swyllys.ingersoll@sun.com 	 * if the value came out to be an odd number.  If so,
547*11973Swyllys.ingersoll@sun.com 	 * then we know it needs a leading 0x00 byte which
548*11973Swyllys.ingersoll@sun.com 	 * will be added below when we convert it to a fixed
549*11973Swyllys.ingersoll@sun.com 	 * length.
550*11973Swyllys.ingersoll@sun.com 	 */
551*11973Swyllys.ingersoll@sun.com 	if ((R->bv_len % 2) != 0)
552*11973Swyllys.ingersoll@sun.com 		signature->Length++;
553*11973Swyllys.ingersoll@sun.com 	if ((S->bv_len % 2) != 0)
554*11973Swyllys.ingersoll@sun.com 		signature->Length++;
555*11973Swyllys.ingersoll@sun.com 
5563089Swyllys 	signature->Data = malloc(signature->Length);
5573089Swyllys 	if (signature->Data == NULL)  {
5583089Swyllys 		ret = KMF_ERR_MEMORY;
5593089Swyllys 		goto cleanup;
5603089Swyllys 	}
561*11973Swyllys.ingersoll@sun.com 	fixedR.bv_val = (char *)signature->Data;
562*11973Swyllys.ingersoll@sun.com 	/* adjust length if it needs a leading 0x00 byte */
563*11973Swyllys.ingersoll@sun.com 	fixedR.bv_len = R->bv_len + (R->bv_len % 2);
564*11973Swyllys.ingersoll@sun.com 
565*11973Swyllys.ingersoll@sun.com 	fixedS.bv_val = (char *)(signature->Data + fixedR.bv_len);
566*11973Swyllys.ingersoll@sun.com 	/* adjust length if it needs a leading 0x00 byte */
567*11973Swyllys.ingersoll@sun.com 	fixedS.bv_len = S->bv_len + (S->bv_len % 2);
568*11973Swyllys.ingersoll@sun.com 
569*11973Swyllys.ingersoll@sun.com 	/*
570*11973Swyllys.ingersoll@sun.com 	 * This will add back any missing leading 0's
571*11973Swyllys.ingersoll@sun.com 	 * that were stripped off earlier when the signature
572*11973Swyllys.ingersoll@sun.com 	 * was parsed.  This ensures that the 2 parts of the
573*11973Swyllys.ingersoll@sun.com 	 * signature are the right length and have the proper
574*11973Swyllys.ingersoll@sun.com 	 * leading 0's prepended.
575*11973Swyllys.ingersoll@sun.com 	 */
576*11973Swyllys.ingersoll@sun.com 	ret = convert_signed_to_fixed(R, &fixedR);
577*11973Swyllys.ingersoll@sun.com 	if (ret)
578*11973Swyllys.ingersoll@sun.com 		goto cleanup;
579*11973Swyllys.ingersoll@sun.com 
580*11973Swyllys.ingersoll@sun.com 	ret = convert_signed_to_fixed(S, &fixedS);
5813089Swyllys cleanup:
5823089Swyllys 	if (R && R->bv_val)
5833089Swyllys 		free(R->bv_val);
5843089Swyllys 	if (S && S->bv_val)
5853089Swyllys 		free(S->bv_val);
5863089Swyllys 
5873089Swyllys 	if (S) free(S);
5883089Swyllys 	if (R) free(R);
5893089Swyllys 
5903089Swyllys 	if (asn1) kmfber_free(asn1, 1);
5913089Swyllys 
5923089Swyllys 	return (ret);
5933089Swyllys }
5943089Swyllys 
5953089Swyllys KMF_RETURN
DerDecodeECDSASignature(KMF_DATA * encoded,KMF_DATA * signature)596*11973Swyllys.ingersoll@sun.com DerDecodeECDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
597*11973Swyllys.ingersoll@sun.com {
598*11973Swyllys.ingersoll@sun.com 	/* ECDSA can be decoded using same code as standard DSA */
599*11973Swyllys.ingersoll@sun.com 	return (DerDecodeDSASignature(encoded, signature));
600*11973Swyllys.ingersoll@sun.com }
601*11973Swyllys.ingersoll@sun.com 
602*11973Swyllys.ingersoll@sun.com KMF_RETURN
DerDecodeSPKI(KMF_DATA * EncodedSPKI,KMF_X509_SPKI * spki)6033089Swyllys DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki)
6043089Swyllys {
6053089Swyllys 	KMF_RETURN ret = KMF_OK;
6063089Swyllys 	BerElement *asn1;
6073089Swyllys 	BerValue bv;
6083089Swyllys 
6093089Swyllys 	if (EncodedSPKI == NULL || EncodedSPKI->Data == NULL ||
6105221Swyllys 	    spki == NULL)
6113089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
6123089Swyllys 
6133089Swyllys 	(void) memset(spki, 0, sizeof (KMF_X509_SPKI));
6143089Swyllys 
6153089Swyllys 	bv.bv_val = (char *)EncodedSPKI->Data;
6163089Swyllys 	bv.bv_len = EncodedSPKI->Length;
6173089Swyllys 
6183089Swyllys 	if ((asn1 = kmfder_init(&bv)) == NULL)
6193089Swyllys 		return (KMF_ERR_MEMORY);
6203089Swyllys 
6213089Swyllys 	ret = get_spki(asn1, spki);
6223089Swyllys 
6233089Swyllys cleanup:
6243089Swyllys 	if (ret != KMF_OK) {
6253089Swyllys 		free_decoded_spki(spki);
6263089Swyllys 	}
6273089Swyllys 	kmfber_free(asn1, 1);
6283089Swyllys 
6293089Swyllys 	return (ret);
6303089Swyllys }
6313089Swyllys 
6323089Swyllys KMF_RETURN
CopySPKI(KMF_X509_SPKI * src,KMF_X509_SPKI ** dest)6333089Swyllys CopySPKI(KMF_X509_SPKI *src,
6343089Swyllys 		KMF_X509_SPKI **dest)
6353089Swyllys {
6363089Swyllys 	KMF_RETURN ret = KMF_OK;
6373089Swyllys 	KMF_X509_SPKI *newspki;
6383089Swyllys 
6393089Swyllys 	*dest = NULL;
6403089Swyllys 
6413089Swyllys 	newspki = malloc(sizeof (KMF_X509_SPKI));
6423089Swyllys 	if (newspki == NULL)
6433089Swyllys 		return (KMF_ERR_MEMORY);
6443089Swyllys 	(void) memset(newspki, 0, sizeof (KMF_X509_SPKI));
6453089Swyllys 
6463089Swyllys 	ret = CopyData(&src->algorithm.algorithm,
6475221Swyllys 	    &newspki->algorithm.algorithm);
6483089Swyllys 	if (ret != KMF_OK)
6493089Swyllys 		goto cleanup;
6503089Swyllys 
6513089Swyllys 	ret = CopyData(&src->algorithm.parameters,
6525221Swyllys 	    &newspki->algorithm.parameters);
6533089Swyllys 	if (ret != KMF_OK)
6543089Swyllys 		goto cleanup;
6553089Swyllys 
6563089Swyllys 	ret = CopyData(&src->subjectPublicKey,
6575221Swyllys 	    &newspki->subjectPublicKey);
6583089Swyllys 	if (ret != KMF_OK)
6593089Swyllys 		goto cleanup;
6603089Swyllys 
6613089Swyllys 	*dest = newspki;
6623089Swyllys cleanup:
6633089Swyllys 	if (ret != KMF_OK) {
6643089Swyllys 		if (newspki)
6653089Swyllys 			free_decoded_spki(newspki);
6663089Swyllys 	}
6673089Swyllys 	return (ret);
6683089Swyllys }
6693089Swyllys 
6703089Swyllys static KMF_RETURN
encode_validity(BerElement * asn1,KMF_X509_VALIDITY * validity)6713089Swyllys encode_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
6723089Swyllys {
6733089Swyllys 	int ret;
6743089Swyllys 
6753089Swyllys 	ret = kmfber_printf(asn1, "{tsts}",
6765221Swyllys 	    validity->notBefore.timeType,
6775221Swyllys 	    validity->notBefore.time.Data,
6785221Swyllys 	    validity->notAfter.timeType,
6795221Swyllys 	    validity->notAfter.time.Data);
6803089Swyllys 
6813089Swyllys 	if (ret == -1)
6823089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
6833089Swyllys 
6843089Swyllys 	return (KMF_OK);
6853089Swyllys }
6863089Swyllys 
6873089Swyllys static KMF_RETURN
get_validity(BerElement * asn1,KMF_X509_VALIDITY * validity)6883089Swyllys get_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
6893089Swyllys {
6903089Swyllys 	KMF_RETURN ret = KMF_OK;
6913089Swyllys 	int tag;
6923089Swyllys 	int t1, t2;
6933089Swyllys 	ber_len_t size;
6943089Swyllys 	char *t1str, *t2str;
6953089Swyllys 
6963089Swyllys 	(void) memset(validity, 0, sizeof (KMF_X509_VALIDITY));
6973089Swyllys 
6983089Swyllys 	tag = kmfber_next_element(asn1, &size, NULL);
6993089Swyllys 	if (tag != BER_CONSTRUCTED_SEQUENCE) {
7003089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
7013089Swyllys 	}
7023089Swyllys 
7033089Swyllys 	if (kmfber_scanf(asn1, "{tata}", &t1, &t1str, &t2, &t2str) == -1) {
7043089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
7053089Swyllys 	}
7063089Swyllys 
7073089Swyllys 	validity->notBefore.timeType = t1;
7083089Swyllys 	validity->notBefore.time.Data = (uchar_t *)t1str;
7093089Swyllys 	validity->notBefore.time.Length = strlen(t1str);
7103089Swyllys 
7113089Swyllys 	validity->notAfter.timeType = t2;
7123089Swyllys 	validity->notAfter.time.Data = (uchar_t *)t2str;
7133089Swyllys 	validity->notAfter.time.Length = strlen(t2str);
7143089Swyllys 
7153089Swyllys 	return (ret);
7163089Swyllys }
7173089Swyllys 
7183089Swyllys KMF_RETURN
AddRDN(KMF_X509_NAME * name,KMF_X509_RDN * newrdn)7193089Swyllys AddRDN(KMF_X509_NAME *name, KMF_X509_RDN *newrdn)
7203089Swyllys {
7213089Swyllys 	KMF_RETURN ret = KMF_OK;
7223089Swyllys 	KMF_X509_RDN *rdnslot = NULL;
7233089Swyllys 
7243089Swyllys 	/* Add new RDN record to existing list */
7253089Swyllys 	name->numberOfRDNs++;
7263089Swyllys 	name->RelativeDistinguishedName =
7275221Swyllys 	    realloc(name->RelativeDistinguishedName,
7285221Swyllys 	    name->numberOfRDNs * sizeof (KMF_X509_RDN));
7293089Swyllys 
7303089Swyllys 	if (name->RelativeDistinguishedName == NULL) {
7313089Swyllys 		ret = KMF_ERR_MEMORY;
7323089Swyllys 		goto cleanup;
7333089Swyllys 	}
7343089Swyllys 	rdnslot = &name->RelativeDistinguishedName[name->numberOfRDNs-1];
7353089Swyllys 
7363089Swyllys 	if (newrdn) {
7373089Swyllys 		(void) memcpy(rdnslot, newrdn, sizeof (KMF_X509_RDN));
7383089Swyllys 	} else {
7393089Swyllys 		rdnslot->numberOfPairs = 0;
7403089Swyllys 		rdnslot->AttributeTypeAndValue = NULL;
7413089Swyllys 	}
7423089Swyllys 
7433089Swyllys cleanup:
7443089Swyllys 	/* No cleanup needed here */
7453089Swyllys 	return (ret);
7463089Swyllys }
7473089Swyllys 
7483089Swyllys static KMF_RETURN
encode_rdn(BerElement * asn1,KMF_X509_NAME * name)7493089Swyllys encode_rdn(BerElement *asn1, KMF_X509_NAME *name)
7503089Swyllys {
7513089Swyllys 	KMF_RETURN ret = KMF_OK;
7523089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *attrtvpair = NULL;
7533089Swyllys 	int i;
7543089Swyllys 	KMF_X509_RDN *rdn;
7553089Swyllys 
7563089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
7573089Swyllys 		ret = KMF_ERR_MEMORY;
7583089Swyllys 		goto cleanup;
7593089Swyllys 	}
7603089Swyllys 
7613089Swyllys 	for (i = 0; i < name->numberOfRDNs; i++) {
7623089Swyllys 		if (kmfber_printf(asn1, "[") == -1) {
7633089Swyllys 			ret = KMF_ERR_MEMORY;
7643089Swyllys 			goto cleanup;
7653089Swyllys 		}
7663089Swyllys 		rdn = &name->RelativeDistinguishedName[i];
7673089Swyllys 		attrtvpair = rdn->AttributeTypeAndValue;
7683089Swyllys 
7693089Swyllys 		if (rdn->numberOfPairs > 0) {
7703089Swyllys 			if (kmfber_printf(asn1, "{Dto}",
7715221Swyllys 			    &attrtvpair->type,
7725221Swyllys 			    attrtvpair->valueType,
7735221Swyllys 			    attrtvpair->value.Data,
7745221Swyllys 			    attrtvpair->value.Length) == -1) {
7753089Swyllys 				ret = KMF_ERR_MEMORY;
7763089Swyllys 				goto cleanup;
7773089Swyllys 			}
7783089Swyllys 		}
7793089Swyllys 		if (kmfber_printf(asn1, "]") == -1) {
7803089Swyllys 			ret = KMF_ERR_MEMORY;
7813089Swyllys 			goto cleanup;
7823089Swyllys 		}
7833089Swyllys 	}
7843089Swyllys 
7853089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
7863089Swyllys 		ret = KMF_ERR_MEMORY;
7873089Swyllys 		goto cleanup;
7883089Swyllys 	}
7893089Swyllys 
7903089Swyllys cleanup:
7913089Swyllys 	/* No cleanup needed here */
7923089Swyllys 
7933089Swyllys 	return (ret);
7943089Swyllys }
7953089Swyllys 
7963089Swyllys 
7973089Swyllys KMF_RETURN
CopyRDN(KMF_X509_NAME * srcname,KMF_X509_NAME ** destname)7983089Swyllys CopyRDN(KMF_X509_NAME *srcname, KMF_X509_NAME **destname)
7993089Swyllys {
8003089Swyllys 	KMF_RETURN ret = KMF_OK;
8013089Swyllys 	KMF_X509_NAME 		*newname = NULL;
8023089Swyllys 	KMF_X509_RDN 		*rdn, *dstrdn;
8033089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
8043089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *srcav = NULL;
8053089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *dstav = NULL;
8063089Swyllys 	int i, j;
8073089Swyllys 
8083089Swyllys 	newname = malloc(sizeof (KMF_X509_NAME));
8093089Swyllys 	if (newname == NULL)
8103089Swyllys 		return (KMF_ERR_MEMORY);
8113089Swyllys 	(void) memset(newname, 0, sizeof (KMF_X509_NAME));
8123089Swyllys 
8133089Swyllys 	newname->numberOfRDNs = srcname->numberOfRDNs;
8143089Swyllys 	newname->RelativeDistinguishedName = malloc(newname->numberOfRDNs *
8155221Swyllys 	    sizeof (KMF_X509_RDN));
8163089Swyllys 	if (newname->RelativeDistinguishedName == NULL) {
8173089Swyllys 		free(newname);
8183089Swyllys 		return (KMF_ERR_MEMORY);
8193089Swyllys 	}
8203089Swyllys 	/* Copy each RDN in the list */
8213089Swyllys 	for (i = 0; i < newname->numberOfRDNs; i++) {
8223089Swyllys 		rdn = &srcname->RelativeDistinguishedName[i];
8233089Swyllys 
8243089Swyllys 		dstrdn = &newname->RelativeDistinguishedName[i];
8253089Swyllys 		(void) memset(dstrdn, 0, sizeof (KMF_X509_RDN));
8263089Swyllys 
8273089Swyllys 		dstrdn->numberOfPairs = rdn->numberOfPairs;
8283089Swyllys 		if (dstrdn->numberOfPairs > 0) {
8293089Swyllys 			av = malloc(dstrdn->numberOfPairs *
8305221Swyllys 			    sizeof (KMF_X509_TYPE_VALUE_PAIR));
8313089Swyllys 			if (av == NULL) {
8323089Swyllys 				ret = KMF_ERR_MEMORY;
8333089Swyllys 				goto cleanup;
8343089Swyllys 			}
8353089Swyllys 			(void) memset(av, 0, dstrdn->numberOfPairs *
8365221Swyllys 			    sizeof (KMF_X509_TYPE_VALUE_PAIR));
8373089Swyllys 
8383089Swyllys 			dstrdn->AttributeTypeAndValue = av;
8393089Swyllys 			if (av == NULL) {
8403089Swyllys 				ret = KMF_ERR_MEMORY;
8413089Swyllys 				goto cleanup;
8423089Swyllys 			}
8433089Swyllys 			/* Copy each A/V pair in the list */
8443089Swyllys 			for (j = 0; j < dstrdn->numberOfPairs; j++) {
8453089Swyllys 				srcav = &rdn->AttributeTypeAndValue[j];
8463089Swyllys 				dstav = &dstrdn->AttributeTypeAndValue[j];
8473089Swyllys 				if ((ret = CopyData(&srcav->type,
8485221Swyllys 				    &dstav->type)) != KMF_OK)
8493089Swyllys 					goto cleanup;
8503089Swyllys 				dstav->valueType = srcav->valueType;
8513089Swyllys 				if ((ret = CopyData(&srcav->value,
8525221Swyllys 				    &dstav->value)) != KMF_OK)
8533089Swyllys 					goto cleanup;
8543089Swyllys 			}
8553089Swyllys 		} else {
8563089Swyllys 			dstrdn->AttributeTypeAndValue = NULL;
8573089Swyllys 		}
8583089Swyllys 	}
8593089Swyllys 	*destname = newname;
8603089Swyllys 
8613089Swyllys cleanup:
8623089Swyllys 	if (ret != KMF_OK) {
8633089Swyllys 		if (newname)
8643089Swyllys 			free_rdn_data(newname);
8653089Swyllys 
8663089Swyllys 		free(newname);
8673089Swyllys 		*destname = NULL;
8683089Swyllys 	}
8693089Swyllys 	return (ret);
8703089Swyllys }
8713089Swyllys 
8723089Swyllys #define	VALID_DIRECTORYSTRING_TAG(t) ( \
8733089Swyllys 	(t == BER_UTF8_STRING) || \
8743089Swyllys 	(t == BER_PRINTABLE_STRING) || \
8753089Swyllys 	(t == BER_IA5STRING) || \
8763089Swyllys 	(t == BER_T61STRING) || \
8773089Swyllys 	(t == BER_BMP_STRING) || \
8783089Swyllys 	(t == BER_UNIVERSAL_STRING))
8793089Swyllys 
8803089Swyllys static KMF_RETURN
get_rdn(BerElement * asn1,KMF_X509_NAME * name)8813089Swyllys get_rdn(BerElement *asn1, KMF_X509_NAME *name)
8823089Swyllys {
8833089Swyllys 	KMF_RETURN ret = KMF_OK;
8843089Swyllys 	ber_len_t size;
8853089Swyllys 	char *end;
8863089Swyllys 	int tag;
8873089Swyllys 	BerValue AttrOID;
8883089Swyllys 	char *AttrValue = NULL;
8893089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *newpair = NULL;
8903089Swyllys 	KMF_X509_RDN 		newrdn;
8913089Swyllys 
8923089Swyllys 	/*
8933089Swyllys 	 * AttributeType	::=  OBJECT IDENTIFIER
8943089Swyllys 	 * AttributeValue	::=  ANY
8953089Swyllys 	 *
8963089Swyllys 	 * AttributeTypeAndValue	::=  SEQUENCE {
8973089Swyllys 	 *	type    AttributeType,
8983089Swyllys 	 *	value   AttributeValue }
8993089Swyllys 	 *
9003089Swyllys 	 * Name ::= CHOICE { -- only one possibility for now --
9013089Swyllys 	 * 		rdnSequence  RDNSequence }
9023089Swyllys 	 *
9033089Swyllys 	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
9043089Swyllys 	 *
9053089Swyllys 	 * DistinguishedName ::=   RDNSequence
9063089Swyllys 	 *
9073089Swyllys 	 * RelativeDistinguishedName  ::=
9083089Swyllys 	 *		 SET SIZE (1 .. MAX) OF AttributeTypeAndValue
9093089Swyllys 	 *
9103089Swyllys 	 */
9113089Swyllys 
9123089Swyllys 	name->numberOfRDNs = 0;
9133089Swyllys 	name->RelativeDistinguishedName = NULL;
9143089Swyllys 
9153089Swyllys 	/* Get the beginning of the RDN Set and a ptr to the end */
9163089Swyllys 	tag = kmfber_first_element(asn1, &size, &end);
9173089Swyllys 	if (tag != BER_CONSTRUCTED_SET) {
9183089Swyllys 		goto cleanup;
9193089Swyllys 	}
9203089Swyllys 
9213089Swyllys 	/* Walk through the individual SET items until the "end" is reached */
9223089Swyllys 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
9235221Swyllys 	    BER_CONSTRUCTED_SET) {
9243089Swyllys 		/* Skip over the SET tag */
9253089Swyllys 		if (kmfber_scanf(asn1, "T", &tag) == -1) {
9263089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
9273089Swyllys 			break;
9283089Swyllys 		}
9293089Swyllys 
9303089Swyllys 		/* An "empty" set member means we tack on an empty node */
9313089Swyllys 		if (size == 0) {
9323089Swyllys 			if ((ret = AddRDN(name, NULL)) != KMF_OK)
9333089Swyllys 				goto cleanup;
9343089Swyllys 			continue;
9353089Swyllys 		}
9363089Swyllys 
9373089Swyllys 		/* Attr OID and peek at the next tag and field length */
9383089Swyllys 		if (kmfber_scanf(asn1, "{Dtl", &AttrOID, &tag, &size) == -1) {
9393089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
9403089Swyllys 			break;
9413089Swyllys 		}
9423089Swyllys 
9433089Swyllys 		if (!(VALID_DIRECTORYSTRING_TAG(tag))) {
9443089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
9453089Swyllys 			break;
9463089Swyllys 		}
9473089Swyllys 
9483089Swyllys 		if (kmfber_scanf(asn1, "a}]", &AttrValue) == -1) {
9493089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
9503089Swyllys 			break;
9513089Swyllys 		}
9523089Swyllys 
9533089Swyllys 		/* Allocate a new name/value pair record */
9543089Swyllys 		newpair = malloc(sizeof (KMF_X509_TYPE_VALUE_PAIR));
9553089Swyllys 		if (newpair == NULL) {
9563089Swyllys 			ret = KMF_ERR_MEMORY;
9573089Swyllys 			break;
9583089Swyllys 		}
9593089Swyllys 		(void) memset(newpair, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
9603089Swyllys 		newpair->type.Data = (uchar_t *)AttrOID.bv_val;
9613089Swyllys 		newpair->type.Length = AttrOID.bv_len;
9623089Swyllys 		newpair->valueType = tag; /* what kind of string is it? */
9633089Swyllys 		newpair->value.Data = (uchar_t *)AttrValue;
9643089Swyllys 		newpair->value.Length = strlen(AttrValue);
9653089Swyllys 
9663089Swyllys 		(void) memset(&newrdn, 0, sizeof (KMF_X509_RDN));
9673089Swyllys 		newrdn.numberOfPairs = 1;
9683089Swyllys 		newrdn.AttributeTypeAndValue = newpair;
9693089Swyllys 
9703089Swyllys 		if ((ret = AddRDN(name, &newrdn)) != KMF_OK)
9713089Swyllys 			break;
9723089Swyllys 	}
9733089Swyllys 
9743089Swyllys cleanup:
9753089Swyllys 	if (ret != KMF_OK) {
9763089Swyllys 		free_rdn_data(name);
9773089Swyllys 	}
9783089Swyllys 	return (ret);
9793089Swyllys }
9803089Swyllys 
9813089Swyllys static KMF_RETURN
set_der_integer(KMF_DATA * data,int value)9823089Swyllys set_der_integer(KMF_DATA *data, int value)
9833089Swyllys {
9843089Swyllys 	if (data == NULL)
9853089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9863089Swyllys 
9873089Swyllys 	data->Data = malloc(sizeof (int));
9883089Swyllys 	if (data->Data == NULL)
9893089Swyllys 		return (KMF_ERR_MEMORY);
9903089Swyllys 
9913089Swyllys 	data->Length = sizeof (int);
9923089Swyllys 	(void) memcpy((void *)data->Data, (const void *)&value, sizeof (int));
9933089Swyllys 
9943089Swyllys 	return (KMF_OK);
9953089Swyllys }
9963089Swyllys 
9973089Swyllys static KMF_RETURN
set_bigint(KMF_BIGINT * data,KMF_BIGINT * bigint)9983089Swyllys set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
9993089Swyllys {
10003089Swyllys 	if (data == NULL || bigint == NULL)
10013089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10023089Swyllys 
10033089Swyllys 	data->val = malloc(bigint->len);
10043089Swyllys 	if (data->val == NULL)
10053089Swyllys 		return (KMF_ERR_MEMORY);
10063089Swyllys 
10073089Swyllys 	data->len = bigint->len;
10083089Swyllys 	(void) memcpy((void *)data->val, (const void *)bigint->val,
10095221Swyllys 	    bigint->len);
10103089Swyllys 
10113089Swyllys 	return (KMF_OK);
10123089Swyllys }
10133089Swyllys 
10143089Swyllys static KMF_RETURN
encode_uniqueid(BerElement * asn1,int tag,KMF_DATA * id)10153089Swyllys encode_uniqueid(BerElement *asn1, int tag, KMF_DATA *id)
10163089Swyllys {
10173089Swyllys 	KMF_RETURN ret = KMF_OK;
10183089Swyllys 	uint32_t len;
10193089Swyllys 
10203089Swyllys 	len = kmfber_calc_taglen(BER_BIT_STRING) +
10215221Swyllys 	    kmfber_calc_lenlen(id->Length * 8) + id->Length;
10223089Swyllys 	if (kmfber_printf(asn1, "TlB", tag, len,
10235221Swyllys 	    id->Data, id->Length * 8) == -1)
10243089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
10253089Swyllys 
10263089Swyllys 	return (ret);
10273089Swyllys }
10283089Swyllys 
10293089Swyllys static KMF_RETURN
encode_extension_list(BerElement * asn1,KMF_X509_EXTENSIONS * extns)10303089Swyllys encode_extension_list(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
10313089Swyllys {
10323089Swyllys 	KMF_RETURN ret = KMF_OK;
10333089Swyllys 	int i;
10343089Swyllys 
10353089Swyllys 	for (i = 0; i < extns->numberOfExtensions; i++) {
10363089Swyllys 		BerValue v;
10373089Swyllys 		v.bv_val = (char *)extns->extensions[i].extnId.Data;
10383089Swyllys 		v.bv_len = extns->extensions[i].extnId.Length;
10393089Swyllys 
10403089Swyllys 		if (kmfber_printf(asn1, "{D", &v) == -1)  {
10413089Swyllys 			ret = KMF_ERR_ENCODING;
10423089Swyllys 			goto cleanup;
10433089Swyllys 		}
10443089Swyllys 
10453089Swyllys 		if (extns->extensions[i].critical) {
10463089Swyllys 			if (kmfber_printf(asn1, "b",
10475221Swyllys 			    extns->extensions[i].critical) == -1) {
10483089Swyllys 				ret = KMF_ERR_ENCODING;
10493089Swyllys 				goto cleanup;
10503089Swyllys 			}
10513089Swyllys 		}
10523089Swyllys 
10533089Swyllys 		if (kmfber_printf(asn1, "o}",
10545221Swyllys 		    extns->extensions[i].BERvalue.Data,
10555221Swyllys 		    extns->extensions[i].BERvalue.Length) == -1) {
10563089Swyllys 			ret = KMF_ERR_ENCODING;
10573089Swyllys 			goto cleanup;
10583089Swyllys 		}
10593089Swyllys 	}
10603089Swyllys cleanup:
10613089Swyllys 	return (ret);
10623089Swyllys }
10633089Swyllys 
10643089Swyllys static KMF_RETURN
encode_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)10653089Swyllys encode_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
10663089Swyllys {
10673089Swyllys 	KMF_RETURN ret = KMF_OK;
10683089Swyllys 	BerElement *extn = NULL;
10693089Swyllys 	BerValue *extnvalue = NULL;
10703089Swyllys 
10713089Swyllys 	extn = kmfder_alloc();
10723089Swyllys 	if (extn == NULL)
10733089Swyllys 		return (KMF_ERR_MEMORY);
10743089Swyllys 
10753089Swyllys 	if (kmfber_printf(extn, "{") == -1) {
10763089Swyllys 		ret = KMF_ERR_ENCODING;
10773089Swyllys 		goto cleanup;
10783089Swyllys 	}
10793089Swyllys 
10803089Swyllys 	ret = encode_extension_list(extn, extns);
10813089Swyllys 
10823089Swyllys 	if (kmfber_printf(extn, "}") == -1) {
10833089Swyllys 		ret = KMF_ERR_ENCODING;
10843089Swyllys 		goto cleanup;
10853089Swyllys 	}
10863089Swyllys 
10873089Swyllys 	if (kmfber_flatten(extn, &extnvalue) == -1) {
10883089Swyllys 		ret = KMF_ERR_MEMORY;
10893089Swyllys 		goto cleanup;
10903089Swyllys 	}
10913089Swyllys 
10923089Swyllys 	if (kmfber_printf(asn1, "Tl", 0xA3, extnvalue->bv_len) == -1) {
10933089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
10943089Swyllys 		goto cleanup;
10953089Swyllys 	}
10963089Swyllys 
10973089Swyllys 	if (kmfber_write(asn1, extnvalue->bv_val, extnvalue->bv_len, 0) == -1) {
10983089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
10993089Swyllys 		goto cleanup;
11003089Swyllys 	}
11013089Swyllys 
11023089Swyllys cleanup:
11033089Swyllys 	kmfber_free(extn, 1);
11043089Swyllys 	if (extnvalue != NULL)
11053089Swyllys 		kmfber_bvfree(extnvalue);
11063089Swyllys 
11073089Swyllys 	return (ret);
11083089Swyllys }
11093089Swyllys 
11103089Swyllys static KMF_RETURN
get_one_extension(BerElement * asn1,KMF_X509_EXTENSION ** retex,char * end)11113089Swyllys get_one_extension(BerElement *asn1, KMF_X509_EXTENSION **retex, char *end)
11123089Swyllys {
11133089Swyllys 	KMF_RETURN ret = KMF_OK;
11143089Swyllys 	ber_len_t size;
11153089Swyllys 	int  critical, tag;
11163089Swyllys 	KMF_X509_EXTENSION *ex = NULL;
11173089Swyllys 	BerValue extOID;
11183089Swyllys 	BerValue extValue;
11193089Swyllys 	BerElement *extnber = NULL;
11203089Swyllys 
11213089Swyllys 	if (kmfber_scanf(asn1, "T", &tag) == -1) {
11223089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11233089Swyllys 		goto cleanup;
11243089Swyllys 	}
11253089Swyllys 
11263089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
11273089Swyllys 	if (tag != BER_OBJECT_IDENTIFIER) {
11283089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11293089Swyllys 		goto cleanup;
11303089Swyllys 	}
11313089Swyllys 	if (kmfber_scanf(asn1, "D", &extOID) == -1) {
11323089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11333089Swyllys 		goto cleanup;
11343089Swyllys 	}
11353089Swyllys 
11363089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
11373089Swyllys 	if (tag != BER_BOOLEAN) {
11383089Swyllys 		critical = 0;
11393089Swyllys 		if (tag != BER_OCTET_STRING)
11403089Swyllys 			goto cleanup;
11413089Swyllys 	} else {
11423089Swyllys 		if (kmfber_scanf(asn1, "b", &critical) == -1)
11433089Swyllys 			goto cleanup;
11443089Swyllys 	}
11453089Swyllys 
11463089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
11473089Swyllys 	if (tag != BER_OCTET_STRING)  {
11483089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11493089Swyllys 		goto cleanup;
11503089Swyllys 	}
11513089Swyllys 	if (kmfber_scanf(asn1, "o", &extValue) == -1)  {
11523089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11533089Swyllys 		goto cleanup;
11543089Swyllys 	}
11553089Swyllys 
11563089Swyllys 	/* allocate a new Extension record */
11573089Swyllys 	ex = malloc(sizeof (KMF_X509_EXTENSION));
11583089Swyllys 	if (ex == NULL) {
11593089Swyllys 		ret = KMF_ERR_MEMORY;
11603089Swyllys 		goto cleanup;
11613089Swyllys 	}
11623089Swyllys 	(void) memset(ex, 0, sizeof (ex));
11633089Swyllys 
11643089Swyllys 	ex->extnId.Data = (uchar_t *)extOID.bv_val;
11653089Swyllys 	ex->extnId.Length = extOID.bv_len;
11663089Swyllys 	ex->critical = critical;
11673089Swyllys 	ex->format = KMF_X509_DATAFORMAT_ENCODED;
11683089Swyllys 	ex->BERvalue.Data = (uchar_t *)extValue.bv_val;
11693089Swyllys 	ex->BERvalue.Length = extValue.bv_len;
11703089Swyllys 
11713089Swyllys 	/* Tag and value is a little tricky */
11723089Swyllys 	ex->value.tagAndValue = malloc(sizeof (KMF_X509EXT_TAGandVALUE));
11733089Swyllys 	if (ex->value.tagAndValue == NULL) {
11743089Swyllys 		ret = KMF_ERR_MEMORY;
11753089Swyllys 		goto cleanup;
11763089Swyllys 	}
11773089Swyllys 	(void) memset(ex->value.tagAndValue, 0,
11785221Swyllys 	    sizeof (KMF_X509EXT_TAGandVALUE));
11793089Swyllys 
11803089Swyllys 	/* Parse the Extension value field */
11813089Swyllys 	extnber = kmfder_init(&extValue);
11823089Swyllys 	if (extnber == NULL) {
11833089Swyllys 		ret = KMF_ERR_MEMORY;
11843089Swyllys 		goto cleanup;
11853089Swyllys 	}
11863089Swyllys 
11873089Swyllys 	/* Get the tag and length of the extension field */
11883089Swyllys 	if (kmfber_scanf(extnber, "tl", &tag, &size) == -1) {
11893089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11903089Swyllys 		goto cleanup;
11913089Swyllys 	}
11923089Swyllys 
11933089Swyllys 	if (kmfber_scanf(extnber, "T", &tag) == -1) {
11943089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11953089Swyllys 		goto cleanup;
11963089Swyllys 	}
11973089Swyllys 
11983089Swyllys 	ex->value.tagAndValue->value.Data = malloc(size);
11993089Swyllys 	ex->value.tagAndValue->value.Length = size;
12003089Swyllys 	size = kmfber_read(extnber,
12015221Swyllys 	    (char *)ex->value.tagAndValue->value.Data, size);
12023089Swyllys 	if (size != ex->value.tagAndValue->value.Length) {
12033089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
12043089Swyllys 		goto cleanup;
12053089Swyllys 	}
12063089Swyllys 	kmfber_free(extnber, 1);
12073089Swyllys 	ex->value.tagAndValue->type = tag;
12083089Swyllys 
12093089Swyllys 	*retex = ex;
12103089Swyllys cleanup:
12113089Swyllys 	if (ret != KMF_OK) {
12123089Swyllys 		if (ex != NULL)
12133089Swyllys 			free_one_extension(ex);
12143089Swyllys 	}
12153089Swyllys 
12163089Swyllys 	return (ret);
12173089Swyllys }
12183089Swyllys 
12193089Swyllys static KMF_RETURN
get_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)12203089Swyllys get_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
12213089Swyllys {
12223089Swyllys 	KMF_RETURN ret = KMF_OK;
12233089Swyllys 	ber_len_t size;
12243089Swyllys 	char *end = NULL;
12253089Swyllys 	KMF_X509_EXTENSION *ex = NULL;
12263089Swyllys 
12273089Swyllys 	/*
12283089Swyllys 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
12293089Swyllys 	 *
12303089Swyllys 	 * Extension  ::=  SEQUENCE  {
12313089Swyllys 	 *	extnID		OBJECT IDENTIFIER,
12323089Swyllys 	 *	critical	BOOLEAN DEFAULT FALSE,
12333089Swyllys 	 *	extnValue	OCTET STRING  }
12343089Swyllys 	 *
12353089Swyllys 	 * { {{D}Bo}, ... }
12363089Swyllys 	 */
12373089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
12385221Swyllys 	    BER_CONSTRUCTED_SEQUENCE)
12393089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
12403089Swyllys 
12413089Swyllys 	while (kmfber_next_element(asn1, &size, end) ==
12425221Swyllys 	    BER_CONSTRUCTED_SEQUENCE) {
12433089Swyllys 		ret = get_one_extension(asn1, &ex, end);
12443089Swyllys 		if (ret != KMF_OK)
12453089Swyllys 			goto cleanup;
12463089Swyllys 
12473089Swyllys 		extns->numberOfExtensions++;
12483089Swyllys 		extns->extensions = realloc(extns->extensions,
12495221Swyllys 		    extns->numberOfExtensions *
12505221Swyllys 		    sizeof (KMF_X509_EXTENSION));
12513089Swyllys 		if (extns->extensions == NULL) {
12523089Swyllys 			ret = KMF_ERR_MEMORY;
12533089Swyllys 			break;
12543089Swyllys 		}
12553089Swyllys 
12563089Swyllys 		extns->extensions[extns->numberOfExtensions-1] = *ex;
12573089Swyllys 		free(ex);
12583089Swyllys 	}
12593089Swyllys 
12603089Swyllys cleanup:
12613089Swyllys 	if (ret != KMF_OK)
12623089Swyllys 		free_extensions(extns);
12633089Swyllys 
12643089Swyllys 	return (ret);
12653089Swyllys }
12663089Swyllys 
12673089Swyllys KMF_RETURN
decode_tbscert_data(BerElement * asn1,KMF_X509_TBS_CERT ** signed_cert_ptr_ptr)12683089Swyllys decode_tbscert_data(BerElement *asn1,
12693089Swyllys 	KMF_X509_TBS_CERT **signed_cert_ptr_ptr)
12703089Swyllys {
12713089Swyllys 	KMF_RETURN ret = KMF_OK;
12723089Swyllys 	KMF_X509_TBS_CERT	*tbscert = NULL;
12733089Swyllys 	int tag, version;
12743089Swyllys 	struct berval *bvserno = NULL;
12753089Swyllys 	KMF_BIGINT serno;
12763089Swyllys 
12773089Swyllys 	if (kmfber_scanf(asn1, "{t", &tag) == -1) {
12783089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
12793089Swyllys 		goto cleanup;
12803089Swyllys 	}
12813089Swyllys 
12823089Swyllys 	/* Version number is optional */
12833089Swyllys 	if (tag == 0xA0) {
12843089Swyllys 		if (kmfber_scanf(asn1, "Ti", &tag, &version) == -1) {
12853089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
12863089Swyllys 			goto cleanup;
12873089Swyllys 		}
12883089Swyllys 	} else {
12893089Swyllys 		version = 0; /* DEFAULT v1 (0) */
12903089Swyllys 	}
12913089Swyllys 
12923089Swyllys 	/* Now get the serial number, it is not optional */
12933089Swyllys 	if (kmfber_scanf(asn1, "I", &bvserno) == -1) {
12943089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
12953089Swyllys 		goto cleanup;
12963089Swyllys 	} else {
12973089Swyllys 		serno.val = (uchar_t *)bvserno->bv_val;
12983089Swyllys 		serno.len = bvserno->bv_len;
12993089Swyllys 	}
13003089Swyllys 
13013089Swyllys 	tbscert = malloc(sizeof (KMF_X509_TBS_CERT));
13023089Swyllys 	if (!tbscert) {
13033089Swyllys 		ret = KMF_ERR_MEMORY;
13043089Swyllys 		goto cleanup;
13053089Swyllys 	}
13063089Swyllys 
13073089Swyllys 	(void) memset(tbscert, 0, sizeof (KMF_X509_TBS_CERT));
13083089Swyllys 
13093089Swyllys 	if ((ret = set_der_integer(&tbscert->version, version)) != KMF_OK)
13103089Swyllys 		goto cleanup;
13113089Swyllys 
13123089Swyllys 	if ((ret = set_bigint(&tbscert->serialNumber, &serno)) != KMF_OK)
13133089Swyllys 		goto cleanup;
13143089Swyllys 
13153089Swyllys 	if ((ret = get_algoid(asn1, &tbscert->signature)) != KMF_OK)
13163089Swyllys 		goto cleanup;
13173089Swyllys 
13183089Swyllys 	if ((ret = get_rdn(asn1, &tbscert->issuer)) != KMF_OK)
13193089Swyllys 		goto cleanup;
13203089Swyllys 
13213089Swyllys 	if ((ret = get_validity(asn1, &tbscert->validity)) != KMF_OK)
13223089Swyllys 		goto cleanup;
13233089Swyllys 
13243089Swyllys 	if ((ret = get_rdn(asn1, &tbscert->subject)) != KMF_OK)
13253089Swyllys 		goto cleanup;
13263089Swyllys 
13273089Swyllys 	if ((ret = get_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
13283089Swyllys 		goto cleanup;
13293089Swyllys 
13303089Swyllys 	/* Check for the optional fields */
13313089Swyllys 	tbscert->extensions.numberOfExtensions = 0;
13323089Swyllys 	tbscert->extensions.extensions = NULL;
13333089Swyllys 
13343089Swyllys 	while ((kmfber_scanf(asn1, "t", &tag)) != -1 &&
13355221Swyllys 	    (tag == 0xA1 || tag == 0xA2 || tag == 0xA3)) {
13363089Swyllys 		char *optfield;
13373089Swyllys 		ber_len_t len;
13383089Swyllys 
13393089Swyllys 		/* consume the tag and length */
13403089Swyllys 		(void) kmfber_scanf(asn1, "T", &tag);
13413089Swyllys 		switch (tag) {
13423089Swyllys 			case 0xA1:
13433089Swyllys 				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
13445221Swyllys 				    BER_BIT_STRING) {
13453089Swyllys 					ret = KMF_ERR_BAD_CERT_FORMAT;
13463089Swyllys 					goto cleanup;
13473089Swyllys 				}
13483089Swyllys 				tbscert->issuerUniqueIdentifier.Data =
13495221Swyllys 				    (uchar_t *)optfield;
13503089Swyllys 				tbscert->issuerUniqueIdentifier.Length =
13515221Swyllys 				    len / 8;
13523089Swyllys 				break;
13533089Swyllys 			case 0xA2:
13543089Swyllys 				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
13555221Swyllys 				    BER_BIT_STRING) {
13563089Swyllys 					ret = KMF_ERR_BAD_CERT_FORMAT;
13573089Swyllys 					goto cleanup;
13583089Swyllys 				}
13593089Swyllys 				tbscert->subjectUniqueIdentifier.Data =
13605221Swyllys 				    (uchar_t *)optfield;
13613089Swyllys 				tbscert->subjectUniqueIdentifier.Length =
13625221Swyllys 				    len / 8;
13633089Swyllys 				break;
13643089Swyllys 			case 0xA3:
13653089Swyllys 			ret = get_extensions(asn1, &tbscert->extensions);
13663089Swyllys 			break;
13673089Swyllys 		}
13683089Swyllys 	}
13693089Swyllys 
13703089Swyllys 	*signed_cert_ptr_ptr = tbscert;
13713089Swyllys 
13723089Swyllys cleanup:
13733089Swyllys 	if (bvserno != NULL) {
13743089Swyllys 		free(bvserno->bv_val);
13753089Swyllys 		free(bvserno);
13763089Swyllys 	}
13773089Swyllys 	if (ret != KMF_OK) {
13783089Swyllys 		if (tbscert) {
13793089Swyllys 			free_tbscert(tbscert);
13803089Swyllys 			free(tbscert);
13813089Swyllys 		}
13823089Swyllys 		*signed_cert_ptr_ptr = NULL;
13833089Swyllys 	}
13843089Swyllys 	return (ret);
13853089Swyllys }
13863089Swyllys 
13873089Swyllys KMF_RETURN
DerDecodeTbsCertificate(const KMF_DATA * Value,KMF_X509_TBS_CERT ** tbscert)13883089Swyllys DerDecodeTbsCertificate(const KMF_DATA *Value,
13893089Swyllys 	KMF_X509_TBS_CERT **tbscert)
13903089Swyllys {
13913089Swyllys 	KMF_RETURN ret = KMF_OK;
13923089Swyllys 	BerElement *asn1 = NULL;
13933089Swyllys 	BerValue 	rawcert;
13943089Swyllys 	KMF_X509_TBS_CERT *newcert = NULL;
13953089Swyllys 
13963089Swyllys 	if (!tbscert || !Value || !Value->Data || !Value->Length)
13973089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
13983089Swyllys 
13993089Swyllys 	rawcert.bv_val = (char *)Value->Data;
14003089Swyllys 	rawcert.bv_len = Value->Length;
14013089Swyllys 
14023089Swyllys 	if ((asn1 = kmfder_init(&rawcert)) == NULL)
14033089Swyllys 		return (KMF_ERR_MEMORY);
14043089Swyllys 
14053089Swyllys 	ret = decode_tbscert_data(asn1, &newcert);
14063089Swyllys 	if (ret != KMF_OK)
14073089Swyllys 		goto cleanup;
14083089Swyllys 
14093089Swyllys 	*tbscert = newcert;
14103089Swyllys 
14113089Swyllys cleanup:
14123089Swyllys 	if (ret != KMF_OK) {
14133089Swyllys 		if (newcert)
14143089Swyllys 			free_tbscert(newcert);
14153089Swyllys 		*tbscert = NULL;
14163089Swyllys 	}
14173089Swyllys 	kmfber_free(asn1, 1);
14183089Swyllys 
14193089Swyllys 	return (ret);
14203089Swyllys }
14213089Swyllys 
14223089Swyllys /*
14233089Swyllys  * Name: DerDecodeSignedCertificate
14243089Swyllys  *
14253089Swyllys  * Description:
14263089Swyllys  * DER decodes the encoded X509 certificate
14273089Swyllys  *
14283089Swyllys  * Parameters:
14293089Swyllys  * Value (input): DER encoded object that shd be decoded
14303089Swyllys  *
14313089Swyllys  * signed_cert_ptr_ptr (output) : Decoded KMF_X509_CERTIFICATE object
14323089Swyllys  */
14333089Swyllys KMF_RETURN
DerDecodeSignedCertificate(const KMF_DATA * Value,KMF_X509_CERTIFICATE ** signed_cert_ptr_ptr)14343089Swyllys DerDecodeSignedCertificate(const KMF_DATA *Value,
14353089Swyllys 	KMF_X509_CERTIFICATE **signed_cert_ptr_ptr)
14363089Swyllys {
14373089Swyllys 	KMF_RETURN ret = KMF_OK;
14383089Swyllys 	BerElement *asn1 = NULL;
14393089Swyllys 	BerValue 	rawcert;
14403089Swyllys 	ber_tag_t	tag;
14413089Swyllys 	ber_len_t	size;
14423089Swyllys 	char		*end = NULL;
14433089Swyllys 	char		*signature;
14443089Swyllys 	KMF_X509_TBS_CERT	*tbscert = NULL;
14453089Swyllys 	KMF_X509_CERTIFICATE *certptr = NULL;
14463089Swyllys 
14473089Swyllys 	if (!signed_cert_ptr_ptr || !Value || !Value->Data || !Value->Length)
14483089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
14493089Swyllys 
14503089Swyllys 	rawcert.bv_val = (char *)Value->Data;
14513089Swyllys 	rawcert.bv_len = Value->Length;
14523089Swyllys 
14533089Swyllys 	if ((asn1 = kmfder_init(&rawcert)) == NULL)
14543089Swyllys 		return (KMF_ERR_MEMORY);
14553089Swyllys 
14563089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
14575221Swyllys 	    BER_CONSTRUCTED_SEQUENCE) {
14583089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
14593089Swyllys 		goto cleanup;
14603089Swyllys 	}
14613089Swyllys 
14623089Swyllys 	certptr = malloc(sizeof (KMF_X509_CERTIFICATE));
14633089Swyllys 	if (certptr == NULL) {
14643089Swyllys 		ret = KMF_ERR_MEMORY;
14653089Swyllys 		goto cleanup;
14663089Swyllys 	}
14673089Swyllys 	(void) memset(certptr, 0, sizeof (KMF_X509_CERTIFICATE));
14683089Swyllys 
14693089Swyllys 	ret = decode_tbscert_data(asn1, &tbscert);
14703089Swyllys 	if (ret != KMF_OK)
14713089Swyllys 		goto cleanup;
14723089Swyllys 
14733089Swyllys 	certptr->certificate = *tbscert;
14743089Swyllys 	free(tbscert);
14753089Swyllys 	tbscert = NULL;
14763089Swyllys 
14773089Swyllys 	/*
14783089Swyllys 	 * The signature data my not be present yet.
14793089Swyllys 	 */
14803089Swyllys 	if ((ret = get_algoid(asn1,
14815221Swyllys 	    &certptr->signature.algorithmIdentifier)) == KMF_OK) {
14823089Swyllys 
14833089Swyllys 		/* Check to see if the cert has a signature yet */
14843089Swyllys 		if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
14853089Swyllys 			/* Finally, get the encrypted signature BITSTRING */
14863089Swyllys 			if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
14873089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
14883089Swyllys 				goto cleanup;
14893089Swyllys 			}
14903089Swyllys 			if (tag != BER_BIT_STRING) {
14913089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
14923089Swyllys 				goto cleanup;
14933089Swyllys 			}
14943089Swyllys 			if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
14953089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
14963089Swyllys 				goto cleanup;
14973089Swyllys 			}
14983089Swyllys 			certptr->signature.encrypted.Data =
14995221Swyllys 			    (uchar_t *)signature;
15003089Swyllys 			certptr->signature.encrypted.Length = size / 8;
15013089Swyllys 		} else {
15023089Swyllys 			certptr->signature.encrypted.Data = NULL;
15033089Swyllys 			certptr->signature.encrypted.Length = 0;
15043089Swyllys 		}
15053089Swyllys 	} else {
15063089Swyllys 		(void) memset(&certptr->signature, 0,
15075221Swyllys 		    sizeof (certptr->signature));
15083089Swyllys 		ret = KMF_OK;
15093089Swyllys 	}
15103089Swyllys 
15113089Swyllys 	*signed_cert_ptr_ptr = certptr;
15123089Swyllys cleanup:
15133089Swyllys 	if (ret != KMF_OK) {
15143089Swyllys 		if (certptr) {
15153089Swyllys 			free_decoded_cert(certptr);
15163089Swyllys 			free(certptr);
15173089Swyllys 		}
15183089Swyllys 
15193089Swyllys 		*signed_cert_ptr_ptr = NULL;
15203089Swyllys 	}
15213089Swyllys 	if (asn1)
15223089Swyllys 		kmfber_free(asn1, 1);
15233089Swyllys 
15243089Swyllys 	return (ret);
15253089Swyllys 
15263089Swyllys }
15273089Swyllys 
15283089Swyllys KMF_RETURN
DerDecodeExtension(KMF_DATA * Data,KMF_X509_EXTENSION ** extn)15293089Swyllys DerDecodeExtension(KMF_DATA *Data, KMF_X509_EXTENSION **extn)
15303089Swyllys {
15313089Swyllys 	KMF_RETURN ret = KMF_OK;
15323089Swyllys 	BerElement *asn1 = NULL;
15333089Swyllys 	BerValue bv;
15343089Swyllys 
15353089Swyllys 	bv.bv_val = (char *)Data->Data;
15363089Swyllys 	bv.bv_len = Data->Length;
15373089Swyllys 
15383089Swyllys 	asn1 = kmfder_init(&bv);
15393089Swyllys 	if (asn1 == NULL)
15403089Swyllys 		return (KMF_ERR_MEMORY);
15413089Swyllys 
15423089Swyllys 	ret = get_one_extension(asn1, extn, NULL);
15433089Swyllys 
15443089Swyllys cleanup:
15453089Swyllys 	if (ret != KMF_OK) {
15463089Swyllys 		if (*extn != NULL) {
15473089Swyllys 			free(*extn);
15483089Swyllys 		}
15493089Swyllys 		*extn = NULL;
15503089Swyllys 	}
15513089Swyllys 
15523089Swyllys 	kmfber_free(asn1, 1);
15533089Swyllys 	return (ret);
15543089Swyllys }
15553089Swyllys 
15563089Swyllys KMF_RETURN
DerDecodeName(KMF_DATA * encodedname,KMF_X509_NAME * name)15573089Swyllys DerDecodeName(KMF_DATA *encodedname, KMF_X509_NAME *name)
15583089Swyllys {
15593089Swyllys 	KMF_RETURN ret = KMF_OK;
15603089Swyllys 	BerElement *asn1 = NULL;
15613089Swyllys 	BerValue  bv;
15623089Swyllys 
15633089Swyllys 	bv.bv_val = (char *)encodedname->Data;
15643089Swyllys 	bv.bv_len = encodedname->Length;
15653089Swyllys 
15663089Swyllys 	asn1 = kmfder_init(&bv);
15673089Swyllys 	if (asn1 == NULL)
15683089Swyllys 		return (KMF_ERR_MEMORY);
15693089Swyllys 
15703089Swyllys 	(void) memset((void *)name, 0, sizeof (KMF_X509_NAME));
15713089Swyllys 
15723089Swyllys 	if ((ret = get_rdn(asn1, name)) != KMF_OK)
15733089Swyllys 		goto cleanup;
15743089Swyllys 
15753089Swyllys cleanup:
15763089Swyllys 	if (asn1)
15773089Swyllys 		kmfber_free(asn1, 1);
15783089Swyllys 	return (ret);
15793089Swyllys }
15803089Swyllys 
15813089Swyllys KMF_RETURN
DerEncodeName(KMF_X509_NAME * name,KMF_DATA * encodedname)15823089Swyllys DerEncodeName(KMF_X509_NAME *name, KMF_DATA *encodedname)
15833089Swyllys {
15843089Swyllys 	KMF_RETURN ret = KMF_OK;
15853089Swyllys 	BerElement *asn1 = NULL;
15863089Swyllys 	BerValue  *bv = NULL;
15873089Swyllys 
15883089Swyllys 	asn1 = kmfder_alloc();
15893089Swyllys 	if (asn1 == NULL)
15903089Swyllys 		return (KMF_ERR_MEMORY);
15913089Swyllys 
15923089Swyllys 	if ((ret = encode_rdn(asn1, name)) != KMF_OK)
15933089Swyllys 		goto cleanup;
15943089Swyllys 
15953089Swyllys 	if (kmfber_flatten(asn1, &bv) == -1) {
15963089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
15973089Swyllys 		goto cleanup;
15983089Swyllys 	}
15993089Swyllys 
16003089Swyllys 	encodedname->Data = (uchar_t *)bv->bv_val;
16013089Swyllys 	encodedname->Length = bv->bv_len;
16023089Swyllys 
16033089Swyllys cleanup:
16043089Swyllys 	if (bv)
16053089Swyllys 		free(bv);
16063089Swyllys 
16073089Swyllys 	if (asn1)
16083089Swyllys 		kmfber_free(asn1, 1);
16093089Swyllys 
16103089Swyllys 	return (ret);
16113089Swyllys }
16123089Swyllys 
16133089Swyllys static KMF_RETURN
encode_tbs_cert(BerElement * asn1,KMF_X509_TBS_CERT * tbscert)16143089Swyllys encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert)
16153089Swyllys {
16163089Swyllys 	KMF_RETURN ret = KMF_OK;
16173089Swyllys 	uint32_t version;
16183089Swyllys 
16193089Swyllys 	/* version should be 4 bytes or less */
16203089Swyllys 	if (tbscert->version.Length > sizeof (int))
16213089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
16223089Swyllys 
16233089Swyllys 	(void) memcpy(&version, tbscert->version.Data,
16245221Swyllys 	    tbscert->version.Length);
16253089Swyllys 
16263089Swyllys 	/* Start the sequence and add the version */
16273089Swyllys 	if (kmfber_printf(asn1, "{Tli", 0xA0, 3, version) == -1) {
16283089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16293089Swyllys 		goto cleanup;
16303089Swyllys 	}
16313089Swyllys 	/* Write the serial number */
16323089Swyllys 	if (kmfber_printf(asn1, "I",
16335221Swyllys 	    (char *)tbscert->serialNumber.val,
16345221Swyllys 	    (size_t)tbscert->serialNumber.len) == -1) {
16353089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16363089Swyllys 		goto cleanup;
16373089Swyllys 	}
16383089Swyllys 
1639*11973Swyllys.ingersoll@sun.com 	/* Don't encode alg parameters in signature algid area */
1640*11973Swyllys.ingersoll@sun.com 	if ((ret = encode_algoid(asn1, &tbscert->signature, FALSE)) != KMF_OK)
16413089Swyllys 		goto cleanup;
16423089Swyllys 
16433089Swyllys 	/* Encode the Issuer RDN */
16443089Swyllys 	if ((ret = encode_rdn(asn1, &tbscert->issuer)) != KMF_OK)
16453089Swyllys 		goto cleanup;
16463089Swyllys 
16473089Swyllys 	/* Encode the Validity fields */
16483089Swyllys 	if ((ret = encode_validity(asn1, &tbscert->validity)) != KMF_OK)
16493089Swyllys 		goto cleanup;
16503089Swyllys 
16513089Swyllys 	/* Encode the Subject RDN */
16523089Swyllys 	if ((ret = encode_rdn(asn1, &tbscert->subject)) != KMF_OK)
16533089Swyllys 		goto cleanup;
16543089Swyllys 
16553089Swyllys 	/* Encode the Subject Public Key Info */
16563089Swyllys 	if ((ret = encode_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
16573089Swyllys 		goto cleanup;
16583089Swyllys 
16593089Swyllys 	/* Optional field:  issuer Unique ID */
16603089Swyllys 	if (tbscert->issuerUniqueIdentifier.Length > 0) {
16613089Swyllys 		if ((ret = encode_uniqueid(asn1, 0xA1,
16625221Swyllys 		    &tbscert->issuerUniqueIdentifier)) != KMF_OK)
16633089Swyllys 			goto cleanup;
16643089Swyllys 	}
16653089Swyllys 
16663089Swyllys 	/* Optional field:  Subject Unique ID */
16673089Swyllys 	if (tbscert->subjectUniqueIdentifier.Length > 0) {
16683089Swyllys 		if ((ret = encode_uniqueid(asn1, 0xA2,
16695221Swyllys 		    &tbscert->subjectUniqueIdentifier)) != KMF_OK)
16703089Swyllys 			goto cleanup;
16713089Swyllys 	}
16723089Swyllys 
16733089Swyllys 	/* Optional field: Certificate Extensions */
16743089Swyllys 	if (tbscert->extensions.numberOfExtensions > 0) {
16753089Swyllys 		if ((ret = encode_extensions(asn1,
16765221Swyllys 		    &tbscert->extensions)) != KMF_OK)
16773089Swyllys 			goto cleanup;
16783089Swyllys 	}
16793089Swyllys 
16803089Swyllys 	/* Close out the TBSCert sequence */
16813089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
16823089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16833089Swyllys 		goto cleanup;
16843089Swyllys 	}
16853089Swyllys 
16863089Swyllys cleanup:
16873089Swyllys 	/*
16883089Swyllys 	 * Memory cleanup is done in the caller or in the individual
16893089Swyllys 	 * encoding routines.
16903089Swyllys 	 */
16913089Swyllys 
16923089Swyllys 	return (ret);
16933089Swyllys }
16943089Swyllys 
16953089Swyllys KMF_RETURN
DerEncodeTbsCertificate(KMF_X509_TBS_CERT * tbs_cert_ptr,KMF_DATA * enc_tbs_cert_ptr)16963089Swyllys DerEncodeTbsCertificate(KMF_X509_TBS_CERT *tbs_cert_ptr,
16973089Swyllys 	KMF_DATA *enc_tbs_cert_ptr)
16983089Swyllys {
16993089Swyllys 	KMF_RETURN ret;
17003089Swyllys 	BerElement *asn1 = NULL;
17013089Swyllys 	BerValue  *tbsdata = NULL;
17023089Swyllys 
17033089Swyllys 	asn1 = kmfder_alloc();
17043089Swyllys 	if (asn1 == NULL)
17053089Swyllys 		return (KMF_ERR_MEMORY);
17063089Swyllys 
17073089Swyllys 	enc_tbs_cert_ptr->Data = NULL;
17083089Swyllys 	enc_tbs_cert_ptr->Length = 0;
17093089Swyllys 
17103089Swyllys 	ret = encode_tbs_cert(asn1, tbs_cert_ptr);
17113089Swyllys 	if (ret != KMF_OK)
17123089Swyllys 		goto cleanup;
17133089Swyllys 
17143089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
17153089Swyllys 		ret = KMF_ERR_MEMORY;
17163089Swyllys 		goto cleanup;
17173089Swyllys 	}
17183089Swyllys 
17193089Swyllys 	enc_tbs_cert_ptr->Data = (uchar_t *)tbsdata->bv_val;
17203089Swyllys 	enc_tbs_cert_ptr->Length = tbsdata->bv_len;
17213089Swyllys 
17223089Swyllys cleanup:
17233089Swyllys 	if (ret != KMF_OK)
17243089Swyllys 		free_data(enc_tbs_cert_ptr);
17253089Swyllys 
17263089Swyllys 	if (asn1 != NULL)
17273089Swyllys 		kmfber_free(asn1, 1);
17283089Swyllys 
17293089Swyllys 	if (tbsdata)
17303089Swyllys 		free(tbsdata);
17313089Swyllys 
17323089Swyllys 	return (ret);
17333089Swyllys }
17343089Swyllys 
17353089Swyllys KMF_RETURN
DerEncodeSignedCertificate(KMF_X509_CERTIFICATE * signed_cert_ptr,KMF_DATA * encodedcert)17363089Swyllys DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr,
17373089Swyllys 	KMF_DATA *encodedcert)
17383089Swyllys {
17393089Swyllys 	KMF_RETURN ret = KMF_OK;
17403089Swyllys 	KMF_X509_TBS_CERT *tbscert = NULL;
17413089Swyllys 	KMF_X509_SIGNATURE		*signature = NULL;
17423089Swyllys 	BerElement	*asn1 = NULL;
17433089Swyllys 	BerValue 	*tbsdata = NULL;
17443089Swyllys 
17453089Swyllys 	if (signed_cert_ptr == NULL || encodedcert == NULL)
17463089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
17473089Swyllys 
17483089Swyllys 	encodedcert->Data = NULL;
17493089Swyllys 	encodedcert->Length = 0;
17503089Swyllys 
17513089Swyllys 	tbscert = &signed_cert_ptr->certificate;
17523089Swyllys 	signature = &signed_cert_ptr->signature;
17533089Swyllys 
17543089Swyllys 	asn1 = kmfder_alloc();
17553089Swyllys 	if (asn1 == NULL)
17563089Swyllys 		return (KMF_ERR_MEMORY);
17573089Swyllys 
17583089Swyllys 	/* Start outer X509 Certificate SEQUENCE */
17593089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
17603089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
17613089Swyllys 		goto cleanup;
17623089Swyllys 	}
17633089Swyllys 
17643089Swyllys 	if ((ret = encode_tbs_cert(asn1, tbscert)) != KMF_OK) {
17653089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
17663089Swyllys 		goto cleanup;
17673089Swyllys 	}
17683089Swyllys 
1769*11973Swyllys.ingersoll@sun.com 	/* Add the Algorithm & Signature Sequence (no parameters) */
17703089Swyllys 	if ((ret = encode_algoid(asn1,
1771*11973Swyllys.ingersoll@sun.com 	    &signature->algorithmIdentifier, FALSE)) != KMF_OK)
17723089Swyllys 		goto cleanup;
17733089Swyllys 
17743089Swyllys 	if (signature->encrypted.Length > 0) {
17753089Swyllys 		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
17765221Swyllys 		    signature->encrypted.Length * 8) == -1) {
17773089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
17783089Swyllys 			goto cleanup;
17793089Swyllys 		}
17803089Swyllys 	}
17813089Swyllys 
17823089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
17833089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
17843089Swyllys 		goto cleanup;
17853089Swyllys 	}
17863089Swyllys 
17873089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
17883089Swyllys 		ret = KMF_ERR_MEMORY;
17893089Swyllys 		goto cleanup;
17903089Swyllys 	}
17913089Swyllys 
17923089Swyllys 	encodedcert->Data = (uchar_t *)tbsdata->bv_val;
17933089Swyllys 	encodedcert->Length = tbsdata->bv_len;
17943089Swyllys 
17953089Swyllys cleanup:
17963089Swyllys 	if (ret != KMF_OK)
17973089Swyllys 		free_data(encodedcert);
17983089Swyllys 
17993089Swyllys 	if (tbsdata)
18003089Swyllys 		free(tbsdata);
18013089Swyllys 
18023089Swyllys 	if (asn1)
18033089Swyllys 		kmfber_free(asn1, 1);
18043089Swyllys 
18053089Swyllys 	return (ret);
18063089Swyllys }
18073089Swyllys 
18083089Swyllys KMF_RETURN
ExtractX509CertParts(KMF_DATA * x509cert,KMF_DATA * tbscert,KMF_DATA * signature)18093089Swyllys ExtractX509CertParts(KMF_DATA *x509cert, KMF_DATA *tbscert,
18103089Swyllys 		KMF_DATA *signature)
18113089Swyllys {
18123089Swyllys 	KMF_RETURN ret = KMF_OK;
18133089Swyllys 	BerElement *der = NULL;
18143089Swyllys 	BerValue x509;
18153089Swyllys 	ber_tag_t tag;
18163089Swyllys 	ber_len_t size;
18173089Swyllys 
18183089Swyllys 	if (tbscert == NULL || x509cert == NULL)
18193089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
18203089Swyllys 
18213089Swyllys 	x509.bv_val = (char *)x509cert->Data;
18223089Swyllys 	x509.bv_len = x509cert->Length;
18233089Swyllys 
18243089Swyllys 	der = kmfder_init(&x509);
18253089Swyllys 	if (der == NULL)
18263089Swyllys 		return (KMF_ERR_MEMORY);
18273089Swyllys 
18283089Swyllys 	/* Skip over the overall Sequence tag to get at the TBS Cert data */
18293089Swyllys 	if (kmfber_scanf(der, "Tl", &tag, &size) == -1) {
18303089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
18313089Swyllys 		goto cleanup;
18323089Swyllys 	}
18333089Swyllys 	if (tag != BER_CONSTRUCTED_SEQUENCE) {
18343089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
18353089Swyllys 		goto cleanup;
18363089Swyllys 	}
18373089Swyllys 
18383089Swyllys 	/*
18393089Swyllys 	 * Since we are extracting a copy of the ENCODED bytes, we
18403089Swyllys 	 * must make sure to also include the bytes for the tag and
18413089Swyllys 	 * the length fields for the CONSTRUCTED SEQUENCE (TBSCert).
18423089Swyllys 	 */
18433089Swyllys 	size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
18443089Swyllys 
18453089Swyllys 	tbscert->Data = malloc(size);
18463089Swyllys 	if (tbscert->Data == NULL) {
18473089Swyllys 		ret = KMF_ERR_MEMORY;
18483089Swyllys 		goto cleanup;
18493089Swyllys 	}
18503089Swyllys 	tbscert->Length = size;
18513089Swyllys 
18523089Swyllys 	/* The der data ptr is now set to the start of the TBS cert sequence */
18533089Swyllys 	size = kmfber_read(der, (char *)tbscert->Data, tbscert->Length);
18543089Swyllys 	if (size != tbscert->Length) {
18553089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
18563089Swyllys 		goto cleanup;
18573089Swyllys 	}
18583089Swyllys 
18593089Swyllys 	if (signature != NULL) {
18603089Swyllys 		KMF_X509_ALGORITHM_IDENTIFIER algoid;
18613089Swyllys 		if ((ret = get_algoid(der, &algoid)) != KMF_OK)
18623089Swyllys 			goto cleanup;
18633089Swyllys 		free_algoid(&algoid);
18643089Swyllys 
18653089Swyllys 		if (kmfber_scanf(der, "tl", &tag, &size) != BER_BIT_STRING) {
18663089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
18673089Swyllys 			goto cleanup;
18683089Swyllys 		}
18693089Swyllys 		/* Now get the signature data */
18703089Swyllys 		if (kmfber_scanf(der, "B", (char **)&signature->Data,
18715221Swyllys 		    (ber_len_t *)&signature->Length) == -1) {
18723089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
18733089Swyllys 			goto cleanup;
18743089Swyllys 		}
18753089Swyllys 		/* convert bitstring length to bytes */
18763089Swyllys 		signature->Length = signature->Length / 8;
18773089Swyllys 	}
18783089Swyllys 
18793089Swyllys cleanup:
18803089Swyllys 	if (der)
18813089Swyllys 		kmfber_free(der, 1);
18823089Swyllys 
18833089Swyllys 	if (ret != KMF_OK)
18843089Swyllys 		free_data(tbscert);
18853089Swyllys 
18863089Swyllys 	return (ret);
18873089Swyllys }
18883089Swyllys 
18893089Swyllys static KMF_RETURN
decode_csr_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)18903089Swyllys decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
18913089Swyllys {
18923089Swyllys 	KMF_RETURN ret = KMF_OK;
18933089Swyllys 	BerValue oid;
18943089Swyllys 
18953089Swyllys 	if (kmfber_scanf(asn1, "{D", &oid) == -1) {
18963089Swyllys 		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
18973089Swyllys 	}
18983089Swyllys 
18993089Swyllys 	/* We only understand extension requests in a CSR */
19003089Swyllys 	if (memcmp(oid.bv_val, extension_request_oid.Data,
19015221Swyllys 	    oid.bv_len) != 0) {
19023089Swyllys 		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
19033089Swyllys 	}
19043089Swyllys 
19053089Swyllys 	if (kmfber_scanf(asn1, "[") == -1) {
19063089Swyllys 		return (KMF_ERR_ENCODING);
19073089Swyllys 	}
19083089Swyllys 	ret = get_extensions(asn1, extns);
19093089Swyllys 
19103089Swyllys 
19113089Swyllys 	return (ret);
19123089Swyllys }
19133089Swyllys 
19143089Swyllys static KMF_RETURN
decode_tbscsr_data(BerElement * asn1,KMF_TBS_CSR ** signed_csr_ptr_ptr)19153089Swyllys decode_tbscsr_data(BerElement *asn1,
19163089Swyllys 	KMF_TBS_CSR **signed_csr_ptr_ptr)
19173089Swyllys {
19183089Swyllys 	KMF_RETURN ret = KMF_OK;
19193089Swyllys 	KMF_TBS_CSR	*tbscsr = NULL;
19203089Swyllys 	char *end = NULL;
19213089Swyllys 	uint32_t version;
19223089Swyllys 	ber_tag_t tag;
19233089Swyllys 	ber_len_t size;
19243089Swyllys 
19253089Swyllys 	/* Now get the version number, it is not optional */
19263089Swyllys 	if (kmfber_scanf(asn1, "{i", &version) == -1) {
19273089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
19283089Swyllys 		goto cleanup;
19293089Swyllys 	}
19303089Swyllys 
19313089Swyllys 	tbscsr = malloc(sizeof (KMF_TBS_CSR));
19323089Swyllys 	if (!tbscsr) {
19333089Swyllys 		ret = KMF_ERR_MEMORY;
19343089Swyllys 		goto cleanup;
19353089Swyllys 	}
19363089Swyllys 
19373089Swyllys 	(void) memset(tbscsr, 0, sizeof (KMF_TBS_CSR));
19383089Swyllys 
19393089Swyllys 	if ((ret = set_der_integer(&tbscsr->version, version)) != KMF_OK)
19403089Swyllys 		goto cleanup;
19413089Swyllys 
19423089Swyllys 	if ((ret = get_rdn(asn1, &tbscsr->subject)) != KMF_OK)
19433089Swyllys 		goto cleanup;
19443089Swyllys 
19453089Swyllys 	if ((ret = get_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
19463089Swyllys 		goto cleanup;
19473089Swyllys 
19483089Swyllys 	/* Check for the optional fields (attributes) */
19493089Swyllys 	if (kmfber_next_element(asn1, &size, end) == 0xA0) {
19503089Swyllys 		if (kmfber_scanf(asn1, "Tl", &tag, &size) == -1) {
19513089Swyllys 			ret = KMF_ERR_ENCODING;
19523089Swyllys 			goto cleanup;
19533089Swyllys 		}
19543089Swyllys 
19553089Swyllys 		ret = decode_csr_extensions(asn1, &tbscsr->extensions);
19563089Swyllys 	}
19573089Swyllys 	if (ret == KMF_OK)
19583089Swyllys 		*signed_csr_ptr_ptr = tbscsr;
19593089Swyllys 
19603089Swyllys cleanup:
19613089Swyllys 	if (ret != KMF_OK) {
19623089Swyllys 		if (tbscsr) {
19633089Swyllys 			free_tbscsr(tbscsr);
19643089Swyllys 			free(tbscsr);
19653089Swyllys 		}
19663089Swyllys 		*signed_csr_ptr_ptr = NULL;
19673089Swyllys 	}
19683089Swyllys 	return (ret);
19693089Swyllys }
19703089Swyllys 
19713089Swyllys KMF_RETURN
DerDecodeTbsCsr(const KMF_DATA * Value,KMF_TBS_CSR ** tbscsr)19723089Swyllys DerDecodeTbsCsr(const KMF_DATA *Value,
19733089Swyllys 	KMF_TBS_CSR **tbscsr)
19743089Swyllys {
19753089Swyllys 	KMF_RETURN ret = KMF_OK;
19763089Swyllys 	BerElement *asn1 = NULL;
19773089Swyllys 	BerValue 	rawcsr;
19783089Swyllys 	KMF_TBS_CSR *newcsr = NULL;
19793089Swyllys 
19803089Swyllys 	if (!tbscsr || !Value || !Value->Data || !Value->Length)
19813089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
19823089Swyllys 
19833089Swyllys 	rawcsr.bv_val = (char *)Value->Data;
19843089Swyllys 	rawcsr.bv_len = Value->Length;
19853089Swyllys 
19863089Swyllys 	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
19873089Swyllys 		return (KMF_ERR_MEMORY);
19883089Swyllys 
19893089Swyllys 	ret = decode_tbscsr_data(asn1, &newcsr);
19903089Swyllys 	if (ret != KMF_OK)
19913089Swyllys 		goto cleanup;
19923089Swyllys 
19933089Swyllys 	*tbscsr = newcsr;
19943089Swyllys 
19953089Swyllys cleanup:
19963089Swyllys 	if (ret != KMF_OK) {
19973089Swyllys 		if (newcsr)
19983089Swyllys 			free_tbscsr(newcsr);
19993089Swyllys 		*tbscsr = NULL;
20003089Swyllys 	}
20013089Swyllys 	kmfber_free(asn1, 1);
20023089Swyllys 
20033089Swyllys 	return (ret);
20043089Swyllys }
20053089Swyllys 
20063089Swyllys KMF_RETURN
DerDecodeSignedCsr(const KMF_DATA * Value,KMF_CSR_DATA ** signed_csr_ptr_ptr)20073089Swyllys DerDecodeSignedCsr(const KMF_DATA *Value,
20083089Swyllys 	KMF_CSR_DATA **signed_csr_ptr_ptr)
20093089Swyllys {
20103089Swyllys 	KMF_RETURN ret = KMF_OK;
20113089Swyllys 	BerElement *asn1 = NULL;
20123089Swyllys 	BerValue 	rawcsr;
20133089Swyllys 	int			tag;
20143089Swyllys 	ber_len_t	size;
20153089Swyllys 	char		*end = NULL;
20163089Swyllys 	char		*signature;
20173089Swyllys 	KMF_TBS_CSR	*tbscsr = NULL;
20183089Swyllys 	KMF_CSR_DATA *csrptr = NULL;
20193089Swyllys 
20203089Swyllys 	if (!signed_csr_ptr_ptr || !Value || !Value->Data || !Value->Length)
20213089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
20223089Swyllys 
20233089Swyllys 	rawcsr.bv_val = (char *)Value->Data;
20243089Swyllys 	rawcsr.bv_len = Value->Length;
20253089Swyllys 
20263089Swyllys 	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
20273089Swyllys 		return (KMF_ERR_MEMORY);
20283089Swyllys 
20293089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
20305221Swyllys 	    BER_CONSTRUCTED_SEQUENCE) {
20313089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
20323089Swyllys 		goto cleanup;
20333089Swyllys 	}
20343089Swyllys 
20353089Swyllys 	csrptr = malloc(sizeof (KMF_CSR_DATA));
20363089Swyllys 	if (csrptr == NULL) {
20373089Swyllys 		ret = KMF_ERR_MEMORY;
20383089Swyllys 		goto cleanup;
20393089Swyllys 	}
20403089Swyllys 	(void) memset(csrptr, 0, sizeof (KMF_CSR_DATA));
20413089Swyllys 
20423089Swyllys 	ret = decode_tbscsr_data(asn1, &tbscsr);
20433089Swyllys 	if (ret != KMF_OK)
20443089Swyllys 		goto cleanup;
20453089Swyllys 
20463089Swyllys 	csrptr->csr = *tbscsr;
20473089Swyllys 	free(tbscsr);
20483089Swyllys 	tbscsr = NULL;
20493089Swyllys 
20503089Swyllys 	if ((ret = get_algoid(asn1,
20515221Swyllys 	    &csrptr->signature.algorithmIdentifier)) != KMF_OK)
20523089Swyllys 		goto cleanup;
20533089Swyllys 
20543089Swyllys 	/* Check to see if the cert has a signature yet */
20553089Swyllys 	if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
20563089Swyllys 		/* Finally, get the encrypted signature BITSTRING */
20573089Swyllys 		if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
20583089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
20593089Swyllys 			goto cleanup;
20603089Swyllys 		}
20613089Swyllys 		if (tag != BER_BIT_STRING) {
20623089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
20633089Swyllys 			goto cleanup;
20643089Swyllys 		}
20653089Swyllys 		if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
20663089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
20673089Swyllys 			goto cleanup;
20683089Swyllys 		}
20693089Swyllys 		csrptr->signature.encrypted.Data = (uchar_t *)signature;
20703089Swyllys 		csrptr->signature.encrypted.Length = size / 8;
20713089Swyllys 	} else {
20723089Swyllys 		csrptr->signature.encrypted.Data = NULL;
20733089Swyllys 		csrptr->signature.encrypted.Length = 0;
20743089Swyllys 	}
20753089Swyllys 
20763089Swyllys 	*signed_csr_ptr_ptr = csrptr;
20773089Swyllys cleanup:
20783089Swyllys 	if (ret != KMF_OK) {
20793089Swyllys 		free_tbscsr(&csrptr->csr);
20803089Swyllys 		free_algoid(&csrptr->signature.algorithmIdentifier);
20813089Swyllys 		if (csrptr->signature.encrypted.Data)
20823089Swyllys 			free(csrptr->signature.encrypted.Data);
20833089Swyllys 
20843089Swyllys 		if (csrptr)
20853089Swyllys 			free(csrptr);
20863089Swyllys 
20873089Swyllys 		*signed_csr_ptr_ptr = NULL;
20883089Swyllys 	}
20893089Swyllys 	if (asn1)
20903089Swyllys 		kmfber_free(asn1, 1);
20913089Swyllys 
20923089Swyllys 	return (ret);
20933089Swyllys 
20943089Swyllys }
20953089Swyllys 
20963089Swyllys static KMF_RETURN
encode_csr_extensions(BerElement * asn1,KMF_TBS_CSR * tbscsr)20973089Swyllys encode_csr_extensions(BerElement *asn1, KMF_TBS_CSR *tbscsr)
20983089Swyllys {
20993089Swyllys 	KMF_RETURN ret = KMF_OK;
21003089Swyllys 	int attlen = 0;
21013089Swyllys 	BerElement *extnasn1 = NULL;
21023089Swyllys 	BerValue *extnvalue = NULL;
21033089Swyllys 
21043089Swyllys 	/* Optional field: CSR attributes and extensions */
21053089Swyllys 	if (tbscsr->extensions.numberOfExtensions > 0) {
21063089Swyllys 		if (kmfber_printf(asn1, "T", 0xA0) == -1) {
21073089Swyllys 			ret = KMF_ERR_ENCODING;
21083089Swyllys 			goto cleanup;
21093089Swyllys 		}
21103089Swyllys 	} else {
21113089Swyllys 		/* No extensions or attributes to encode */
21123089Swyllys 		return (KMF_OK);
21133089Swyllys 	}
21143089Swyllys 
21153089Swyllys 	/*
21163089Swyllys 	 * attributes [0] Attributes
21173089Swyllys 	 * Attributes := SET OF Attribute
21183089Swyllys 	 * Attribute  := SEQUENCE {
21193089Swyllys 	 *   { ATTRIBUTE ID
21203089Swyllys 	 *	values SET SIZE(1..MAX) of ATTRIBUTE
21213089Swyllys 	 *   }
21223089Swyllys 	 *
21233089Swyllys 	 * Ex: { ExtensionRequest OID [ { {extn1 } , {extn2 } } ] }
21243089Swyllys 	 */
21253089Swyllys 
21263089Swyllys 	/*
21273089Swyllys 	 * Encode any extensions and add to the attributes section.
21283089Swyllys 	 */
21293089Swyllys 	if (tbscsr->extensions.numberOfExtensions > 0) {
21303089Swyllys 		extnasn1 = kmfder_alloc();
21313089Swyllys 		if (extnasn1 == NULL) {
21323089Swyllys 			ret = KMF_ERR_MEMORY;
21333089Swyllys 			goto cleanup;
21343089Swyllys 		}
21353089Swyllys 
21363089Swyllys 		if (kmfber_printf(extnasn1, "{D[{",
21375221Swyllys 		    &extension_request_oid) == -1) {
21383089Swyllys 			ret = KMF_ERR_ENCODING;
21393089Swyllys 			goto cleanup_1;
21403089Swyllys 		}
21413089Swyllys 
21423089Swyllys 		if ((ret = encode_extension_list(extnasn1,
21435221Swyllys 		    &tbscsr->extensions)) != KMF_OK) {
21443089Swyllys 			goto cleanup_1;
21453089Swyllys 		}
21463089Swyllys 
21473089Swyllys 		if (kmfber_printf(extnasn1, "}]}") == -1) {
21483089Swyllys 			ret = KMF_ERR_ENCODING;
21493089Swyllys 			goto cleanup_1;
21503089Swyllys 		}
21513089Swyllys 
21523089Swyllys 		if (kmfber_flatten(extnasn1, &extnvalue) == -1) {
21533089Swyllys 			ret = KMF_ERR_MEMORY;
21543089Swyllys 			goto cleanup_1;
21553089Swyllys 		}
21563089Swyllys cleanup_1:
21573089Swyllys 		kmfber_free(extnasn1, 1);
21583089Swyllys 
21593089Swyllys 		if (ret == KMF_OK)
21603089Swyllys 			/* Add 2 bytes to cover the tag and the length */
21613089Swyllys 			attlen = extnvalue->bv_len;
21623089Swyllys 	}
21633089Swyllys 	if (ret != KMF_OK)
21643089Swyllys 		goto cleanup;
21653089Swyllys 
21663089Swyllys 	if (kmfber_printf(asn1, "l", attlen) == -1) {
21673089Swyllys 		ret = KMF_ERR_ENCODING;
21683089Swyllys 		goto cleanup;
21693089Swyllys 	}
21703089Swyllys 
21713089Swyllys 	/* Write the actual encoded extensions */
21723089Swyllys 	if (extnvalue != NULL && extnvalue->bv_val != NULL) {
21733089Swyllys 		if (kmfber_write(asn1, extnvalue->bv_val,
21745221Swyllys 		    extnvalue->bv_len, 0) == -1) {
21753089Swyllys 			ret = KMF_ERR_ENCODING;
21763089Swyllys 			goto cleanup;
21773089Swyllys 		}
21783089Swyllys 	}
21793089Swyllys 
21803089Swyllys cleanup:
21813089Swyllys 	/*
21823089Swyllys 	 * Memory cleanup is done in the caller or in the individual
21833089Swyllys 	 * encoding routines.
21843089Swyllys 	 */
21853089Swyllys 	if (extnvalue) {
21863089Swyllys 		if (extnvalue->bv_val)
21873089Swyllys 			free(extnvalue->bv_val);
21883089Swyllys 		free(extnvalue);
21893089Swyllys 	}
21903089Swyllys 
21913089Swyllys 	return (ret);
21923089Swyllys }
21933089Swyllys 
21943089Swyllys static KMF_RETURN
encode_tbs_csr(BerElement * asn1,KMF_TBS_CSR * tbscsr)21953089Swyllys encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr)
21963089Swyllys {
21973089Swyllys 	KMF_RETURN ret = KMF_OK;
21983089Swyllys 	uint32_t version;
21993089Swyllys 
22003089Swyllys 	/* Start the version */
22013089Swyllys 	(void) memcpy(&version, tbscsr->version.Data,
22025221Swyllys 	    tbscsr->version.Length);
22033089Swyllys 
22043890Swyllys 	if (kmfber_printf(asn1, "{i", version) == -1) {
22053089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
22063089Swyllys 		goto cleanup;
22073089Swyllys 	}
22083089Swyllys 
22093089Swyllys 	/* Encode the Subject RDN */
22103089Swyllys 	if ((ret = encode_rdn(asn1, &tbscsr->subject)) != KMF_OK)
22113089Swyllys 		goto cleanup;
22123089Swyllys 
22133089Swyllys 	/* Encode the Subject Public Key Info */
22143089Swyllys 	if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
22153089Swyllys 		goto cleanup;
22163089Swyllys 
22173089Swyllys 	if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK)
22183089Swyllys 		goto cleanup;
22193089Swyllys 
22203089Swyllys 	/* Close out the TBSCert sequence */
22213089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
22223089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
22233089Swyllys 		goto cleanup;
22243089Swyllys 	}
22253089Swyllys 
22263089Swyllys cleanup:
22273089Swyllys 	return (ret);
22283089Swyllys }
22293089Swyllys 
22303089Swyllys KMF_RETURN
DerEncodeDSAPrivateKey(KMF_DATA * encodedkey,KMF_RAW_DSA_KEY * dsa)22313089Swyllys DerEncodeDSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_DSA_KEY *dsa)
22323089Swyllys {
22333089Swyllys 	KMF_RETURN rv = KMF_OK;
22343089Swyllys 	BerElement *asn1 = NULL;
22353089Swyllys 	BerValue  *dsadata = NULL;
22363089Swyllys 
22373089Swyllys 	asn1 = kmfder_alloc();
22383089Swyllys 	if (asn1 == NULL)
22393089Swyllys 		return (KMF_ERR_MEMORY);
22403089Swyllys 
22413089Swyllys 	if (kmfber_printf(asn1, "I",
22425221Swyllys 	    dsa->value.val, dsa->value.len) == -1) {
22433089Swyllys 		rv = KMF_ERR_MEMORY;
22443089Swyllys 		goto cleanup;
22453089Swyllys 	}
22463089Swyllys 
22473089Swyllys 	if (kmfber_flatten(asn1, &dsadata) == -1) {
22483089Swyllys 		rv = KMF_ERR_MEMORY;
22493089Swyllys 		goto cleanup;
22503089Swyllys 	}
22513089Swyllys 
22523089Swyllys 	encodedkey->Data = (uchar_t *)dsadata->bv_val;
22533089Swyllys 	encodedkey->Length = dsadata->bv_len;
22543089Swyllys 
22553089Swyllys 	free(dsadata);
22563089Swyllys cleanup:
22573089Swyllys 	kmfber_free(asn1, 1);
22583089Swyllys 	return (rv);
22593089Swyllys }
22603089Swyllys 
22613089Swyllys KMF_RETURN
DerEncodeRSAPrivateKey(KMF_DATA * encodedkey,KMF_RAW_RSA_KEY * rsa)22623089Swyllys DerEncodeRSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_RSA_KEY *rsa)
22633089Swyllys {
22643089Swyllys 	KMF_RETURN rv = KMF_OK;
22653089Swyllys 	BerElement *asn1 = NULL;
22663089Swyllys 	uchar_t ver = 0;
22673089Swyllys 	BerValue  *rsadata = NULL;
22683089Swyllys 
22693089Swyllys 	asn1 = kmfder_alloc();
22703089Swyllys 	if (asn1 == NULL)
22713089Swyllys 		return (KMF_ERR_MEMORY);
22723089Swyllys 
22733089Swyllys 	if (kmfber_printf(asn1, "{IIIIIIIII}",
22745221Swyllys 	    &ver, 1,
22755221Swyllys 	    rsa->mod.val, rsa->mod.len,
22765221Swyllys 	    rsa->pubexp.val, rsa->pubexp.len,
22775221Swyllys 	    rsa->priexp.val, rsa->priexp.len,
22785221Swyllys 	    rsa->prime1.val, rsa->prime1.len,
22795221Swyllys 	    rsa->prime2.val, rsa->prime2.len,
22805221Swyllys 	    rsa->exp1.val, rsa->exp1.len,
22815221Swyllys 	    rsa->exp2.val, rsa->exp2.len,
22825221Swyllys 	    rsa->coef.val, rsa->coef.len) == -1)
22833089Swyllys 		goto cleanup;
22843089Swyllys 
22853089Swyllys 	if (kmfber_flatten(asn1, &rsadata) == -1) {
22863089Swyllys 		rv = KMF_ERR_MEMORY;
22873089Swyllys 		goto cleanup;
22883089Swyllys 	}
22893089Swyllys 
22903089Swyllys 	encodedkey->Data = (uchar_t *)rsadata->bv_val;
22913089Swyllys 	encodedkey->Length = rsadata->bv_len;
22923089Swyllys 
22933089Swyllys 	free(rsadata);
22943089Swyllys cleanup:
22953089Swyllys 	kmfber_free(asn1, 1);
22963089Swyllys 	return (rv);
22973089Swyllys }
22983089Swyllys 
2299*11973Swyllys.ingersoll@sun.com KMF_RETURN
DerEncodeECPrivateKey(KMF_DATA * encodedkey,KMF_RAW_EC_KEY * eckey)2300*11973Swyllys.ingersoll@sun.com DerEncodeECPrivateKey(KMF_DATA *encodedkey, KMF_RAW_EC_KEY *eckey)
2301*11973Swyllys.ingersoll@sun.com {
2302*11973Swyllys.ingersoll@sun.com 	KMF_RETURN rv = KMF_OK;
2303*11973Swyllys.ingersoll@sun.com 	BerElement *asn1 = NULL;
2304*11973Swyllys.ingersoll@sun.com 	uchar_t ver = 1;
2305*11973Swyllys.ingersoll@sun.com 	BerValue  *data = NULL;
2306*11973Swyllys.ingersoll@sun.com 
2307*11973Swyllys.ingersoll@sun.com 	asn1 = kmfder_alloc();
2308*11973Swyllys.ingersoll@sun.com 	if (asn1 == NULL)
2309*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
2310*11973Swyllys.ingersoll@sun.com 
2311*11973Swyllys.ingersoll@sun.com 	if (kmfber_printf(asn1, "{io",
2312*11973Swyllys.ingersoll@sun.com 	    ver, eckey->value.val, eckey->value.len) == -1) {
2313*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_ENCODING;
2314*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2315*11973Swyllys.ingersoll@sun.com 	}
2316*11973Swyllys.ingersoll@sun.com 	/*
2317*11973Swyllys.ingersoll@sun.com 	 * Indicate that we are using the named curve option
2318*11973Swyllys.ingersoll@sun.com 	 * for the parameters.
2319*11973Swyllys.ingersoll@sun.com 	 */
2320*11973Swyllys.ingersoll@sun.com 	if (kmfber_printf(asn1, "T", 0xA0) == -1) {
2321*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_ENCODING;
2322*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2323*11973Swyllys.ingersoll@sun.com 	}
2324*11973Swyllys.ingersoll@sun.com 	if (kmfber_printf(asn1, "l", eckey->params.Length) == -1) {
2325*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_ENCODING;
2326*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2327*11973Swyllys.ingersoll@sun.com 	}
2328*11973Swyllys.ingersoll@sun.com 	if (kmfber_write(asn1, (char *)eckey->params.Data,
2329*11973Swyllys.ingersoll@sun.com 	    eckey->params.Length, 0) == -1) {
2330*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_ENCODING;
2331*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2332*11973Swyllys.ingersoll@sun.com 	}
2333*11973Swyllys.ingersoll@sun.com 	if (kmfber_printf(asn1, "}") == -1) {
2334*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_ENCODING;
2335*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2336*11973Swyllys.ingersoll@sun.com 	}
2337*11973Swyllys.ingersoll@sun.com 	if (kmfber_flatten(asn1, &data) == -1) {
2338*11973Swyllys.ingersoll@sun.com 		rv = KMF_ERR_MEMORY;
2339*11973Swyllys.ingersoll@sun.com 		goto cleanup;
2340*11973Swyllys.ingersoll@sun.com 	}
2341*11973Swyllys.ingersoll@sun.com 	encodedkey->Data = (uchar_t *)data->bv_val;
2342*11973Swyllys.ingersoll@sun.com 	encodedkey->Length = data->bv_len;
2343*11973Swyllys.ingersoll@sun.com 
2344*11973Swyllys.ingersoll@sun.com cleanup:
2345*11973Swyllys.ingersoll@sun.com 	kmfber_free(asn1, 1);
2346*11973Swyllys.ingersoll@sun.com 	return (rv);
2347*11973Swyllys.ingersoll@sun.com }
2348*11973Swyllys.ingersoll@sun.com 
23493089Swyllys 
23503089Swyllys KMF_RETURN
DerEncodeTbsCsr(KMF_TBS_CSR * tbs_csr_ptr,KMF_DATA * enc_tbs_csr_ptr)23513089Swyllys DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr,
23523089Swyllys 	KMF_DATA *enc_tbs_csr_ptr)
23533089Swyllys {
23543089Swyllys 	KMF_RETURN ret;
23553089Swyllys 	BerValue  *tbsdata = NULL;
23563089Swyllys 	BerElement *asn1 = NULL;
23573089Swyllys 
23583089Swyllys 	asn1 = kmfder_alloc();
23593089Swyllys 
23603089Swyllys 	enc_tbs_csr_ptr->Data = NULL;
23613089Swyllys 	enc_tbs_csr_ptr->Length = 0;
23623089Swyllys 
23633089Swyllys 	if (asn1 == NULL)
23643089Swyllys 		return (KMF_ERR_MEMORY);
23653089Swyllys 
23663089Swyllys 	ret = encode_tbs_csr(asn1, tbs_csr_ptr);
23673089Swyllys 	if (ret != KMF_OK)
23683089Swyllys 		goto cleanup;
23693089Swyllys 
23703089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
23713089Swyllys 		ret = KMF_ERR_MEMORY;
23723089Swyllys 		goto cleanup;
23733089Swyllys 	}
23743089Swyllys 
23753089Swyllys 	enc_tbs_csr_ptr->Data = (uchar_t *)tbsdata->bv_val;
23763089Swyllys 	enc_tbs_csr_ptr->Length = tbsdata->bv_len;
23773089Swyllys 
23783089Swyllys cleanup:
23793089Swyllys 	if (ret != KMF_OK)
23803089Swyllys 		free_data(enc_tbs_csr_ptr);
23813089Swyllys 
23823089Swyllys 	if (asn1 != NULL)
23833089Swyllys 		kmfber_free(asn1, 1);
23843089Swyllys 
23853089Swyllys 	if (tbsdata)
23863089Swyllys 		free(tbsdata);
23873089Swyllys 
23883089Swyllys 	return (ret);
23893089Swyllys }
23903089Swyllys 
23913089Swyllys KMF_RETURN
DerEncodeSignedCsr(KMF_CSR_DATA * signed_csr_ptr,KMF_DATA * encodedcsr)23923089Swyllys DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr,
23933089Swyllys 	KMF_DATA *encodedcsr)
23943089Swyllys {
23953089Swyllys 	KMF_RETURN ret = KMF_OK;
23963089Swyllys 	KMF_TBS_CSR *tbscsr = NULL;
23973089Swyllys 	KMF_X509_SIGNATURE		*signature = NULL;
23983089Swyllys 	BerElement	*asn1 = NULL;
23993089Swyllys 	BerValue 	*tbsdata = NULL;
24003089Swyllys 
24013089Swyllys 	if (signed_csr_ptr == NULL)
24023089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24033089Swyllys 
24043089Swyllys 	tbscsr = &signed_csr_ptr->csr;
24053089Swyllys 	signature = &signed_csr_ptr->signature;
24063089Swyllys 
24073089Swyllys 	asn1 = kmfder_alloc();
24083089Swyllys 	if (asn1 == NULL)
24093089Swyllys 		return (KMF_ERR_MEMORY);
24103089Swyllys 
24113089Swyllys 	/* Start outer CSR SEQUENCE */
24123089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
24133089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
24143089Swyllys 		goto cleanup;
24153089Swyllys 	}
24163089Swyllys 
24173089Swyllys 	ret = encode_tbs_csr(asn1, tbscsr);
24183089Swyllys 
24193089Swyllys 	/* Add the Algorithm & Signature Sequence */
24203089Swyllys 	if ((ret = encode_algoid(asn1,
2421*11973Swyllys.ingersoll@sun.com 	    &signature->algorithmIdentifier, FALSE)) != KMF_OK)
24223089Swyllys 		goto cleanup;
24233089Swyllys 
24243089Swyllys 	if (signature->encrypted.Length > 0) {
24253089Swyllys 		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
24265221Swyllys 		    signature->encrypted.Length * 8) == -1) {
24273089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
24283089Swyllys 			goto cleanup;
24293089Swyllys 		}
24303089Swyllys 	}
24313089Swyllys 
24323089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
24333089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
24343089Swyllys 		goto cleanup;
24353089Swyllys 	}
24363089Swyllys 
24373089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
24383089Swyllys 		ret = KMF_ERR_MEMORY;
24393089Swyllys 		goto cleanup;
24403089Swyllys 	}
24413089Swyllys 
24423089Swyllys 	encodedcsr->Data = (uchar_t *)tbsdata->bv_val;
24433089Swyllys 	encodedcsr->Length = tbsdata->bv_len;
24443089Swyllys 
24453089Swyllys cleanup:
24463089Swyllys 	if (ret != KMF_OK) {
24473089Swyllys 		free_data(encodedcsr);
24483089Swyllys 	}
24493089Swyllys 
24503089Swyllys 	if (tbsdata)
24513089Swyllys 		free(tbsdata);
24523089Swyllys 
24533089Swyllys 	if (asn1)
24543089Swyllys 		kmfber_free(asn1, 1);
24553089Swyllys 	return (ret);
24563089Swyllys }
24573089Swyllys 
2458*11973Swyllys.ingersoll@sun.com static KMF_RETURN
ber_copy_data(KMF_DATA * dst,KMF_DATA * src)2459*11973Swyllys.ingersoll@sun.com ber_copy_data(KMF_DATA *dst, KMF_DATA *src)
2460*11973Swyllys.ingersoll@sun.com {
2461*11973Swyllys.ingersoll@sun.com 	KMF_RETURN ret = KMF_OK;
2462*11973Swyllys.ingersoll@sun.com 
2463*11973Swyllys.ingersoll@sun.com 	if (dst == NULL || src == NULL)
2464*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_BAD_PARAMETER);
2465*11973Swyllys.ingersoll@sun.com 
2466*11973Swyllys.ingersoll@sun.com 	dst->Data = malloc(src->Length);
2467*11973Swyllys.ingersoll@sun.com 	if (dst->Data == NULL)
2468*11973Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
2469*11973Swyllys.ingersoll@sun.com 
2470*11973Swyllys.ingersoll@sun.com 	dst->Length = src->Length;
2471*11973Swyllys.ingersoll@sun.com 	(void) memcpy(dst->Data, src->Data, src->Length);
2472*11973Swyllys.ingersoll@sun.com 
2473*11973Swyllys.ingersoll@sun.com 	return (ret);
2474*11973Swyllys.ingersoll@sun.com }
2475*11973Swyllys.ingersoll@sun.com 
24763089Swyllys KMF_RETURN
ExtractSPKIData(const KMF_X509_SPKI * pKey,KMF_ALGORITHM_INDEX AlgorithmId,KMF_DATA * pKeyParts,uint32_t * uNumKeyParts)24773089Swyllys ExtractSPKIData(
24783089Swyllys 	const KMF_X509_SPKI *pKey,
24793089Swyllys 	KMF_ALGORITHM_INDEX AlgorithmId,
24803089Swyllys 	KMF_DATA *pKeyParts,
24813089Swyllys 	uint32_t *uNumKeyParts)
24823089Swyllys {
24833089Swyllys 	KMF_RETURN ret = KMF_OK;
24843089Swyllys 	BerElement *asn1 = NULL;
24853089Swyllys 	BerValue 	*P, *Q, *G, *Mod, *Exp, *PubKey;
24863089Swyllys 	BerValue	PubKeyParams, PubKeyData;
24873089Swyllys 
24883089Swyllys 	if (pKeyParts == NULL || uNumKeyParts == NULL || pKey == NULL)
24893089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24903089Swyllys 
24913089Swyllys 	switch (AlgorithmId) {
24925221Swyllys 		case KMF_ALGID_DSA:
24935221Swyllys 		case KMF_ALGID_SHA1WithDSA:
24945221Swyllys 			*uNumKeyParts = 0;
24955221Swyllys 			/* Get the parameters from the algorithm definition */
24965221Swyllys 			PubKeyParams.bv_val =
24975221Swyllys 			    (char *)pKey->algorithm.parameters.Data;
24985221Swyllys 			PubKeyParams.bv_len = pKey->algorithm.parameters.Length;
24995221Swyllys 			if ((asn1 = kmfder_init(&PubKeyParams)) == NULL)
25005221Swyllys 				return (KMF_ERR_MEMORY);
25015221Swyllys 
25025221Swyllys 			if (kmfber_scanf(asn1, "{III}", &P, &Q, &G) == -1) {
25035221Swyllys 				kmfber_free(asn1, 1);
25045221Swyllys 				return (KMF_ERR_BAD_KEY_FORMAT);
25055221Swyllys 			}
25065221Swyllys 			pKeyParts[KMF_DSA_PRIME].Data = (uchar_t *)P->bv_val;
25075221Swyllys 			pKeyParts[KMF_DSA_PRIME].Length = P->bv_len;
25085221Swyllys 			pKeyParts[KMF_DSA_SUB_PRIME].Data =
25095221Swyllys 			    (uchar_t *)Q->bv_val;
25105221Swyllys 			pKeyParts[KMF_DSA_SUB_PRIME].Length = Q->bv_len;
25115221Swyllys 			pKeyParts[KMF_DSA_BASE].Data = (uchar_t *)G->bv_val;
25125221Swyllys 			pKeyParts[KMF_DSA_BASE].Length = G->bv_len;
25135221Swyllys 
25145221Swyllys 			free(P);
25155221Swyllys 			free(Q);
25165221Swyllys 			free(G);
25173089Swyllys 			kmfber_free(asn1, 1);
25185221Swyllys 
25195221Swyllys 			/* Get the PubKey data */
25205221Swyllys 			PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
25215221Swyllys 			PubKeyData.bv_len = pKey->subjectPublicKey.Length;
25225221Swyllys 			if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
25235221Swyllys 				ret = KMF_ERR_MEMORY;
25245221Swyllys 				goto cleanup;
25255221Swyllys 			}
25265221Swyllys 			PubKey = NULL;
25275221Swyllys 			if (kmfber_scanf(asn1, "I", &PubKey) == -1) {
25285221Swyllys 				ret = KMF_ERR_BAD_KEY_FORMAT;
25295221Swyllys 				goto cleanup;
25305221Swyllys 			}
25315221Swyllys 			pKeyParts[KMF_DSA_PUBLIC_VALUE].Data =
25325221Swyllys 			    (uchar_t *)PubKey->bv_val;
25335221Swyllys 			pKeyParts[KMF_DSA_PUBLIC_VALUE].Length = PubKey->bv_len;
25345221Swyllys 
25355221Swyllys 			free(PubKey);
25365221Swyllys 
25375221Swyllys 			*uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS;
25385221Swyllys 			break;
2539*11973Swyllys.ingersoll@sun.com 		case KMF_ALGID_SHA1WithECDSA:
2540*11973Swyllys.ingersoll@sun.com 		case KMF_ALGID_ECDSA:
2541*11973Swyllys.ingersoll@sun.com 			(void) ber_copy_data(&pKeyParts[KMF_ECDSA_PARAMS],
2542*11973Swyllys.ingersoll@sun.com 			    (KMF_DATA *)&pKey->algorithm.parameters);
2543*11973Swyllys.ingersoll@sun.com 
2544*11973Swyllys.ingersoll@sun.com 			(void) ber_copy_data(&pKeyParts[KMF_ECDSA_POINT],
2545*11973Swyllys.ingersoll@sun.com 			    (KMF_DATA *)&pKey->subjectPublicKey);
2546*11973Swyllys.ingersoll@sun.com 
2547*11973Swyllys.ingersoll@sun.com 			*uNumKeyParts = 2;
2548*11973Swyllys.ingersoll@sun.com 			break;
25495221Swyllys 
25505221Swyllys 		case KMF_ALGID_RSA:
25515221Swyllys 		case KMF_ALGID_MD2WithRSA:
25525221Swyllys 		case KMF_ALGID_MD5WithRSA:
25535221Swyllys 		case KMF_ALGID_SHA1WithRSA:
25545221Swyllys 			*uNumKeyParts = 0;
25555221Swyllys 			PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
25565221Swyllys 			PubKeyData.bv_len = pKey->subjectPublicKey.Length;
25575221Swyllys 			if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
25585221Swyllys 				ret = KMF_ERR_MEMORY;
25595221Swyllys 				goto cleanup;
25605221Swyllys 			}
25615221Swyllys 			if (kmfber_scanf(asn1, "{II}", &Mod, &Exp) == -1) {
25625221Swyllys 				ret = KMF_ERR_BAD_KEY_FORMAT;
25635221Swyllys 				goto cleanup;
25645221Swyllys 			}
25655221Swyllys 			pKeyParts[KMF_RSA_MODULUS].Data =
25665221Swyllys 			    (uchar_t *)Mod->bv_val;
25675221Swyllys 			pKeyParts[KMF_RSA_MODULUS].Length = Mod->bv_len;
25685221Swyllys 			pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Data =
25695221Swyllys 			    (uchar_t *)Exp->bv_val;
25705221Swyllys 			pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Length = Exp->bv_len;
25715221Swyllys 			*uNumKeyParts = KMF_NUMBER_RSA_PUBLIC_KEY_PARTS;
25725221Swyllys 
25735221Swyllys 			free(Mod);
25745221Swyllys 			free(Exp);
25755221Swyllys 			break;
25765221Swyllys 		default:
25775221Swyllys 			return (KMF_ERR_BAD_PARAMETER);
25783089Swyllys 	}
25793089Swyllys cleanup:
25803089Swyllys 	if (ret != KMF_OK) {
25813089Swyllys 		int i;
25823089Swyllys 		for (i = 0; i < *uNumKeyParts; i++)
25833089Swyllys 			free_data(&pKeyParts[i]);
25843089Swyllys 	}
25853089Swyllys 	if (asn1 != NULL) {
25863089Swyllys 		kmfber_free(asn1, 1);
25873089Swyllys 	}
25883089Swyllys 
25893089Swyllys 	return (ret);
25903089Swyllys }
2591