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 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 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 6799ebb4caSwyllys free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid) 6899ebb4caSwyllys { 6999ebb4caSwyllys free_data(&algoid->algorithm); 7099ebb4caSwyllys free_data(&algoid->parameters); 7199ebb4caSwyllys } 7299ebb4caSwyllys 7399ebb4caSwyllys static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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