📄 crypto.c
字号:
/* * Copyright (c) 2004 - 2007 Kungliga Tekniska H鰃skolan * (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 intset_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 intrsa_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 intrsa_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 intrsa_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 intrsa_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 intrsa_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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -