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