summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/hx509/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/lib/hx509/crypto.c')
-rw-r--r--crypto/heimdal/lib/hx509/crypto.c2706
1 files changed, 0 insertions, 2706 deletions
diff --git a/crypto/heimdal/lib/hx509/crypto.c b/crypto/heimdal/lib/hx509/crypto.c
deleted file mode 100644
index e0f00ad..0000000
--- a/crypto/heimdal/lib/hx509/crypto.c
+++ /dev/null
@@ -1,2706 +0,0 @@
-/*
- * 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:
- *
- * 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.
- *
- * 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.
- */
-
-#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;
- unsigned long num_bits;
-};
-
-struct hx509_private_key_ops {
- const char *pemtype;
- const heim_oid *(*key_oid)(void);
- 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 (*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 {
- unsigned int ref;
- const struct signature_alg *md;
- const heim_oid *signature_alg;
- union {
- RSA *rsa;
- void *keydata;
- } private_key;
- /* new crypto layer */
- hx509_private_key_ops *ops;
-};
-
-/*
- *
- */
-
-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);
- int flags;
-#define PROVIDE_CONF 1
-#define REQUIRE_SIGNER 2
-
-#define SIG_DIGEST 0x100
-#define SIG_PUBLIC_SIG 0x200
-#define SIG_SECRET 0x400
-
-#define RA_RSA_USES_DIGEST_INFO 0x1000000
-
-
- int (*verify_signature)(hx509_context context,
- const struct signature_alg *,
- const Certificate *,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- const heim_octet_string *);
- int (*create_signature)(hx509_context,
- const struct signature_alg *,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- AlgorithmIdentifier *,
- heim_octet_string *);
-};
-
-/*
- *
- */
-
-static BIGNUM *
-heim_int2BN(const heim_integer *i)
-{
- BIGNUM *bn;
-
- bn = BN_bin2bn(i->data, i->length, NULL);
- BN_set_negative(bn, i->negative);
- return bn;
-}
-
-/*
- *
- */
-
-static int
-set_digest_alg(DigestAlgorithmIdentifier *id,
- const heim_oid *oid,
- const void *param, size_t length)
-{
- int ret;
- if (param) {
- id->parameters = malloc(sizeof(*id->parameters));
- if (id->parameters == NULL)
- return ENOMEM;
- id->parameters->data = malloc(length);
- if (id->parameters->data == NULL) {
- free(id->parameters);
- id->parameters = NULL;
- return ENOMEM;
- }
- memcpy(id->parameters->data, param, length);
- id->parameters->length = length;
- } else
- id->parameters = NULL;
- ret = der_copy_oid(oid, &id->algorithm);
- if (ret) {
- if (id->parameters) {
- free(id->parameters->data);
- free(id->parameters);
- id->parameters = NULL;
- }
- return ret;
- }
- return 0;
-}
-
-/*
- *
- */
-
-static int
-rsa_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 SubjectPublicKeyInfo *spi;
- DigestInfo di;
- unsigned char *to;
- int tosize, retsize;
- int ret;
- RSA *rsa;
- RSAPublicKey pk;
- size_t size;
-
- 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;
- }
-
- rsa->n = heim_int2BN(&pk.modulus);
- rsa->e = heim_int2BN(&pk.publicExponent);
-
- free_RSAPublicKey(&pk);
-
- if (rsa->n == NULL || rsa->e == NULL) {
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto out;
- }
-
- tosize = RSA_size(rsa);
- to = malloc(tosize);
- if (to == NULL) {
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto out;
- }
-
- 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,
- "RSA public decrypt failed: %d", retsize);
- free(to);
- goto out;
- }
- if (retsize > tosize)
- _hx509_abort("internal rsa decryption failure: ret > tosize");
-
- if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) {
-
- ret = decode_DigestInfo(to, retsize, &di, &size);
- free(to);
- if (ret) {
- goto out;
- }
-
- /* Check for extra data inside the sigature */
- if (size != 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)
- {
- 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 ||
- memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0))
- {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature");
- goto out;
- }
-
- ret = _hx509_verify_signature(context,
- NULL,
- &di.digestAlgorithm,
- data,
- &di.digest);
- } else {
- if (retsize != data->length ||
- memcmp(to, data->data, retsize) != 0)
- {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- hx509_set_error_string(context, 0, ret, "RSA Signature incorrect");
- goto out;
- }
- free(to);
- }
-
- out:
- free_DigestInfo(&di);
- RSA_free(rsa);
- return ret;
-}
-
-static int
-rsa_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;
- size_t size;
- int ret;
-
- if (alg)
- sig_oid = &alg->algorithm;
- else
- sig_oid = signer->signature_alg;
-
- if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha256WithRSAEncryption()) == 0) {
- digest_alg = hx509_signature_sha256();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha1WithRSAEncryption()) == 0) {
- digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
- digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
- digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_dsa_with_sha1()) == 0) {
- digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, 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) {
- digest_alg = NULL;
- } else
- return HX509_ALG_NOT_SUPP;
-
- if (signatureAlgorithm) {
- ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
- if (ret) {
- hx509_clear_error_string(context);
- return ret;
- }
- }
-
- if (digest_alg) {
- DigestInfo di;
- memset(&di, 0, sizeof(di));
-
- ret = _hx509_create_signature(context,
- NULL,
- digest_alg,
- data,
- &di.digestAlgorithm,
- &di.digest);
- if (ret)
- return ret;
- ASN1_MALLOC_ENCODE(DigestInfo,
- indata.data,
- indata.length,
- &di,
- &size,
- ret);
- free_DigestInfo(&di);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "out of memory");
- return ret;
- }
- if (indata.length != size)
- _hx509_abort("internal ASN.1 encoder error");
- } else {
- indata = *data;
- }
-
- sig->length = RSA_size(signer->private_key.rsa);
- sig->data = malloc(sig->length);
- if (sig->data == NULL) {
- der_free_octet_string(&indata);
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
-
- ret = RSA_private_encrypt(indata.length, indata.data,
- sig->data,
- signer->private_key.rsa,
- RSA_PKCS1_PADDING);
- if (indata.data != data->data)
- der_free_octet_string(&indata);
- if (ret <= 0) {
- ret = HX509_CMS_FAILED_CREATE_SIGATURE;
- hx509_set_error_string(context, 0, ret,
- "RSA private decrypt failed: %d", ret);
- return ret;
- }
- if (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 void *data,
- size_t len,
- hx509_private_key private_key)
-{
- 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 = oid_id_pkcs1_sha1WithRSAEncryption();
-
- return 0;
-}
-
-static int
-rsa_private_key2SPKI(hx509_context context,
- hx509_private_key private_key,
- SubjectPublicKeyInfo *spki)
-{
- int len, ret;
-
- memset(spki, 0, sizeof(*spki));
-
- len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
-
- spki->subjectPublicKey.data = malloc(len);
- if (spki->subjectPublicKey.data == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
- return ENOMEM;
- }
- spki->subjectPublicKey.length = len * 8;
-
- ret = set_digest_alg(&spki->algorithm,oid_id_pkcs1_rsaEncryption(),
- "\x05\x00", 2);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "malloc - out of memory");
- free(spki->subjectPublicKey.data);
- spki->subjectPublicKey.data = NULL;
- spki->subjectPublicKey.length = 0;
- return ret;
- }
-
- {
- unsigned char *pp = spki->subjectPublicKey.data;
- i2d_RSAPublicKey(private_key->private_key.rsa, &pp);
- }
-
- return 0;
-}
-
-static int
-rsa_generate_private_key(hx509_context context,
- struct hx509_generate_private_context *ctx,
- hx509_private_key private_key)
-{
- BIGNUM *e;
- int ret;
- unsigned long bits;
-
- static const int default_rsa_e = 65537;
- static const int default_rsa_bits = 1024;
-
- private_key->private_key.rsa = RSA_new();
- if (private_key->private_key.rsa == NULL) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Failed to generate RSA key");
- return HX509_PARSING_KEY_FAILED;
- }
-
- e = BN_new();
- BN_set_word(e, default_rsa_e);
-
- bits = default_rsa_bits;
-
- 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);
- if (ret != 1) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Failed to generate RSA key");
- return HX509_PARSING_KEY_FAILED;
- }
- private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
-
- return 0;
-}
-
-static int
-rsa_private_key_export(hx509_context context,
- const hx509_private_key key,
- heim_octet_string *data)
-{
- int ret;
-
- 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,
- "Private key is not exportable");
- 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);
- }
-
- return 0;
-}
-
-static BIGNUM *
-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);
- } else if (strcasecmp(type, "rsa-exponent") == 0) {
- return BN_dup(key->private_key.rsa->e);
- } else
- return NULL;
-}
-
-
-
-static hx509_private_key_ops rsa_private_key_ops = {
- "RSA PRIVATE KEY",
- oid_id_pkcs1_rsaEncryption,
- rsa_private_key2SPKI,
- rsa_private_key_export,
- rsa_private_key_import,
- rsa_generate_private_key,
- rsa_get_internal
-};
-
-
-/*
- *
- */
-
-static int
-dsa_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 SubjectPublicKeyInfo *spi;
- DSAPublicKey pk;
- DSAParams param;
- size_t size;
- DSA *dsa;
- int ret;
-
- spi = &signer->tbsCertificate.subjectPublicKeyInfo;
-
- dsa = DSA_new();
- if (dsa == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
-
- ret = decode_DSAPublicKey(spi->subjectPublicKey.data,
- spi->subjectPublicKey.length / 8,
- &pk, &size);
- if (ret)
- goto out;
-
- dsa->pub_key = heim_int2BN(&pk);
-
- free_DSAPublicKey(&pk);
-
- if (dsa->pub_key == NULL) {
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto out;
- }
-
- if (spi->algorithm.parameters == NULL) {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- hx509_set_error_string(context, 0, ret, "DSA parameters missing");
- goto out;
- }
-
- ret = decode_DSAParams(spi->algorithm.parameters->data,
- spi->algorithm.parameters->length,
- &param,
- &size);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode");
- goto out;
- }
-
- dsa->p = heim_int2BN(&param.p);
- dsa->q = heim_int2BN(&param.q);
- dsa->g = heim_int2BN(&param.g);
-
- free_DSAParams(&param);
-
- if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto out;
- }
-
- ret = DSA_verify(-1, data->data, data->length,
- (unsigned char*)sig->data, sig->length,
- dsa);
- if (ret == 1)
- ret = 0;
- else if (ret == 0 || ret == -1) {
- ret = HX509_CRYPTO_BAD_SIGNATURE;
- hx509_set_error_string(context, 0, ret, "BAD DSA sigature");
- } else {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature");
- }
-
- out:
- DSA_free(dsa);
-
- return ret;
-}
-
-#if 0
-static int
-dsa_parse_private_key(hx509_context context,
- const void *data,
- size_t len,
- hx509_private_key private_key)
-{
- const unsigned char *p = data;
-
- 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();
-
- return 0;
-/* else */
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "No support to parse DSA keys");
- return HX509_PARSING_KEY_FAILED;
-}
-#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,
- 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)
-{
- SHA256_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(SHA256_DIGEST_LENGTH);
- if (sig->data == NULL) {
- sig->length = 0;
- return ENOMEM;
- }
- sig->length = SHA256_DIGEST_LENGTH;
-
- 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,
- 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) {
- 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;
- }
-
- MD5_Init(&m);
- MD5_Update(&m, data->data, data->length);
- MD5_Final (digest, &m);
-
- if (memcmp(digest, sig->data, MD5_DIGEST_LENGTH) != 0) {
- hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE,
- "Bad MD5 sigature");
- 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;
- }
-
- 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;
- }
-
- return 0;
-}
-
-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,
- NULL,
- PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
- 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,
- NULL,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
- 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,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
- 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,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
- 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,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
- 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,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
- rsa_verify_signature,
- rsa_create_signature
-};
-
-static const struct signature_alg dsa_sha1_alg = {
- "dsa-with-sha1",
- oid_id_dsa_with_sha1,
- NULL,
- oid_id_dsa,
- oid_id_secsig_sha_1,
- PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
- dsa_verify_signature,
- /* create_signature */ NULL,
-};
-
-static const struct signature_alg sha256_alg = {
- "sha-256",
- oid_id_sha256,
- hx509_signature_sha256,
- NULL,
- NULL,
- SIG_DIGEST,
- sha256_verify_signature,
- sha256_create_signature
-};
-
-static const struct signature_alg sha1_alg = {
- "sha1",
- oid_id_secsig_sha_1,
- hx509_signature_sha1,
- NULL,
- NULL,
- SIG_DIGEST,
- sha1_verify_signature,
- sha1_create_signature
-};
-
-static const struct signature_alg md5_alg = {
- "rsa-md5",
- oid_id_rsa_digest_md5,
- hx509_signature_md5,
- NULL,
- NULL,
- SIG_DIGEST,
- md5_verify_signature
-};
-
-static const struct signature_alg md2_alg = {
- "rsa-md2",
- oid_id_rsa_digest_md2,
- hx509_signature_md2,
- NULL,
- NULL,
- SIG_DIGEST,
- md2_verify_signature
-};
-
-/*
- * Order matter in this structure, "best" first for each "key
- * compatible" type (type is RSA, DSA, none, etc)
- */
-
-static const struct signature_alg *sig_algs[] = {
- &rsa_with_sha256_alg,
- &rsa_with_sha1_alg,
- &pkcs1_rsa_sha1_alg,
- &rsa_with_md5_alg,
- &rsa_with_md2_alg,
- &heim_rsa_pkcs1_x509,
- &dsa_sha1_alg,
- &sha256_alg,
- &sha1_alg,
- &md5_alg,
- &md2_alg,
- NULL
-};
-
-static const struct signature_alg *
-find_sig_alg(const heim_oid *oid)
-{
- int i;
- for (i = 0; sig_algs[i]; i++)
- if (der_heim_oid_cmp((*sig_algs[i]->sig_oid)(), oid) == 0)
- return sig_algs[i];
- return NULL;
-}
-
-/*
- *
- */
-
-static struct hx509_private_key_ops *private_algs[] = {
- &rsa_private_key_ops,
- NULL
-};
-
-static hx509_private_key_ops *
-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)
- return private_algs[i];
- }
- return NULL;
-}
-
-
-int
-_hx509_verify_signature(hx509_context context,
- const Certificate *signer,
- const AlgorithmIdentifier *alg,
- const heim_octet_string *data,
- const heim_octet_string *sig)
-{
- 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 (signer && (md->flags & PROVIDE_CONF) == 0) {
- hx509_clear_error_string(context);
- return HX509_CRYPTO_SIG_NO_CONF;
- }
- if (signer == NULL && (md->flags & REQUIRE_SIGNER)) {
- hx509_clear_error_string(context);
- return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER;
- }
- if (md->key_oid && signer) {
- const SubjectPublicKeyInfo *spi;
- spi = &signer->tbsCertificate.subjectPublicKeyInfo;
-
- 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;
- }
- }
- return (*md->verify_signature)(context, md, signer, alg, data, sig);
-}
-
-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,
- const heim_octet_string *data,
- AlgorithmIdentifier *signatureAlgorithm,
- heim_octet_string *sig)
-{
- 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,
- "algorithm no supported");
- return HX509_SIG_ALG_NO_SUPPORTED;
- }
-
- if (signer && (md->flags & PROVIDE_CONF) == 0) {
- hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
- "algorithm provides no conf");
- return HX509_CRYPTO_SIG_NO_CONF;
- }
-
- return (*md->create_signature)(context, md, signer, alg, data,
- signatureAlgorithm, sig);
-}
-
-int
-_hx509_create_signature_bitstring(hx509_context context,
- const hx509_private_key signer,
- const AlgorithmIdentifier *alg,
- const heim_octet_string *data,
- AlgorithmIdentifier *signatureAlgorithm,
- heim_bit_string *sig)
-{
- heim_octet_string os;
- int ret;
-
- ret = _hx509_create_signature(context, signer, alg,
- data, signatureAlgorithm, &os);
- if (ret)
- return ret;
- sig->data = os.data;
- sig->length = os.length * 8;
- return 0;
-}
-
-int
-_hx509_public_encrypt(hx509_context context,
- const heim_octet_string *cleartext,
- const Certificate *cert,
- heim_oid *encryption_oid,
- heim_octet_string *ciphertext)
-{
- const SubjectPublicKeyInfo *spi;
- unsigned char *to;
- int tosize;
- int ret;
- RSA *rsa;
- RSAPublicKey pk;
- size_t size;
-
- 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;
- }
-
- 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);
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
-
- tosize = RSA_size(rsa);
- to = malloc(tosize);
- if (to == NULL) {
- RSA_free(rsa);
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
-
- ret = RSA_public_encrypt(cleartext->length,
- (unsigned char *)cleartext->data,
- to, rsa, RSA_PKCS1_PADDING);
- RSA_free(rsa);
- if (ret <= 0) {
- free(to);
- hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT,
- "RSA public encrypt failed with %d", ret);
- return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT;
- }
- if (ret > tosize)
- _hx509_abort("internal rsa decryption failure: ret > tosize");
-
- ciphertext->length = ret;
- ciphertext->data = to;
-
- ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(), encryption_oid);
- if (ret) {
- der_free_octet_string(ciphertext);
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
-
- return 0;
-}
-
-int
-_hx509_private_key_private_decrypt(hx509_context context,
- const heim_octet_string *ciphertext,
- const heim_oid *encryption_oid,
- hx509_private_key p,
- heim_octet_string *cleartext)
-{
- int ret;
-
- cleartext->data = NULL;
- cleartext->length = 0;
-
- if (p->private_key.rsa == NULL) {
- hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
- "Private RSA key missing");
- return HX509_PRIVATE_KEY_MISSING;
- }
-
- cleartext->length = RSA_size(p->private_key.rsa);
- cleartext->data = malloc(cleartext->length);
- if (cleartext->data == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
- ret = RSA_private_decrypt(ciphertext->length, ciphertext->data,
- cleartext->data,
- p->private_key.rsa,
- RSA_PKCS1_PADDING);
- if (ret <= 0) {
- der_free_octet_string(cleartext);
- hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT,
- "Failed to decrypt using private key: %d", ret);
- return HX509_CRYPTO_RSA_PRIVATE_DECRYPT;
- }
- if (cleartext->length < ret)
- _hx509_abort("internal rsa decryption failure: ret > tosize");
-
- cleartext->length = ret;
-
- return 0;
-}
-
-
-int
-_hx509_parse_private_key(hx509_context context,
- const heim_oid *key_oid,
- const void *data,
- size_t len,
- hx509_private_key *private_key)
-{
- struct hx509_private_key_ops *ops;
- int ret;
-
- *private_key = NULL;
-
- ops = find_private_alg(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);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "out of memory");
- return ret;
- }
-
- ret = (*ops->import)(context, data, len, *private_key);
- if (ret)
- _hx509_private_key_free(private_key);
-
- return ret;
-}
-
-/*
- *
- */
-
-int
-_hx509_private_key2SPKI(hx509_context context,
- hx509_private_key private_key,
- SubjectPublicKeyInfo *spki)
-{
- const struct hx509_private_key_ops *ops = private_key->ops;
- if (ops == NULL || ops->get_spki == NULL) {
- hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
- "Private key have no key2SPKI function");
- return HX509_UNIMPLEMENTED_OPERATION;
- }
- return (*ops->get_spki)(context, private_key, spki);
-}
-
-int
-_hx509_generate_private_key_init(hx509_context context,
- const heim_oid *oid,
- struct hx509_generate_private_context **ctx)
-{
- *ctx = NULL;
-
- if (der_heim_oid_cmp(oid, oid_id_pkcs1_rsaEncryption()) != 0) {
- hx509_set_error_string(context, 0, EINVAL,
- "private key not an RSA key");
- return EINVAL;
- }
-
- *ctx = calloc(1, sizeof(**ctx));
- if (*ctx == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
- (*ctx)->key_oid = oid;
-
- return 0;
-}
-
-int
-_hx509_generate_private_key_is_ca(hx509_context context,
- struct hx509_generate_private_context *ctx)
-{
- ctx->isCA = 1;
- return 0;
-}
-
-int
-_hx509_generate_private_key_bits(hx509_context context,
- struct hx509_generate_private_context *ctx,
- unsigned long bits)
-{
- ctx->num_bits = bits;
- return 0;
-}
-
-
-void
-_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)
-{
- free(*ctx);
- *ctx = NULL;
-}
-
-int
-_hx509_generate_private_key(hx509_context context,
- struct hx509_generate_private_context *ctx,
- hx509_private_key *private_key)
-{
- struct hx509_private_key_ops *ops;
- int ret;
-
- *private_key = NULL;
-
- ops = 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);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "out of memory");
- return ret;
- }
-
- ret = (*ops->generate_private_key)(context, ctx, *private_key);
- if (ret)
- _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; }
-
-const AlgorithmIdentifier *
-hx509_signature_sha384(void)
-{ return &_hx509_signature_sha384_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_sha256(void)
-{ return &_hx509_signature_sha256_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_sha1(void)
-{ return &_hx509_signature_sha1_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_md5(void)
-{ return &_hx509_signature_md5_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_md2(void)
-{ return &_hx509_signature_md2_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_rsa_with_sha512(void)
-{ return &_hx509_signature_rsa_with_sha512_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_rsa_with_sha384(void)
-{ return &_hx509_signature_rsa_with_sha384_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_rsa_with_sha256(void)
-{ return &_hx509_signature_rsa_with_sha256_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_rsa_with_sha1(void)
-{ return &_hx509_signature_rsa_with_sha1_data; }
-
-const AlgorithmIdentifier *
-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; }
-
-const AlgorithmIdentifier *
-hx509_signature_rsa_pkcs1_x509(void)
-{ return &_hx509_signature_rsa_pkcs1_x509_data; }
-
-const AlgorithmIdentifier *
-hx509_crypto_des_rsdi_ede3_cbc(void)
-{ return &_hx509_des_rsdi_ede3_cbc_oid; }
-
-const AlgorithmIdentifier *
-hx509_crypto_aes128_cbc(void)
-{ return &_hx509_crypto_aes128_cbc_data; }
-
-const AlgorithmIdentifier *
-hx509_crypto_aes256_cbc(void)
-{ return &_hx509_crypto_aes256_cbc_data; }
-
-/*
- *
- */
-
-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 =
- &_hx509_crypto_aes128_cbc_data;
-
-/*
- *
- */
-
-int
-_hx509_private_key_init(hx509_private_key *key,
- hx509_private_key_ops *ops,
- void *keydata)
-{
- *key = calloc(1, sizeof(**key));
- if (*key == NULL)
- return ENOMEM;
- (*key)->ref = 1;
- (*key)->ops = ops;
- (*key)->private_key.keydata = keydata;
- return 0;
-}
-
-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");
- return key;
-}
-
-const char *
-_hx509_private_pem_name(hx509_private_key key)
-{
- return key->ops->pemtype;
-}
-
-int
-_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)
- return 0;
-
- if ((*key)->private_key.rsa)
- RSA_free((*key)->private_key.rsa);
- (*key)->private_key.rsa = NULL;
- free(*key);
- *key = NULL;
- return 0;
-}
-
-void
-_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->md = &pkcs1_rsa_sha1_alg;
-}
-
-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);
- if (ret)
- hx509_set_error_string(context, 0, ret, "malloc out of memory");
- return ret;
-}
-
-int
-_hx509_private_key_exportable(hx509_private_key key)
-{
- if (key->ops->export == NULL)
- return 0;
- return 1;
-}
-
-BIGNUM *
-_hx509_private_key_get_internal(hx509_context context,
- hx509_private_key key,
- const char *type)
-{
- if (key->ops->get_internal == NULL)
- return NULL;
- return (*key->ops->get_internal)(context, key, type);
-}
-
-int
-_hx509_private_key_export(hx509_context context,
- const hx509_private_key key,
- 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);
-}
-
-/*
- *
- */
-
-struct hx509cipher {
- const char *name;
- const heim_oid *(*oid_func)(void);
- 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 *,
- hx509_crypto, heim_octet_string *);
-};
-
-struct hx509_crypto_data {
- char *name;
- const struct hx509cipher *cipher;
- const EVP_CIPHER *c;
- heim_octet_string key;
- heim_oid oid;
- void *param;
-};
-
-/*
- *
- */
-
-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 int
-CMSCBCParam_get(hx509_context context, const hx509_crypto crypto,
- const heim_octet_string *ivec, heim_octet_string *param)
-{
- size_t size;
- int ret;
-
- assert(crypto->param == NULL);
- if (ivec == NULL)
- return 0;
-
- ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length,
- ivec, &size, ret);
- if (ret == 0 && size != param->length)
- _hx509_abort("Internal asn1 encoder failure");
- if (ret)
- hx509_clear_error_string(context);
- return ret;
-}
-
-static int
-CMSCBCParam_set(hx509_context context, const heim_octet_string *param,
- hx509_crypto crypto, heim_octet_string *ivec)
-{
- int ret;
- if (ivec == NULL)
- return 0;
-
- ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL);
- if (ret)
- hx509_clear_error_string(context);
-
- return ret;
-}
-
-struct _RC2_params {
- int maximum_effective_key;
-};
-
-static int
-CMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto,
- const heim_octet_string *ivec, heim_octet_string *param)
-{
- CMSRC2CBCParameter rc2params;
- const struct _RC2_params *p = crypto->param;
- int maximum_effective_key = 128;
- size_t size;
- int ret;
-
- memset(&rc2params, 0, sizeof(rc2params));
-
- if (p)
- maximum_effective_key = p->maximum_effective_key;
-
- switch(maximum_effective_key) {
- case 40:
- rc2params.rc2ParameterVersion = 160;
- break;
- case 64:
- rc2params.rc2ParameterVersion = 120;
- break;
- case 128:
- rc2params.rc2ParameterVersion = 58;
- break;
- }
- rc2params.iv = *ivec;
-
- ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length,
- &rc2params, &size, ret);
- if (ret == 0 && size != param->length)
- _hx509_abort("Internal asn1 encoder failure");
-
- return ret;
-}
-
-static int
-CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
- hx509_crypto crypto, heim_octet_string *ivec)
-{
- CMSRC2CBCParameter rc2param;
- struct _RC2_params *p;
- size_t size;
- int ret;
-
- ret = decode_CMSRC2CBCParameter(param->data, param->length,
- &rc2param, &size);
- if (ret) {
- hx509_clear_error_string(context);
- return ret;
- }
-
- p = calloc(1, sizeof(*p));
- if (p == NULL) {
- free_CMSRC2CBCParameter(&rc2param);
- hx509_clear_error_string(context);
- return ENOMEM;
- }
- switch(rc2param.rc2ParameterVersion) {
- case 160:
- crypto->c = EVP_rc2_40_cbc();
- p->maximum_effective_key = 40;
- break;
- case 120:
- crypto->c = EVP_rc2_64_cbc();
- p->maximum_effective_key = 64;
- break;
- case 58:
- crypto->c = EVP_rc2_cbc();
- p->maximum_effective_key = 128;
- break;
- default:
- free(p);
- free_CMSRC2CBCParameter(&rc2param);
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
- }
- if (ivec)
- ret = der_copy_octet_string(&rc2param.iv, ivec);
- free_CMSRC2CBCParameter(&rc2param);
- if (ret) {
- free(p);
- hx509_clear_error_string(context);
- } else
- crypto->param = p;
-
- return ret;
-}
-
-/*
- *
- */
-
-static const struct hx509cipher ciphers[] = {
- {
- "rc2-cbc",
- oid_id_pkcs3_rc2_cbc,
- NULL,
- EVP_rc2_cbc,
- CMSRC2CBCParam_get,
- CMSRC2CBCParam_set
- },
- {
- "rc2-cbc",
- oid_id_rsadsi_rc2_cbc,
- NULL,
- EVP_rc2_cbc,
- CMSRC2CBCParam_get,
- CMSRC2CBCParam_set
- },
- {
- "rc2-40-cbc",
- oid_private_rc2_40,
- NULL,
- EVP_rc2_40_cbc,
- CMSRC2CBCParam_get,
- CMSRC2CBCParam_set
- },
- {
- "des-ede3-cbc",
- oid_id_pkcs3_des_ede3_cbc,
- NULL,
- EVP_des_ede3_cbc,
- CMSCBCParam_get,
- CMSCBCParam_set
- },
- {
- "des-ede3-cbc",
- oid_id_rsadsi_des_ede3_cbc,
- hx509_crypto_des_rsdi_ede3_cbc,
- EVP_des_ede3_cbc,
- CMSCBCParam_get,
- CMSCBCParam_set
- },
- {
- "aes-128-cbc",
- oid_id_aes_128_cbc,
- hx509_crypto_aes128_cbc,
- EVP_aes_128_cbc,
- CMSCBCParam_get,
- CMSCBCParam_set
- },
- {
- "aes-192-cbc",
- oid_id_aes_192_cbc,
- NULL,
- EVP_aes_192_cbc,
- CMSCBCParam_get,
- CMSCBCParam_set
- },
- {
- "aes-256-cbc",
- oid_id_aes_256_cbc,
- hx509_crypto_aes256_cbc,
- EVP_aes_256_cbc,
- CMSCBCParam_get,
- CMSCBCParam_set
- }
-};
-
-static const struct hx509cipher *
-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)
- return &ciphers[i];
-
- return NULL;
-}
-
-static const struct hx509cipher *
-find_cipher_by_name(const char *name)
-{
- int i;
-
- for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
- if (strcasecmp(name, ciphers[i].name) == 0)
- return &ciphers[i];
-
- return NULL;
-}
-
-
-const heim_oid *
-hx509_crypto_enctype_by_name(const char *name)
-{
- const struct hx509cipher *cipher;
-
- cipher = find_cipher_by_name(name);
- if (cipher == NULL)
- return NULL;
- return (*cipher->oid_func)();
-}
-
-int
-hx509_crypto_init(hx509_context context,
- const char *provider,
- const heim_oid *enctype,
- hx509_crypto *crypto)
-{
- const struct hx509cipher *cipher;
-
- *crypto = NULL;
-
- cipher = find_cipher_by_oid(enctype);
- if (cipher == NULL) {
- hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
- "Algorithm not supported");
- return HX509_ALG_NOT_SUPP;
- }
-
- *crypto = calloc(1, sizeof(**crypto));
- if (*crypto == NULL) {
- hx509_clear_error_string(context);
- return ENOMEM;
- }
-
- (*crypto)->cipher = cipher;
- (*crypto)->c = (*cipher->evp_func)();
-
- if (der_copy_oid(enctype, &(*crypto)->oid)) {
- hx509_crypto_destroy(*crypto);
- *crypto = NULL;
- hx509_clear_error_string(context);
- return ENOMEM;
- }
-
- return 0;
-}
-
-const char *
-hx509_crypto_provider(hx509_crypto crypto)
-{
- return "unknown";
-}
-
-void
-hx509_crypto_destroy(hx509_crypto crypto)
-{
- if (crypto->name)
- free(crypto->name);
- if (crypto->key.data)
- free(crypto->key.data);
- if (crypto->param)
- free(crypto->param);
- der_free_oid(&crypto->oid);
- memset(crypto, 0, sizeof(*crypto));
- free(crypto);
-}
-
-int
-hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
-{
- return 0;
-}
-
-int
-hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
-{
- if (EVP_CIPHER_key_length(crypto->c) > length)
- return HX509_CRYPTO_INTERNAL_ERROR;
-
- if (crypto->key.data) {
- free(crypto->key.data);
- crypto->key.data = NULL;
- crypto->key.length = 0;
- }
- crypto->key.data = malloc(length);
- if (crypto->key.data == NULL)
- return ENOMEM;
- memcpy(crypto->key.data, data, length);
- crypto->key.length = length;
-
- return 0;
-}
-
-int
-hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key)
-{
- if (crypto->key.data) {
- free(crypto->key.data);
- crypto->key.length = 0;
- }
-
- crypto->key.length = EVP_CIPHER_key_length(crypto->c);
- crypto->key.data = malloc(crypto->key.length);
- if (crypto->key.data == NULL) {
- crypto->key.length = 0;
- return ENOMEM;
- }
- if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) {
- free(crypto->key.data);
- crypto->key.data = NULL;
- crypto->key.length = 0;
- return HX509_CRYPTO_INTERNAL_ERROR;
- }
- if (key)
- return der_copy_octet_string(&crypto->key, key);
- else
- return 0;
-}
-
-int
-hx509_crypto_set_params(hx509_context context,
- hx509_crypto crypto,
- const heim_octet_string *param,
- heim_octet_string *ivec)
-{
- return (*crypto->cipher->set_params)(context, param, crypto, ivec);
-}
-
-int
-hx509_crypto_get_params(hx509_context context,
- hx509_crypto crypto,
- const heim_octet_string *ivec,
- heim_octet_string *param)
-{
- return (*crypto->cipher->get_params)(context, crypto, ivec, param);
-}
-
-int
-hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
-{
- ivec->length = EVP_CIPHER_iv_length(crypto->c);
- ivec->data = malloc(ivec->length);
- if (ivec->data == NULL) {
- ivec->length = 0;
- return ENOMEM;
- }
-
- if (RAND_bytes(ivec->data, ivec->length) <= 0) {
- free(ivec->data);
- ivec->data = NULL;
- ivec->length = 0;
- return HX509_CRYPTO_INTERNAL_ERROR;
- }
- return 0;
-}
-
-int
-hx509_crypto_encrypt(hx509_crypto crypto,
- const void *data,
- const size_t length,
- const heim_octet_string *ivec,
- heim_octet_string **ciphertext)
-{
- EVP_CIPHER_CTX evp;
- size_t padsize;
- int ret;
-
- *ciphertext = NULL;
-
- assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
-
- EVP_CIPHER_CTX_init(&evp);
-
- ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
- crypto->key.data, ivec->data, 1);
- if (ret != 1) {
- EVP_CIPHER_CTX_cleanup(&evp);
- ret = HX509_CRYPTO_INTERNAL_ERROR;
- goto out;
- }
-
- *ciphertext = calloc(1, sizeof(**ciphertext));
- if (*ciphertext == NULL) {
- 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);
- }
- (*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;
- unsigned char *p = (*ciphertext)->data;
- p += length;
- for (i = 0; i < padsize; i++)
- *p++ = padsize;
- }
-
- ret = EVP_Cipher(&evp, (*ciphertext)->data,
- (*ciphertext)->data,
- length + padsize);
- if (ret != 1) {
- ret = HX509_CRYPTO_INTERNAL_ERROR;
- goto out;
- }
- ret = 0;
-
- out:
- if (ret) {
- if (*ciphertext) {
- if ((*ciphertext)->data) {
- free((*ciphertext)->data);
- }
- free(*ciphertext);
- *ciphertext = NULL;
- }
- }
- EVP_CIPHER_CTX_cleanup(&evp);
-
- return ret;
-}
-
-int
-hx509_crypto_decrypt(hx509_crypto crypto,
- const void *data,
- const size_t length,
- heim_octet_string *ivec,
- heim_octet_string *clear)
-{
- EVP_CIPHER_CTX evp;
- void *idata = NULL;
- int ret;
-
- clear->data = NULL;
- clear->length = 0;
-
- if (ivec && EVP_CIPHER_iv_length(crypto->c) < ivec->length)
- return HX509_CRYPTO_INTERNAL_ERROR;
-
- if (crypto->key.data == NULL)
- return HX509_CRYPTO_INTERNAL_ERROR;
-
- if (ivec)
- idata = ivec->data;
-
- EVP_CIPHER_CTX_init(&evp);
-
- ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
- crypto->key.data, idata, 0);
- if (ret != 1) {
- EVP_CIPHER_CTX_cleanup(&evp);
- return HX509_CRYPTO_INTERNAL_ERROR;
- }
-
- clear->length = length;
- clear->data = malloc(length);
- if (clear->data == NULL) {
- EVP_CIPHER_CTX_cleanup(&evp);
- clear->length = 0;
- return ENOMEM;
- }
-
- if (EVP_Cipher(&evp, clear->data, data, length) != 1) {
- return HX509_CRYPTO_INTERNAL_ERROR;
- }
- EVP_CIPHER_CTX_cleanup(&evp);
-
- if (EVP_CIPHER_block_size(crypto->c) > 1) {
- int padsize;
- unsigned char *p;
- int j, bsize = EVP_CIPHER_block_size(crypto->c);
-
- if (clear->length < bsize) {
- ret = HX509_CMS_PADDING_ERROR;
- goto out;
- }
-
- p = clear->data;
- p += clear->length - 1;
- padsize = *p;
- if (padsize > bsize) {
- ret = HX509_CMS_PADDING_ERROR;
- goto out;
- }
- clear->length -= padsize;
- for (j = 0; j < padsize; j++) {
- if (*p-- != padsize) {
- ret = HX509_CMS_PADDING_ERROR;
- goto out;
- }
- }
- }
-
- return 0;
-
- out:
- if (clear->data)
- free(clear->data);
- clear->data = NULL;
- clear->length = 0;
- return ret;
-}
-
-typedef int (*PBE_string2key_func)(hx509_context,
- const char *,
- const heim_octet_string *,
- hx509_crypto *, heim_octet_string *,
- heim_octet_string *,
- const heim_oid *, const EVP_MD *);
-
-static int
-PBE_string2key(hx509_context context,
- const char *password,
- const heim_octet_string *parameters,
- hx509_crypto *crypto,
- heim_octet_string *key, heim_octet_string *iv,
- const heim_oid *enc_oid,
- const EVP_MD *md)
-{
- PKCS12_PBEParams p12params;
- int passwordlen;
- hx509_crypto c;
- int iter, saltlen, ret;
- unsigned char *salt;
-
- passwordlen = password ? strlen(password) : 0;
-
- if (parameters == NULL)
- return HX509_ALG_NOT_SUPP;
-
- ret = decode_PKCS12_PBEParams(parameters->data,
- parameters->length,
- &p12params, NULL);
- if (ret)
- goto out;
-
- if (p12params.iterations)
- iter = *p12params.iterations;
- else
- iter = 1;
- salt = p12params.salt.data;
- saltlen = p12params.salt.length;
-
- 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,
- PKCS12_IV_ID, iter, iv->length, iv->data, md)) {
- ret = HX509_CRYPTO_INTERNAL_ERROR;
- goto out;
- }
-
- ret = hx509_crypto_init(context, NULL, enc_oid, &c);
- if (ret)
- goto out;
-
- ret = hx509_crypto_set_key_data(c, key->data, key->length);
- if (ret) {
- hx509_crypto_destroy(c);
- goto out;
- }
-
- *crypto = c;
-out:
- free_PKCS12_PBEParams(&p12params);
- return ret;
-}
-
-static const heim_oid *
-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) {
- *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) {
- *c = EVP_rc2_cbc();
- *md = EVP_sha1();
- *s2k = PBE_string2key;
- return oid_id_pkcs3_rc2_cbc();
-#if 0
- } else if (der_heim_oid_cmp(oid, 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) {
- *c = EVP_rc4();
- *md = EVP_sha1();
- *s2k = PBE_string2key;
- return oid_id_pkcs3_rc4();
-#endif
- } else if (der_heim_oid_cmp(oid, 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 NULL;
-}
-
-/*
- *
- */
-
-int
-_hx509_pbe_encrypt(hx509_context context,
- hx509_lock lock,
- const AlgorithmIdentifier *ai,
- const heim_octet_string *content,
- heim_octet_string *econtent)
-{
- hx509_clear_error_string(context);
- return EINVAL;
-}
-
-/*
- *
- */
-
-int
-_hx509_pbe_decrypt(hx509_context context,
- hx509_lock lock,
- const AlgorithmIdentifier *ai,
- const heim_octet_string *econtent,
- heim_octet_string *content)
-{
- const struct _hx509_password *pw;
- heim_octet_string key, iv;
- const heim_oid *enc_oid;
- const EVP_CIPHER *c;
- const EVP_MD *md;
- PBE_string2key_func s2k;
- int i, ret = 0;
-
- memset(&key, 0, sizeof(key));
- memset(&iv, 0, sizeof(iv));
-
- memset(content, 0, sizeof(*content));
-
- enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k);
- if (enc_oid == NULL) {
- hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
- "String to key algorithm not supported");
- ret = HX509_ALG_NOT_SUPP;
- goto out;
- }
-
- key.length = EVP_CIPHER_key_length(c);
- key.data = malloc(key.length);
- if (key.data == NULL) {
- ret = ENOMEM;
- hx509_clear_error_string(context);
- goto out;
- }
-
- iv.length = EVP_CIPHER_iv_length(c);
- iv.data = malloc(iv.length);
- if (iv.data == NULL) {
- ret = ENOMEM;
- hx509_clear_error_string(context);
- goto out;
- }
-
- pw = _hx509_lock_get_passwords(lock);
-
- ret = HX509_CRYPTO_INTERNAL_ERROR;
- for (i = 0; i < pw->len + 1; i++) {
- hx509_crypto crypto;
- const char *password;
-
- if (i < pw->len)
- password = pw->val[i];
- else if (i < pw->len + 1)
- password = "";
- else
- password = NULL;
-
- ret = (*s2k)(context, password, ai->parameters, &crypto,
- &key, &iv, enc_oid, md);
- if (ret)
- goto out;
-
- ret = hx509_crypto_decrypt(crypto,
- econtent->data,
- econtent->length,
- &iv,
- content);
- hx509_crypto_destroy(crypto);
- if (ret == 0)
- goto out;
-
- }
-out:
- if (key.data)
- der_free_octet_string(&key);
- if (iv.data)
- der_free_octet_string(&iv);
- return ret;
-}
-
-/*
- *
- */
-
-
-int
-_hx509_match_keys(hx509_cert c, hx509_private_key private_key)
-{
- const Certificate *cert;
- const SubjectPublicKeyInfo *spi;
- RSAPublicKey pk;
- RSA *rsa;
- size_t size;
- int ret;
-
- if (private_key->private_key.rsa == NULL)
- return 0;
-
- rsa = private_key->private_key.rsa;
- if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL)
- return 0;
-
- cert = _hx509_get_cert(c);
- spi = &cert->tbsCertificate.subjectPublicKeyInfo;
-
- rsa = RSA_new();
- if (rsa == NULL)
- return 0;
-
- ret = decode_RSAPublicKey(spi->subjectPublicKey.data,
- spi->subjectPublicKey.length / 8,
- &pk, &size);
- if (ret) {
- RSA_free(rsa);
- return 0;
- }
- rsa->n = heim_int2BN(&pk.modulus);
- rsa->e = heim_int2BN(&pk.publicExponent);
-
- free_RSAPublicKey(&pk);
-
- rsa->d = BN_dup(private_key->private_key.rsa->d);
- rsa->p = BN_dup(private_key->private_key.rsa->p);
- rsa->q = BN_dup(private_key->private_key.rsa->q);
- rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
- 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 ||
- rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
- rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
- RSA_free(rsa);
- return 0;
- }
-
- ret = RSA_check_key(rsa);
- RSA_free(rsa);
-
- return ret == 1;
-}
-
-static const heim_oid *
-find_keytype(const hx509_private_key key)
-{
- const struct signature_alg *md;
-
- if (key == NULL)
- return NULL;
-
- md = find_sig_alg(key->signature_alg);
- if (md == NULL)
- return NULL;
- return (*md->key_oid)();
-}
-
-
-int
-hx509_crypto_select(const hx509_context context,
- int type,
- const hx509_private_key source,
- hx509_peer_info peer,
- AlgorithmIdentifier *selected)
-{
- const AlgorithmIdentifier *def;
- size_t i, j;
- int ret, bits;
-
- memset(selected, 0, sizeof(*selected));
-
- if (type == HX509_SELECT_DIGEST) {
- bits = SIG_DIGEST;
- 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;
- } else if (type == HX509_SELECT_SECRET_ENC) {
- bits = SIG_SECRET;
- def = _hx509_crypto_default_secret_alg;
- } else {
- hx509_set_error_string(context, 0, EINVAL,
- "Unknown type %d of selection", type);
- return EINVAL;
- }
-
- if (peer) {
- const heim_oid *keytype = NULL;
-
- keytype = find_keytype(source);
-
- for (i = 0; i < peer->len; i++) {
- 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)(),
- &peer->val[i].algorithm) != 0)
- continue;
- if (keytype && sig_algs[j]->key_oid &&
- der_heim_oid_cmp(keytype, (*sig_algs[j]->key_oid)()))
- continue;
-
- /* found one, use that */
- ret = copy_AlgorithmIdentifier(&peer->val[i], selected);
- if (ret)
- hx509_clear_error_string(context);
- return ret;
- }
- if (bits & SIG_SECRET) {
- const struct hx509cipher *cipher;
-
- cipher = find_cipher_by_oid(&peer->val[i].algorithm);
- if (cipher == NULL)
- continue;
- if (cipher->ai_func == NULL)
- continue;
- ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);
- if (ret)
- hx509_clear_error_string(context);
- return ret;
- }
- }
- }
-
- /* use default */
- ret = copy_AlgorithmIdentifier(def, selected);
- if (ret)
- hx509_clear_error_string(context);
- return ret;
-}
-
-int
-hx509_crypto_available(hx509_context context,
- int type,
- hx509_cert source,
- AlgorithmIdentifier **val,
- unsigned int *plen)
-{
- const heim_oid *keytype = NULL;
- unsigned int len, i;
- void *ptr;
- int bits, ret;
-
- *val = NULL;
-
- if (type == HX509_SELECT_ALL) {
- bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;
- } else if (type == HX509_SELECT_DIGEST) {
- bits = SIG_DIGEST;
- } else if (type == HX509_SELECT_PUBLIC_SIG) {
- bits = SIG_PUBLIC_SIG;
- } else {
- hx509_set_error_string(context, 0, EINVAL,
- "Unknown type %d of available", type);
- return EINVAL;
- }
-
- if (source)
- keytype = find_keytype(_hx509_cert_private_key(source));
-
- len = 0;
- for (i = 0; sig_algs[i]; i++) {
- if ((sig_algs[i]->flags & bits) == 0)
- 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))
- continue;
-
- /* found one, add that to the list */
- ptr = realloc(*val, sizeof(**val) * (len + 1));
- if (ptr == NULL)
- goto out;
- *val = ptr;
-
- ret = copy_AlgorithmIdentifier((*sig_algs[i]->sig_alg)(), &(*val)[len]);
- if (ret)
- goto out;
- len++;
- }
-
- /* Add AES */
- if (bits & SIG_SECRET) {
-
- for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
-
- if (ciphers[i].ai_func == NULL)
- continue;
-
- ptr = realloc(*val, sizeof(**val) * (len + 1));
- if (ptr == NULL)
- goto out;
- *val = ptr;
-
- ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);
- if (ret)
- goto out;
- len++;
- }
- }
-
- *plen = len;
- return 0;
-
-out:
- for (i = 0; i < len; i++)
- free_AlgorithmIdentifier(&(*val)[i]);
- free(*val);
- *val = NULL;
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
-}
-
-void
-hx509_crypto_free_algs(AlgorithmIdentifier *val,
- unsigned int len)
-{
- unsigned int i;
- for (i = 0; i < len; i++)
- free_AlgorithmIdentifier(&val[i]);
- free(val);
-}
OpenPOWER on IntegriCloud