Solaris 开发者安全性指南

第 8 章 Solaris 加密框架介绍

Solaris 加密框架是一种体系结构,可使 Solaris 操作系统中的应用程序使用或提供加密服务。所有与框架的交互都基于 RSA Security Inc. 的 PKCS#11 加密令牌接口 (Cryptographic Token Interface, Cryptoki)。PKCS#11 是 RSA Laboratories(RSA Security Inc. 的研究机构)开发的一种产品。本章介绍 Solaris 加密框架的以下主题:

Solaris 加密术语

获取加密服务的应用程序、库或内核模块称作消费方,通过加密框架向消费方提供加密服务的应用程序称作提供者,或称作插件。用来实现加密操作的软件称作机制。机制不只是算法,还包括算法的应用方式。例如,应用于验证机制的 DES(数据加密标准)算法被视为一个单独的机制,应用于逐块加密的 DES 则是另一个机制。

令牌是可以执行加密的设备的抽象术语。此外,令牌可以存储要用在加密操作中的信息。一个令牌可以支持一个或多个机制。令牌可以代表硬件,例如加速器板中的部件。仅代表软件的令牌称作软令牌。令牌可以插入插槽中,插槽也是一种物理比喻。插槽是使用加密服务的应用程序的连接点。

除了提供者的特定插槽以外,Solaris 实现还提供一个名为元插槽的特殊插槽。元插槽是 Solaris 加密框架库 (libpkcs11.so) 的一个组件。元插槽充当一个虚拟插槽,它具有框架中安装的所有令牌和插槽的组合功能。实际上,元插槽使应用程序通过单个插槽与任何可用的加密服务透明地连接。当应用程序请求加密服务时,元插槽将指向最适合的插槽,这简化了插槽的选择过程。在某些情况下可能需要一个不同的插槽,此时,应用程序必须显式地执行单独的搜索。元插槽由系统自动启用,而且只能由系统管理员通过显式的操作来禁用。

会话是令牌与使用加密服务的应用程序之间的连接。PKCS #11 标准使用两种对象:令牌对象和会话对象。会话对象是暂时的对象,即它只在会话期间存在。在会话结束之后仍存在的对象称作令牌对象

令牌对象的缺省位置是 $HOME/.sunw/pkcs11_softtoken。或者,可以将令牌对象存储到 $SOFTTOKEN_DIR/pkcs11_softtoken 中。专用令牌对象由个人识别码 (personal identification numbe, PIN) 保护。要创建或更改令牌对象,需要对用户进行验证,除非用户访问的是专用令牌对象。

加密框架概述

加密框架是 Solaris OS 的一部分,它提供 Sun Microsystems, Inc. 和各个第三方供应商的加密服务。加密框架提供以下各种服务:

下图提供了加密框架的概述。该图中的浅灰色阴影表示加密框架的用户级部分,深灰色阴影表示加密框架的内核级部分,带有斜条纹的背景表示专用软件部分。

图 8–1 Solaris 加密框架概述

该图显示 Solaris 加密框架中的主要元素。

加密框架的组件

加密框架的组件如下所述:

加密开发者需要了解的内容

本节介绍可插入到 Solaris 加密框架中的四种应用程序的开发要求。

用户级消费方的开发要求

要开发用户级消费方,开发者需要牢记以下几点:

有关更多信息,请参见第 9 章,编写用户级加密应用程序和提供者

用户级提供者的开发要求

要开发用户级提供者,开发者需要牢记以下几点:

内核级消费方的开发要求

要开发内核级消费方,开发者需要牢记以下几点:

内核级提供者的开发要求

要开发内核级提供者,开发者需要牢记以下几点:

避免在用户级提供者中出现数据清除冲突

插入到加密框架中的用户级库应当提供 _fini() 函数。卸载用户级库时,装入器会调用 _fini() 函数。_fini() 函数是确保所有的清除操作都在恰当的时间正确完成所必需的。系统不假设那些使用 libpkcs11 的库调用 C_Finalize(),因为 libpkcs11 是共享库,有可能正由应用程序使用。

要提供 _fini() 函数,需要在可重定位对象的程序数据部分中创建一个 .fini 部分。.fini 部分提供运行时终止代码块。请参见《链接程序和库指南》。以下代码样例演示了如何设计 .fini 部分。


示例 8–1 向 PKCS #11 库提供 _fini()

#pragma fini(pkcs11_fini)

static void pkcs11_fini();



/* [... (other library code omitted)] */



static void

pkcs11_fini()

{

        (void) pthread_mutex_lock(&pkcs11mutex);

        

        /* If CRYPTOKI is not initialized, do not clean up */

        if (!initialized) {

                (void) pthread_mutex_unlock(&pkcs11mutex);

                return;

        }

        

        (void) finalize_routine(NULL_PTR);

        

        (void) pthread_mutex_unlock(&pkcs11mutex);

}