diff options
Diffstat (limited to 'crypto/heimdal/lib/hx509/crypto.c')
-rw-r--r-- | crypto/heimdal/lib/hx509/crypto.c | 1737 |
1 files changed, 1119 insertions, 618 deletions
diff --git a/crypto/heimdal/lib/hx509/crypto.c b/crypto/heimdal/lib/hx509/crypto.c index e0f00ad7b45b..4559a9c49391 100644 --- a/crypto/heimdal/lib/hx509/crypto.c +++ b/crypto/heimdal/lib/hx509/crypto.c @@ -1,47 +1,42 @@ /* - * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include "hx_locl.h" -RCSID("$Id: crypto.c 22435 2008-01-14 20:53:56Z lha $"); struct hx509_crypto; struct signature_alg; -enum crypto_op_type { - COT_SIGN -}; - struct hx509_generate_private_context { const heim_oid *key_oid; int isCA; @@ -50,40 +45,23 @@ 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, + hx509_key_format_t, 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_key_format_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 +71,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,13 +84,14 @@ 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 +#define PROVIDE_CONF 0x1 +#define REQUIRE_SIGNER 0x2 +#define SELF_SIGNED_OK 0x4 #define SIG_DIGEST 0x100 #define SIG_PUBLIC_SIG 0x200 @@ -118,7 +99,8 @@ struct signature_alg { #define RA_RSA_USES_DIGEST_INFO 0x1000000 - + time_t best_before; /* refuse signature made after best before date */ + const EVP_MD *(*evp_md)(void); int (*verify_signature)(hx509_context context, const struct signature_alg *, const Certificate *, @@ -132,6 +114,106 @@ 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 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_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 +266,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 */ + /* * */ @@ -202,32 +543,18 @@ rsa_verify_signature(hx509_context context, int tosize, retsize; int ret; RSA *rsa; - RSAPublicKey pk; size_t size; + const unsigned char *p; memset(&di, 0, sizeof(di)); spi = &signer->tbsCertificate.subjectPublicKeyInfo; - rsa = RSA_new(); - if (rsa == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - ret = decode_RSAPublicKey(spi->subjectPublicKey.data, - spi->subjectPublicKey.length / 8, - &pk, &size); - if (ret) { - hx509_set_error_string(context, 0, ret, "Failed to decode RSAPublicKey"); - goto out; - } + p = spi->subjectPublicKey.data; + size = spi->subjectPublicKey.length / 8; - rsa->n = heim_int2BN(&pk.modulus); - rsa->e = heim_int2BN(&pk.publicExponent); - - free_RSAPublicKey(&pk); - - if (rsa->n == NULL || rsa->e == NULL) { + rsa = d2i_RSAPublicKey(NULL, &p, size); + if (rsa == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; @@ -241,11 +568,11 @@ rsa_verify_signature(hx509_context context, goto out; } - retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data, + retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data, to, rsa, RSA_PKCS1_PADDING); if (retsize <= 0) { ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, + hx509_set_error_string(context, 0, ret, "RSA public decrypt failed: %d", retsize); free(to); goto out; @@ -260,23 +587,23 @@ rsa_verify_signature(hx509_context context, if (ret) { goto out; } - + /* Check for extra data inside the sigature */ - if (size != retsize) { + if (size != (size_t)retsize) { ret = HX509_CRYPTO_SIG_INVALID_FORMAT; hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); goto out; } - - if (sig_alg->digest_oid && - der_heim_oid_cmp(&di.digestAlgorithm.algorithm, - (*sig_alg->digest_oid)()) != 0) + + if (sig_alg->digest_alg && + der_heim_oid_cmp(&di.digestAlgorithm.algorithm, + &sig_alg->digest_alg->algorithm) != 0) { ret = HX509_CRYPTO_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch"); goto out; } - + /* verify that the parameters are NULL or the NULL-type */ if (di.digestAlgorithm.parameters != NULL && (di.digestAlgorithm.parameters->length != 2 || @@ -293,8 +620,8 @@ rsa_verify_signature(hx509_context context, data, &di.digest); } else { - if (retsize != data->length || - memcmp(to, data->data, retsize) != 0) + if ((size_t)retsize != data->length || + ct_memcmp(to, data->data, retsize) != 0) { ret = HX509_CRYPTO_SIG_INVALID_FORMAT; hx509_set_error_string(context, 0, ret, "RSA Signature incorrect"); @@ -302,10 +629,12 @@ rsa_verify_signature(hx509_context context, } free(to); } + ret = 0; out: free_DigestInfo(&di); - RSA_free(rsa); + if (rsa) + RSA_free(rsa); return ret; } @@ -323,25 +652,32 @@ rsa_create_signature(hx509_context context, const heim_oid *sig_oid; 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_SHA512WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha512(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha384(); + } else 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; @@ -391,8 +727,8 @@ rsa_create_signature(hx509_context context, return ENOMEM; } - ret = RSA_private_encrypt(indata.length, indata.data, - sig->data, + ret = RSA_private_encrypt(indata.length, indata.data, + sig->data, signer->private_key.rsa, RSA_PKCS1_PADDING); if (indata.data != data->data) @@ -400,33 +736,43 @@ rsa_create_signature(hx509_context context, if (ret <= 0) { ret = HX509_CMS_FAILED_CREATE_SIGATURE; hx509_set_error_string(context, 0, ret, - "RSA private decrypt failed: %d", ret); + "RSA private encrypt failed: %d", ret); return ret; } - if (ret > sig->length) + if ((size_t)ret > sig->length) _hx509_abort("RSA signature prelen longer the output len"); sig->length = ret; - + return 0; } static int rsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, const void *data, size_t len, + hx509_key_format_t format, hx509_private_key private_key) { - const unsigned char *p = data; + switch (format) { + case HX509_KEY_FORMAT_DER: { + const unsigned char *p = data; + + private_key->private_key.rsa = + d2i_RSAPrivateKey(NULL, &p, len); + if (private_key->private_key.rsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse RSA key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + break; - private_key->private_key.rsa = - d2i_RSAPrivateKey(NULL, &p, len); - if (private_key->private_key.rsa == NULL) { - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "Failed to parse RSA key"); - return HX509_PARSING_KEY_FAILED; } - private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption(); + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } return 0; } @@ -449,7 +795,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"); @@ -468,7 +814,7 @@ rsa_private_key2SPKI(hx509_context context, } static int -rsa_generate_private_key(hx509_context context, +rsa_generate_private_key(hx509_context context, struct hx509_generate_private_context *ctx, hx509_private_key private_key) { @@ -477,7 +823,7 @@ rsa_generate_private_key(hx509_context context, unsigned long bits; static const int default_rsa_e = 65537; - static const int default_rsa_bits = 1024; + static const int default_rsa_bits = 2048; private_key->private_key.rsa = RSA_new(); if (private_key->private_key.rsa == NULL) { @@ -485,7 +831,7 @@ rsa_generate_private_key(hx509_context context, "Failed to generate RSA key"); return HX509_PARSING_KEY_FAILED; } - + e = BN_new(); BN_set_word(e, default_rsa_e); @@ -493,8 +839,6 @@ rsa_generate_private_key(hx509_context context, if (ctx->num_bits) bits = ctx->num_bits; - else if (ctx->isCA) - bits *= 2; ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL); BN_free(e); @@ -503,14 +847,15 @@ 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; } -static int +static int rsa_private_key_export(hx509_context context, const hx509_private_key key, + hx509_key_format_t format, heim_octet_string *data) { int ret; @@ -518,32 +863,41 @@ rsa_private_key_export(hx509_context context, data->data = NULL; data->length = 0; - ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); - if (ret <= 0) { - ret = EINVAL; - hx509_set_error_string(context, 0, ret, + switch (format) { + case HX509_KEY_FORMAT_DER: + + ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); + if (ret <= 0) { + ret = EINVAL; + hx509_set_error_string(context, 0, ret, "Private key is not exportable"); - return ret; - } + return ret; + } - data->data = malloc(ret); - if (data->data == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "malloc out of memory"); - return ret; - } - data->length = ret; - - { - unsigned char *p = data->data; - i2d_RSAPrivateKey(key->private_key.rsa, &p); + data->data = malloc(ret); + if (data->data == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + return ret; + } + data->length = ret; + + { + unsigned char *p = data->data; + i2d_RSAPrivateKey(key->private_key.rsa, &p); + } + break; + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; } return 0; } 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 +911,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 +920,114 @@ 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, + hx509_key_format_t format, + heim_octet_string *data) +{ + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; +} + +static int +ecdsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, + const void *data, + size_t len, + hx509_key_format_t format, + 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; + } + + switch (format) { + case HX509_KEY_FORMAT_DER: + + 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; + break; + + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + 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 */ /* * @@ -664,11 +1127,11 @@ dsa_parse_private_key(hx509_context context, { const unsigned char *p = data; - private_key->private_key.dsa = + private_key->private_key.dsa = 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 */ @@ -678,39 +1141,8 @@ dsa_parse_private_key(hx509_context context, } #endif - static int -sha1_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) -{ - unsigned char digest[SHA_DIGEST_LENGTH]; - SHA_CTX m; - - if (sig->length != SHA_DIGEST_LENGTH) { - hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, - "SHA1 sigature have wrong length"); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } - - SHA1_Init(&m); - SHA1_Update(&m, data->data, data->length); - SHA1_Final (digest, &m); - - if (memcmp(digest, sig->data, SHA_DIGEST_LENGTH) != 0) { - hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, - "Bad SHA1 sigature"); - return HX509_CRYPTO_BAD_SIGNATURE; - } - - return 0; -} - -static int -sha256_create_signature(hx509_context context, +evp_md_create_signature(hx509_context context, const struct signature_alg *sig_alg, const hx509_private_key signer, const AlgorithmIdentifier *alg, @@ -718,339 +1150,448 @@ sha256_create_signature(hx509_context context, AlgorithmIdentifier *signatureAlgorithm, heim_octet_string *sig) { - SHA256_CTX m; - + size_t sigsize = EVP_MD_size(sig_alg->evp_md()); + EVP_MD_CTX *ctx; + memset(sig, 0, sizeof(*sig)); 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; } - - sig->data = malloc(SHA256_DIGEST_LENGTH); + + sig->data = malloc(sigsize); if (sig->data == NULL) { sig->length = 0; return ENOMEM; } - sig->length = SHA256_DIGEST_LENGTH; + sig->length = sigsize; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestUpdate(ctx, data->data, data->length); + EVP_DigestFinal_ex(ctx, sig->data, NULL); + EVP_MD_CTX_destroy(ctx); - SHA256_Init(&m); - SHA256_Update(&m, data->data, data->length); - SHA256_Final (sig->data, &m); return 0; } static int -sha256_verify_signature(hx509_context context, +evp_md_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) { - unsigned char digest[SHA256_DIGEST_LENGTH]; - SHA256_CTX m; - - if (sig->length != SHA256_DIGEST_LENGTH) { + unsigned char digest[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *ctx; + size_t sigsize = EVP_MD_size(sig_alg->evp_md()); + + if (sig->length != sigsize || sigsize > sizeof(digest)) { hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, "SHA256 sigature have wrong length"); return HX509_CRYPTO_SIG_INVALID_FORMAT; } - SHA256_Init(&m); - SHA256_Update(&m, data->data, data->length); - SHA256_Final (digest, &m); - - if (memcmp(digest, sig->data, SHA256_DIGEST_LENGTH) != 0) { - hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, - "Bad SHA256 sigature"); - return HX509_CRYPTO_BAD_SIGNATURE; - } - - return 0; -} - -static int -sha1_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) -{ - SHA_CTX m; - - memset(sig, 0, sizeof(*sig)); - - if (signatureAlgorithm) { - int ret; - ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(), - "\x05\x00", 2); - if (ret) - return ret; - } - - - sig->data = malloc(SHA_DIGEST_LENGTH); - if (sig->data == NULL) { - sig->length = 0; - return ENOMEM; - } - sig->length = SHA_DIGEST_LENGTH; - - SHA1_Init(&m); - SHA1_Update(&m, data->data, data->length); - SHA1_Final (sig->data, &m); - - return 0; -} - -static int -md5_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) -{ - unsigned char digest[MD5_DIGEST_LENGTH]; - MD5_CTX m; - - if (sig->length != MD5_DIGEST_LENGTH) { - hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, - "MD5 sigature have wrong length"); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestUpdate(ctx, data->data, data->length); + EVP_DigestFinal_ex(ctx, digest, NULL); + EVP_MD_CTX_destroy(ctx); - MD5_Init(&m); - MD5_Update(&m, data->data, data->length); - MD5_Final (digest, &m); - - if (memcmp(digest, sig->data, MD5_DIGEST_LENGTH) != 0) { + if (ct_memcmp(digest, sig->data, sigsize) != 0) { hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, - "Bad MD5 sigature"); + "Bad %s sigature", sig_alg->name); return HX509_CRYPTO_BAD_SIGNATURE; } return 0; } -static int -md2_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) -{ - unsigned char digest[MD2_DIGEST_LENGTH]; - MD2_CTX m; - - if (sig->length != MD2_DIGEST_LENGTH) { - hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, - "MD2 sigature have wrong length"); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } +#ifdef HAVE_OPENSSL - MD2_Init(&m); - MD2_Update(&m, data->data, data->length); - MD2_Final (digest, &m); - - if (memcmp(digest, sig->data, MD2_DIGEST_LENGTH) != 0) { - hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, - "Bad MD2 sigature"); - return HX509_CRYPTO_BAD_SIGNATURE; - } +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|SELF_SIGNED_OK, + 0, + NULL, + ecdsa_verify_signature, + ecdsa_create_signature, + 32 +}; - return 0; -} +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|SELF_SIGNED_OK, + 0, + NULL, + 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, + NULL, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 }; 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|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha512_alg = { + "rsa-with-sha512", + ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha512_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha512_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, NULL, - PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha384_alg = { + "rsa-with-sha384", + ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha384_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha384_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 }; 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, - PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + 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|SELF_SIGNED_OK, + 0, + NULL, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 }; 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, - PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + 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|SELF_SIGNED_OK, + 0, + NULL, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 }; -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, - PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, +static const struct signature_alg rsa_with_sha1_alg_secsig = { + "rsa-with-sha1", + ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION, + &_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|SELF_SIGNED_OK, + 0, + NULL, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 }; -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, +static const struct signature_alg rsa_with_md5_alg = { + "rsa-with-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, + NULL, rsa_verify_signature, - rsa_create_signature + rsa_create_signature, + 0 }; 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, + NULL, dsa_verify_signature, /* create_signature */ NULL, + 0 +}; + +static const struct signature_alg sha512_alg = { + "sha-512", + ASN1_OID_ID_SHA512, + &_hx509_signature_sha512_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha512, + evp_md_verify_signature, + evp_md_create_signature, + 0 +}; + +static const struct signature_alg sha384_alg = { + "sha-384", + ASN1_OID_ID_SHA512, + &_hx509_signature_sha384_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha384, + evp_md_verify_signature, + evp_md_create_signature, + 0 }; 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, - sha256_verify_signature, - sha256_create_signature + 0, + EVP_sha256, + evp_md_verify_signature, + evp_md_create_signature, + 0 }; 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, - sha1_verify_signature, - sha1_create_signature + 0, + EVP_sha1, + evp_md_verify_signature, + evp_md_create_signature, + 0 }; 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, - md5_verify_signature -}; - -static const struct signature_alg md2_alg = { - "rsa-md2", - oid_id_rsa_digest_md2, - hx509_signature_md2, + 0, + EVP_md5, + evp_md_verify_signature, NULL, - NULL, - SIG_DIGEST, - md2_verify_signature + 0 }; -/* +/* * 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_sha512_alg, + &rsa_with_sha384_alg, &rsa_with_sha256_alg, &rsa_with_sha1_alg, + &rsa_with_sha1_alg_secsig, &pkcs1_rsa_sha1_alg, &rsa_with_md5_alg, - &rsa_with_md2_alg, &heim_rsa_pkcs1_x509, &dsa_sha1_alg, + &sha512_alg, + &sha384_alg, &sha256_alg, &sha1_alg, &md5_alg, - &md2_alg, NULL }; 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 }; -static hx509_private_key_ops * -find_private_alg(const heim_oid *oid) +hx509_private_key_ops * +hx509_find_private_alg(const heim_oid *oid) { int i; 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_self_signed_valid(hx509_context context, + const AlgorithmIdentifier *alg) +{ + 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->flags & SELF_SIGNED_OK) == 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE, + "Algorithm %s not trusted for self signatures", + md->name); + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + } + return 0; +} + int _hx509_verify_signature(hx509_context context, - const Certificate *signer, + const hx509_cert cert, const AlgorithmIdentifier *alg, const heim_octet_string *data, const heim_octet_string *sig) { const struct signature_alg *md; + const Certificate *signer = NULL; + + if (cert) + signer = _hx509_get_cert(cert); md = find_sig_alg(&alg->algorithm); if (md == NULL) { @@ -1069,7 +1610,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; } @@ -1078,27 +1619,6 @@ _hx509_verify_signature(hx509_context context, } int -_hx509_verify_signature_bitstring(hx509_context context, - const Certificate *signer, - const AlgorithmIdentifier *alg, - const heim_octet_string *data, - const heim_bit_string *sig) -{ - heim_octet_string os; - - if (sig->length & 7) { - hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, - "signature not multiple of 8 bits"); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } - - os.data = sig->data; - os.length = sig->length / 8; - - return _hx509_verify_signature(context, signer, alg, data, &os); -} - -int _hx509_create_signature(hx509_context context, const hx509_private_key signer, const AlgorithmIdentifier *alg, @@ -1108,13 +1628,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, @@ -1128,7 +1641,7 @@ _hx509_create_signature(hx509_context context, return HX509_CRYPTO_SIG_NO_CONF; } - return (*md->create_signature)(context, md, signer, alg, data, + return (*md->create_signature)(context, md, signer, alg, data, signatureAlgorithm, sig); } @@ -1164,35 +1677,19 @@ _hx509_public_encrypt(hx509_context context, int tosize; int ret; RSA *rsa; - RSAPublicKey pk; size_t size; + const unsigned char *p; ciphertext->data = NULL; ciphertext->length = 0; spi = &cert->tbsCertificate.subjectPublicKeyInfo; - rsa = RSA_new(); - if (rsa == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } + p = spi->subjectPublicKey.data; + size = spi->subjectPublicKey.length / 8; - ret = decode_RSAPublicKey(spi->subjectPublicKey.data, - spi->subjectPublicKey.length / 8, - &pk, &size); - if (ret) { - RSA_free(rsa); - hx509_set_error_string(context, 0, ret, "RSAPublicKey decode failure"); - return ret; - } - rsa->n = heim_int2BN(&pk.modulus); - rsa->e = heim_int2BN(&pk.publicExponent); - - free_RSAPublicKey(&pk); - - if (rsa->n == NULL || rsa->e == NULL) { - RSA_free(rsa); + rsa = d2i_RSAPublicKey(NULL, &p, size); + if (rsa == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } @@ -1205,8 +1702,8 @@ _hx509_public_encrypt(hx509_context context, return ENOMEM; } - ret = RSA_public_encrypt(cleartext->length, - (unsigned char *)cleartext->data, + ret = RSA_public_encrypt(cleartext->length, + (unsigned char *)cleartext->data, to, rsa, RSA_PKCS1_PADDING); RSA_free(rsa); if (ret <= 0) { @@ -1221,7 +1718,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"); @@ -1232,7 +1729,7 @@ _hx509_public_encrypt(hx509_context context, } int -_hx509_private_key_private_decrypt(hx509_context context, +hx509_private_key_private_decrypt(hx509_context context, const heim_octet_string *ciphertext, const heim_oid *encryption_oid, hx509_private_key p, @@ -1265,7 +1762,7 @@ _hx509_private_key_private_decrypt(hx509_context context, "Failed to decrypt using private key: %d", ret); return HX509_CRYPTO_RSA_PRIVATE_DECRYPT; } - if (cleartext->length < ret) + if (cleartext->length < (size_t)ret) _hx509_abort("internal rsa decryption failure: ret > tosize"); cleartext->length = ret; @@ -1275,10 +1772,11 @@ _hx509_private_key_private_decrypt(hx509_context context, int -_hx509_parse_private_key(hx509_context context, - const heim_oid *key_oid, +hx509_parse_private_key(hx509_context context, + const AlgorithmIdentifier *keyai, const void *data, size_t len, + hx509_key_format_t format, hx509_private_key *private_key) { struct hx509_private_key_ops *ops; @@ -1286,21 +1784,21 @@ _hx509_parse_private_key(hx509_context context, *private_key = NULL; - ops = find_private_alg(key_oid); + ops = hx509_find_private_alg(&keyai->algorithm); if (ops == NULL) { hx509_clear_error_string(context); return HX509_SIG_ALG_NO_SUPPORTED; } - ret = _hx509_private_key_init(private_key, ops, NULL); + ret = hx509_private_key_init(private_key, ops, NULL); if (ret) { hx509_set_error_string(context, 0, ret, "out of memory"); return ret; } - ret = (*ops->import)(context, data, len, *private_key); + ret = (*ops->import)(context, keyai, data, len, format, *private_key); if (ret) - _hx509_private_key_free(private_key); + hx509_private_key_free(private_key); return ret; } @@ -1310,7 +1808,7 @@ _hx509_parse_private_key(hx509_context context, */ int -_hx509_private_key2SPKI(hx509_context context, +hx509_private_key2SPKI(hx509_context context, hx509_private_key private_key, SubjectPublicKeyInfo *spki) { @@ -1330,8 +1828,8 @@ _hx509_generate_private_key_init(hx509_context context, { *ctx = NULL; - if (der_heim_oid_cmp(oid, oid_id_pkcs1_rsaEncryption()) != 0) { - hx509_set_error_string(context, 0, EINVAL, + 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; } @@ -1381,13 +1879,13 @@ _hx509_generate_private_key(hx509_context context, *private_key = NULL; - ops = find_private_alg(ctx->key_oid); + ops = hx509_find_private_alg(ctx->key_oid); if (ops == NULL) { hx509_clear_error_string(context); return HX509_SIG_ALG_NO_SUPPORTED; } - ret = _hx509_private_key_init(private_key, ops, NULL); + ret = hx509_private_key_init(private_key, ops, NULL); if (ret) { hx509_set_error_string(context, 0, ret, "out of memory"); return ret; @@ -1395,103 +1893,15 @@ _hx509_generate_private_key(hx509_context context, ret = (*ops->generate_private_key)(context, ctx, *private_key); if (ret) - _hx509_private_key_free(private_key); + hx509_private_key_free(private_key); 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; } @@ -1513,8 +1923,16 @@ hx509_signature_md5(void) { return &_hx509_signature_md5_data; } const AlgorithmIdentifier * -hx509_signature_md2(void) -{ return &_hx509_signature_md2_data; } +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) @@ -1537,10 +1955,6 @@ hx509_signature_rsa_with_md5(void) { return &_hx509_signature_rsa_with_md5_data; } const AlgorithmIdentifier * -hx509_signature_rsa_with_md2(void) -{ return &_hx509_signature_rsa_with_md2_data; } - -const AlgorithmIdentifier * hx509_signature_rsa(void) { return &_hx509_signature_rsa_data; } @@ -1564,11 +1978,11 @@ hx509_crypto_aes256_cbc(void) * */ -const AlgorithmIdentifier * _hx509_crypto_default_sig_alg = - &_hx509_signature_rsa_with_sha1_data; -const AlgorithmIdentifier * _hx509_crypto_default_digest_alg = - &_hx509_signature_sha1_data; -const AlgorithmIdentifier * _hx509_crypto_default_secret_alg = +const AlgorithmIdentifier * _hx509_crypto_default_sig_alg = + &_hx509_signature_rsa_with_sha256_data; +const AlgorithmIdentifier * _hx509_crypto_default_digest_alg = + &_hx509_signature_sha256_data; +const AlgorithmIdentifier * _hx509_crypto_default_secret_alg = &_hx509_crypto_aes128_cbc_data; /* @@ -1576,7 +1990,7 @@ const AlgorithmIdentifier * _hx509_crypto_default_secret_alg = */ int -_hx509_private_key_init(hx509_private_key *key, +hx509_private_key_init(hx509_private_key *key, hx509_private_key_ops *ops, void *keydata) { @@ -1592,11 +2006,11 @@ _hx509_private_key_init(hx509_private_key *key, hx509_private_key _hx509_private_key_ref(hx509_private_key key) { - if (key->ref <= 0) - _hx509_abort("refcount <= 0"); - key->ref++; if (key->ref == 0) - _hx509_abort("refcount == 0"); + _hx509_abort("key refcount <= 0 on ref"); + key->ref++; + if (key->ref == UINT_MAX) + _hx509_abort("key refcount == UINT_MAX on ref"); return key; } @@ -1607,18 +2021,25 @@ _hx509_private_pem_name(hx509_private_key key) } int -_hx509_private_key_free(hx509_private_key *key) +hx509_private_key_free(hx509_private_key *key) { if (key == NULL || *key == NULL) return 0; - if ((*key)->ref <= 0) - _hx509_abort("refcount <= 0"); + if ((*key)->ref == 0) + _hx509_abort("key refcount == 0 on free"); 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; @@ -1626,22 +2047,22 @@ _hx509_private_key_free(hx509_private_key *key) } void -_hx509_private_key_assign_rsa(hx509_private_key key, void *ptr) +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; } -int +int _hx509_private_key_oid(hx509_context context, const hx509_private_key key, 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; @@ -1657,7 +2078,7 @@ _hx509_private_key_exportable(hx509_private_key key) BIGNUM * _hx509_private_key_get_internal(hx509_context context, - hx509_private_key key, + hx509_private_key key, const char *type) { if (key->ops->get_internal == NULL) @@ -1665,16 +2086,17 @@ _hx509_private_key_get_internal(hx509_context context, return (*key->ops->get_internal)(context, key, type); } -int +int _hx509_private_key_export(hx509_context context, const hx509_private_key key, + hx509_key_format_t format, heim_octet_string *data) { if (key->ops->export == NULL) { hx509_clear_error_string(context); return HX509_UNIMPLEMENTED_OPERATION; } - return (*key->ops->export)(context, key, data); + return (*key->ops->export)(context, key, format, data); } /* @@ -1683,17 +2105,25 @@ _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, const heim_octet_string *, heim_octet_string *); - int (*set_params)(hx509_context, const heim_octet_string *, + int (*set_params)(hx509_context, const heim_octet_string *, hx509_crypto, heim_octet_string *); }; struct hx509_crypto_data { char *name; + int flags; +#define ALLOW_WEAK 1 + +#define PADDING_NONE 2 +#define PADDING_PKCS7 4 +#define PADDING_FLAGS (2|4) const struct hx509cipher *cipher; const EVP_CIPHER *c; heim_octet_string key; @@ -1705,15 +2135,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 +2278,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 +2287,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 +2296,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 +2305,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 +2314,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 +2323,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 +2332,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 +2341,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, @@ -1920,10 +2353,10 @@ static const struct hx509cipher ciphers[] = { static const struct hx509cipher * find_cipher_by_oid(const heim_oid *oid) { - int i; + size_t 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; @@ -1932,7 +2365,7 @@ find_cipher_by_oid(const heim_oid *oid) static const struct hx509cipher * find_cipher_by_name(const char *name) { - int i; + size_t i; for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) if (strcasecmp(name, ciphers[i].name) == 0) @@ -1950,7 +2383,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 @@ -1976,6 +2409,7 @@ hx509_crypto_init(hx509_context context, return ENOMEM; } + (*crypto)->flags = PADDING_PKCS7; (*crypto)->cipher = cipher; (*crypto)->c = (*cipher->evp_func)(); @@ -2015,10 +2449,33 @@ 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; +} + +void +hx509_crypto_set_padding(hx509_crypto crypto, int padding_type) +{ + switch (padding_type) { + case HX509_CRYPTO_PADDING_PKCS7: + crypto->flags &= ~PADDING_FLAGS; + crypto->flags |= PADDING_PKCS7; + break; + case HX509_CRYPTO_PADDING_NONE: + crypto->flags &= ~PADDING_FLAGS; + crypto->flags |= PADDING_NONE; + break; + default: + _hx509_abort("Invalid padding"); + } +} + int hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length) { - if (EVP_CIPHER_key_length(crypto->c) > length) + if (EVP_CIPHER_key_length(crypto->c) > (int)length) return HX509_CRYPTO_INTERNAL_ERROR; if (crypto->key.data) { @@ -2063,7 +2520,7 @@ hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key) int hx509_crypto_set_params(hx509_context context, - hx509_crypto crypto, + hx509_crypto crypto, const heim_octet_string *param, heim_octet_string *ivec) { @@ -2072,7 +2529,7 @@ hx509_crypto_set_params(hx509_context context, int hx509_crypto_get_params(hx509_context context, - hx509_crypto crypto, + hx509_crypto crypto, const heim_octet_string *ivec, heim_octet_string *param) { @@ -2106,12 +2563,16 @@ hx509_crypto_encrypt(hx509_crypto crypto, heim_octet_string **ciphertext) { EVP_CIPHER_CTX evp; - size_t padsize; + size_t padsize, bsize; int ret; *ciphertext = NULL; - assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length); + if ((crypto->cipher->flags & CIPHER_WEAK) && + (crypto->flags & ALLOW_WEAK) == 0) + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + + assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length); EVP_CIPHER_CTX_init(&evp); @@ -2128,23 +2589,30 @@ hx509_crypto_encrypt(hx509_crypto crypto, ret = ENOMEM; goto out; } - - if (EVP_CIPHER_block_size(crypto->c) == 1) { - padsize = 0; - } else { - int bsize = EVP_CIPHER_block_size(crypto->c); - padsize = bsize - (length % bsize); + + assert(crypto->flags & PADDING_FLAGS); + + bsize = EVP_CIPHER_block_size(crypto->c); + padsize = 0; + + if (crypto->flags & PADDING_NONE) { + if (bsize != 1 && (length % bsize) != 0) + return HX509_CMS_PADDING_ERROR; + } else if (crypto->flags & PADDING_PKCS7) { + if (bsize != 1) + padsize = bsize - (length % bsize); } + (*ciphertext)->length = length + padsize; (*ciphertext)->data = malloc(length + padsize); if ((*ciphertext)->data == NULL) { ret = ENOMEM; goto out; } - + memcpy((*ciphertext)->data, data, length); if (padsize) { - int i; + size_t i; unsigned char *p = (*ciphertext)->data; p += length; for (i = 0; i < padsize; i++) @@ -2189,7 +2657,11 @@ hx509_crypto_decrypt(hx509_crypto crypto, clear->data = NULL; clear->length = 0; - if (ivec && EVP_CIPHER_iv_length(crypto->c) < ivec->length) + 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) < (int)ivec->length) return HX509_CRYPTO_INTERNAL_ERROR; if (crypto->key.data == NULL) @@ -2220,12 +2692,12 @@ hx509_crypto_decrypt(hx509_crypto crypto, } EVP_CIPHER_CTX_cleanup(&evp); - if (EVP_CIPHER_block_size(crypto->c) > 1) { + if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) { int padsize; - unsigned char *p; + unsigned char *p; int j, bsize = EVP_CIPHER_block_size(crypto->c); - if (clear->length < bsize) { + if ((int)clear->length < bsize) { ret = HX509_CMS_PADDING_ERROR; goto out; } @@ -2259,7 +2731,7 @@ hx509_crypto_decrypt(hx509_crypto crypto, typedef int (*PBE_string2key_func)(hx509_context, const char *, const heim_octet_string *, - hx509_crypto *, heim_octet_string *, + hx509_crypto *, heim_octet_string *, heim_octet_string *, const heim_oid *, const EVP_MD *); @@ -2267,7 +2739,7 @@ static int PBE_string2key(hx509_context context, const char *password, const heim_octet_string *parameters, - hx509_crypto *crypto, + hx509_crypto *crypto, heim_octet_string *key, heim_octet_string *iv, const heim_oid *enc_oid, const EVP_MD *md) @@ -2296,13 +2768,13 @@ PBE_string2key(hx509_context context, salt = p12params.salt.data; saltlen = p12params.salt.length; - if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, + if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, PKCS12_KEY_ID, iter, key->length, key->data, md)) { ret = HX509_CRYPTO_INTERNAL_ERROR; goto out; } - - if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, + + if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, PKCS12_IV_ID, iter, iv->length, iv->data, md)) { ret = HX509_CRYPTO_INTERNAL_ERROR; goto out; @@ -2312,6 +2784,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); @@ -2325,38 +2799,38 @@ out: } static const heim_oid * -find_string2key(const heim_oid *oid, - const EVP_CIPHER **c, +find_string2key(const heim_oid *oid, + const EVP_CIPHER **c, 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; @@ -2394,7 +2868,8 @@ _hx509_pbe_decrypt(hx509_context context, const EVP_CIPHER *c; const EVP_MD *md; PBE_string2key_func s2k; - int i, ret = 0; + int ret = 0; + size_t i; memset(&key, 0, sizeof(key)); memset(&iv, 0, sizeof(iv)); @@ -2439,7 +2914,7 @@ _hx509_pbe_decrypt(hx509_context context, else password = NULL; - ret = (*s2k)(context, password, ai->parameters, &crypto, + ret = (*s2k)(context, password, ai->parameters, &crypto, &key, &iv, enc_oid, md); if (ret) goto out; @@ -2452,7 +2927,7 @@ _hx509_pbe_decrypt(hx509_context context, hx509_crypto_destroy(crypto); if (ret == 0) goto out; - + } out: if (key.data) @@ -2467,8 +2942,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; @@ -2510,7 +2985,7 @@ _hx509_match_keys(hx509_cert c, hx509_private_key private_key) rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1); rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp); - if (rsa->n == NULL || rsa->e == NULL || + if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL) { RSA_free(rsa); @@ -2523,6 +2998,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 +3028,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 +3038,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,16 +3046,22 @@ 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; + /* XXX depend on `source´ and `peer´ */ + 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; } else { - hx509_set_error_string(context, 0, EINVAL, + hx509_set_error_string(context, 0, EINVAL, "Unknown type %d of selection", type); return EINVAL; } @@ -2576,11 +3075,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)())) + if (keytype && sig_algs[j]->key_oid && + der_heim_oid_cmp(keytype, sig_algs[j]->key_oid)) continue; /* found one, use that */ @@ -2633,7 +3132,7 @@ hx509_crypto_available(hx509_context context, } else if (type == HX509_SELECT_PUBLIC_SIG) { bits = SIG_PUBLIC_SIG; } else { - hx509_set_error_string(context, 0, EINVAL, + hx509_set_error_string(context, 0, EINVAL, "Unknown type %d of available", type); return EINVAL; } @@ -2647,8 +3146,8 @@ hx509_crypto_available(hx509_context context, continue; 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)) + if (keytype && sig_algs[i]->key_oid && + der_heim_oid_cmp(sig_algs[i]->key_oid, keytype)) continue; /* found one, add that to the list */ @@ -2657,7 +3156,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 +3166,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; @@ -2675,7 +3176,7 @@ hx509_crypto_available(hx509_context context, if (ptr == NULL) goto out; *val = ptr; - + ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]); if (ret) goto out; @@ -2703,4 +3204,4 @@ hx509_crypto_free_algs(AlgorithmIdentifier *val, for (i = 0; i < len; i++) free_AlgorithmIdentifier(&val[i]); free(val); -} +} |