“逻辑”布局是呈现给基础 CSP/KSP 的数据布局。 此布局使用更易于人类阅读的名称,文件可能无法一一对应卡片所用物理布局中的文件。
文件命名要求
文件名由最多 8 个 ANSI 字符(8 位)组成,不包括 Windows 文件和目录命名约定不允许的字符。 目录结构由两个级别组成:根目录和应用程序使用的目录。 目录名称由最多 8 个 ANSI 字符组成。 若要生成不区分大小写的文件名和目录名称,卡微型驱动程序实现应将字符串转换为小写。
文件命名虚拟化
允许在卡片微型驱动程序中实现虚拟文件系统,以便将目录和文件映射到卡上的相应位置。 不允许在正常操作中进行写入的卡片(如身份证)可以模拟写入操作,但在卡片插入期间必须保留“写入”的任何文件,并且在读取时必须返回这些文件。
物理卡片数据布局
有关卡上的文件的以下信息概述了卡和文件系统的使用方式。 不应通过了解这些文件或其内容来设计卡微型驱动程序。 卡微型驱动程序应编写为通用接口层。
逻辑数据布局
卡片标识符
卡标识符是卡的唯一标识符。 它可能以某种形式表示给 UI 中的用户,但否则仅用于与引用值进行比较来建立卡片的标识。 为用户准备卡片时,会分配此值。 它组织为字节数组。
文件名
此文件的逻辑名称为“CardId”。 它位于根目录中。
访问条件
此文件的访问条件为 E(R)、U(R)和 A(RW)。
内容
该文件组织为 16 字节数组。 它应被视为不透明的二进制数据。
备注
此值由Microsoft软件分配,以确保为卡片生成唯一值。 它与在制造期间可能会或可能不会分配给卡的序列号无关。
应用程序目录
应用程序目录文件由固定长度的应用程序名称条目列表组成。 应用程序目录名称是包含所有应用程序的文件的逻辑子目录的名称。 对于使用 CAPI2 的应用程序,名称为“mscp”,其索引值为零。
逻辑名称
此文件的逻辑名称为“cardapps”。 它位于根目录中。
访问条件
此文件的访问条件为 E(R)、U(RW)和 A(RW)。
内容
该文件组织为一系列记录,每条记录包含一个字节索引,后接以零结尾的应用程序名称字符串(ANSI)。
备注
应用程序的实施要求应用程序名称映射到卡片上的唯一目录,并映射到卡片缓存文件中应用程序数据的唯一索引。 卡片应用程序目录允许应用程序在缓存文件中查找其索引值,方法是在应用程序目录中查找其名称,并指出发生此情况的位置的索引。 该文件包含一个包含应用程序名称的 8 个字节记录,末尾填充零。 应用程序名称可以使用所有 8 个字节,因此不需要将生成的字符串设置为零终止。 因此,“创建”卡的文件内容为以下 8 个字节:
{‘mscp’,0,0,0,0}
缓存文件
为了提高性能并减少与卡的通信,基本 CSP/KSP 可以通过各种方式缓存卡数据。 缓存文件用于通过指示卡上的数据版本号来控制基础 CSP/KSP 中缓存子系统的作。 更改数据后,此值将递增。 将缓存文件的内部副本与从卡中读取的版本进行比较,可让基础 CSP/KSP 确定是否可以使用缓存数据,还是必须刷新。 出于多种原因(包括撤回和重新插入卡)可能需要做出这种决定。
从卡读取卡标识符和缓存文件应该完全足以允许使用在主机上缓存了不确定时间段内的信息。
逻辑名称
此文件的逻辑名称为“CardCF”。 它位于根目录中。
访问条件
此文件的访问条件为 E(R)、U(RW)和 A(RW)。
内容
该文件将全局数据组织为2字节值形式,然后是一系列由应用程序维护和解释的32位缓存值。 第一个保留供基本 CSP/KSP 使用。 此后,每个应用程序都会分配一个 DWORD。
typedef struct _CARD_CACHE_FILE_FORMAT
{
BYTE bVersion; // Cache version
BYTE bPinsFreshness; // Card PIN
WORD wContainersFreshness;
WORD wFilesFreshness;
} CARD_CACHE_FILE_FORMAT, *PCARD_CACHE_FILE_FORMAT;
备注
如果应用程序内部的缓存数据副本指示感兴趣的数据的版本号不同于从卡读取的文件,则会刷新应用程序的内部缓存。 通常在每笔信用卡交易的开始,会检查缓存。
每个缓存应用程序都有一个应用程序缓存数据 DWORD 的数组,该数组通过应用程序目录文件中的应用程序索引进行索引。 添加应用程序后,文件以 4 字节增量增长。
容器映射文件
容器映射文件由基础 CSP/KSP 拥有,包含多个 CONTAINERMAPRECORD 类型的记录。 这些记录关联容器标识符,该标识符通常是 CAPI 分配给可用于访问该容器的密钥和证书的索引的 GUID。
文件中记录的位置(索引)对应于与该容器关联的证书和密钥信息的索引。 因此,此类文件中的第二条记录的索引值从零开始,为 1。
与此容器关联的证书以及容器的签名和/或密钥交换密钥都共享此索引(UserCerts\SignatureCert1、SignatureKey1 等)。 记录包含与该索引关联的键的容器 GUID 和大小信息。
逻辑名称
此文件的逻辑名称为“CMapFile”。 它位于“mscp”目录中。
访问条件
此文件的访问条件为 E(R)、U(RW)和 A(RW)。
内容
此文件的访问条件为 E(R)、U(RW)和 A(RW)。
备注
此文件由基本 CSP/KSP 创建及其内容也由其维护。 提供有关此文件的内部结构的信息仅供参考。 文件中的记录采用以下格式:
CONTAINERMAPRECORD
这些记录包含 CAPI 分配的容器 GUID 以及与该容器关联的关联密钥交换或签名密钥的密钥大小。 所有 WORD 字段都是 little-Endian 字节顺序。
//
// Type: CONTAINER_MAP_RECORD
//
// This structure describes the format of the Base CSP's
// container map file, stored on the card. This is well-known
// logical file wszCONTAINER_MAP_FILE. The file consists of
// zero or more of these records.
//
#define MAX_CONTAINER_NAME_LEN 39
// This flag is set in the CONTAINER_MAP_RECORD bFlags
// member if the corresponding container is valid and currently
// exists on the card. // If the container is deleted, its
// bFlags field must be cleared.
#define CONTAINER_MAP_VALID_CONTAINER 1
// This flag is set in the CONTAINER_MAP_RECORD bFlags
// member if the corresponding container is the default
// container on the card.
define CONTAINER_MAP_DEFAULT_CONTAINER 2
typedef struct _CONTAINER_MAP_RECORD
{
WCHAR wszGuid [MAX_CONTAINER_NAME_LEN + 1];
BYTE bFlags;
BYTE bReserved;
WORD wSigKeySizeBits;
WORD wKeyExchangeKeySizeBits;
} CONTAINER_MAP_RECORD, *PCONTAINER_MAP_RECORD;
wszGuid 成员由 CAPI 分配给容器的标识符的 UNICODE 字符串表示形式组成。 这通常是 GUID 字符串,但并非总是如此。 标识符名称不能包含特殊字符“\”。 预配只读卡片时,预配过程必须遵循标识符名称的相同准则。
容器名称必须以 null 结尾,并且长度不得大于(MAX_CONTAINER_NAME_LEN + 1)字符,包括 NULL 终止符。
如果必须从此表中删除记录,则通过向记录写入零来使条目失效。 以后,新数据可以覆盖此类记录。 该表未“打包”以删除非活动条目。
以下位对 Flags 字节有效:
- 当容器记录有效时,比特位 0 会被设置。
- 默认容器时,位 1 被设置。 容器映射中同时只有一条记录可以设置此位。 仅当还设置了位 0 时,才能设置此位。 换句话说,不能有无效的默认容器。 所有其他比特位目前都保留用于卡微型驱动程序的未来修订。
- 对于默认容器,这会转换为字节0x03。 对于不是默认值的有效容器,此值0x01。
- 位 2-7 保留供将来使用。
数据布局摘要
下表汇总了卡片微驱动程序和基本 CSP/KSP 间接口中的数据结构,用于典型实现中的应用。 “逻辑名称”是基础 CSP/KSP 用来与卡微型驱动程序通信的字符串;它可能直接映射至卡片上的相应元素,也可能不与该元素直接映射。
请注意,证书和密钥按基本 CSP/KSP 按其用途按逻辑分组为子目录,只需使用实际文件名的索引。 添加到卡的任何证书或密钥都根据其目录中的索引号进行命名。 为了说明目的,下表显示了一些示例证书和密钥。
目录名称 | 文件名 | 类型 | 访问条件 | 注释 |
---|---|---|---|---|
<根> | cardid | 文件 | E(R) U(R) A(RW) | 卡片标识符 |
<根> | cardcf | 文件 | E(R) U(RW) A(RW) | 缓存文件 |
<根> | 卡片应用程序 | 文件 | E(R) U(R) A(RW) | 按应用程序名称编制目录索引。 有关详细信息,请参阅“应用程序目录”。 |
mscp | 迪尔 | E(R) U(RW) A(RW) | 基本 CSP/KSP 应用目录 | |
mscp | cmapfile | 文件 | E(R) U(RW) A(RW) | 要编制索引的 CAPI GUID |
mscp | kxc00 | 文件 | E(R) U(RW) A(RW) | (示例) 密钥交换证书 0 |
mscp | ksc00 | 文件 | E(R) U(RW) A(RW) | (示例) 密钥签名证书 0 |
mscp | ksc01 | 文件 | E(R) U(RW) A(RW) | (示例) 密钥签名证书 1 |
mscp | msroots | 文件 | E(R) U(RW) A(RW) | 企业受信任的根 |
注意 与 msroots 的互作性:mscp\msroots 文件是 PKCS #7 格式的证书存储。
文件访问控制
已知主体
已知主体标识符是用于识别可以尝试以某种方式访问卡数据的各种类型用户的标识符。 下表显示了有效的授权主体,其缩写为单个字母,可以与数据访问操作标识符一起使用以定义访问条件。 虽然可能有更多可识别的主体,但列表仅限于那些对基础 CSP/KSP 与卡微型驱动程序之间的通信有意义的主体。
名称 | DESCRIPTION | 记忆 | PIN_ID映射 |
---|---|---|---|
所有人 | 任何请求者,包括未经身份验证的(或匿名)用户。 | E | ROLE_EVERYONE (0) |
用户 | 卡片的用户客户端,通过使用 PIN 向卡证明其身份。 | U | ROLE_USER (1) |
管理员 | 与卡上的卡或数据具有管理关系的卡颁发者或其他方。 使用特殊的 PIN 或 KEY(可能对卡或用户不唯一)执行用户无法在不使用此数据的情况下执行的管理任务,例如解锁 PIN。 | 一个 | ROLE_ADMIN (2) |
在以下讨论中使用“每个人”时,通常意味着卡片的任何用户(无论是否经过身份验证)。 例如,“每个人都可以读取文件”,这意味着用户或管理员可以自动读取该文件。
对于文件系统访问,管理员通常被视为“超级用户”,并且拥有与用户相同的所有权限(执行权限除外)。
目录访问条件
主体可以使用两组权限在卡片文件系统中创建目录。 下表汇总了每个权限的效果。
目录访问条件 | 含义 |
---|---|
用户创建删除目录权限 | 用户和管理员可以使用 CardCreateFile 在目录中创建文件。 用户和管理员可以通过调用 CardDeleteDirectory 删除目录(如果目录不为空)。 每个人都可以使用 CardEnumFiles 列出目录的内容。 |
管理员创建删除目录操作 | 管理员可以使用 CardCreateFile 在目录中创建文件。 管理员可以使用 CardDeleteDirectory 删除目录。 每个人都可以使用 CardEnumFiles 列出目录的内容。
注意 此 ACL 是可选的。 它可以从智能卡微型驱动程序规范的未来修订中删除。
|
注意 创建目录时,每个人都自动有权列出目录中的文件。 目录没有单独的“列表”权限。
文件访问操作
主体可以通过多种方式使用文件的内容。 下表中列出了有效操作,其中包含一个字母缩写,可以作为与主要指示符一起使用,并且用于定义访问条件。 具体而言,请注意,Execute(X)与其他文件访问操作之间没有逻辑关系,它是一个独立的操作。
操作/权限 | DESCRIPTION | 记忆 |
---|---|---|
读取 | 直接或采用格式化或已处理的形式接收文件的内容。 |
R |
写入 | 更改文件的内容、可能创建文件或删除、替换或更改现有数据。 |
W |
执行 | 将文件内容用于卡片代表请求者执行的操作,而无法接收已使用的数据或可行地获取它。 |
X |
文件访问条件
访问条件类似于 ACL。 访问条件控制哪些主体可以访问给定文件,以及他们可以执行哪些操作。 卡上的每个文件都有一个访问条件,可通过主体列表及其访问权限来描述。 如果说明中不包含主体或特权,则假定拒绝该主体或特权。 通常情况下,访问条件是在卡上执行的。
下表列出了通过 CardCreateFile 提供的访问条件,并将它们映射到相应的访问条件助记符。
文件访问条件 | 实际含义 | 访问条件助记符 |
---|---|---|
InvalidAc | 检索 ACL 时出错。 |
|
EveryoneReadUserWriteAc | 这意味着每个人都可以读取文件或获取文件信息(CardReadFile 或 CardGetFileInfo),用户和管理员可以读取文件、写入文件并删除文件。 |
E(R)、U(RW)、A(RW) |
UserWriteExecuteAc | 用户可以写入文件,可以“执行”文件,并可以删除该文件。 没有人(包括用户)可以读取文件的内容。 管理员还可以写入此文件的内容,但不能执行该文件,并且可以删除该文件。 |
U(WX) A(W) |
EveryoneReadAdminWriteAc (任何人可读,管理员可写) | 这意味着每个人都可以读取文件或获取文件信息(CardReadFile 或 CardGetFileInfo),但只有管理员才能写入文件并删除该文件。 |
E(R)、U(R)、A(RW) |
UnknownAc | 该文件受卡上的访问条件(AC)保护,其不属于预定义的 AC 类型之一。 |
|
UserReadWriteAc | 每个人都无法访问 // 用户读取写入 // // 示例:密码钱包文件 |
U(RW),A(RW) |
AdminReadWriteAc | 每个人/用户无访问权限 管理员读取写入 // 示例:管理数据。 |
A(RW) |
下表列出了常见项的一些示例访问条件。
访问条件 | DESCRIPTION |
---|---|
E(X) U(W) A(W) | 这是用户 PIN 的访问条件。 当需要 PIN 的操作开始时,用户是身份不明的。 必须“执行”PIN 才能建立用户的标识。 输入 PIN 后,用户的标识将从 E 升级到 U。用户和管理员都可以编写 PIN。 |
U(WX) A(W) | 用户的私钥文件可能永远不会从卡中读取,并且只有用户才能将其内容用于加密作。 用户或管理员可能会更改此数据。 |
E(R) U(R) A(RW) | 卡片标识符。 |
有关目录和文件访问条件的说明
- 主体需要对文件具有读取访问权限,以便 CardGetFileInfo 成功。
- 没有单独的列表权限用于列出目录的内容。
- “在目录中创建访问权限”意味着有权在目录中创建文件,而“删除目录上的访问权限”意味着有权删除目录本身。 若要删除文件,卡片主体必须具有对文件本身的写入访问权限。
- 无法通过智能卡微型驱动程序接口创建具有 E(W) 权限的目录。
- 无法通过智能卡微型驱动程序界面更改文件或目录权限,而无需删除和重新创建文件或目录。
- 无法通过智能卡微型驱动程序界面创建由管理员或未经身份验证的用户拥有的私钥文件。
- 无法通过智能卡微型驱动程序接口在卡(E(X)、U(W)和 A(W)上创建 PIN 文件。
- 无法通过智能卡微型驱动程序接口查询目录访问条件。
- 只能通过智能卡微型驱动程序接口创建具有可用访问条件组合子集的文件。