From 9b261c008a395a323e0516f4cd3f3134aa050577 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 Jun 2009 19:06:16 +1000 Subject: s4:heimdal: import lorikeet-heimdal-200906080040 (commit 904d0124b46eed7a8ad6e5b73e892ff34b6865ba) Also including the supporting changes required to pass make test A number of heimdal functions and constants have changed since we last imported a tree (for the better, but inconvenient for us). Andrew Bartlett --- source4/heimdal/lib/hx509/cms.c | 478 +++++++++++++++++++++++++++------------- 1 file changed, 327 insertions(+), 151 deletions(-) (limited to 'source4/heimdal/lib/hx509/cms.c') diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c index ba1800ddf2..4766c34655 100644 --- a/source4/heimdal/lib/hx509/cms.c +++ b/source4/heimdal/lib/hx509/cms.c @@ -32,7 +32,6 @@ */ #include "hx_locl.h" -RCSID("$Id$"); /** * @page page_cms CMS/PKCS7 message functions. @@ -474,6 +473,9 @@ hx509_cms_unenvelope(hx509_context context, if (ret) goto out; + if (flags & HX509_CMS_UE_ALLOW_WEAK) + hx509_crypto_allow_weak(crypto); + if (params) { ret = hx509_crypto_set_params(context, crypto, params, &ivec); if (ret) { @@ -527,7 +529,9 @@ out: * used to RSA. * * @param context A hx509 context. - * @param flags flags to control the behavior, no flags today + * @param flags flags to control the behavior. + * - HX509_CMS_EV_NO_KU_CHECK - Dont check KU on certificate + * - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo * @param cert Certificate to encrypt the EnvelopedData encryption key * with. * @param data pointer the data to encrypt. @@ -565,16 +569,21 @@ hx509_cms_envelope_1(hx509_context context, memset(content, 0, sizeof(*content)); if (encryption_type == NULL) - encryption_type = oid_id_aes_256_cbc(); + encryption_type = &asn1_oid_id_aes_256_cbc; - ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); - if (ret) - goto out; + if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) { + ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); + if (ret) + goto out; + } ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); if (ret) goto out; + if (flags & HX509_CMS_EV_ALLOW_WEAK) + hx509_crypto_allow_weak(crypto); + ret = hx509_crypto_set_random_key(crypto, &key); if (ret) { hx509_set_error_string(context, 0, ret, @@ -738,12 +747,16 @@ find_attribute(const CMSAttributes *attr, const heim_oid *oid) * Decode SignedData and verify that the signature is correct. * * @param context A hx509 context. - * @param ctx a hx509 version context - * @param data + * @param ctx a hx509 verify context. + * @param flags to control the behaivor of the function. + * - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage + * - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch + * - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below. + * @param data pointer to CMS SignedData encoded data. * @param length length of the data that data point to. - * @param signedContent + * @param signedContent external data used for signature. * @param pool certificate pool to build certificates paths. - * @param contentType free with der_free_oid() + * @param contentType free with der_free_oid(). * @param content the output of the function, free with * der_free_octet_string(). * @param signer_certs list of the cerficates used to sign this @@ -755,6 +768,7 @@ find_attribute(const CMSAttributes *attr, const heim_oid *oid) int hx509_cms_verify_signed(hx509_context context, hx509_verify_ctx ctx, + unsigned int flags, const void *data, size_t length, const heim_octet_string *signedContent, @@ -797,8 +811,15 @@ hx509_cms_verify_signed(hx509_context context, "Both external and internal SignedData"); goto out; } + if (sd.encapContentInfo.eContent) - signedContent = sd.encapContentInfo.eContent; + ret = der_copy_octet_string(sd.encapContentInfo.eContent, content); + else + ret = der_copy_octet_string(signedContent, content); + if (ret) { + hx509_set_error_string(context, 0, ret, "malloc: out of memory"); + goto out; + } ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer", 0, NULL, &certs); @@ -823,7 +844,7 @@ hx509_cms_verify_signed(hx509_context context, } for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) { - heim_octet_string *signed_data; + heim_octet_string signed_data; const heim_oid *match_oid; heim_oid decode_oid; @@ -841,8 +862,22 @@ hx509_cms_verify_signed(hx509_context context, ret = find_CMSIdentifier(context, &signer_info->sid, certs, _hx509_verify_get_time(ctx), &cert, HX509_QUERY_KU_DIGITALSIGNATURE); - if (ret) - continue; + if (ret) { + /** + * If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal + * search for matching certificates by not considering + * KeyUsage bits on the certificates. + */ + if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0) + continue; + + ret = find_CMSIdentifier(context, &signer_info->sid, certs, + _hx509_verify_get_time(ctx), &cert, + 0); + if (ret) + continue; + + } if (signer_info->signedAttrs) { const Attribute *attr; @@ -854,7 +889,7 @@ hx509_cms_verify_signed(hx509_context context, sa.len = signer_info->signedAttrs->len; /* verify that sigature exists */ - attr = find_attribute(&sa, oid_id_pkcs9_messageDigest()); + attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest); if (attr == NULL) { ret = HX509_CRYPTO_SIGNATURE_MISSING; hx509_set_error_string(context, 0, ret, @@ -885,7 +920,7 @@ hx509_cms_verify_signed(hx509_context context, ret = _hx509_verify_signature(context, NULL, &signer_info->digestAlgorithm, - signedContent, + content, &os); der_free_octet_string(&os); if (ret) { @@ -898,9 +933,9 @@ hx509_cms_verify_signed(hx509_context context, * Fetch content oid inside signedAttrs or set it to * id-pkcs7-data. */ - attr = find_attribute(&sa, oid_id_pkcs9_contentType()); + attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType); if (attr == NULL) { - match_oid = oid_id_pkcs7_data(); + match_oid = &asn1_oid_id_pkcs7_data; } else { if (attr->value.len != 1) { ret = HX509_CMS_DATA_OID_MISMATCH; @@ -922,36 +957,36 @@ hx509_cms_verify_signed(hx509_context context, match_oid = &decode_oid; } - ALLOC(signed_data, 1); - if (signed_data == NULL) { - if (match_oid == &decode_oid) - der_free_oid(&decode_oid); - ret = ENOMEM; - hx509_clear_error_string(context); - goto next_sigature; - } - ASN1_MALLOC_ENCODE(CMSAttributes, - signed_data->data, - signed_data->length, + signed_data.data, + signed_data.length, &sa, &size, ret); if (ret) { if (match_oid == &decode_oid) der_free_oid(&decode_oid); - free(signed_data); hx509_clear_error_string(context); goto next_sigature; } - if (size != signed_data->length) + if (size != signed_data.length) _hx509_abort("internal ASN.1 encoder error"); } else { - signed_data = rk_UNCONST(signedContent); - match_oid = oid_id_pkcs7_data(); + signed_data.data = content->data; + signed_data.length = content->length; + match_oid = &asn1_oid_id_pkcs7_data; } - if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) { + /** + * If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow + * encapContentInfo mismatch with the oid in signedAttributes + * (or if no signedAttributes where use, pkcs7-data oid). + * This is only needed to work with broken CMS implementations + * that doesn't follow CMS signedAttributes rules. + */ + + if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) && + (flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) { ret = HX509_CMS_DATA_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "Oid in message mismatch from the expected"); @@ -963,23 +998,28 @@ hx509_cms_verify_signed(hx509_context context, ret = hx509_verify_signature(context, cert, &signer_info->signatureAlgorithm, - signed_data, + &signed_data, &signer_info->signature); if (ret) hx509_set_error_string(context, HX509_ERROR_APPEND, ret, - "Failed to verify sigature in " + "Failed to verify signature in " "CMS SignedData"); } - if (signed_data != signedContent) { - der_free_octet_string(signed_data); - free(signed_data); - } + if (signer_info->signedAttrs) + free(signed_data.data); if (ret) goto next_sigature; - ret = hx509_verify_path(context, ctx, cert, certs); - if (ret) - goto next_sigature; + /** + * If HX509_CMS_VS_NO_VALIDATE flags is set, do not verify the + * signing certificates and leave that up to the caller. + */ + + if ((flags & HX509_CMS_VS_NO_VALIDATE) == 0) { + ret = hx509_verify_path(context, ctx, cert, certs); + if (ret) + goto next_sigature; + } ret = hx509_certs_add(context, *signer_certs, cert); if (ret) @@ -992,7 +1032,18 @@ hx509_cms_verify_signed(hx509_context context, hx509_cert_free(cert); cert = NULL; } - if (found_valid_sig == 0) { + /** + * If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty + * SignerInfo (no signatures). If SignedData have no signatures, + * the function will return 0 with signer_certs set to NULL. Zero + * signers is allowed by the standard, but since its only useful + * in corner cases, it make into a flag that the caller have to + * turn on. + */ + if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) { + if (*signer_certs) + hx509_certs_free(signer_certs); + } else if (found_valid_sig == 0) { if (ret == 0) { ret = HX509_CMS_SIGNER_NOT_FOUND; hx509_set_error_string(context, 0, ret, @@ -1007,20 +1058,13 @@ hx509_cms_verify_signed(hx509_context context, goto out; } - content->data = malloc(signedContent->length); - if (content->data == NULL) { - hx509_clear_error_string(context); - ret = ENOMEM; - goto out; - } - content->length = signedContent->length; - memcpy(content->data, signedContent->data, content->length); - out: free_SignedData(&sd); if (certs) hx509_certs_free(&certs); if (ret) { + if (content->data) + der_free_octet_string(content); if (*signer_certs) hx509_certs_free(signer_certs); der_free_oid(contentType); @@ -1097,26 +1141,55 @@ hx509_cms_create_signed_1(hx509_context context, hx509_certs pool, heim_octet_string *signed_data) { - AlgorithmIdentifier digest; - hx509_name name; - SignerInfo *signer_info; - heim_octet_string buf, content, sigdata = { 0, NULL }; + hx509_certs certs; + int ret = 0; + + signed_data->data = NULL; + signed_data->length = 0; + + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); + if (ret) + return ret; + ret = hx509_certs_add(context, certs, cert); + if (ret) + goto out; + + ret = hx509_cms_create_signed(context, flags, eContentType, data, length, + digest_alg, certs, peer, anchors, pool, + signed_data); + + out: + hx509_certs_free(&certs); + return ret; +} + +struct sigctx { SignedData sd; - int ret; + const AlgorithmIdentifier *digest_alg; + const heim_oid *eContentType; + heim_octet_string content; + hx509_peer_info peer; + int cmsidflag; + hx509_certs certs; + hx509_certs anchors; + hx509_certs pool; +}; + +static int +sig_process(hx509_context context, void *ctx, hx509_cert cert) +{ + struct sigctx *sigctx = ctx; + heim_octet_string buf, sigdata = { 0, NULL }; + SignerInfo *signer_info = NULL; + AlgorithmIdentifier digest; size_t size; + void *ptr; + int ret; + SignedData *sd = &sigctx->sd; hx509_path path; - int cmsidflag = CMS_ID_SKI; - memset(&sd, 0, sizeof(sd)); - memset(&name, 0, sizeof(name)); - memset(&path, 0, sizeof(path)); memset(&digest, 0, sizeof(digest)); - - content.data = rk_UNCONST(data); - content.length = length; - - if (flags & HX509_CMS_SIGATURE_ID_NAME) - cmsidflag = CMS_ID_NAME; + memset(&path, 0, sizeof(path)); if (_hx509_cert_private_key(cert) == NULL) { hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, @@ -1124,55 +1197,37 @@ hx509_cms_create_signed_1(hx509_context context, return HX509_PRIVATE_KEY_MISSING; } - if (digest_alg == NULL) { - ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, - _hx509_cert_private_key(cert), peer, &digest); - } else { - ret = copy_AlgorithmIdentifier(digest_alg, &digest); + if (sigctx->digest_alg) { + ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest); if (ret) hx509_clear_error_string(context); + } else { + ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, + _hx509_cert_private_key(cert), + sigctx->peer, &digest); } if (ret) goto out; - sd.version = CMSVersion_v3; - - if (eContentType == NULL) - eContentType = oid_id_pkcs7_data(); - - der_copy_oid(eContentType, &sd.encapContentInfo.eContentType); - - /* */ - if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) { - ALLOC(sd.encapContentInfo.eContent, 1); - if (sd.encapContentInfo.eContent == NULL) { - hx509_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - sd.encapContentInfo.eContent->data = malloc(length); - if (sd.encapContentInfo.eContent->data == NULL) { - hx509_clear_error_string(context); - ret = ENOMEM; - goto out; - } - memcpy(sd.encapContentInfo.eContent->data, data, length); - sd.encapContentInfo.eContent->length = length; - } + /* + * Allocate on more signerInfo and do the signature processing + */ - ALLOC_SEQ(&sd.signerInfos, 1); - if (sd.signerInfos.val == NULL) { - hx509_clear_error_string(context); + ptr = realloc(sd->signerInfos.val, + (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0])); + if (ptr == NULL) { ret = ENOMEM; goto out; } + sd->signerInfos.val = ptr; - signer_info = &sd.signerInfos.val[0]; + signer_info = &sd->signerInfos.val[sd->signerInfos.len]; + + memset(signer_info, 0, sizeof(*signer_info)); signer_info->version = 1; - ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid); + ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid); if (ret) { hx509_clear_error_string(context); goto out; @@ -1181,7 +1236,6 @@ hx509_cms_create_signed_1(hx509_context context, signer_info->signedAttrs = NULL; signer_info->unsignedAttrs = NULL; - ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm); if (ret) { hx509_clear_error_string(context); @@ -1192,7 +1246,7 @@ hx509_cms_create_signed_1(hx509_context context, * If it isn't pkcs7-data send signedAttributes */ - if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) { + if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) { CMSAttributes sa; heim_octet_string sig; @@ -1205,7 +1259,7 @@ hx509_cms_create_signed_1(hx509_context context, ret = _hx509_create_signature(context, NULL, &digest, - &content, + &sigctx->content, NULL, &sig); if (ret) @@ -1227,9 +1281,10 @@ hx509_cms_create_signed_1(hx509_context context, ret = add_one_attribute(&signer_info->signedAttrs->val, &signer_info->signedAttrs->len, - oid_id_pkcs9_messageDigest(), + &asn1_oid_id_pkcs9_messageDigest, &buf); if (ret) { + free(buf.data); hx509_clear_error_string(context); goto out; } @@ -1238,7 +1293,7 @@ hx509_cms_create_signed_1(hx509_context context, ASN1_MALLOC_ENCODE(ContentType, buf.data, buf.length, - eContentType, + sigctx->eContentType, &size, ret); if (ret) @@ -1248,9 +1303,10 @@ hx509_cms_create_signed_1(hx509_context context, ret = add_one_attribute(&signer_info->signedAttrs->val, &signer_info->signedAttrs->len, - oid_id_pkcs9_contentType(), + &asn1_oid_id_pkcs9_contentType, &buf); if (ret) { + free(buf.data); hx509_clear_error_string(context); goto out; } @@ -1271,16 +1327,15 @@ hx509_cms_create_signed_1(hx509_context context, if (size != sigdata.length) _hx509_abort("internal ASN.1 encoder error"); } else { - sigdata.data = content.data; - sigdata.length = content.length; + sigdata.data = sigctx->content.data; + sigdata.length = sigctx->content.length; } - { AlgorithmIdentifier sigalg; ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG, - _hx509_cert_private_key(cert), peer, + _hx509_cert_private_key(cert), sigctx->peer, &sigalg); if (ret) goto out; @@ -1296,54 +1351,165 @@ hx509_cms_create_signed_1(hx509_context context, goto out; } - ALLOC_SEQ(&sd.digestAlgorithms, 1); - if (sd.digestAlgorithms.val == NULL) { - ret = ENOMEM; - hx509_clear_error_string(context); - goto out; - } - - ret = copy_AlgorithmIdentifier(&digest, &sd.digestAlgorithms.val[0]); - if (ret) { - hx509_clear_error_string(context); - goto out; - } + sigctx->sd.signerInfos.len++; + signer_info = NULL; /* * Provide best effort path */ - if (pool) { - _hx509_calculate_path(context, - HX509_CALCULATE_PATH_NO_ANCHOR, - time(NULL), - anchors, - 0, - cert, - pool, - &path); - } else - _hx509_path_append(context, &path, cert); + if (sigctx->certs) { + unsigned int i; + + if (sigctx->pool) { + _hx509_calculate_path(context, + HX509_CALCULATE_PATH_NO_ANCHOR, + time(NULL), + sigctx->anchors, + 0, + cert, + sigctx->pool, + &path); + } else + _hx509_path_append(context, &path, cert); + + for (i = 0; i < path.len; i++) { + /* XXX remove dups */ + ret = hx509_certs_add(context, sigctx->certs, path.val[i]); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + } + + out: + if (signer_info) + free_SignerInfo(signer_info); + if (sigdata.data != sigctx->content.data) + der_free_octet_string(&sigdata); + _hx509_path_free(&path); + free_AlgorithmIdentifier(&digest); + + return ret; +} + +static int +cert_process(hx509_context context, void *ctx, hx509_cert cert) +{ + struct sigctx *sigctx = ctx; + const unsigned int i = sigctx->sd.certificates->len; + void *ptr; + int ret; + + ptr = realloc(sigctx->sd.certificates->val, + (i + 1) * sizeof(sigctx->sd.certificates->val[0])); + if (ptr == NULL) + return ENOMEM; + sigctx->sd.certificates->val = ptr; + + ret = hx509_cert_binary(context, cert, + &sigctx->sd.certificates->val[i]); + if (ret == 0) + sigctx->sd.certificates->len++; + + return ret; +} + +int +hx509_cms_create_signed(hx509_context context, + int flags, + const heim_oid *eContentType, + const void *data, size_t length, + const AlgorithmIdentifier *digest_alg, + hx509_certs certs, + hx509_peer_info peer, + hx509_certs anchors, + hx509_certs pool, + heim_octet_string *signed_data) +{ + unsigned int i; + hx509_name name; + int ret; + size_t size; + struct sigctx sigctx; + + memset(&sigctx, 0, sizeof(sigctx)); + memset(&name, 0, sizeof(name)); + + if (eContentType == NULL) + eContentType = &asn1_oid_id_pkcs7_data; + + sigctx.digest_alg = digest_alg; + sigctx.content.data = rk_UNCONST(data); + sigctx.content.length = length; + sigctx.eContentType = eContentType; + sigctx.peer = peer; + /** + * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name + * and serial number if possible. Otherwise subject key identifier + * will preferred. + */ + if (flags & HX509_CMS_SIGNATURE_ID_NAME) + sigctx.cmsidflag = CMS_ID_NAME; + else + sigctx.cmsidflag = CMS_ID_SKI; + + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs); + if (ret) + return ret; + + sigctx.anchors = anchors; + sigctx.pool = pool; + sigctx.sd.version = CMSVersion_v3; - if (path.len) { - int i; + der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); - ALLOC(sd.certificates, 1); - if (sd.certificates == NULL) { + /** + * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures. + */ + if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) { + ALLOC(sigctx.sd.encapContentInfo.eContent, 1); + if (sigctx.sd.encapContentInfo.eContent == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } - ALLOC_SEQ(sd.certificates, path.len); - if (sd.certificates->val == NULL) { + + sigctx.sd.encapContentInfo.eContent->data = malloc(length); + if (sigctx.sd.encapContentInfo.eContent->data == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } + memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length); + sigctx.sd.encapContentInfo.eContent->length = length; + } - for (i = 0; i < path.len; i++) { - ret = hx509_cert_binary(context, path.val[i], - &sd.certificates->val[i]); + /** + * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no + * signatures). + */ + if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) { + ret = hx509_certs_iter(context, certs, sig_process, &sigctx); + if (ret) + goto out; + } + + if (sigctx.sd.signerInfos.len) { + ALLOC_SEQ(&sigctx.sd.digestAlgorithms, sigctx.sd.signerInfos.len); + if (sigctx.sd.digestAlgorithms.val == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + + /* XXX remove dups */ + for (i = 0; i < sigctx.sd.signerInfos.len; i++) { + AlgorithmIdentifier *di = + &sigctx.sd.signerInfos.val[i].digestAlgorithm; + ret = copy_AlgorithmIdentifier(di, + &sigctx.sd.digestAlgorithms.val[i]); if (ret) { hx509_clear_error_string(context); goto out; @@ -1351,9 +1517,22 @@ hx509_cms_create_signed_1(hx509_context context, } } + if (sigctx.certs) { + ALLOC(sigctx.sd.certificates, 1); + if (sigctx.sd.certificates == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = hx509_certs_iter(context, sigctx.certs, cert_process, &sigctx); + if (ret) + goto out; + } + ASN1_MALLOC_ENCODE(SignedData, signed_data->data, signed_data->length, - &sd, &size, ret); + &sigctx.sd, &size, ret); if (ret) { hx509_clear_error_string(context); goto out; @@ -1362,11 +1541,8 @@ hx509_cms_create_signed_1(hx509_context context, _hx509_abort("internal ASN.1 encoder error"); out: - if (sigdata.data != content.data) - der_free_octet_string(&sigdata); - free_AlgorithmIdentifier(&digest); - _hx509_path_free(&path); - free_SignedData(&sd); + hx509_certs_free(&sigctx.certs); + free_SignedData(&sigctx.sd); return ret; } -- cgit