Linux内核主内存加密框架

AI助手已提取文章相关产品:

冻结与加密:Linux内核对主内存加密的支持

高亮点

  • 操作系统内核中高效主内存加密和解密的通用概念
  • 为Linux内核开发主内存加密原型
  • 将原型集成到运行Android容器的移动设备上
  • 在实际使用的智能手机上应用该原型
  • 全面的安全性和性能评估以证明其实际可用性

1 引言

几十年来,数字世界不断深入我们的企业和个人生活。随着移动设备的创新,个人在数字世界中的数字足迹急剧增加。我们不仅在云端或持久存储中留下敏感的行为痕迹,也在主内存中留下了这些痕迹。应用程序保留在内存中的数据通常以明文形式存在,例如凭证、图片、密码或密钥材料[7, 8, 47, 49]。尤其是在敏感的企业或政府领域,对有价值且可能属于机密数据的可靠保护是一个重要课题。通过联合测试行动组(JTAG)[38],冷启动[20, 22, 44],或直接内存访问(DMA)[1, 4, 6, 29, 40],等内存攻击已被证明能够有效披露随机存取存储器中的秘密。

为了解决这一问题,我们提出了一种面向Linux内核的框架——冻结与加密(F&C),该框架通过在随机存取存储器中加密敏感数据,以保护无人看管或被盗的移动设备及工作站免受内存攻击。

我们设计的F&C框架兼容多平台和不同内核版本,并仅需对内核进行最小改动,从而维持其通用可操作性。该机制能够对系统上运行的任意进程的完整进程空间实现透明且选择性的保护。我们将F&C集成到内核中,基于现有的控制组(cgroups)冻结子系统构建。控制组机制本身允许动态地形成进程组,在下文中也称为控制组(cgroups)。不同的控制组子系统会对这些控制组实施各自的策略,以限制它们对系统资源(如中央处理器或内存子系统)的访问,防止某个控制组耗尽中央处理器或随机存取存储器资源。冻结子系统(下文中简称为冻结器)则允许对控制组进行冻结与解冻,即实现其挂起与恢复。

在冻结控制组时,内核会向该控制组中的进程发送一个信号。每个进程通过进入内核空间中所谓的“冰箱”来响应该信号。“冰箱”是一个循环,确保进程既不会在用户空间执行,也不会响应外部事件。当处于冻结状态时,进程的用户空间部分无法访问或修改其内存空间。因此,“冰箱”是临时修改进程内存而不会对其用户空间部分产生副作用的理想场所。特别是,我们让进程自身并行地对其内存空间的各个段(例如堆、栈、代码或匿名段)进行加密和解密。这使得我们的方法在多核系统上特别高效。在解冻控制组时,我们会在允许进程离开之前,先让它们解密其内存。为了实现并行化,F&C在“冰箱”内部对进程和线程进行同步,因为它们操作的是共享资源。

我们用于控制组加密和解密的密钥仅在冻结与解冻,且可能在每次冻结时发生变化。尽管我们的设计使F&C独立于硬件平台,但它也可以在支持进程挂起和进程组的其他操作系统上实现。

我们通过一个在实际生产中使用的、大规模的应用场景展示了该机制的有效性。这是一个虚拟化平台,能够在单个智能手机上同时运行多个Android容器[3, 32]。我们使用F&C来保护挂起容器的主内存,防止具有全部物理访问权限的攻击者进行攻击。该平台特别适合F&C,因为它能够利用安全元件(SE)实现安全的加密密钥管理,从而防止对加密密钥的暴力破解攻击。在容器被加密期间,我们使用SE对加密密钥进行封装,仅允许知晓SE密码短语的合法用户解密容器。具体而言,我们的贡献包括:
- 一种支持进程组和挂起的操作系统内核的高效进程内存加解密方案。
- 针对Linux内核的原型开发。
- 在具有安全密钥管理的复杂移动设备架构上集成原型并将其实现于实际场景。
- 对移动设备上的实际可用性进行彻底的安全性和性能评估。

本文组织如下:我们首先在第2节中描述攻击者模型。在第3节中,介绍F&C的设计。接着,在第4节中详细阐述原型的实现。在第5节中,我们概述移动设备架构以及为支持F&C而对其设计所做的扩展。性能评估和安全评估分别在第6节和第7节中给出。第8节介绍了相关工作,最后在第9节进行总结。

2 威胁模型

我们考虑这样一种攻击者,其目标是从处于F&C保护下的无人看管且未被篡改的设备中提取敏感数据。该攻击者能够获得对受保护设备的物理访问权限,并拥有充足的时间以及访问易失性和持久性内存的能力。为访问内存,攻击者会利用硬件和软件漏洞,例如通过直接内存访问(DMA)、联合测试行动组(JTAG)或冷启动攻击。这些手段还允许攻击者攻陷系统中未挂起的部分,包括操作系统内核。然而,攻击者无法实施邪恶女仆攻击,即无法秘密地在设备上部署后门以等待用户返回。这意味着一旦设备被篡改,便不再被信任,例如在发生盗窃或丢失的情况下,或者用户察觉到篡改企图时。

关于我们的应用场景,对手可能拥有安全元件(SE),但不知道SE的密码短语,因此无法揭示存储在SE上的秘密。此外,攻击者无法破解最先进的密码学原语。此类攻击场景可能发生于敏感的企业或政府领域,设备所有者同时使用企业容器和个人容器。在这种情况下,攻击者在获得对设备的物理访问权限后,试图获取存储在企业容器中的敏感数据。

3 内存保护概念

我们首先在第3.1小节中介绍F&C整体设计及其涉及的OS组件的概述。随后,在第3.2小节中详细阐述主内存加密过程中进程的同步。下文中,“加密”一词也适用于解密,仅在解密与加密不同的情况下进行区分。

3.1 冻结与加密设计

基于Linux内核的cgroups冻结器,F&C允许动态创建包含我们对其内存空间进行加密的进程和线程的控制组。从现在起,我们将进程和线程统称为任务,仅在需要时进行区分。对于每个控制组,我们在每次加密过程中使用独立的临时密钥。

我们将进程的内存空间划分为以下段:
- 文本 。任务的可执行、只读代码。
- 数据 。可写以及属于任务代码的只读数据。包含在编译时初始化的静态分配变量。
- BSS段 。零初始化的可写数据。包含在编译时未初始化的静态分配变量。
- 。任务动态分配的内存。
- 。函数的局部变量及其参数等。
- 匿名映射 。任务可以映射到其进程空间并与他人共享的大块动态内存分配。
- 文件映射 。内存映射区域的所有部分。例如,大型可写文件,以及只读文件(如共享库的代码)。我们进一步区分常规映射与非常规映射,以及它们的访问权限。非常规映射包括内存映射设备、直接内存访问(DMA)或进程间通信(IPC)资源。
- 特殊映射 。定时器、向量、vdso和vsyscall段。这些段不包含机密用户数据。内核将这些段作为系统范围共享内核资源进行管理,并作为内核接口提供给任务使用。

除了特殊映射外,任务可以在所有其他段中加载或存储机密信息。因此,F&C允许选择除特殊映射外的所有其他段进行加密。根据使用场景的不同,较少的段可能是关键的,因而可以不进行加密。我们将在第5节中概述本使用场景下的关键段。

3.1.1 控制组的状态

图1描述了控制组及其任务的四种不同状态。在系统中,我们有任意数量的处于任何状态的控制组,以及可能成为冻结器控制组一部分或形成新控制组的非受保护任务。这使我们能够创建互不相交的控制组,同时冻结或解冻多个控制组,并分配不同的加密密钥。

  • 解冻 。在默认状态下,多个任务处于运行状态,例如图1中的任务1,且该控制组未分配加密密钥。控制组机制默认确保将来创建的子任务被包含在该控制组内。箭头表示任务的执行。
  • 冻结 。开始冻结后,控制组进入冻结状态,并分配有一个任意的加密密钥。冰箱中的任务进入一个不可中断状态,并一直停留在其中,直到该控制组被解冻。任务1已进入冰箱,目前正在对其内存段进行加密。正在运行的任务2的箭头表示它正从用户空间的执行跳转至内核空间进入冰箱。在冰箱中,进程的用户空间部分无法访问或修改其内存。这些任务无法响应传入的进程间通信或外部事件(例如终止信号)。内核会缓冲此类数据和事件,使任务在解冻后能够处理它们。
  • Frozen 。完成加密后,控制组处于冻结状态,并已清除其加密密钥。其所有任务均处于不可中断状态,卡在内核空间的冰箱中,脱离运行队列。一旦被调度,内核会立即再次调用调度器以切换到另一个任务。所有任务均已加密先前指定的内存段。
  • 解冻 。启动解冻后,控制组处于解冻中状态,并使用与冻结时相同的密钥进行解密。该控制组将其任务带入唤醒状态。当被调度时,这些任务在离开冰箱前同时解密各自的段。任务1在图1中即将解密其段,而任务2已经完成解密。我们仍将任务2保留在冰箱中以进行同步,直到其控制组的所有任务均完成解密。这使得相互依赖的任务能够同时被释放。
3.1.2 冻结器的扩展

我们扩展了冻结器的初始化、冻结和解冻功能,以管理控制组的保护。图2以序列图的形式展示了这些功能。粗体元素代表我们为冻结器引入的新功能。

F&C的初始化。用户空间中的特权进程可以通过与内核的接口来管理控制组功能,从而创建控制组并添加或移除任务。为了初始化一个冻结器控制组,一个特权进程将任务添加到该控制组中,此处为任务X和任务Y。我们通过增加选项来扩展该接口,以将冻结器与任意密钥以及需要加密的内存段列表相关联。该概念有意将密钥管理留给F&C所应用的具体使用场景。位于用户空间的特权实体必须确保向F&C提供加密所需的密钥,并安全存储已加密控制组的密钥。该密钥可以例如来自密码派生、可信平台模块(TPM)或SE,如第5节中所述的应用场景。

冻结过程 。如图2所示,一个特权进程启动控制组的冻结和解冻。冻结器改变其状态,并向其任务发送信号以进入冰箱。每个任务在完成加密后通知冻结器。当冻结器收到所有加密通知后,该控制组进入冻结状态,且冻结器清除加密密钥。为了擦除可能残留的敏感信息,冻结器还会在加密完成后清零由运行中或已终止的进程释放的页面、已使用的加密内核结构以及内存中相关的内核栈范围。最后,冻结器通知用户空间该控制组的加密已完成。标准冻结器仅在用户空间请求其实际状态时才切换状态。在F&C中,子系统主动管理其状态,以便能够尽可能早地清除密钥和其他残留信息。我们还会主动通知用户空间(例如管理控制组加密的实体)状态的变化。我们在应用场景中展示了此功能的实用性。

解冻过程 。在触发控制组的解冻并因此开始解密之前,一个特权进程会将相应的密钥传递给冻结器。冻结器唤醒每个包含在内的任务。当被调度时,这通常会导致任务离开冰箱。在我们的机制中,任务首先解密其先前已加密的内存段,并通知冻结器。与原始的冻结器不同,我们不会立即切换到解冻状态,而是等待最后一个任务完成解密并通知冻结器后再进行状态切换。随后,任务在被调度时安全地离开冰箱并恢复执行。冻结器清除解密密钥、其他残留物,并通知用户空间。因此,密钥及其痕迹仅在加密和解密期间存在于冻结器中。

3.2 任务同步

由于加密控制组中的任务并行进入冰箱并共享资源,因此我们对其并发加密进行同步。共享资源的同步非常重要,因为某些任务可能尚未挂起或不属于加密控制组。在这种情况下,我们确保仅当所有共享该资源的任务都进入冰箱后,才对共享资源进行加密。内核内存管理负责任务间的资源共享。共享资源可以是地址空间(AS)和物理页,如图3所示。地址空间(AS)描述了一个任务所拥有的不同内存段,例如堆、栈或代码段。每个过程都有其自己的虚拟地址空间,表示各内存段的虚拟内存布局。当存在映射时,地址空间中的内存页指向主内存中的物理页。当多个地址空间的映射指向同一物理页时,该物理页即被共享。接下来,我们首先关注共享的地址空间,然后再讨论共享的物理页。

3.2.1 共享地址空间

一个任务可以生成线程并派生新进程。内核为派生的进程分配其自己的地址空间。在生成线程时,父进程与其生成的线程共享其地址空间。图3展示了进程A和B的任务共享它们的地址空间的情况。我们的目标是确保每个地址空间仅被一个任务加密,以避免同一地址空间被多次加密。如果没有同步机制,共享任务在进入冰箱时会反复加密同一个地址空间,并且任务可能会访问正在被加密的内存。

图4重点关注了进入冰箱的任务的时间顺序,其中过程A和B属于同一个控制组。这使得最后到达的任务能够根据该列表快速开始加密。我们确保在所有段都被识别之前不会启动加密。如图4所示,过程B的TaskY与TaskX并行对其地址空间进行加密。两个任务都在共享其地址空间的所有其他任务进入冰箱后才开始加密。相反,对于一个进程,只有被调度并唤醒的第一个任务才会解密这些段。一旦所有进程空间的解密完全完成,我们允许全部任务离开冰箱。此后,任务返回用户空间运行,可以访问其地址空间,并分配或释放内存。

3.2.2 共享物理页

任务在其加密过程中使用虚拟地址。然而,实际被加密的物理页可能在进程边界之间共享,这会使加密过程变得复杂。因此,我们必须在加密页面之前确定该页面是否与其他进程共享,以防止其他地址空间(AS)遭到破坏。共享页面包含在多个地址空间中,并可进一步分类:第一,这些页面可能是所有任务都仅用于只读的页面;第二,这些可能是可写的写时复制(COW)页面,它们在进程仅读取页面时在进程间共享;一旦某个共享进程对页面进行写入,写时复制(COW)会分配一个新页面,以确保该任务在一个独立的副本上写入;第三,共享页面可能表示用于进程间通信(IPC)的共享内存,其中不同的进程操作同一组物理页;第四,页面可能通过内核的Kernel Samepage Merging(KSM)机制被合并,该机制会搜索相同的

冻结与加密:Linux内核对主内存加密的支持

4 实现

在本节中,我们描述了在ARM和x86架构上针对Linux内核的原型实现,已在3.4、3.10和最新的4.x内核版本上进行了测试。我们首先介绍从用户空间对F&C的管理。随后,我们重点讨论对内存管理所做的扩展以及在冻结和解冻期间任务的同步机制。接着,我们详细阐述任务加密其内存空间所采用的过程。

4.1 与用户空间的交互

为了将密钥和段列表从用户空间传递到内核,我们在cgroup虚拟文件系统中创建了额外的文件。我们通过文件句柄读取从用户空间接收到的密钥和段列表,类似于现有的冻结器状态更改功能。然而,使用文件系统中的inotify机制来通知用户空间关于文件系统的变更,在cgroup虚拟文件系统的伪文件上无法正常工作。因此,用户空间必须周期性地读取状态文件,以检查冻结器状态是否发生变化。为了避免这种轮询,我们在冻结和解冻操作结束时,使用eventfd和cgroup通知API显式地通知用户空间。

F&C的一个限制是,我们当前的原型仅允许为互不相交的冻结cgroup从用户空间传递任意密钥。这里的“互不相交”是指这些cgroup之间不共享任何页面。例如,在我们的应用场景中的容器即为此类情况,参见第5节。对于非互不相交的cgroup,若使用相同的密钥,则可以确保解密的正确性,且不受加密顺序的影响,而使用不同密钥则无法保证这一点。以两个相互共享页面的cgroup A和B为例,当首先冻结cgroup A时,它会用自己的密钥加密其内存,但会保留共享页面未加密,因为另一个cgroup的任务可能仍在使用该页面。当cgroup B加密其内存空间时,若此时cgroup A仍处于冻结状态,则最终会用自己的密钥加密这些共享物理页。如果两个密钥相同,则cgroup A和B可以按任意顺序进行解密。若使用不同的密钥,则管理cgroup的用户空间实体必须确保按照与加密顺序相反的顺序进行解冻,否则cgroup A将用自己的密钥对共享页面进行解密。一种可能的解决方案是为共享页面引入一个共享密钥。另一种方向是使用可交换加密算法来放宽此限制,这将允许在使用不同密钥的同时随意调整解密顺序。该方法的限制在于,尽管解密顺序变得无关紧要,但我们仍必须将共享页面的cgroup保留在冰箱中,直到依赖的cgroup被解冻后才能完成解密。

用户空间还必须避免同时解冻和冻结非不相交的控制组,因为当共享物理页时,加密任务可能会与解密任务发生冲突。在从用户空间触发进程组加密时,必须考虑这些限制。容器化通过避免共享物理页,可确保创建不相交的控制组。

4.2 内存管理

一个过程及其生成的线程共享描述任务内存布局的内核结构。图6显示了Linux内核用于内存管理的相关组件以及任务如何共享资源。该图以进程A和B为例,概述了资源共享的情况。每个任务都有自己的进程描述符用于过程管理,其中包含例如名称和进程ID。我们临时修改浅灰色的加密过程中的组件,如虚拟内存地址(VMAs)和页表项(PTEs)。中灰色表示我们为其引入新功能以处理共享资源的组件。

进程描述符指向一个内存描述符,该描述符描述了进程的虚拟内存布局。内存描述符跟踪其拥有的用户数量,即与父进程共享该内存描述符的线程数量。我们扩展了内存描述符,以额外记录已进入冰箱的冻结的共享任务的数量。通过这种方式,任务能够判断自己是第一个还是最后一个进入冰箱的任务。内存描述符所指向的内存由一个链表形式的VMA表示,这些VMA代表了我们需要选择性加密的内存段。在进行加密时,我们将不可写的VMA设置为临时可写。

内存描述符保持对页全局目录(PGD)的引用,用于将进程的虚拟地址转换为对应的物理地址。基于从PGD开始、遍历页上级目录(PUD)和页中间目录(PMD)的页遍历,我们可以确定已映射的虚拟地址所对应的PTE,即页面存在于主内存中时。PTE包含多个值以跟踪页面的状态,例如页面是否在进程之间共享,或者该进程是否已访问或写入页面。当写入物理页面时,内核也可能修改PTE的值。因此,在加密物理页面之前,我们先保存PTE的值,并在页面加密完成后立即恢复它们。这尤其可以防止文件支持的页面通过页缓存意外地被标记为持久化,方法是在加密过程中不设置脏标志。

存在的PTE通过引用所谓的页描述符来映射一个物理页面,该描述符描述内存中的一个特定物理页面,并直接指向该页面的物理地址。我们在页描述符中设置一个标志,用于指示在加密期间对内存中的物理页面加锁。通过对页面加锁,我们确保加锁的任务获得对该页面的独占访问权。此外,我们扩展了页描述符的功能,以支持标记页面为已加密。通过此功能和页面加锁机制,我们确保任务仅加密一次页面。为了跟踪引用该页面的实体,页描述符维护了一个反向映射,指向引用的VMA。由于VMA具有对其所属的反向引用内存描述符,我们能够知晓所有可能在控制组之外引用所述页面的任务。这使我们能够确定任务引用的共享页面是否可以被加密。

4.3 任务的同步

图7描绘了一个序列图,描述了任务如何通过冰箱运行。我们使用实线框突出显示新功能,而标准冻结器功能则用虚线框表示。进入冰箱的任务首先保存其当前任务状态。然后我们递增一个新引入的cgroup级屏障,该屏障用于计数进入冰箱的任务。在解冻时,该屏障会强制解冻任务在冰箱中等待,直到整个cgroup的解密完成。下一步,我们递增任务内存描述符的冻结用户计数。首个用户,即第一个任务,识别出进程空间中被选为加密的内存段。在可能识别内存段之后,任务像往常一样进入TASK_UNINTERRUPTIBLE状态。如果进程尚未加密,任务会检查自己是否是内存描述符的最后进入用户。如果是,则任务将内存描述符标记为已加密,并对已识别的内存段进行加密。之后,或者在任务不是内存描述符的最后用户的情况下,任务通知冻结器自身已被冻结。接着执行通用冷冻过程。任务将自身标志设为冻结,并进入一个循环,检查其cgroup是否已被冻结。当被调度时,冻结的任务执行通用功能,并指示调度器切换到另一个任务。

解冻控制组时,冻结器会唤醒该控制组的任务,离开冻结状态,每个任务清除其FROZEN标志。任务通常会离开冰箱并恢复其先前的进程状态。然而,我们的机制会在任务离开之前处理其解密。为此,解冻任务首先递减冻结用户计数器。这确保了只有第一个使用内存描述符的解冻任务会解密关联的内存空间,其他任务则跳过解密。下一步,每个任务递减cgroup级屏障。最后一个即将离开冰箱的任务完成该屏障,所有在屏障处等待的其他任务最终可以自由离开冰箱。最后一个任务还会通知冻结器整个cgroup的解密已终止。

4.4 进程空间加密

对于使用内核加密API在主内存中的加密,我们采用基于NEON指令的异步位切片AES CTR实现,密钥长度为256位。CTR模式通过其并行化特性在多核系统上实现了特别高的性能。我们使用物理页面地址作为初始化向量(IVs),从而为每个加密块生成不同的IV。在加密过程中,任务会遍历其内存描述符中先前识别的VMA。任务首先检查VMA的写权限。如果VMA不可写,任务会将其设置为可写。然后任务逐页加密VMA。在完成整个VMA的加密后,任务会根据需要恢复VMA的写权限。当任务完成最后一个VMA的加密后,加密过程终止。

图8展示了页面级加密过程的方案。页面级加密过程首先检查待加密的虚拟页面是否物理上存在于主内存中。我们跳过不存在的页面。由于被换出的页面也被标记为不存在,因此我们不对被换出的页面进行加密。关于交换分区的加密,请参考标准的Linux交换分区加密。对于存在的页面,任务尝试获取我们的锁。若获取失败,则表明该页面当前正在被另一个任务加密。因此,任务将跳过该页面的加密。

图8中的下一步骤取决于我们是在加密还是解密控制组。在解密情况下,我们只需要检查页面是否已经解密。如果是,则页面直接解锁;否则,我们将其标记为已解密并开始立即解密。图示中简化了此步骤,省略了检查和可能的页解锁操作。

在加密情况下,我们必须确保页面已准备就绪可加密。这意味着首先检查页描述符是否已被标记为已加密。如果是这种情况,任务将释放锁并跳过该页面。如果页面尚未被加密,任务接着检查该页描述符是否被多次引用。如果仅有一个页表项(PTE)引用该页面,则任务立即认为该页面准备就绪可加密。多个引用表明该页面是共享的,可能尚未准备就绪。在这种情况下,任务必须特别检查该页面是否准备就绪可加密,因为它跨越了地址空间边界。若对未准备就绪的页面进行加密,将会破坏其他进程的地址空间。因此,任务会释放对该非准备就绪页面的锁并跳过它。当同一个控制组中的另一个任务后续考虑对该页面进行加密时,如果该页面仅与同一控制组内的进程共享,则将确保该页面稍后被加密。

在将页面标记为已加密/已解密后,无论加密还是解密,后续流程均相同,如图8所示。如果页面已准备就绪,任务将其标记为已加密。在写入页面之前,任务会保存页表项的标志。这些标志用于指示页面是否为可写、脏页或年轻页。任务需要检查页面是否可写,因为向只读页面写入会导致触发页面错误时发生写时复制(COW),这将导致该页面的复制以及副本的加密。由于任务确保该页面仅在控制组内使用,因此在加密前会先将页表项设置为可写,以避免页面错误。下一步,任务对物理页面进行加密,随后恢复页表项的标志,以确保页表项标志保持不变。最后,任务解锁页面。

5 应用场景

我们在实际使用中展示了F&C在智能手机上的能力。我们使用运行多个基于移动设备虚拟化平台的Android容器的Nexus 5智能手机[3, 32, 39]。当带有虚拟化平台的移动设备正在被积极使用时,一个Android容器处于前台,而一个或多个容器在后台运行。我们对后台容器进行加密,仅保留正在使用的容器未加密。在设备空闲一段时间后,我们会确保加密全部容器,以保护所有敏感数据免受内存攻击。

5.1 虚拟化平台的组件与扩展

图9展示了虚拟化平台中最相关的组件。该示意图描述了一个场景,其中运行的容器C0..X位于用户空间和内核空间的可信组件之上。这些可信组件能够基于操作系统级虚拟化来创建和管理C0..X。C1..X是隔离的安卓用户容器包含应用程序和可能的敏感数据,例如个人容器和企业容器。C0是一个最小化、加固且可信的管理容器,提供用于虚拟化C1..X硬件设备的功能,并且不包含任何敏感用户数据。C0..X在内核级别被嵌入到独立的命名空间中。Linux命名空间为命名空间内的进程提供对系统资源(如IPC、PID或网络命名空间)的独立视图,从而隔离不同命名空间中的进程,使其无法感知其他命名空间的存在。该平台使用CPU、内存和设备cgroup子系统来限制C0..X对硬件资源的访问。在用户空间中,容器管理(CM)负责C0..X的配置、启动和切换。CM为每个启动的C0..X分配不同的cgroup,并将其各自嵌入独立的命名空间中。C1..X将其持久化数据存储在使用基于内核的全盘加密(FDE)保护的镜像中。因此,CM存储了被封装的、持久化的磁盘加密密钥KFDE1到X,分别对应C1..X。这些密钥只能通过SE进行解封,而CM与SE进行通信。C0拥有一个可信GUI应用,用户在此提供SE的密码短语(PIN)以启动C1..X。其他安全构建模块,例如仅允许通过明确定义的通道进行IPC,以实现C0..X之间的隔离,可在[32]中找到。

对于F&C,我们假设C1..X的传入敏感数据是已加密的,并且加密在C1..X内部终止。我们需要对那些处理敏感数据(如企业机密)的C1..X进行加密,而其余部分可以保持未加密。我们不对C0的RAM内容进行加密,因为它不包含任何敏感的用户数据。我们扩展了CM的功能,以配置F&C,并生成、封装和解封用于C1..X的RAM加密密钥,记为KRAM1到X,该过程类似于KFDE1到X的封装,使用SE来完成。KFDE1到X在C1..X启动后被解封,属于CM的一部分,因此不受C1..X加密的保护。因此,这些密钥也需要受到攻击防护。我们在对先前已启动的C1..X进行加密时,立即封装KFDE1到X。

图9中的加粗组件描述了C1处于前台而其他容器处于后台的场景。图中显示冻结器正在使用未封装的KRAM1,这表明系统已锁定C1,即将切换到C0,并在后台对C1进行加密。与此同时,FDE模块仅保留未封装的KFDE1。内核不需要解封KFDE2到X,因为C2到X已被冻结且无法访问其文件系统。在冻结C1完成后,容器管理器还会从内核中移除C1的未封装的KFDE1。

与普通智能手机类似,我们要求用户重新认证以启动或恢复已挂起的加密容器。该架构适合我们的机制,因为它基于具有双因素认证的安全元件(SE)来实现安全的加密密钥管理,例如通过NFC连接的智能卡或微型SD卡。这使得我们能够使用SE安全地封装加密密钥。使用SE可以防止对加密密钥进行暴力破解攻击,但在重新认证时可能会影响可用性。然而,由于生产场景对安全性要求较高,使用SE仍是首选方案。对于其他使用场景,我们的系统可轻松适配为安全性较低但可用性更高的方案,例如基于个人识别码(PIN)或密码的密钥派生,或滑动图案。

5.2 容器加密和密钥管理

对于C1..X的加密,我们考虑第3.1小节中描述的所有可选内存段与本场景相关,但以下情况除外:
- 只读可执行文件映射段 。这是共享库代码,在我们的系统中不包含敏感用户数据,仅包含共享的常量数据。由于每个容器都具有完整的用户空间,C1..X包含独立的库,例如libc。库的数据段不属于此类别,因此会被加密。
- 可写非常规文件映射段 。这些段表示内存映射设备、进程间通信资源或DMA文件的内存区域,驱动程序通过这些区域与硬件设备共享内存。在大多数平台上,对这类内存进行加密可能会破坏内存空间,因为例如硬件设备并不知晓加密的存在。

所有其他段都必须受到保护,因为进程可能会在那里存储或加载敏感数据。图10中的示意图描述了保护C1..X敏感数据的流程。图示展示了启动、加密和解密Ci的步骤。

Start Ci 。要启动Ci,我们在前台C0的可信图形用户界面中输入当前安全元件的个人识别码。该图形用户界面将带有个人识别码的启动Ci信息传递给容器管理器。容器管理器使用基于硬件随机数的硬件熵作为种子的内核随机数生成器,随机生成一个新的RAMi。容器管理器解锁安全元件,并用它来封装生成的KRAMi。此时,容器管理器同时持有已封装和未封装的KRAMi。未封装的KRAMi被存储起来,以便在锁定或切换回C0时无需用户交互和安全元件即可立即加密Ci。相反,已封装的KRAMi则被保存,用于下次通过安全元件对Ci进行解密。接下来,容器管理器在前台启动Ci,使C0进入后台。因此,容器管理器创建Ci的命名空间,配置其控制组,并挂载其镜像。容器管理器还指定需要加密的段。启动Ci包括使用安全元件解封Ci的KDFEi,以为FDE模块提供密钥以访问已加密的数据镜像。这一部分在图10中被省略。

冻结 Ci 。当用户主动切换回C0,或当用户或系统锁定Ci导致切换回C0时,我们会冻结并加密Ci的RAM。根据图10,CM随后会暂停Ci并立即切换到C0。CM向冻结器提供存储的未封装的KRAMi,并启动Ci的冻结过程。这将触发F&C,对Ci进行加密。在此期间,CM从用户空间清除其存储的未封装的KRAMi。加密完成后,冻结器清除其在内核中使用的KRAMi并通知CM。然后CM清除用户空间和内核空间中不再需要的未封装的KFDEi。我们通过在RAM中覆写加密密钥并刷新相应缓存来销毁这些密钥。之后,CM仅保留已封装的KRAMi和KFDEi,在内存中不留任何Ci的易失性和持久性数据痕迹。内核内存中的所有机密资产均被删除,且未加密的段不包含任何机密信息。在其他使用场景中,管理加密的实体此时可进一步清除内核中存在的资产,例如IPSec的凭证(IPSec是一种内核级VPN模式)。

解冻Cii 。仅在启动和解冻Ci时,即在解密并将Ci切换至前台时,用户需要向可信图形用户界面提供SE的PIN。容器管理器使用SE解封已封装的KRAMi,并将未封装的KRAMi提供给冻结器。随后,容器管理器触发解冻操作。冻结器解密Ci,在内核中清除其使用的密钥,并通知容器管理器。然后,容器管理器恢复Ci,将其切换至前台。为简化说明,图10省略了容器管理器在解冻Ci之前还会解封已封装的KFDEi并将其提供给FDE模块的过程。容器管理器会保留其用户空间中的未封装KRAMi副本,以供下一次冻结使用。此时,容器管理器也可以生成一个新的未封装KRAMi及其对应的已封装版本,用于下一次冻结。这可以防止重放攻击交换已加密RAM的旧部分。然而,此类场景不在我们的攻击者模型范围内,我们认为该威胁可忽略不计。

5.3 后台活动

主应用处理器在休眠的智能手机上处于睡眠状态。对于后台活动,设备通过硬件组件和中断控制器维持与外部源的连接。当发生事件时(例如,在安卓操作系统中触发通知),主应用处理器以及相应的内核和进程将被唤醒。在我们的平台上,与常见移动设备类似,加密容器的传入事件由底层内核处理。由于本平台具备硬件设备虚拟化基础设施,内核会将所有传入事件转发给虚拟化组件。这使得这些组件能够在Ci处于非活动状态且已加密(直至下次解锁)的情况下,仍可处理冻结的Ci的后台活动。该平台在用户空间或直接在内核中对硬件设备进行虚拟化。通过扩展虚拟化组件,我们能够缓冲传入事件,并在未加密的C0中向用户发送通知。

用户空间虚拟化设备 。对于这类硬件设备,C0中的多路复用器为所有容器虚拟化设备功能。多路复用器在用户空间中虚拟化那些部分驱动功能实现在用户空间的设备,例如作为无线接口层(RIL)一部分的无线接口,或Wi-Fi功能。因此,我们的平台通过内核中的无线接口接收发往可能处于冻结状态的Ci的短消息和电话通话,并将其传递给C0中的多路复用器。这使得我们可以通过向多路复用器添加功能,以在C0内部通知用户有关冻结的Ci的事件。为此,我们可以在多路复用器中使用标准安卓通知意图,在C0的图形用户界面应用中触发通知。多路复用器必须缓冲Ci的数据,直到Ci解冻并处理这些数据,例如通过读取终止于C0的套接字。我们以无线接口为例验证了多路复用器的扩展功能。对于电话通话和短消息,用户可在C0中收到通知,并在Ci解冻后立即无缝接听来电或接收短消息。

内核空间虚拟化设备 。以相同的方式,可以在内核中为冻结的Ci处理虚拟化的硬件设备(如闹钟或网络设备)的数据。我们在内核中接收冻结的Ci的闹钟事件和传入的网络数据包,并将数据进行缓冲。我们可以使用UNIX域套接字使C0在其用户界面中发出通知。特别是,这使得能够可靠地向用户通知之前在冻结的Ci中设置的过期的计时器和闹钟。

完整的后台可操作性 。对于所有传入数据,我们可以在Ci中通知用户。我们可以使用多路复用器,根据传入数据为不同事件向用户显示特定的通知。实际上,仅在概念上限制了Ci的出站流量处理。出站流量可以是通过网络接口对传入消息的响应,或发送给远程网络服务器的保活数据包。在联网方面,应用程序主要使用谷歌云消息服务(GCM)基础设施,并且只有在设备向GCM回传时才会接收数据,例如即时消息。从远程实体的角度来看,这使得冻结的Ci看似暂时失去连接。不了解容器加密的远程服务会将其数据进行缓冲并发送当Ci报告回来时,这会导致虚拟化层无法获取进一步的传入网络事件。由于网络连接通常是端到端加密的,我们既无法检查在C0中接收到的明文数据,也无法代表Ci保持连接活动。为了实现完整的网络流量处理,我们可以在C0中虚拟化Ci的连接管理。但缺点是,这需要将相关的连接凭据以明文形式保存在C0中。由于这会使凭据容易受到内存攻击,因此此方案不可行。一种在内存攻击方面更安全的选择是利用远程后端,并在其中保存连接凭据的副本。例如,容器管理器(CM)可以将加密数据转发到该后端,由后端解密并解析端到端加密的数据。然后,后端可以通知CM具体的事件,并代表Ci处理远程连接,例如连接到GCM服务。相应地,CM可以在C0中触发一个Android意图,以通知用户任何正在进行的与网络相关的事件。这将使我们的原型具备完全的后台运行能力。然而,将敏感用户数据保留在后端可能引发隐私问题,因此仅建议用于完全由企业管控的容器,即企业容器。对于用户的个人容器,该方案不太适用。此外,这种方法会增加设备上的通信开销,并且实现该功能需要相对较高的实现工作量。因此,我们当前的解决方案是将所有使用的连接凭据安全地保留在全部冻结的Ci内部。这在功能性和安全性之间做出了一定的权衡。在解冻后,我们始终观察到应用程序的功能能够无缝继续,且应用程序能快速从远程服务恢复其数据。

6 性能与统计

在本节中,我们展示了在应用场景下,F&C对任务、VMA以及已加密页面的性能结果和统计数据。我们配置平台,在单个Linux 3.4内核(4KB页大小;与标准安卓相同,无交换分区或KSM)之上运行两个完整的安卓5.1.1容器,外加一个管理容器。这模拟了一个包含个人和企业域的真实场景。在评估过程中,我们有意对两个容器都进行加密,以通过多个大型控制组来考验F&C的能力。在一般使用情况下,仅加密处理企业机密的业务容器可能是更合适的选择,具有更高的可用性。我们遵循5.1小节中所述的加密段选择方法。

我们确定了若干测试用户,让他们在运行虚拟化架构的Nexus 5智能手机上使用F&C以生成统计数据(四核2.3 GHz Krait 400 CPU)。为了在手机上部署F&C,我们在设备重启后向用户提供了一个包含修改后的内核和虚拟化层的更新,以支持主内存加密。用户能够无缝地继续使用他们的两个容器及其数据和数十个应用程序,例如社交、企业、邮件或媒体应用程序。解冻的容器持续稳定运行,即使经过长时间冻结后也是如此。评估期间还包括一些具有挑战性的测试用例,涉及后台事件,例如用户在冻结的容器中达到内存限制或接听电话。通过这些测试用例,我们验证了F&C即使在系统处于高负载下也能可靠运行,手机仍然具有实际可用性,并且保持完全稳定。

为了收集统计数据,我们在F&C中引入了一种性能分析机制。我们扩展了原型,在加密过程中于内核中收集最重要的统计信息,例如加密持续时间、加密页面数量以及任务数量。该扩展在每次加/解密过程后将统计信息写入一个伪文件。这使得我们能够查询并记录每次加/解密过程的统计信息到文件中,并在评估阶段结束时从设备中提取这些数据。图11展示了测得的加/解密时间与页面数量之间的关系。黑色十字和灰色圆圈分别表示容器冻结和解冻的时间(单位为毫秒)。总共我们收集了超过730个容器加/解密样本,期间用户在智能手机上任意运行数量的应用程序,且持续时间不确定。运行的应用程序越多,存在的页面就越多,需要加密的页面也越多。平均而言,在四个可用核心上并行加密约142,500个页面,冻结耗时2,468毫秒,解冻耗时2,266毫秒。在极端情况下,当安卓低内存终止器被触发且容器耗尽其全部资源时,耗时大约增加到仍然可接受的4,000毫秒。当开始冻结Ci时,容器管理器会立即快速切换回C0[32]。这意味着用户若打算切换到另一个容器Cj,可以在Ci后台加密的同时,在C0中开始输入SE的密码短语。由于输入密码需要一定时间,因此切换操作的额外开销通常仅包括解冻Cj所需的时间。图11中的两条趋势线表明加密时间呈线性增长,并显示了解密速度比加密更快。这是合理的,因为在加密过程中存在额外的同步开销。方差来源于内核在此复杂系统中调度的各种不同事件和进程。测得的加密时间从写入冻结器状态文件的瞬间开始,直到用户空间接收到冻结器的通知为止。在此期间,性能主要取决于控制组内部的同步以及调度器的行为。

总之,我们的解决方案适用于需要保护敏感数据的日常使用环境。我们的原型设备在没有硬件加密加速器的情况下运行。我们预计,在利用硬件加密加速器的设备上,F&C的性能将有显著提升,例如在x86架构上可用的设备,或基于ARMv8架构的设备。

表1展示了我们收集的更多统计数据。在一个平均加密周期中,有1,043个任务正在运行,其中包括52个进程生成的991个线程。这表明控制组的规模较大,且用户正在运行许多应用程序。第二行显示,在冻结期间,52个加密任务识别出27,410个VMA,其中13,391个VMA需要进行加密。剩余的14,646个VMA代表非敏感段。冻结任务平均总共映射了约380,500个虚拟页面。当多个页表项指向同一个物理页面时,会出现大量重复页面。因此,加密的物理页面总数约为142,500个,平均明显更少,同时约有238,000个页面可以跳过。加密页面的平均数量约占内存的560 MB。最下面一行显示了加密页面在不同VMA中的分类情况。大多数页面属于文件支持段或匿名段。只有少量页面属于栈、堆、数据和文本段。因此,未来的改进方向是清零并解除文件支持段的映射,而不是对其进行加密。这虽然会带来一定的运行时性能开销,但影响可能几乎无法察觉,并能显著改善挂起和恢复性能。

为了测量F&C对功耗的影响,我们单独进行了功耗测量。额外的电池消耗取决于挂起和恢复容器的频率以及需要加密的内存量。在我们的测量中,我们在两个用户容器和管理容器之间自动切换,在100次循环中每10秒挂起和恢复一次,同时保持唤醒锁。我们在具有相同软件配置的设备上进行了有和没有F&C的对比测试。我们使用完全充电的新手机独立重复该实验5次。每次重复之前,我们启动了不同数量的应用程序,以测试从低到高主内存消耗的各种场景。为了能够自动在容器之间切换,我们调整了F&C以使用固定密钥。为了从用户空间跟踪电池消耗,我们使用了Linux内核提供的power supply class接口。我们测得没有F&C时平均电池消耗约为2.5%,而启用F&C时不超过4.0%。因此,在正常手机使用情况下,对功耗的影响很小。

7 安全评估

我们首先基于一个通用的进程组讨论F&C本身的安全性,然后将我们的考虑扩展到应用场景。根据第2节中的攻击者模型,我们假设攻击者在有足够时间的情况下,能够对无人看管或被盗的设备进行物理访问,从而访问其全部易失性内存。这使得攻击者能够获取并分析其完整的内存内容。此外,该攻击者可以控制系统的非挂起部分,从而同时掌控硬件和软件。

7.1 加密进程组

F&C使用CTR模式下的AES对RAM中选定内存段的页面进行加密,并使用每个页面的唯一物理地址作为IV。因此,相同的页面会以不同的结果被加密,由于攻击者无法破解密码学原语,加密后的页面不会泄露任何敏感信息。在加密一个控制组后,我们会清除冻结器中使用的密钥以及其他AES遗留物和已释放的页面。当用户空间中的密钥也被移除后,对手将无法解密受保护的页面。这意味着攻击者只能尝试从未加密的页面和段中获取敏感数据。F&C允许选择所有内存段进行加密,但那些极不可能包含机密数据的特殊段除外。对于已加密的段,我们仅保留与未加密且正在运行的进程共享的页面为未加密状态。当确保与其他进程共享敏感数据的进程被包含在冻结的控制组中时,我们不会留下任何一个敏感页面未加密。即使是一组较少的选定内存段,在了解系统上进程存储其敏感数据所在段的前提下,也可以覆盖所有敏感区域。

7.2 应用场景

关于我们的应用场景,攻击者的目标是获取容器在持久存储和随机存取存储器中的机密数据。平台本身的安全性,例如C0和容器管理器,已在[32]中讨论过。F&C在用户主动将容器切换到后台、锁定手机或设备空闲一段时间后,会对容器进行加密。基于此,我们讨论了设备已挂起、容器处于活动且解锁状态,以及容器已锁定但尚未完全挂起的场景。

挂起设备 。此攻击场景最为可能,因为智能手机大部分时间都处于挂起状态,这意味着容器已经处于已加密状态。在此场景中,攻击从设备完全挂起时开始。此时,除C0外的所有容器均已加密。容器不会与其他实体共享敏感数据,因为物理页的内存使用与容器边界相关联。由于我们对所有相关内存段进行了加密(参见第5节),因此完全覆盖了容器在随机存取存储器中的敏感数据。F&C会在内核中清除未封装的RAM加密密钥。持久内存始终由全盘加密进行加密,其中内核存储未封装的全盘加密密钥。

在我们的应用场景中,内核中的未封装FDE密钥和用户空间中的未封装RAM加密密钥是唯一未通过加密保护的资产。然而,在容器加密终止的时刻,容器管理器会清除这些未封装的密钥,从而防止攻击者解密任何持久性和易失性内存。封装密钥组件只能通过安全元件进行解封。攻击者可能拥有安全元件,但缺乏密码短语的知识,也无法对安全元件进行暴力破解。因此,封装的加密密钥可安全地存储在主内存中。这意味着我们不需要诸如CPU寄存器之类的特殊密钥存储。容器管理器仅在加密期间以及容器处于未加密状态时,将未封装的密钥对应物保留在RAM中。在此期间将未封装的密钥重定位(例如,到ARM TrustZone)并不会提高平台的安全性,因为敏感数据已经是明文。

由于拥有该设备,攻击者只能等待传入数据,例如短消息或网络流量。由于敏感数据通常是端到端加密的,并且加密在容器内部终止,因此攻击者无法解密这些数据。对于未加密的数据,例如短消息,在到达移动设备之前就可能被截获,这与内存加密无关。

我们通过以特权用户身份读取进程空间,并使用工具Volatility和冷启动攻击(如[20]中所述)分析锁定设备的内存转储,确保不会留下任何敏感数据。在普通设备上,我们能够轻松恢复大量敏感数据,例如Exchange账户密码、全盘加密密钥以及其他凭证。尽管了解这些敏感资产的存在,但我们无法在受F&C保护的设备上检测到任何敏感数据。在对系统进行取证分析期间列出进程时,会发现F&C甚至伪装了进程参数和环境变量,因为这些信息属于进程栈的一部分。

未锁定的前台容器 。在此场景中,我们假设受害者一直在使用某个容器,直到攻击开始的那一刻,例如在遭遇胁迫或暴力犯罪的情况下。在此期间,正在使用的容器不会被加密,直到系统触发挂起。当攻击者阻止容器自行锁定时,攻击者可以直接与容器交互并收集其所有数据,而无需进行内存攻击。通过内存攻击,攻击者能够读取未锁定的前台的明文内存加密密钥,但这并不会产生额外的攻击向量,因为其他容器是使用独立的临时随机密钥进行加密的。

关于冻结的后台容器,对手对其进程没有影响,内存内容不共享容器之间以及解密冻结容器页面的密钥不存在。因此,后台容器仍然受到安全保护。

Locked ForegroundContainer 。锁定的前台容器要么刚刚进入挂起状态,要么在经过一段空闲时间后即将挂起。与之前场景相同,后台容器仍受到安全保护。当挂起正在进行时,即使对于完全加载的容器,加密过程也会迅速终止,这一点已在第6节中进行了评估。这意味着,在此期间攻击者若获得设备控制权,想要提取有价值的明文数据或加密密钥的时间窗口极有可能不切实际。

设备尚未挂起容器的场景与之前的场景类似,不同之处在于前台容器已被锁定。攻击者可以持续与其屏幕锁应用交互,确保已锁定的前台容器永远不会被挂起。接下来,攻击者可以尝试利用软件层来访问未挂起的容器,或尝试进行内存攻击以获取容器的数据或其内存加密密钥。通过配置容器在短时间内无活动后即进入挂起状态,可降低此场景发生的可能性。

7.3 讨论

攻击者能够在设备所有者不在场的情况下对其内存加密设备进行篡改,这不在我们的攻击者模型范围内。这种情况包括能够未被察觉地获得完全权限或未被察觉地重放内存内容的攻击者,例如通过执行writing内存攻击。正如我们在相关工作部分指出的,这种模型尤其难以防御,需要在软硬件层面攻击方面具备额外的抗篡改能力。对于运行时内存加密技术而言,它们会透明地加密主内存,并可能保留一部分RAM工作集为未加密状态,在此场景下,攻击者将能够立即提取所有敏感数据,因为容器仍保持完全可操作状态,并可在任意时刻恢复运行。攻击者可以等待主应用程序处理器将敏感内存加载到未加密的RAM工作集中,或者直接利用已获取的权限读取内存。我们基于容器挂起的加密方法具有如下优势:容器无法在合法用户

您可能感兴趣的与本文相关内容

【电能质量扰动】基于ML和DWT的电能质量扰动分类方法研究(Matlab实现)内容概要:本文研究了一种基于机器学习(ML)和离散小波变换(DWT)的电能质量扰动分类方法,并提供了Matlab实现方案。首先利用DWT对电能质量信号进行多尺度分解,提取信号的时频域特征,有效捕捉电压暂降、暂升、中断、谐波、闪变等常见扰动的关键信息;随后结合机器学习分类器(如SVM、BP神经网络等)对提取的特征进行训练分类,实现对不同类型扰动的自动识别准确区分。该方法充分发挥DWT在信号去噪特征提取方面的优势,结合ML强大的模式识别能力,提升了分类精度鲁棒性,具有较强的实用价值。; 适合人群:电气工程、自动化、电力系统及其自动化等相关专业的研究生、科研人员及从事电能质量监测分析的工程技术人员;具备一定的信号处理基础和Matlab编程能力者更佳。; 使用场景及目标:①应用于智能电网中的电能质量在线监测系统,实现扰动类型的自动识别;②作为高校或科研机构在信号处理、模式识别、电力系统分析等课程的教学案例或科研实验平台;③目标是提高电能质量扰动分类的准确性效率,为后续的电能治理设备保护提供决策依据。; 阅读建议:建议读者结合Matlab代码深入理解DWT的实现过程特征提取步骤,重点关注小波基选择、分解层数设定及特征向量构造对分类性能的影响,并尝试对比不同机器学习模型的分类效果,以全面掌握该方法的核心技术要点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值