mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
openssl: add hash_algorithm parameter to pkcs7_new()
The pkcs7_new() function currently uses the hash algorithm from the X509 certificate's signature, but the content signature may use a different hash algorithm. This adds a parameter to allow specifying what hash algorithm the content signature generation used.
This commit is contained in:
@@ -355,7 +355,7 @@ static int verb_pkcs7(int argc, char *argv[], void *userdata) {
|
||||
|
||||
_cleanup_(PKCS7_freep) PKCS7 *pkcs7 = NULL;
|
||||
PKCS7_SIGNER_INFO *signer_info;
|
||||
r = pkcs7_new(certificate, /* private_key= */ NULL, &pkcs7, &signer_info);
|
||||
r = pkcs7_new(certificate, /* private_key= */ NULL, /* hash_algorithm= */ NULL, &pkcs7, &signer_info);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate PKCS#7 context: %m");
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ static int asn1_timestamp(ASN1_TIME **ret) {
|
||||
static int pkcs7_new_with_attributes(
|
||||
X509 *certificate,
|
||||
EVP_PKEY *private_key,
|
||||
const char *hash_algorithm,
|
||||
STACK_OF(X509_ATTRIBUTE) *signed_attributes,
|
||||
PKCS7 **ret_p7,
|
||||
PKCS7_SIGNER_INFO **ret_si) {
|
||||
@@ -336,7 +337,7 @@ static int pkcs7_new_with_attributes(
|
||||
|
||||
_cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
|
||||
PKCS7_SIGNER_INFO *si = NULL; /* avoid false maybe-uninitialized warning */
|
||||
r = pkcs7_new(certificate, private_key, &p7, &si);
|
||||
r = pkcs7_new(certificate, private_key, hash_algorithm, &p7, &si);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate PKCS# context: %m");
|
||||
|
||||
@@ -562,7 +563,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
|
||||
_cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
|
||||
PKCS7_SIGNER_INFO *si = NULL; /* avoid false maybe-uninitialized warning */
|
||||
r = pkcs7_new_with_attributes(certificate, private_key, signed_attributes, &p7, &si);
|
||||
r = pkcs7_new_with_attributes(certificate, private_key, /* hash_algorithm= */ NULL, signed_attributes, &p7, &si);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -1126,14 +1126,15 @@ int digest_and_sign(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) {
|
||||
int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) {
|
||||
assert(certificate);
|
||||
assert(ret_p7);
|
||||
|
||||
/* This function sets up a new PKCS7 signing context. If a private key is provided, the context is
|
||||
* set up for "in-band" signing with PKCS7_dataFinal(). If a private key is not provided, the context
|
||||
* is set up for "out-of-band" signing, meaning the signature has to be provided by the user and
|
||||
* copied into the signer info's "enc_digest" field. */
|
||||
* copied into the signer info's "enc_digest" field. If the signing hash algorithm is not provided,
|
||||
* SHA-256 is used. */
|
||||
|
||||
_cleanup_(PKCS7_freep) PKCS7 *p7 = PKCS7_new();
|
||||
if (!p7)
|
||||
@@ -1151,21 +1152,22 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SI
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 certificate: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
int x509_mdnid = 0, x509_pknid = 0;
|
||||
if (X509_get_signature_info(certificate, &x509_mdnid, &x509_pknid, NULL, NULL) == 0)
|
||||
int x509_pknid = 0;
|
||||
if (X509_get_signature_info(certificate, NULL, &x509_pknid, NULL, NULL) == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get X509 digest NID: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
const EVP_MD *md = EVP_get_digestbynid(x509_mdnid);
|
||||
const EVP_MD *md = EVP_get_digestbyname(hash_algorithm ?: "SHA256");
|
||||
if (!md)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest algorithm via digest NID");
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest algorithm '%s'",
|
||||
hash_algorithm ?: "SHA256");
|
||||
|
||||
_cleanup_(PKCS7_SIGNER_INFO_freep) PKCS7_SIGNER_INFO *si = PKCS7_SIGNER_INFO_new();
|
||||
if (!si)
|
||||
return log_oom();
|
||||
|
||||
if (private_key) {
|
||||
if (PKCS7_SIGNER_INFO_set(si, certificate, private_key, EVP_get_digestbynid(x509_mdnid)) <= 0)
|
||||
if (PKCS7_SIGNER_INFO_set(si, certificate, private_key, md) <= 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to configure signer info: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
} else {
|
||||
@@ -1183,7 +1185,7 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SI
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info serial: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (X509_ALGOR_set0(si->digest_alg, OBJ_nid2obj(x509_mdnid), V_ASN1_NULL, NULL) == 0)
|
||||
if (X509_ALGOR_set0(si->digest_alg, OBJ_nid2obj(EVP_MD_type(md)), V_ASN1_NULL, NULL) == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info digest algorithm: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s
|
||||
|
||||
int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size);
|
||||
|
||||
int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si);
|
||||
int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si);
|
||||
|
||||
int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user