📄 cms.c
字号:
ret = hx509_crypto_set_key_data(crypto, key.data, key.length); if (ret) { hx509_crypto_destroy(crypto); hx509_set_error_string(context, 0, ret, "Failed to set key for decryption " "of EnvelopedData"); goto out; } ret = hx509_crypto_decrypt(crypto, enccontent->data, enccontent->length, ivec.length ? &ivec : NULL, content); hx509_crypto_destroy(crypto); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decrypt EnvelopedData"); goto out; } }out: free_EnvelopedData(&ed); der_free_octet_string(&key); if (ivec.length) der_free_octet_string(&ivec); if (ret) { der_free_oid(contentType); der_free_octet_string(content); } return ret;}/** * Encrypt end encode EnvelopedData. * * Encrypt and encode EnvelopedData. The data is encrypted with a * random key and the the random key is encrypted with the * certificates private key. This limits what private key type can be * used to RSA. * * @param context A hx509 context. * @param flags flags to control the behavior, no flags today * @param cert Certificate to encrypt the EnvelopedData encryption key * with. * @param data pointer the data to encrypt. * @param length length of the data that data point to. * @param encryption_type Encryption cipher to use for the bulk data, * use NULL to get default. * @param contentType type of the data that is encrypted * @param content the output of the function, * free with der_free_octet_string(). * * @ingroup hx509_cms */inthx509_cms_envelope_1(hx509_context context, int flags, hx509_cert cert, const void *data, size_t length, const heim_oid *encryption_type, const heim_oid *contentType, heim_octet_string *content){ KeyTransRecipientInfo *ri; heim_octet_string ivec; heim_octet_string key; hx509_crypto crypto = NULL; EnvelopedData ed; size_t size; int ret; memset(&ivec, 0, sizeof(ivec)); memset(&key, 0, sizeof(key)); memset(&ed, 0, sizeof(ed)); memset(content, 0, sizeof(*content)); if (encryption_type == NULL) encryption_type = oid_id_aes_256_cbc(); ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); if (ret) goto out; ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); if (ret) goto out; ret = hx509_crypto_set_random_key(crypto, &key); if (ret) { hx509_set_error_string(context, 0, ret, "Create random key for EnvelopedData content"); goto out; } ret = hx509_crypto_random_iv(crypto, &ivec); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to create a random iv"); goto out; } ret = hx509_crypto_encrypt(crypto, data, length, &ivec, &ed.encryptedContentInfo.encryptedContent); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encrypt EnvelopedData content"); goto out; } { AlgorithmIdentifier *enc_alg; enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm; ret = der_copy_oid(encryption_type, &enc_alg->algorithm); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set crypto oid " "for EnvelopedData"); goto out; } ALLOC(enc_alg->parameters, 1); if (enc_alg->parameters == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate crypto paramaters " "for EnvelopedData"); goto out; } ret = hx509_crypto_get_params(context, crypto, &ivec, enc_alg->parameters); if (ret) { goto out; } } ALLOC_SEQ(&ed.recipientInfos, 1); if (ed.recipientInfos.val == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate recipients info " "for EnvelopedData"); goto out; } ri = &ed.recipientInfos.val[0]; ri->version = 0; ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set CMS identifier info " "for EnvelopedData"); goto out; } ret = _hx509_cert_public_encrypt(context, &key, cert, &ri->keyEncryptionAlgorithm.algorithm, &ri->encryptedKey); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to encrypt transport key for " "EnvelopedData"); goto out; } /* * */ ed.version = 0; ed.originatorInfo = NULL; ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy content oid for " "EnvelopedData"); goto out; } ed.unprotectedAttrs = NULL; ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length, &ed, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encode EnvelopedData"); goto out; } if (size != content->length) _hx509_abort("internal ASN.1 encoder error");out: if (crypto) hx509_crypto_destroy(crypto); if (ret) der_free_octet_string(content); der_free_octet_string(&key); der_free_octet_string(&ivec); free_EnvelopedData(&ed); return ret;}static intany_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs){ int ret, i; if (sd->certificates == NULL) return 0; for (i = 0; i < sd->certificates->len; i++) { hx509_cert c; ret = hx509_cert_init_data(context, sd->certificates->val[i].data, sd->certificates->val[i].length, &c); if (ret) return ret; ret = hx509_certs_add(context, certs, c); hx509_cert_free(c); if (ret) return ret; } return 0;}static const Attribute *find_attribute(const CMSAttributes *attr, const heim_oid *oid){ int i; for (i = 0; i < attr->len; i++) if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0) return &attr->val[i]; return NULL;}/** * Decode SignedData and verify that the signature is correct. * * @param context A hx509 context. * @param ctx a hx509 version context * @param data * @param length length of the data that data point to. * @param signedContent * @param pool certificate pool to build certificates paths. * @param contentType free with der_free_oid() * @param content the output of the function, free with * der_free_octet_string(). * @param signer_certs list of the cerficates used to sign this * request, free with hx509_certs_free(). * * @ingroup hx509_cms */inthx509_cms_verify_signed(hx509_context context, hx509_verify_ctx ctx, const void *data, size_t length, const heim_octet_string *signedContent, hx509_certs pool, heim_oid *contentType, heim_octet_string *content, hx509_certs *signer_certs){ SignerInfo *signer_info; hx509_cert cert = NULL; hx509_certs certs = NULL; SignedData sd; size_t size; int ret, i, found_valid_sig; *signer_certs = NULL; content->data = NULL; content->length = 0; contentType->length = 0; contentType->components = NULL; memset(&sd, 0, sizeof(sd)); ret = decode_SignedData(data, length, &sd, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode SignedData"); goto out; } if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "No content data in SignedData"); goto out; } if (sd.encapContentInfo.eContent && signedContent) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "Both external and internal SignedData"); goto out; } if (sd.encapContentInfo.eContent) signedContent = sd.encapContentInfo.eContent; ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer", 0, NULL, &certs); if (ret) goto out; ret = hx509_certs_init(context, "MEMORY:cms-signer-certs", 0, NULL, signer_certs); if (ret) goto out; /* XXX Check CMS version */ ret = any_to_certs(context, &sd, certs); if (ret) goto out; if (pool) { ret = hx509_certs_merge(context, certs, pool); if (ret) goto out; } for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) { heim_octet_string *signed_data; const heim_oid *match_oid; heim_oid decode_oid; signer_info = &sd.signerInfos.val[i]; match_oid = NULL; if (signer_info->signature.length == 0) { ret = HX509_CMS_MISSING_SIGNER_DATA; hx509_set_error_string(context, 0, ret, "SignerInfo %d in SignedData " "missing sigature", i); continue; } ret = find_CMSIdentifier(context, &signer_info->sid, certs, &cert, HX509_QUERY_KU_DIGITALSIGNATURE); if (ret) continue; if (signer_info->signedAttrs) { const Attribute *attr; CMSAttributes sa; heim_octet_string os; sa.val = signer_info->signedAttrs->val; sa.len = signer_info->signedAttrs->len; /* verify that sigature exists */ attr = find_attribute(&sa, oid_id_pkcs9_messageDigest()); if (attr == NULL) { ret = HX509_CRYPTO_SIGNATURE_MISSING; hx509_set_error_string(context, 0, ret, "SignerInfo have signed attributes " "but messageDigest (signature) " "is missing"); goto next_sigature; } if (attr->value.len != 1) { ret = HX509_CRYPTO_SIGNATURE_MISSING; hx509_set_error_string(context, 0, ret, "SignerInfo have more then one " "messageDigest (signature)"); goto next_sigature; } ret = decode_MessageDigest(attr->value.val[0].data, attr->value.val[0].length, &os, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode " "messageDigest (signature)"); goto next_sigature; } ret = _hx509_verify_signature(context, NULL, &signer_info->digestAlgorithm, signedContent, &os); der_free_octet_string(&os); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to verify messageDigest"); goto next_sigature; } /* * Fetch content oid inside signedAttrs or set it to * id-pkcs7-data. */ attr = find_attribute(&sa, oid_id_pkcs9_contentType()); if (attr == NULL) { match_oid = oid_id_pkcs7_data(); } else { if (attr->value.len != 1) { ret = HX509_CMS_DATA_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "More then one oid in signedAttrs"); goto next_sigature; } ret = decode_ContentType(attr->value.val[0].data, attr->value.val[0].length, &decode_oid, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode " "oid in signedAttrs"); goto next_sigature; } match_oid = &decode_oid; } ALLOC(signed_data, 1); if (signed_data == NULL) { if (match_oid == &decode_oid) der_free_oid(&decode_oid); ret = ENOMEM; hx509_clear_error_string(context); goto next_sigature; } ASN1_MALLOC_ENCODE(CMSAttributes, signed_data->data, signed_data->length, &sa, &size, ret); if (ret) { if (match_oid == &decode_oid) der_free_oid(&decode_oid); free(signed_data); hx509_clear_error_string(context); goto next_sigature; } if (size != signed_data->length) _hx509_abort("internal ASN.1 encoder error"); } else { signed_data = rk_UNCONST(signedContent); match_oid = oid_id_pkcs7_data(); } if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) { ret = HX509_CMS_DATA_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "Oid in message mismatch from the expected"); } if (match_oid == &decode_oid) der_free_oid(&decode_oid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -