199ebb4caSwyllys /*
2*e65e5c2dSWyllys Ingersoll * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
399ebb4caSwyllys * Use is subject to license terms.
49a767088Shaimay */
59a767088Shaimay /*
699ebb4caSwyllys * Copyright (c) 1995-1999 Intel Corporation. All rights reserved.
799ebb4caSwyllys */
899ebb4caSwyllys
999ebb4caSwyllys #include <strings.h>
1099ebb4caSwyllys #include <kmftypes.h>
1199ebb4caSwyllys #include <ber_der.h>
12*e65e5c2dSWyllys Ingersoll #include <kmfber_int.h>
1399ebb4caSwyllys #include <kmfapi.h>
1499ebb4caSwyllys #include <kmfapiP.h>
1599ebb4caSwyllys
1699ebb4caSwyllys #include <stdio.h>
1799ebb4caSwyllys
1899ebb4caSwyllys #define DSA_RAW_SIG_LEN 40
1999ebb4caSwyllys
2099ebb4caSwyllys static uint8_t OID_ExtensionRequest[] = { OID_PKCS_9, 14 };
2199ebb4caSwyllys const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
2299ebb4caSwyllys OID_ExtensionRequest};
2399ebb4caSwyllys
2499ebb4caSwyllys static KMF_RETURN
encode_algoid(BerElement * asn1,KMF_X509_ALGORITHM_IDENTIFIER * algoid,boolean_t encode_params)25*e65e5c2dSWyllys Ingersoll encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid,
26*e65e5c2dSWyllys Ingersoll boolean_t encode_params)
2799ebb4caSwyllys {
2899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
2999ebb4caSwyllys
3099ebb4caSwyllys if (kmfber_printf(asn1, "{D", &algoid->algorithm) == -1) {
3199ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
3299ebb4caSwyllys }
33*e65e5c2dSWyllys Ingersoll if (!encode_params) {
34*e65e5c2dSWyllys Ingersoll if (kmfber_printf(asn1, "}") == -1)
35*e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_CERT_FORMAT);
36*e65e5c2dSWyllys Ingersoll } else if (algoid->parameters.Data == NULL ||
3799ebb4caSwyllys algoid->parameters.Length == 0) {
3899ebb4caSwyllys if (kmfber_printf(asn1, "n}") == -1)
3999ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
4099ebb4caSwyllys } else {
4199ebb4caSwyllys /*
4299ebb4caSwyllys * The algorithm data can be anything, so we just write it
4399ebb4caSwyllys * straight into the buffer. It is already DER encoded.
4499ebb4caSwyllys */
4599ebb4caSwyllys (void) kmfber_write(asn1, (char *)algoid->parameters.Data,
4699ebb4caSwyllys algoid->parameters.Length, 0);
4799ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
4899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
4999ebb4caSwyllys }
5099ebb4caSwyllys }
5199ebb4caSwyllys
5299ebb4caSwyllys return (ret);
5399ebb4caSwyllys }
5499ebb4caSwyllys
5599ebb4caSwyllys static void
free_data(KMF_DATA * data)5699ebb4caSwyllys free_data(KMF_DATA *data)
5799ebb4caSwyllys {
5899ebb4caSwyllys if (data == NULL || data->Data == NULL)
5999ebb4caSwyllys return;
6099ebb4caSwyllys
6199ebb4caSwyllys free(data->Data);
6299ebb4caSwyllys data->Data = NULL;
6399ebb4caSwyllys data->Length = 0;
6499ebb4caSwyllys }
6599ebb4caSwyllys
6699ebb4caSwyllys static void
free_algoid(KMF_X509_ALGORITHM_IDENTIFIER * algoid)6799ebb4caSwyllys free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
6899ebb4caSwyllys {
6999ebb4caSwyllys free_data(&algoid->algorithm);
7099ebb4caSwyllys free_data(&algoid->parameters);
7199ebb4caSwyllys }
7299ebb4caSwyllys
7399ebb4caSwyllys static void
free_decoded_spki(KMF_X509_SPKI * spki)7499ebb4caSwyllys free_decoded_spki(KMF_X509_SPKI *spki)
7599ebb4caSwyllys {
7699ebb4caSwyllys if (spki != NULL) {
7799ebb4caSwyllys free_algoid(&spki->algorithm);
7899ebb4caSwyllys free_data(&spki->subjectPublicKey);
7999ebb4caSwyllys }
8099ebb4caSwyllys }
8199ebb4caSwyllys
8299ebb4caSwyllys static void
free_rdn_data(KMF_X509_NAME * name)8399ebb4caSwyllys free_rdn_data(KMF_X509_NAME *name)
8499ebb4caSwyllys {
8599ebb4caSwyllys KMF_X509_RDN *newrdn = NULL;
8699ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *av = NULL;
8799ebb4caSwyllys int i, j;
8899ebb4caSwyllys
8999ebb4caSwyllys if (name && name->numberOfRDNs) {
9099ebb4caSwyllys for (i = 0; i < name->numberOfRDNs; i++) {
9199ebb4caSwyllys newrdn = &name->RelativeDistinguishedName[i];
9299ebb4caSwyllys for (j = 0; j < newrdn->numberOfPairs; j++) {
9399ebb4caSwyllys av = &newrdn->AttributeTypeAndValue[j];
9499ebb4caSwyllys free_data(&av->type);
9599ebb4caSwyllys free_data(&av->value);
9699ebb4caSwyllys }
9799ebb4caSwyllys free(newrdn->AttributeTypeAndValue);
9899ebb4caSwyllys }
9999ebb4caSwyllys free(name->RelativeDistinguishedName);
10099ebb4caSwyllys name->numberOfRDNs = 0;
10199ebb4caSwyllys name->RelativeDistinguishedName = NULL;
10299ebb4caSwyllys }
10399ebb4caSwyllys }
10499ebb4caSwyllys
10599ebb4caSwyllys static void
free_validity(KMF_X509_VALIDITY * validity)10699ebb4caSwyllys free_validity(KMF_X509_VALIDITY *validity)
10799ebb4caSwyllys {
10899ebb4caSwyllys free_data(&validity->notBefore.time);
10999ebb4caSwyllys free_data(&validity->notAfter.time);
11099ebb4caSwyllys }
11199ebb4caSwyllys
11299ebb4caSwyllys static void
free_one_extension(KMF_X509_EXTENSION * exptr)11399ebb4caSwyllys free_one_extension(KMF_X509_EXTENSION *exptr)
11499ebb4caSwyllys {
11599ebb4caSwyllys free_data(&exptr->extnId);
11699ebb4caSwyllys free_data(&exptr->BERvalue);
11799ebb4caSwyllys
11899ebb4caSwyllys if (exptr->value.tagAndValue) {
11999ebb4caSwyllys free_data(&exptr->value.tagAndValue->value);
12099ebb4caSwyllys free(exptr->value.tagAndValue);
12199ebb4caSwyllys }
12299ebb4caSwyllys }
12399ebb4caSwyllys
12499ebb4caSwyllys static void
free_extensions(KMF_X509_EXTENSIONS * extns)12599ebb4caSwyllys free_extensions(KMF_X509_EXTENSIONS *extns)
12699ebb4caSwyllys {
12799ebb4caSwyllys int i;
12899ebb4caSwyllys KMF_X509_EXTENSION *exptr;
12999ebb4caSwyllys
13099ebb4caSwyllys if (extns && extns->numberOfExtensions > 0) {
13199ebb4caSwyllys for (i = 0; i < extns->numberOfExtensions; i++) {
13299ebb4caSwyllys exptr = &extns->extensions[i];
13399ebb4caSwyllys free_one_extension(exptr);
13499ebb4caSwyllys }
13599ebb4caSwyllys free(extns->extensions);
13699ebb4caSwyllys extns->numberOfExtensions = 0;
13799ebb4caSwyllys extns->extensions = NULL;
13899ebb4caSwyllys }
13999ebb4caSwyllys }
14099ebb4caSwyllys
14199ebb4caSwyllys static void
free_tbscsr(KMF_TBS_CSR * tbscsr)14299ebb4caSwyllys free_tbscsr(KMF_TBS_CSR *tbscsr)
14399ebb4caSwyllys {
14499ebb4caSwyllys if (tbscsr) {
14599ebb4caSwyllys free_data(&tbscsr->version);
14699ebb4caSwyllys
14799ebb4caSwyllys free_rdn_data(&tbscsr->subject);
14899ebb4caSwyllys
14999ebb4caSwyllys free_decoded_spki(&tbscsr->subjectPublicKeyInfo);
15099ebb4caSwyllys
15199ebb4caSwyllys free_extensions(&tbscsr->extensions);
15299ebb4caSwyllys }
15399ebb4caSwyllys }
15499ebb4caSwyllys
15599ebb4caSwyllys
15699ebb4caSwyllys static void
free_bigint(KMF_BIGINT * bn)15799ebb4caSwyllys free_bigint(KMF_BIGINT *bn)
15899ebb4caSwyllys {
15999ebb4caSwyllys if (bn != NULL && bn->val != NULL) {
16099ebb4caSwyllys free(bn->val);
16199ebb4caSwyllys bn->val = NULL;
16299ebb4caSwyllys bn->len = 0;
16399ebb4caSwyllys }
16499ebb4caSwyllys }
16599ebb4caSwyllys
16699ebb4caSwyllys static void
free_tbscert(KMF_X509_TBS_CERT * tbscert)16799ebb4caSwyllys free_tbscert(KMF_X509_TBS_CERT *tbscert)
16899ebb4caSwyllys {
16999ebb4caSwyllys if (tbscert) {
17099ebb4caSwyllys free_data(&tbscert->version);
17199ebb4caSwyllys free_bigint(&tbscert->serialNumber);
17299ebb4caSwyllys free_algoid(&tbscert->signature);
17399ebb4caSwyllys
17499ebb4caSwyllys free_rdn_data(&tbscert->issuer);
17599ebb4caSwyllys free_rdn_data(&tbscert->subject);
17699ebb4caSwyllys
17799ebb4caSwyllys free_validity(&tbscert->validity);
17899ebb4caSwyllys
17999ebb4caSwyllys free_data(&tbscert->issuerUniqueIdentifier);
18099ebb4caSwyllys free_data(&tbscert->subjectUniqueIdentifier);
18199ebb4caSwyllys free_decoded_spki(&tbscert->subjectPublicKeyInfo);
18299ebb4caSwyllys free_extensions(&tbscert->extensions);
18399ebb4caSwyllys
18499ebb4caSwyllys free_data(&tbscert->issuerUniqueIdentifier);
18599ebb4caSwyllys free_data(&tbscert->subjectUniqueIdentifier);
18699ebb4caSwyllys }
18799ebb4caSwyllys }
18899ebb4caSwyllys
18999ebb4caSwyllys static void
free_decoded_cert(KMF_X509_CERTIFICATE * certptr)19099ebb4caSwyllys free_decoded_cert(KMF_X509_CERTIFICATE *certptr)
19199ebb4caSwyllys {
19299ebb4caSwyllys if (!certptr)
19399ebb4caSwyllys return;
19499ebb4caSwyllys
19599ebb4caSwyllys free_tbscert(&certptr->certificate);
19699ebb4caSwyllys
19799ebb4caSwyllys free_algoid(&certptr->signature.algorithmIdentifier);
19899ebb4caSwyllys free_data(&certptr->signature.encrypted);
19999ebb4caSwyllys }
20099ebb4caSwyllys
20199ebb4caSwyllys static KMF_RETURN
get_sequence_data(BerElement * asn1,BerValue * seqdata)202*e65e5c2dSWyllys Ingersoll get_sequence_data(BerElement *asn1, BerValue *seqdata)
20399ebb4caSwyllys {
204*e65e5c2dSWyllys Ingersoll ber_tag_t tag;
20599ebb4caSwyllys ber_len_t size;
20699ebb4caSwyllys
20799ebb4caSwyllys tag = kmfber_next_element(asn1, &size, NULL);
208*e65e5c2dSWyllys Ingersoll if (tag == BER_OBJECT_IDENTIFIER) {
209*e65e5c2dSWyllys Ingersoll /* The whole block is the OID. */
210*e65e5c2dSWyllys Ingersoll size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
211*e65e5c2dSWyllys Ingersoll seqdata->bv_val = malloc(size);
212*e65e5c2dSWyllys Ingersoll if (seqdata->bv_val == NULL) {
213*e65e5c2dSWyllys Ingersoll return (KMF_ERR_MEMORY);
214*e65e5c2dSWyllys Ingersoll }
215*e65e5c2dSWyllys Ingersoll /* read the raw data into the Algoritm params area. */
216*e65e5c2dSWyllys Ingersoll if (kmfber_read(asn1, seqdata->bv_val, size) ==
217*e65e5c2dSWyllys Ingersoll -1) {
218*e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_CERT_FORMAT);
219*e65e5c2dSWyllys Ingersoll }
220*e65e5c2dSWyllys Ingersoll seqdata->bv_len = size;
221*e65e5c2dSWyllys Ingersoll return (KMF_OK);
222*e65e5c2dSWyllys Ingersoll } else if (tag != BER_CONSTRUCTED_SEQUENCE)
22399ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
22499ebb4caSwyllys
225*e65e5c2dSWyllys Ingersoll if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
226*e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_CERT_FORMAT);
227*e65e5c2dSWyllys Ingersoll }
228*e65e5c2dSWyllys Ingersoll /*
229*e65e5c2dSWyllys Ingersoll * We need to read the tag and the length bytes too,
230*e65e5c2dSWyllys Ingersoll * so adjust the size.
231*e65e5c2dSWyllys Ingersoll */
232*e65e5c2dSWyllys Ingersoll size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
233*e65e5c2dSWyllys Ingersoll seqdata->bv_val = malloc(size);
234*e65e5c2dSWyllys Ingersoll if (seqdata->bv_val == NULL) {
235*e65e5c2dSWyllys Ingersoll return (KMF_ERR_MEMORY);
236*e65e5c2dSWyllys Ingersoll }
237*e65e5c2dSWyllys Ingersoll /* read the raw data into the Algoritm params area. */
238*e65e5c2dSWyllys Ingersoll if (kmfber_read(asn1, seqdata->bv_val, size) ==
239*e65e5c2dSWyllys Ingersoll -1) {
240*e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_CERT_FORMAT);
241*e65e5c2dSWyllys Ingersoll }
242*e65e5c2dSWyllys Ingersoll seqdata->bv_len = size;
243*e65e5c2dSWyllys Ingersoll return (KMF_OK);
244*e65e5c2dSWyllys Ingersoll }
245*e65e5c2dSWyllys Ingersoll
246*e65e5c2dSWyllys Ingersoll static KMF_RETURN
get_algoid(BerElement * asn1,KMF_X509_ALGORITHM_IDENTIFIER * algoid)247*e65e5c2dSWyllys Ingersoll get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
248*e65e5c2dSWyllys Ingersoll {
249*e65e5c2dSWyllys Ingersoll KMF_RETURN rv = KMF_OK;
250*e65e5c2dSWyllys Ingersoll ber_tag_t tag;
251*e65e5c2dSWyllys Ingersoll ber_len_t size;
252*e65e5c2dSWyllys Ingersoll BerValue algoid_data;
253*e65e5c2dSWyllys Ingersoll BerValue AlgOID;
254*e65e5c2dSWyllys Ingersoll BerElement *oidasn1 = NULL;
255*e65e5c2dSWyllys Ingersoll
256*e65e5c2dSWyllys Ingersoll /* Read the entire OID seq into it's own data block */
257*e65e5c2dSWyllys Ingersoll rv = get_sequence_data(asn1, &algoid_data);
258*e65e5c2dSWyllys Ingersoll if (rv != KMF_OK)
259*e65e5c2dSWyllys Ingersoll return (rv);
260*e65e5c2dSWyllys Ingersoll
261*e65e5c2dSWyllys Ingersoll /* Now parse just this block so we don't overrun */
262*e65e5c2dSWyllys Ingersoll if ((oidasn1 = kmfder_init(&algoid_data)) == NULL)
263*e65e5c2dSWyllys Ingersoll return (KMF_ERR_MEMORY);
264*e65e5c2dSWyllys Ingersoll tag = kmfber_next_element(oidasn1, &size, NULL);
265*e65e5c2dSWyllys Ingersoll if (tag == BER_OBJECT_IDENTIFIER) {
266*e65e5c2dSWyllys Ingersoll algoid->algorithm.Data = (uchar_t *)algoid_data.bv_val;
267*e65e5c2dSWyllys Ingersoll algoid->algorithm.Length = algoid_data.bv_len;
268*e65e5c2dSWyllys Ingersoll algoid->parameters.Data = NULL;
269*e65e5c2dSWyllys Ingersoll algoid->parameters.Length = 0;
270*e65e5c2dSWyllys Ingersoll kmfber_free(oidasn1, 1);
271*e65e5c2dSWyllys Ingersoll return (KMF_OK);
272*e65e5c2dSWyllys Ingersoll }
273*e65e5c2dSWyllys Ingersoll
274*e65e5c2dSWyllys Ingersoll if ((tag = kmfber_scanf(oidasn1, "{D", &AlgOID)) == -1) {
275*e65e5c2dSWyllys Ingersoll kmfber_free(oidasn1, 1);
27699ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
27799ebb4caSwyllys }
27899ebb4caSwyllys algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val;
27999ebb4caSwyllys algoid->algorithm.Length = AlgOID.bv_len;
28099ebb4caSwyllys
281*e65e5c2dSWyllys Ingersoll tag = kmfber_next_element(oidasn1, &size, NULL);
282*e65e5c2dSWyllys Ingersoll if (tag == BER_NULL) {
283*e65e5c2dSWyllys Ingersoll (void) kmfber_scanf(oidasn1, "n}");
284*e65e5c2dSWyllys Ingersoll algoid->parameters.Data = NULL;
285*e65e5c2dSWyllys Ingersoll algoid->parameters.Length = 0;
286*e65e5c2dSWyllys Ingersoll } else if (tag == KMFBER_END_OF_SEQORSET || tag == KMFBER_DEFAULT) {
287*e65e5c2dSWyllys Ingersoll /* close sequence, we are done with Algoid */
28899ebb4caSwyllys algoid->parameters.Data = NULL;
28999ebb4caSwyllys algoid->parameters.Length = 0;
29099ebb4caSwyllys } else {
291*e65e5c2dSWyllys Ingersoll /* The rest of the data is the algorithm parameters */
292*e65e5c2dSWyllys Ingersoll if ((kmfber_scanf(oidasn1, "tl", &tag, &size)) == -1) {
293*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_BAD_CERT_FORMAT;
29499ebb4caSwyllys goto cleanup;
29599ebb4caSwyllys }
29699ebb4caSwyllys
29799ebb4caSwyllys /*
29899ebb4caSwyllys * We need to read the tag and the length bytes too,
29999ebb4caSwyllys * so adjust the size.
30099ebb4caSwyllys */
30199ebb4caSwyllys size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
30299ebb4caSwyllys algoid->parameters.Data = malloc(size);
30399ebb4caSwyllys if (algoid->parameters.Data == NULL) {
304*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_MEMORY;
30599ebb4caSwyllys goto cleanup;
30699ebb4caSwyllys }
30799ebb4caSwyllys /* read the raw data into the Algoritm params area. */
308*e65e5c2dSWyllys Ingersoll if (kmfber_read(oidasn1, (char *)algoid->parameters.Data,
30999ebb4caSwyllys size) == -1) {
310*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_BAD_CERT_FORMAT;
31199ebb4caSwyllys goto cleanup;
31299ebb4caSwyllys }
31399ebb4caSwyllys algoid->parameters.Length = size;
31499ebb4caSwyllys }
31599ebb4caSwyllys cleanup:
316*e65e5c2dSWyllys Ingersoll if (rv != KMF_OK) {
31799ebb4caSwyllys free_algoid(algoid);
31899ebb4caSwyllys }
319*e65e5c2dSWyllys Ingersoll kmfber_free(oidasn1, 1);
32099ebb4caSwyllys
321*e65e5c2dSWyllys Ingersoll return (rv);
32299ebb4caSwyllys }
32399ebb4caSwyllys
32499ebb4caSwyllys static KMF_RETURN
CopyData(KMF_DATA * src,KMF_DATA * dst)32599ebb4caSwyllys CopyData(KMF_DATA *src, KMF_DATA *dst)
32699ebb4caSwyllys {
32799ebb4caSwyllys if (src && dst && src->Data != NULL && src->Length > 0) {
32899ebb4caSwyllys dst->Length = src->Length;
32997732469Shaimay dst->Data = malloc(dst->Length);
33099ebb4caSwyllys if (dst->Data == NULL)
33199ebb4caSwyllys return (KMF_ERR_MEMORY);
33299ebb4caSwyllys (void) memcpy(dst->Data, src->Data, src->Length);
33399ebb4caSwyllys }
33499ebb4caSwyllys return (KMF_OK);
33599ebb4caSwyllys }
33699ebb4caSwyllys
33799ebb4caSwyllys static KMF_RETURN
encode_spki(BerElement * asn1,KMF_X509_SPKI * spki)33899ebb4caSwyllys encode_spki(BerElement *asn1, KMF_X509_SPKI *spki)
33999ebb4caSwyllys {
34099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
34199ebb4caSwyllys
34299ebb4caSwyllys if (kmfber_printf(asn1, "{") == -1)
34399ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
34499ebb4caSwyllys
345*e65e5c2dSWyllys Ingersoll /*
346*e65e5c2dSWyllys Ingersoll * The SPKI is the only place where algorithm parameters
347*e65e5c2dSWyllys Ingersoll * should be encoded.
348*e65e5c2dSWyllys Ingersoll */
349*e65e5c2dSWyllys Ingersoll if ((ret = encode_algoid(asn1, &spki->algorithm, TRUE)) != KMF_OK)
35099ebb4caSwyllys return (ret);
35199ebb4caSwyllys
35299ebb4caSwyllys if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data,
35399ebb4caSwyllys spki->subjectPublicKey.Length * 8) == -1)
35499ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
35599ebb4caSwyllys
35699ebb4caSwyllys return (ret);
35799ebb4caSwyllys }
35899ebb4caSwyllys
35999ebb4caSwyllys KMF_RETURN
DerEncodeSPKI(KMF_X509_SPKI * spki,KMF_DATA * EncodedSPKI)36099ebb4caSwyllys DerEncodeSPKI(KMF_X509_SPKI *spki, KMF_DATA *EncodedSPKI)
36199ebb4caSwyllys {
36299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
36399ebb4caSwyllys BerElement *asn1;
36499ebb4caSwyllys BerValue *result;
36599ebb4caSwyllys
36699ebb4caSwyllys if (spki == NULL || EncodedSPKI == NULL)
36799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
36899ebb4caSwyllys
36999ebb4caSwyllys if ((asn1 = kmfder_alloc()) == NULL)
37099ebb4caSwyllys return (KMF_ERR_MEMORY);
37199ebb4caSwyllys
37299ebb4caSwyllys if ((ret = encode_spki(asn1, spki)) != KMF_OK) {
37399ebb4caSwyllys return (ret);
37499ebb4caSwyllys }
37599ebb4caSwyllys
37699ebb4caSwyllys if (kmfber_flatten(asn1, &result) == -1) {
37799ebb4caSwyllys kmfber_free(asn1, 1);
37899ebb4caSwyllys return (KMF_ERR_ENCODING);
37999ebb4caSwyllys }
38099ebb4caSwyllys
38199ebb4caSwyllys EncodedSPKI->Data = (uchar_t *)result->bv_val;
38299ebb4caSwyllys EncodedSPKI->Length = result->bv_len;
38399ebb4caSwyllys
38499ebb4caSwyllys free(result);
38599ebb4caSwyllys kmfber_free(asn1, 1);
38699ebb4caSwyllys return (KMF_OK);
38799ebb4caSwyllys }
38899ebb4caSwyllys
38999ebb4caSwyllys static KMF_RETURN
get_spki(BerElement * asn1,KMF_X509_SPKI * spki)39099ebb4caSwyllys get_spki(BerElement *asn1, KMF_X509_SPKI *spki)
39199ebb4caSwyllys {
39299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
39399ebb4caSwyllys char *bitstr = NULL;
39499ebb4caSwyllys ber_len_t size;
39599ebb4caSwyllys
39699ebb4caSwyllys if (kmfber_scanf(asn1, "{") == -1)
39799ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
39899ebb4caSwyllys
39999ebb4caSwyllys if ((ret = get_algoid(asn1, &spki->algorithm)) != KMF_OK)
40099ebb4caSwyllys return (ret);
40199ebb4caSwyllys
40299ebb4caSwyllys if (kmfber_scanf(asn1, "B}", &bitstr, &size) == BER_BIT_STRING) {
40399ebb4caSwyllys spki->subjectPublicKey.Data = (uchar_t *)bitstr;
40499ebb4caSwyllys spki->subjectPublicKey.Length = size / 8;
40599ebb4caSwyllys } else {
40699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
40799ebb4caSwyllys goto cleanup;
40899ebb4caSwyllys }
40999ebb4caSwyllys cleanup:
41099ebb4caSwyllys if (ret != KMF_OK) {
41199ebb4caSwyllys if (bitstr != NULL)
41299ebb4caSwyllys free(bitstr);
41399ebb4caSwyllys spki->subjectPublicKey.Data = NULL;
41499ebb4caSwyllys spki->subjectPublicKey.Length = 0;
41599ebb4caSwyllys
41699ebb4caSwyllys free_algoid(&spki->algorithm);
41799ebb4caSwyllys }
41899ebb4caSwyllys return (ret);
41999ebb4caSwyllys }
42099ebb4caSwyllys
421*e65e5c2dSWyllys Ingersoll
42299ebb4caSwyllys KMF_RETURN
DerEncodeDSASignature(KMF_DATA * rawdata,KMF_DATA * signature)42399ebb4caSwyllys DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
42499ebb4caSwyllys {
42599ebb4caSwyllys BerElement *asn1;
42699ebb4caSwyllys BerValue *buf;
42799ebb4caSwyllys int n;
42899ebb4caSwyllys
42999ebb4caSwyllys if (rawdata == NULL || signature == NULL)
43099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
43199ebb4caSwyllys
432*e65e5c2dSWyllys Ingersoll if (rawdata->Data == NULL || rawdata->Length == 0)
43399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
43499ebb4caSwyllys
43599ebb4caSwyllys asn1 = kmfder_alloc();
43699ebb4caSwyllys if (asn1 == NULL)
43799ebb4caSwyllys return (KMF_ERR_MEMORY);
43899ebb4caSwyllys
43999ebb4caSwyllys /*
440*e65e5c2dSWyllys Ingersoll * The [EC]DSA signature is the concatenation of 2
44199ebb4caSwyllys * bignum values.
44299ebb4caSwyllys */
443*e65e5c2dSWyllys Ingersoll n = rawdata->Length/2;
44499ebb4caSwyllys if (kmfber_printf(asn1, "{II}",
4452cbed729Swyllys rawdata->Data, n, &rawdata->Data[n], n) == -1) {
44699ebb4caSwyllys kmfber_free(asn1, 1);
44799ebb4caSwyllys return (KMF_ERR_MEMORY);
44899ebb4caSwyllys }
44999ebb4caSwyllys
45099ebb4caSwyllys if (kmfber_flatten(asn1, &buf) == -1) {
45199ebb4caSwyllys kmfber_free(asn1, 1);
45299ebb4caSwyllys return (KMF_ERR_ENCODING);
45399ebb4caSwyllys }
45499ebb4caSwyllys
45599ebb4caSwyllys signature->Data = (uchar_t *)buf->bv_val;
45699ebb4caSwyllys signature->Length = buf->bv_len;
45799ebb4caSwyllys
45899ebb4caSwyllys kmfber_free(asn1, 1);
45999ebb4caSwyllys free(buf);
46099ebb4caSwyllys
46199ebb4caSwyllys return (KMF_OK);
46299ebb4caSwyllys }
46399ebb4caSwyllys
464*e65e5c2dSWyllys Ingersoll /*
465*e65e5c2dSWyllys Ingersoll * ECDSA and DSA encode signatures the same way.
466*e65e5c2dSWyllys Ingersoll */
467*e65e5c2dSWyllys Ingersoll KMF_RETURN
DerEncodeECDSASignature(KMF_DATA * rawdata,KMF_DATA * signature)468*e65e5c2dSWyllys Ingersoll DerEncodeECDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
469*e65e5c2dSWyllys Ingersoll {
470*e65e5c2dSWyllys Ingersoll return (DerEncodeDSASignature(rawdata, signature));
471*e65e5c2dSWyllys Ingersoll }
472*e65e5c2dSWyllys Ingersoll
473*e65e5c2dSWyllys Ingersoll /*
474*e65e5c2dSWyllys Ingersoll * Convert a signed DSA sig to a fixed-length unsigned one.
475*e65e5c2dSWyllys Ingersoll * This is necessary because DER encoding seeks to use the
476*e65e5c2dSWyllys Ingersoll * minimal amount of bytes but we need a full 20 byte DSA
477*e65e5c2dSWyllys Ingersoll * value with leading 0x00 bytes.
478*e65e5c2dSWyllys Ingersoll */
479*e65e5c2dSWyllys Ingersoll static KMF_RETURN
convert_signed_to_fixed(BerValue * src,BerValue * dst)480*e65e5c2dSWyllys Ingersoll convert_signed_to_fixed(BerValue *src, BerValue *dst)
481*e65e5c2dSWyllys Ingersoll {
482*e65e5c2dSWyllys Ingersoll int cnt;
483*e65e5c2dSWyllys Ingersoll char *p;
484*e65e5c2dSWyllys Ingersoll if (dst->bv_len > src->bv_len) {
485*e65e5c2dSWyllys Ingersoll cnt = dst->bv_len - src->bv_len;
486*e65e5c2dSWyllys Ingersoll /* prepend with leading 0s */
487*e65e5c2dSWyllys Ingersoll (void) memset(dst->bv_val, 0x00, cnt);
488*e65e5c2dSWyllys Ingersoll (void) memcpy(dst->bv_val + cnt, src->bv_val,
489*e65e5c2dSWyllys Ingersoll src->bv_len);
490*e65e5c2dSWyllys Ingersoll return (KMF_OK);
491*e65e5c2dSWyllys Ingersoll }
492*e65e5c2dSWyllys Ingersoll if (dst->bv_len == src->bv_len) {
493*e65e5c2dSWyllys Ingersoll (void) memcpy(dst->bv_val, src->bv_val,
494*e65e5c2dSWyllys Ingersoll dst->bv_len);
495*e65e5c2dSWyllys Ingersoll return (KMF_OK);
496*e65e5c2dSWyllys Ingersoll }
497*e65e5c2dSWyllys Ingersoll /*
498*e65e5c2dSWyllys Ingersoll * src is larger than dest, strip leading 0s.
499*e65e5c2dSWyllys Ingersoll * This should not be necessary, but do it just in case.
500*e65e5c2dSWyllys Ingersoll */
501*e65e5c2dSWyllys Ingersoll cnt = src->bv_len - dst->bv_len;
502*e65e5c2dSWyllys Ingersoll p = src->bv_val;
503*e65e5c2dSWyllys Ingersoll while (cnt-- > 0) {
504*e65e5c2dSWyllys Ingersoll if (*p++ != 0x00)
505*e65e5c2dSWyllys Ingersoll return (KMF_ERR_ENCODING);
506*e65e5c2dSWyllys Ingersoll }
507*e65e5c2dSWyllys Ingersoll (void) memcpy(dst->bv_val, p, dst->bv_len);
508*e65e5c2dSWyllys Ingersoll return (KMF_OK);
509*e65e5c2dSWyllys Ingersoll }
510*e65e5c2dSWyllys Ingersoll
51199ebb4caSwyllys KMF_RETURN
DerDecodeDSASignature(KMF_DATA * encoded,KMF_DATA * signature)51299ebb4caSwyllys DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
51399ebb4caSwyllys {
51499ebb4caSwyllys KMF_RETURN ret = KMF_OK;
51599ebb4caSwyllys BerElement *asn1 = NULL;
51699ebb4caSwyllys BerValue buf, *R = NULL, *S = NULL;
517*e65e5c2dSWyllys Ingersoll BerValue fixedR, fixedS;
51899ebb4caSwyllys
51999ebb4caSwyllys buf.bv_val = (char *)encoded->Data;
52099ebb4caSwyllys buf.bv_len = encoded->Length;
52199ebb4caSwyllys
52299ebb4caSwyllys if (encoded == NULL || encoded->Data == NULL ||
52399ebb4caSwyllys signature == NULL)
52499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
52599ebb4caSwyllys
52699ebb4caSwyllys signature->Data = NULL;
52799ebb4caSwyllys signature->Length = 0;
52899ebb4caSwyllys
52999ebb4caSwyllys if ((asn1 = kmfder_init(&buf)) == NULL)
53099ebb4caSwyllys return (KMF_ERR_MEMORY);
53199ebb4caSwyllys
53299ebb4caSwyllys if (kmfber_scanf(asn1, "{II}", &R, &S) == -1) {
53399ebb4caSwyllys ret = KMF_ERR_BAD_PARAMETER;
53499ebb4caSwyllys goto cleanup;
53599ebb4caSwyllys }
53699ebb4caSwyllys signature->Length = R->bv_len + S->bv_len;
537*e65e5c2dSWyllys Ingersoll /*
538*e65e5c2dSWyllys Ingersoll * If either of the values had a leading 0 lopped off
539*e65e5c2dSWyllys Ingersoll * they will be 1 byte short and need to be adjusted below.
540*e65e5c2dSWyllys Ingersoll * The stripping is correct as per ASN.1 rules.
541*e65e5c2dSWyllys Ingersoll *
542*e65e5c2dSWyllys Ingersoll * We don't know the exact length that the R and S values
543*e65e5c2dSWyllys Ingersoll * must be, it depends on the signature algorithm and,
544*e65e5c2dSWyllys Ingersoll * in the case of EC, the curve used. So instead of
545*e65e5c2dSWyllys Ingersoll * checking for a specific length, we just check to see
546*e65e5c2dSWyllys Ingersoll * if the value came out to be an odd number. If so,
547*e65e5c2dSWyllys Ingersoll * then we know it needs a leading 0x00 byte which
548*e65e5c2dSWyllys Ingersoll * will be added below when we convert it to a fixed
549*e65e5c2dSWyllys Ingersoll * length.
550*e65e5c2dSWyllys Ingersoll */
551*e65e5c2dSWyllys Ingersoll if ((R->bv_len % 2) != 0)
552*e65e5c2dSWyllys Ingersoll signature->Length++;
553*e65e5c2dSWyllys Ingersoll if ((S->bv_len % 2) != 0)
554*e65e5c2dSWyllys Ingersoll signature->Length++;
555*e65e5c2dSWyllys Ingersoll
55699ebb4caSwyllys signature->Data = malloc(signature->Length);
55799ebb4caSwyllys if (signature->Data == NULL) {
55899ebb4caSwyllys ret = KMF_ERR_MEMORY;
55999ebb4caSwyllys goto cleanup;
56099ebb4caSwyllys }
561*e65e5c2dSWyllys Ingersoll fixedR.bv_val = (char *)signature->Data;
562*e65e5c2dSWyllys Ingersoll /* adjust length if it needs a leading 0x00 byte */
563*e65e5c2dSWyllys Ingersoll fixedR.bv_len = R->bv_len + (R->bv_len % 2);
56499ebb4caSwyllys
565*e65e5c2dSWyllys Ingersoll fixedS.bv_val = (char *)(signature->Data + fixedR.bv_len);
566*e65e5c2dSWyllys Ingersoll /* adjust length if it needs a leading 0x00 byte */
567*e65e5c2dSWyllys Ingersoll fixedS.bv_len = S->bv_len + (S->bv_len % 2);
568*e65e5c2dSWyllys Ingersoll
569*e65e5c2dSWyllys Ingersoll /*
570*e65e5c2dSWyllys Ingersoll * This will add back any missing leading 0's
571*e65e5c2dSWyllys Ingersoll * that were stripped off earlier when the signature
572*e65e5c2dSWyllys Ingersoll * was parsed. This ensures that the 2 parts of the
573*e65e5c2dSWyllys Ingersoll * signature are the right length and have the proper
574*e65e5c2dSWyllys Ingersoll * leading 0's prepended.
575*e65e5c2dSWyllys Ingersoll */
576*e65e5c2dSWyllys Ingersoll ret = convert_signed_to_fixed(R, &fixedR);
577*e65e5c2dSWyllys Ingersoll if (ret)
578*e65e5c2dSWyllys Ingersoll goto cleanup;
579*e65e5c2dSWyllys Ingersoll
580*e65e5c2dSWyllys Ingersoll ret = convert_signed_to_fixed(S, &fixedS);
58199ebb4caSwyllys cleanup:
58299ebb4caSwyllys if (R && R->bv_val)
58399ebb4caSwyllys free(R->bv_val);
58499ebb4caSwyllys if (S && S->bv_val)
58599ebb4caSwyllys free(S->bv_val);
58699ebb4caSwyllys
58799ebb4caSwyllys if (S) free(S);
58899ebb4caSwyllys if (R) free(R);
58999ebb4caSwyllys
59099ebb4caSwyllys if (asn1) kmfber_free(asn1, 1);
59199ebb4caSwyllys
59299ebb4caSwyllys return (ret);
59399ebb4caSwyllys }
59499ebb4caSwyllys
59599ebb4caSwyllys KMF_RETURN
DerDecodeECDSASignature(KMF_DATA * encoded,KMF_DATA * signature)596*e65e5c2dSWyllys Ingersoll DerDecodeECDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
597*e65e5c2dSWyllys Ingersoll {
598*e65e5c2dSWyllys Ingersoll /* ECDSA can be decoded using same code as standard DSA */
599*e65e5c2dSWyllys Ingersoll return (DerDecodeDSASignature(encoded, signature));
600*e65e5c2dSWyllys Ingersoll }
601*e65e5c2dSWyllys Ingersoll
602*e65e5c2dSWyllys Ingersoll KMF_RETURN
DerDecodeSPKI(KMF_DATA * EncodedSPKI,KMF_X509_SPKI * spki)60399ebb4caSwyllys DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki)
60499ebb4caSwyllys {
60599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
60699ebb4caSwyllys BerElement *asn1;
60799ebb4caSwyllys BerValue bv;
60899ebb4caSwyllys
60999ebb4caSwyllys if (EncodedSPKI == NULL || EncodedSPKI->Data == NULL ||
61099ebb4caSwyllys spki == NULL)
61199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
61299ebb4caSwyllys
61399ebb4caSwyllys (void) memset(spki, 0, sizeof (KMF_X509_SPKI));
61499ebb4caSwyllys
61599ebb4caSwyllys bv.bv_val = (char *)EncodedSPKI->Data;
61699ebb4caSwyllys bv.bv_len = EncodedSPKI->Length;
61799ebb4caSwyllys
61899ebb4caSwyllys if ((asn1 = kmfder_init(&bv)) == NULL)
61999ebb4caSwyllys return (KMF_ERR_MEMORY);
62099ebb4caSwyllys
62199ebb4caSwyllys ret = get_spki(asn1, spki);
62299ebb4caSwyllys
62399ebb4caSwyllys cleanup:
62499ebb4caSwyllys if (ret != KMF_OK) {
62599ebb4caSwyllys free_decoded_spki(spki);
62699ebb4caSwyllys }
62799ebb4caSwyllys kmfber_free(asn1, 1);
62899ebb4caSwyllys
62999ebb4caSwyllys return (ret);
63099ebb4caSwyllys }
63199ebb4caSwyllys
63299ebb4caSwyllys KMF_RETURN
CopySPKI(KMF_X509_SPKI * src,KMF_X509_SPKI ** dest)63399ebb4caSwyllys CopySPKI(KMF_X509_SPKI *src,
63499ebb4caSwyllys KMF_X509_SPKI **dest)
63599ebb4caSwyllys {
63699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
63799ebb4caSwyllys KMF_X509_SPKI *newspki;
63899ebb4caSwyllys
63999ebb4caSwyllys *dest = NULL;
64099ebb4caSwyllys
64199ebb4caSwyllys newspki = malloc(sizeof (KMF_X509_SPKI));
64299ebb4caSwyllys if (newspki == NULL)
64399ebb4caSwyllys return (KMF_ERR_MEMORY);
64499ebb4caSwyllys (void) memset(newspki, 0, sizeof (KMF_X509_SPKI));
64599ebb4caSwyllys
64699ebb4caSwyllys ret = CopyData(&src->algorithm.algorithm,
64799ebb4caSwyllys &newspki->algorithm.algorithm);
64899ebb4caSwyllys if (ret != KMF_OK)
64999ebb4caSwyllys goto cleanup;
65099ebb4caSwyllys
65199ebb4caSwyllys ret = CopyData(&src->algorithm.parameters,
65299ebb4caSwyllys &newspki->algorithm.parameters);
65399ebb4caSwyllys if (ret != KMF_OK)
65499ebb4caSwyllys goto cleanup;
65599ebb4caSwyllys
65699ebb4caSwyllys ret = CopyData(&src->subjectPublicKey,
65799ebb4caSwyllys &newspki->subjectPublicKey);
65899ebb4caSwyllys if (ret != KMF_OK)
65999ebb4caSwyllys goto cleanup;
66099ebb4caSwyllys
66199ebb4caSwyllys *dest = newspki;
66299ebb4caSwyllys cleanup:
66399ebb4caSwyllys if (ret != KMF_OK) {
66499ebb4caSwyllys if (newspki)
66599ebb4caSwyllys free_decoded_spki(newspki);
66699ebb4caSwyllys }
66799ebb4caSwyllys return (ret);
66899ebb4caSwyllys }
66999ebb4caSwyllys
67099ebb4caSwyllys static KMF_RETURN
encode_validity(BerElement * asn1,KMF_X509_VALIDITY * validity)67199ebb4caSwyllys encode_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
67299ebb4caSwyllys {
67399ebb4caSwyllys int ret;
67499ebb4caSwyllys
67599ebb4caSwyllys ret = kmfber_printf(asn1, "{tsts}",
67699ebb4caSwyllys validity->notBefore.timeType,
67799ebb4caSwyllys validity->notBefore.time.Data,
67899ebb4caSwyllys validity->notAfter.timeType,
67999ebb4caSwyllys validity->notAfter.time.Data);
68099ebb4caSwyllys
68199ebb4caSwyllys if (ret == -1)
68299ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
68399ebb4caSwyllys
68499ebb4caSwyllys return (KMF_OK);
68599ebb4caSwyllys }
68699ebb4caSwyllys
68799ebb4caSwyllys static KMF_RETURN
get_validity(BerElement * asn1,KMF_X509_VALIDITY * validity)68899ebb4caSwyllys get_validity(BerElement *asn1, KMF_X509_VALIDITY *validity)
68999ebb4caSwyllys {
69099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
69199ebb4caSwyllys int tag;
69299ebb4caSwyllys int t1, t2;
69399ebb4caSwyllys ber_len_t size;
69499ebb4caSwyllys char *t1str, *t2str;
69599ebb4caSwyllys
69699ebb4caSwyllys (void) memset(validity, 0, sizeof (KMF_X509_VALIDITY));
69799ebb4caSwyllys
69899ebb4caSwyllys tag = kmfber_next_element(asn1, &size, NULL);
69999ebb4caSwyllys if (tag != BER_CONSTRUCTED_SEQUENCE) {
70099ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
70199ebb4caSwyllys }
70299ebb4caSwyllys
70399ebb4caSwyllys if (kmfber_scanf(asn1, "{tata}", &t1, &t1str, &t2, &t2str) == -1) {
70499ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
70599ebb4caSwyllys }
70699ebb4caSwyllys
70799ebb4caSwyllys validity->notBefore.timeType = t1;
70899ebb4caSwyllys validity->notBefore.time.Data = (uchar_t *)t1str;
70999ebb4caSwyllys validity->notBefore.time.Length = strlen(t1str);
71099ebb4caSwyllys
71199ebb4caSwyllys validity->notAfter.timeType = t2;
71299ebb4caSwyllys validity->notAfter.time.Data = (uchar_t *)t2str;
71399ebb4caSwyllys validity->notAfter.time.Length = strlen(t2str);
71499ebb4caSwyllys
71599ebb4caSwyllys return (ret);
71699ebb4caSwyllys }
71799ebb4caSwyllys
71899ebb4caSwyllys KMF_RETURN
AddRDN(KMF_X509_NAME * name,KMF_X509_RDN * newrdn)71999ebb4caSwyllys AddRDN(KMF_X509_NAME *name, KMF_X509_RDN *newrdn)
72099ebb4caSwyllys {
72199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
72299ebb4caSwyllys KMF_X509_RDN *rdnslot = NULL;
72399ebb4caSwyllys
72499ebb4caSwyllys /* Add new RDN record to existing list */
72599ebb4caSwyllys name->numberOfRDNs++;
72699ebb4caSwyllys name->RelativeDistinguishedName =
72799ebb4caSwyllys realloc(name->RelativeDistinguishedName,
72899ebb4caSwyllys name->numberOfRDNs * sizeof (KMF_X509_RDN));
72999ebb4caSwyllys
73099ebb4caSwyllys if (name->RelativeDistinguishedName == NULL) {
73199ebb4caSwyllys ret = KMF_ERR_MEMORY;
73299ebb4caSwyllys goto cleanup;
73399ebb4caSwyllys }
73499ebb4caSwyllys rdnslot = &name->RelativeDistinguishedName[name->numberOfRDNs-1];
73599ebb4caSwyllys
73699ebb4caSwyllys if (newrdn) {
73799ebb4caSwyllys (void) memcpy(rdnslot, newrdn, sizeof (KMF_X509_RDN));
73899ebb4caSwyllys } else {
73999ebb4caSwyllys rdnslot->numberOfPairs = 0;
74099ebb4caSwyllys rdnslot->AttributeTypeAndValue = NULL;
74199ebb4caSwyllys }
74299ebb4caSwyllys
74399ebb4caSwyllys cleanup:
74499ebb4caSwyllys /* No cleanup needed here */
74599ebb4caSwyllys return (ret);
74699ebb4caSwyllys }
74799ebb4caSwyllys
74899ebb4caSwyllys static KMF_RETURN
encode_rdn(BerElement * asn1,KMF_X509_NAME * name)74999ebb4caSwyllys encode_rdn(BerElement *asn1, KMF_X509_NAME *name)
75099ebb4caSwyllys {
75199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
75299ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *attrtvpair = NULL;
75399ebb4caSwyllys int i;
75499ebb4caSwyllys KMF_X509_RDN *rdn;
75599ebb4caSwyllys
75699ebb4caSwyllys if (kmfber_printf(asn1, "{") == -1) {
75799ebb4caSwyllys ret = KMF_ERR_MEMORY;
75899ebb4caSwyllys goto cleanup;
75999ebb4caSwyllys }
76099ebb4caSwyllys
76199ebb4caSwyllys for (i = 0; i < name->numberOfRDNs; i++) {
76299ebb4caSwyllys if (kmfber_printf(asn1, "[") == -1) {
76399ebb4caSwyllys ret = KMF_ERR_MEMORY;
76499ebb4caSwyllys goto cleanup;
76599ebb4caSwyllys }
76699ebb4caSwyllys rdn = &name->RelativeDistinguishedName[i];
76799ebb4caSwyllys attrtvpair = rdn->AttributeTypeAndValue;
76899ebb4caSwyllys
76999ebb4caSwyllys if (rdn->numberOfPairs > 0) {
77099ebb4caSwyllys if (kmfber_printf(asn1, "{Dto}",
77199ebb4caSwyllys &attrtvpair->type,
77299ebb4caSwyllys attrtvpair->valueType,
77399ebb4caSwyllys attrtvpair->value.Data,
77499ebb4caSwyllys attrtvpair->value.Length) == -1) {
77599ebb4caSwyllys ret = KMF_ERR_MEMORY;
77699ebb4caSwyllys goto cleanup;
77799ebb4caSwyllys }
77899ebb4caSwyllys }
77999ebb4caSwyllys if (kmfber_printf(asn1, "]") == -1) {
78099ebb4caSwyllys ret = KMF_ERR_MEMORY;
78199ebb4caSwyllys goto cleanup;
78299ebb4caSwyllys }
78399ebb4caSwyllys }
78499ebb4caSwyllys
78599ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
78699ebb4caSwyllys ret = KMF_ERR_MEMORY;
78799ebb4caSwyllys goto cleanup;
78899ebb4caSwyllys }
78999ebb4caSwyllys
79099ebb4caSwyllys cleanup:
79199ebb4caSwyllys /* No cleanup needed here */
79299ebb4caSwyllys
79399ebb4caSwyllys return (ret);
79499ebb4caSwyllys }
79599ebb4caSwyllys
79699ebb4caSwyllys
79799ebb4caSwyllys KMF_RETURN
CopyRDN(KMF_X509_NAME * srcname,KMF_X509_NAME ** destname)79899ebb4caSwyllys CopyRDN(KMF_X509_NAME *srcname, KMF_X509_NAME **destname)
79999ebb4caSwyllys {
80099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
80199ebb4caSwyllys KMF_X509_NAME *newname = NULL;
80299ebb4caSwyllys KMF_X509_RDN *rdn, *dstrdn;
80399ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *av = NULL;
80499ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *srcav = NULL;
80599ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *dstav = NULL;
80699ebb4caSwyllys int i, j;
80799ebb4caSwyllys
80899ebb4caSwyllys newname = malloc(sizeof (KMF_X509_NAME));
80999ebb4caSwyllys if (newname == NULL)
81099ebb4caSwyllys return (KMF_ERR_MEMORY);
81199ebb4caSwyllys (void) memset(newname, 0, sizeof (KMF_X509_NAME));
81299ebb4caSwyllys
81399ebb4caSwyllys newname->numberOfRDNs = srcname->numberOfRDNs;
81499ebb4caSwyllys newname->RelativeDistinguishedName = malloc(newname->numberOfRDNs *
81599ebb4caSwyllys sizeof (KMF_X509_RDN));
81699ebb4caSwyllys if (newname->RelativeDistinguishedName == NULL) {
81799ebb4caSwyllys free(newname);
81899ebb4caSwyllys return (KMF_ERR_MEMORY);
81999ebb4caSwyllys }
82099ebb4caSwyllys /* Copy each RDN in the list */
82199ebb4caSwyllys for (i = 0; i < newname->numberOfRDNs; i++) {
82299ebb4caSwyllys rdn = &srcname->RelativeDistinguishedName[i];
82399ebb4caSwyllys
82499ebb4caSwyllys dstrdn = &newname->RelativeDistinguishedName[i];
82599ebb4caSwyllys (void) memset(dstrdn, 0, sizeof (KMF_X509_RDN));
82699ebb4caSwyllys
82799ebb4caSwyllys dstrdn->numberOfPairs = rdn->numberOfPairs;
82899ebb4caSwyllys if (dstrdn->numberOfPairs > 0) {
82999ebb4caSwyllys av = malloc(dstrdn->numberOfPairs *
83099ebb4caSwyllys sizeof (KMF_X509_TYPE_VALUE_PAIR));
83199ebb4caSwyllys if (av == NULL) {
83299ebb4caSwyllys ret = KMF_ERR_MEMORY;
83399ebb4caSwyllys goto cleanup;
83499ebb4caSwyllys }
83599ebb4caSwyllys (void) memset(av, 0, dstrdn->numberOfPairs *
83699ebb4caSwyllys sizeof (KMF_X509_TYPE_VALUE_PAIR));
83799ebb4caSwyllys
83899ebb4caSwyllys dstrdn->AttributeTypeAndValue = av;
83999ebb4caSwyllys if (av == NULL) {
84099ebb4caSwyllys ret = KMF_ERR_MEMORY;
84199ebb4caSwyllys goto cleanup;
84299ebb4caSwyllys }
84399ebb4caSwyllys /* Copy each A/V pair in the list */
84499ebb4caSwyllys for (j = 0; j < dstrdn->numberOfPairs; j++) {
84599ebb4caSwyllys srcav = &rdn->AttributeTypeAndValue[j];
84699ebb4caSwyllys dstav = &dstrdn->AttributeTypeAndValue[j];
84799ebb4caSwyllys if ((ret = CopyData(&srcav->type,
84899ebb4caSwyllys &dstav->type)) != KMF_OK)
84999ebb4caSwyllys goto cleanup;
85099ebb4caSwyllys dstav->valueType = srcav->valueType;
85199ebb4caSwyllys if ((ret = CopyData(&srcav->value,
85299ebb4caSwyllys &dstav->value)) != KMF_OK)
85399ebb4caSwyllys goto cleanup;
85499ebb4caSwyllys }
85599ebb4caSwyllys } else {
85699ebb4caSwyllys dstrdn->AttributeTypeAndValue = NULL;
85799ebb4caSwyllys }
85899ebb4caSwyllys }
85999ebb4caSwyllys *destname = newname;
86099ebb4caSwyllys
86199ebb4caSwyllys cleanup:
86299ebb4caSwyllys if (ret != KMF_OK) {
86399ebb4caSwyllys if (newname)
86499ebb4caSwyllys free_rdn_data(newname);
86599ebb4caSwyllys
86699ebb4caSwyllys free(newname);
86799ebb4caSwyllys *destname = NULL;
86899ebb4caSwyllys }
86999ebb4caSwyllys return (ret);
87099ebb4caSwyllys }
87199ebb4caSwyllys
87299ebb4caSwyllys #define VALID_DIRECTORYSTRING_TAG(t) ( \
87399ebb4caSwyllys (t == BER_UTF8_STRING) || \
87499ebb4caSwyllys (t == BER_PRINTABLE_STRING) || \
87599ebb4caSwyllys (t == BER_IA5STRING) || \
87699ebb4caSwyllys (t == BER_T61STRING) || \
87799ebb4caSwyllys (t == BER_BMP_STRING) || \
87899ebb4caSwyllys (t == BER_UNIVERSAL_STRING))
87999ebb4caSwyllys
88099ebb4caSwyllys static KMF_RETURN
get_rdn(BerElement * asn1,KMF_X509_NAME * name)88199ebb4caSwyllys get_rdn(BerElement *asn1, KMF_X509_NAME *name)
88299ebb4caSwyllys {
88399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
88499ebb4caSwyllys ber_len_t size;
88599ebb4caSwyllys char *end;
88699ebb4caSwyllys int tag;
88799ebb4caSwyllys BerValue AttrOID;
88899ebb4caSwyllys char *AttrValue = NULL;
88999ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *newpair = NULL;
89099ebb4caSwyllys KMF_X509_RDN newrdn;
89199ebb4caSwyllys
89299ebb4caSwyllys /*
89399ebb4caSwyllys * AttributeType ::= OBJECT IDENTIFIER
89499ebb4caSwyllys * AttributeValue ::= ANY
89599ebb4caSwyllys *
89699ebb4caSwyllys * AttributeTypeAndValue ::= SEQUENCE {
89799ebb4caSwyllys * type AttributeType,
89899ebb4caSwyllys * value AttributeValue }
89999ebb4caSwyllys *
90099ebb4caSwyllys * Name ::= CHOICE { -- only one possibility for now --
90199ebb4caSwyllys * rdnSequence RDNSequence }
90299ebb4caSwyllys *
90399ebb4caSwyllys * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
90499ebb4caSwyllys *
90599ebb4caSwyllys * DistinguishedName ::= RDNSequence
90699ebb4caSwyllys *
90799ebb4caSwyllys * RelativeDistinguishedName ::=
90899ebb4caSwyllys * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
90999ebb4caSwyllys *
91099ebb4caSwyllys */
91199ebb4caSwyllys
91299ebb4caSwyllys name->numberOfRDNs = 0;
91399ebb4caSwyllys name->RelativeDistinguishedName = NULL;
91499ebb4caSwyllys
91599ebb4caSwyllys /* Get the beginning of the RDN Set and a ptr to the end */
91699ebb4caSwyllys tag = kmfber_first_element(asn1, &size, &end);
91799ebb4caSwyllys if (tag != BER_CONSTRUCTED_SET) {
91899ebb4caSwyllys goto cleanup;
91999ebb4caSwyllys }
92099ebb4caSwyllys
92199ebb4caSwyllys /* Walk through the individual SET items until the "end" is reached */
92299ebb4caSwyllys while ((tag = kmfber_next_element(asn1, &size, end)) ==
92399ebb4caSwyllys BER_CONSTRUCTED_SET) {
92499ebb4caSwyllys /* Skip over the SET tag */
92599ebb4caSwyllys if (kmfber_scanf(asn1, "T", &tag) == -1) {
92699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
92799ebb4caSwyllys break;
92899ebb4caSwyllys }
92999ebb4caSwyllys
93099ebb4caSwyllys /* An "empty" set member means we tack on an empty node */
93199ebb4caSwyllys if (size == 0) {
93299ebb4caSwyllys if ((ret = AddRDN(name, NULL)) != KMF_OK)
93399ebb4caSwyllys goto cleanup;
93499ebb4caSwyllys continue;
93599ebb4caSwyllys }
93699ebb4caSwyllys
93799ebb4caSwyllys /* Attr OID and peek at the next tag and field length */
93899ebb4caSwyllys if (kmfber_scanf(asn1, "{Dtl", &AttrOID, &tag, &size) == -1) {
93999ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
94099ebb4caSwyllys break;
94199ebb4caSwyllys }
94299ebb4caSwyllys
94399ebb4caSwyllys if (!(VALID_DIRECTORYSTRING_TAG(tag))) {
94499ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
94599ebb4caSwyllys break;
94699ebb4caSwyllys }
94799ebb4caSwyllys
94899ebb4caSwyllys if (kmfber_scanf(asn1, "a}]", &AttrValue) == -1) {
94999ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
95099ebb4caSwyllys break;
95199ebb4caSwyllys }
95299ebb4caSwyllys
95399ebb4caSwyllys /* Allocate a new name/value pair record */
95499ebb4caSwyllys newpair = malloc(sizeof (KMF_X509_TYPE_VALUE_PAIR));
95599ebb4caSwyllys if (newpair == NULL) {
95699ebb4caSwyllys ret = KMF_ERR_MEMORY;
95799ebb4caSwyllys break;
95899ebb4caSwyllys }
95999ebb4caSwyllys (void) memset(newpair, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
96099ebb4caSwyllys newpair->type.Data = (uchar_t *)AttrOID.bv_val;
96199ebb4caSwyllys newpair->type.Length = AttrOID.bv_len;
96299ebb4caSwyllys newpair->valueType = tag; /* what kind of string is it? */
96399ebb4caSwyllys newpair->value.Data = (uchar_t *)AttrValue;
96499ebb4caSwyllys newpair->value.Length = strlen(AttrValue);
96599ebb4caSwyllys
96699ebb4caSwyllys (void) memset(&newrdn, 0, sizeof (KMF_X509_RDN));
96799ebb4caSwyllys newrdn.numberOfPairs = 1;
96899ebb4caSwyllys newrdn.AttributeTypeAndValue = newpair;
96999ebb4caSwyllys
97099ebb4caSwyllys if ((ret = AddRDN(name, &newrdn)) != KMF_OK)
97199ebb4caSwyllys break;
97299ebb4caSwyllys }
97399ebb4caSwyllys
97499ebb4caSwyllys cleanup:
97599ebb4caSwyllys if (ret != KMF_OK) {
97699ebb4caSwyllys free_rdn_data(name);
97799ebb4caSwyllys }
97899ebb4caSwyllys return (ret);
97999ebb4caSwyllys }
98099ebb4caSwyllys
98199ebb4caSwyllys static KMF_RETURN
set_der_integer(KMF_DATA * data,int value)98299ebb4caSwyllys set_der_integer(KMF_DATA *data, int value)
98399ebb4caSwyllys {
98499ebb4caSwyllys if (data == NULL)
98599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
98699ebb4caSwyllys
98799ebb4caSwyllys data->Data = malloc(sizeof (int));
98899ebb4caSwyllys if (data->Data == NULL)
98999ebb4caSwyllys return (KMF_ERR_MEMORY);
99099ebb4caSwyllys
99199ebb4caSwyllys data->Length = sizeof (int);
99299ebb4caSwyllys (void) memcpy((void *)data->Data, (const void *)&value, sizeof (int));
99399ebb4caSwyllys
99499ebb4caSwyllys return (KMF_OK);
99599ebb4caSwyllys }
99699ebb4caSwyllys
99799ebb4caSwyllys static KMF_RETURN
set_bigint(KMF_BIGINT * data,KMF_BIGINT * bigint)99899ebb4caSwyllys set_bigint(KMF_BIGINT *data, KMF_BIGINT *bigint)
99999ebb4caSwyllys {
100099ebb4caSwyllys if (data == NULL || bigint == NULL)
100199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
100299ebb4caSwyllys
100399ebb4caSwyllys data->val = malloc(bigint->len);
100499ebb4caSwyllys if (data->val == NULL)
100599ebb4caSwyllys return (KMF_ERR_MEMORY);
100699ebb4caSwyllys
100799ebb4caSwyllys data->len = bigint->len;
100899ebb4caSwyllys (void) memcpy((void *)data->val, (const void *)bigint->val,
100999ebb4caSwyllys bigint->len);
101099ebb4caSwyllys
101199ebb4caSwyllys return (KMF_OK);
101299ebb4caSwyllys }
101399ebb4caSwyllys
101499ebb4caSwyllys static KMF_RETURN
encode_uniqueid(BerElement * asn1,int tag,KMF_DATA * id)101599ebb4caSwyllys encode_uniqueid(BerElement *asn1, int tag, KMF_DATA *id)
101699ebb4caSwyllys {
101799ebb4caSwyllys KMF_RETURN ret = KMF_OK;
101899ebb4caSwyllys uint32_t len;
101999ebb4caSwyllys
102099ebb4caSwyllys len = kmfber_calc_taglen(BER_BIT_STRING) +
102199ebb4caSwyllys kmfber_calc_lenlen(id->Length * 8) + id->Length;
102299ebb4caSwyllys if (kmfber_printf(asn1, "TlB", tag, len,
102399ebb4caSwyllys id->Data, id->Length * 8) == -1)
102499ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
102599ebb4caSwyllys
102699ebb4caSwyllys return (ret);
102799ebb4caSwyllys }
102899ebb4caSwyllys
102999ebb4caSwyllys static KMF_RETURN
encode_extension_list(BerElement * asn1,KMF_X509_EXTENSIONS * extns)103099ebb4caSwyllys encode_extension_list(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
103199ebb4caSwyllys {
103299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
103399ebb4caSwyllys int i;
103499ebb4caSwyllys
103599ebb4caSwyllys for (i = 0; i < extns->numberOfExtensions; i++) {
103699ebb4caSwyllys BerValue v;
103799ebb4caSwyllys v.bv_val = (char *)extns->extensions[i].extnId.Data;
103899ebb4caSwyllys v.bv_len = extns->extensions[i].extnId.Length;
103999ebb4caSwyllys
104099ebb4caSwyllys if (kmfber_printf(asn1, "{D", &v) == -1) {
104199ebb4caSwyllys ret = KMF_ERR_ENCODING;
104299ebb4caSwyllys goto cleanup;
104399ebb4caSwyllys }
104499ebb4caSwyllys
104599ebb4caSwyllys if (extns->extensions[i].critical) {
104699ebb4caSwyllys if (kmfber_printf(asn1, "b",
104799ebb4caSwyllys extns->extensions[i].critical) == -1) {
104899ebb4caSwyllys ret = KMF_ERR_ENCODING;
104999ebb4caSwyllys goto cleanup;
105099ebb4caSwyllys }
105199ebb4caSwyllys }
105299ebb4caSwyllys
105399ebb4caSwyllys if (kmfber_printf(asn1, "o}",
105499ebb4caSwyllys extns->extensions[i].BERvalue.Data,
105599ebb4caSwyllys extns->extensions[i].BERvalue.Length) == -1) {
105699ebb4caSwyllys ret = KMF_ERR_ENCODING;
105799ebb4caSwyllys goto cleanup;
105899ebb4caSwyllys }
105999ebb4caSwyllys }
106099ebb4caSwyllys cleanup:
106199ebb4caSwyllys return (ret);
106299ebb4caSwyllys }
106399ebb4caSwyllys
106499ebb4caSwyllys static KMF_RETURN
encode_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)106599ebb4caSwyllys encode_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
106699ebb4caSwyllys {
106799ebb4caSwyllys KMF_RETURN ret = KMF_OK;
106899ebb4caSwyllys BerElement *extn = NULL;
106999ebb4caSwyllys BerValue *extnvalue = NULL;
107099ebb4caSwyllys
107199ebb4caSwyllys extn = kmfder_alloc();
107299ebb4caSwyllys if (extn == NULL)
107399ebb4caSwyllys return (KMF_ERR_MEMORY);
107499ebb4caSwyllys
107599ebb4caSwyllys if (kmfber_printf(extn, "{") == -1) {
107699ebb4caSwyllys ret = KMF_ERR_ENCODING;
107799ebb4caSwyllys goto cleanup;
107899ebb4caSwyllys }
107999ebb4caSwyllys
108099ebb4caSwyllys ret = encode_extension_list(extn, extns);
108199ebb4caSwyllys
108299ebb4caSwyllys if (kmfber_printf(extn, "}") == -1) {
108399ebb4caSwyllys ret = KMF_ERR_ENCODING;
108499ebb4caSwyllys goto cleanup;
108599ebb4caSwyllys }
108699ebb4caSwyllys
108799ebb4caSwyllys if (kmfber_flatten(extn, &extnvalue) == -1) {
108899ebb4caSwyllys ret = KMF_ERR_MEMORY;
108999ebb4caSwyllys goto cleanup;
109099ebb4caSwyllys }
109199ebb4caSwyllys
109299ebb4caSwyllys if (kmfber_printf(asn1, "Tl", 0xA3, extnvalue->bv_len) == -1) {
109399ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
109499ebb4caSwyllys goto cleanup;
109599ebb4caSwyllys }
109699ebb4caSwyllys
109799ebb4caSwyllys if (kmfber_write(asn1, extnvalue->bv_val, extnvalue->bv_len, 0) == -1) {
109899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
109999ebb4caSwyllys goto cleanup;
110099ebb4caSwyllys }
110199ebb4caSwyllys
110299ebb4caSwyllys cleanup:
110399ebb4caSwyllys kmfber_free(extn, 1);
110499ebb4caSwyllys if (extnvalue != NULL)
110599ebb4caSwyllys kmfber_bvfree(extnvalue);
110699ebb4caSwyllys
110799ebb4caSwyllys return (ret);
110899ebb4caSwyllys }
110999ebb4caSwyllys
111099ebb4caSwyllys static KMF_RETURN
get_one_extension(BerElement * asn1,KMF_X509_EXTENSION ** retex,char * end)111199ebb4caSwyllys get_one_extension(BerElement *asn1, KMF_X509_EXTENSION **retex, char *end)
111299ebb4caSwyllys {
111399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
111499ebb4caSwyllys ber_len_t size;
111599ebb4caSwyllys int critical, tag;
111699ebb4caSwyllys KMF_X509_EXTENSION *ex = NULL;
111799ebb4caSwyllys BerValue extOID;
111899ebb4caSwyllys BerValue extValue;
111999ebb4caSwyllys BerElement *extnber = NULL;
112099ebb4caSwyllys
112199ebb4caSwyllys if (kmfber_scanf(asn1, "T", &tag) == -1) {
112299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
112399ebb4caSwyllys goto cleanup;
112499ebb4caSwyllys }
112599ebb4caSwyllys
112699ebb4caSwyllys tag = kmfber_next_element(asn1, &size, end);
112799ebb4caSwyllys if (tag != BER_OBJECT_IDENTIFIER) {
112899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
112999ebb4caSwyllys goto cleanup;
113099ebb4caSwyllys }
113199ebb4caSwyllys if (kmfber_scanf(asn1, "D", &extOID) == -1) {
113299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
113399ebb4caSwyllys goto cleanup;
113499ebb4caSwyllys }
113599ebb4caSwyllys
113699ebb4caSwyllys tag = kmfber_next_element(asn1, &size, end);
113799ebb4caSwyllys if (tag != BER_BOOLEAN) {
113899ebb4caSwyllys critical = 0;
113999ebb4caSwyllys if (tag != BER_OCTET_STRING)
114099ebb4caSwyllys goto cleanup;
114199ebb4caSwyllys } else {
114299ebb4caSwyllys if (kmfber_scanf(asn1, "b", &critical) == -1)
114399ebb4caSwyllys goto cleanup;
114499ebb4caSwyllys }
114599ebb4caSwyllys
114699ebb4caSwyllys tag = kmfber_next_element(asn1, &size, end);
114799ebb4caSwyllys if (tag != BER_OCTET_STRING) {
114899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
114999ebb4caSwyllys goto cleanup;
115099ebb4caSwyllys }
115199ebb4caSwyllys if (kmfber_scanf(asn1, "o", &extValue) == -1) {
115299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
115399ebb4caSwyllys goto cleanup;
115499ebb4caSwyllys }
115599ebb4caSwyllys
115699ebb4caSwyllys /* allocate a new Extension record */
115799ebb4caSwyllys ex = malloc(sizeof (KMF_X509_EXTENSION));
115899ebb4caSwyllys if (ex == NULL) {
115999ebb4caSwyllys ret = KMF_ERR_MEMORY;
116099ebb4caSwyllys goto cleanup;
116199ebb4caSwyllys }
116299ebb4caSwyllys (void) memset(ex, 0, sizeof (ex));
116399ebb4caSwyllys
116499ebb4caSwyllys ex->extnId.Data = (uchar_t *)extOID.bv_val;
116599ebb4caSwyllys ex->extnId.Length = extOID.bv_len;
116699ebb4caSwyllys ex->critical = critical;
116799ebb4caSwyllys ex->format = KMF_X509_DATAFORMAT_ENCODED;
116899ebb4caSwyllys ex->BERvalue.Data = (uchar_t *)extValue.bv_val;
116999ebb4caSwyllys ex->BERvalue.Length = extValue.bv_len;
117099ebb4caSwyllys
117199ebb4caSwyllys /* Tag and value is a little tricky */
117299ebb4caSwyllys ex->value.tagAndValue = malloc(sizeof (KMF_X509EXT_TAGandVALUE));
117399ebb4caSwyllys if (ex->value.tagAndValue == NULL) {
117499ebb4caSwyllys ret = KMF_ERR_MEMORY;
117599ebb4caSwyllys goto cleanup;
117699ebb4caSwyllys }
117799ebb4caSwyllys (void) memset(ex->value.tagAndValue, 0,
117899ebb4caSwyllys sizeof (KMF_X509EXT_TAGandVALUE));
117999ebb4caSwyllys
118099ebb4caSwyllys /* Parse the Extension value field */
118199ebb4caSwyllys extnber = kmfder_init(&extValue);
118299ebb4caSwyllys if (extnber == NULL) {
118399ebb4caSwyllys ret = KMF_ERR_MEMORY;
118499ebb4caSwyllys goto cleanup;
118599ebb4caSwyllys }
118699ebb4caSwyllys
118799ebb4caSwyllys /* Get the tag and length of the extension field */
118899ebb4caSwyllys if (kmfber_scanf(extnber, "tl", &tag, &size) == -1) {
118999ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
119099ebb4caSwyllys goto cleanup;
119199ebb4caSwyllys }
119299ebb4caSwyllys
119399ebb4caSwyllys if (kmfber_scanf(extnber, "T", &tag) == -1) {
119499ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
119599ebb4caSwyllys goto cleanup;
119699ebb4caSwyllys }
119799ebb4caSwyllys
119899ebb4caSwyllys ex->value.tagAndValue->value.Data = malloc(size);
119999ebb4caSwyllys ex->value.tagAndValue->value.Length = size;
120099ebb4caSwyllys size = kmfber_read(extnber,
120199ebb4caSwyllys (char *)ex->value.tagAndValue->value.Data, size);
120299ebb4caSwyllys if (size != ex->value.tagAndValue->value.Length) {
120399ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
120499ebb4caSwyllys goto cleanup;
120599ebb4caSwyllys }
120699ebb4caSwyllys kmfber_free(extnber, 1);
120799ebb4caSwyllys ex->value.tagAndValue->type = tag;
120899ebb4caSwyllys
120999ebb4caSwyllys *retex = ex;
121099ebb4caSwyllys cleanup:
121199ebb4caSwyllys if (ret != KMF_OK) {
121299ebb4caSwyllys if (ex != NULL)
121399ebb4caSwyllys free_one_extension(ex);
121499ebb4caSwyllys }
121599ebb4caSwyllys
121699ebb4caSwyllys return (ret);
121799ebb4caSwyllys }
121899ebb4caSwyllys
121999ebb4caSwyllys static KMF_RETURN
get_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)122099ebb4caSwyllys get_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
122199ebb4caSwyllys {
122299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
122399ebb4caSwyllys ber_len_t size;
122499ebb4caSwyllys char *end = NULL;
122599ebb4caSwyllys KMF_X509_EXTENSION *ex = NULL;
122699ebb4caSwyllys
122799ebb4caSwyllys /*
122899ebb4caSwyllys * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
122999ebb4caSwyllys *
123099ebb4caSwyllys * Extension ::= SEQUENCE {
123199ebb4caSwyllys * extnID OBJECT IDENTIFIER,
123299ebb4caSwyllys * critical BOOLEAN DEFAULT FALSE,
123399ebb4caSwyllys * extnValue OCTET STRING }
123499ebb4caSwyllys *
123599ebb4caSwyllys * { {{D}Bo}, ... }
123699ebb4caSwyllys */
123799ebb4caSwyllys if (kmfber_first_element(asn1, &size, &end) !=
123899ebb4caSwyllys BER_CONSTRUCTED_SEQUENCE)
123999ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
124099ebb4caSwyllys
124199ebb4caSwyllys while (kmfber_next_element(asn1, &size, end) ==
124299ebb4caSwyllys BER_CONSTRUCTED_SEQUENCE) {
124399ebb4caSwyllys ret = get_one_extension(asn1, &ex, end);
124499ebb4caSwyllys if (ret != KMF_OK)
124599ebb4caSwyllys goto cleanup;
124699ebb4caSwyllys
124799ebb4caSwyllys extns->numberOfExtensions++;
124899ebb4caSwyllys extns->extensions = realloc(extns->extensions,
124999ebb4caSwyllys extns->numberOfExtensions *
125099ebb4caSwyllys sizeof (KMF_X509_EXTENSION));
125199ebb4caSwyllys if (extns->extensions == NULL) {
125299ebb4caSwyllys ret = KMF_ERR_MEMORY;
125399ebb4caSwyllys break;
125499ebb4caSwyllys }
125599ebb4caSwyllys
125699ebb4caSwyllys extns->extensions[extns->numberOfExtensions-1] = *ex;
125799ebb4caSwyllys free(ex);
125899ebb4caSwyllys }
125999ebb4caSwyllys
126099ebb4caSwyllys cleanup:
126199ebb4caSwyllys if (ret != KMF_OK)
126299ebb4caSwyllys free_extensions(extns);
126399ebb4caSwyllys
126499ebb4caSwyllys return (ret);
126599ebb4caSwyllys }
126699ebb4caSwyllys
126799ebb4caSwyllys KMF_RETURN
decode_tbscert_data(BerElement * asn1,KMF_X509_TBS_CERT ** signed_cert_ptr_ptr)126899ebb4caSwyllys decode_tbscert_data(BerElement *asn1,
126999ebb4caSwyllys KMF_X509_TBS_CERT **signed_cert_ptr_ptr)
127099ebb4caSwyllys {
127199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
127299ebb4caSwyllys KMF_X509_TBS_CERT *tbscert = NULL;
127399ebb4caSwyllys int tag, version;
127499ebb4caSwyllys struct berval *bvserno = NULL;
127599ebb4caSwyllys KMF_BIGINT serno;
127699ebb4caSwyllys
127799ebb4caSwyllys if (kmfber_scanf(asn1, "{t", &tag) == -1) {
127899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
127999ebb4caSwyllys goto cleanup;
128099ebb4caSwyllys }
128199ebb4caSwyllys
128299ebb4caSwyllys /* Version number is optional */
128399ebb4caSwyllys if (tag == 0xA0) {
128499ebb4caSwyllys if (kmfber_scanf(asn1, "Ti", &tag, &version) == -1) {
128599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
128699ebb4caSwyllys goto cleanup;
128799ebb4caSwyllys }
128899ebb4caSwyllys } else {
128999ebb4caSwyllys version = 0; /* DEFAULT v1 (0) */
129099ebb4caSwyllys }
129199ebb4caSwyllys
129299ebb4caSwyllys /* Now get the serial number, it is not optional */
129399ebb4caSwyllys if (kmfber_scanf(asn1, "I", &bvserno) == -1) {
129499ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
129599ebb4caSwyllys goto cleanup;
129699ebb4caSwyllys } else {
129799ebb4caSwyllys serno.val = (uchar_t *)bvserno->bv_val;
129899ebb4caSwyllys serno.len = bvserno->bv_len;
129999ebb4caSwyllys }
130099ebb4caSwyllys
130199ebb4caSwyllys tbscert = malloc(sizeof (KMF_X509_TBS_CERT));
130299ebb4caSwyllys if (!tbscert) {
130399ebb4caSwyllys ret = KMF_ERR_MEMORY;
130499ebb4caSwyllys goto cleanup;
130599ebb4caSwyllys }
130699ebb4caSwyllys
130799ebb4caSwyllys (void) memset(tbscert, 0, sizeof (KMF_X509_TBS_CERT));
130899ebb4caSwyllys
130999ebb4caSwyllys if ((ret = set_der_integer(&tbscert->version, version)) != KMF_OK)
131099ebb4caSwyllys goto cleanup;
131199ebb4caSwyllys
131299ebb4caSwyllys if ((ret = set_bigint(&tbscert->serialNumber, &serno)) != KMF_OK)
131399ebb4caSwyllys goto cleanup;
131499ebb4caSwyllys
131599ebb4caSwyllys if ((ret = get_algoid(asn1, &tbscert->signature)) != KMF_OK)
131699ebb4caSwyllys goto cleanup;
131799ebb4caSwyllys
131899ebb4caSwyllys if ((ret = get_rdn(asn1, &tbscert->issuer)) != KMF_OK)
131999ebb4caSwyllys goto cleanup;
132099ebb4caSwyllys
132199ebb4caSwyllys if ((ret = get_validity(asn1, &tbscert->validity)) != KMF_OK)
132299ebb4caSwyllys goto cleanup;
132399ebb4caSwyllys
132499ebb4caSwyllys if ((ret = get_rdn(asn1, &tbscert->subject)) != KMF_OK)
132599ebb4caSwyllys goto cleanup;
132699ebb4caSwyllys
132799ebb4caSwyllys if ((ret = get_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
132899ebb4caSwyllys goto cleanup;
132999ebb4caSwyllys
133099ebb4caSwyllys /* Check for the optional fields */
133199ebb4caSwyllys tbscert->extensions.numberOfExtensions = 0;
133299ebb4caSwyllys tbscert->extensions.extensions = NULL;
133399ebb4caSwyllys
133499ebb4caSwyllys while ((kmfber_scanf(asn1, "t", &tag)) != -1 &&
133599ebb4caSwyllys (tag == 0xA1 || tag == 0xA2 || tag == 0xA3)) {
133699ebb4caSwyllys char *optfield;
133799ebb4caSwyllys ber_len_t len;
133899ebb4caSwyllys
133999ebb4caSwyllys /* consume the tag and length */
134099ebb4caSwyllys (void) kmfber_scanf(asn1, "T", &tag);
134199ebb4caSwyllys switch (tag) {
134299ebb4caSwyllys case 0xA1:
134399ebb4caSwyllys if (kmfber_scanf(asn1, "B", &optfield, &len) !=
134499ebb4caSwyllys BER_BIT_STRING) {
134599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
134699ebb4caSwyllys goto cleanup;
134799ebb4caSwyllys }
134899ebb4caSwyllys tbscert->issuerUniqueIdentifier.Data =
134999ebb4caSwyllys (uchar_t *)optfield;
135099ebb4caSwyllys tbscert->issuerUniqueIdentifier.Length =
135199ebb4caSwyllys len / 8;
135299ebb4caSwyllys break;
135399ebb4caSwyllys case 0xA2:
135499ebb4caSwyllys if (kmfber_scanf(asn1, "B", &optfield, &len) !=
135599ebb4caSwyllys BER_BIT_STRING) {
135699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
135799ebb4caSwyllys goto cleanup;
135899ebb4caSwyllys }
135999ebb4caSwyllys tbscert->subjectUniqueIdentifier.Data =
136099ebb4caSwyllys (uchar_t *)optfield;
136199ebb4caSwyllys tbscert->subjectUniqueIdentifier.Length =
136299ebb4caSwyllys len / 8;
136399ebb4caSwyllys break;
136499ebb4caSwyllys case 0xA3:
136599ebb4caSwyllys ret = get_extensions(asn1, &tbscert->extensions);
136699ebb4caSwyllys break;
136799ebb4caSwyllys }
136899ebb4caSwyllys }
136999ebb4caSwyllys
137099ebb4caSwyllys *signed_cert_ptr_ptr = tbscert;
137199ebb4caSwyllys
137299ebb4caSwyllys cleanup:
137399ebb4caSwyllys if (bvserno != NULL) {
137499ebb4caSwyllys free(bvserno->bv_val);
137599ebb4caSwyllys free(bvserno);
137699ebb4caSwyllys }
137799ebb4caSwyllys if (ret != KMF_OK) {
137899ebb4caSwyllys if (tbscert) {
137999ebb4caSwyllys free_tbscert(tbscert);
138099ebb4caSwyllys free(tbscert);
138199ebb4caSwyllys }
138299ebb4caSwyllys *signed_cert_ptr_ptr = NULL;
138399ebb4caSwyllys }
138499ebb4caSwyllys return (ret);
138599ebb4caSwyllys }
138699ebb4caSwyllys
138799ebb4caSwyllys KMF_RETURN
DerDecodeTbsCertificate(const KMF_DATA * Value,KMF_X509_TBS_CERT ** tbscert)138899ebb4caSwyllys DerDecodeTbsCertificate(const KMF_DATA *Value,
138999ebb4caSwyllys KMF_X509_TBS_CERT **tbscert)
139099ebb4caSwyllys {
139199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
139299ebb4caSwyllys BerElement *asn1 = NULL;
139399ebb4caSwyllys BerValue rawcert;
139499ebb4caSwyllys KMF_X509_TBS_CERT *newcert = NULL;
139599ebb4caSwyllys
139699ebb4caSwyllys if (!tbscert || !Value || !Value->Data || !Value->Length)
139799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
139899ebb4caSwyllys
139999ebb4caSwyllys rawcert.bv_val = (char *)Value->Data;
140099ebb4caSwyllys rawcert.bv_len = Value->Length;
140199ebb4caSwyllys
140299ebb4caSwyllys if ((asn1 = kmfder_init(&rawcert)) == NULL)
140399ebb4caSwyllys return (KMF_ERR_MEMORY);
140499ebb4caSwyllys
140599ebb4caSwyllys ret = decode_tbscert_data(asn1, &newcert);
140699ebb4caSwyllys if (ret != KMF_OK)
140799ebb4caSwyllys goto cleanup;
140899ebb4caSwyllys
140999ebb4caSwyllys *tbscert = newcert;
141099ebb4caSwyllys
141199ebb4caSwyllys cleanup:
141299ebb4caSwyllys if (ret != KMF_OK) {
141399ebb4caSwyllys if (newcert)
141499ebb4caSwyllys free_tbscert(newcert);
141599ebb4caSwyllys *tbscert = NULL;
141699ebb4caSwyllys }
141799ebb4caSwyllys kmfber_free(asn1, 1);
141899ebb4caSwyllys
141999ebb4caSwyllys return (ret);
142099ebb4caSwyllys }
142199ebb4caSwyllys
142299ebb4caSwyllys /*
142399ebb4caSwyllys * Name: DerDecodeSignedCertificate
142499ebb4caSwyllys *
142599ebb4caSwyllys * Description:
142699ebb4caSwyllys * DER decodes the encoded X509 certificate
142799ebb4caSwyllys *
142899ebb4caSwyllys * Parameters:
142999ebb4caSwyllys * Value (input): DER encoded object that shd be decoded
143099ebb4caSwyllys *
143199ebb4caSwyllys * signed_cert_ptr_ptr (output) : Decoded KMF_X509_CERTIFICATE object
143299ebb4caSwyllys */
143399ebb4caSwyllys KMF_RETURN
DerDecodeSignedCertificate(const KMF_DATA * Value,KMF_X509_CERTIFICATE ** signed_cert_ptr_ptr)143499ebb4caSwyllys DerDecodeSignedCertificate(const KMF_DATA *Value,
143599ebb4caSwyllys KMF_X509_CERTIFICATE **signed_cert_ptr_ptr)
143699ebb4caSwyllys {
143799ebb4caSwyllys KMF_RETURN ret = KMF_OK;
143899ebb4caSwyllys BerElement *asn1 = NULL;
143999ebb4caSwyllys BerValue rawcert;
144099ebb4caSwyllys ber_tag_t tag;
144199ebb4caSwyllys ber_len_t size;
144299ebb4caSwyllys char *end = NULL;
144399ebb4caSwyllys char *signature;
144499ebb4caSwyllys KMF_X509_TBS_CERT *tbscert = NULL;
144599ebb4caSwyllys KMF_X509_CERTIFICATE *certptr = NULL;
144699ebb4caSwyllys
144799ebb4caSwyllys if (!signed_cert_ptr_ptr || !Value || !Value->Data || !Value->Length)
144899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
144999ebb4caSwyllys
145099ebb4caSwyllys rawcert.bv_val = (char *)Value->Data;
145199ebb4caSwyllys rawcert.bv_len = Value->Length;
145299ebb4caSwyllys
145399ebb4caSwyllys if ((asn1 = kmfder_init(&rawcert)) == NULL)
145499ebb4caSwyllys return (KMF_ERR_MEMORY);
145599ebb4caSwyllys
145699ebb4caSwyllys if (kmfber_first_element(asn1, &size, &end) !=
145799ebb4caSwyllys BER_CONSTRUCTED_SEQUENCE) {
145899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
145999ebb4caSwyllys goto cleanup;
146099ebb4caSwyllys }
146199ebb4caSwyllys
146299ebb4caSwyllys certptr = malloc(sizeof (KMF_X509_CERTIFICATE));
146399ebb4caSwyllys if (certptr == NULL) {
146499ebb4caSwyllys ret = KMF_ERR_MEMORY;
146599ebb4caSwyllys goto cleanup;
146699ebb4caSwyllys }
146799ebb4caSwyllys (void) memset(certptr, 0, sizeof (KMF_X509_CERTIFICATE));
146899ebb4caSwyllys
146999ebb4caSwyllys ret = decode_tbscert_data(asn1, &tbscert);
147099ebb4caSwyllys if (ret != KMF_OK)
147199ebb4caSwyllys goto cleanup;
147299ebb4caSwyllys
147399ebb4caSwyllys certptr->certificate = *tbscert;
147499ebb4caSwyllys free(tbscert);
147599ebb4caSwyllys tbscert = NULL;
147699ebb4caSwyllys
147799ebb4caSwyllys /*
147899ebb4caSwyllys * The signature data my not be present yet.
147999ebb4caSwyllys */
148099ebb4caSwyllys if ((ret = get_algoid(asn1,
148199ebb4caSwyllys &certptr->signature.algorithmIdentifier)) == KMF_OK) {
148299ebb4caSwyllys
148399ebb4caSwyllys /* Check to see if the cert has a signature yet */
148499ebb4caSwyllys if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
148599ebb4caSwyllys /* Finally, get the encrypted signature BITSTRING */
148699ebb4caSwyllys if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
148799ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
148899ebb4caSwyllys goto cleanup;
148999ebb4caSwyllys }
149099ebb4caSwyllys if (tag != BER_BIT_STRING) {
149199ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
149299ebb4caSwyllys goto cleanup;
149399ebb4caSwyllys }
149499ebb4caSwyllys if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
149599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
149699ebb4caSwyllys goto cleanup;
149799ebb4caSwyllys }
149899ebb4caSwyllys certptr->signature.encrypted.Data =
149999ebb4caSwyllys (uchar_t *)signature;
150099ebb4caSwyllys certptr->signature.encrypted.Length = size / 8;
150199ebb4caSwyllys } else {
150299ebb4caSwyllys certptr->signature.encrypted.Data = NULL;
150399ebb4caSwyllys certptr->signature.encrypted.Length = 0;
150499ebb4caSwyllys }
150599ebb4caSwyllys } else {
150699ebb4caSwyllys (void) memset(&certptr->signature, 0,
150799ebb4caSwyllys sizeof (certptr->signature));
150899ebb4caSwyllys ret = KMF_OK;
150999ebb4caSwyllys }
151099ebb4caSwyllys
151199ebb4caSwyllys *signed_cert_ptr_ptr = certptr;
151299ebb4caSwyllys cleanup:
151399ebb4caSwyllys if (ret != KMF_OK) {
151499ebb4caSwyllys if (certptr) {
151599ebb4caSwyllys free_decoded_cert(certptr);
151699ebb4caSwyllys free(certptr);
151799ebb4caSwyllys }
151899ebb4caSwyllys
151999ebb4caSwyllys *signed_cert_ptr_ptr = NULL;
152099ebb4caSwyllys }
152199ebb4caSwyllys if (asn1)
152299ebb4caSwyllys kmfber_free(asn1, 1);
152399ebb4caSwyllys
152499ebb4caSwyllys return (ret);
152599ebb4caSwyllys
152699ebb4caSwyllys }
152799ebb4caSwyllys
152899ebb4caSwyllys KMF_RETURN
DerDecodeExtension(KMF_DATA * Data,KMF_X509_EXTENSION ** extn)152999ebb4caSwyllys DerDecodeExtension(KMF_DATA *Data, KMF_X509_EXTENSION **extn)
153099ebb4caSwyllys {
153199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
153299ebb4caSwyllys BerElement *asn1 = NULL;
153399ebb4caSwyllys BerValue bv;
153499ebb4caSwyllys
153599ebb4caSwyllys bv.bv_val = (char *)Data->Data;
153699ebb4caSwyllys bv.bv_len = Data->Length;
153799ebb4caSwyllys
153899ebb4caSwyllys asn1 = kmfder_init(&bv);
153999ebb4caSwyllys if (asn1 == NULL)
154099ebb4caSwyllys return (KMF_ERR_MEMORY);
154199ebb4caSwyllys
154299ebb4caSwyllys ret = get_one_extension(asn1, extn, NULL);
154399ebb4caSwyllys
154499ebb4caSwyllys cleanup:
154599ebb4caSwyllys if (ret != KMF_OK) {
154699ebb4caSwyllys if (*extn != NULL) {
154799ebb4caSwyllys free(*extn);
154899ebb4caSwyllys }
154999ebb4caSwyllys *extn = NULL;
155099ebb4caSwyllys }
155199ebb4caSwyllys
155299ebb4caSwyllys kmfber_free(asn1, 1);
155399ebb4caSwyllys return (ret);
155499ebb4caSwyllys }
155599ebb4caSwyllys
155699ebb4caSwyllys KMF_RETURN
DerDecodeName(KMF_DATA * encodedname,KMF_X509_NAME * name)155799ebb4caSwyllys DerDecodeName(KMF_DATA *encodedname, KMF_X509_NAME *name)
155899ebb4caSwyllys {
155999ebb4caSwyllys KMF_RETURN ret = KMF_OK;
156099ebb4caSwyllys BerElement *asn1 = NULL;
156199ebb4caSwyllys BerValue bv;
156299ebb4caSwyllys
156399ebb4caSwyllys bv.bv_val = (char *)encodedname->Data;
156499ebb4caSwyllys bv.bv_len = encodedname->Length;
156599ebb4caSwyllys
156699ebb4caSwyllys asn1 = kmfder_init(&bv);
156799ebb4caSwyllys if (asn1 == NULL)
156899ebb4caSwyllys return (KMF_ERR_MEMORY);
156999ebb4caSwyllys
157099ebb4caSwyllys (void) memset((void *)name, 0, sizeof (KMF_X509_NAME));
157199ebb4caSwyllys
157299ebb4caSwyllys if ((ret = get_rdn(asn1, name)) != KMF_OK)
157399ebb4caSwyllys goto cleanup;
157499ebb4caSwyllys
157599ebb4caSwyllys cleanup:
157699ebb4caSwyllys if (asn1)
157799ebb4caSwyllys kmfber_free(asn1, 1);
157899ebb4caSwyllys return (ret);
157999ebb4caSwyllys }
158099ebb4caSwyllys
158199ebb4caSwyllys KMF_RETURN
DerEncodeName(KMF_X509_NAME * name,KMF_DATA * encodedname)158299ebb4caSwyllys DerEncodeName(KMF_X509_NAME *name, KMF_DATA *encodedname)
158399ebb4caSwyllys {
158499ebb4caSwyllys KMF_RETURN ret = KMF_OK;
158599ebb4caSwyllys BerElement *asn1 = NULL;
158699ebb4caSwyllys BerValue *bv = NULL;
158799ebb4caSwyllys
158899ebb4caSwyllys asn1 = kmfder_alloc();
158999ebb4caSwyllys if (asn1 == NULL)
159099ebb4caSwyllys return (KMF_ERR_MEMORY);
159199ebb4caSwyllys
159299ebb4caSwyllys if ((ret = encode_rdn(asn1, name)) != KMF_OK)
159399ebb4caSwyllys goto cleanup;
159499ebb4caSwyllys
159599ebb4caSwyllys if (kmfber_flatten(asn1, &bv) == -1) {
159699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
159799ebb4caSwyllys goto cleanup;
159899ebb4caSwyllys }
159999ebb4caSwyllys
160099ebb4caSwyllys encodedname->Data = (uchar_t *)bv->bv_val;
160199ebb4caSwyllys encodedname->Length = bv->bv_len;
160299ebb4caSwyllys
160399ebb4caSwyllys cleanup:
160499ebb4caSwyllys if (bv)
160599ebb4caSwyllys free(bv);
160699ebb4caSwyllys
160799ebb4caSwyllys if (asn1)
160899ebb4caSwyllys kmfber_free(asn1, 1);
160999ebb4caSwyllys
161099ebb4caSwyllys return (ret);
161199ebb4caSwyllys }
161299ebb4caSwyllys
161399ebb4caSwyllys static KMF_RETURN
encode_tbs_cert(BerElement * asn1,KMF_X509_TBS_CERT * tbscert)161499ebb4caSwyllys encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert)
161599ebb4caSwyllys {
161699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
161799ebb4caSwyllys uint32_t version;
161899ebb4caSwyllys
161999ebb4caSwyllys /* version should be 4 bytes or less */
162099ebb4caSwyllys if (tbscert->version.Length > sizeof (int))
162199ebb4caSwyllys return (KMF_ERR_BAD_CERT_FORMAT);
162299ebb4caSwyllys
162399ebb4caSwyllys (void) memcpy(&version, tbscert->version.Data,
162499ebb4caSwyllys tbscert->version.Length);
162599ebb4caSwyllys
162699ebb4caSwyllys /* Start the sequence and add the version */
162799ebb4caSwyllys if (kmfber_printf(asn1, "{Tli", 0xA0, 3, version) == -1) {
162899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
162999ebb4caSwyllys goto cleanup;
163099ebb4caSwyllys }
163199ebb4caSwyllys /* Write the serial number */
163299ebb4caSwyllys if (kmfber_printf(asn1, "I",
163399ebb4caSwyllys (char *)tbscert->serialNumber.val,
163499ebb4caSwyllys (size_t)tbscert->serialNumber.len) == -1) {
163599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
163699ebb4caSwyllys goto cleanup;
163799ebb4caSwyllys }
163899ebb4caSwyllys
1639*e65e5c2dSWyllys Ingersoll /* Don't encode alg parameters in signature algid area */
1640*e65e5c2dSWyllys Ingersoll if ((ret = encode_algoid(asn1, &tbscert->signature, FALSE)) != KMF_OK)
164199ebb4caSwyllys goto cleanup;
164299ebb4caSwyllys
164399ebb4caSwyllys /* Encode the Issuer RDN */
164499ebb4caSwyllys if ((ret = encode_rdn(asn1, &tbscert->issuer)) != KMF_OK)
164599ebb4caSwyllys goto cleanup;
164699ebb4caSwyllys
164799ebb4caSwyllys /* Encode the Validity fields */
164899ebb4caSwyllys if ((ret = encode_validity(asn1, &tbscert->validity)) != KMF_OK)
164999ebb4caSwyllys goto cleanup;
165099ebb4caSwyllys
165199ebb4caSwyllys /* Encode the Subject RDN */
165299ebb4caSwyllys if ((ret = encode_rdn(asn1, &tbscert->subject)) != KMF_OK)
165399ebb4caSwyllys goto cleanup;
165499ebb4caSwyllys
165599ebb4caSwyllys /* Encode the Subject Public Key Info */
165699ebb4caSwyllys if ((ret = encode_spki(asn1, &tbscert->subjectPublicKeyInfo)) != KMF_OK)
165799ebb4caSwyllys goto cleanup;
165899ebb4caSwyllys
165999ebb4caSwyllys /* Optional field: issuer Unique ID */
166099ebb4caSwyllys if (tbscert->issuerUniqueIdentifier.Length > 0) {
166199ebb4caSwyllys if ((ret = encode_uniqueid(asn1, 0xA1,
166299ebb4caSwyllys &tbscert->issuerUniqueIdentifier)) != KMF_OK)
166399ebb4caSwyllys goto cleanup;
166499ebb4caSwyllys }
166599ebb4caSwyllys
166699ebb4caSwyllys /* Optional field: Subject Unique ID */
166799ebb4caSwyllys if (tbscert->subjectUniqueIdentifier.Length > 0) {
166899ebb4caSwyllys if ((ret = encode_uniqueid(asn1, 0xA2,
166999ebb4caSwyllys &tbscert->subjectUniqueIdentifier)) != KMF_OK)
167099ebb4caSwyllys goto cleanup;
167199ebb4caSwyllys }
167299ebb4caSwyllys
167399ebb4caSwyllys /* Optional field: Certificate Extensions */
167499ebb4caSwyllys if (tbscert->extensions.numberOfExtensions > 0) {
167599ebb4caSwyllys if ((ret = encode_extensions(asn1,
167699ebb4caSwyllys &tbscert->extensions)) != KMF_OK)
167799ebb4caSwyllys goto cleanup;
167899ebb4caSwyllys }
167999ebb4caSwyllys
168099ebb4caSwyllys /* Close out the TBSCert sequence */
168199ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
168299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
168399ebb4caSwyllys goto cleanup;
168499ebb4caSwyllys }
168599ebb4caSwyllys
168699ebb4caSwyllys cleanup:
168799ebb4caSwyllys /*
168899ebb4caSwyllys * Memory cleanup is done in the caller or in the individual
168999ebb4caSwyllys * encoding routines.
169099ebb4caSwyllys */
169199ebb4caSwyllys
169299ebb4caSwyllys return (ret);
169399ebb4caSwyllys }
169499ebb4caSwyllys
169599ebb4caSwyllys KMF_RETURN
DerEncodeTbsCertificate(KMF_X509_TBS_CERT * tbs_cert_ptr,KMF_DATA * enc_tbs_cert_ptr)169699ebb4caSwyllys DerEncodeTbsCertificate(KMF_X509_TBS_CERT *tbs_cert_ptr,
169799ebb4caSwyllys KMF_DATA *enc_tbs_cert_ptr)
169899ebb4caSwyllys {
169999ebb4caSwyllys KMF_RETURN ret;
170099ebb4caSwyllys BerElement *asn1 = NULL;
170199ebb4caSwyllys BerValue *tbsdata = NULL;
170299ebb4caSwyllys
170399ebb4caSwyllys asn1 = kmfder_alloc();
170499ebb4caSwyllys if (asn1 == NULL)
170599ebb4caSwyllys return (KMF_ERR_MEMORY);
170699ebb4caSwyllys
170799ebb4caSwyllys enc_tbs_cert_ptr->Data = NULL;
170899ebb4caSwyllys enc_tbs_cert_ptr->Length = 0;
170999ebb4caSwyllys
171099ebb4caSwyllys ret = encode_tbs_cert(asn1, tbs_cert_ptr);
171199ebb4caSwyllys if (ret != KMF_OK)
171299ebb4caSwyllys goto cleanup;
171399ebb4caSwyllys
171499ebb4caSwyllys if (kmfber_flatten(asn1, &tbsdata) == -1) {
171599ebb4caSwyllys ret = KMF_ERR_MEMORY;
171699ebb4caSwyllys goto cleanup;
171799ebb4caSwyllys }
171899ebb4caSwyllys
171999ebb4caSwyllys enc_tbs_cert_ptr->Data = (uchar_t *)tbsdata->bv_val;
172099ebb4caSwyllys enc_tbs_cert_ptr->Length = tbsdata->bv_len;
172199ebb4caSwyllys
172299ebb4caSwyllys cleanup:
172399ebb4caSwyllys if (ret != KMF_OK)
172499ebb4caSwyllys free_data(enc_tbs_cert_ptr);
172599ebb4caSwyllys
172699ebb4caSwyllys if (asn1 != NULL)
172799ebb4caSwyllys kmfber_free(asn1, 1);
172899ebb4caSwyllys
172999ebb4caSwyllys if (tbsdata)
173099ebb4caSwyllys free(tbsdata);
173199ebb4caSwyllys
173299ebb4caSwyllys return (ret);
173399ebb4caSwyllys }
173499ebb4caSwyllys
173599ebb4caSwyllys KMF_RETURN
DerEncodeSignedCertificate(KMF_X509_CERTIFICATE * signed_cert_ptr,KMF_DATA * encodedcert)173699ebb4caSwyllys DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr,
173799ebb4caSwyllys KMF_DATA *encodedcert)
173899ebb4caSwyllys {
173999ebb4caSwyllys KMF_RETURN ret = KMF_OK;
174099ebb4caSwyllys KMF_X509_TBS_CERT *tbscert = NULL;
174199ebb4caSwyllys KMF_X509_SIGNATURE *signature = NULL;
174299ebb4caSwyllys BerElement *asn1 = NULL;
174399ebb4caSwyllys BerValue *tbsdata = NULL;
174499ebb4caSwyllys
174599ebb4caSwyllys if (signed_cert_ptr == NULL || encodedcert == NULL)
174699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
174799ebb4caSwyllys
174899ebb4caSwyllys encodedcert->Data = NULL;
174999ebb4caSwyllys encodedcert->Length = 0;
175099ebb4caSwyllys
175199ebb4caSwyllys tbscert = &signed_cert_ptr->certificate;
175299ebb4caSwyllys signature = &signed_cert_ptr->signature;
175399ebb4caSwyllys
175499ebb4caSwyllys asn1 = kmfder_alloc();
175599ebb4caSwyllys if (asn1 == NULL)
175699ebb4caSwyllys return (KMF_ERR_MEMORY);
175799ebb4caSwyllys
175899ebb4caSwyllys /* Start outer X509 Certificate SEQUENCE */
175999ebb4caSwyllys if (kmfber_printf(asn1, "{") == -1) {
176099ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
176199ebb4caSwyllys goto cleanup;
176299ebb4caSwyllys }
176399ebb4caSwyllys
176499ebb4caSwyllys if ((ret = encode_tbs_cert(asn1, tbscert)) != KMF_OK) {
176599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
176699ebb4caSwyllys goto cleanup;
176799ebb4caSwyllys }
176899ebb4caSwyllys
1769*e65e5c2dSWyllys Ingersoll /* Add the Algorithm & Signature Sequence (no parameters) */
177099ebb4caSwyllys if ((ret = encode_algoid(asn1,
1771*e65e5c2dSWyllys Ingersoll &signature->algorithmIdentifier, FALSE)) != KMF_OK)
177299ebb4caSwyllys goto cleanup;
177399ebb4caSwyllys
177499ebb4caSwyllys if (signature->encrypted.Length > 0) {
177599ebb4caSwyllys if (kmfber_printf(asn1, "B", signature->encrypted.Data,
177699ebb4caSwyllys signature->encrypted.Length * 8) == -1) {
177799ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
177899ebb4caSwyllys goto cleanup;
177999ebb4caSwyllys }
178099ebb4caSwyllys }
178199ebb4caSwyllys
178299ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
178399ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
178499ebb4caSwyllys goto cleanup;
178599ebb4caSwyllys }
178699ebb4caSwyllys
178799ebb4caSwyllys if (kmfber_flatten(asn1, &tbsdata) == -1) {
178899ebb4caSwyllys ret = KMF_ERR_MEMORY;
178999ebb4caSwyllys goto cleanup;
179099ebb4caSwyllys }
179199ebb4caSwyllys
179299ebb4caSwyllys encodedcert->Data = (uchar_t *)tbsdata->bv_val;
179399ebb4caSwyllys encodedcert->Length = tbsdata->bv_len;
179499ebb4caSwyllys
179599ebb4caSwyllys cleanup:
179699ebb4caSwyllys if (ret != KMF_OK)
179799ebb4caSwyllys free_data(encodedcert);
179899ebb4caSwyllys
179999ebb4caSwyllys if (tbsdata)
180099ebb4caSwyllys free(tbsdata);
180199ebb4caSwyllys
180299ebb4caSwyllys if (asn1)
180399ebb4caSwyllys kmfber_free(asn1, 1);
180499ebb4caSwyllys
180599ebb4caSwyllys return (ret);
180699ebb4caSwyllys }
180799ebb4caSwyllys
180899ebb4caSwyllys KMF_RETURN
ExtractX509CertParts(KMF_DATA * x509cert,KMF_DATA * tbscert,KMF_DATA * signature)180999ebb4caSwyllys ExtractX509CertParts(KMF_DATA *x509cert, KMF_DATA *tbscert,
181099ebb4caSwyllys KMF_DATA *signature)
181199ebb4caSwyllys {
181299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
181399ebb4caSwyllys BerElement *der = NULL;
181499ebb4caSwyllys BerValue x509;
181599ebb4caSwyllys ber_tag_t tag;
181699ebb4caSwyllys ber_len_t size;
181799ebb4caSwyllys
181899ebb4caSwyllys if (tbscert == NULL || x509cert == NULL)
181999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
182099ebb4caSwyllys
182199ebb4caSwyllys x509.bv_val = (char *)x509cert->Data;
182299ebb4caSwyllys x509.bv_len = x509cert->Length;
182399ebb4caSwyllys
182499ebb4caSwyllys der = kmfder_init(&x509);
182599ebb4caSwyllys if (der == NULL)
182699ebb4caSwyllys return (KMF_ERR_MEMORY);
182799ebb4caSwyllys
182899ebb4caSwyllys /* Skip over the overall Sequence tag to get at the TBS Cert data */
182999ebb4caSwyllys if (kmfber_scanf(der, "Tl", &tag, &size) == -1) {
183099ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
183199ebb4caSwyllys goto cleanup;
183299ebb4caSwyllys }
183399ebb4caSwyllys if (tag != BER_CONSTRUCTED_SEQUENCE) {
183499ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
183599ebb4caSwyllys goto cleanup;
183699ebb4caSwyllys }
183799ebb4caSwyllys
183899ebb4caSwyllys /*
183999ebb4caSwyllys * Since we are extracting a copy of the ENCODED bytes, we
184099ebb4caSwyllys * must make sure to also include the bytes for the tag and
184199ebb4caSwyllys * the length fields for the CONSTRUCTED SEQUENCE (TBSCert).
184299ebb4caSwyllys */
184399ebb4caSwyllys size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
184499ebb4caSwyllys
184599ebb4caSwyllys tbscert->Data = malloc(size);
184699ebb4caSwyllys if (tbscert->Data == NULL) {
184799ebb4caSwyllys ret = KMF_ERR_MEMORY;
184899ebb4caSwyllys goto cleanup;
184999ebb4caSwyllys }
185099ebb4caSwyllys tbscert->Length = size;
185199ebb4caSwyllys
185299ebb4caSwyllys /* The der data ptr is now set to the start of the TBS cert sequence */
185399ebb4caSwyllys size = kmfber_read(der, (char *)tbscert->Data, tbscert->Length);
185499ebb4caSwyllys if (size != tbscert->Length) {
185599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
185699ebb4caSwyllys goto cleanup;
185799ebb4caSwyllys }
185899ebb4caSwyllys
185999ebb4caSwyllys if (signature != NULL) {
186099ebb4caSwyllys KMF_X509_ALGORITHM_IDENTIFIER algoid;
186199ebb4caSwyllys if ((ret = get_algoid(der, &algoid)) != KMF_OK)
186299ebb4caSwyllys goto cleanup;
186399ebb4caSwyllys free_algoid(&algoid);
186499ebb4caSwyllys
186599ebb4caSwyllys if (kmfber_scanf(der, "tl", &tag, &size) != BER_BIT_STRING) {
186699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
186799ebb4caSwyllys goto cleanup;
186899ebb4caSwyllys }
186999ebb4caSwyllys /* Now get the signature data */
187099ebb4caSwyllys if (kmfber_scanf(der, "B", (char **)&signature->Data,
187199ebb4caSwyllys (ber_len_t *)&signature->Length) == -1) {
187299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
187399ebb4caSwyllys goto cleanup;
187499ebb4caSwyllys }
187599ebb4caSwyllys /* convert bitstring length to bytes */
187699ebb4caSwyllys signature->Length = signature->Length / 8;
187799ebb4caSwyllys }
187899ebb4caSwyllys
187999ebb4caSwyllys cleanup:
188099ebb4caSwyllys if (der)
188199ebb4caSwyllys kmfber_free(der, 1);
188299ebb4caSwyllys
188399ebb4caSwyllys if (ret != KMF_OK)
188499ebb4caSwyllys free_data(tbscert);
188599ebb4caSwyllys
188699ebb4caSwyllys return (ret);
188799ebb4caSwyllys }
188899ebb4caSwyllys
188999ebb4caSwyllys static KMF_RETURN
decode_csr_extensions(BerElement * asn1,KMF_X509_EXTENSIONS * extns)189099ebb4caSwyllys decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
189199ebb4caSwyllys {
189299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
189399ebb4caSwyllys BerValue oid;
189499ebb4caSwyllys
189599ebb4caSwyllys if (kmfber_scanf(asn1, "{D", &oid) == -1) {
189699ebb4caSwyllys return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
189799ebb4caSwyllys }
189899ebb4caSwyllys
189999ebb4caSwyllys /* We only understand extension requests in a CSR */
190099ebb4caSwyllys if (memcmp(oid.bv_val, extension_request_oid.Data,
190199ebb4caSwyllys oid.bv_len) != 0) {
190299ebb4caSwyllys return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
190399ebb4caSwyllys }
190499ebb4caSwyllys
190599ebb4caSwyllys if (kmfber_scanf(asn1, "[") == -1) {
190699ebb4caSwyllys return (KMF_ERR_ENCODING);
190799ebb4caSwyllys }
190899ebb4caSwyllys ret = get_extensions(asn1, extns);
190999ebb4caSwyllys
191099ebb4caSwyllys
191199ebb4caSwyllys return (ret);
191299ebb4caSwyllys }
191399ebb4caSwyllys
191499ebb4caSwyllys static KMF_RETURN
decode_tbscsr_data(BerElement * asn1,KMF_TBS_CSR ** signed_csr_ptr_ptr)191599ebb4caSwyllys decode_tbscsr_data(BerElement *asn1,
191699ebb4caSwyllys KMF_TBS_CSR **signed_csr_ptr_ptr)
191799ebb4caSwyllys {
191899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
191999ebb4caSwyllys KMF_TBS_CSR *tbscsr = NULL;
192099ebb4caSwyllys char *end = NULL;
192199ebb4caSwyllys uint32_t version;
192299ebb4caSwyllys ber_tag_t tag;
192399ebb4caSwyllys ber_len_t size;
192499ebb4caSwyllys
192599ebb4caSwyllys /* Now get the version number, it is not optional */
192699ebb4caSwyllys if (kmfber_scanf(asn1, "{i", &version) == -1) {
192799ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
192899ebb4caSwyllys goto cleanup;
192999ebb4caSwyllys }
193099ebb4caSwyllys
193199ebb4caSwyllys tbscsr = malloc(sizeof (KMF_TBS_CSR));
193299ebb4caSwyllys if (!tbscsr) {
193399ebb4caSwyllys ret = KMF_ERR_MEMORY;
193499ebb4caSwyllys goto cleanup;
193599ebb4caSwyllys }
193699ebb4caSwyllys
193799ebb4caSwyllys (void) memset(tbscsr, 0, sizeof (KMF_TBS_CSR));
193899ebb4caSwyllys
193999ebb4caSwyllys if ((ret = set_der_integer(&tbscsr->version, version)) != KMF_OK)
194099ebb4caSwyllys goto cleanup;
194199ebb4caSwyllys
194299ebb4caSwyllys if ((ret = get_rdn(asn1, &tbscsr->subject)) != KMF_OK)
194399ebb4caSwyllys goto cleanup;
194499ebb4caSwyllys
194599ebb4caSwyllys if ((ret = get_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
194699ebb4caSwyllys goto cleanup;
194799ebb4caSwyllys
194899ebb4caSwyllys /* Check for the optional fields (attributes) */
194999ebb4caSwyllys if (kmfber_next_element(asn1, &size, end) == 0xA0) {
195099ebb4caSwyllys if (kmfber_scanf(asn1, "Tl", &tag, &size) == -1) {
195199ebb4caSwyllys ret = KMF_ERR_ENCODING;
195299ebb4caSwyllys goto cleanup;
195399ebb4caSwyllys }
195499ebb4caSwyllys
195599ebb4caSwyllys ret = decode_csr_extensions(asn1, &tbscsr->extensions);
195699ebb4caSwyllys }
195799ebb4caSwyllys if (ret == KMF_OK)
195899ebb4caSwyllys *signed_csr_ptr_ptr = tbscsr;
195999ebb4caSwyllys
196099ebb4caSwyllys cleanup:
196199ebb4caSwyllys if (ret != KMF_OK) {
196299ebb4caSwyllys if (tbscsr) {
196399ebb4caSwyllys free_tbscsr(tbscsr);
196499ebb4caSwyllys free(tbscsr);
196599ebb4caSwyllys }
196699ebb4caSwyllys *signed_csr_ptr_ptr = NULL;
196799ebb4caSwyllys }
196899ebb4caSwyllys return (ret);
196999ebb4caSwyllys }
197099ebb4caSwyllys
197199ebb4caSwyllys KMF_RETURN
DerDecodeTbsCsr(const KMF_DATA * Value,KMF_TBS_CSR ** tbscsr)197299ebb4caSwyllys DerDecodeTbsCsr(const KMF_DATA *Value,
197399ebb4caSwyllys KMF_TBS_CSR **tbscsr)
197499ebb4caSwyllys {
197599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
197699ebb4caSwyllys BerElement *asn1 = NULL;
197799ebb4caSwyllys BerValue rawcsr;
197899ebb4caSwyllys KMF_TBS_CSR *newcsr = NULL;
197999ebb4caSwyllys
198099ebb4caSwyllys if (!tbscsr || !Value || !Value->Data || !Value->Length)
198199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
198299ebb4caSwyllys
198399ebb4caSwyllys rawcsr.bv_val = (char *)Value->Data;
198499ebb4caSwyllys rawcsr.bv_len = Value->Length;
198599ebb4caSwyllys
198699ebb4caSwyllys if ((asn1 = kmfder_init(&rawcsr)) == NULL)
198799ebb4caSwyllys return (KMF_ERR_MEMORY);
198899ebb4caSwyllys
198999ebb4caSwyllys ret = decode_tbscsr_data(asn1, &newcsr);
199099ebb4caSwyllys if (ret != KMF_OK)
199199ebb4caSwyllys goto cleanup;
199299ebb4caSwyllys
199399ebb4caSwyllys *tbscsr = newcsr;
199499ebb4caSwyllys
199599ebb4caSwyllys cleanup:
199699ebb4caSwyllys if (ret != KMF_OK) {
199799ebb4caSwyllys if (newcsr)
199899ebb4caSwyllys free_tbscsr(newcsr);
199999ebb4caSwyllys *tbscsr = NULL;
200099ebb4caSwyllys }
200199ebb4caSwyllys kmfber_free(asn1, 1);
200299ebb4caSwyllys
200399ebb4caSwyllys return (ret);
200499ebb4caSwyllys }
200599ebb4caSwyllys
200699ebb4caSwyllys KMF_RETURN
DerDecodeSignedCsr(const KMF_DATA * Value,KMF_CSR_DATA ** signed_csr_ptr_ptr)200799ebb4caSwyllys DerDecodeSignedCsr(const KMF_DATA *Value,
200899ebb4caSwyllys KMF_CSR_DATA **signed_csr_ptr_ptr)
200999ebb4caSwyllys {
201099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
201199ebb4caSwyllys BerElement *asn1 = NULL;
201299ebb4caSwyllys BerValue rawcsr;
201399ebb4caSwyllys int tag;
201499ebb4caSwyllys ber_len_t size;
201599ebb4caSwyllys char *end = NULL;
201699ebb4caSwyllys char *signature;
201799ebb4caSwyllys KMF_TBS_CSR *tbscsr = NULL;
201899ebb4caSwyllys KMF_CSR_DATA *csrptr = NULL;
201999ebb4caSwyllys
202099ebb4caSwyllys if (!signed_csr_ptr_ptr || !Value || !Value->Data || !Value->Length)
202199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
202299ebb4caSwyllys
202399ebb4caSwyllys rawcsr.bv_val = (char *)Value->Data;
202499ebb4caSwyllys rawcsr.bv_len = Value->Length;
202599ebb4caSwyllys
202699ebb4caSwyllys if ((asn1 = kmfder_init(&rawcsr)) == NULL)
202799ebb4caSwyllys return (KMF_ERR_MEMORY);
202899ebb4caSwyllys
202999ebb4caSwyllys if (kmfber_first_element(asn1, &size, &end) !=
203099ebb4caSwyllys BER_CONSTRUCTED_SEQUENCE) {
203199ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
203299ebb4caSwyllys goto cleanup;
203399ebb4caSwyllys }
203499ebb4caSwyllys
203599ebb4caSwyllys csrptr = malloc(sizeof (KMF_CSR_DATA));
203699ebb4caSwyllys if (csrptr == NULL) {
203799ebb4caSwyllys ret = KMF_ERR_MEMORY;
203899ebb4caSwyllys goto cleanup;
203999ebb4caSwyllys }
204099ebb4caSwyllys (void) memset(csrptr, 0, sizeof (KMF_CSR_DATA));
204199ebb4caSwyllys
204299ebb4caSwyllys ret = decode_tbscsr_data(asn1, &tbscsr);
204399ebb4caSwyllys if (ret != KMF_OK)
204499ebb4caSwyllys goto cleanup;
204599ebb4caSwyllys
204699ebb4caSwyllys csrptr->csr = *tbscsr;
204799ebb4caSwyllys free(tbscsr);
204899ebb4caSwyllys tbscsr = NULL;
204999ebb4caSwyllys
205099ebb4caSwyllys if ((ret = get_algoid(asn1,
205199ebb4caSwyllys &csrptr->signature.algorithmIdentifier)) != KMF_OK)
205299ebb4caSwyllys goto cleanup;
205399ebb4caSwyllys
205499ebb4caSwyllys /* Check to see if the cert has a signature yet */
205599ebb4caSwyllys if (kmfber_next_element(asn1, &size, end) == BER_BIT_STRING) {
205699ebb4caSwyllys /* Finally, get the encrypted signature BITSTRING */
205799ebb4caSwyllys if (kmfber_scanf(asn1, "tl", &tag, &size) == -1) {
205899ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
205999ebb4caSwyllys goto cleanup;
206099ebb4caSwyllys }
206199ebb4caSwyllys if (tag != BER_BIT_STRING) {
206299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
206399ebb4caSwyllys goto cleanup;
206499ebb4caSwyllys }
206599ebb4caSwyllys if (kmfber_scanf(asn1, "B}", &signature, &size) == -1) {
206699ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
206799ebb4caSwyllys goto cleanup;
206899ebb4caSwyllys }
206999ebb4caSwyllys csrptr->signature.encrypted.Data = (uchar_t *)signature;
207099ebb4caSwyllys csrptr->signature.encrypted.Length = size / 8;
207199ebb4caSwyllys } else {
207299ebb4caSwyllys csrptr->signature.encrypted.Data = NULL;
207399ebb4caSwyllys csrptr->signature.encrypted.Length = 0;
207499ebb4caSwyllys }
207599ebb4caSwyllys
207699ebb4caSwyllys *signed_csr_ptr_ptr = csrptr;
207799ebb4caSwyllys cleanup:
207899ebb4caSwyllys if (ret != KMF_OK) {
207999ebb4caSwyllys free_tbscsr(&csrptr->csr);
208099ebb4caSwyllys free_algoid(&csrptr->signature.algorithmIdentifier);
208199ebb4caSwyllys if (csrptr->signature.encrypted.Data)
208299ebb4caSwyllys free(csrptr->signature.encrypted.Data);
208399ebb4caSwyllys
208499ebb4caSwyllys if (csrptr)
208599ebb4caSwyllys free(csrptr);
208699ebb4caSwyllys
208799ebb4caSwyllys *signed_csr_ptr_ptr = NULL;
208899ebb4caSwyllys }
208999ebb4caSwyllys if (asn1)
209099ebb4caSwyllys kmfber_free(asn1, 1);
209199ebb4caSwyllys
209299ebb4caSwyllys return (ret);
209399ebb4caSwyllys
209499ebb4caSwyllys }
209599ebb4caSwyllys
209699ebb4caSwyllys static KMF_RETURN
encode_csr_extensions(BerElement * asn1,KMF_TBS_CSR * tbscsr)209799ebb4caSwyllys encode_csr_extensions(BerElement *asn1, KMF_TBS_CSR *tbscsr)
209899ebb4caSwyllys {
209999ebb4caSwyllys KMF_RETURN ret = KMF_OK;
210099ebb4caSwyllys int attlen = 0;
210199ebb4caSwyllys BerElement *extnasn1 = NULL;
210299ebb4caSwyllys BerValue *extnvalue = NULL;
210399ebb4caSwyllys
210499ebb4caSwyllys /* Optional field: CSR attributes and extensions */
210599ebb4caSwyllys if (tbscsr->extensions.numberOfExtensions > 0) {
210699ebb4caSwyllys if (kmfber_printf(asn1, "T", 0xA0) == -1) {
210799ebb4caSwyllys ret = KMF_ERR_ENCODING;
210899ebb4caSwyllys goto cleanup;
210999ebb4caSwyllys }
211099ebb4caSwyllys } else {
211199ebb4caSwyllys /* No extensions or attributes to encode */
211299ebb4caSwyllys return (KMF_OK);
211399ebb4caSwyllys }
211499ebb4caSwyllys
211599ebb4caSwyllys /*
211699ebb4caSwyllys * attributes [0] Attributes
211799ebb4caSwyllys * Attributes := SET OF Attribute
211899ebb4caSwyllys * Attribute := SEQUENCE {
211999ebb4caSwyllys * { ATTRIBUTE ID
212099ebb4caSwyllys * values SET SIZE(1..MAX) of ATTRIBUTE
212199ebb4caSwyllys * }
212299ebb4caSwyllys *
212399ebb4caSwyllys * Ex: { ExtensionRequest OID [ { {extn1 } , {extn2 } } ] }
212499ebb4caSwyllys */
212599ebb4caSwyllys
212699ebb4caSwyllys /*
212799ebb4caSwyllys * Encode any extensions and add to the attributes section.
212899ebb4caSwyllys */
212999ebb4caSwyllys if (tbscsr->extensions.numberOfExtensions > 0) {
213099ebb4caSwyllys extnasn1 = kmfder_alloc();
213199ebb4caSwyllys if (extnasn1 == NULL) {
213299ebb4caSwyllys ret = KMF_ERR_MEMORY;
213399ebb4caSwyllys goto cleanup;
213499ebb4caSwyllys }
213599ebb4caSwyllys
213699ebb4caSwyllys if (kmfber_printf(extnasn1, "{D[{",
213799ebb4caSwyllys &extension_request_oid) == -1) {
213899ebb4caSwyllys ret = KMF_ERR_ENCODING;
213999ebb4caSwyllys goto cleanup_1;
214099ebb4caSwyllys }
214199ebb4caSwyllys
214299ebb4caSwyllys if ((ret = encode_extension_list(extnasn1,
214399ebb4caSwyllys &tbscsr->extensions)) != KMF_OK) {
214499ebb4caSwyllys goto cleanup_1;
214599ebb4caSwyllys }
214699ebb4caSwyllys
214799ebb4caSwyllys if (kmfber_printf(extnasn1, "}]}") == -1) {
214899ebb4caSwyllys ret = KMF_ERR_ENCODING;
214999ebb4caSwyllys goto cleanup_1;
215099ebb4caSwyllys }
215199ebb4caSwyllys
215299ebb4caSwyllys if (kmfber_flatten(extnasn1, &extnvalue) == -1) {
215399ebb4caSwyllys ret = KMF_ERR_MEMORY;
215499ebb4caSwyllys goto cleanup_1;
215599ebb4caSwyllys }
215699ebb4caSwyllys cleanup_1:
215799ebb4caSwyllys kmfber_free(extnasn1, 1);
215899ebb4caSwyllys
215999ebb4caSwyllys if (ret == KMF_OK)
216099ebb4caSwyllys /* Add 2 bytes to cover the tag and the length */
216199ebb4caSwyllys attlen = extnvalue->bv_len;
216299ebb4caSwyllys }
216399ebb4caSwyllys if (ret != KMF_OK)
216499ebb4caSwyllys goto cleanup;
216599ebb4caSwyllys
216699ebb4caSwyllys if (kmfber_printf(asn1, "l", attlen) == -1) {
216799ebb4caSwyllys ret = KMF_ERR_ENCODING;
216899ebb4caSwyllys goto cleanup;
216999ebb4caSwyllys }
217099ebb4caSwyllys
217199ebb4caSwyllys /* Write the actual encoded extensions */
217299ebb4caSwyllys if (extnvalue != NULL && extnvalue->bv_val != NULL) {
217399ebb4caSwyllys if (kmfber_write(asn1, extnvalue->bv_val,
217499ebb4caSwyllys extnvalue->bv_len, 0) == -1) {
217599ebb4caSwyllys ret = KMF_ERR_ENCODING;
217699ebb4caSwyllys goto cleanup;
217799ebb4caSwyllys }
217899ebb4caSwyllys }
217999ebb4caSwyllys
218099ebb4caSwyllys cleanup:
218199ebb4caSwyllys /*
218299ebb4caSwyllys * Memory cleanup is done in the caller or in the individual
218399ebb4caSwyllys * encoding routines.
218499ebb4caSwyllys */
218599ebb4caSwyllys if (extnvalue) {
218699ebb4caSwyllys if (extnvalue->bv_val)
218799ebb4caSwyllys free(extnvalue->bv_val);
218899ebb4caSwyllys free(extnvalue);
218999ebb4caSwyllys }
219099ebb4caSwyllys
219199ebb4caSwyllys return (ret);
219299ebb4caSwyllys }
219399ebb4caSwyllys
219499ebb4caSwyllys static KMF_RETURN
encode_tbs_csr(BerElement * asn1,KMF_TBS_CSR * tbscsr)219599ebb4caSwyllys encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr)
219699ebb4caSwyllys {
219799ebb4caSwyllys KMF_RETURN ret = KMF_OK;
219899ebb4caSwyllys uint32_t version;
219999ebb4caSwyllys
220099ebb4caSwyllys /* Start the version */
220199ebb4caSwyllys (void) memcpy(&version, tbscsr->version.Data,
220299ebb4caSwyllys tbscsr->version.Length);
220399ebb4caSwyllys
220402b8f7bbSwyllys if (kmfber_printf(asn1, "{i", version) == -1) {
220599ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
220699ebb4caSwyllys goto cleanup;
220799ebb4caSwyllys }
220899ebb4caSwyllys
220999ebb4caSwyllys /* Encode the Subject RDN */
221099ebb4caSwyllys if ((ret = encode_rdn(asn1, &tbscsr->subject)) != KMF_OK)
221199ebb4caSwyllys goto cleanup;
221299ebb4caSwyllys
221399ebb4caSwyllys /* Encode the Subject Public Key Info */
221499ebb4caSwyllys if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
221599ebb4caSwyllys goto cleanup;
221699ebb4caSwyllys
221799ebb4caSwyllys if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK)
221899ebb4caSwyllys goto cleanup;
221999ebb4caSwyllys
222099ebb4caSwyllys /* Close out the TBSCert sequence */
222199ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
222299ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
222399ebb4caSwyllys goto cleanup;
222499ebb4caSwyllys }
222599ebb4caSwyllys
222699ebb4caSwyllys cleanup:
222799ebb4caSwyllys return (ret);
222899ebb4caSwyllys }
222999ebb4caSwyllys
223099ebb4caSwyllys KMF_RETURN
DerEncodeDSAPrivateKey(KMF_DATA * encodedkey,KMF_RAW_DSA_KEY * dsa)223199ebb4caSwyllys DerEncodeDSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_DSA_KEY *dsa)
223299ebb4caSwyllys {
223399ebb4caSwyllys KMF_RETURN rv = KMF_OK;
223499ebb4caSwyllys BerElement *asn1 = NULL;
223599ebb4caSwyllys BerValue *dsadata = NULL;
223699ebb4caSwyllys
223799ebb4caSwyllys asn1 = kmfder_alloc();
223899ebb4caSwyllys if (asn1 == NULL)
223999ebb4caSwyllys return (KMF_ERR_MEMORY);
224099ebb4caSwyllys
224199ebb4caSwyllys if (kmfber_printf(asn1, "I",
224299ebb4caSwyllys dsa->value.val, dsa->value.len) == -1) {
224399ebb4caSwyllys rv = KMF_ERR_MEMORY;
224499ebb4caSwyllys goto cleanup;
224599ebb4caSwyllys }
224699ebb4caSwyllys
224799ebb4caSwyllys if (kmfber_flatten(asn1, &dsadata) == -1) {
224899ebb4caSwyllys rv = KMF_ERR_MEMORY;
224999ebb4caSwyllys goto cleanup;
225099ebb4caSwyllys }
225199ebb4caSwyllys
225299ebb4caSwyllys encodedkey->Data = (uchar_t *)dsadata->bv_val;
225399ebb4caSwyllys encodedkey->Length = dsadata->bv_len;
225499ebb4caSwyllys
225599ebb4caSwyllys free(dsadata);
225699ebb4caSwyllys cleanup:
225799ebb4caSwyllys kmfber_free(asn1, 1);
225899ebb4caSwyllys return (rv);
225999ebb4caSwyllys }
226099ebb4caSwyllys
226199ebb4caSwyllys KMF_RETURN
DerEncodeRSAPrivateKey(KMF_DATA * encodedkey,KMF_RAW_RSA_KEY * rsa)226299ebb4caSwyllys DerEncodeRSAPrivateKey(KMF_DATA *encodedkey, KMF_RAW_RSA_KEY *rsa)
226399ebb4caSwyllys {
226499ebb4caSwyllys KMF_RETURN rv = KMF_OK;
226599ebb4caSwyllys BerElement *asn1 = NULL;
226699ebb4caSwyllys uchar_t ver = 0;
226799ebb4caSwyllys BerValue *rsadata = NULL;
226899ebb4caSwyllys
226999ebb4caSwyllys asn1 = kmfder_alloc();
227099ebb4caSwyllys if (asn1 == NULL)
227199ebb4caSwyllys return (KMF_ERR_MEMORY);
227299ebb4caSwyllys
227399ebb4caSwyllys if (kmfber_printf(asn1, "{IIIIIIIII}",
227499ebb4caSwyllys &ver, 1,
227599ebb4caSwyllys rsa->mod.val, rsa->mod.len,
227699ebb4caSwyllys rsa->pubexp.val, rsa->pubexp.len,
227799ebb4caSwyllys rsa->priexp.val, rsa->priexp.len,
227899ebb4caSwyllys rsa->prime1.val, rsa->prime1.len,
227999ebb4caSwyllys rsa->prime2.val, rsa->prime2.len,
228099ebb4caSwyllys rsa->exp1.val, rsa->exp1.len,
228199ebb4caSwyllys rsa->exp2.val, rsa->exp2.len,
228299ebb4caSwyllys rsa->coef.val, rsa->coef.len) == -1)
228399ebb4caSwyllys goto cleanup;
228499ebb4caSwyllys
228599ebb4caSwyllys if (kmfber_flatten(asn1, &rsadata) == -1) {
228699ebb4caSwyllys rv = KMF_ERR_MEMORY;
228799ebb4caSwyllys goto cleanup;
228899ebb4caSwyllys }
228999ebb4caSwyllys
229099ebb4caSwyllys encodedkey->Data = (uchar_t *)rsadata->bv_val;
229199ebb4caSwyllys encodedkey->Length = rsadata->bv_len;
229299ebb4caSwyllys
229399ebb4caSwyllys free(rsadata);
229499ebb4caSwyllys cleanup:
229599ebb4caSwyllys kmfber_free(asn1, 1);
229699ebb4caSwyllys return (rv);
229799ebb4caSwyllys }
229899ebb4caSwyllys
2299*e65e5c2dSWyllys Ingersoll KMF_RETURN
DerEncodeECPrivateKey(KMF_DATA * encodedkey,KMF_RAW_EC_KEY * eckey)2300*e65e5c2dSWyllys Ingersoll DerEncodeECPrivateKey(KMF_DATA *encodedkey, KMF_RAW_EC_KEY *eckey)
2301*e65e5c2dSWyllys Ingersoll {
2302*e65e5c2dSWyllys Ingersoll KMF_RETURN rv = KMF_OK;
2303*e65e5c2dSWyllys Ingersoll BerElement *asn1 = NULL;
2304*e65e5c2dSWyllys Ingersoll uchar_t ver = 1;
2305*e65e5c2dSWyllys Ingersoll BerValue *data = NULL;
2306*e65e5c2dSWyllys Ingersoll
2307*e65e5c2dSWyllys Ingersoll asn1 = kmfder_alloc();
2308*e65e5c2dSWyllys Ingersoll if (asn1 == NULL)
2309*e65e5c2dSWyllys Ingersoll return (KMF_ERR_MEMORY);
2310*e65e5c2dSWyllys Ingersoll
2311*e65e5c2dSWyllys Ingersoll if (kmfber_printf(asn1, "{io",
2312*e65e5c2dSWyllys Ingersoll ver, eckey->value.val, eckey->value.len) == -1) {
2313*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_ENCODING;
2314*e65e5c2dSWyllys Ingersoll goto cleanup;
2315*e65e5c2dSWyllys Ingersoll }
2316*e65e5c2dSWyllys Ingersoll /*
2317*e65e5c2dSWyllys Ingersoll * Indicate that we are using the named curve option
2318*e65e5c2dSWyllys Ingersoll * for the parameters.
2319*e65e5c2dSWyllys Ingersoll */
2320*e65e5c2dSWyllys Ingersoll if (kmfber_printf(asn1, "T", 0xA0) == -1) {
2321*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_ENCODING;
2322*e65e5c2dSWyllys Ingersoll goto cleanup;
2323*e65e5c2dSWyllys Ingersoll }
2324*e65e5c2dSWyllys Ingersoll if (kmfber_printf(asn1, "l", eckey->params.Length) == -1) {
2325*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_ENCODING;
2326*e65e5c2dSWyllys Ingersoll goto cleanup;
2327*e65e5c2dSWyllys Ingersoll }
2328*e65e5c2dSWyllys Ingersoll if (kmfber_write(asn1, (char *)eckey->params.Data,
2329*e65e5c2dSWyllys Ingersoll eckey->params.Length, 0) == -1) {
2330*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_ENCODING;
2331*e65e5c2dSWyllys Ingersoll goto cleanup;
2332*e65e5c2dSWyllys Ingersoll }
2333*e65e5c2dSWyllys Ingersoll if (kmfber_printf(asn1, "}") == -1) {
2334*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_ENCODING;
2335*e65e5c2dSWyllys Ingersoll goto cleanup;
2336*e65e5c2dSWyllys Ingersoll }
2337*e65e5c2dSWyllys Ingersoll if (kmfber_flatten(asn1, &data) == -1) {
2338*e65e5c2dSWyllys Ingersoll rv = KMF_ERR_MEMORY;
2339*e65e5c2dSWyllys Ingersoll goto cleanup;
2340*e65e5c2dSWyllys Ingersoll }
2341*e65e5c2dSWyllys Ingersoll encodedkey->Data = (uchar_t *)data->bv_val;
2342*e65e5c2dSWyllys Ingersoll encodedkey->Length = data->bv_len;
2343*e65e5c2dSWyllys Ingersoll
2344*e65e5c2dSWyllys Ingersoll cleanup:
2345*e65e5c2dSWyllys Ingersoll kmfber_free(asn1, 1);
2346*e65e5c2dSWyllys Ingersoll return (rv);
2347*e65e5c2dSWyllys Ingersoll }
2348*e65e5c2dSWyllys Ingersoll
234999ebb4caSwyllys
235099ebb4caSwyllys KMF_RETURN
DerEncodeTbsCsr(KMF_TBS_CSR * tbs_csr_ptr,KMF_DATA * enc_tbs_csr_ptr)235199ebb4caSwyllys DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr,
235299ebb4caSwyllys KMF_DATA *enc_tbs_csr_ptr)
235399ebb4caSwyllys {
235499ebb4caSwyllys KMF_RETURN ret;
235599ebb4caSwyllys BerValue *tbsdata = NULL;
235699ebb4caSwyllys BerElement *asn1 = NULL;
235799ebb4caSwyllys
235899ebb4caSwyllys asn1 = kmfder_alloc();
235999ebb4caSwyllys
236099ebb4caSwyllys enc_tbs_csr_ptr->Data = NULL;
236199ebb4caSwyllys enc_tbs_csr_ptr->Length = 0;
236299ebb4caSwyllys
236399ebb4caSwyllys if (asn1 == NULL)
236499ebb4caSwyllys return (KMF_ERR_MEMORY);
236599ebb4caSwyllys
236699ebb4caSwyllys ret = encode_tbs_csr(asn1, tbs_csr_ptr);
236799ebb4caSwyllys if (ret != KMF_OK)
236899ebb4caSwyllys goto cleanup;
236999ebb4caSwyllys
237099ebb4caSwyllys if (kmfber_flatten(asn1, &tbsdata) == -1) {
237199ebb4caSwyllys ret = KMF_ERR_MEMORY;
237299ebb4caSwyllys goto cleanup;
237399ebb4caSwyllys }
237499ebb4caSwyllys
237599ebb4caSwyllys enc_tbs_csr_ptr->Data = (uchar_t *)tbsdata->bv_val;
237699ebb4caSwyllys enc_tbs_csr_ptr->Length = tbsdata->bv_len;
237799ebb4caSwyllys
237899ebb4caSwyllys cleanup:
237999ebb4caSwyllys if (ret != KMF_OK)
238099ebb4caSwyllys free_data(enc_tbs_csr_ptr);
238199ebb4caSwyllys
238299ebb4caSwyllys if (asn1 != NULL)
238399ebb4caSwyllys kmfber_free(asn1, 1);
238499ebb4caSwyllys
238599ebb4caSwyllys if (tbsdata)
238699ebb4caSwyllys free(tbsdata);
238799ebb4caSwyllys
238899ebb4caSwyllys return (ret);
238999ebb4caSwyllys }
239099ebb4caSwyllys
239199ebb4caSwyllys KMF_RETURN
DerEncodeSignedCsr(KMF_CSR_DATA * signed_csr_ptr,KMF_DATA * encodedcsr)239299ebb4caSwyllys DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr,
239399ebb4caSwyllys KMF_DATA *encodedcsr)
239499ebb4caSwyllys {
239599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
239699ebb4caSwyllys KMF_TBS_CSR *tbscsr = NULL;
239799ebb4caSwyllys KMF_X509_SIGNATURE *signature = NULL;
239899ebb4caSwyllys BerElement *asn1 = NULL;
239999ebb4caSwyllys BerValue *tbsdata = NULL;
240099ebb4caSwyllys
240199ebb4caSwyllys if (signed_csr_ptr == NULL)
240299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
240399ebb4caSwyllys
240499ebb4caSwyllys tbscsr = &signed_csr_ptr->csr;
240599ebb4caSwyllys signature = &signed_csr_ptr->signature;
240699ebb4caSwyllys
240799ebb4caSwyllys asn1 = kmfder_alloc();
240899ebb4caSwyllys if (asn1 == NULL)
240999ebb4caSwyllys return (KMF_ERR_MEMORY);
241099ebb4caSwyllys
241199ebb4caSwyllys /* Start outer CSR SEQUENCE */
241299ebb4caSwyllys if (kmfber_printf(asn1, "{") == -1) {
241399ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
241499ebb4caSwyllys goto cleanup;
241599ebb4caSwyllys }
241699ebb4caSwyllys
241799ebb4caSwyllys ret = encode_tbs_csr(asn1, tbscsr);
241899ebb4caSwyllys
241999ebb4caSwyllys /* Add the Algorithm & Signature Sequence */
242099ebb4caSwyllys if ((ret = encode_algoid(asn1,
2421*e65e5c2dSWyllys Ingersoll &signature->algorithmIdentifier, FALSE)) != KMF_OK)
242299ebb4caSwyllys goto cleanup;
242399ebb4caSwyllys
242499ebb4caSwyllys if (signature->encrypted.Length > 0) {
242599ebb4caSwyllys if (kmfber_printf(asn1, "B", signature->encrypted.Data,
242699ebb4caSwyllys signature->encrypted.Length * 8) == -1) {
242799ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
242899ebb4caSwyllys goto cleanup;
242999ebb4caSwyllys }
243099ebb4caSwyllys }
243199ebb4caSwyllys
243299ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
243399ebb4caSwyllys ret = KMF_ERR_BAD_CERT_FORMAT;
243499ebb4caSwyllys goto cleanup;
243599ebb4caSwyllys }
243699ebb4caSwyllys
243799ebb4caSwyllys if (kmfber_flatten(asn1, &tbsdata) == -1) {
243899ebb4caSwyllys ret = KMF_ERR_MEMORY;
243999ebb4caSwyllys goto cleanup;
244099ebb4caSwyllys }
244199ebb4caSwyllys
244299ebb4caSwyllys encodedcsr->Data = (uchar_t *)tbsdata->bv_val;
244399ebb4caSwyllys encodedcsr->Length = tbsdata->bv_len;
244499ebb4caSwyllys
244599ebb4caSwyllys cleanup:
244699ebb4caSwyllys if (ret != KMF_OK) {
244799ebb4caSwyllys free_data(encodedcsr);
244899ebb4caSwyllys }
244999ebb4caSwyllys
245099ebb4caSwyllys if (tbsdata)
245199ebb4caSwyllys free(tbsdata);
245299ebb4caSwyllys
245399ebb4caSwyllys if (asn1)
245499ebb4caSwyllys kmfber_free(asn1, 1);
245599ebb4caSwyllys return (ret);
245699ebb4caSwyllys }
245799ebb4caSwyllys
2458*e65e5c2dSWyllys Ingersoll static KMF_RETURN
ber_copy_data(KMF_DATA * dst,KMF_DATA * src)2459*e65e5c2dSWyllys Ingersoll ber_copy_data(KMF_DATA *dst, KMF_DATA *src)
2460*e65e5c2dSWyllys Ingersoll {
2461*e65e5c2dSWyllys Ingersoll KMF_RETURN ret = KMF_OK;
2462*e65e5c2dSWyllys Ingersoll
2463*e65e5c2dSWyllys Ingersoll if (dst == NULL || src == NULL)
2464*e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_PARAMETER);
2465*e65e5c2dSWyllys Ingersoll
2466*e65e5c2dSWyllys Ingersoll dst->Data = malloc(src->Length);
2467*e65e5c2dSWyllys Ingersoll if (dst->Data == NULL)
2468*e65e5c2dSWyllys Ingersoll return (KMF_ERR_MEMORY);
2469*e65e5c2dSWyllys Ingersoll
2470*e65e5c2dSWyllys Ingersoll dst->Length = src->Length;
2471*e65e5c2dSWyllys Ingersoll (void) memcpy(dst->Data, src->Data, src->Length);
2472*e65e5c2dSWyllys Ingersoll
2473*e65e5c2dSWyllys Ingersoll return (ret);
2474*e65e5c2dSWyllys Ingersoll }
2475*e65e5c2dSWyllys Ingersoll
247699ebb4caSwyllys KMF_RETURN
ExtractSPKIData(const KMF_X509_SPKI * pKey,KMF_ALGORITHM_INDEX AlgorithmId,KMF_DATA * pKeyParts,uint32_t * uNumKeyParts)247799ebb4caSwyllys ExtractSPKIData(
247899ebb4caSwyllys const KMF_X509_SPKI *pKey,
247999ebb4caSwyllys KMF_ALGORITHM_INDEX AlgorithmId,
248099ebb4caSwyllys KMF_DATA *pKeyParts,
248199ebb4caSwyllys uint32_t *uNumKeyParts)
248299ebb4caSwyllys {
248399ebb4caSwyllys KMF_RETURN ret = KMF_OK;
248499ebb4caSwyllys BerElement *asn1 = NULL;
248599ebb4caSwyllys BerValue *P, *Q, *G, *Mod, *Exp, *PubKey;
248699ebb4caSwyllys BerValue PubKeyParams, PubKeyData;
248799ebb4caSwyllys
248899ebb4caSwyllys if (pKeyParts == NULL || uNumKeyParts == NULL || pKey == NULL)
248999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
249099ebb4caSwyllys
249199ebb4caSwyllys switch (AlgorithmId) {
249299ebb4caSwyllys case KMF_ALGID_DSA:
249399ebb4caSwyllys case KMF_ALGID_SHA1WithDSA:
24942cbed729Swyllys *uNumKeyParts = 0;
24952cbed729Swyllys /* Get the parameters from the algorithm definition */
24962cbed729Swyllys PubKeyParams.bv_val =
24972cbed729Swyllys (char *)pKey->algorithm.parameters.Data;
249899ebb4caSwyllys PubKeyParams.bv_len = pKey->algorithm.parameters.Length;
249999ebb4caSwyllys if ((asn1 = kmfder_init(&PubKeyParams)) == NULL)
250099ebb4caSwyllys return (KMF_ERR_MEMORY);
250199ebb4caSwyllys
250299ebb4caSwyllys if (kmfber_scanf(asn1, "{III}", &P, &Q, &G) == -1) {
250399ebb4caSwyllys kmfber_free(asn1, 1);
250499ebb4caSwyllys return (KMF_ERR_BAD_KEY_FORMAT);
250599ebb4caSwyllys }
250699ebb4caSwyllys pKeyParts[KMF_DSA_PRIME].Data = (uchar_t *)P->bv_val;
250799ebb4caSwyllys pKeyParts[KMF_DSA_PRIME].Length = P->bv_len;
25082cbed729Swyllys pKeyParts[KMF_DSA_SUB_PRIME].Data =
25092cbed729Swyllys (uchar_t *)Q->bv_val;
251099ebb4caSwyllys pKeyParts[KMF_DSA_SUB_PRIME].Length = Q->bv_len;
251199ebb4caSwyllys pKeyParts[KMF_DSA_BASE].Data = (uchar_t *)G->bv_val;
251299ebb4caSwyllys pKeyParts[KMF_DSA_BASE].Length = G->bv_len;
251399ebb4caSwyllys
251499ebb4caSwyllys free(P);
251599ebb4caSwyllys free(Q);
251699ebb4caSwyllys free(G);
251799ebb4caSwyllys kmfber_free(asn1, 1);
251899ebb4caSwyllys
251999ebb4caSwyllys /* Get the PubKey data */
252099ebb4caSwyllys PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
252199ebb4caSwyllys PubKeyData.bv_len = pKey->subjectPublicKey.Length;
252299ebb4caSwyllys if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
252399ebb4caSwyllys ret = KMF_ERR_MEMORY;
252499ebb4caSwyllys goto cleanup;
252599ebb4caSwyllys }
252699ebb4caSwyllys PubKey = NULL;
252799ebb4caSwyllys if (kmfber_scanf(asn1, "I", &PubKey) == -1) {
252899ebb4caSwyllys ret = KMF_ERR_BAD_KEY_FORMAT;
252999ebb4caSwyllys goto cleanup;
253099ebb4caSwyllys }
253199ebb4caSwyllys pKeyParts[KMF_DSA_PUBLIC_VALUE].Data =
253299ebb4caSwyllys (uchar_t *)PubKey->bv_val;
253399ebb4caSwyllys pKeyParts[KMF_DSA_PUBLIC_VALUE].Length = PubKey->bv_len;
253499ebb4caSwyllys
253599ebb4caSwyllys free(PubKey);
253699ebb4caSwyllys
253799ebb4caSwyllys *uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS;
253899ebb4caSwyllys break;
2539*e65e5c2dSWyllys Ingersoll case KMF_ALGID_SHA1WithECDSA:
2540*e65e5c2dSWyllys Ingersoll case KMF_ALGID_ECDSA:
2541*e65e5c2dSWyllys Ingersoll (void) ber_copy_data(&pKeyParts[KMF_ECDSA_PARAMS],
2542*e65e5c2dSWyllys Ingersoll (KMF_DATA *)&pKey->algorithm.parameters);
2543*e65e5c2dSWyllys Ingersoll
2544*e65e5c2dSWyllys Ingersoll (void) ber_copy_data(&pKeyParts[KMF_ECDSA_POINT],
2545*e65e5c2dSWyllys Ingersoll (KMF_DATA *)&pKey->subjectPublicKey);
2546*e65e5c2dSWyllys Ingersoll
2547*e65e5c2dSWyllys Ingersoll *uNumKeyParts = 2;
2548*e65e5c2dSWyllys Ingersoll break;
254999ebb4caSwyllys
255099ebb4caSwyllys case KMF_ALGID_RSA:
255199ebb4caSwyllys case KMF_ALGID_MD2WithRSA:
255299ebb4caSwyllys case KMF_ALGID_MD5WithRSA:
255399ebb4caSwyllys case KMF_ALGID_SHA1WithRSA:
25542cbed729Swyllys *uNumKeyParts = 0;
255599ebb4caSwyllys PubKeyData.bv_val = (char *)pKey->subjectPublicKey.Data;
255699ebb4caSwyllys PubKeyData.bv_len = pKey->subjectPublicKey.Length;
255799ebb4caSwyllys if ((asn1 = kmfder_init(&PubKeyData)) == NULL) {
255899ebb4caSwyllys ret = KMF_ERR_MEMORY;
255999ebb4caSwyllys goto cleanup;
256099ebb4caSwyllys }
256199ebb4caSwyllys if (kmfber_scanf(asn1, "{II}", &Mod, &Exp) == -1) {
256299ebb4caSwyllys ret = KMF_ERR_BAD_KEY_FORMAT;
256399ebb4caSwyllys goto cleanup;
256499ebb4caSwyllys }
25652cbed729Swyllys pKeyParts[KMF_RSA_MODULUS].Data =
25662cbed729Swyllys (uchar_t *)Mod->bv_val;
256799ebb4caSwyllys pKeyParts[KMF_RSA_MODULUS].Length = Mod->bv_len;
256899ebb4caSwyllys pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Data =
256999ebb4caSwyllys (uchar_t *)Exp->bv_val;
257099ebb4caSwyllys pKeyParts[KMF_RSA_PUBLIC_EXPONENT].Length = Exp->bv_len;
257199ebb4caSwyllys *uNumKeyParts = KMF_NUMBER_RSA_PUBLIC_KEY_PARTS;
257299ebb4caSwyllys
257399ebb4caSwyllys free(Mod);
257499ebb4caSwyllys free(Exp);
257599ebb4caSwyllys break;
257699ebb4caSwyllys default:
257799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
257899ebb4caSwyllys }
257999ebb4caSwyllys cleanup:
258099ebb4caSwyllys if (ret != KMF_OK) {
258199ebb4caSwyllys int i;
258299ebb4caSwyllys for (i = 0; i < *uNumKeyParts; i++)
258399ebb4caSwyllys free_data(&pKeyParts[i]);
258499ebb4caSwyllys }
258599ebb4caSwyllys if (asn1 != NULL) {
258699ebb4caSwyllys kmfber_free(asn1, 1);
258799ebb4caSwyllys }
258899ebb4caSwyllys
258999ebb4caSwyllys return (ret);
259099ebb4caSwyllys }
2591