xref: /onnv-gate/usr/src/lib/libkmf/ber_der/common/clasn1.c (revision 3991:376d3096844b)
13089Swyllys /*
23433Shaimay  * Copyright 2007 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
103089Swyllys 
113089Swyllys #include <strings.h>
123089Swyllys #include <kmftypes.h>
133089Swyllys #include <ber_der.h>
143089Swyllys #include <kmfapi.h>
153089Swyllys #include <kmfapiP.h>
163089Swyllys 
173089Swyllys #include <stdio.h>
183089Swyllys 
193089Swyllys #define	DSA_RAW_SIG_LEN	40
203089Swyllys 
213089Swyllys static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
223089Swyllys const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
233089Swyllys 	OID_ExtensionRequest};
243089Swyllys 
253089Swyllys static KMF_RETURN
263089Swyllys encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
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 	}
333089Swyllys 	if (algoid->parameters.Data == NULL ||
343089Swyllys 		algoid->parameters.Length == 0) {
353089Swyllys 		if (kmfber_printf(asn1, "n}") == -1)
363089Swyllys 			return (KMF_ERR_BAD_CERT_FORMAT);
373089Swyllys 	} else {
383089Swyllys 		/*
393089Swyllys 		 * The algorithm data can be anything, so we just write it
403089Swyllys 		 * straight into the buffer.  It is already DER encoded.
413089Swyllys 		 */
423089Swyllys 		(void) kmfber_write(asn1, (char *)algoid->parameters.Data,
433089Swyllys 			algoid->parameters.Length, 0);
443089Swyllys 		if (kmfber_printf(asn1, "}") == -1) {
453089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
463089Swyllys 		}
473089Swyllys 	}
483089Swyllys 
493089Swyllys 	return (ret);
503089Swyllys }
513089Swyllys 
523089Swyllys static void
533089Swyllys free_data(KMF_DATA *data)
543089Swyllys {
553089Swyllys 	if (data == NULL || data->Data == NULL)
563089Swyllys 		return;
573089Swyllys 
583089Swyllys 	free(data->Data);
593089Swyllys 	data->Data = NULL;
603089Swyllys 	data->Length = 0;
613089Swyllys }
623089Swyllys 
633089Swyllys static void
643089Swyllys free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
653089Swyllys {
663089Swyllys 	free_data(&algoid->algorithm);
673089Swyllys 	free_data(&algoid->parameters);
683089Swyllys }
693089Swyllys 
703089Swyllys static void
713089Swyllys free_decoded_spki(KMF_X509_SPKI *spki)
723089Swyllys {
733089Swyllys 	if (spki != NULL) {
743089Swyllys 		free_algoid(&spki->algorithm);
753089Swyllys 		free_data(&spki->subjectPublicKey);
763089Swyllys 	}
773089Swyllys }
783089Swyllys 
793089Swyllys static void
803089Swyllys free_rdn_data(KMF_X509_NAME *name)
813089Swyllys {
823089Swyllys 	KMF_X509_RDN 		*newrdn = NULL;
833089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
843089Swyllys 	int i, j;
853089Swyllys 
863089Swyllys 	if (name && name->numberOfRDNs) {
873089Swyllys 		for (i = 0; i < name->numberOfRDNs; i++) {
883089Swyllys 			newrdn = &name->RelativeDistinguishedName[i];
893089Swyllys 			for (j = 0; j < newrdn->numberOfPairs; j++) {
903089Swyllys 				av = &newrdn->AttributeTypeAndValue[j];
913089Swyllys 				free_data(&av->type);
923089Swyllys 				free_data(&av->value);
933089Swyllys 			}
943089Swyllys 			free(newrdn->AttributeTypeAndValue);
953089Swyllys 		}
963089Swyllys 		free(name->RelativeDistinguishedName);
973089Swyllys 		name->numberOfRDNs = 0;
983089Swyllys 		name->RelativeDistinguishedName = NULL;
993089Swyllys 	}
1003089Swyllys }
1013089Swyllys 
1023089Swyllys static void
1033089Swyllys free_validity(KMF_X509_VALIDITY *validity)
1043089Swyllys {
1053089Swyllys 	free_data(&validity->notBefore.time);
1063089Swyllys 	free_data(&validity->notAfter.time);
1073089Swyllys }
1083089Swyllys 
1093089Swyllys static void
1103089Swyllys free_one_extension(KMF_X509_EXTENSION *exptr)
1113089Swyllys {
1123089Swyllys 	free_data(&exptr->extnId);
1133089Swyllys 	free_data(&exptr->BERvalue);
1143089Swyllys 
1153089Swyllys 	if (exptr->value.tagAndValue) {
1163089Swyllys 		free_data(&exptr->value.tagAndValue->value);
1173089Swyllys 		free(exptr->value.tagAndValue);
1183089Swyllys 	}
1193089Swyllys }
1203089Swyllys 
1213089Swyllys static void
1223089Swyllys free_extensions(KMF_X509_EXTENSIONS *extns)
1233089Swyllys {
1243089Swyllys 	int i;
1253089Swyllys 	KMF_X509_EXTENSION *exptr;
1263089Swyllys 
1273089Swyllys 	if (extns && extns->numberOfExtensions > 0) {
1283089Swyllys 		for (i = 0; i < extns->numberOfExtensions; i++) {
1293089Swyllys 			exptr = &extns->extensions[i];
1303089Swyllys 			free_one_extension(exptr);
1313089Swyllys 		}
1323089Swyllys 		free(extns->extensions);
1333089Swyllys 		extns->numberOfExtensions = 0;
1343089Swyllys 		extns->extensions = NULL;
1353089Swyllys 	}
1363089Swyllys }
1373089Swyllys 
1383089Swyllys static void
1393089Swyllys free_tbscsr(KMF_TBS_CSR *tbscsr)
1403089Swyllys {
1413089Swyllys 	if (tbscsr) {
1423089Swyllys 		free_data(&tbscsr->version);
1433089Swyllys 
1443089Swyllys 		free_rdn_data(&tbscsr->subject);
1453089Swyllys 
1463089Swyllys 		free_decoded_spki(&tbscsr->subjectPublicKeyInfo);
1473089Swyllys 
1483089Swyllys 		free_extensions(&tbscsr->extensions);
1493089Swyllys 	}
1503089Swyllys }
1513089Swyllys 
1523089Swyllys 
1533089Swyllys static void
1543089Swyllys free_bigint(KMF_BIGINT *bn)
1553089Swyllys {
1563089Swyllys 	if (bn != NULL && bn->val != NULL) {
1573089Swyllys 		free(bn->val);
1583089Swyllys 		bn->val = NULL;
1593089Swyllys 		bn->len = 0;
1603089Swyllys 	}
1613089Swyllys }
1623089Swyllys 
1633089Swyllys static void
1643089Swyllys free_tbscert(KMF_X509_TBS_CERT *tbscert)
1653089Swyllys {
1663089Swyllys 	if (tbscert) {
1673089Swyllys 		free_data(&tbscert->version);
1683089Swyllys 		free_bigint(&tbscert->serialNumber);
1693089Swyllys 		free_algoid(&tbscert->signature);
1703089Swyllys 
1713089Swyllys 		free_rdn_data(&tbscert->issuer);
1723089Swyllys 		free_rdn_data(&tbscert->subject);
1733089Swyllys 
1743089Swyllys 		free_validity(&tbscert->validity);
1753089Swyllys 
1763089Swyllys 		free_data(&tbscert->issuerUniqueIdentifier);
1773089Swyllys 		free_data(&tbscert->subjectUniqueIdentifier);
1783089Swyllys 		free_decoded_spki(&tbscert->subjectPublicKeyInfo);
1793089Swyllys 		free_extensions(&tbscert->extensions);
1803089Swyllys 
1813089Swyllys 		free_data(&tbscert->issuerUniqueIdentifier);
1823089Swyllys 		free_data(&tbscert->subjectUniqueIdentifier);
1833089Swyllys 	}
1843089Swyllys }
1853089Swyllys 
1863089Swyllys static void
1873089Swyllys free_decoded_cert(KMF_X509_CERTIFICATE *certptr)
1883089Swyllys {
1893089Swyllys 	if (!certptr)
1903089Swyllys 		return;
1913089Swyllys 
1923089Swyllys 	free_tbscert(&certptr->certificate);
1933089Swyllys 
1943089Swyllys 	free_algoid(&certptr->signature.algorithmIdentifier);
1953089Swyllys 	free_data(&certptr->signature.encrypted);
1963089Swyllys }
1973089Swyllys 
1983089Swyllys static KMF_RETURN
1993089Swyllys get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
2003089Swyllys {
2013089Swyllys 	KMF_RETURN ret = KMF_OK;
2023089Swyllys 	ber_tag_t tag, newtag;
2033089Swyllys 	ber_len_t size;
2043089Swyllys 	BerValue AlgOID = {NULL, 0};
2053089Swyllys 
2063089Swyllys 	tag = kmfber_next_element(asn1, &size, NULL);
2073089Swyllys 	if (tag != BER_CONSTRUCTED_SEQUENCE)
2083089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
2093089Swyllys 
2103089Swyllys 	if ((tag = kmfber_scanf(asn1, "{Dt", &AlgOID, &newtag)) == -1) {
2113089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
2123089Swyllys 	}
2133089Swyllys 	algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val;
2143089Swyllys 	algoid->algorithm.Length = AlgOID.bv_len;
2153089Swyllys 
2163089Swyllys 	if (newtag == BER_NULL) {
2173089Swyllys 		(void) kmfber_scanf(asn1, "n}");
2183089Swyllys 		algoid->parameters.Data = NULL;
2193089Swyllys 		algoid->parameters.Length = 0;
2203089Swyllys 	} else {
2213089Swyllys 		/* Peek at the tag and length bytes */
2223089Swyllys 		if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
2233089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
2243089Swyllys 			goto cleanup;
2253089Swyllys 		}
2263089Swyllys 
2273089Swyllys 		/*
2283089Swyllys 		 * We need to read the tag and the length bytes too,
2293089Swyllys 		 * so adjust the size.
2303089Swyllys 		 */
2313089Swyllys 		size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
2323089Swyllys 		algoid->parameters.Data = malloc(size);
2333089Swyllys 		if (algoid->parameters.Data == NULL) {
2343089Swyllys 			ret = KMF_ERR_MEMORY;
2353089Swyllys 			goto cleanup;
2363089Swyllys 		}
2373089Swyllys 		/* read the raw data into the Algoritm params area. */
2383089Swyllys 		if (kmfber_read(asn1, (char *)algoid->parameters.Data,
2393089Swyllys 			size) == -1) {
2403089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
2413089Swyllys 			goto cleanup;
2423089Swyllys 		}
2433089Swyllys 		algoid->parameters.Length = size;
2443089Swyllys 		if ((tag = kmfber_scanf(asn1, "}")) == -1) {
2453089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
2463089Swyllys 		}
2473089Swyllys 	}
2483089Swyllys cleanup:
2493089Swyllys 	if (ret != KMF_OK) {
2503089Swyllys 		free_algoid(algoid);
2513089Swyllys 	}
2523089Swyllys 
2533089Swyllys 	return (ret);
2543089Swyllys }
2553089Swyllys 
2563089Swyllys static KMF_RETURN
2573089Swyllys CopyData(KMF_DATA *src, KMF_DATA *dst)
2583089Swyllys {
2593089Swyllys 	if (src && dst && src->Data != NULL && src->Length > 0) {
2603089Swyllys 		dst->Length = src->Length;
261*3991Shaimay 		dst->Data = malloc(dst->Length);
2623089Swyllys 		if (dst->Data == NULL)
2633089Swyllys 			return (KMF_ERR_MEMORY);
2643089Swyllys 		(void) memcpy(dst->Data, src->Data, src->Length);
2653089Swyllys 	}
2663089Swyllys 	return (KMF_OK);
2673089Swyllys }
2683089Swyllys 
2693089Swyllys static KMF_RETURN
2703089Swyllys encode_spki(BerElement *asn1, KMF_X509_SPKI *spki)
2713089Swyllys {
2723089Swyllys 	KMF_RETURN ret = KMF_OK;
2733089Swyllys 
2743089Swyllys 	if (kmfber_printf(asn1, "{") == -1)
2753089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
2763089Swyllys 
2773089Swyllys 	if ((ret = encode_algoid(asn1, &spki->algorithm)) != KMF_OK)
2783089Swyllys 		return (ret);
2793089Swyllys 
2803089Swyllys 	if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data,
2813089Swyllys 				spki->subjectPublicKey.Length * 8) == -1)
2823089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
2833089Swyllys 
2843089Swyllys 	return (ret);
2853089Swyllys }
2863089Swyllys 
2873089Swyllys KMF_RETURN
2883089Swyllys DerEncodeSPKI(KMF_X509_SPKI *spki, KMF_DATA *EncodedSPKI)
2893089Swyllys {
2903089Swyllys 	KMF_RETURN ret = KMF_OK;
2913089Swyllys 	BerElement *asn1;
2923089Swyllys 	BerValue *result;
2933089Swyllys 
2943089Swyllys 	if (spki == NULL || EncodedSPKI == NULL)
2953089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
2963089Swyllys 
2973089Swyllys 	if ((asn1 = kmfder_alloc()) == NULL)
2983089Swyllys 		return (KMF_ERR_MEMORY);
2993089Swyllys 
3003089Swyllys 	if ((ret = encode_spki(asn1, spki)) != KMF_OK) {
3013089Swyllys 		return (ret);
3023089Swyllys 	}
3033089Swyllys 
3043089Swyllys 	if (kmfber_flatten(asn1, &result) == -1) {
3053089Swyllys 		kmfber_free(asn1, 1);
3063089Swyllys 		return (KMF_ERR_ENCODING);
3073089Swyllys 	}
3083089Swyllys 
3093089Swyllys 	EncodedSPKI->Data = (uchar_t *)result->bv_val;
3103089Swyllys 	EncodedSPKI->Length = result->bv_len;
3113089Swyllys 
3123089Swyllys 	free(result);
3133089Swyllys 	kmfber_free(asn1, 1);
3143089Swyllys 	return (KMF_OK);
3153089Swyllys }
3163089Swyllys 
3173089Swyllys static KMF_RETURN
3183089Swyllys get_spki(BerElement *asn1, KMF_X509_SPKI *spki)
3193089Swyllys {
3203089Swyllys 	KMF_RETURN ret = KMF_OK;
3213089Swyllys 	char *bitstr = NULL;
3223089Swyllys 	ber_len_t size;
3233089Swyllys 
3243089Swyllys 	if (kmfber_scanf(asn1, "{") == -1)
3253089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
3263089Swyllys 
3273089Swyllys 	if ((ret = get_algoid(asn1, &spki->algorithm)) != KMF_OK)
3283089Swyllys 		return (ret);
3293089Swyllys 
3303089Swyllys 	if (kmfber_scanf(asn1, "B}", &bitstr, &size) == BER_BIT_STRING) {
3313089Swyllys 		spki->subjectPublicKey.Data = (uchar_t *)bitstr;
3323089Swyllys 		spki->subjectPublicKey.Length = size / 8;
3333089Swyllys 	} else {
3343089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
3353089Swyllys 		goto cleanup;
3363089Swyllys 	}
3373089Swyllys cleanup:
3383089Swyllys 	if (ret != KMF_OK) {
3393089Swyllys 		if (bitstr != NULL)
3403089Swyllys 			free(bitstr);
3413089Swyllys 		spki->subjectPublicKey.Data = NULL;
3423089Swyllys 		spki->subjectPublicKey.Length = 0;
3433089Swyllys 
3443089Swyllys 		free_algoid(&spki->algorithm);
3453089Swyllys 	}
3463089Swyllys 	return (ret);
3473089Swyllys }
3483089Swyllys 
3493089Swyllys KMF_RETURN
3503089Swyllys DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
3513089Swyllys {
3523089Swyllys 	BerElement *asn1;
3533089Swyllys 	BerValue *buf;
3543089Swyllys 	int n;
3553089Swyllys 
3563089Swyllys 	if (rawdata == NULL || signature == NULL)
3573089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3583089Swyllys 
3593089Swyllys 	if (rawdata->Data == NULL || rawdata->Length != DSA_RAW_SIG_LEN)
3603089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
3613089Swyllys 
3623089Swyllys 	asn1 = kmfder_alloc();
3633089Swyllys 	if (asn1 == NULL)
3643089Swyllys 		return (KMF_ERR_MEMORY);
3653089Swyllys 
3663089Swyllys 	/*
3673089Swyllys 	 * The DSA signature is the concatenation of 2 SHA-1 hashed
3683089Swyllys 	 * bignum values.
3693089Swyllys 	 */
3703089Swyllys 	n = DSA_RAW_SIG_LEN/2;
3713089Swyllys 	if (kmfber_printf(asn1, "{II}",
3723089Swyllys 			rawdata->Data, n,
3733089Swyllys 			&rawdata->Data[n], n) == -1) {
3743089Swyllys 		kmfber_free(asn1, 1);
3753089Swyllys 		return (KMF_ERR_MEMORY);
3763089Swyllys 	}
3773089Swyllys 
3783089Swyllys 	if (kmfber_flatten(asn1, &buf) == -1) {
3793089Swyllys 		kmfber_free(asn1, 1);
3803089Swyllys 		return (KMF_ERR_ENCODING);
3813089Swyllys 	}
3823089Swyllys 
3833089Swyllys 	signature->Data = (uchar_t *)buf->bv_val;
3843089Swyllys 	signature->Length = buf->bv_len;
3853089Swyllys 
3863089Swyllys 	kmfber_free(asn1, 1);
3873089Swyllys 	free(buf);
3883089Swyllys 
3893089Swyllys 	return (KMF_OK);
3903089Swyllys }
3913089Swyllys 
3923089Swyllys KMF_RETURN
3933089Swyllys DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
3943089Swyllys {
3953089Swyllys 	KMF_RETURN ret = KMF_OK;
3963089Swyllys 	BerElement *asn1 = NULL;
3973089Swyllys 	BerValue buf, *R = NULL, *S = NULL;
3983089Swyllys 
3993089Swyllys 	buf.bv_val = (char *)encoded->Data;
4003089Swyllys 	buf.bv_len = encoded->Length;
4013089Swyllys 
4023089Swyllys 	if (encoded == NULL || encoded->Data == NULL ||
4033089Swyllys 	    signature == NULL)
4043089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
4053089Swyllys 
4063089Swyllys 	signature->Data = NULL;
4073089Swyllys 	signature->Length = 0;
4083089Swyllys 
4093089Swyllys 	if ((asn1 = kmfder_init(&buf)) == NULL)
4103089Swyllys 		return (KMF_ERR_MEMORY);
4113089Swyllys 
4123089Swyllys 	if (kmfber_scanf(asn1, "{II}", &R, &S) == -1) {
4133089Swyllys 		ret = KMF_ERR_BAD_PARAMETER;
4143089Swyllys 		goto cleanup;
4153089Swyllys 	}
4163089Swyllys 	signature->Length = R->bv_len + S->bv_len;
4173089Swyllys 	signature->Data = malloc(signature->Length);
4183089Swyllys 	if (signature->Data == NULL)  {
4193089Swyllys 		ret = KMF_ERR_MEMORY;
4203089Swyllys 		goto cleanup;
4213089Swyllys 	}
4223089Swyllys 	(void) memcpy(signature->Data, R->bv_val, R->bv_len);
4233089Swyllys 	(void) memcpy(&signature->Data[R->bv_len], S->bv_val, S->bv_len);
4243089Swyllys 
4253089Swyllys cleanup:
4263089Swyllys 	if (R && R->bv_val)
4273089Swyllys 		free(R->bv_val);
4283089Swyllys 	if (S && S->bv_val)
4293089Swyllys 		free(S->bv_val);
4303089Swyllys 
4313089Swyllys 	if (S) free(S);
4323089Swyllys 	if (R) free(R);
4333089Swyllys 
4343089Swyllys 	if (asn1) kmfber_free(asn1, 1);
4353089Swyllys 
4363089Swyllys 	return (ret);
4373089Swyllys }
4383089Swyllys 
4393089Swyllys KMF_RETURN
4403089Swyllys DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki)
4413089Swyllys {
4423089Swyllys 	KMF_RETURN ret = KMF_OK;
4433089Swyllys 	BerElement *asn1;
4443089Swyllys 	BerValue bv;
4453089Swyllys 
4463089Swyllys 	if (EncodedSPKI == NULL || EncodedSPKI->Data == NULL ||
4473089Swyllys 		spki == NULL)
4483089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
4493089Swyllys 
4503089Swyllys 	(void) memset(spki, 0, sizeof (KMF_X509_SPKI));
4513089Swyllys 
4523089Swyllys 	bv.bv_val = (char *)EncodedSPKI->Data;
4533089Swyllys 	bv.bv_len = EncodedSPKI->Length;
4543089Swyllys 
4553089Swyllys 	if ((asn1 = kmfder_init(&bv)) == NULL)
4563089Swyllys 		return (KMF_ERR_MEMORY);
4573089Swyllys 
4583089Swyllys 	ret = get_spki(asn1, spki);
4593089Swyllys 
4603089Swyllys cleanup:
4613089Swyllys 	if (ret != KMF_OK) {
4623089Swyllys 		free_decoded_spki(spki);
4633089Swyllys 	}
4643089Swyllys 	kmfber_free(asn1, 1);
4653089Swyllys 
4663089Swyllys 	return (ret);
4673089Swyllys }
4683089Swyllys 
4693089Swyllys KMF_RETURN
4703089Swyllys CopySPKI(KMF_X509_SPKI *src,
4713089Swyllys 		KMF_X509_SPKI **dest)
4723089Swyllys {
4733089Swyllys 	KMF_RETURN ret = KMF_OK;
4743089Swyllys 	KMF_X509_SPKI *newspki;
4753089Swyllys 
4763089Swyllys 	*dest = NULL;
4773089Swyllys 
4783089Swyllys 	newspki = malloc(sizeof (KMF_X509_SPKI));
4793089Swyllys 	if (newspki == NULL)
4803089Swyllys 		return (KMF_ERR_MEMORY);
4813089Swyllys 	(void) memset(newspki, 0, sizeof (KMF_X509_SPKI));
4823089Swyllys 
4833089Swyllys 	ret = CopyData(&src->algorithm.algorithm,
4843089Swyllys 		&newspki->algorithm.algorithm);
4853089Swyllys 	if (ret != KMF_OK)
4863089Swyllys 		goto cleanup;
4873089Swyllys 
4883089Swyllys 	ret = CopyData(&src->algorithm.parameters,
4893089Swyllys 			&newspki->algorithm.parameters);
4903089Swyllys 	if (ret != KMF_OK)
4913089Swyllys 		goto cleanup;
4923089Swyllys 
4933089Swyllys 	ret = CopyData(&src->subjectPublicKey,
4943089Swyllys 		&newspki->subjectPublicKey);
4953089Swyllys 	if (ret != KMF_OK)
4963089Swyllys 		goto cleanup;
4973089Swyllys 
4983089Swyllys 	*dest = newspki;
4993089Swyllys cleanup:
5003089Swyllys 	if (ret != KMF_OK) {
5013089Swyllys 		if (newspki)
5023089Swyllys 			free_decoded_spki(newspki);
5033089Swyllys 	}
5043089Swyllys 	return (ret);
5053089Swyllys }
5063089Swyllys 
5073089Swyllys static KMF_RETURN
5083089Swyllys encode_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
5093089Swyllys {
5103089Swyllys 	int ret;
5113089Swyllys 
5123089Swyllys 	ret = kmfber_printf(asn1, "{tsts}",
5133089Swyllys 			validity->notBefore.timeType,
5143089Swyllys 			validity->notBefore.time.Data,
5153089Swyllys 			validity->notAfter.timeType,
5163089Swyllys 			validity->notAfter.time.Data);
5173089Swyllys 
5183089Swyllys 	if (ret == -1)
5193089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
5203089Swyllys 
5213089Swyllys 	return (KMF_OK);
5223089Swyllys }
5233089Swyllys 
5243089Swyllys static KMF_RETURN
5253089Swyllys get_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
5263089Swyllys {
5273089Swyllys 	KMF_RETURN ret = KMF_OK;
5283089Swyllys 	int tag;
5293089Swyllys 	int t1, t2;
5303089Swyllys 	ber_len_t size;
5313089Swyllys 	char *t1str, *t2str;
5323089Swyllys 
5333089Swyllys 	(void) memset(validity, 0, sizeof (KMF_X509_VALIDITY));
5343089Swyllys 
5353089Swyllys 	tag = kmfber_next_element(asn1, &size, NULL);
5363089Swyllys 	if (tag != BER_CONSTRUCTED_SEQUENCE) {
5373089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
5383089Swyllys 	}
5393089Swyllys 
5403089Swyllys 	if (kmfber_scanf(asn1, "{tata}", &t1, &t1str, &t2, &t2str) == -1) {
5413089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
5423089Swyllys 	}
5433089Swyllys 
5443089Swyllys 	validity->notBefore.timeType = t1;
5453089Swyllys 	validity->notBefore.time.Data = (uchar_t *)t1str;
5463089Swyllys 	validity->notBefore.time.Length = strlen(t1str);
5473089Swyllys 
5483089Swyllys 	validity->notAfter.timeType = t2;
5493089Swyllys 	validity->notAfter.time.Data = (uchar_t *)t2str;
5503089Swyllys 	validity->notAfter.time.Length = strlen(t2str);
5513089Swyllys 
5523089Swyllys 	return (ret);
5533089Swyllys }
5543089Swyllys 
5553089Swyllys KMF_RETURN
5563089Swyllys AddRDN(KMF_X509_NAME *name, KMF_X509_RDN *newrdn)
5573089Swyllys {
5583089Swyllys 	KMF_RETURN ret = KMF_OK;
5593089Swyllys 	KMF_X509_RDN *rdnslot = NULL;
5603089Swyllys 
5613089Swyllys 	/* Add new RDN record to existing list */
5623089Swyllys 	name->numberOfRDNs++;
5633089Swyllys 	name->RelativeDistinguishedName =
5643089Swyllys 			realloc(name->RelativeDistinguishedName,
5653089Swyllys 			name->numberOfRDNs * sizeof (KMF_X509_RDN));
5663089Swyllys 
5673089Swyllys 	if (name->RelativeDistinguishedName == NULL) {
5683089Swyllys 		ret = KMF_ERR_MEMORY;
5693089Swyllys 		goto cleanup;
5703089Swyllys 	}
5713089Swyllys 	rdnslot = &name->RelativeDistinguishedName[name->numberOfRDNs-1];
5723089Swyllys 
5733089Swyllys 	if (newrdn) {
5743089Swyllys 		(void) memcpy(rdnslot, newrdn, sizeof (KMF_X509_RDN));
5753089Swyllys 	} else {
5763089Swyllys 		rdnslot->numberOfPairs = 0;
5773089Swyllys 		rdnslot->AttributeTypeAndValue = NULL;
5783089Swyllys 	}
5793089Swyllys 
5803089Swyllys cleanup:
5813089Swyllys 	/* No cleanup needed here */
5823089Swyllys 	return (ret);
5833089Swyllys }
5843089Swyllys 
5853089Swyllys static KMF_RETURN
5863089Swyllys encode_rdn(BerElement *asn1, KMF_X509_NAME *name)
5873089Swyllys {
5883089Swyllys 	KMF_RETURN ret = KMF_OK;
5893089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *attrtvpair = NULL;
5903089Swyllys 	int i;
5913089Swyllys 	KMF_X509_RDN *rdn;
5923089Swyllys 
5933089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
5943089Swyllys 		ret = KMF_ERR_MEMORY;
5953089Swyllys 		goto cleanup;
5963089Swyllys 	}
5973089Swyllys 
5983089Swyllys 	for (i = 0; i < name->numberOfRDNs; i++) {
5993089Swyllys 		if (kmfber_printf(asn1, "[") == -1) {
6003089Swyllys 			ret = KMF_ERR_MEMORY;
6013089Swyllys 			goto cleanup;
6023089Swyllys 		}
6033089Swyllys 		rdn = &name->RelativeDistinguishedName[i];
6043089Swyllys 		attrtvpair = rdn->AttributeTypeAndValue;
6053089Swyllys 
6063089Swyllys 		if (rdn->numberOfPairs > 0) {
6073089Swyllys 			if (kmfber_printf(asn1, "{Dto}",
6083089Swyllys 				&attrtvpair->type,
6093089Swyllys 				attrtvpair->valueType,
6103089Swyllys 				attrtvpair->value.Data,
6113089Swyllys 				attrtvpair->value.Length) == -1) {
6123089Swyllys 				ret = KMF_ERR_MEMORY;
6133089Swyllys 				goto cleanup;
6143089Swyllys 			}
6153089Swyllys 		}
6163089Swyllys 		if (kmfber_printf(asn1, "]") == -1) {
6173089Swyllys 			ret = KMF_ERR_MEMORY;
6183089Swyllys 			goto cleanup;
6193089Swyllys 		}
6203089Swyllys 	}
6213089Swyllys 
6223089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
6233089Swyllys 		ret = KMF_ERR_MEMORY;
6243089Swyllys 		goto cleanup;
6253089Swyllys 	}
6263089Swyllys 
6273089Swyllys cleanup:
6283089Swyllys 	/* No cleanup needed here */
6293089Swyllys 
6303089Swyllys 	return (ret);
6313089Swyllys }
6323089Swyllys 
6333089Swyllys 
6343089Swyllys KMF_RETURN
6353089Swyllys CopyRDN(KMF_X509_NAME *srcname, KMF_X509_NAME **destname)
6363089Swyllys {
6373089Swyllys 	KMF_RETURN ret = KMF_OK;
6383089Swyllys 	KMF_X509_NAME 		*newname = NULL;
6393089Swyllys 	KMF_X509_RDN 		*rdn, *dstrdn;
6403089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
6413089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *srcav = NULL;
6423089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *dstav = NULL;
6433089Swyllys 	int i, j;
6443089Swyllys 
6453089Swyllys 	newname = malloc(sizeof (KMF_X509_NAME));
6463089Swyllys 	if (newname == NULL)
6473089Swyllys 		return (KMF_ERR_MEMORY);
6483089Swyllys 	(void) memset(newname, 0, sizeof (KMF_X509_NAME));
6493089Swyllys 
6503089Swyllys 	newname->numberOfRDNs = srcname->numberOfRDNs;
6513089Swyllys 	newname->RelativeDistinguishedName = malloc(newname->numberOfRDNs *
6523089Swyllys 			sizeof (KMF_X509_RDN));
6533089Swyllys 	if (newname->RelativeDistinguishedName == NULL) {
6543089Swyllys 		free(newname);
6553089Swyllys 		return (KMF_ERR_MEMORY);
6563089Swyllys 	}
6573089Swyllys 	/* Copy each RDN in the list */
6583089Swyllys 	for (i = 0; i < newname->numberOfRDNs; i++) {
6593089Swyllys 		rdn = &srcname->RelativeDistinguishedName[i];
6603089Swyllys 
6613089Swyllys 		dstrdn = &newname->RelativeDistinguishedName[i];
6623089Swyllys 		(void) memset(dstrdn, 0, sizeof (KMF_X509_RDN));
6633089Swyllys 
6643089Swyllys 		dstrdn->numberOfPairs = rdn->numberOfPairs;
6653089Swyllys 		if (dstrdn->numberOfPairs > 0) {
6663089Swyllys 			av = malloc(dstrdn->numberOfPairs *
6673089Swyllys 				sizeof (KMF_X509_TYPE_VALUE_PAIR));
6683089Swyllys 			if (av == NULL) {
6693089Swyllys 				ret = KMF_ERR_MEMORY;
6703089Swyllys 				goto cleanup;
6713089Swyllys 			}
6723089Swyllys 			(void) memset(av, 0, dstrdn->numberOfPairs *
6733089Swyllys 				sizeof (KMF_X509_TYPE_VALUE_PAIR));
6743089Swyllys 
6753089Swyllys 			dstrdn->AttributeTypeAndValue = av;
6763089Swyllys 			if (av == NULL) {
6773089Swyllys 				ret = KMF_ERR_MEMORY;
6783089Swyllys 				goto cleanup;
6793089Swyllys 			}
6803089Swyllys 			/* Copy each A/V pair in the list */
6813089Swyllys 			for (j = 0; j < dstrdn->numberOfPairs; j++) {
6823089Swyllys 				srcav = &rdn->AttributeTypeAndValue[j];
6833089Swyllys 				dstav = &dstrdn->AttributeTypeAndValue[j];
6843089Swyllys 				if ((ret = CopyData(&srcav->type,
6853089Swyllys 					&dstav->type)) != KMF_OK)
6863089Swyllys 					goto cleanup;
6873089Swyllys 				dstav->valueType = srcav->valueType;
6883089Swyllys 				if ((ret = CopyData(&srcav->value,
6893089Swyllys 					&dstav->value)) != KMF_OK)
6903089Swyllys 					goto cleanup;
6913089Swyllys 			}
6923089Swyllys 		} else {
6933089Swyllys 			dstrdn->AttributeTypeAndValue = NULL;
6943089Swyllys 		}
6953089Swyllys 	}
6963089Swyllys 	*destname = newname;
6973089Swyllys 
6983089Swyllys cleanup:
6993089Swyllys 	if (ret != KMF_OK) {
7003089Swyllys 		if (newname)
7013089Swyllys 			free_rdn_data(newname);
7023089Swyllys 
7033089Swyllys 		free(newname);
7043089Swyllys 		*destname = NULL;
7053089Swyllys 	}
7063089Swyllys 	return (ret);
7073089Swyllys }
7083089Swyllys 
7093089Swyllys #define	VALID_DIRECTORYSTRING_TAG(t) ( \
7103089Swyllys 	(t == BER_UTF8_STRING) || \
7113089Swyllys 	(t == BER_PRINTABLE_STRING) || \
7123089Swyllys 	(t == BER_IA5STRING) || \
7133089Swyllys 	(t == BER_T61STRING) || \
7143089Swyllys 	(t == BER_BMP_STRING) || \
7153089Swyllys 	(t == BER_UNIVERSAL_STRING))
7163089Swyllys 
7173089Swyllys static KMF_RETURN
7183089Swyllys get_rdn(BerElement *asn1, KMF_X509_NAME *name)
7193089Swyllys {
7203089Swyllys 	KMF_RETURN ret = KMF_OK;
7213089Swyllys 	ber_len_t size;
7223089Swyllys 	char *end;
7233089Swyllys 	int tag;
7243089Swyllys 	BerValue AttrOID;
7253089Swyllys 	char *AttrValue = NULL;
7263089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *newpair = NULL;
7273089Swyllys 	KMF_X509_RDN 		newrdn;
7283089Swyllys 
7293089Swyllys 	/*
7303089Swyllys 	 * AttributeType	::=  OBJECT IDENTIFIER
7313089Swyllys 	 * AttributeValue	::=  ANY
7323089Swyllys 	 *
7333089Swyllys 	 * AttributeTypeAndValue	::=  SEQUENCE {
7343089Swyllys 	 *	type    AttributeType,
7353089Swyllys 	 *	value   AttributeValue }
7363089Swyllys 	 *
7373089Swyllys 	 * Name ::= CHOICE { -- only one possibility for now --
7383089Swyllys 	 * 		rdnSequence  RDNSequence }
7393089Swyllys 	 *
7403089Swyllys 	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
7413089Swyllys 	 *
7423089Swyllys 	 * DistinguishedName ::=   RDNSequence
7433089Swyllys 	 *
7443089Swyllys 	 * RelativeDistinguishedName  ::=
7453089Swyllys 	 *		 SET SIZE (1 .. MAX) OF AttributeTypeAndValue
7463089Swyllys 	 *
7473089Swyllys 	 */
7483089Swyllys 
7493089Swyllys 	name->numberOfRDNs = 0;
7503089Swyllys 	name->RelativeDistinguishedName = NULL;
7513089Swyllys 
7523089Swyllys 	/* Get the beginning of the RDN Set and a ptr to the end */
7533089Swyllys 	tag = kmfber_first_element(asn1, &size, &end);
7543089Swyllys 	if (tag != BER_CONSTRUCTED_SET) {
7553089Swyllys 		goto cleanup;
7563089Swyllys 	}
7573089Swyllys 
7583089Swyllys 	/* Walk through the individual SET items until the "end" is reached */
7593089Swyllys 	while ((tag = kmfber_next_element(asn1, &size, end)) ==
7603089Swyllys 		BER_CONSTRUCTED_SET) {
7613089Swyllys 		/* Skip over the SET tag */
7623089Swyllys 		if (kmfber_scanf(asn1, "T", &tag) == -1) {
7633089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
7643089Swyllys 			break;
7653089Swyllys 		}
7663089Swyllys 
7673089Swyllys 		/* An "empty" set member means we tack on an empty node */
7683089Swyllys 		if (size == 0) {
7693089Swyllys 			if ((ret = AddRDN(name, NULL)) != KMF_OK)
7703089Swyllys 				goto cleanup;
7713089Swyllys 			continue;
7723089Swyllys 		}
7733089Swyllys 
7743089Swyllys 		/* Attr OID and peek at the next tag and field length */
7753089Swyllys 		if (kmfber_scanf(asn1, "{Dtl", &AttrOID, &tag, &size) == -1) {
7763089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
7773089Swyllys 			break;
7783089Swyllys 		}
7793089Swyllys 
7803089Swyllys 		if (!(VALID_DIRECTORYSTRING_TAG(tag))) {
7813089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
7823089Swyllys 			break;
7833089Swyllys 		}
7843089Swyllys 
7853089Swyllys 		if (kmfber_scanf(asn1, "a}]", &AttrValue) == -1) {
7863089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
7873089Swyllys 			break;
7883089Swyllys 		}
7893089Swyllys 
7903089Swyllys 		/* Allocate a new name/value pair record */
7913089Swyllys 		newpair = malloc(sizeof (KMF_X509_TYPE_VALUE_PAIR));
7923089Swyllys 		if (newpair == NULL) {
7933089Swyllys 			ret = KMF_ERR_MEMORY;
7943089Swyllys 			break;
7953089Swyllys 		}
7963089Swyllys 		(void) memset(newpair, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
7973089Swyllys 		newpair->type.Data = (uchar_t *)AttrOID.bv_val;
7983089Swyllys 		newpair->type.Length = AttrOID.bv_len;
7993089Swyllys 		newpair->valueType = tag; /* what kind of string is it? */
8003089Swyllys 		newpair->value.Data = (uchar_t *)AttrValue;
8013089Swyllys 		newpair->value.Length = strlen(AttrValue);
8023089Swyllys 
8033089Swyllys 		(void) memset(&newrdn, 0, sizeof (KMF_X509_RDN));
8043089Swyllys 		newrdn.numberOfPairs = 1;
8053089Swyllys 		newrdn.AttributeTypeAndValue = newpair;
8063089Swyllys 
8073089Swyllys 		if ((ret = AddRDN(name, &newrdn)) != KMF_OK)
8083089Swyllys 			break;
8093089Swyllys 	}
8103089Swyllys 
8113089Swyllys cleanup:
8123089Swyllys 	if (ret != KMF_OK) {
8133089Swyllys 		free_rdn_data(name);
8143089Swyllys 	}
8153089Swyllys 	return (ret);
8163089Swyllys }
8173089Swyllys 
8183089Swyllys static KMF_RETURN
8193089Swyllys set_der_integer(KMF_DATA *data, int value)
8203089Swyllys {
8213089Swyllys 	if (data == NULL)
8223089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
8233089Swyllys 
8243089Swyllys 	data->Data = malloc(sizeof (int));
8253089Swyllys 	if (data->Data == NULL)
8263089Swyllys 		return (KMF_ERR_MEMORY);
8273089Swyllys 
8283089Swyllys 	data->Length = sizeof (int);
8293089Swyllys 	(void) memcpy((void *)data->Data, (const void *)&value, sizeof (int));
8303089Swyllys 
8313089Swyllys 	return (KMF_OK);
8323089Swyllys }
8333089Swyllys 
8343089Swyllys static KMF_RETURN
8353089Swyllys set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
8363089Swyllys {
8373089Swyllys 	if (data == NULL || bigint == NULL)
8383089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
8393089Swyllys 
8403089Swyllys 	data->val = malloc(bigint->len);
8413089Swyllys 	if (data->val == NULL)
8423089Swyllys 		return (KMF_ERR_MEMORY);
8433089Swyllys 
8443089Swyllys 	data->len = bigint->len;
8453089Swyllys 	(void) memcpy((void *)data->val, (const void *)bigint->val,
8463089Swyllys 		bigint->len);
8473089Swyllys 
8483089Swyllys 	return (KMF_OK);
8493089Swyllys }
8503089Swyllys 
8513089Swyllys static KMF_RETURN
8523089Swyllys encode_uniqueid(BerElement *asn1, int tag, KMF_DATA *id)
8533089Swyllys {
8543089Swyllys 	KMF_RETURN ret = KMF_OK;
8553089Swyllys 	uint32_t len;
8563089Swyllys 
8573089Swyllys 	len = kmfber_calc_taglen(BER_BIT_STRING) +
8583089Swyllys 		kmfber_calc_lenlen(id->Length * 8) + id->Length;
8593089Swyllys 	if (kmfber_printf(asn1, "TlB", tag, len,
8603089Swyllys 		id->Data, id->Length * 8) == -1)
8613089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
8623089Swyllys 
8633089Swyllys 	return (ret);
8643089Swyllys }
8653089Swyllys 
8663089Swyllys static KMF_RETURN
8673089Swyllys encode_extension_list(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
8683089Swyllys {
8693089Swyllys 	KMF_RETURN ret = KMF_OK;
8703089Swyllys 	int i;
8713089Swyllys 
8723089Swyllys 	for (i = 0; i < extns->numberOfExtensions; i++) {
8733089Swyllys 		BerValue v;
8743089Swyllys 		v.bv_val = (char *)extns->extensions[i].extnId.Data;
8753089Swyllys 		v.bv_len = extns->extensions[i].extnId.Length;
8763089Swyllys 
8773089Swyllys 		if (kmfber_printf(asn1, "{D", &v) == -1)  {
8783089Swyllys 			ret = KMF_ERR_ENCODING;
8793089Swyllys 			goto cleanup;
8803089Swyllys 		}
8813089Swyllys 
8823089Swyllys 		if (extns->extensions[i].critical) {
8833089Swyllys 			if (kmfber_printf(asn1, "b",
8843089Swyllys 				extns->extensions[i].critical) == -1) {
8853089Swyllys 				ret = KMF_ERR_ENCODING;
8863089Swyllys 				goto cleanup;
8873089Swyllys 			}
8883089Swyllys 		}
8893089Swyllys 
8903089Swyllys 		if (kmfber_printf(asn1, "o}",
8913089Swyllys 			extns->extensions[i].BERvalue.Data,
8923089Swyllys 			extns->extensions[i].BERvalue.Length) == -1) {
8933089Swyllys 			ret = KMF_ERR_ENCODING;
8943089Swyllys 			goto cleanup;
8953089Swyllys 		}
8963089Swyllys 	}
8973089Swyllys cleanup:
8983089Swyllys 	return (ret);
8993089Swyllys }
9003089Swyllys 
9013089Swyllys static KMF_RETURN
9023089Swyllys encode_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
9033089Swyllys {
9043089Swyllys 	KMF_RETURN ret = KMF_OK;
9053089Swyllys 	BerElement *extn = NULL;
9063089Swyllys 	BerValue *extnvalue = NULL;
9073089Swyllys 
9083089Swyllys 	extn = kmfder_alloc();
9093089Swyllys 	if (extn == NULL)
9103089Swyllys 		return (KMF_ERR_MEMORY);
9113089Swyllys 
9123089Swyllys 	if (kmfber_printf(extn, "{") == -1) {
9133089Swyllys 		ret = KMF_ERR_ENCODING;
9143089Swyllys 		goto cleanup;
9153089Swyllys 	}
9163089Swyllys 
9173089Swyllys 	ret = encode_extension_list(extn, extns);
9183089Swyllys 
9193089Swyllys 	if (kmfber_printf(extn, "}") == -1) {
9203089Swyllys 		ret = KMF_ERR_ENCODING;
9213089Swyllys 		goto cleanup;
9223089Swyllys 	}
9233089Swyllys 
9243089Swyllys 	if (kmfber_flatten(extn, &extnvalue) == -1) {
9253089Swyllys 		ret = KMF_ERR_MEMORY;
9263089Swyllys 		goto cleanup;
9273089Swyllys 	}
9283089Swyllys 
9293089Swyllys 	if (kmfber_printf(asn1, "Tl", 0xA3, extnvalue->bv_len) == -1) {
9303089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9313089Swyllys 		goto cleanup;
9323089Swyllys 	}
9333089Swyllys 
9343089Swyllys 	if (kmfber_write(asn1, extnvalue->bv_val, extnvalue->bv_len, 0) == -1) {
9353089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9363089Swyllys 		goto cleanup;
9373089Swyllys 	}
9383089Swyllys 
9393089Swyllys cleanup:
9403089Swyllys 	kmfber_free(extn, 1);
9413089Swyllys 	if (extnvalue != NULL)
9423089Swyllys 		kmfber_bvfree(extnvalue);
9433089Swyllys 
9443089Swyllys 	return (ret);
9453089Swyllys }
9463089Swyllys 
9473089Swyllys static KMF_RETURN
9483089Swyllys get_one_extension(BerElement *asn1, KMF_X509_EXTENSION **retex, char *end)
9493089Swyllys {
9503089Swyllys 	KMF_RETURN ret = KMF_OK;
9513089Swyllys 	ber_len_t size;
9523089Swyllys 	int  critical, tag;
9533089Swyllys 	KMF_X509_EXTENSION *ex = NULL;
9543089Swyllys 	BerValue extOID;
9553089Swyllys 	BerValue extValue;
9563089Swyllys 	BerElement *extnber = NULL;
9573089Swyllys 
9583089Swyllys 	if (kmfber_scanf(asn1, "T", &tag) == -1) {
9593089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9603089Swyllys 		goto cleanup;
9613089Swyllys 	}
9623089Swyllys 
9633089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
9643089Swyllys 	if (tag != BER_OBJECT_IDENTIFIER) {
9653089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9663089Swyllys 		goto cleanup;
9673089Swyllys 	}
9683089Swyllys 	if (kmfber_scanf(asn1, "D", &extOID) == -1) {
9693089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9703089Swyllys 		goto cleanup;
9713089Swyllys 	}
9723089Swyllys 
9733089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
9743089Swyllys 	if (tag != BER_BOOLEAN) {
9753089Swyllys 		critical = 0;
9763089Swyllys 		if (tag != BER_OCTET_STRING)
9773089Swyllys 			goto cleanup;
9783089Swyllys 	} else {
9793089Swyllys 		if (kmfber_scanf(asn1, "b", &critical) == -1)
9803089Swyllys 			goto cleanup;
9813089Swyllys 	}
9823089Swyllys 
9833089Swyllys 	tag = kmfber_next_element(asn1, &size, end);
9843089Swyllys 	if (tag != BER_OCTET_STRING)  {
9853089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9863089Swyllys 		goto cleanup;
9873089Swyllys 	}
9883089Swyllys 	if (kmfber_scanf(asn1, "o", &extValue) == -1)  {
9893089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
9903089Swyllys 		goto cleanup;
9913089Swyllys 	}
9923089Swyllys 
9933089Swyllys 	/* allocate a new Extension record */
9943089Swyllys 	ex = malloc(sizeof (KMF_X509_EXTENSION));
9953089Swyllys 	if (ex == NULL) {
9963089Swyllys 		ret = KMF_ERR_MEMORY;
9973089Swyllys 		goto cleanup;
9983089Swyllys 	}
9993089Swyllys 	(void) memset(ex, 0, sizeof (ex));
10003089Swyllys 
10013089Swyllys 	ex->extnId.Data = (uchar_t *)extOID.bv_val;
10023089Swyllys 	ex->extnId.Length = extOID.bv_len;
10033089Swyllys 	ex->critical = critical;
10043089Swyllys 	ex->format = KMF_X509_DATAFORMAT_ENCODED;
10053089Swyllys 	ex->BERvalue.Data = (uchar_t *)extValue.bv_val;
10063089Swyllys 	ex->BERvalue.Length = extValue.bv_len;
10073089Swyllys 
10083089Swyllys 	/* Tag and value is a little tricky */
10093089Swyllys 	ex->value.tagAndValue = malloc(sizeof (KMF_X509EXT_TAGandVALUE));
10103089Swyllys 	if (ex->value.tagAndValue == NULL) {
10113089Swyllys 		ret = KMF_ERR_MEMORY;
10123089Swyllys 		goto cleanup;
10133089Swyllys 	}
10143089Swyllys 	(void) memset(ex->value.tagAndValue, 0,
10153089Swyllys 		sizeof (KMF_X509EXT_TAGandVALUE));
10163089Swyllys 
10173089Swyllys 	/* Parse the Extension value field */
10183089Swyllys 	extnber = kmfder_init(&extValue);
10193089Swyllys 	if (extnber == NULL) {
10203089Swyllys 		ret = KMF_ERR_MEMORY;
10213089Swyllys 		goto cleanup;
10223089Swyllys 	}
10233089Swyllys 
10243089Swyllys 	/* Get the tag and length of the extension field */
10253089Swyllys 	if (kmfber_scanf(extnber, "tl", &tag, &size) == -1) {
10263089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
10273089Swyllys 		goto cleanup;
10283089Swyllys 	}
10293089Swyllys 
10303089Swyllys 	if (kmfber_scanf(extnber, "T", &tag) == -1) {
10313089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
10323089Swyllys 		goto cleanup;
10333089Swyllys 	}
10343089Swyllys 
10353089Swyllys 	ex->value.tagAndValue->value.Data = malloc(size);
10363089Swyllys 	ex->value.tagAndValue->value.Length = size;
10373089Swyllys 	size = kmfber_read(extnber,
10383089Swyllys 		(char *)ex->value.tagAndValue->value.Data, size);
10393089Swyllys 	if (size != ex->value.tagAndValue->value.Length) {
10403089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
10413089Swyllys 		goto cleanup;
10423089Swyllys 	}
10433089Swyllys 	kmfber_free(extnber, 1);
10443089Swyllys 	ex->value.tagAndValue->type = tag;
10453089Swyllys 
10463089Swyllys 	*retex = ex;
10473089Swyllys cleanup:
10483089Swyllys 	if (ret != KMF_OK) {
10493089Swyllys 		if (ex != NULL)
10503089Swyllys 			free_one_extension(ex);
10513089Swyllys 	}
10523089Swyllys 
10533089Swyllys 	return (ret);
10543089Swyllys }
10553089Swyllys 
10563089Swyllys static KMF_RETURN
10573089Swyllys get_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
10583089Swyllys {
10593089Swyllys 	KMF_RETURN ret = KMF_OK;
10603089Swyllys 	ber_len_t size;
10613089Swyllys 	char *end = NULL;
10623089Swyllys 	KMF_X509_EXTENSION *ex = NULL;
10633089Swyllys 
10643089Swyllys 	/*
10653089Swyllys 	 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
10663089Swyllys 	 *
10673089Swyllys 	 * Extension  ::=  SEQUENCE  {
10683089Swyllys 	 *	extnID		OBJECT IDENTIFIER,
10693089Swyllys 	 *	critical	BOOLEAN DEFAULT FALSE,
10703089Swyllys 	 *	extnValue	OCTET STRING  }
10713089Swyllys 	 *
10723089Swyllys 	 * { {{D}Bo}, ... }
10733089Swyllys 	 */
10743089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
10753089Swyllys 		BER_CONSTRUCTED_SEQUENCE)
10763089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
10773089Swyllys 
10783089Swyllys 	while (kmfber_next_element(asn1, &size, end) ==
10793089Swyllys 		BER_CONSTRUCTED_SEQUENCE) {
10803089Swyllys 		ret = get_one_extension(asn1, &ex, end);
10813089Swyllys 		if (ret != KMF_OK)
10823089Swyllys 			goto cleanup;
10833089Swyllys 
10843089Swyllys 		extns->numberOfExtensions++;
10853089Swyllys 		extns->extensions = realloc(extns->extensions,
10863089Swyllys 			extns->numberOfExtensions *
10873089Swyllys 			sizeof (KMF_X509_EXTENSION));
10883089Swyllys 		if (extns->extensions == NULL) {
10893089Swyllys 			ret = KMF_ERR_MEMORY;
10903089Swyllys 			break;
10913089Swyllys 		}
10923089Swyllys 
10933089Swyllys 		extns->extensions[extns->numberOfExtensions-1] = *ex;
10943089Swyllys 		free(ex);
10953089Swyllys 	}
10963089Swyllys 
10973089Swyllys cleanup:
10983089Swyllys 	if (ret != KMF_OK)
10993089Swyllys 		free_extensions(extns);
11003089Swyllys 
11013089Swyllys 	return (ret);
11023089Swyllys }
11033089Swyllys 
11043089Swyllys KMF_RETURN
11053089Swyllys decode_tbscert_data(BerElement *asn1,
11063089Swyllys 	KMF_X509_TBS_CERT **signed_cert_ptr_ptr)
11073089Swyllys {
11083089Swyllys 	KMF_RETURN ret = KMF_OK;
11093089Swyllys 	KMF_X509_TBS_CERT	*tbscert = NULL;
11103089Swyllys 	int tag, version;
11113089Swyllys 	struct berval *bvserno = NULL;
11123089Swyllys 	KMF_BIGINT serno;
11133089Swyllys 
11143089Swyllys 	if (kmfber_scanf(asn1, "{t", &tag) == -1) {
11153089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11163089Swyllys 		goto cleanup;
11173089Swyllys 	}
11183089Swyllys 
11193089Swyllys 	/* Version number is optional */
11203089Swyllys 	if (tag == 0xA0) {
11213089Swyllys 		if (kmfber_scanf(asn1, "Ti", &tag, &version) == -1) {
11223089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
11233089Swyllys 			goto cleanup;
11243089Swyllys 		}
11253089Swyllys 	} else {
11263089Swyllys 		version = 0; /* DEFAULT v1 (0) */
11273089Swyllys 	}
11283089Swyllys 
11293089Swyllys 	/* Now get the serial number, it is not optional */
11303089Swyllys 	if (kmfber_scanf(asn1, "I", &bvserno) == -1) {
11313089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
11323089Swyllys 		goto cleanup;
11333089Swyllys 	} else {
11343089Swyllys 		serno.val = (uchar_t *)bvserno->bv_val;
11353089Swyllys 		serno.len = bvserno->bv_len;
11363089Swyllys 	}
11373089Swyllys 
11383089Swyllys 	tbscert = malloc(sizeof (KMF_X509_TBS_CERT));
11393089Swyllys 	if (!tbscert) {
11403089Swyllys 		ret = KMF_ERR_MEMORY;
11413089Swyllys 		goto cleanup;
11423089Swyllys 	}
11433089Swyllys 
11443089Swyllys 	(void) memset(tbscert, 0, sizeof (KMF_X509_TBS_CERT));
11453089Swyllys 
11463089Swyllys 	if ((ret = set_der_integer(&tbscert->version, version)) != KMF_OK)
11473089Swyllys 		goto cleanup;
11483089Swyllys 
11493089Swyllys 	if ((ret = set_bigint(&tbscert->serialNumber, &serno)) != KMF_OK)
11503089Swyllys 		goto cleanup;
11513089Swyllys 
11523089Swyllys 	if ((ret = get_algoid(asn1, &tbscert->signature)) != KMF_OK)
11533089Swyllys 		goto cleanup;
11543089Swyllys 
11553089Swyllys 	if ((ret = get_rdn(asn1, &tbscert->issuer)) != KMF_OK)
11563089Swyllys 		goto cleanup;
11573089Swyllys 
11583089Swyllys 	if ((ret = get_validity(asn1, &tbscert->validity)) != KMF_OK)
11593089Swyllys 		goto cleanup;
11603089Swyllys 
11613089Swyllys 	if ((ret = get_rdn(asn1, &tbscert->subject)) != KMF_OK)
11623089Swyllys 		goto cleanup;
11633089Swyllys 
11643089Swyllys 	if ((ret = get_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
11653089Swyllys 		goto cleanup;
11663089Swyllys 
11673089Swyllys 	/* Check for the optional fields */
11683089Swyllys 	tbscert->extensions.numberOfExtensions = 0;
11693089Swyllys 	tbscert->extensions.extensions = NULL;
11703089Swyllys 
11713089Swyllys 	while ((kmfber_scanf(asn1, "t", &tag)) != -1 &&
11723089Swyllys 			(tag == 0xA1 || tag == 0xA2 || tag == 0xA3)) {
11733089Swyllys 		char *optfield;
11743089Swyllys 		ber_len_t len;
11753089Swyllys 
11763089Swyllys 		/* consume the tag and length */
11773089Swyllys 		(void) kmfber_scanf(asn1, "T", &tag);
11783089Swyllys 		switch (tag) {
11793089Swyllys 			case 0xA1:
11803089Swyllys 				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
11813089Swyllys 					BER_BIT_STRING) {
11823089Swyllys 					ret = KMF_ERR_BAD_CERT_FORMAT;
11833089Swyllys 					goto cleanup;
11843089Swyllys 				}
11853089Swyllys 				tbscert->issuerUniqueIdentifier.Data =
11863089Swyllys 					(uchar_t *)optfield;
11873089Swyllys 				tbscert->issuerUniqueIdentifier.Length =
11883089Swyllys 					len / 8;
11893089Swyllys 				break;
11903089Swyllys 			case 0xA2:
11913089Swyllys 				if (kmfber_scanf(asn1, "B", &optfield, &len) !=
11923089Swyllys 					BER_BIT_STRING) {
11933089Swyllys 					ret = KMF_ERR_BAD_CERT_FORMAT;
11943089Swyllys 					goto cleanup;
11953089Swyllys 				}
11963089Swyllys 				tbscert->subjectUniqueIdentifier.Data =
11973089Swyllys 					(uchar_t *)optfield;
11983089Swyllys 				tbscert->subjectUniqueIdentifier.Length =
11993089Swyllys 					len / 8;
12003089Swyllys 				break;
12013089Swyllys 			case 0xA3:
12023089Swyllys 			ret = get_extensions(asn1, &tbscert->extensions);
12033089Swyllys 			break;
12043089Swyllys 		}
12053089Swyllys 	}
12063089Swyllys 
12073089Swyllys 	*signed_cert_ptr_ptr = tbscert;
12083089Swyllys 
12093089Swyllys cleanup:
12103089Swyllys 	if (bvserno != NULL) {
12113089Swyllys 		free(bvserno->bv_val);
12123089Swyllys 		free(bvserno);
12133089Swyllys 	}
12143089Swyllys 	if (ret != KMF_OK) {
12153089Swyllys 		if (tbscert) {
12163089Swyllys 			free_tbscert(tbscert);
12173089Swyllys 			free(tbscert);
12183089Swyllys 		}
12193089Swyllys 		*signed_cert_ptr_ptr = NULL;
12203089Swyllys 	}
12213089Swyllys 	return (ret);
12223089Swyllys }
12233089Swyllys 
12243089Swyllys KMF_RETURN
12253089Swyllys DerDecodeTbsCertificate(const KMF_DATA *Value,
12263089Swyllys 	KMF_X509_TBS_CERT **tbscert)
12273089Swyllys {
12283089Swyllys 	KMF_RETURN ret = KMF_OK;
12293089Swyllys 	BerElement *asn1 = NULL;
12303089Swyllys 	BerValue 	rawcert;
12313089Swyllys 	KMF_X509_TBS_CERT *newcert = NULL;
12323089Swyllys 
12333089Swyllys 	if (!tbscert || !Value || !Value->Data || !Value->Length)
12343089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
12353089Swyllys 
12363089Swyllys 	rawcert.bv_val = (char *)Value->Data;
12373089Swyllys 	rawcert.bv_len = Value->Length;
12383089Swyllys 
12393089Swyllys 	if ((asn1 = kmfder_init(&rawcert)) == NULL)
12403089Swyllys 		return (KMF_ERR_MEMORY);
12413089Swyllys 
12423089Swyllys 	ret = decode_tbscert_data(asn1, &newcert);
12433089Swyllys 	if (ret != KMF_OK)
12443089Swyllys 		goto cleanup;
12453089Swyllys 
12463089Swyllys 	*tbscert = newcert;
12473089Swyllys 
12483089Swyllys cleanup:
12493089Swyllys 	if (ret != KMF_OK) {
12503089Swyllys 		if (newcert)
12513089Swyllys 			free_tbscert(newcert);
12523089Swyllys 		*tbscert = NULL;
12533089Swyllys 	}
12543089Swyllys 	kmfber_free(asn1, 1);
12553089Swyllys 
12563089Swyllys 	return (ret);
12573089Swyllys }
12583089Swyllys 
12593089Swyllys /*
12603089Swyllys  * Name: DerDecodeSignedCertificate
12613089Swyllys  *
12623089Swyllys  * Description:
12633089Swyllys  * DER decodes the encoded X509 certificate
12643089Swyllys  *
12653089Swyllys  * Parameters:
12663089Swyllys  * Value (input): DER encoded object that shd be decoded
12673089Swyllys  *
12683089Swyllys  * signed_cert_ptr_ptr (output) : Decoded KMF_X509_CERTIFICATE object
12693089Swyllys  */
12703089Swyllys KMF_RETURN
12713089Swyllys DerDecodeSignedCertificate(const KMF_DATA *Value,
12723089Swyllys 	KMF_X509_CERTIFICATE **signed_cert_ptr_ptr)
12733089Swyllys {
12743089Swyllys 	KMF_RETURN ret = KMF_OK;
12753089Swyllys 	BerElement *asn1 = NULL;
12763089Swyllys 	BerValue 	rawcert;
12773089Swyllys 	ber_tag_t	tag;
12783089Swyllys 	ber_len_t	size;
12793089Swyllys 	char		*end = NULL;
12803089Swyllys 	char		*signature;
12813089Swyllys 	KMF_X509_TBS_CERT	*tbscert = NULL;
12823089Swyllys 	KMF_X509_CERTIFICATE *certptr = NULL;
12833089Swyllys 
12843089Swyllys 	if (!signed_cert_ptr_ptr || !Value || !Value->Data || !Value->Length)
12853089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
12863089Swyllys 
12873089Swyllys 	rawcert.bv_val = (char *)Value->Data;
12883089Swyllys 	rawcert.bv_len = Value->Length;
12893089Swyllys 
12903089Swyllys 	if ((asn1 = kmfder_init(&rawcert)) == NULL)
12913089Swyllys 		return (KMF_ERR_MEMORY);
12923089Swyllys 
12933089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
12943089Swyllys 		BER_CONSTRUCTED_SEQUENCE) {
12953089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
12963089Swyllys 		goto cleanup;
12973089Swyllys 	}
12983089Swyllys 
12993089Swyllys 	certptr = malloc(sizeof (KMF_X509_CERTIFICATE));
13003089Swyllys 	if (certptr == NULL) {
13013089Swyllys 		ret = KMF_ERR_MEMORY;
13023089Swyllys 		goto cleanup;
13033089Swyllys 	}
13043089Swyllys 	(void) memset(certptr, 0, sizeof (KMF_X509_CERTIFICATE));
13053089Swyllys 
13063089Swyllys 	ret = decode_tbscert_data(asn1, &tbscert);
13073089Swyllys 	if (ret != KMF_OK)
13083089Swyllys 		goto cleanup;
13093089Swyllys 
13103089Swyllys 	certptr->certificate = *tbscert;
13113089Swyllys 	free(tbscert);
13123089Swyllys 	tbscert = NULL;
13133089Swyllys 
13143089Swyllys 	/*
13153089Swyllys 	 * The signature data my not be present yet.
13163089Swyllys 	 */
13173089Swyllys 	if ((ret = get_algoid(asn1,
13183089Swyllys 		&certptr->signature.algorithmIdentifier)) == KMF_OK) {
13193089Swyllys 
13203089Swyllys 		/* Check to see if the cert has a signature yet */
13213089Swyllys 		if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
13223089Swyllys 			/* Finally, get the encrypted signature BITSTRING */
13233089Swyllys 			if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
13243089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
13253089Swyllys 				goto cleanup;
13263089Swyllys 			}
13273089Swyllys 			if (tag != BER_BIT_STRING) {
13283089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
13293089Swyllys 				goto cleanup;
13303089Swyllys 			}
13313089Swyllys 			if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
13323089Swyllys 				ret = KMF_ERR_BAD_CERT_FORMAT;
13333089Swyllys 				goto cleanup;
13343089Swyllys 			}
13353089Swyllys 			certptr->signature.encrypted.Data =
13363089Swyllys 				(uchar_t *)signature;
13373089Swyllys 			certptr->signature.encrypted.Length = size / 8;
13383089Swyllys 		} else {
13393089Swyllys 			certptr->signature.encrypted.Data = NULL;
13403089Swyllys 			certptr->signature.encrypted.Length = 0;
13413089Swyllys 		}
13423089Swyllys 	} else {
13433089Swyllys 		(void) memset(&certptr->signature, 0,
13443089Swyllys 			sizeof (certptr->signature));
13453089Swyllys 		ret = KMF_OK;
13463089Swyllys 	}
13473089Swyllys 
13483089Swyllys 	*signed_cert_ptr_ptr = certptr;
13493089Swyllys cleanup:
13503089Swyllys 	if (ret != KMF_OK) {
13513089Swyllys 		if (certptr) {
13523089Swyllys 			free_decoded_cert(certptr);
13533089Swyllys 			free(certptr);
13543089Swyllys 		}
13553089Swyllys 
13563089Swyllys 		*signed_cert_ptr_ptr = NULL;
13573089Swyllys 	}
13583089Swyllys 	if (asn1)
13593089Swyllys 		kmfber_free(asn1, 1);
13603089Swyllys 
13613089Swyllys 	return (ret);
13623089Swyllys 
13633089Swyllys }
13643089Swyllys 
13653089Swyllys KMF_RETURN
13663089Swyllys DerDecodeExtension(KMF_DATA *Data, KMF_X509_EXTENSION **extn)
13673089Swyllys {
13683089Swyllys 	KMF_RETURN ret = KMF_OK;
13693089Swyllys 	BerElement *asn1 = NULL;
13703089Swyllys 	BerValue bv;
13713089Swyllys 
13723089Swyllys 	bv.bv_val = (char *)Data->Data;
13733089Swyllys 	bv.bv_len = Data->Length;
13743089Swyllys 
13753089Swyllys 	asn1 = kmfder_init(&bv);
13763089Swyllys 	if (asn1 == NULL)
13773089Swyllys 		return (KMF_ERR_MEMORY);
13783089Swyllys 
13793089Swyllys 	ret = get_one_extension(asn1, extn, NULL);
13803089Swyllys 
13813089Swyllys cleanup:
13823089Swyllys 	if (ret != KMF_OK) {
13833089Swyllys 		if (*extn != NULL) {
13843089Swyllys 			free(*extn);
13853089Swyllys 		}
13863089Swyllys 		*extn = NULL;
13873089Swyllys 	}
13883089Swyllys 
13893089Swyllys 	kmfber_free(asn1, 1);
13903089Swyllys 	return (ret);
13913089Swyllys }
13923089Swyllys 
13933089Swyllys KMF_RETURN
13943089Swyllys DerDecodeName(KMF_DATA *encodedname, KMF_X509_NAME *name)
13953089Swyllys {
13963089Swyllys 	KMF_RETURN ret = KMF_OK;
13973089Swyllys 	BerElement *asn1 = NULL;
13983089Swyllys 	BerValue  bv;
13993089Swyllys 
14003089Swyllys 	bv.bv_val = (char *)encodedname->Data;
14013089Swyllys 	bv.bv_len = encodedname->Length;
14023089Swyllys 
14033089Swyllys 	asn1 = kmfder_init(&bv);
14043089Swyllys 	if (asn1 == NULL)
14053089Swyllys 		return (KMF_ERR_MEMORY);
14063089Swyllys 
14073089Swyllys 	(void) memset((void *)name, 0, sizeof (KMF_X509_NAME));
14083089Swyllys 
14093089Swyllys 	if ((ret = get_rdn(asn1, name)) != KMF_OK)
14103089Swyllys 		goto cleanup;
14113089Swyllys 
14123089Swyllys cleanup:
14133089Swyllys 	if (asn1)
14143089Swyllys 		kmfber_free(asn1, 1);
14153089Swyllys 	return (ret);
14163089Swyllys }
14173089Swyllys 
14183089Swyllys KMF_RETURN
14193089Swyllys DerEncodeName(KMF_X509_NAME *name, KMF_DATA *encodedname)
14203089Swyllys {
14213089Swyllys 	KMF_RETURN ret = KMF_OK;
14223089Swyllys 	BerElement *asn1 = NULL;
14233089Swyllys 	BerValue  *bv = NULL;
14243089Swyllys 
14253089Swyllys 	asn1 = kmfder_alloc();
14263089Swyllys 	if (asn1 == NULL)
14273089Swyllys 		return (KMF_ERR_MEMORY);
14283089Swyllys 
14293089Swyllys 	if ((ret = encode_rdn(asn1, name)) != KMF_OK)
14303089Swyllys 		goto cleanup;
14313089Swyllys 
14323089Swyllys 	if (kmfber_flatten(asn1, &bv) == -1) {
14333089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
14343089Swyllys 		goto cleanup;
14353089Swyllys 	}
14363089Swyllys 
14373089Swyllys 	encodedname->Data = (uchar_t *)bv->bv_val;
14383089Swyllys 	encodedname->Length = bv->bv_len;
14393089Swyllys 
14403089Swyllys cleanup:
14413089Swyllys 	if (bv)
14423089Swyllys 		free(bv);
14433089Swyllys 
14443089Swyllys 	if (asn1)
14453089Swyllys 		kmfber_free(asn1, 1);
14463089Swyllys 
14473089Swyllys 	return (ret);
14483089Swyllys }
14493089Swyllys 
14503089Swyllys static KMF_RETURN
14513089Swyllys encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert)
14523089Swyllys {
14533089Swyllys 	KMF_RETURN ret = KMF_OK;
14543089Swyllys 	uint32_t version;
14553089Swyllys 
14563089Swyllys 	/* version should be 4 bytes or less */
14573089Swyllys 	if (tbscert->version.Length > sizeof (int))
14583089Swyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
14593089Swyllys 
14603089Swyllys 	(void) memcpy(&version, tbscert->version.Data,
14613089Swyllys 		tbscert->version.Length);
14623089Swyllys 
14633089Swyllys 	/* Start the sequence and add the version */
14643089Swyllys 	if (kmfber_printf(asn1, "{Tli", 0xA0, 3, version) == -1) {
14653089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
14663089Swyllys 		goto cleanup;
14673089Swyllys 	}
14683089Swyllys 	/* Write the serial number */
14693089Swyllys 	if (kmfber_printf(asn1, "I",
14703089Swyllys 		(char *)tbscert->serialNumber.val,
14713089Swyllys 		(size_t)tbscert->serialNumber.len) == -1) {
14723089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
14733089Swyllys 		goto cleanup;
14743089Swyllys 	}
14753089Swyllys 
14763089Swyllys 	if ((ret = encode_algoid(asn1, &tbscert->signature)) != KMF_OK)
14773089Swyllys 		goto cleanup;
14783089Swyllys 
14793089Swyllys 	/* Encode the Issuer RDN */
14803089Swyllys 	if ((ret = encode_rdn(asn1, &tbscert->issuer)) != KMF_OK)
14813089Swyllys 		goto cleanup;
14823089Swyllys 
14833089Swyllys 	/* Encode the Validity fields */
14843089Swyllys 	if ((ret = encode_validity(asn1, &tbscert->validity)) != KMF_OK)
14853089Swyllys 		goto cleanup;
14863089Swyllys 
14873089Swyllys 	/* Encode the Subject RDN */
14883089Swyllys 	if ((ret = encode_rdn(asn1, &tbscert->subject)) != KMF_OK)
14893089Swyllys 		goto cleanup;
14903089Swyllys 
14913089Swyllys 	/* Encode the Subject Public Key Info */
14923089Swyllys 	if ((ret = encode_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
14933089Swyllys 		goto cleanup;
14943089Swyllys 
14953089Swyllys 	/* Optional field:  issuer Unique ID */
14963089Swyllys 	if (tbscert->issuerUniqueIdentifier.Length > 0) {
14973089Swyllys 		if ((ret = encode_uniqueid(asn1, 0xA1,
14983089Swyllys 			&tbscert->issuerUniqueIdentifier)) != KMF_OK)
14993089Swyllys 			goto cleanup;
15003089Swyllys 	}
15013089Swyllys 
15023089Swyllys 	/* Optional field:  Subject Unique ID */
15033089Swyllys 	if (tbscert->subjectUniqueIdentifier.Length > 0) {
15043089Swyllys 		if ((ret = encode_uniqueid(asn1, 0xA2,
15053089Swyllys 			&tbscert->subjectUniqueIdentifier)) != KMF_OK)
15063089Swyllys 			goto cleanup;
15073089Swyllys 	}
15083089Swyllys 
15093089Swyllys 	/* Optional field: Certificate Extensions */
15103089Swyllys 	if (tbscert->extensions.numberOfExtensions > 0) {
15113089Swyllys 		if ((ret = encode_extensions(asn1,
15123089Swyllys 			&tbscert->extensions)) != KMF_OK)
15133089Swyllys 			goto cleanup;
15143089Swyllys 	}
15153089Swyllys 
15163089Swyllys 	/* Close out the TBSCert sequence */
15173089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
15183089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
15193089Swyllys 		goto cleanup;
15203089Swyllys 	}
15213089Swyllys 
15223089Swyllys cleanup:
15233089Swyllys 	/*
15243089Swyllys 	 * Memory cleanup is done in the caller or in the individual
15253089Swyllys 	 * encoding routines.
15263089Swyllys 	 */
15273089Swyllys 
15283089Swyllys 	return (ret);
15293089Swyllys }
15303089Swyllys 
15313089Swyllys KMF_RETURN
15323089Swyllys DerEncodeTbsCertificate(KMF_X509_TBS_CERT *tbs_cert_ptr,
15333089Swyllys 	KMF_DATA *enc_tbs_cert_ptr)
15343089Swyllys {
15353089Swyllys 	KMF_RETURN ret;
15363089Swyllys 	BerElement *asn1 = NULL;
15373089Swyllys 	BerValue  *tbsdata = NULL;
15383089Swyllys 
15393089Swyllys 	asn1 = kmfder_alloc();
15403089Swyllys 	if (asn1 == NULL)
15413089Swyllys 		return (KMF_ERR_MEMORY);
15423089Swyllys 
15433089Swyllys 	enc_tbs_cert_ptr->Data = NULL;
15443089Swyllys 	enc_tbs_cert_ptr->Length = 0;
15453089Swyllys 
15463089Swyllys 	ret = encode_tbs_cert(asn1, tbs_cert_ptr);
15473089Swyllys 	if (ret != KMF_OK)
15483089Swyllys 		goto cleanup;
15493089Swyllys 
15503089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
15513089Swyllys 		ret = KMF_ERR_MEMORY;
15523089Swyllys 		goto cleanup;
15533089Swyllys 	}
15543089Swyllys 
15553089Swyllys 	enc_tbs_cert_ptr->Data = (uchar_t *)tbsdata->bv_val;
15563089Swyllys 	enc_tbs_cert_ptr->Length = tbsdata->bv_len;
15573089Swyllys 
15583089Swyllys cleanup:
15593089Swyllys 	if (ret != KMF_OK)
15603089Swyllys 		free_data(enc_tbs_cert_ptr);
15613089Swyllys 
15623089Swyllys 	if (asn1 != NULL)
15633089Swyllys 		kmfber_free(asn1, 1);
15643089Swyllys 
15653089Swyllys 	if (tbsdata)
15663089Swyllys 		free(tbsdata);
15673089Swyllys 
15683089Swyllys 	return (ret);
15693089Swyllys }
15703089Swyllys 
15713089Swyllys KMF_RETURN
15723089Swyllys DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr,
15733089Swyllys 	KMF_DATA *encodedcert)
15743089Swyllys {
15753089Swyllys 	KMF_RETURN ret = KMF_OK;
15763089Swyllys 	KMF_X509_TBS_CERT *tbscert = NULL;
15773089Swyllys 	KMF_X509_SIGNATURE		*signature = NULL;
15783089Swyllys 	BerElement	*asn1 = NULL;
15793089Swyllys 	BerValue 	*tbsdata = NULL;
15803089Swyllys 
15813089Swyllys 	if (signed_cert_ptr == NULL || encodedcert == NULL)
15823089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
15833089Swyllys 
15843089Swyllys 	encodedcert->Data = NULL;
15853089Swyllys 	encodedcert->Length = 0;
15863089Swyllys 
15873089Swyllys 	tbscert = &signed_cert_ptr->certificate;
15883089Swyllys 	signature = &signed_cert_ptr->signature;
15893089Swyllys 
15903089Swyllys 	asn1 = kmfder_alloc();
15913089Swyllys 	if (asn1 == NULL)
15923089Swyllys 		return (KMF_ERR_MEMORY);
15933089Swyllys 
15943089Swyllys 	/* Start outer X509 Certificate SEQUENCE */
15953089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
15963089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
15973089Swyllys 		goto cleanup;
15983089Swyllys 	}
15993089Swyllys 
16003089Swyllys 	if ((ret = encode_tbs_cert(asn1, tbscert)) != KMF_OK) {
16013089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16023089Swyllys 		goto cleanup;
16033089Swyllys 	}
16043089Swyllys 
16053089Swyllys 	/* Add the Algorithm & Signature Sequence */
16063089Swyllys 	if ((ret = encode_algoid(asn1,
16073089Swyllys 		&signature->algorithmIdentifier)) != KMF_OK)
16083089Swyllys 		goto cleanup;
16093089Swyllys 
16103089Swyllys 	if (signature->encrypted.Length > 0) {
16113089Swyllys 		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
16123089Swyllys 			signature->encrypted.Length * 8) == -1) {
16133089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
16143089Swyllys 			goto cleanup;
16153089Swyllys 		}
16163089Swyllys 	}
16173089Swyllys 
16183089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
16193089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16203089Swyllys 		goto cleanup;
16213089Swyllys 	}
16223089Swyllys 
16233089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
16243089Swyllys 		ret = KMF_ERR_MEMORY;
16253089Swyllys 		goto cleanup;
16263089Swyllys 	}
16273089Swyllys 
16283089Swyllys 	encodedcert->Data = (uchar_t *)tbsdata->bv_val;
16293089Swyllys 	encodedcert->Length = tbsdata->bv_len;
16303089Swyllys 
16313089Swyllys cleanup:
16323089Swyllys 	if (ret != KMF_OK)
16333089Swyllys 		free_data(encodedcert);
16343089Swyllys 
16353089Swyllys 	if (tbsdata)
16363089Swyllys 		free(tbsdata);
16373089Swyllys 
16383089Swyllys 	if (asn1)
16393089Swyllys 		kmfber_free(asn1, 1);
16403089Swyllys 
16413089Swyllys 	return (ret);
16423089Swyllys }
16433089Swyllys 
16443089Swyllys KMF_RETURN
16453089Swyllys ExtractX509CertParts(KMF_DATA *x509cert, KMF_DATA *tbscert,
16463089Swyllys 		KMF_DATA *signature)
16473089Swyllys {
16483089Swyllys 	KMF_RETURN ret = KMF_OK;
16493089Swyllys 	BerElement *der = NULL;
16503089Swyllys 	BerValue x509;
16513089Swyllys 	ber_tag_t tag;
16523089Swyllys 	ber_len_t size;
16533089Swyllys 
16543089Swyllys 	if (tbscert == NULL || x509cert == NULL)
16553089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
16563089Swyllys 
16573089Swyllys 	x509.bv_val = (char *)x509cert->Data;
16583089Swyllys 	x509.bv_len = x509cert->Length;
16593089Swyllys 
16603089Swyllys 	der = kmfder_init(&x509);
16613089Swyllys 	if (der == NULL)
16623089Swyllys 		return (KMF_ERR_MEMORY);
16633089Swyllys 
16643089Swyllys 	/* Skip over the overall Sequence tag to get at the TBS Cert data */
16653089Swyllys 	if (kmfber_scanf(der, "Tl", &tag, &size) == -1) {
16663089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16673089Swyllys 		goto cleanup;
16683089Swyllys 	}
16693089Swyllys 	if (tag != BER_CONSTRUCTED_SEQUENCE) {
16703089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16713089Swyllys 		goto cleanup;
16723089Swyllys 	}
16733089Swyllys 
16743089Swyllys 	/*
16753089Swyllys 	 * Since we are extracting a copy of the ENCODED bytes, we
16763089Swyllys 	 * must make sure to also include the bytes for the tag and
16773089Swyllys 	 * the length fields for the CONSTRUCTED SEQUENCE (TBSCert).
16783089Swyllys 	 */
16793089Swyllys 	size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
16803089Swyllys 
16813089Swyllys 	tbscert->Data = malloc(size);
16823089Swyllys 	if (tbscert->Data == NULL) {
16833089Swyllys 		ret = KMF_ERR_MEMORY;
16843089Swyllys 		goto cleanup;
16853089Swyllys 	}
16863089Swyllys 	tbscert->Length = size;
16873089Swyllys 
16883089Swyllys 	/* The der data ptr is now set to the start of the TBS cert sequence */
16893089Swyllys 	size = kmfber_read(der, (char *)tbscert->Data, tbscert->Length);
16903089Swyllys 	if (size != tbscert->Length) {
16913089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
16923089Swyllys 		goto cleanup;
16933089Swyllys 	}
16943089Swyllys 
16953089Swyllys 	if (signature != NULL) {
16963089Swyllys 		KMF_X509_ALGORITHM_IDENTIFIER algoid;
16973089Swyllys 		if ((ret = get_algoid(der, &algoid)) != KMF_OK)
16983089Swyllys 			goto cleanup;
16993089Swyllys 		free_algoid(&algoid);
17003089Swyllys 
17013089Swyllys 		if (kmfber_scanf(der, "tl", &tag, &size) != BER_BIT_STRING) {
17023089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
17033089Swyllys 			goto cleanup;
17043089Swyllys 		}
17053089Swyllys 		/* Now get the signature data */
17063089Swyllys 		if (kmfber_scanf(der, "B", (char **)&signature->Data,
17073089Swyllys 			(ber_len_t *)&signature->Length) == -1) {
17083089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
17093089Swyllys 			goto cleanup;
17103089Swyllys 		}
17113089Swyllys 		/* convert bitstring length to bytes */
17123089Swyllys 		signature->Length = signature->Length / 8;
17133089Swyllys 	}
17143089Swyllys 
17153089Swyllys cleanup:
17163089Swyllys 	if (der)
17173089Swyllys 		kmfber_free(der, 1);
17183089Swyllys 
17193089Swyllys 	if (ret != KMF_OK)
17203089Swyllys 		free_data(tbscert);
17213089Swyllys 
17223089Swyllys 	return (ret);
17233089Swyllys }
17243089Swyllys 
17253089Swyllys /*
17263089Swyllys  * Name: GetKeyFromSpki
17273089Swyllys  *
17283089Swyllys  * Description:
17293089Swyllys  * This function parses the KMF_X509_SPKI into its
17303089Swyllys  * key and parameter components based on the key generation algorithm.
17313089Swyllys  * NOTE:  Currently, it only checks for the RSA and DSA algorithms.
17323089Swyllys  *	The RSA algorithm is equivalent to the default behavior.
17333089Swyllys  *	All other algorithms will default to the parameters = NULL and the
17343089Swyllys  *	key data equal to whatever is in the CSSM_KEY structure for the key
17353089Swyllys  *
17363089Swyllys  * Parameters:
17373089Swyllys  * AlgId (input) : Algorithm identifier
17383089Swyllys  * SpkiPtr (input): SPKI structure that contains the key
17393089Swyllys  * key_ptr(output): The output key
17403089Swyllys  *
17413089Swyllys  */
17423089Swyllys KMF_RETURN
17433089Swyllys GetKeyFromSpki(KMF_ALGORITHM_INDEX AlgId,
17443089Swyllys 	KMF_X509_SPKI *SpkiPtr,
17453089Swyllys 	KMF_DATA **key_ptr)
17463089Swyllys {
17473089Swyllys 	KMF_RETURN ret = KMF_OK;
17483089Swyllys 	BerElement *asn1;
17493089Swyllys 	BerValue *encodedkey = NULL;
17503089Swyllys 
17513089Swyllys 	if (!key_ptr || !SpkiPtr) {
17523089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
17533089Swyllys 	}
17543089Swyllys 	*key_ptr = NULL;
17553089Swyllys 
17563089Swyllys 	switch (AlgId) {
17573089Swyllys 		case KMF_ALGID_DSA:
17583089Swyllys 			asn1 = kmfder_alloc();
17593089Swyllys 			if (asn1 == NULL) {
17603089Swyllys 				return (KMF_ERR_MEMORY);
17613089Swyllys 			}
17623089Swyllys 
17633089Swyllys 			if ((ret = encode_spki(asn1, SpkiPtr)) != KMF_OK) {
17643089Swyllys 				ret = KMF_ERR_MEMORY;
17653089Swyllys 				goto cleanup;
17663089Swyllys 			}
17673089Swyllys 
17683089Swyllys 			if (kmfber_flatten(asn1, &encodedkey) == -1) {
17693089Swyllys 				ret = KMF_ERR_MEMORY;
17703089Swyllys 				goto cleanup;
17713089Swyllys 			}
17723089Swyllys 
17733089Swyllys 			*key_ptr = malloc(sizeof (KMF_DATA));
17743089Swyllys 
17753089Swyllys 			if (!*key_ptr) {
17763089Swyllys 				ret = KMF_ERR_MEMORY;
17773089Swyllys 				goto cleanup;
17783089Swyllys 			}
17793089Swyllys 
17803089Swyllys 			(*key_ptr)->Length = encodedkey->bv_len;
17813089Swyllys 			(*key_ptr)->Data = (uchar_t *)encodedkey->bv_val;
17823089Swyllys cleanup:
17833089Swyllys 			kmfber_free(asn1, 1);
17843089Swyllys 			if (encodedkey)
17853089Swyllys 				free(encodedkey);
17863089Swyllys 		break;
17873089Swyllys 		default: /* RSA */
17883089Swyllys 			*key_ptr = malloc(sizeof (KMF_DATA));
17893089Swyllys 
17903089Swyllys 			if (!*key_ptr) {
17913089Swyllys 				return (KMF_ERR_MEMORY);
17923089Swyllys 			}
17933089Swyllys 			(*key_ptr)->Length = SpkiPtr->subjectPublicKey.Length;
17943089Swyllys 			(*key_ptr)->Data = malloc((*key_ptr)->Length);
17953089Swyllys 
17963089Swyllys 			if (!(*key_ptr)->Data) {
17973089Swyllys 				free(*key_ptr);
17983089Swyllys 				*key_ptr = NULL;
17993089Swyllys 				return (KMF_ERR_MEMORY);
18003089Swyllys 			}
18013089Swyllys 			(void) memcpy((*key_ptr)->Data,
18023089Swyllys 				SpkiPtr->subjectPublicKey.Data,
18033089Swyllys 				(*key_ptr)->Length);
18043089Swyllys 			return (ret);
18053089Swyllys 	}
18063089Swyllys 	return (ret);
18073089Swyllys }
18083089Swyllys 
18093089Swyllys static KMF_RETURN
18103089Swyllys decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
18113089Swyllys {
18123089Swyllys 	KMF_RETURN ret = KMF_OK;
18133089Swyllys 	BerValue oid;
18143089Swyllys 
18153089Swyllys 	if (kmfber_scanf(asn1, "{D", &oid) == -1) {
18163089Swyllys 		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
18173089Swyllys 	}
18183089Swyllys 
18193089Swyllys 	/* We only understand extension requests in a CSR */
18203089Swyllys 	if (memcmp(oid.bv_val, extension_request_oid.Data,
18213089Swyllys 		oid.bv_len) != 0) {
18223089Swyllys 		return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
18233089Swyllys 	}
18243089Swyllys 
18253089Swyllys 	if (kmfber_scanf(asn1, "[") == -1) {
18263089Swyllys 		return (KMF_ERR_ENCODING);
18273089Swyllys 	}
18283089Swyllys 	ret = get_extensions(asn1, extns);
18293089Swyllys 
18303089Swyllys 
18313089Swyllys 	return (ret);
18323089Swyllys }
18333089Swyllys 
18343089Swyllys static KMF_RETURN
18353089Swyllys decode_tbscsr_data(BerElement *asn1,
18363089Swyllys 	KMF_TBS_CSR **signed_csr_ptr_ptr)
18373089Swyllys {
18383089Swyllys 	KMF_RETURN ret = KMF_OK;
18393089Swyllys 	KMF_TBS_CSR	*tbscsr = NULL;
18403089Swyllys 	char *end = NULL;
18413089Swyllys 	uint32_t version;
18423089Swyllys 	ber_tag_t tag;
18433089Swyllys 	ber_len_t size;
18443089Swyllys 
18453089Swyllys 	/* Now get the version number, it is not optional */
18463089Swyllys 	if (kmfber_scanf(asn1, "{i", &version) == -1) {
18473089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
18483089Swyllys 		goto cleanup;
18493089Swyllys 	}
18503089Swyllys 
18513089Swyllys 	tbscsr = malloc(sizeof (KMF_TBS_CSR));
18523089Swyllys 	if (!tbscsr) {
18533089Swyllys 		ret = KMF_ERR_MEMORY;
18543089Swyllys 		goto cleanup;
18553089Swyllys 	}
18563089Swyllys 
18573089Swyllys 	(void) memset(tbscsr, 0, sizeof (KMF_TBS_CSR));
18583089Swyllys 
18593089Swyllys 	if ((ret = set_der_integer(&tbscsr->version, version)) != KMF_OK)
18603089Swyllys 		goto cleanup;
18613089Swyllys 
18623089Swyllys 	if ((ret = get_rdn(asn1, &tbscsr->subject)) != KMF_OK)
18633089Swyllys 		goto cleanup;
18643089Swyllys 
18653089Swyllys 	if ((ret = get_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
18663089Swyllys 		goto cleanup;
18673089Swyllys 
18683089Swyllys 	/* Check for the optional fields (attributes) */
18693089Swyllys 	if (kmfber_next_element(asn1, &size, end) == 0xA0) {
18703089Swyllys 		if (kmfber_scanf(asn1, "Tl", &tag, &size) == -1) {
18713089Swyllys 			ret = KMF_ERR_ENCODING;
18723089Swyllys 			goto cleanup;
18733089Swyllys 		}
18743089Swyllys 
18753089Swyllys 		ret = decode_csr_extensions(asn1, &tbscsr->extensions);
18763089Swyllys 	}
18773089Swyllys 	if (ret == KMF_OK)
18783089Swyllys 		*signed_csr_ptr_ptr = tbscsr;
18793089Swyllys 
18803089Swyllys cleanup:
18813089Swyllys 	if (ret != KMF_OK) {
18823089Swyllys 		if (tbscsr) {
18833089Swyllys 			free_tbscsr(tbscsr);
18843089Swyllys 			free(tbscsr);
18853089Swyllys 		}
18863089Swyllys 		*signed_csr_ptr_ptr = NULL;
18873089Swyllys 	}
18883089Swyllys 	return (ret);
18893089Swyllys }
18903089Swyllys 
18913089Swyllys KMF_RETURN
18923089Swyllys DerDecodeTbsCsr(const KMF_DATA *Value,
18933089Swyllys 	KMF_TBS_CSR **tbscsr)
18943089Swyllys {
18953089Swyllys 	KMF_RETURN ret = KMF_OK;
18963089Swyllys 	BerElement *asn1 = NULL;
18973089Swyllys 	BerValue 	rawcsr;
18983089Swyllys 	KMF_TBS_CSR *newcsr = NULL;
18993089Swyllys 
19003089Swyllys 	if (!tbscsr || !Value || !Value->Data || !Value->Length)
19013089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
19023089Swyllys 
19033089Swyllys 	rawcsr.bv_val = (char *)Value->Data;
19043089Swyllys 	rawcsr.bv_len = Value->Length;
19053089Swyllys 
19063089Swyllys 	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
19073089Swyllys 		return (KMF_ERR_MEMORY);
19083089Swyllys 
19093089Swyllys 	ret = decode_tbscsr_data(asn1, &newcsr);
19103089Swyllys 	if (ret != KMF_OK)
19113089Swyllys 		goto cleanup;
19123089Swyllys 
19133089Swyllys 	*tbscsr = newcsr;
19143089Swyllys 
19153089Swyllys cleanup:
19163089Swyllys 	if (ret != KMF_OK) {
19173089Swyllys 		if (newcsr)
19183089Swyllys 			free_tbscsr(newcsr);
19193089Swyllys 		*tbscsr = NULL;
19203089Swyllys 	}
19213089Swyllys 	kmfber_free(asn1, 1);
19223089Swyllys 
19233089Swyllys 	return (ret);
19243089Swyllys }
19253089Swyllys 
19263089Swyllys KMF_RETURN
19273089Swyllys DerDecodeSignedCsr(const KMF_DATA *Value,
19283089Swyllys 	KMF_CSR_DATA **signed_csr_ptr_ptr)
19293089Swyllys {
19303089Swyllys 	KMF_RETURN ret = KMF_OK;
19313089Swyllys 	BerElement *asn1 = NULL;
19323089Swyllys 	BerValue 	rawcsr;
19333089Swyllys 	int			tag;
19343089Swyllys 	ber_len_t	size;
19353089Swyllys 	char		*end = NULL;
19363089Swyllys 	char		*signature;
19373089Swyllys 	KMF_TBS_CSR	*tbscsr = NULL;
19383089Swyllys 	KMF_CSR_DATA *csrptr = NULL;
19393089Swyllys 
19403089Swyllys 	if (!signed_csr_ptr_ptr || !Value || !Value->Data || !Value->Length)
19413089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
19423089Swyllys 
19433089Swyllys 	rawcsr.bv_val = (char *)Value->Data;
19443089Swyllys 	rawcsr.bv_len = Value->Length;
19453089Swyllys 
19463089Swyllys 	if ((asn1 = kmfder_init(&rawcsr)) == NULL)
19473089Swyllys 		return (KMF_ERR_MEMORY);
19483089Swyllys 
19493089Swyllys 	if (kmfber_first_element(asn1, &size, &end) !=
19503089Swyllys 		BER_CONSTRUCTED_SEQUENCE) {
19513089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
19523089Swyllys 		goto cleanup;
19533089Swyllys 	}
19543089Swyllys 
19553089Swyllys 	csrptr = malloc(sizeof (KMF_CSR_DATA));
19563089Swyllys 	if (csrptr == NULL) {
19573089Swyllys 		ret = KMF_ERR_MEMORY;
19583089Swyllys 		goto cleanup;
19593089Swyllys 	}
19603089Swyllys 	(void) memset(csrptr, 0, sizeof (KMF_CSR_DATA));
19613089Swyllys 
19623089Swyllys 	ret = decode_tbscsr_data(asn1, &tbscsr);
19633089Swyllys 	if (ret != KMF_OK)
19643089Swyllys 		goto cleanup;
19653089Swyllys 
19663089Swyllys 	csrptr->csr = *tbscsr;
19673089Swyllys 	free(tbscsr);
19683089Swyllys 	tbscsr = NULL;
19693089Swyllys 
19703089Swyllys 	if ((ret = get_algoid(asn1,
19713089Swyllys 		&csrptr->signature.algorithmIdentifier)) != KMF_OK)
19723089Swyllys 		goto cleanup;
19733089Swyllys 
19743089Swyllys 	/* Check to see if the cert has a signature yet */
19753089Swyllys 	if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
19763089Swyllys 		/* Finally, get the encrypted signature BITSTRING */
19773089Swyllys 		if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
19783089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
19793089Swyllys 			goto cleanup;
19803089Swyllys 		}
19813089Swyllys 		if (tag != BER_BIT_STRING) {
19823089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
19833089Swyllys 			goto cleanup;
19843089Swyllys 		}
19853089Swyllys 		if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
19863089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
19873089Swyllys 			goto cleanup;
19883089Swyllys 		}
19893089Swyllys 		csrptr->signature.encrypted.Data = (uchar_t *)signature;
19903089Swyllys 		csrptr->signature.encrypted.Length = size / 8;
19913089Swyllys 	} else {
19923089Swyllys 		csrptr->signature.encrypted.Data = NULL;
19933089Swyllys 		csrptr->signature.encrypted.Length = 0;
19943089Swyllys 	}
19953089Swyllys 
19963089Swyllys 	*signed_csr_ptr_ptr = csrptr;
19973089Swyllys cleanup:
19983089Swyllys 	if (ret != KMF_OK) {
19993089Swyllys 		free_tbscsr(&csrptr->csr);
20003089Swyllys 		free_algoid(&csrptr->signature.algorithmIdentifier);
20013089Swyllys 		if (csrptr->signature.encrypted.Data)
20023089Swyllys 			free(csrptr->signature.encrypted.Data);
20033089Swyllys 
20043089Swyllys 		if (csrptr)
20053089Swyllys 			free(csrptr);
20063089Swyllys 
20073089Swyllys 		*signed_csr_ptr_ptr = NULL;
20083089Swyllys 	}
20093089Swyllys 	if (asn1)
20103089Swyllys 		kmfber_free(asn1, 1);
20113089Swyllys 
20123089Swyllys 	return (ret);
20133089Swyllys 
20143089Swyllys }
20153089Swyllys 
20163089Swyllys static KMF_RETURN
20173089Swyllys encode_csr_extensions(BerElement *asn1, KMF_TBS_CSR *tbscsr)
20183089Swyllys {
20193089Swyllys 	KMF_RETURN ret = KMF_OK;
20203089Swyllys 	int attlen = 0;
20213089Swyllys 	BerElement *extnasn1 = NULL;
20223089Swyllys 	BerValue *extnvalue = NULL;
20233089Swyllys 
20243089Swyllys 	/* Optional field: CSR attributes and extensions */
20253089Swyllys 	if (tbscsr->extensions.numberOfExtensions > 0) {
20263089Swyllys 		if (kmfber_printf(asn1, "T", 0xA0) == -1) {
20273089Swyllys 			ret = KMF_ERR_ENCODING;
20283089Swyllys 			goto cleanup;
20293089Swyllys 		}
20303089Swyllys 	} else {
20313089Swyllys 		/* No extensions or attributes to encode */
20323089Swyllys 		return (KMF_OK);
20333089Swyllys 	}
20343089Swyllys 
20353089Swyllys 	/*
20363089Swyllys 	 * attributes [0] Attributes
20373089Swyllys 	 * Attributes := SET OF Attribute
20383089Swyllys 	 * Attribute  := SEQUENCE {
20393089Swyllys 	 *   { ATTRIBUTE ID
20403089Swyllys 	 *	values SET SIZE(1..MAX) of ATTRIBUTE
20413089Swyllys 	 *   }
20423089Swyllys 	 *
20433089Swyllys 	 * Ex: { ExtensionRequest OID [ { {extn1 } , {extn2 } } ] }
20443089Swyllys 	 */
20453089Swyllys 
20463089Swyllys 	/*
20473089Swyllys 	 * Encode any extensions and add to the attributes section.
20483089Swyllys 	 */
20493089Swyllys 	if (tbscsr->extensions.numberOfExtensions > 0) {
20503089Swyllys 		extnasn1 = kmfder_alloc();
20513089Swyllys 		if (extnasn1 == NULL) {
20523089Swyllys 			ret = KMF_ERR_MEMORY;
20533089Swyllys 			goto cleanup;
20543089Swyllys 		}
20553089Swyllys 
20563089Swyllys 		if (kmfber_printf(extnasn1, "{D[{",
20573089Swyllys 			&extension_request_oid) == -1) {
20583089Swyllys 			ret = KMF_ERR_ENCODING;
20593089Swyllys 			goto cleanup_1;
20603089Swyllys 		}
20613089Swyllys 
20623089Swyllys 		if ((ret = encode_extension_list(extnasn1,
20633089Swyllys 			&tbscsr->extensions)) != KMF_OK) {
20643089Swyllys 			goto cleanup_1;
20653089Swyllys 		}
20663089Swyllys 
20673089Swyllys 		if (kmfber_printf(extnasn1, "}]}") == -1) {
20683089Swyllys 			ret = KMF_ERR_ENCODING;
20693089Swyllys 			goto cleanup_1;
20703089Swyllys 		}
20713089Swyllys 
20723089Swyllys 		if (kmfber_flatten(extnasn1, &extnvalue) == -1) {
20733089Swyllys 			ret = KMF_ERR_MEMORY;
20743089Swyllys 			goto cleanup_1;
20753089Swyllys 		}
20763089Swyllys cleanup_1:
20773089Swyllys 		kmfber_free(extnasn1, 1);
20783089Swyllys 
20793089Swyllys 		if (ret == KMF_OK)
20803089Swyllys 			/* Add 2 bytes to cover the tag and the length */
20813089Swyllys 			attlen = extnvalue->bv_len;
20823089Swyllys 	}
20833089Swyllys 	if (ret != KMF_OK)
20843089Swyllys 		goto cleanup;
20853089Swyllys 
20863089Swyllys 	if (kmfber_printf(asn1, "l", attlen) == -1) {
20873089Swyllys 		ret = KMF_ERR_ENCODING;
20883089Swyllys 		goto cleanup;
20893089Swyllys 	}
20903089Swyllys 
20913089Swyllys 	/* Write the actual encoded extensions */
20923089Swyllys 	if (extnvalue != NULL && extnvalue->bv_val != NULL) {
20933089Swyllys 		if (kmfber_write(asn1, extnvalue->bv_val,
20943089Swyllys 			extnvalue->bv_len, 0) == -1) {
20953089Swyllys 			ret = KMF_ERR_ENCODING;
20963089Swyllys 			goto cleanup;
20973089Swyllys 		}
20983089Swyllys 	}
20993089Swyllys 
21003089Swyllys cleanup:
21013089Swyllys 	/*
21023089Swyllys 	 * Memory cleanup is done in the caller or in the individual
21033089Swyllys 	 * encoding routines.
21043089Swyllys 	 */
21053089Swyllys 	if (extnvalue) {
21063089Swyllys 		if (extnvalue->bv_val)
21073089Swyllys 			free(extnvalue->bv_val);
21083089Swyllys 		free(extnvalue);
21093089Swyllys 	}
21103089Swyllys 
21113089Swyllys 	return (ret);
21123089Swyllys }
21133089Swyllys 
21143089Swyllys static KMF_RETURN
21153089Swyllys encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr)
21163089Swyllys {
21173089Swyllys 	KMF_RETURN ret = KMF_OK;
21183089Swyllys 	uint32_t version;
21193089Swyllys 
21203089Swyllys 	/* Start the version */
21213089Swyllys 	(void) memcpy(&version, tbscsr->version.Data,
21223089Swyllys 		tbscsr->version.Length);
21233089Swyllys 
21243890Swyllys 	if (kmfber_printf(asn1, "{i", version) == -1) {
21253089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
21263089Swyllys 		goto cleanup;
21273089Swyllys 	}
21283089Swyllys 
21293089Swyllys 	/* Encode the Subject RDN */
21303089Swyllys 	if ((ret = encode_rdn(asn1, &tbscsr->subject)) != KMF_OK)
21313089Swyllys 		goto cleanup;
21323089Swyllys 
21333089Swyllys 	/* Encode the Subject Public Key Info */
21343089Swyllys 	if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
21353089Swyllys 		goto cleanup;
21363089Swyllys 
21373089Swyllys 
21383089Swyllys 	if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK)
21393089Swyllys 		goto cleanup;
21403089Swyllys 
21413089Swyllys 	/* Close out the TBSCert sequence */
21423089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
21433089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
21443089Swyllys 		goto cleanup;
21453089Swyllys 	}
21463089Swyllys 
21473089Swyllys cleanup:
21483089Swyllys 	return (ret);
21493089Swyllys }
21503089Swyllys 
21513089Swyllys KMF_RETURN
21523089Swyllys DerEncodeDSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_DSA_KEY *dsa)
21533089Swyllys {
21543089Swyllys 	KMF_RETURN rv = KMF_OK;
21553089Swyllys 	BerElement *asn1 = NULL;
21563089Swyllys 	BerValue  *dsadata = NULL;
21573089Swyllys 
21583089Swyllys 	asn1 = kmfder_alloc();
21593089Swyllys 	if (asn1 == NULL)
21603089Swyllys 		return (KMF_ERR_MEMORY);
21613089Swyllys 
21623089Swyllys 	if (kmfber_printf(asn1, "I",
21633089Swyllys 		dsa->value.val, dsa->value.len) == -1) {
21643089Swyllys 		rv = KMF_ERR_MEMORY;
21653089Swyllys 		goto cleanup;
21663089Swyllys 	}
21673089Swyllys 
21683089Swyllys 	if (kmfber_flatten(asn1, &dsadata) == -1) {
21693089Swyllys 		rv = KMF_ERR_MEMORY;
21703089Swyllys 		goto cleanup;
21713089Swyllys 	}
21723089Swyllys 
21733089Swyllys 	encodedkey->Data = (uchar_t *)dsadata->bv_val;
21743089Swyllys 	encodedkey->Length = dsadata->bv_len;
21753089Swyllys 
21763089Swyllys 	free(dsadata);
21773089Swyllys cleanup:
21783089Swyllys 	kmfber_free(asn1, 1);
21793089Swyllys 	return (rv);
21803089Swyllys }
21813089Swyllys 
21823089Swyllys KMF_RETURN
21833089Swyllys DerEncodeRSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_RSA_KEY *rsa)
21843089Swyllys {
21853089Swyllys 	KMF_RETURN rv = KMF_OK;
21863089Swyllys 	BerElement *asn1 = NULL;
21873089Swyllys 	uchar_t ver = 0;
21883089Swyllys 	BerValue  *rsadata = NULL;
21893089Swyllys 
21903089Swyllys 	asn1 = kmfder_alloc();
21913089Swyllys 	if (asn1 == NULL)
21923089Swyllys 		return (KMF_ERR_MEMORY);
21933089Swyllys 
21943089Swyllys 	if (kmfber_printf(asn1, "{IIIIIIIII}",
21953089Swyllys 		&ver, 1,
21963089Swyllys 		rsa->mod.val, rsa->mod.len,
21973089Swyllys 		rsa->pubexp.val, rsa->pubexp.len,
21983089Swyllys 		rsa->priexp.val, rsa->priexp.len,
21993089Swyllys 		rsa->prime1.val, rsa->prime1.len,
22003089Swyllys 		rsa->prime2.val, rsa->prime2.len,
22013089Swyllys 		rsa->exp1.val, rsa->exp1.len,
22023089Swyllys 		rsa->exp2.val, rsa->exp2.len,
22033089Swyllys 		rsa->coef.val, rsa->coef.len) == -1)
22043089Swyllys 		goto cleanup;
22053089Swyllys 
22063089Swyllys 	if (kmfber_flatten(asn1, &rsadata) == -1) {
22073089Swyllys 		rv = KMF_ERR_MEMORY;
22083089Swyllys 		goto cleanup;
22093089Swyllys 	}
22103089Swyllys 
22113089Swyllys 	encodedkey->Data = (uchar_t *)rsadata->bv_val;
22123089Swyllys 	encodedkey->Length = rsadata->bv_len;
22133089Swyllys 
22143089Swyllys 	free(rsadata);
22153089Swyllys cleanup:
22163089Swyllys 	kmfber_free(asn1, 1);
22173089Swyllys 	return (rv);
22183089Swyllys }
22193089Swyllys 
22203089Swyllys 
22213089Swyllys KMF_RETURN
22223089Swyllys DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr,
22233089Swyllys 	KMF_DATA *enc_tbs_csr_ptr)
22243089Swyllys {
22253089Swyllys 	KMF_RETURN ret;
22263089Swyllys 	BerValue  *tbsdata = NULL;
22273089Swyllys 	BerElement *asn1 = NULL;
22283089Swyllys 
22293089Swyllys 	asn1 = kmfder_alloc();
22303089Swyllys 
22313089Swyllys 	enc_tbs_csr_ptr->Data = NULL;
22323089Swyllys 	enc_tbs_csr_ptr->Length = 0;
22333089Swyllys 
22343089Swyllys 	if (asn1 == NULL)
22353089Swyllys 		return (KMF_ERR_MEMORY);
22363089Swyllys 
22373089Swyllys 	ret = encode_tbs_csr(asn1, tbs_csr_ptr);
22383089Swyllys 	if (ret != KMF_OK)
22393089Swyllys 		goto cleanup;
22403089Swyllys 
22413089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
22423089Swyllys 		ret = KMF_ERR_MEMORY;
22433089Swyllys 		goto cleanup;
22443089Swyllys 	}
22453089Swyllys 
22463089Swyllys 	enc_tbs_csr_ptr->Data = (uchar_t *)tbsdata->bv_val;
22473089Swyllys 	enc_tbs_csr_ptr->Length = tbsdata->bv_len;
22483089Swyllys 
22493089Swyllys cleanup:
22503089Swyllys 	if (ret != KMF_OK)
22513089Swyllys 		free_data(enc_tbs_csr_ptr);
22523089Swyllys 
22533089Swyllys 	if (asn1 != NULL)
22543089Swyllys 		kmfber_free(asn1, 1);
22553089Swyllys 
22563089Swyllys 	if (tbsdata)
22573089Swyllys 		free(tbsdata);
22583089Swyllys 
22593089Swyllys 	return (ret);
22603089Swyllys }
22613089Swyllys 
22623089Swyllys KMF_RETURN
22633089Swyllys DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr,
22643089Swyllys 	KMF_DATA *encodedcsr)
22653089Swyllys {
22663089Swyllys 	KMF_RETURN ret = KMF_OK;
22673089Swyllys 	KMF_TBS_CSR *tbscsr = NULL;
22683089Swyllys 	KMF_X509_SIGNATURE		*signature = NULL;
22693089Swyllys 	BerElement	*asn1 = NULL;
22703089Swyllys 	BerValue 	*tbsdata = NULL;
22713089Swyllys 
22723089Swyllys 	if (signed_csr_ptr == NULL)
22733089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
22743089Swyllys 
22753089Swyllys 	tbscsr = &signed_csr_ptr->csr;
22763089Swyllys 	signature = &signed_csr_ptr->signature;
22773089Swyllys 
22783089Swyllys 	asn1 = kmfder_alloc();
22793089Swyllys 	if (asn1 == NULL)
22803089Swyllys 		return (KMF_ERR_MEMORY);
22813089Swyllys 
22823089Swyllys 	/* Start outer CSR SEQUENCE */
22833089Swyllys 	if (kmfber_printf(asn1, "{") == -1) {
22843089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
22853089Swyllys 		goto cleanup;
22863089Swyllys 	}
22873089Swyllys 
22883089Swyllys 	ret = encode_tbs_csr(asn1, tbscsr);
22893089Swyllys 
22903089Swyllys 	/* Add the Algorithm & Signature Sequence */
22913089Swyllys 	if ((ret = encode_algoid(asn1,
22923089Swyllys 		&signature->algorithmIdentifier)) != KMF_OK)
22933089Swyllys 		goto cleanup;
22943089Swyllys 
22953089Swyllys 	if (signature->encrypted.Length > 0) {
22963089Swyllys 		if (kmfber_printf(asn1, "B", signature->encrypted.Data,
22973089Swyllys 			signature->encrypted.Length * 8) == -1) {
22983089Swyllys 			ret = KMF_ERR_BAD_CERT_FORMAT;
22993089Swyllys 			goto cleanup;
23003089Swyllys 		}
23013089Swyllys 	}
23023089Swyllys 
23033089Swyllys 	if (kmfber_printf(asn1, "}") == -1) {
23043089Swyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
23053089Swyllys 		goto cleanup;
23063089Swyllys 	}
23073089Swyllys 
23083089Swyllys 	if (kmfber_flatten(asn1, &tbsdata) == -1) {
23093089Swyllys 		ret = KMF_ERR_MEMORY;
23103089Swyllys 		goto cleanup;
23113089Swyllys 	}
23123089Swyllys 
23133089Swyllys 	encodedcsr->Data = (uchar_t *)tbsdata->bv_val;
23143089Swyllys 	encodedcsr->Length = tbsdata->bv_len;
23153089Swyllys 
23163089Swyllys cleanup:
23173089Swyllys 	if (ret != KMF_OK) {
23183089Swyllys 		free_data(encodedcsr);
23193089Swyllys 	}
23203089Swyllys 
23213089Swyllys 	if (tbsdata)
23223089Swyllys 		free(tbsdata);
23233089Swyllys 
23243089Swyllys 	if (asn1)
23253089Swyllys 		kmfber_free(asn1, 1);
23263089Swyllys 	return (ret);
23273089Swyllys }
23283089Swyllys 
23293089Swyllys KMF_RETURN
23303089Swyllys ExtractSPKIData(
23313089Swyllys 	const KMF_X509_SPKI *pKey,
23323089Swyllys 	KMF_ALGORITHM_INDEX AlgorithmId,
23333089Swyllys 	KMF_DATA *pKeyParts,
23343089Swyllys 	uint32_t *uNumKeyParts)
23353089Swyllys {
23363089Swyllys 	KMF_RETURN ret = KMF_OK;
23373089Swyllys 	BerElement *asn1 = NULL;
23383089Swyllys 	BerValue 	*P, *Q, *G, *Mod, *Exp, *PubKey;
23393089Swyllys 	BerValue	PubKeyParams, PubKeyData;
23403089Swyllys 
23413089Swyllys 	if (pKeyParts == NULL || uNumKeyParts == NULL || pKey == NULL)
23423089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
23433089Swyllys 
23443089Swyllys 	switch (AlgorithmId) {
23453089Swyllys 	    case KMF_ALGID_DSA:
23463089Swyllys 	    case KMF_ALGID_SHA1WithDSA:
23473089Swyllys 		/* First, get the parameters from the algorithm definition */
23483089Swyllys 		PubKeyParams.bv_val = (char *)pKey->algorithm.parameters.Data;
23493089Swyllys 		PubKeyParams.bv_len = pKey->algorithm.parameters.Length;
23503089Swyllys 		if ((asn1 = kmfder_init(&PubKeyParams)) == NULL)
23513089Swyllys 			return (KMF_ERR_MEMORY);
23523089Swyllys 
23533089Swyllys 		if (kmfber_scanf(asn1, "{III}", &P, &Q, &G) == -1) {
23543089Swyllys 			kmfber_free(asn1, 1);
23553089Swyllys 			return (KMF_ERR_BAD_KEY_FORMAT);
23563089Swyllys 		}
23573089Swyllys 		pKeyParts[KMF_DSA_PRIME].Data = (uchar_t *)P->bv_val;
23583089Swyllys 		pKeyParts[KMF_DSA_PRIME].Length = P->bv_len;
23593089Swyllys 		pKeyParts[KMF_DSA_SUB_PRIME].Data = (uchar_t *)Q->bv_val;
23603089Swyllys 		pKeyParts[KMF_DSA_SUB_PRIME].Length = Q->bv_len;
23613089Swyllys 		pKeyParts[KMF_DSA_BASE].Data = (uchar_t *)G->bv_val;
23623089Swyllys 		pKeyParts[KMF_DSA_BASE].Length = G->bv_len;
23633089Swyllys 
23643089Swyllys 		free(P);
23653089Swyllys 		free(Q);
23663089Swyllys 		free(G);
23673089Swyllys 		kmfber_free(asn1, 1);
23683089Swyllys 
23693089Swyllys 		/* Get the PubKey data */
23703089Swyllys 		PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
23713089Swyllys 		PubKeyData.bv_len = pKey->subjectPublicKey.Length;
23723089Swyllys 		if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
23733089Swyllys 			ret = KMF_ERR_MEMORY;
23743089Swyllys 			goto cleanup;
23753089Swyllys 		}
23763089Swyllys 		PubKey = NULL;
23773089Swyllys 		if (kmfber_scanf(asn1, "I", &PubKey) == -1) {
23783089Swyllys 			ret = KMF_ERR_BAD_KEY_FORMAT;
23793089Swyllys 			goto cleanup;
23803089Swyllys 		}
23813089Swyllys 		pKeyParts[KMF_DSA_PUBLIC_VALUE].Data =
23823089Swyllys 			(uchar_t *)PubKey->bv_val;
23833089Swyllys 		pKeyParts[KMF_DSA_PUBLIC_VALUE].Length = PubKey->bv_len;
23843089Swyllys 
23853089Swyllys 		free(PubKey);
23863089Swyllys 
23873089Swyllys 		*uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS;
23883089Swyllys 		break;
23893089Swyllys 
23903089Swyllys 	    case KMF_ALGID_RSA:
23913089Swyllys 	    case KMF_ALGID_MD2WithRSA:
23923089Swyllys 	    case KMF_ALGID_MD5WithRSA:
23933089Swyllys 	    case KMF_ALGID_SHA1WithRSA:
23943089Swyllys 		PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
23953089Swyllys 		PubKeyData.bv_len = pKey->subjectPublicKey.Length;
23963089Swyllys 		if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
23973089Swyllys 			ret = KMF_ERR_MEMORY;
23983089Swyllys 			goto cleanup;
23993089Swyllys 		}
24003089Swyllys 		if (kmfber_scanf(asn1, "{II}", &Mod, &Exp) == -1) {
24013089Swyllys 			ret = KMF_ERR_BAD_KEY_FORMAT;
24023089Swyllys 			goto cleanup;
24033089Swyllys 		}
24043089Swyllys 		pKeyParts[KMF_RSA_MODULUS].Data = (uchar_t *)Mod->bv_val;
24053089Swyllys 		pKeyParts[KMF_RSA_MODULUS].Length = Mod->bv_len;
24063089Swyllys 		pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Data =
24073089Swyllys 			(uchar_t *)Exp->bv_val;
24083089Swyllys 		pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Length = Exp->bv_len;
24093089Swyllys 		*uNumKeyParts = KMF_NUMBER_RSA_PUBLIC_KEY_PARTS;
24103089Swyllys 
24113089Swyllys 		free(Mod);
24123089Swyllys 		free(Exp);
24133089Swyllys 		break;
24143089Swyllys 	    default:
24153089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
24163089Swyllys 	}
24173089Swyllys cleanup:
24183089Swyllys 	if (ret != KMF_OK) {
24193089Swyllys 		int i;
24203089Swyllys 		for (i = 0; i < *uNumKeyParts; i++)
24213089Swyllys 			free_data(&pKeyParts[i]);
24223089Swyllys 	}
24233089Swyllys 	if (asn1 != NULL) {
24243089Swyllys 		kmfber_free(asn1, 1);
24253089Swyllys 	}
24263089Swyllys 
24273089Swyllys 	return (ret);
24283089Swyllys }
2429