📄 crypto.c
字号:
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;}inthx509_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);}inthx509_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);}inthx509_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;}inthx509_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;}inthx509_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 intPBE_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)();}inthx509_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -