summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hx509
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-06-08 19:06:16 +1000
committerAndrew Bartlett <abartlet@samba.org>2009-06-12 07:45:48 +1000
commit9b261c008a395a323e0516f4cd3f3134aa050577 (patch)
tree91cf543ba7ccd560313bea52fa8678f0456e8485 /source4/heimdal/lib/hx509
parent5cef57ff7d899773a084d23838b7f18a83f6e79d (diff)
downloadsamba-9b261c008a395a323e0516f4cd3f3134aa050577.tar.gz
samba-9b261c008a395a323e0516f4cd3f3134aa050577.tar.bz2
samba-9b261c008a395a323e0516f4cd3f3134aa050577.zip
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
Diffstat (limited to 'source4/heimdal/lib/hx509')
-rw-r--r--source4/heimdal/lib/hx509/ca.c32
-rw-r--r--source4/heimdal/lib/hx509/cert.c169
-rw-r--r--source4/heimdal/lib/hx509/cms.c478
-rw-r--r--source4/heimdal/lib/hx509/collector.c5
-rw-r--r--source4/heimdal/lib/hx509/crypto.c995
-rw-r--r--source4/heimdal/lib/hx509/env.c1
-rw-r--r--source4/heimdal/lib/hx509/error.c1
-rw-r--r--source4/heimdal/lib/hx509/file.c1
-rw-r--r--source4/heimdal/lib/hx509/hx509.h19
-rw-r--r--source4/heimdal/lib/hx509/hx509_err.et5
-rw-r--r--source4/heimdal/lib/hx509/hx_locl.h4
-rw-r--r--source4/heimdal/lib/hx509/keyset.c76
-rw-r--r--source4/heimdal/lib/hx509/ks_dir.c3
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c100
-rw-r--r--source4/heimdal/lib/hx509/ks_keychain.c63
-rw-r--r--source4/heimdal/lib/hx509/ks_mem.c1
-rw-r--r--source4/heimdal/lib/hx509/ks_null.c1
-rw-r--r--source4/heimdal/lib/hx509/ks_p11.c11
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c45
-rw-r--r--source4/heimdal/lib/hx509/lock.c1
-rw-r--r--source4/heimdal/lib/hx509/name.c63
-rw-r--r--source4/heimdal/lib/hx509/peer.c34
-rw-r--r--source4/heimdal/lib/hx509/print.c37
-rw-r--r--source4/heimdal/lib/hx509/req.c1
-rw-r--r--source4/heimdal/lib/hx509/revoke.c8
-rw-r--r--source4/heimdal/lib/hx509/sel-gram.y1
-rw-r--r--source4/heimdal/lib/hx509/test_name.c1
27 files changed, 1570 insertions, 586 deletions
diff --git a/source4/heimdal/lib/hx509/ca.c b/source4/heimdal/lib/hx509/ca.c
index cbd58ebd01..624d74289d 100644
--- a/source4/heimdal/lib/hx509/ca.c
+++ b/source4/heimdal/lib/hx509/ca.c
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <pkinit_asn1.h>
-RCSID("$Id$");
/**
* @page page_ca Hx509 CA functions
@@ -672,7 +671,7 @@ hx509_ca_tbs_add_san_pkinit(hx509_context context,
ret = hx509_ca_tbs_add_san_otherName(context,
tbs,
- oid_id_pkinit_san(),
+ &asn1_oid_id_pkinit_san,
&os);
free(os.data);
out:
@@ -736,7 +735,7 @@ hx509_ca_tbs_add_san_ms_upn(hx509_context context,
hx509_ca_tbs tbs,
const char *principal)
{
- return add_utf8_san(context, tbs, oid_id_pkinit_ms_san(), principal);
+ return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
}
/**
@@ -757,7 +756,7 @@ hx509_ca_tbs_add_san_jid(hx509_context context,
hx509_ca_tbs tbs,
const char *jid)
{
- return add_utf8_san(context, tbs, oid_id_pkix_on_xmppAddr(), jid);
+ return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
}
@@ -926,7 +925,7 @@ build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
return ENOMEM;
}
/* prefix with CN=<ts>,...*/
- ret = _hx509_name_modify(context, subject, 1, oid_id_at_commonName(), tstr);
+ ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
free(tstr);
if (ret)
free_Name(subject);
@@ -1110,7 +1109,7 @@ ca_sign(hx509_context context,
data.length = 34;
ret = add_extension(context, tbsc, 0,
- oid_id_ms_cert_enroll_domaincontroller(),
+ &asn1_oid_id_ms_cert_enroll_domaincontroller,
&data);
if (ret)
goto out;
@@ -1129,7 +1128,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 1,
- oid_id_x509_ce_keyUsage(), &data);
+ &asn1_oid_id_x509_ce_keyUsage, &data);
free(data.data);
if (ret)
goto out;
@@ -1146,7 +1145,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_extKeyUsage(), &data);
+ &asn1_oid_id_x509_ce_extKeyUsage, &data);
free(data.data);
if (ret)
goto out;
@@ -1163,7 +1162,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_subjectAltName(),
+ &asn1_oid_id_x509_ce_subjectAltName,
&data);
free(data.data);
if (ret)
@@ -1181,7 +1180,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_authorityKeyIdentifier(),
+ &asn1_oid_id_x509_ce_authorityKeyIdentifier,
&data);
free(data.data);
if (ret)
@@ -1214,7 +1213,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_subjectKeyIdentifier(),
+ &asn1_oid_id_x509_ce_subjectKeyIdentifier,
&data);
free(data.data);
if (ret)
@@ -1247,7 +1246,7 @@ ca_sign(hx509_context context,
_hx509_abort("internal ASN.1 encoder error");
/* Critical if this is a CA */
ret = add_extension(context, tbsc, tbs->flags.ca,
- oid_id_x509_ce_basicConstraints(),
+ &asn1_oid_id_x509_ce_basicConstraints,
&data);
free(data.data);
if (ret)
@@ -1271,7 +1270,7 @@ ca_sign(hx509_context context,
*info.pCPathLenConstraint = tbs->pathLenConstraint;
}
- ret = der_copy_oid(oid_id_pkix_ppl_inheritAll(),
+ ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
&info.proxyPolicy.policyLanguage);
if (ret) {
free_ProxyCertInfo(&info);
@@ -1289,7 +1288,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_pkix_pe_proxyCertInfo(),
+ &asn1_oid_id_pkix_pe_proxyCertInfo,
&data);
free(data.data);
if (ret)
@@ -1307,7 +1306,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, FALSE,
- oid_id_x509_ce_cRLDistributionPoints(),
+ &asn1_oid_id_x509_ce_cRLDistributionPoints,
&data);
free(data.data);
if (ret)
@@ -1399,8 +1398,7 @@ get_AuthorityKeyIdentifier(hx509_context context,
*/
ret = copy_Name(&certificate->tbsCertificate.subject, &name);
- if (ai->authorityCertSerialNumber == NULL) {
- ret = ENOMEM;
+ if (ret) {
hx509_set_error_string(context, 0, ret, "Out of memory");
goto out;
}
diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c
index 121847faaa..cd9ae01fac 100644
--- a/source4/heimdal/lib/hx509/cert.c
+++ b/source4/heimdal/lib/hx509/cert.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#include "crypto-headers.h"
#include <rtbl.h>
@@ -59,6 +58,7 @@ struct hx509_verify_ctx_data {
#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
+#define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
time_t time_now;
unsigned int max_depth;
#define HX509_VERIFY_MAX_DEPTH 30
@@ -432,6 +432,7 @@ hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
* Set the trust anchors in the verification context, makes an
* reference to the keyset, so the consumer can free the keyset
* independent of the destruction of the verification context (ctx).
+ * If there already is a keyset attached, it's released.
*
* @param ctx a verification context
* @param set a keyset containing the trust anchors.
@@ -442,6 +443,8 @@ hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
void
hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
{
+ if (ctx->trust_anchors)
+ hx509_certs_free(&ctx->trust_anchors);
ctx->trust_anchors = _hx509_certs_ref(set);
}
@@ -569,6 +572,16 @@ hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
}
+void
+hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
+ int boolean)
+{
+ if (boolean)
+ ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
+ else
+ ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
+}
+
static const Extension *
find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
{
@@ -594,7 +607,7 @@ find_extension_auth_key_id(const Certificate *subject,
memset(ai, 0, sizeof(*ai));
- e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
+ e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -613,7 +626,7 @@ _hx509_find_extension_subject_key_id(const Certificate *issuer,
memset(si, 0, sizeof(*si));
- e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
+ e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -632,7 +645,7 @@ find_extension_name_constraints(const Certificate *subject,
memset(nc, 0, sizeof(*nc));
- e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
+ e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -650,7 +663,7 @@ find_extension_subject_alt_name(const Certificate *cert, int *i,
memset(sa, 0, sizeof(*sa));
- e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -668,7 +681,7 @@ find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
memset(eku, 0, sizeof(*eku));
- e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -748,8 +761,7 @@ hx509_cert_find_subjectAltName_otherName(hx509_context context,
ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
i++;
if (ret == HX509_EXTENSION_NOT_FOUND) {
- ret = 0;
- break;
+ return 0;
} else if (ret != 0) {
hx509_set_error_string(context, 0, ret, "Error searching for SAN");
hx509_free_octet_string_list(list);
@@ -773,7 +785,6 @@ hx509_cert_find_subjectAltName_otherName(hx509_context context,
}
free_GeneralNames(&sa);
}
- return 0;
}
@@ -790,7 +801,7 @@ check_key_usage(hx509_context context, const Certificate *cert,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
if (e == NULL) {
if (req_present) {
hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
@@ -847,7 +858,7 @@ check_basic_constraints(hx509_context context, const Certificate *cert,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i);
if (e == NULL) {
switch(type) {
case PROXY_CERT:
@@ -1134,7 +1145,7 @@ is_proxy_cert(hx509_context context,
if (rinfo)
memset(rinfo, 0, sizeof(*rinfo));
- e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
+ e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i);
if (e == NULL) {
hx509_clear_error_string(context);
return HX509_EXTENSION_NOT_FOUND;
@@ -1472,7 +1483,9 @@ hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *s
* @param context a hx509 context.
* @param p a hx509 certificate object.
* @param alg AlgorithmIdentifier, should be freed with
- * free_AlgorithmIdentifier().
+ * free_AlgorithmIdentifier(). The algorithmidentifier is
+ * typicly rsaEncryption, or id-ecPublicKey, or some other
+ * public key mechanism.
*
* @return An hx509 error code, see hx509_get_error_string().
*
@@ -2003,7 +2016,7 @@ hx509_verify_path(hx509_context context,
free_ProxyCertInfo(&info);
j = 0;
- if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
+ if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
ret = HX509_PROXY_CERT_INVALID;
hx509_set_error_string(context, 0, ret,
"Proxy certificate have explicity "
@@ -2012,7 +2025,7 @@ hx509_verify_path(hx509_context context,
}
j = 0;
- if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
+ if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
ret = HX509_PROXY_CERT_INVALID;
hx509_set_error_string(context, 0, ret,
"Proxy certificate have explicity "
@@ -2053,7 +2066,7 @@ hx509_verify_path(hx509_context context,
if (proxy_issuer.u.rdnSequence.len < 2
|| proxy_issuer.u.rdnSequence.val[j - 1].len > 1
|| der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
- oid_id_at_commonName()))
+ &asn1_oid_id_at_commonName))
{
ret = HX509_PROXY_CERT_NAME_WRONG;
hx509_set_error_string(context, 0, ret,
@@ -2263,6 +2276,24 @@ hx509_verify_path(hx509_context context,
"Failed to verify signature of certificate");
goto out;
}
+ /*
+ * Verify that the sigature algorithm "best-before" date is
+ * before the creation date of the certificate, do this for
+ * trust anchors too, since any trust anchor that is created
+ * after a algorithm is known to be bad deserved to be invalid.
+ *
+ * Skip the leaf certificate for now...
+ */
+
+ if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
+ time_t notBefore =
+ _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
+ ret = _hx509_signature_best_before(context,
+ &c->signatureAlgorithm,
+ notBefore);
+ if (ret)
+ goto out;
+ }
}
out:
@@ -2329,6 +2360,7 @@ hx509_verify_hostname(hx509_context context,
/* XXX krb5_socklen_t */ int sa_size)
{
GeneralNames san;
+ const Name *name;
int ret, i, j;
if (sa && sa_size <= 0)
@@ -2339,11 +2371,10 @@ hx509_verify_hostname(hx509_context context,
i = 0;
do {
ret = find_extension_subject_alt_name(cert->data, &i, &san);
- if (ret == HX509_EXTENSION_NOT_FOUND) {
- ret = 0;
- break;
- } else if (ret != 0)
+ if (ret == HX509_EXTENSION_NOT_FOUND)
break;
+ else if (ret != 0)
+ return HX509_PARSING_NAME_FAILED;
for (j = 0; j < san.len; j++) {
switch (san.val[j].element) {
@@ -2360,31 +2391,31 @@ hx509_verify_hostname(hx509_context context,
free_GeneralNames(&san);
} while (1);
- {
- const Name *name = &cert->data->tbsCertificate.subject;
-
- /* match if first component is a CN= */
- if (name->u.rdnSequence.len > 0
- && name->u.rdnSequence.val[0].len == 1
- && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
- oid_id_at_commonName()) == 0)
- {
- DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
-
- switch (ds->element) {
- case choice_DirectoryString_printableString:
- if (strcasecmp(ds->u.printableString, hostname) == 0)
- return 0;
- break;
- case choice_DirectoryString_ia5String:
- if (strcasecmp(ds->u.ia5String, hostname) == 0)
+ name = &cert->data->tbsCertificate.subject;
+
+ /* Find first CN= in the name, and try to match the hostname on that */
+ for (ret = 0, i = name->u.rdnSequence.len - 1; ret == 0 && i >= 0; i--) {
+ for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
+ AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
+
+ if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
+ DirectoryString *ds = &n->value;
+ switch (ds->element) {
+ case choice_DirectoryString_printableString:
+ if (strcasecmp(ds->u.printableString, hostname) == 0)
+ return 0;
+ break;
+ case choice_DirectoryString_ia5String:
+ if (strcasecmp(ds->u.ia5String, hostname) == 0)
return 0;
- break;
- case choice_DirectoryString_utf8String:
- if (strcasecmp(ds->u.utf8String, hostname) == 0)
- return 0;
- default:
- break;
+ break;
+ case choice_DirectoryString_utf8String:
+ if (strcasecmp(ds->u.utf8String, hostname) == 0)
+ return 0;
+ default:
+ break;
+ }
+ ret = HX509_NAME_CONSTRAINT_ERROR;
}
}
}
@@ -2495,7 +2526,7 @@ hx509_cert_get_friendly_name(hx509_cert cert)
if (cert->friendlyname)
return cert->friendlyname;
- a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
+ a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
if (a == NULL) {
hx509_name name;
@@ -2746,7 +2777,7 @@ hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
int
hx509_query_match_cmp_func(hx509_query *q,
- int (*func)(void *, hx509_cert),
+ int (*func)(hx509_context, hx509_cert, void *),
void *ctx)
{
if (func)
@@ -2869,7 +2900,7 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
hx509_cert_attribute a;
- a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
+ a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
if (a == NULL)
return 0;
if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
@@ -2891,7 +2922,7 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
return 0;
}
if (q->match & HX509_QUERY_MATCH_FUNCTION) {
- ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
+ ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
if (ret != 0)
return 0;
}
@@ -3163,7 +3194,7 @@ _hx509_cert_get_keyusage(hx509_context context,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
if (e == NULL)
return HX509_KU_CERT_MISSING;
@@ -3348,6 +3379,46 @@ _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
}
}
+ {
+ Certificate *c = _hx509_get_cert(cert);
+ heim_octet_string os, sig;
+ hx509_env envhash = NULL;
+ char *buf;
+
+ os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
+ os.length =
+ c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ hx509_signature_sha1(),
+ &os,
+ NULL,
+ &sig);
+ if (ret != 0)
+ goto out;
+
+ ret = hex_encode(sig.data, sig.length, &buf);
+ der_free_octet_string(&sig);
+ if (ret < 0) {
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret,
+ "Out of memory");
+ goto out;
+ }
+
+ ret = hx509_env_add(context, &envhash, "sha1", buf);
+ free(buf);
+ if (ret)
+ goto out;
+
+ ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
+ if (ret) {
+ hx509_env_free(&envhash);
+ goto out;
+ }
+ }
+
ret = hx509_env_add_binding(context, env, "certificate", envcert);
if (ret)
goto out;
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;
}
diff --git a/source4/heimdal/lib/hx509/collector.c b/source4/heimdal/lib/hx509/collector.c
index b59052bb4e..ab36fe2dc8 100644
--- a/source4/heimdal/lib/hx509/collector.c
+++ b/source4/heimdal/lib/hx509/collector.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct private_key {
AlgorithmIdentifier alg;
@@ -144,7 +143,7 @@ _hx509_collector_private_key_add(hx509_context context,
if (private_key) {
key->private_key = private_key;
} else {
- ret = _hx509_parse_private_key(context, &alg->algorithm,
+ ret = _hx509_parse_private_key(context, alg,
key_data->data, key_data->length,
&key->private_key);
if (ret)
@@ -306,7 +305,7 @@ _hx509_collector_collect_private_keys(hx509_context context,
c->val.data[i]->private_key = NULL;
}
}
- (*keys)[nkeys++] = NULL;
+ (*keys)[nkeys] = NULL;
return 0;
}
diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c
index 4a8ec8f756..8063100717 100644
--- a/source4/heimdal/lib/hx509/crypto.c
+++ b/source4/heimdal/lib/hx509/crypto.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct hx509_crypto;
@@ -50,40 +49,21 @@ struct hx509_generate_private_context {
struct hx509_private_key_ops {
const char *pemtype;
- const heim_oid *(*key_oid)(void);
+ const heim_oid *key_oid;
+ int (*available)(const hx509_private_key,
+ const AlgorithmIdentifier *);
int (*get_spki)(hx509_context,
const hx509_private_key,
SubjectPublicKeyInfo *);
int (*export)(hx509_context context,
const hx509_private_key,
heim_octet_string *);
- int (*import)(hx509_context,
- const void *data,
- size_t len,
- hx509_private_key private_key);
+ int (*import)(hx509_context, const AlgorithmIdentifier *,
+ const void *, size_t, hx509_private_key);
int (*generate_private_key)(hx509_context,
struct hx509_generate_private_context *,
hx509_private_key);
BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
- int (*handle_alg)(const hx509_private_key,
- const AlgorithmIdentifier *,
- enum crypto_op_type);
- int (*sign)(hx509_context context,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- AlgorithmIdentifier *,
- heim_octet_string *);
-#if 0
- const AlgorithmIdentifier *(*preferred_sig_alg)
- (const hx509_private_key,
- const hx509_peer_info);
- int (*unwrap)(hx509_context context,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- heim_octet_string *);
-#endif
};
struct hx509_private_key {
@@ -93,8 +73,10 @@ struct hx509_private_key {
union {
RSA *rsa;
void *keydata;
+#ifdef HAVE_OPENSSL
+ EC_KEY *ecdsa;
+#endif
} private_key;
- /* new crypto layer */
hx509_private_key_ops *ops;
};
@@ -104,10 +86,10 @@ struct hx509_private_key {
struct signature_alg {
const char *name;
- const heim_oid *(*sig_oid)(void);
- const AlgorithmIdentifier *(*sig_alg)(void);
- const heim_oid *(*key_oid)(void);
- const heim_oid *(*digest_oid)(void);
+ const heim_oid *sig_oid;
+ const AlgorithmIdentifier *sig_alg;
+ const heim_oid *key_oid;
+ const AlgorithmIdentifier *digest_alg;
int flags;
#define PROVIDE_CONF 1
#define REQUIRE_SIGNER 2
@@ -118,7 +100,7 @@ struct signature_alg {
#define RA_RSA_USES_DIGEST_INFO 0x1000000
-
+ time_t best_before; /* refuse signature made after best before date */
int (*verify_signature)(hx509_context context,
const struct signature_alg *,
const Certificate *,
@@ -132,6 +114,116 @@ struct signature_alg {
const heim_octet_string *,
AlgorithmIdentifier *,
heim_octet_string *);
+ int digest_size;
+};
+
+static const struct signature_alg *
+find_sig_alg(const heim_oid *oid);
+
+/*
+ *
+ */
+
+static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
+
+static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+const AlgorithmIdentifier _hx509_signature_sha512_data = {
+ { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
+const AlgorithmIdentifier _hx509_signature_sha384_data = {
+ { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+const AlgorithmIdentifier _hx509_signature_sha256_data = {
+ { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
+const AlgorithmIdentifier _hx509_signature_sha1_data = {
+ { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
+const AlgorithmIdentifier _hx509_signature_md5_data = {
+ { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 };
+const AlgorithmIdentifier _hx509_signature_md2_data = {
+ { 6, rk_UNCONST(md2_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
+const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
+ { 6, rk_UNCONST(ecPublicKey) }, NULL
+};
+
+static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
+ { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
+};
+
+static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
+ { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
+ { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
+ { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
+ { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
+ { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
+};
+
+static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
+ { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
+};
+
+static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = {
+ { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL
+};
+
+static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
+const AlgorithmIdentifier _hx509_signature_rsa_data = {
+ { 7, rk_UNCONST(rsa_oid) }, NULL
+};
+
+static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
+const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
+ { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
+};
+
+static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
+const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
+ { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
+};
+
+static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
+const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
+ { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
+};
+
+static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
+const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
+ { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
};
/*
@@ -184,6 +276,265 @@ set_digest_alg(DigestAlgorithmIdentifier *id,
return 0;
}
+#ifdef HAVE_OPENSSL
+
+static int
+heim_oid2ecnid(heim_oid *oid)
+{
+ /*
+ * Now map to openssl OID fun
+ */
+
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0)
+ return NID_X9_62_prime256v1;
+ else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r1) == 0)
+ return NID_secp160r1;
+ else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r2) == 0)
+ return NID_secp160r2;
+
+ return -1;
+}
+
+static int
+parse_ECParameters(hx509_context context,
+ heim_octet_string *parameters, int *nid)
+{
+ ECParameters ecparam;
+ size_t size;
+ int ret;
+
+ if (parameters == NULL) {
+ ret = HX509_PARSING_KEY_FAILED;
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters missing");
+ return ret;
+ }
+
+ ret = decode_ECParameters(parameters->data, parameters->length,
+ &ecparam, &size);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to decode EC parameters");
+ return ret;
+ }
+
+ if (ecparam.element != choice_ECParameters_namedCurve) {
+ free_ECParameters(&ecparam);
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters is not a named curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+
+ *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
+ free_ECParameters(&ecparam);
+ if (*nid == -1) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to find matcing NID for EC curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+static int
+ecdsa_verify_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const Certificate *signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ const heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ const SubjectPublicKeyInfo *spi;
+ heim_octet_string digest;
+ int ret;
+ EC_KEY *key = NULL;
+ int groupnid;
+ EC_GROUP *group;
+ const unsigned char *p;
+ long len;
+
+ digest_alg = sig_alg->digest_alg;
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &digest);
+ if (ret)
+ return ret;
+
+ /* set up EC KEY */
+ spi = &signer->tbsCertificate.subjectPublicKeyInfo;
+
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm, &asn1_oid_id_ecPublicKey) != 0)
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+
+#ifdef HAVE_OPENSSL
+ /*
+ * Find the group id
+ */
+
+ ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
+ if (ret) {
+ der_free_octet_string(&digest);
+ return ret;
+ }
+
+ /*
+ * Create group, key, parse key
+ */
+
+ key = EC_KEY_new();
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ EC_KEY_set_group(key, group);
+ EC_GROUP_free(group);
+
+ p = spi->subjectPublicKey.data;
+ len = spi->subjectPublicKey.length / 8;
+
+ if (o2i_ECPublicKey(&key, &p, len) == NULL) {
+ EC_KEY_free(key);
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+#else
+ key = SubjectPublicKeyInfo2EC_KEY(spi);
+#endif
+
+ ret = ECDSA_verify(-1, digest.data, digest.length,
+ sig->data, sig->length, key);
+ der_free_octet_string(&digest);
+ EC_KEY_free(key);
+ if (ret != 1) {
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+ecdsa_create_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const hx509_private_key signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ AlgorithmIdentifier *signatureAlgorithm,
+ heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ heim_octet_string indata;
+ const heim_oid *sig_oid;
+ unsigned int siglen;
+ int ret;
+
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig_oid = sig_alg->sig_oid;
+ digest_alg = sig_alg->digest_alg;
+
+ if (signatureAlgorithm) {
+ ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto error;
+ }
+ }
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &indata);
+ if (ret) {
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ goto error;
+ }
+
+ sig->length = ECDSA_size(signer->private_key.ecdsa);
+ sig->data = malloc(sig->length);
+ if (sig->data == NULL) {
+ der_free_octet_string(&indata);
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto error;
+ }
+
+ siglen = sig->length;
+
+ ret = ECDSA_sign(-1, indata.data, indata.length,
+ sig->data, &siglen, signer->private_key.ecdsa);
+ der_free_octet_string(&indata);
+ if (ret != 1) {
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ hx509_set_error_string(context, 0, ret,
+ "ECDSA sign failed: %d", ret);
+ goto error;
+ }
+ if (siglen > sig->length)
+ _hx509_abort("ECDSA signature prelen longer the output len");
+
+ sig->length = siglen;
+
+ return 0;
+ error:
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ return ret;
+}
+
+static int
+ecdsa_available(const hx509_private_key signer,
+ const AlgorithmIdentifier *sig_alg)
+{
+ const struct signature_alg *sig;
+ const EC_GROUP *group;
+ BN_CTX *bnctx = NULL;
+ BIGNUM *order = NULL;
+ int ret = 0;
+
+ if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig = find_sig_alg(&sig_alg->algorithm);
+
+ if (sig == NULL || sig->digest_size == 0)
+ return 0;
+
+ group = EC_KEY_get0_group(signer->private_key.ecdsa);
+ if (group == NULL)
+ return 0;
+
+ bnctx = BN_CTX_new();
+ order = BN_new();
+ if (order == NULL)
+ goto err;
+
+ if (EC_GROUP_get_order(group, order, bnctx) != 1)
+ goto err;
+
+ if (BN_num_bytes(order) > sig->digest_size)
+ ret = 1;
+ err:
+ if (bnctx)
+ BN_CTX_free(bnctx);
+ if (order)
+ BN_clear_free(order);
+
+ return ret;
+}
+
+
+#endif /* HAVE_OPENSSL */
+
/*
*
*/
@@ -268,9 +619,9 @@ rsa_verify_signature(hx509_context context,
goto out;
}
- if (sig_alg->digest_oid &&
+ if (sig_alg->digest_alg &&
der_heim_oid_cmp(&di.digestAlgorithm.algorithm,
- (*sig_alg->digest_oid)()) != 0)
+ &sig_alg->digest_alg->algorithm) != 0)
{
ret = HX509_CRYPTO_OID_MISMATCH;
hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");
@@ -324,24 +675,27 @@ rsa_create_signature(hx509_context context,
size_t size;
int ret;
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0)
+ return HX509_ALG_NOT_SUPP;
+
if (alg)
sig_oid = &alg->algorithm;
else
sig_oid = signer->signature_alg;
- if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha256WithRSAEncryption()) == 0) {
+ if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha256WithRSAEncryption) == 0) {
digest_alg = hx509_signature_sha256();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha1WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha1WithRSAEncryption) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_dsa_with_sha1()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_dsa_with_sha1) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_rsaEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_heim_rsa_pkcs1_x509()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_heim_rsa_pkcs1_x509) == 0) {
digest_alg = NULL;
} else
return HX509_ALG_NOT_SUPP;
@@ -413,6 +767,7 @@ rsa_create_signature(hx509_context context,
static int
rsa_private_key_import(hx509_context context,
+ const AlgorithmIdentifier *keyai,
const void *data,
size_t len,
hx509_private_key private_key)
@@ -426,7 +781,7 @@ rsa_private_key_import(hx509_context context,
"Failed to parse RSA key");
return HX509_PARSING_KEY_FAILED;
}
- private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
return 0;
}
@@ -449,7 +804,7 @@ rsa_private_key2SPKI(hx509_context context,
}
spki->subjectPublicKey.length = len * 8;
- ret = set_digest_alg(&spki->algorithm,oid_id_pkcs1_rsaEncryption(),
+ ret = set_digest_alg(&spki->algorithm, &asn1_oid_id_pkcs1_rsaEncryption,
"\x05\x00", 2);
if (ret) {
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
@@ -503,7 +858,7 @@ rsa_generate_private_key(hx509_context context,
"Failed to generate RSA key");
return HX509_PARSING_KEY_FAILED;
}
- private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
return 0;
}
@@ -543,7 +898,9 @@ rsa_private_key_export(hx509_context context,
}
static BIGNUM *
-rsa_get_internal(hx509_context context, hx509_private_key key, const char *type)
+rsa_get_internal(hx509_context context,
+ hx509_private_key key,
+ const char *type)
{
if (strcasecmp(type, "rsa-modulus") == 0) {
return BN_dup(key->private_key.rsa->n);
@@ -557,7 +914,8 @@ rsa_get_internal(hx509_context context, hx509_private_key key, const char *type)
static hx509_private_key_ops rsa_private_key_ops = {
"RSA PRIVATE KEY",
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ NULL,
rsa_private_key2SPKI,
rsa_private_key_export,
rsa_private_key_import,
@@ -565,6 +923,104 @@ static hx509_private_key_ops rsa_private_key_ops = {
rsa_get_internal
};
+#ifdef HAVE_OPENSSL
+
+static int
+ecdsa_private_key2SPKI(hx509_context context,
+ hx509_private_key private_key,
+ SubjectPublicKeyInfo *spki)
+{
+ memset(spki, 0, sizeof(*spki));
+ return ENOMEM;
+}
+
+static int
+ecdsa_private_key_export(hx509_context context,
+ const hx509_private_key key,
+ heim_octet_string *data)
+{
+ return ENOMEM;
+}
+
+static int
+ecdsa_private_key_import(hx509_context context,
+ const AlgorithmIdentifier *keyai,
+ const void *data,
+ size_t len,
+ hx509_private_key private_key)
+{
+ const unsigned char *p = data;
+ EC_KEY **pkey = NULL;
+
+ if (keyai->parameters) {
+ EC_GROUP *group;
+ int groupnid;
+ EC_KEY *key;
+ int ret;
+
+ ret = parse_ECParameters(context, keyai->parameters, &groupnid);
+ if (ret)
+ return ret;
+
+ key = EC_KEY_new();
+ if (key == NULL)
+ return ENOMEM;
+
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ if (group == NULL) {
+ EC_KEY_free(key);
+ return ENOMEM;
+ }
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_set_group(key, group) == 0) {
+ EC_KEY_free(key);
+ EC_GROUP_free(group);
+ return ENOMEM;
+ }
+ EC_GROUP_free(group);
+ pkey = &key;
+ }
+
+ private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
+ if (private_key->private_key.ecdsa == NULL) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse EC private key");
+ return HX509_PARSING_KEY_FAILED;
+ }
+ private_key->signature_alg = &asn1_oid_id_ecdsa_with_SHA256;
+
+ return 0;
+}
+
+static int
+ecdsa_generate_private_key(hx509_context context,
+ struct hx509_generate_private_context *ctx,
+ hx509_private_key private_key)
+{
+ return ENOMEM;
+}
+
+static BIGNUM *
+ecdsa_get_internal(hx509_context context,
+ hx509_private_key key,
+ const char *type)
+{
+ return NULL;
+}
+
+
+static hx509_private_key_ops ecdsa_private_key_ops = {
+ "EC PRIVATE KEY",
+ &asn1_oid_id_ecPublicKey,
+ ecdsa_available,
+ ecdsa_private_key2SPKI,
+ ecdsa_private_key_export,
+ ecdsa_private_key_import,
+ ecdsa_generate_private_key,
+ ecdsa_get_internal
+};
+
+#endif /* HAVE_OPENSSL */
/*
*
@@ -668,7 +1124,7 @@ dsa_parse_private_key(hx509_context context,
d2i_DSAPrivateKey(NULL, &p, len);
if (private_key->private_key.dsa == NULL)
return EINVAL;
- private_key->signature_alg = oid_id_dsa_with_sha1();
+ private_key->signature_alg = &asn1_oid_id_dsa_with_sha1;
return 0;
/* else */
@@ -724,7 +1180,7 @@ sha256_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
"\x05\x00", 2);
if (ret)
return ret;
@@ -790,7 +1246,7 @@ sha1_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
"\x05\x00", 2);
if (ret)
return ret;
@@ -871,131 +1327,176 @@ md2_verify_signature(hx509_context context,
return 0;
}
+#ifdef HAVE_OPENSSL
+
+static const struct signature_alg ecdsa_with_sha256_alg = {
+ "ecdsa-with-sha256",
+ &asn1_oid_id_ecdsa_with_SHA256,
+ &_hx509_signature_ecdsa_with_sha256_data,
+ &asn1_oid_id_ecPublicKey,
+ &_hx509_signature_sha256_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 32
+};
+
+static const struct signature_alg ecdsa_with_sha1_alg = {
+ "ecdsa-with-sha1",
+ &asn1_oid_id_ecdsa_with_SHA1,
+ &_hx509_signature_ecdsa_with_sha1_data,
+ &asn1_oid_id_ecPublicKey,
+ &_hx509_signature_sha1_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 20
+};
+
+#endif
+
static const struct signature_alg heim_rsa_pkcs1_x509 = {
"rsa-pkcs1-x509",
- oid_id_heim_rsa_pkcs1_x509,
- hx509_signature_rsa_pkcs1_x509,
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_heim_rsa_pkcs1_x509,
+ &_hx509_signature_rsa_pkcs1_x509_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
NULL,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg pkcs1_rsa_sha1_alg = {
"rsa",
- oid_id_pkcs1_rsaEncryption,
- hx509_signature_rsa_with_sha1,
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_rsa_with_sha1_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
NULL,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_sha256_alg = {
"rsa-with-sha256",
- oid_id_pkcs1_sha256WithRSAEncryption,
- hx509_signature_rsa_with_sha256,
- oid_id_pkcs1_rsaEncryption,
- oid_id_sha256,
+ &asn1_oid_id_pkcs1_sha256WithRSAEncryption,
+ &_hx509_signature_rsa_with_sha256_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_sha256_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_sha1_alg = {
"rsa-with-sha1",
- oid_id_pkcs1_sha1WithRSAEncryption,
- hx509_signature_rsa_with_sha1,
- oid_id_pkcs1_rsaEncryption,
- oid_id_secsig_sha_1,
+ &asn1_oid_id_pkcs1_sha1WithRSAEncryption,
+ &_hx509_signature_rsa_with_sha1_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_sha1_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_md5_alg = {
"rsa-with-md5",
- oid_id_pkcs1_md5WithRSAEncryption,
- hx509_signature_rsa_with_md5,
- oid_id_pkcs1_rsaEncryption,
- oid_id_rsa_digest_md5,
+ &asn1_oid_id_pkcs1_md5WithRSAEncryption,
+ &_hx509_signature_rsa_with_md5_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_md5_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 1230739889,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_md2_alg = {
"rsa-with-md2",
- oid_id_pkcs1_md2WithRSAEncryption,
- hx509_signature_rsa_with_md2,
- oid_id_pkcs1_rsaEncryption,
- oid_id_rsa_digest_md2,
+ &asn1_oid_id_pkcs1_md2WithRSAEncryption,
+ &_hx509_signature_rsa_with_md2_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_md2_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 1230739889,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg dsa_sha1_alg = {
"dsa-with-sha1",
- oid_id_dsa_with_sha1,
+ &asn1_oid_id_dsa_with_sha1,
NULL,
- oid_id_dsa,
- oid_id_secsig_sha_1,
+ &asn1_oid_id_dsa,
+ &_hx509_signature_sha1_data,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
+ 0,
dsa_verify_signature,
/* create_signature */ NULL,
};
static const struct signature_alg sha256_alg = {
"sha-256",
- oid_id_sha256,
- hx509_signature_sha256,
+ &asn1_oid_id_sha256,
+ &_hx509_signature_sha256_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
sha256_verify_signature,
sha256_create_signature
};
static const struct signature_alg sha1_alg = {
"sha1",
- oid_id_secsig_sha_1,
- hx509_signature_sha1,
+ &asn1_oid_id_secsig_sha_1,
+ &_hx509_signature_sha1_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
sha1_verify_signature,
sha1_create_signature
};
static const struct signature_alg md5_alg = {
"rsa-md5",
- oid_id_rsa_digest_md5,
- hx509_signature_md5,
+ &asn1_oid_id_rsa_digest_md5,
+ &_hx509_signature_md5_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
md5_verify_signature
};
static const struct signature_alg md2_alg = {
"rsa-md2",
- oid_id_rsa_digest_md2,
- hx509_signature_md2,
+ &asn1_oid_id_rsa_digest_md2,
+ &_hx509_signature_md2_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
md2_verify_signature
};
/*
* Order matter in this structure, "best" first for each "key
- * compatible" type (type is RSA, DSA, none, etc)
+ * compatible" type (type is ECDSA, RSA, DSA, none, etc)
*/
static const struct signature_alg *sig_algs[] = {
+#ifdef HAVE_OPENSSL
+ &ecdsa_with_sha256_alg,
+ &ecdsa_with_sha1_alg,
+#endif
&rsa_with_sha256_alg,
&rsa_with_sha1_alg,
&pkcs1_rsa_sha1_alg,
@@ -1013,19 +1514,51 @@ static const struct signature_alg *sig_algs[] = {
static const struct signature_alg *
find_sig_alg(const heim_oid *oid)
{
- int i;
+ unsigned int i;
for (i = 0; sig_algs[i]; i++)
- if (der_heim_oid_cmp((*sig_algs[i]->sig_oid)(), oid) == 0)
+ if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)
return sig_algs[i];
return NULL;
}
+static const AlgorithmIdentifier *
+alg_for_privatekey(const hx509_private_key pk, int type)
+{
+ const heim_oid *keytype;
+ unsigned int i;
+
+ if (pk->ops == NULL)
+ return NULL;
+
+ keytype = pk->ops->key_oid;
+
+ for (i = 0; sig_algs[i]; i++) {
+ if (sig_algs[i]->key_oid == NULL)
+ continue;
+ if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)
+ continue;
+ if (pk->ops->available &&
+ pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)
+ continue;
+ if (type == HX509_SELECT_PUBLIC_SIG)
+ return sig_algs[i]->sig_alg;
+ if (type == HX509_SELECT_DIGEST)
+ return sig_algs[i]->digest_alg;
+
+ return NULL;
+ }
+ return NULL;
+}
+
/*
*
*/
static struct hx509_private_key_ops *private_algs[] = {
&rsa_private_key_ops,
+#ifdef HAVE_OPENSSL
+ &ecdsa_private_key_ops,
+#endif
NULL
};
@@ -1036,12 +1569,37 @@ find_private_alg(const heim_oid *oid)
for (i = 0; private_algs[i]; i++) {
if (private_algs[i]->key_oid == NULL)
continue;
- if (der_heim_oid_cmp((*private_algs[i]->key_oid)(), oid) == 0)
+ if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)
return private_algs[i];
}
return NULL;
}
+/*
+ * Check if the algorithm `alg' have a best before date, and if it
+ * des, make sure the its before the time `t'.
+ */
+
+int
+_hx509_signature_best_before(hx509_context context,
+ const AlgorithmIdentifier *alg,
+ time_t t)
+{
+ const struct signature_alg *md;
+
+ md = find_sig_alg(&alg->algorithm);
+ if (md == NULL) {
+ hx509_clear_error_string(context);
+ return HX509_SIG_ALG_NO_SUPPORTED;
+ }
+ if (md->best_before && md->best_before < t) {
+ hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
+ "Algorithm %s has passed it best before date",
+ md->name);
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+ }
+ return 0;
+}
int
_hx509_verify_signature(hx509_context context,
@@ -1069,7 +1627,7 @@ _hx509_verify_signature(hx509_context context,
const SubjectPublicKeyInfo *spi;
spi = &signer->tbsCertificate.subjectPublicKeyInfo;
- if (der_heim_oid_cmp(&spi->algorithm.algorithm, (*md->key_oid)()) != 0) {
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;
}
@@ -1108,13 +1666,6 @@ _hx509_create_signature(hx509_context context,
{
const struct signature_alg *md;
- if (signer && signer->ops && signer->ops->handle_alg &&
- (*signer->ops->handle_alg)(signer, alg, COT_SIGN))
- {
- return (*signer->ops->sign)(context, signer, alg, data,
- signatureAlgorithm, sig);
- }
-
md = find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
@@ -1221,7 +1772,7 @@ _hx509_public_encrypt(hx509_context context,
ciphertext->length = ret;
ciphertext->data = to;
- ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(), encryption_oid);
+ ret = der_copy_oid(&asn1_oid_id_pkcs1_rsaEncryption, encryption_oid);
if (ret) {
der_free_octet_string(ciphertext);
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
@@ -1276,7 +1827,7 @@ _hx509_private_key_private_decrypt(hx509_context context,
int
_hx509_parse_private_key(hx509_context context,
- const heim_oid *key_oid,
+ const AlgorithmIdentifier *keyai,
const void *data,
size_t len,
hx509_private_key *private_key)
@@ -1286,7 +1837,7 @@ _hx509_parse_private_key(hx509_context context,
*private_key = NULL;
- ops = find_private_alg(key_oid);
+ ops = find_private_alg(&keyai->algorithm);
if (ops == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
@@ -1298,7 +1849,7 @@ _hx509_parse_private_key(hx509_context context,
return ret;
}
- ret = (*ops->import)(context, data, len, *private_key);
+ ret = (*ops->import)(context, keyai, data, len, *private_key);
if (ret)
_hx509_private_key_free(private_key);
@@ -1330,7 +1881,7 @@ _hx509_generate_private_key_init(hx509_context context,
{
*ctx = NULL;
- if (der_heim_oid_cmp(oid, oid_id_pkcs1_rsaEncryption()) != 0) {
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0) {
hx509_set_error_string(context, 0, EINVAL,
"private key not an RSA key");
return EINVAL;
@@ -1400,98 +1951,10 @@ _hx509_generate_private_key(hx509_context context,
return ret;
}
-
/*
*
*/
-static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
-
-static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
-const AlgorithmIdentifier _hx509_signature_sha512_data = {
- { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
-const AlgorithmIdentifier _hx509_signature_sha384_data = {
- { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
-const AlgorithmIdentifier _hx509_signature_sha256_data = {
- { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
-const AlgorithmIdentifier _hx509_signature_sha1_data = {
- { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
-const AlgorithmIdentifier _hx509_signature_md5_data = {
- { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 };
-const AlgorithmIdentifier _hx509_signature_md2_data = {
- { 6, rk_UNCONST(md2_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
- { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
- { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
- { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
- { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
-};
-
-static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
- { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
-};
-
-static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = {
- { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL
-};
-
-static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
-const AlgorithmIdentifier _hx509_signature_rsa_data = {
- { 7, rk_UNCONST(rsa_oid) }, NULL
-};
-
-static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
-const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
- { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
-};
-
-static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
-const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
- { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
-};
-
-static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
-const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
- { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
-};
-
-static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
-const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
- { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
-};
-
const AlgorithmIdentifier *
hx509_signature_sha512(void)
{ return &_hx509_signature_sha512_data; }
@@ -1517,6 +1980,18 @@ hx509_signature_md2(void)
{ return &_hx509_signature_md2_data; }
const AlgorithmIdentifier *
+hx509_signature_ecPublicKey(void)
+{ return &_hx509_signature_ecPublicKey; }
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha256(void)
+{ return &_hx509_signature_ecdsa_with_sha256_data; }
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha1(void)
+{ return &_hx509_signature_ecdsa_with_sha1_data; }
+
+const AlgorithmIdentifier *
hx509_signature_rsa_with_sha512(void)
{ return &_hx509_signature_rsa_with_sha512_data; }
@@ -1565,9 +2040,9 @@ hx509_crypto_aes256_cbc(void)
*/
const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
- &_hx509_signature_rsa_with_sha1_data;
+ &_hx509_signature_rsa_with_sha256_data;
const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
- &_hx509_signature_sha1_data;
+ &_hx509_signature_sha256_data;
const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
&_hx509_crypto_aes128_cbc_data;
@@ -1617,8 +2092,15 @@ _hx509_private_key_free(hx509_private_key *key)
if (--(*key)->ref > 0)
return 0;
- if ((*key)->private_key.rsa)
- RSA_free((*key)->private_key.rsa);
+ if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
+ if ((*key)->private_key.rsa)
+ RSA_free((*key)->private_key.rsa);
+#ifdef HAVE_OPENSSL
+ } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0) {
+ if ((*key)->private_key.ecdsa)
+ EC_KEY_free((*key)->private_key.ecdsa);
+#endif
+ }
(*key)->private_key.rsa = NULL;
free(*key);
*key = NULL;
@@ -1631,7 +2113,7 @@ _hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
if (key->private_key.rsa)
RSA_free(key->private_key.rsa);
key->private_key.rsa = ptr;
- key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
key->md = &pkcs1_rsa_sha1_alg;
}
@@ -1641,7 +2123,7 @@ _hx509_private_key_oid(hx509_context context,
heim_oid *data)
{
int ret;
- ret = der_copy_oid((*key->ops->key_oid)(), data);
+ ret = der_copy_oid(key->ops->key_oid, data);
if (ret)
hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret;
@@ -1683,7 +2165,9 @@ _hx509_private_key_export(hx509_context context,
struct hx509cipher {
const char *name;
- const heim_oid *(*oid_func)(void);
+ int flags;
+#define CIPHER_WEAK 1
+ const heim_oid *oid;
const AlgorithmIdentifier *(*ai_func)(void);
const EVP_CIPHER *(*evp_func)(void);
int (*get_params)(hx509_context, const hx509_crypto,
@@ -1694,6 +2178,8 @@ struct hx509cipher {
struct hx509_crypto_data {
char *name;
+ int flags;
+#define ALLOW_WEAK 1
const struct hx509cipher *cipher;
const EVP_CIPHER *c;
heim_octet_string key;
@@ -1705,15 +2191,10 @@ struct hx509_crypto_data {
*
*/
-static const heim_oid *
-oid_private_rc2_40(void)
-{
- static unsigned oid_data[] = { 127, 1 };
- static const heim_oid oid = { 2, oid_data };
-
- return &oid;
-}
+static unsigned private_rc2_40_oid_data[] = { 127, 1 };
+static heim_oid asn1_oid_private_rc2_40 =
+ { 2, private_rc2_40_oid_data };
/*
*
@@ -1853,7 +2334,8 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
static const struct hx509cipher ciphers[] = {
{
"rc2-cbc",
- oid_id_pkcs3_rc2_cbc,
+ CIPHER_WEAK,
+ &asn1_oid_id_pkcs3_rc2_cbc,
NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
@@ -1861,7 +2343,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"rc2-cbc",
- oid_id_rsadsi_rc2_cbc,
+ CIPHER_WEAK,
+ &asn1_oid_id_rsadsi_rc2_cbc,
NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
@@ -1869,7 +2352,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"rc2-40-cbc",
- oid_private_rc2_40,
+ CIPHER_WEAK,
+ &asn1_oid_private_rc2_40,
NULL,
EVP_rc2_40_cbc,
CMSRC2CBCParam_get,
@@ -1877,7 +2361,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"des-ede3-cbc",
- oid_id_pkcs3_des_ede3_cbc,
+ 0,
+ &asn1_oid_id_pkcs3_des_ede3_cbc,
NULL,
EVP_des_ede3_cbc,
CMSCBCParam_get,
@@ -1885,7 +2370,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"des-ede3-cbc",
- oid_id_rsadsi_des_ede3_cbc,
+ 0,
+ &asn1_oid_id_rsadsi_des_ede3_cbc,
hx509_crypto_des_rsdi_ede3_cbc,
EVP_des_ede3_cbc,
CMSCBCParam_get,
@@ -1893,7 +2379,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-128-cbc",
- oid_id_aes_128_cbc,
+ 0,
+ &asn1_oid_id_aes_128_cbc,
hx509_crypto_aes128_cbc,
EVP_aes_128_cbc,
CMSCBCParam_get,
@@ -1901,7 +2388,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-192-cbc",
- oid_id_aes_192_cbc,
+ 0,
+ &asn1_oid_id_aes_192_cbc,
NULL,
EVP_aes_192_cbc,
CMSCBCParam_get,
@@ -1909,7 +2397,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-256-cbc",
- oid_id_aes_256_cbc,
+ 0,
+ &asn1_oid_id_aes_256_cbc,
hx509_crypto_aes256_cbc,
EVP_aes_256_cbc,
CMSCBCParam_get,
@@ -1923,7 +2412,7 @@ find_cipher_by_oid(const heim_oid *oid)
int i;
for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
- if (der_heim_oid_cmp(oid, (*ciphers[i].oid_func)()) == 0)
+ if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)
return &ciphers[i];
return NULL;
@@ -1950,7 +2439,7 @@ hx509_crypto_enctype_by_name(const char *name)
cipher = find_cipher_by_name(name);
if (cipher == NULL)
return NULL;
- return (*cipher->oid_func)();
+ return cipher->oid;
}
int
@@ -2015,6 +2504,12 @@ hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
return 0;
}
+void
+hx509_crypto_allow_weak(hx509_crypto crypto)
+{
+ crypto->flags |= ALLOW_WEAK;
+}
+
int
hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
{
@@ -2111,6 +2606,10 @@ hx509_crypto_encrypt(hx509_crypto crypto,
*ciphertext = NULL;
+ if ((crypto->cipher->flags & CIPHER_WEAK) &&
+ (crypto->flags & ALLOW_WEAK) == 0)
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+
assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
EVP_CIPHER_CTX_init(&evp);
@@ -2189,6 +2688,10 @@ hx509_crypto_decrypt(hx509_crypto crypto,
clear->data = NULL;
clear->length = 0;
+ if ((crypto->cipher->flags & CIPHER_WEAK) &&
+ (crypto->flags & ALLOW_WEAK) == 0)
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+
if (ivec && EVP_CIPHER_iv_length(crypto->c) < ivec->length)
return HX509_CRYPTO_INTERNAL_ERROR;
@@ -2312,6 +2815,8 @@ PBE_string2key(hx509_context context,
if (ret)
goto out;
+ hx509_crypto_allow_weak(c);
+
ret = hx509_crypto_set_key_data(c, key->data, key->length);
if (ret) {
hx509_crypto_destroy(c);
@@ -2330,33 +2835,33 @@ find_string2key(const heim_oid *oid,
const EVP_MD **md,
PBE_string2key_func *s2k)
{
- if (der_heim_oid_cmp(oid, oid_id_pbewithSHAAnd40BitRC2_CBC()) == 0) {
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_pbewithSHAAnd40BitRC2_CBC) == 0) {
*c = EVP_rc2_40_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_private_rc2_40();
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC2_CBC()) == 0) {
+ return &asn1_oid_private_rc2_40;
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC2_CBC) == 0) {
*c = EVP_rc2_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_rc2_cbc();
+ return &asn1_oid_id_pkcs3_rc2_cbc;
#if 0
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd40BitRC4()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd40BitRC4) == 0) {
*c = EVP_rc4_40();
*md = EVP_sha1();
*s2k = PBE_string2key;
return NULL;
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC4()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC4) == 0) {
*c = EVP_rc4();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_rc4();
+ return &asn1_oid_id_pkcs3_rc4;
#endif
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC) == 0) {
*c = EVP_des_ede3_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_des_ede3_cbc();
+ return &asn1_oid_id_pkcs3_des_ede3_cbc;
}
return NULL;
@@ -2467,8 +2972,8 @@ out:
*/
-int
-_hx509_match_keys(hx509_cert c, hx509_private_key private_key)
+static int
+match_keys_rsa(hx509_cert c, hx509_private_key private_key)
{
const Certificate *cert;
const SubjectPublicKeyInfo *spi;
@@ -2523,6 +3028,25 @@ _hx509_match_keys(hx509_cert c, hx509_private_key private_key)
return ret == 1;
}
+static int
+match_keys_ec(hx509_cert c, hx509_private_key private_key)
+{
+ return 1; /* XXX use EC_KEY_check_key */
+}
+
+
+int
+_hx509_match_keys(hx509_cert c, hx509_private_key key)
+{
+ if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0)
+ return match_keys_rsa(c, key);
+ if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0)
+ return match_keys_ec(c, key);
+ return 0;
+
+}
+
+
static const heim_oid *
find_keytype(const hx509_private_key key)
{
@@ -2534,10 +3058,9 @@ find_keytype(const hx509_private_key key)
md = find_sig_alg(key->signature_alg);
if (md == NULL)
return NULL;
- return (*md->key_oid)();
+ return md->key_oid;
}
-
int
hx509_crypto_select(const hx509_context context,
int type,
@@ -2545,7 +3068,7 @@ hx509_crypto_select(const hx509_context context,
hx509_peer_info peer,
AlgorithmIdentifier *selected)
{
- const AlgorithmIdentifier *def;
+ const AlgorithmIdentifier *def = NULL;
size_t i, j;
int ret, bits;
@@ -2553,11 +3076,17 @@ hx509_crypto_select(const hx509_context context,
if (type == HX509_SELECT_DIGEST) {
bits = SIG_DIGEST;
- def = _hx509_crypto_default_digest_alg;
+ if (source)
+ def = alg_for_privatekey(source, type);
+ if (def == NULL)
+ def = _hx509_crypto_default_digest_alg;
} else if (type == HX509_SELECT_PUBLIC_SIG) {
bits = SIG_PUBLIC_SIG;
/* XXX depend on `source´ and `peer´ */
- def = _hx509_crypto_default_sig_alg;
+ if (source)
+ def = alg_for_privatekey(source, type);
+ if (def == NULL)
+ def = _hx509_crypto_default_sig_alg;
} else if (type == HX509_SELECT_SECRET_ENC) {
bits = SIG_SECRET;
def = _hx509_crypto_default_secret_alg;
@@ -2576,11 +3105,11 @@ hx509_crypto_select(const hx509_context context,
for (j = 0; sig_algs[j]; j++) {
if ((sig_algs[j]->flags & bits) != bits)
continue;
- if (der_heim_oid_cmp((*sig_algs[j]->sig_oid)(),
+ if (der_heim_oid_cmp(sig_algs[j]->sig_oid,
&peer->val[i].algorithm) != 0)
continue;
if (keytype && sig_algs[j]->key_oid &&
- der_heim_oid_cmp(keytype, (*sig_algs[j]->key_oid)()))
+ der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))
continue;
/* found one, use that */
@@ -2648,7 +3177,7 @@ hx509_crypto_available(hx509_context context,
if (sig_algs[i]->sig_alg == NULL)
continue;
if (keytype && sig_algs[i]->key_oid &&
- der_heim_oid_cmp((*sig_algs[i]->key_oid)(), keytype))
+ der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))
continue;
/* found one, add that to the list */
@@ -2657,7 +3186,7 @@ hx509_crypto_available(hx509_context context,
goto out;
*val = ptr;
- ret = copy_AlgorithmIdentifier((*sig_algs[i]->sig_alg)(), &(*val)[len]);
+ ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);
if (ret)
goto out;
len++;
@@ -2667,7 +3196,9 @@ hx509_crypto_available(hx509_context context,
if (bits & SIG_SECRET) {
for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
-
+
+ if (ciphers[i].flags & CIPHER_WEAK)
+ continue;
if (ciphers[i].ai_func == NULL)
continue;
diff --git a/source4/heimdal/lib/hx509/env.c b/source4/heimdal/lib/hx509/env.c
index 0b0a68ceae..7598aebaae 100644
--- a/source4/heimdal/lib/hx509/env.c
+++ b/source4/heimdal/lib/hx509/env.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_env Hx509 enviroment functions
diff --git a/source4/heimdal/lib/hx509/error.c b/source4/heimdal/lib/hx509/error.c
index 6f25404145..45813efb38 100644
--- a/source4/heimdal/lib/hx509/error.c
+++ b/source4/heimdal/lib/hx509/error.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_error Hx509 error reporting functions
diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c
index a364dd2179..ba7a23f471 100644
--- a/source4/heimdal/lib/hx509/file.c
+++ b/source4/heimdal/lib/hx509/file.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$ID$");
int
_hx509_map_file_os(const char *fn, heim_octet_string *os)
diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h
index 5e5a2f811b..86aad7ec9c 100644
--- a/source4/heimdal/lib/hx509/hx509.h
+++ b/source4/heimdal/lib/hx509/hx509.h
@@ -36,8 +36,9 @@
#ifndef HEIMDAL_HX509_H
#define HEIMDAL_HX509_H 1
-#include <heim_asn1.h>
#include <rfc2459_asn1.h>
+#include <stdarg.h>
+#include <stdio.h>
typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
typedef struct hx509_cert_data *hx509_cert;
@@ -124,6 +125,17 @@ typedef enum {
/* flags to hx509_cms_unenvelope */
#define HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT 0x01
+#define HX509_CMS_UE_ALLOW_WEAK 0x02
+
+/* flags to hx509_cms_envelope_1 */
+#define HX509_CMS_EV_NO_KU_CHECK 0x01
+#define HX509_CMS_EV_ALLOW_WEAK 0x02
+
+/* flags to hx509_cms_verify_signed */
+#define HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH 0x01
+#define HX509_CMS_VS_NO_KU_CHECK 0x02
+#define HX509_CMS_VS_ALLOW_ZERO_SIGNER 0x04
+#define HX509_CMS_VS_NO_VALIDATE 0x08
/* selectors passed to hx509_crypto_select and hx509_crypto_available */
#define HX509_SELECT_ALL 0
@@ -142,8 +154,9 @@ typedef enum {
#define HX509_CA_TEMPLATE_EKU 64
/* flags hx509_cms_create_signed* */
-#define HX509_CMS_SIGATURE_DETACHED 1
-#define HX509_CMS_SIGATURE_ID_NAME 2
+#define HX509_CMS_SIGNATURE_DETACHED 0x01
+#define HX509_CMS_SIGNATURE_ID_NAME 0x02
+#define HX509_CMS_SIGNATURE_NO_SIGNER 0x04
/* hx509_verify_hostname nametype */
typedef enum {
diff --git a/source4/heimdal/lib/hx509/hx509_err.et b/source4/heimdal/lib/hx509/hx509_err.et
index c1dfaf587e..76bbfaeaba 100644
--- a/source4/heimdal/lib/hx509/hx509_err.et
+++ b/source4/heimdal/lib/hx509/hx509_err.et
@@ -62,9 +62,10 @@ error_code OID_MISMATCH, "Mismatch bewteen oids"
error_code NO_PROMPTER, "No prompter function defined"
error_code SIGNATURE_WITHOUT_SIGNER, "Signature require signer, but non available"
error_code RSA_PUBLIC_ENCRYPT, "RSA public encyption failed"
-error_code RSA_PRIVATE_ENCRYPT, "RSA public encyption failed"
-error_code RSA_PUBLIC_DECRYPT, "RSA private decryption failed"
+error_code RSA_PRIVATE_ENCRYPT, "RSA private encyption failed"
+error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed"
error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed"
+error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date"
# revoke related errors
index 96
diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h
index 8de2353f15..2d1c036d53 100644
--- a/source4/heimdal/lib/hx509/hx_locl.h
+++ b/source4/heimdal/lib/hx509/hx_locl.h
@@ -33,9 +33,7 @@
/* $Id$ */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
@@ -145,7 +143,7 @@ struct hx509_query_data {
Name *subject_name;
hx509_path *path;
char *friendlyname;
- int (*cmp_func)(void *, hx509_cert);
+ int (*cmp_func)(hx509_context, hx509_cert, void *);
void *cmp_func_ctx;
heim_octet_string *keyhash_sha1;
time_t timenow;
diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c
index b68064b512..c4f035ab87 100644
--- a/source4/heimdal/lib/hx509/keyset.c
+++ b/source4/heimdal/lib/hx509/keyset.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_keyset Certificate store operations
@@ -481,6 +480,10 @@ hx509_certs_find(hx509_context context,
hx509_certs_end_seq(context, certs, cursor);
if (ret)
return ret;
+ /**
+ * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
+ * the query.
+ */
if (c == NULL) {
hx509_clear_error_string(context);
return HX509_CERT_NOT_FOUND;
@@ -489,6 +492,77 @@ hx509_certs_find(hx509_context context,
return 0;
}
+/**
+ * Filter certificate matching the query.
+ *
+ * @param context a hx509 context.
+ * @param certs certificate store to search.
+ * @param q query allocated with @ref hx509_query functions.
+ * @param result the filtered certificate store, caller must free with
+ * hx509_certs_free().
+ *
+ * @return Returns an hx509 error code.
+ *
+ * @ingroup hx509_keyset
+ */
+
+int
+hx509_certs_filter(hx509_context context,
+ hx509_certs certs,
+ const hx509_query *q,
+ hx509_certs *result)
+{
+ hx509_cursor cursor;
+ hx509_cert c;
+ int ret, found = 0;
+
+ _hx509_query_statistic(context, 0, q);
+
+ ret = hx509_certs_init(context, "MEMORY:filter-certs", 0,
+ NULL, result);
+ if (ret)
+ return ret;
+
+ ret = hx509_certs_start_seq(context, certs, &cursor);
+ if (ret) {
+ hx509_certs_free(result);
+ return ret;
+ }
+
+ c = NULL;
+ while (1) {
+ ret = hx509_certs_next_cert(context, certs, cursor, &c);
+ if (ret)
+ break;
+ if (c == NULL)
+ break;
+ if (_hx509_query_match_cert(context, q, c)) {
+ hx509_certs_add(context, *result, c);
+ found = 1;
+ }
+ hx509_cert_free(c);
+ }
+
+ hx509_certs_end_seq(context, certs, cursor);
+ if (ret) {
+ hx509_certs_free(result);
+ return ret;
+ }
+
+ /**
+ * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
+ * the query.
+ */
+ if (!found) {
+ hx509_certs_free(result);
+ hx509_clear_error_string(context);
+ return HX509_CERT_NOT_FOUND;
+ }
+
+ return 0;
+}
+
+
static int
certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
{
diff --git a/source4/heimdal/lib/hx509/ks_dir.c b/source4/heimdal/lib/hx509/ks_dir.c
index 76c0c42633..a627fc65a2 100644
--- a/source4/heimdal/lib/hx509/ks_dir.c
+++ b/source4/heimdal/lib/hx509/ks_dir.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#include <dirent.h>
/*
@@ -71,7 +70,7 @@ dir_init(hx509_context context,
return ENOENT;
}
- if ((sb.st_mode & S_IFDIR) == 0) {
+ if (!S_ISDIR(sb.st_mode)) {
hx509_set_error_string(context, 0, ENOTDIR,
"%s is not a directory", residue);
return ENOTDIR;
diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c
index ca0171f8b9..74808f7607 100644
--- a/source4/heimdal/lib/hx509/ks_file.c
+++ b/source4/heimdal/lib/hx509/ks_file.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
typedef enum { USE_PEM, USE_DER } outformat;
@@ -50,7 +49,8 @@ static int
parse_certificate(hx509_context context, const char *fn,
struct hx509_collector *c,
const hx509_pem_header *headers,
- const void *data, size_t len)
+ const void *data, size_t len,
+ const AlgorithmIdentifier *ai)
{
hx509_cert cert;
int ret;
@@ -130,10 +130,40 @@ out:
}
static int
-parse_rsa_private_key(hx509_context context, const char *fn,
+parse_pkcs8_private_key(hx509_context context, const char *fn,
+ struct hx509_collector *c,
+ const hx509_pem_header *headers,
+ const void *data, size_t length,
+ const AlgorithmIdentifier *ai)
+{
+ PKCS8PrivateKeyInfo ki;
+ heim_octet_string keydata;
+
+ int ret;
+
+ ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
+ if (ret)
+ return ret;
+
+ keydata.data = rk_UNCONST(data);
+ keydata.length = length;
+
+ ret = _hx509_collector_private_key_add(context,
+ c,
+ &ki.privateKeyAlgorithm,
+ NULL,
+ &ki.privateKey,
+ &keydata);
+ free_PKCS8PrivateKeyInfo(&ki);
+ return ret;
+}
+
+static int
+parse_pem_private_key(hx509_context context, const char *fn,
struct hx509_collector *c,
const hx509_pem_header *headers,
- const void *data, size_t len)
+ const void *data, size_t len,
+ const AlgorithmIdentifier *ai)
{
int ret = 0;
const char *enc;
@@ -159,7 +189,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (strcmp(enc, "4,ENCRYPTED") != 0) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "RSA key encrypted in unknown method %s "
+ "Private key encrypted in unknown method %s "
"in file",
enc, fn);
hx509_clear_error_string(context);
@@ -169,7 +199,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
dek = hx509_pem_find_header(headers, "DEK-Info");
if (dek == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Encrypted RSA missing DEK-Info");
+ "Encrypted private key missing DEK-Info");
return HX509_PARSING_KEY_FAILED;
}
@@ -201,7 +231,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (cipher == NULL) {
free(ivdata);
hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
- "RSA key encrypted with "
+ "Private key encrypted with "
"unsupported cipher: %s",
type);
free(type);
@@ -218,7 +248,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
free(ivdata);
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Salt have wrong length in RSA key file");
+ "Salt have wrong length in "
+ "private key file");
return HX509_PARSING_KEY_FAILED;
}
@@ -231,9 +262,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
password = pw->val[i];
passwordlen = strlen(password);
- ret = try_decrypt(context, c, hx509_signature_rsa(),
- cipher, ivdata, password, passwordlen,
- data, len);
+ ret = try_decrypt(context, c, ai, cipher, ivdata,
+ password, passwordlen, data, len);
if (ret == 0) {
decrypted = 1;
break;
@@ -253,9 +283,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
ret = hx509_lock_prompt(lock, &prompt);
if (ret == 0)
- ret = try_decrypt(context, c, hx509_signature_rsa(),
- cipher, ivdata, password, strlen(password),
- data, len);
+ ret = try_decrypt(context, c, ai, cipher, ivdata, password,
+ strlen(password), data, len);
/* XXX add password to lock password collection ? */
memset(password, 0, sizeof(password));
}
@@ -267,12 +296,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
keydata.data = rk_UNCONST(data);
keydata.length = len;
- ret = _hx509_collector_private_key_add(context,
- c,
- hx509_signature_rsa(),
- NULL,
- &keydata,
- NULL);
+ ret = _hx509_collector_private_key_add(context, c, ai, NULL,
+ &keydata, NULL);
}
return ret;
@@ -282,10 +307,14 @@ parse_rsa_private_key(hx509_context context, const char *fn,
struct pem_formats {
const char *name;
int (*func)(hx509_context, const char *, struct hx509_collector *,
- const hx509_pem_header *, const void *, size_t);
+ const hx509_pem_header *, const void *, size_t,
+ const AlgorithmIdentifier *);
+ const AlgorithmIdentifier *(*ai)(void);
} formats[] = {
- { "CERTIFICATE", parse_certificate },
- { "RSA PRIVATE KEY", parse_rsa_private_key }
+ { "CERTIFICATE", parse_certificate, NULL },
+ { "PRIVATE KEY", parse_pkcs8_private_key, NULL },
+ { "RSA PRIVATE KEY", parse_pem_private_key, hx509_signature_rsa },
+ { "EC PRIVATE KEY", parse_pem_private_key, hx509_signature_ecPublicKey }
};
@@ -305,9 +334,18 @@ pem_func(hx509_context context, const char *type,
for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
const char *q = formats[j].name;
if (strcasecmp(type, q) == 0) {
- ret = (*formats[j].func)(context, NULL, pem_ctx->c, header, data, len);
- if (ret == 0)
- break;
+ const AlgorithmIdentifier *ai = NULL;
+ if (formats[j].ai != NULL)
+ ai = (*formats[j].ai)();
+
+ ret = (*formats[j].func)(context, NULL, pem_ctx->c,
+ header, data, len, ai);
+ if (ret) {
+ hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
+ "Failed parseing PEM format %s", type);
+ return ret;
+ }
+ break;
}
}
if (j == sizeof(formats)/sizeof(formats[0])) {
@@ -409,13 +447,19 @@ file_init_common(hx509_context context,
}
for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
- ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length);
+ const AlgorithmIdentifier *ai = NULL;
+ if (formats[i].ai != NULL)
+ ai = (*formats[i].ai)();
+
+ ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length, ai);
if (ret == 0)
break;
}
rk_xfree(ptr);
- if (ret)
+ if (ret) {
+ hx509_clear_error_string(context);
goto out;
+ }
}
}
diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c
index 2dc0721563..01d0c55d1c 100644
--- a/source4/heimdal/lib/hx509/ks_keychain.c
+++ b/source4/heimdal/lib/hx509/ks_keychain.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#ifdef HAVE_FRAMEWORK_SECURITY
@@ -119,6 +118,8 @@ kc_rsa_private_encrypt(int flen,
CSSM_DATA sig, in;
int fret = 0;
+ if (padding != RSA_PKCS1_PADDING)
+ return -1;
cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
if(cret) abort();
@@ -157,7 +158,62 @@ static int
kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
RSA * rsa, int padding)
{
- return -1;
+ struct kc_rsa *kc = RSA_get_app_data(rsa);
+
+ CSSM_RETURN cret;
+ OSStatus ret;
+ const CSSM_ACCESS_CREDENTIALS *creds;
+ SecKeyRef privKeyRef = (SecKeyRef)kc->item;
+ CSSM_CSP_HANDLE cspHandle;
+ const CSSM_KEY *cssmKey;
+ CSSM_CC_HANDLE handle = 0;
+ CSSM_DATA out, in, rem;
+ int fret = 0;
+ CSSM_SIZE outlen = 0;
+ char remdata[1024];
+
+ if (padding != RSA_PKCS1_PADDING)
+ return -1;
+
+ cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
+ if(cret) abort();
+
+ cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);
+ if(cret) abort();
+
+ ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT,
+ kSecCredentialTypeDefault, &creds);
+ if(ret) abort();
+
+
+ ret = CSSM_CSP_CreateAsymmetricContext (cspHandle,
+ CSSM_ALGID_RSA,
+ creds,
+ cssmKey,
+ CSSM_PADDING_PKCS1,
+ &handle);
+ if(ret) abort();
+
+ in.Data = (uint8 *)from;
+ in.Length = flen;
+
+ out.Data = (uint8 *)to;
+ out.Length = kc->keysize;
+
+ rem.Data = (uint8 *)remdata;
+ rem.Length = sizeof(remdata);
+
+ cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem);
+ if(cret) {
+ /* cssmErrorString(cret); */
+ fret = -1;
+ } else
+ fret = out.Length;
+
+ if(handle)
+ CSSM_DeleteContext(handle);
+
+ return fret;
}
static int
@@ -504,8 +560,7 @@ keychain_iter_end(hx509_context context,
struct iter *iter = cursor;
if (iter->certs) {
- int ret;
- ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
+ hx509_certs_end_seq(context, iter->certs, iter->cursor);
hx509_certs_free(&iter->certs);
} else {
CFRelease(iter->searchRef);
diff --git a/source4/heimdal/lib/hx509/ks_mem.c b/source4/heimdal/lib/hx509/ks_mem.c
index bf952fbeee..299a3932c9 100644
--- a/source4/heimdal/lib/hx509/ks_mem.c
+++ b/source4/heimdal/lib/hx509/ks_mem.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("Id$");
/*
* Should use two hash/tree certificates intead of a array. Criteria
diff --git a/source4/heimdal/lib/hx509/ks_null.c b/source4/heimdal/lib/hx509/ks_null.c
index fae631fb3f..136d2d4345 100644
--- a/source4/heimdal/lib/hx509/ks_null.c
+++ b/source4/heimdal/lib/hx509/ks_null.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
static int
diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c
index 652cdc2210..52697f834b 100644
--- a/source4/heimdal/lib/hx509/ks_p11.c
+++ b/source4/heimdal/lib/hx509/ks_p11.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -332,7 +331,7 @@ p11_init_slot(hx509_context context,
}
asprintf(&slot->name, "%.*s",
- i, slot_info.slotDescription);
+ (int)i, slot_info.slotDescription);
if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)
return 0;
@@ -711,7 +710,7 @@ collect_cert(hx509_context context,
_hx509_set_cert_attribute(context,
cert,
- oid_id_pkcs_9_at_localKeyId(),
+ &asn1_oid_id_pkcs_9_at_localKeyId,
&data);
}
@@ -945,11 +944,7 @@ p11_release_module(struct p11_module *p)
if (p->slot[i].flags & P11_SESSION_IN_USE)
_hx509_abort("pkcs11 module release while session in use");
if (p->slot[i].flags & P11_SESSION) {
- int ret;
-
- ret = P11FUNC(p, CloseSession, (p->slot[i].session));
- if (ret != CKR_OK)
- ;
+ P11FUNC(p, CloseSession, (p->slot[i].session));
}
if (p->slot[i].name)
diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c
index b59bd215f0..c17ce3f6ac 100644
--- a/source4/heimdal/lib/hx509/ks_p12.c
+++ b/source4/heimdal/lib/hx509/ks_p12.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct ks_pkcs12 {
hx509_certs certs;
@@ -45,7 +44,7 @@ typedef int (*collector_func)(hx509_context,
const PKCS12_Attributes *);
struct type {
- const heim_oid * (*oid)(void);
+ const heim_oid *oid;
collector_func func;
};
@@ -77,7 +76,7 @@ keyBag_parser(hx509_context context,
const heim_octet_string *os = NULL;
int ret;
- attr = find_attribute(attrs, oid_id_pkcs_9_at_localKeyId());
+ attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId);
if (attr)
os = &attr->attrValues;
@@ -140,7 +139,7 @@ certBag_parser(hx509_context context,
if (ret)
return ret;
- if (der_heim_oid_cmp(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) {
free_PKCS12_CertBag(&cb);
return 0;
}
@@ -166,13 +165,13 @@ certBag_parser(hx509_context context,
{
const PKCS12_Attribute *attr;
- const heim_oid * (*oids[])(void) = {
- oid_id_pkcs_9_at_localKeyId, oid_id_pkcs_9_at_friendlyName
+ const heim_oid *oids[] = {
+ &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName
};
int i;
- for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
- const heim_oid *oid = (*(oids[i]))();
+ for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
+ const heim_oid *oid = oids[i];
attr = find_attribute(attrs, oid);
if (attr)
_hx509_set_cert_attribute(context, cert, oid,
@@ -248,7 +247,7 @@ encryptedData_parser(hx509_context context,
if (ret)
return ret;
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) == 0)
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
ret = parse_safe_content(context, c, content.data, content.length);
der_free_octet_string(&content);
@@ -285,7 +284,7 @@ envelopedData_parser(hx509_context context,
return ret;
}
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) == 0)
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
ret = parse_safe_content(context, c, content.data, content.length);
der_free_octet_string(&content);
@@ -296,12 +295,12 @@ envelopedData_parser(hx509_context context,
struct type bagtypes[] = {
- { oid_id_pkcs12_keyBag, keyBag_parser },
- { oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
- { oid_id_pkcs12_certBag, certBag_parser },
- { oid_id_pkcs7_data, safeContent_parser },
- { oid_id_pkcs7_encryptedData, encryptedData_parser },
- { oid_id_pkcs7_envelopedData, envelopedData_parser }
+ { &asn1_oid_id_pkcs12_keyBag, keyBag_parser },
+ { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
+ { &asn1_oid_id_pkcs12_certBag, certBag_parser },
+ { &asn1_oid_id_pkcs7_data, safeContent_parser },
+ { &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser },
+ { &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser }
};
static void
@@ -314,7 +313,7 @@ parse_pkcs12_type(hx509_context context,
int i;
for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++)
- if (der_heim_oid_cmp((*bagtypes[i].oid)(), oid) == 0)
+ if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0)
(*bagtypes[i].func)(context, c, data, length, attrs);
}
@@ -376,7 +375,7 @@ p12_init(hx509_context context,
goto out;
}
- if (der_heim_oid_cmp(&pfx.authSafe.contentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) {
free_PKCS12_PFX(&pfx);
ret = EINVAL;
hx509_set_error_string(context, 0, ret,
@@ -506,7 +505,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
free(os.data);
if (ret)
goto out;
- ret = der_copy_oid(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType);
+ ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType);
if (ret) {
free_PKCS12_CertBag(&cb);
goto out;
@@ -517,7 +516,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
if (ret)
goto out;
- ret = addBag(context, as, oid_id_pkcs12_certBag(), os.data, os.length);
+ ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length);
if (_hx509_cert_private_key_exportable(c)) {
hx509_private_key key = _hx509_cert_private_key(c);
@@ -541,7 +540,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
free_PKCS8PrivateKeyInfo(&pki);
return ret;
}
- /* set attribute, oid_id_pkcs_9_at_localKeyId() */
+ /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */
ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length,
&pki, &size, ret);
@@ -549,7 +548,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
if (ret)
return ret;
- ret = addBag(context, as, oid_id_pkcs12_keyBag(), os.data, os.length);
+ ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length);
if (ret)
return ret;
}
@@ -598,7 +597,7 @@ p12_store(hx509_context context,
if (ret)
goto out;
- ret = der_copy_oid(oid_id_pkcs7_data(), &pfx.authSafe.contentType);
+ ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType);
if (ret)
goto out;
diff --git a/source4/heimdal/lib/hx509/lock.c b/source4/heimdal/lib/hx509/lock.c
index e2ceedecb8..219a301928 100644
--- a/source4/heimdal/lib/hx509/lock.c
+++ b/source4/heimdal/lib/hx509/lock.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_lock Locking and unlocking certificates and encrypted data.
diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c
index 069eed6062..b8f48d5236 100644
--- a/source4/heimdal/lib/hx509/name.c
+++ b/source4/heimdal/lib/hx509/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2009 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <wind.h>
-RCSID("$Id$");
/**
* @page page_name PKIX/X.509 Names
@@ -63,20 +62,20 @@ RCSID("$Id$");
static const struct {
const char *n;
- const heim_oid *(*o)(void);
+ const heim_oid *o;
wind_profile_flags flags;
} no[] = {
- { "C", oid_id_at_countryName },
- { "CN", oid_id_at_commonName },
- { "DC", oid_id_domainComponent },
- { "L", oid_id_at_localityName },
- { "O", oid_id_at_organizationName },
- { "OU", oid_id_at_organizationalUnitName },
- { "S", oid_id_at_stateOrProvinceName },
- { "STREET", oid_id_at_streetAddress },
- { "UID", oid_id_Userid },
- { "emailAddress", oid_id_pkcs9_emailAddress },
- { "serialNumber", oid_id_at_serialNumber }
+ { "C", &asn1_oid_id_at_countryName },
+ { "CN", &asn1_oid_id_at_commonName },
+ { "DC", &asn1_oid_id_domainComponent },
+ { "L", &asn1_oid_id_at_localityName },
+ { "O", &asn1_oid_id_at_organizationName },
+ { "OU", &asn1_oid_id_at_organizationalUnitName },
+ { "S", &asn1_oid_id_at_stateOrProvinceName },
+ { "STREET", &asn1_oid_id_at_streetAddress },
+ { "UID", &asn1_oid_id_Userid },
+ { "emailAddress", &asn1_oid_id_pkcs9_emailAddress },
+ { "serialNumber", &asn1_oid_id_at_serialNumber }
};
static char *
@@ -145,7 +144,7 @@ oidtostring(const heim_oid *type)
size_t i;
for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
- if (der_heim_oid_cmp((*no[i].o)(), type) == 0)
+ if (der_heim_oid_cmp(no[i].o, type) == 0)
return strdup(no[i].n);
}
if (der_print_heim_oid(type, '.', &s) != 0)
@@ -163,7 +162,7 @@ stringtooid(const char *name, size_t len, heim_oid *oid)
for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
if (strncasecmp(no[i].n, name, len) == 0)
- return der_copy_oid((*no[i].o)(), oid);
+ return der_copy_oid(no[i].o, oid);
}
s = malloc(len + 1);
if (s == NULL)
@@ -197,7 +196,7 @@ int
_hx509_Name_to_string(const Name *n, char **str)
{
size_t total_len = 0;
- int i, j;
+ int i, j, ret;
*str = strdup("");
if (*str == NULL)
@@ -224,15 +223,20 @@ _hx509_Name_to_string(const Name *n, char **str)
ss = ds->u.utf8String;
break;
case choice_DirectoryString_bmpString: {
- uint16_t *bmp = ds->u.bmpString.data;
+ const uint16_t *bmp = ds->u.bmpString.data;
size_t bmplen = ds->u.bmpString.length;
size_t k;
- ss = malloc(bmplen + 1);
+ ret = wind_ucs2utf8_length(bmp, bmplen, &k);
+ if (ret)
+ return ret;
+
+ ss = malloc(k + 1);
if (ss == NULL)
_hx509_abort("allocation failure"); /* XXX */
- for (k = 0; k < bmplen; k++)
- ss[k] = bmp[k] & 0xff; /* XXX */
+ ret = wind_ucs2utf8(bmp, bmplen, ss, NULL);
+ if (ret)
+ return ret;
ss[k] = '\0';
break;
}
@@ -244,15 +248,20 @@ _hx509_Name_to_string(const Name *n, char **str)
ss[ds->u.teletexString.length] = '\0';
break;
case choice_DirectoryString_universalString: {
- uint32_t *uni = ds->u.universalString.data;
+ const uint32_t *uni = ds->u.universalString.data;
size_t unilen = ds->u.universalString.length;
size_t k;
- ss = malloc(unilen + 1);
+ ret = wind_ucs4utf8_length(uni, unilen, &k);
+ if (ret)
+ return ret;
+
+ ss = malloc(k + 1);
if (ss == NULL)
_hx509_abort("allocation failure"); /* XXX */
- for (k = 0; k < unilen; k++)
- ss[k] = uni[k] & 0xff; /* XXX */
+ ret = wind_ucs4utf8(uni, unilen, ss, NULL);
+ if (ret)
+ return ret;
ss[k] = '\0';
break;
}
@@ -344,8 +353,10 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
if (name == NULL)
return ENOMEM;
ret = wind_utf8ucs4(ds->u.utf8String, name, &len);
- if (ret)
+ if (ret) {
+ free(name);
return ret;
+ }
break;
default:
_hx509_abort("unknown directory type: %d", ds->element);
diff --git a/source4/heimdal/lib/hx509/peer.c b/source4/heimdal/lib/hx509/peer.c
index f5841e497b..c796e19173 100644
--- a/source4/heimdal/lib/hx509/peer.c
+++ b/source4/heimdal/lib/hx509/peer.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_peer Hx509 crypto selecting functions
@@ -121,6 +120,39 @@ hx509_peer_info_set_cert(hx509_peer_info peer,
}
/**
+ * Add an additional algorithm that the peer supports.
+ *
+ * @param context A hx509 context.
+ * @param peer the peer to set the new algorithms for
+ * @param val an AlgorithmsIdentier to add
+ *
+ * @return An hx509 error code, see hx509_get_error_string().
+ *
+ * @ingroup hx509_peer
+ */
+
+int
+hx509_peer_info_add_cms_alg(hx509_context context,
+ hx509_peer_info peer,
+ const AlgorithmIdentifier *val)
+{
+ void *ptr;
+ int ret;
+
+ ptr = realloc(peer->val, sizeof(peer->val[0]) * (peer->len + 1));
+ if (ptr == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ ret = copy_AlgorithmIdentifier(val, &peer->val[peer->len]);
+ if (ret == 0)
+ peer->len += 1;
+ else
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ return ret;
+}
+
+/**
* Set the algorithms that the peer supports.
*
* @param context A hx509 context.
diff --git a/source4/heimdal/lib/hx509/print.c b/source4/heimdal/lib/hx509/print.c
index 38d103905f..ddafb7f46e 100644
--- a/source4/heimdal/lib/hx509/print.c
+++ b/source4/heimdal/lib/hx509/print.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_print Hx509 printing functions
@@ -547,14 +546,14 @@ check_CRLDistributionPoints(hx509_validate_ctx ctx,
struct {
const char *name;
- const heim_oid *(*oid)(void);
+ const heim_oid *oid;
int (*func)(hx509_validate_ctx, heim_any *);
-} check_altname[] = {
- { "pk-init", oid_id_pkinit_san, check_pkinit_san },
- { "jabber", oid_id_pkix_on_xmppAddr, check_utf8_string_san },
- { "dns-srv", oid_id_pkix_on_dnsSRV, check_altnull },
- { "card-id", oid_id_uspkicommon_card_id, check_altnull },
- { "Microsoft NT-PRINCIPAL-NAME", oid_id_pkinit_ms_san, check_utf8_string_san }
+} altname_types[] = {
+ { "pk-init", &asn1_oid_id_pkinit_san, check_pkinit_san },
+ { "jabber", &asn1_oid_id_pkix_on_xmppAddr, check_utf8_string_san },
+ { "dns-srv", &asn1_oid_id_pkix_on_dnsSRV, check_altnull },
+ { "card-id", &asn1_oid_id_uspkicommon_card_id, check_altnull },
+ { "Microsoft NT-PRINCIPAL-NAME", &asn1_oid_id_pkinit_ms_san, check_utf8_string_san }
};
static int
@@ -597,17 +596,17 @@ check_altName(hx509_validate_ctx ctx,
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"%sAltName otherName ", name);
- for (j = 0; j < sizeof(check_altname)/sizeof(check_altname[0]); j++) {
- if (der_heim_oid_cmp((*check_altname[j].oid)(),
+ for (j = 0; j < sizeof(altname_types)/sizeof(altname_types[0]); j++) {
+ if (der_heim_oid_cmp(altname_types[j].oid,
&gn.val[i].u.otherName.type_id) != 0)
continue;
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s: ",
- check_altname[j].name);
- (*check_altname[j].func)(ctx, &gn.val[i].u.otherName.value);
+ altname_types[j].name);
+ (*altname_types[j].func)(ctx, &gn.val[i].u.otherName.value);
break;
}
- if (j == sizeof(check_altname)/sizeof(check_altname[0])) {
+ if (j == sizeof(altname_types)/sizeof(altname_types[0])) {
hx509_oid_print(&gn.val[i].u.otherName.type_id,
validate_vprint, ctx);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " unknown");
@@ -751,14 +750,14 @@ check_authorityInfoAccess(hx509_validate_ctx ctx,
struct {
const char *name;
- const heim_oid *(*oid)(void);
+ const heim_oid *oid;
int (*func)(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *);
enum critical_flag cf;
} check_extension[] = {
-#define ext(name, checkname) #name, &oid_id_x509_ce_##name, check_##checkname
+#define ext(name, checkname) #name, &asn1_oid_id_x509_ce_##name, check_##checkname
{ ext(subjectDirectoryAttributes, Null), M_N_C },
{ ext(subjectKeyIdentifier, subjectKeyIdentifier), M_N_C },
{ ext(keyUsage, Null), S_C },
@@ -782,13 +781,13 @@ struct {
{ ext(freshestCRL, Null), M_N_C },
{ ext(inhibitAnyPolicy, Null), M_C },
#undef ext
-#define ext(name, checkname) #name, &oid_id_pkix_pe_##name, check_##checkname
+#define ext(name, checkname) #name, &asn1_oid_id_pkix_pe_##name, check_##checkname
{ ext(proxyCertInfo, proxyCertInfo), M_C },
{ ext(authorityInfoAccess, authorityInfoAccess), M_C },
#undef ext
- { "US Fed PKI - PIV Interim", oid_id_uspkicommon_piv_interim,
+ { "US Fed PKI - PIV Interim", &asn1_oid_id_uspkicommon_piv_interim,
check_Null, D_C },
- { "Netscape cert comment", oid_id_netscape_cert_comment,
+ { "Netscape cert comment", &asn1_oid_id_netscape_cert_comment,
check_Null, D_C },
{ NULL }
};
@@ -949,7 +948,7 @@ hx509_validate_cert(hx509_context context,
for (i = 0; i < t->extensions->len; i++) {
for (j = 0; check_extension[j].name; j++)
- if (der_heim_oid_cmp((*check_extension[j].oid)(),
+ if (der_heim_oid_cmp(check_extension[j].oid,
&t->extensions->val[i].extnID) == 0)
break;
if (check_extension[j].name == NULL) {
diff --git a/source4/heimdal/lib/hx509/req.c b/source4/heimdal/lib/hx509/req.c
index 9836777143..0d174e0cec 100644
--- a/source4/heimdal/lib/hx509/req.c
+++ b/source4/heimdal/lib/hx509/req.c
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <pkcs10_asn1.h>
-RCSID("$Id$");
struct hx509_request_data {
hx509_name name;
diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c
index 3f35b0d190..adb31164c1 100644
--- a/source4/heimdal/lib/hx509/revoke.c
+++ b/source4/heimdal/lib/hx509/revoke.c
@@ -50,7 +50,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct revoke_crl {
char *path;
@@ -235,7 +234,7 @@ verify_ocsp(hx509_context context,
}
ret = hx509_cert_check_eku(context, signer,
- oid_id_pkix_kp_OCSPSigning(), 0);
+ &asn1_oid_id_pkix_kp_OCSPSigning, 0);
if (ret)
goto out;
}
@@ -295,7 +294,7 @@ parse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic)
}
ret = der_heim_oid_cmp(&resp.responseBytes->responseType,
- oid_id_pkix_ocsp_basic());
+ &asn1_oid_id_pkix_ocsp_basic);
if (ret != 0) {
free_OCSPResponse(&resp);
return HX509_REVOKE_WRONG_DATA;
@@ -1011,8 +1010,7 @@ hx509_ocsp_request(hx509_context context,
goto out;
}
es->len = 1;
-
- ret = der_copy_oid(oid_id_pkix_ocsp_nonce(), &es->val[0].extnID);
+ ret = der_copy_oid(&asn1_oid_id_pkix_ocsp_nonce, &es->val[0].extnID);
if (ret) {
free_OCSPRequest(&req);
return ret;
diff --git a/source4/heimdal/lib/hx509/sel-gram.y b/source4/heimdal/lib/hx509/sel-gram.y
index e529479724..7f7c9980e0 100644
--- a/source4/heimdal/lib/hx509/sel-gram.y
+++ b/source4/heimdal/lib/hx509/sel-gram.y
@@ -39,7 +39,6 @@
#include <stdlib.h>
#include <hx_locl.h>
-RCSID("$Id$");
%}
diff --git a/source4/heimdal/lib/hx509/test_name.c b/source4/heimdal/lib/hx509/test_name.c
index da83e52786..2cdcdf85f6 100644
--- a/source4/heimdal/lib/hx509/test_name.c
+++ b/source4/heimdal/lib/hx509/test_name.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
static int
test_name(hx509_context context, const char *name)