creds: query OpenSSL for GCM tag length

Follow-up for: 21bc0b6fa1

Follow-up for: 99d0a9fdb0
This commit is contained in:
dongshengyuan
2026-07-27 19:19:31 +09:00
committed by Yu Watanabe
parent ecc8c69eca
commit 7412c16ef8
3 changed files with 27 additions and 13 deletions
+24 -13
View File
@@ -1107,8 +1107,6 @@ int encrypt_credential_and_warn(
return log_error_errno(r, "Failed to acquired randomized IV: %m");
}
tsz = 16; /* FIXME: On OpenSSL 3 there is EVP_CIPHER_CTX_get_tag_length(), until then let's hardcode this */
context = sym_EVP_CIPHER_CTX_new();
if (!context)
return log_openssl_errors(LOG_ERR, "Failed to allocate encryption object");
@@ -1116,6 +1114,10 @@ int encrypt_credential_and_warn(
if (sym_EVP_EncryptInit_ex(context, cc, NULL, md, iv.iov_base) != 1)
return log_openssl_errors(LOG_ERR, "Failed to initialize encryption context");
tsz = sym_EVP_CIPHER_CTX_get_tag_length(context);
if (tsz <= 0 || (size_t) tsz > CREDENTIAL_FIELD_SIZE_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid tag size reported by OpenSSL.");
/* Just an upper estimate */
output.iov_len =
ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz) +
@@ -1336,8 +1338,9 @@ int decrypt_credential_and_warn(
struct metadata_credential_header *m;
uint8_t md[SHA256_DIGEST_LENGTH];
const EVP_CIPHER *cc;
uint32_t tag_size;
size_t p, hs;
int r, added;
int r, added, tsz;
assert(iovec_is_valid(input));
assert(ret);
@@ -1405,7 +1408,9 @@ int decrypt_credential_and_warn(
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected block size in header.");
if (le32toh(h->iv_size) > CREDENTIAL_FIELD_SIZE_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "IV size too large.");
if (le32toh(h->tag_size) != 16) /* FIXME: On OpenSSL 3, let's verify via EVP_CIPHER_CTX_get_tag_length() */
tag_size = le32toh(h->tag_size);
if (tag_size == 0 || tag_size > CREDENTIAL_FIELD_SIZE_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected tag size in header.");
/* Ensure we have space for the full header now (we don't know the size of the name hence this is a
@@ -1417,7 +1422,7 @@ int decrypt_credential_and_warn(
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
ALIGN8(offsetof(struct metadata_credential_header, name)) +
le32toh(h->tag_size))
tag_size)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
p = ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size));
@@ -1448,7 +1453,7 @@ int decrypt_credential_and_warn(
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
ALIGN8(offsetof(struct metadata_credential_header, name)) +
le32toh(h->tag_size))
tag_size)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
p += ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) +
@@ -1469,7 +1474,7 @@ int decrypt_credential_and_warn(
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
ALIGN8(offsetof(struct metadata_credential_header, name)) +
le32toh(h->tag_size))
tag_size)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
p += ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) +
@@ -1487,7 +1492,7 @@ int decrypt_credential_and_warn(
ALIGN8(offsetof(struct tpm2_pinned_srk_credential_header, data) + le32toh(z_srk->size)) +
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
ALIGN8(offsetof(struct metadata_credential_header, name)) +
le32toh(h->tag_size))
tag_size)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
p += ALIGN8(offsetof(struct tpm2_pinned_srk_credential_header, data) +
@@ -1538,7 +1543,7 @@ int decrypt_credential_and_warn(
p +
sizeof(struct scoped_credential_header) +
ALIGN8(offsetof(struct metadata_credential_header, name)) +
le32toh(h->tag_size))
tag_size)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
p += sizeof(struct scoped_credential_header);
@@ -1580,6 +1585,12 @@ int decrypt_credential_and_warn(
if (sym_EVP_DecryptInit_ex(context, cc, NULL, NULL, NULL) != 1)
return log_openssl_errors(LOG_ERR, "Failed to initialize decryption context");
tsz = sym_EVP_CIPHER_CTX_get_tag_length(context);
if (tsz <= 0 || (size_t) tsz > CREDENTIAL_FIELD_SIZE_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid tag size reported by OpenSSL.");
if (tag_size != (uint32_t) tsz)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected tag size in header.");
if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, le32toh(h->iv_size), NULL) != 1)
return log_openssl_errors(LOG_ERR, "Failed to set IV size on decryption context");
@@ -1589,7 +1600,7 @@ int decrypt_credential_and_warn(
if (sym_EVP_DecryptUpdate(context, NULL, &added, input->iov_base, p) != 1)
return log_openssl_errors(LOG_ERR, "Failed to write AAD data");
plaintext.iov_base = malloc(input->iov_len - p - le32toh(h->tag_size));
plaintext.iov_base = malloc(input->iov_len - p - tag_size);
if (!plaintext.iov_base)
return -ENOMEM;
@@ -1598,14 +1609,14 @@ int decrypt_credential_and_warn(
plaintext.iov_base,
&added,
(uint8_t*) input->iov_base + p,
input->iov_len - p - le32toh(h->tag_size)) != 1)
input->iov_len - p - tag_size) != 1)
return log_openssl_errors(LOG_ERR, "Failed to decrypt data");
assert(added >= 0);
assert((size_t) added <= input->iov_len - p - le32toh(h->tag_size));
assert((size_t) added <= input->iov_len - p - tag_size);
plaintext.iov_len = added;
if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input->iov_base + input->iov_len - le32toh(h->tag_size)) != 1)
if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, tag_size, (uint8_t*) input->iov_base + input->iov_len - tag_size) != 1)
return log_openssl_errors(LOG_ERR, "Failed to set tag");
if (sym_EVP_DecryptFinal_ex(context, (uint8_t*) plaintext.iov_base + plaintext.iov_len, &added) != 1) {
+2
View File
@@ -126,6 +126,7 @@ static DLSYM_PROTOTYPE(ERR_peek_last_error) = NULL;
DLSYM_PROTOTYPE(EVP_CIPHER_CTX_ctrl) = NULL;
DLSYM_PROTOTYPE(EVP_CIPHER_CTX_free) = NULL;
static DLSYM_PROTOTYPE(EVP_CIPHER_CTX_get_block_size) = NULL;
DLSYM_PROTOTYPE(EVP_CIPHER_CTX_get_tag_length) = NULL;
DLSYM_PROTOTYPE(EVP_CIPHER_CTX_new) = NULL;
static DLSYM_PROTOTYPE(EVP_CIPHER_fetch) = NULL;
DLSYM_PROTOTYPE(EVP_CIPHER_free) = NULL;
@@ -450,6 +451,7 @@ int dlopen_libcrypto(int log_level) {
DLSYM_ARG(EVP_CIPHER_CTX_ctrl),
DLSYM_ARG(EVP_CIPHER_CTX_free),
DLSYM_ARG(EVP_CIPHER_CTX_get_block_size),
DLSYM_ARG(EVP_CIPHER_CTX_get_tag_length),
DLSYM_ARG(EVP_CIPHER_CTX_new),
DLSYM_ARG(EVP_CIPHER_fetch),
DLSYM_ARG(EVP_CIPHER_free),
+1
View File
@@ -132,6 +132,7 @@ extern DLSYM_PROTOTYPE(ERR_error_string_n);
extern DLSYM_PROTOTYPE(ERR_get_error);
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_ctrl);
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_free);
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_get_tag_length);
extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_new);
extern DLSYM_PROTOTYPE(EVP_CIPHER_free);
extern DLSYM_PROTOTYPE(EVP_CIPHER_get_block_size);