From nobody Fri Nov 21 10:14:38 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1763041439; cv=none; d=zohomail.com; s=zohoarc; b=lW5RQ6GWQIurJiEtm4QA10ZUAqR6RZPXhh4PajnQUVH0/TwkqlVrl7fU4rB0pCHehs58ioXjphMHfNUICQs9PmwfwTZDVX73aeW90b88h9jC82yWyx1uzq6YAHIA2QnexIncmvnowCiO4a6ivPQRpAVxRKivf4l6PyqpIpfTFt8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763041439; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id; bh=B1H1AuouhiVYhxYuHi+cv4DjOZ1OdDSZ6C7rFIXq9Jg=; b=j1w0TXQLY6pCLxdhM/qMOEbUFJ7xk4wTHRxs0UtMzzaOlg51I0amtOZLVLkb4b7WJbFLI6xirZnO6hnqPkbNKomWsy0dCDIr2FV315OcEYJxSbWVRaAyQydCRKNCUH6RGyabhXwgSKIFF7imM67LSzvpJRwfcNr1MVR7meniZao= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1763041439221831.0053906441341; Thu, 13 Nov 2025 05:43:59 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 35A854456F; Thu, 13 Nov 2025 08:43:58 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 88F3744AEF; Thu, 13 Nov 2025 08:39:40 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 0A4A343E51; Thu, 13 Nov 2025 08:32:56 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 2CF4B442D4 for ; Thu, 13 Nov 2025 08:32:53 -0500 (EST) Received: from mail-pf1-f199.google.com (mail-pf1-f199.google.com [209.85.210.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-199-6_gaGTt4PHC5wKUHJRtUSg-1; Thu, 13 Nov 2025 08:32:51 -0500 Received: by mail-pf1-f199.google.com with SMTP id d2e1a72fcca58-7b90740249dso1785369b3a.0 for ; Thu, 13 Nov 2025 05:32:51 -0800 (PST) Received: from armenon-kvm.armenon-thinkpadp16vgen1.bengluru.csb ([49.36.110.242]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b927151380sm2373676b3a.38.2025.11.13.05.32.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 05:32:47 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763040772; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B1H1AuouhiVYhxYuHi+cv4DjOZ1OdDSZ6C7rFIXq9Jg=; b=BuoKSg/IuWvg5+uD//YBfr2g9pyEn/2khCgtJLeRWRBAmGwxI3towEK/XbFHHeR4/mGoM+ MgsZf7+zuuL6CsXFecvBah+xIZzQpQi8KJlewRZgzLhjIw+LLzdKirU1xf47VVHROzT6iE /FPExV2OkYB/n92botu0RsN+9bb/tMg= X-MC-Unique: 6_gaGTt4PHC5wKUHJRtUSg-1 X-Mimecast-MFC-AGG-ID: 6_gaGTt4PHC5wKUHJRtUSg_1763040770 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763040770; x=1763645570; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=B1H1AuouhiVYhxYuHi+cv4DjOZ1OdDSZ6C7rFIXq9Jg=; b=bv0qgJmkIq2+5/SDizUxdQOKC2sSOipO2LBYA63xhQPl/ptuSxlnfgS24IrJ3TXoS6 Zs7IBsen5kxQlc2BSfhlRGzYrkSjZmHl5TzVSQZdOv8ZIIh16pwgwQC9p55Rds6/fkwS tNMHgM9DZdqdnH40daYCe/DvQWvdLjXmuCb4bITtRsrsOg1YkUeAUjSPOMLMIG2N8AwZ 3a237s5uHXCZHYpbzp3fHqmigOgiC0V8EJDwIMH9Bez6fAWpleMtEAGnN7G1dvAz2XQd H+SzM8S0lk6MUAKsPXYCWdj2p8jQASI8ndmOo86ZjJdcFSgaPpsEcVyzWz98ftQfWmfr 9vgg== X-Gm-Message-State: AOJu0Yz9uhfsUzz4DjjG6n3OBPV5Dy6MDpNAUIMuBEm2CJvXzAnOyBVa WVVw7StS0xXQYXh0vc4D5KdEi0oUyNAgYuPwhQzk0j1g3UGUoc7vhONAu59IxDd/QRM+/rZ/NI+ JA6+AG/NP7czbeE02+eVLXZQofs+BUxMU5fYPaGc3S3QzDIjUecQK+nDHiL84Tyte6hqmLP/XTc AfsOXxdGB0HlQjMbsTI5144RizD4PJUPGZR9lDUnE7JQ== X-Gm-Gg: ASbGnctkwKkpfiUa30BnjsVv9JNRBW5IuJ8eM0pn0L0gUJuybO0lJNhtuZLhypQKJmj b+LodSAseo82ByUvuz8gU+YJnDNGVbfsUdK3vFRqNrRfhD4xGAaMUR6hcuJXJ0j6guEdhacf0y3 uu/CGcMG1l2rhGpOPtN7udhsRHT8lB92KeJa6rjSCxP5WPqB80OrRo5hItmZ+74lRJbUMqC0nPC iQxXDUO6yV1B0ZZlJrccMjhqZ/52SXij2rdWspdoGt+8AvYWIKAiDTh+wAIUhtEnl4qS9NBQmhC XsCGYRgiZMQaQDXmk5gwytNASyjsqrU4Wn/lbJ7Rb/yNtvM3Hx+YRh4ozpLLfi86lMiYS9I82cp Vvuaf2TSat5JEZ1qOs7I4HuibJrryRCU6x0MAMFj4bsllNoQ= X-Received: by 2002:a05:6a00:2d8a:b0:781:c54:4d12 with SMTP id d2e1a72fcca58-7b7a3380bf0mr7717835b3a.13.1763040769759; Thu, 13 Nov 2025 05:32:49 -0800 (PST) X-Google-Smtp-Source: AGHT+IFI+c9FXTgV5CVNOwMRcYdLWcKwyOKFAz2p3PqZOGdkMyb3JNiB9NynsyfSsvxYfarzmq8qjw== X-Received: by 2002:a05:6a00:2d8a:b0:781:c54:4d12 with SMTP id d2e1a72fcca58-7b7a3380bf0mr7717789b3a.13.1763040769188; Thu, 13 Nov 2025 05:32:49 -0800 (PST) To: devel@lists.libvirt.org Subject: [RFC 4/4] secret: Add functionality to load and save secrets in encrypted format Date: Thu, 13 Nov 2025 19:02:23 +0530 Message-ID: <20251113133223.32729-5-armenon@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251113133223.32729-1-armenon@redhat.com> References: <20251113133223.32729-1-armenon@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 0GVJo0y1PI414ojfRTBVJ4Enl7oTtPzL9RQsaZzKrMs_1763040770 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: HUHB7D6RFT2Y4IK2F223EGDSUAHYWRXY X-Message-ID-Hash: HUHB7D6RFT2Y4IK2F223EGDSUAHYWRXY X-MailFrom: armenon@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Arun Menon , =?UTF-8?q?Michal=20Pr=C3=ADvozn=C3=ADk?= X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Arun Menon via Devel Reply-To: Arun Menon X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1763041450522158500 Content-Type: text/plain; charset="utf-8"; x-default="true" Since we now have the functionality to provide the secrets driver with an encryption key, we can use it to encrypt the secrets. While loading the secrets, we check whether the secret is encrypted or not and accordingly get the value. The value_encrypted boolean flag is currently ephemeral (in memory). This flag must be persisted to the disk to ensure that the secrets service knows whether the secret is in the plaintext or ciphertext format across restarts. This is vital and will be addressed in subsequent commits. Signed-off-by: Arun Menon --- src/conf/virsecretobj.c | 13 +++++++ src/conf/virsecretobj.h | 7 ++++ src/libvirt_private.syms | 2 ++ src/secret/secret_driver.c | 72 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/conf/virsecretobj.c b/src/conf/virsecretobj.c index 66270e2751..8184c3e49e 100644 --- a/src/conf/virsecretobj.c +++ b/src/conf/virsecretobj.c @@ -43,6 +43,7 @@ struct _virSecretObj { virSecretDef *def; unsigned char *value; /* May be NULL */ size_t value_size; + bool value_encrypted; }; =20 static virClass *virSecretObjClass; @@ -786,6 +787,18 @@ virSecretObjSetValueSize(virSecretObj *obj, obj->value_size =3D value_size; } =20 +bool +virSecretObjGetEncryptionFlag(virSecretObj *obj) +{ + return obj->value_encrypted; +} + +void +virSecretObjSetEncryptionFlag(virSecretObj *obj, + bool encryption) +{ + obj->value_encrypted =3D encryption; +} =20 static int virSecretLoadValidateUUID(virSecretDef *def, diff --git a/src/conf/virsecretobj.h b/src/conf/virsecretobj.h index 17897c5513..4e3b285b82 100644 --- a/src/conf/virsecretobj.h +++ b/src/conf/virsecretobj.h @@ -113,3 +113,10 @@ virSecretObjSetValueSize(virSecretObj *obj, int virSecretLoadAllConfigs(virSecretObjList *secrets, const char *configDir); + +void +virSecretObjSetEncryptionFlag(virSecretObj *obj, + bool encryption); + +bool +virSecretObjGetEncryptionFlag(virSecretObj *obj); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fc5fdb00f4..cf6a4ffe03 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1483,6 +1483,7 @@ virSecretObjDeleteConfig; virSecretObjDeleteData; virSecretObjEndAPI; virSecretObjGetDef; +virSecretObjGetEncryptionFlag; virSecretObjGetValue; virSecretObjGetValueSize; virSecretObjListAdd; @@ -1496,6 +1497,7 @@ virSecretObjListRemove; virSecretObjSaveConfig; virSecretObjSaveData; virSecretObjSetDef; +virSecretObjSetEncryptionFlag; virSecretObjSetValue; virSecretObjSetValueSize; =20 diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index 0b415e5ef3..44f0611fdc 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -43,6 +43,9 @@ #include "virutil.h" #include "virinhibitor.h" #include "virfile.h" +#include "virrandom.h" +#include "vircrypto.h" +#include "virsecureerase.h" =20 #define VIR_FROM_THIS VIR_FROM_SECRET =20 @@ -369,6 +372,12 @@ secretSetValue(virSecretPtr secret, virSecretDef *def; virObjectEvent *event =3D NULL; =20 + g_autofree uint8_t *encryptedValue =3D NULL; + size_t encryptedValueLen =3D 0; + uint8_t iv[16] =3D { 0 }; + g_autofree uint8_t *valueToSave =3D NULL; + size_t valueToSaveLen =3D 0; + virCheckFlags(0, -1); =20 if (!(obj =3D secretObjFromSecret(secret))) @@ -378,8 +387,32 @@ secretSetValue(virSecretPtr secret, if (virSecretSetValueEnsureACL(secret->conn, def) < 0) goto cleanup; =20 - if (virSecretObjSetValue(obj, value, value_size) < 0) - goto cleanup; + if (driver->encrypt_data !=3D 0 && driver->masterKeyLen >=3D 32) { + virSecretObjSetEncryptionFlag(obj, true); + if (virRandomBytes(iv, sizeof(iv)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to gene= rate random IV")); + goto cleanup; + } + if (virCryptoEncryptData(VIR_CRYPTO_CIPHER_AES256CBC, + driver->masterKey, driver->masterKeyLen, + iv, sizeof(iv), + (uint8_t *)value, value_size, + &encryptedValue, &encryptedValueLen) < 0)= { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to encr= ypt secret value")); + goto cleanup; + } + valueToSaveLen =3D sizeof(iv) + encryptedValueLen; + valueToSave =3D g_new0(uint8_t, valueToSaveLen); + memcpy(valueToSave, iv, sizeof(iv)); + memcpy(valueToSave + sizeof(iv), encryptedValue, encryptedValueLen= ); + + if (virSecretObjSetValue(obj, valueToSave, valueToSaveLen) < 0) + goto cleanup; + } else { + virSecretObjSetEncryptionFlag(obj, false); + if (virSecretObjSetValue(obj, value, value_size) < 0) + goto cleanup; + } =20 event =3D virSecretEventValueChangedNew(def->uuid, def->usage_type, @@ -387,6 +420,9 @@ secretSetValue(virSecretPtr secret, ret =3D 0; =20 cleanup: + virSecureErase(encryptedValue, encryptedValueLen); + virSecureErase(iv, sizeof(iv)); + virSecureErase(valueToSave, valueToSaveLen); virSecretObjEndAPI(&obj); virObjectEventStateQueue(driver->secretEventState, event); =20 @@ -402,6 +438,11 @@ secretGetValue(virSecretPtr secret, unsigned char *ret =3D NULL; virSecretObj *obj; virSecretDef *def; + g_autofree uint8_t *decryptedValue =3D NULL; + size_t decryptedValueLen =3D 0; + uint8_t iv[16] =3D { 0 }; + uint8_t *ciphertext =3D NULL; + size_t ciphertextLen =3D 0; =20 virCheckFlags(0, NULL); =20 @@ -444,6 +485,32 @@ secretGetValue(virSecretPtr secret, =20 *value_size =3D virSecretObjGetValueSize(obj); =20 + if (virSecretObjGetEncryptionFlag(obj) && driver->masterKeyLen >=3D 32= ) { + if (*value_size < sizeof(iv)) { + /* The encrypted secret size should be greater than IV */ + virReportError(VIR_ERR_INVALID_SECRET, "%s", + _("Encrypted secret size is invalid")); + goto cleanup; + } + memcpy(iv, ret, sizeof(iv)); + ciphertext =3D ret + sizeof(iv); + ciphertextLen =3D *value_size - sizeof(iv); + + if (virCryptoDecryptData(VIR_CRYPTO_CIPHER_AES256CBC, + driver->masterKey, driver->masterKeyLen, + iv, sizeof(iv), + ciphertext, ciphertextLen, + &decryptedValue, &decryptedValueLen) < 0)= { + virReportError(VIR_ERR_INVALID_SECRET, "%s", + _("Decryption of secret value failed")); + goto cleanup; + } + + g_free(ret); + ret =3D g_steal_pointer(&decryptedValue); + *value_size =3D decryptedValueLen; + } + cleanup: virSecretObjEndAPI(&obj); =20 @@ -502,6 +569,7 @@ secretStateCleanupLocked(void) =20 virObjectUnref(driver->secrets); VIR_FREE(driver->configDir); + VIR_FREE(driver->masterKeyPath); =20 virObjectUnref(driver->secretEventState); virInhibitorFree(driver->inhibitor); --=20 2.51.1