9. 保护 CoAP
本节定义 CoAP 的 DTLS 绑定.
在 provisioning phase 中, CoAP 设备会被配置其所需的安全信息, 包括 keying materials 和 access control lists. 本规范在 Section 9.1.3.2.1 中定义 RawPublicKey 模式的 provisioning. 在 provisioning phase 结束时, 设备将处于四种 security modes 之一, 并具有该模式所需的如下信息. 对于本规范, NoSec 和 RawPublicKey 模式是 mandatory to implement.
NoSec: 没有协议级安全性 (DTLS 被禁用). 在适当时 SHOULD 使用替代技术提供较低层安全性. [IPsec-CoAP] 讨论了 IPsec 的使用. 与受限节点一起使用的某些链路层也提供链路层安全性, 在具备适当密钥管理时可能适用.
PreSharedKey: DTLS 被启用, 存在预共享密钥 [RFC4279] 列表, 并且每个密钥都包含可用该密钥与哪些节点通信的列表, 如 Section 9.1.3.1 所述. 在极端情况下, 此 CoAP 节点需要通信的每个节点可以各有一个密钥 (1:1 node/key ratio). 反过来, 如果两个以上实体共享某个特定预共享密钥, 该密钥只能使这些实体以该组成员身份进行认证, 而不能以特定对等方身份进行认证.
RawPublicKey: DTLS 被启用, 设备具有一个无证书的非对称密钥对 (raw public key), 该密钥对使用 out-of-band 机制 [RFC7250] 进行验证, 如 Section 9.1.3.2 所述. 设备还具有一个由公钥计算出的 identity, 以及可与之通信的节点 identities 列表.
Certificate: DTLS 被启用, 设备具有一个带有 X.509 certificate [RFC5280] 的非对称密钥对, 该证书将密钥对绑定到其 subject, 并由某个公共 trust root 签名, 如 Section 9.1.3.3 所述. 设备还具有一个 root trust anchors 列表, 可用于验证证书.
在 "NoSec" 模式中, 系统只是通过普通 UDP over IP 发送分组, 并由 "coap" scheme 和 CoAP 默认端口指示. 系统的安全性仅依赖于阻止攻击者在包含 CoAP 节点的网络上发送或接收分组. 关于这种方法的额外复杂性, 见 Section 11.5.
其他三种 security modes 使用 DTLS 实现, 并由 "coaps" scheme 和 DTLS-secured CoAP 默认端口指示. 其结果是一个 security association, 可用于在安全模型限制内进行认证, 并基于该认证对通信伙伴授权. CoAP 本身不提供用于认证或授权的协议原语. 如果需要这些能力, 可以由 communication security (即 IPsec 或 DTLS) 提供, 或由 object security (在 payload 内) 提供. 对某些操作需要授权的设备预计会要求这两种安全形式之一. 必然地, 在涉及 intermediary 时, communication security 只有在该 intermediary 属于信任关系的一部分时才有效. CoAP 不提供把客户端可能与某个 intermediary 之间具有的不同授权级别转发给后续 intermediaries 或 origin servers 的方式, 因此可能需要在第一个 intermediary 处执行所有授权.
9.1. DTLS 保护的 CoAP
正如 HTTP 使用 TCP 之上的 Transport Layer Security (TLS) 来保护一样, CoAP 使用 UDP 之上的 Datagram TLS (DTLS) [RFC6347] 来保护 (见 Figure 13). 本节定义 CoAP 到 DTLS 的绑定, 以及适合受限环境的最小 mandatory-to-implement 配置. 该绑定通过相对于单播 CoAP 的一系列差异来定义. 在实践中, DTLS 是 TLS 加上用于处理 UDP 传输不可靠特性的功能.
+----------------------+
| Application |
+----------------------+
+----------------------+
| Requests/Responses |
|----------------------| CoAP
| Messages |
+----------------------+
+----------------------+
| DTLS |
+----------------------+
+----------------------+
| UDP |
+----------------------+
Figure 13: Abstract Layering of DTLS-Secured CoAP
在某些受限节点 (flash 和/或 RAM 有限) 和网络 (带宽有限或有高可扩展性要求) 中, 并且取决于所使用的具体 cipher suites, 并非所有 DTLS 模式都适用. 某些 DTLS cipher suites 可能显著增加实现复杂度, 以及在建立 security association 时所需的初始握手开销. 初始握手完成后, DTLS 为每个 datagram 增加约 13 bytes 的有限开销, 这不包括任何 initialization vectors/nonces (例如 TLS_PSK_WITH_AES_128_CCM_8 [RFC6655] 中的 8 bytes), integrity check values (例如 TLS_PSK_WITH_AES_128_CCM_8 [RFC6655] 中的 8 bytes), 以及 cipher suite 所需的 padding.
对于基于 CoAP 的应用, 是否适用某种给定的 DTLS 模式应结合可能适用的具体 cipher suites, session maintenance 是否与应用流兼容, 以及受限节点和新增网络开销是否有足够资源来仔细权衡. (对于使用 DTLS 的某些模式, 本规范标识了 mandatory-to-implement cipher suite. 这是为了在这些 cipher suites 确实适用的情形中最大化互操作性的实现要求. 应用的具体安全策略可以决定实际可用的 cipher suites 集合.) DTLS 不适用于 group keying (组播通信). 但是, 它可以成为未来 group key management protocol 的一个组件.
9.1.1. 消息层
充当 CoAP 客户端的端点也应充当 DTLS 客户端. 它应在适当端口上向服务器发起 session. 当 DTLS handshake 完成后, 客户端可以发起第一个 CoAP 请求. 所有 CoAP 报文 MUST 作为 DTLS "application data" 发送.
为将 Acknowledgement message 或 Reset message 与 Confirmable message 匹配, 或将 Reset message 与 Non-confirmable message 匹配, 增加以下规则: DTLS session MUST 相同, 且 epoch MUST 相同.
当一个报文在同一 DTLS session 和同一 epoch 中发送, 并具有相同 Message ID 时, 它就是同一个报文.
注意: 当 Confirmable message 被重传时, 每次尝试都会使用新的 DTLS sequence_number, 即使 CoAP Message ID 保持不变. 因此接收方仍必须按 Section 4.5 中所述执行去重. 重传 MUST NOT 跨 epoch 执行.
RawPublicKey 和 Certificate 模式中的 DTLS 连接使用 mutual authentication 建立, 因此可以保持打开并复用于任一方向的未来报文交换. 设备在需要回收资源时可以关闭 DTLS 连接, 但一般而言应尽可能长时间保持连接打开. 每次 CoAP 报文交换后都关闭 DTLS 连接非常低效.
9.1.2. 请求/响应层
为将响应与请求匹配, 增加以下规则: DTLS session MUST 相同, 且 epoch MUST 相同.
这意味着对 DTLS 保护请求的响应 MUST 始终使用同一 security session 和 epoch 进行 DTLS 保护. 任何向 DTLS 请求提供 NoSec 响应的尝试都不能匹配该请求, 因此 MUST 被拒绝 (除非它确实匹配某个无关的 NoSec 请求).
9.1.3. 端点身份
设备 SHOULD 支持 Server Name Indication (SNI), 以在 [RFC6066] Section 3 定义的 SNI HostName 字段中指示其 authority. 这是必要的, 这样当一个充当多个 Authorities 的虚拟服务器的主机收到新的 DTLS 连接时, 它就知道应为该 DTLS session 使用哪些密钥.
9.1.3.1. 预共享密钥
在与新节点建立连接时, 系统根据它试图到达哪些节点来选择适当密钥, 然后使用 DTLS 的 PSK (Pre-Shared Key) 模式建立 DTLS session. 这些模式中的实现 MUST 支持 [RFC6655] 中规定的 mandatory-to-implement cipher suite TLS_PSK_WITH_AES_128_CCM_8.
根据 commissioning model, 应用可能需要为 identity hints 定义 application profile (如 [RFC4279] Section 5.2 所要求并详细说明的), 以启用 PSK identity hints 的使用.
[RFC4279] Section 7 的安全考虑适用. 特别是, 应用应仔细权衡它们是否需要 Perfect Forward Secrecy (PFS), 并选择适当的 cipher suite ([RFC4279] Section 7.1). PSK 的熵必须足以缓解 brute-force 攻击, 以及在 PSK 不是随机选择而是由人选择时缓解 dictionary attacks ([RFC4279] Section 7.2). 客户端 identities 的明文通信可能泄露数据或损害隐私 ([RFC4279] Section 7.3).
9.1.3.2. 原始公钥证书
在此模式中, 设备具有非对称密钥对, 但没有 X.509 certificate (称为 raw public key). 例如, 非对称密钥对由制造商生成并安装在设备上 (另见 Section 11.6). 设备 MAY 配置多个 raw public keys. raw public key 的类型和长度取决于所使用的 cipher suite. RawPublicKey 模式中的实现 MUST 支持 [RFC7251], [RFC5246] 和 [RFC4492] 中规定的 mandatory-to-implement cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8. 所用密钥 MUST 能用于 ECDSA. 曲线 secp256r1 MUST 被支持 [RFC4492]. 该曲线等价于 NIST P-256 曲线. 哈希算法为 SHA-256. 实现 MUST 使用 Supported Elliptic Curves 和 Supported Point Formats Extensions [RFC4492]. 未压缩点格式 MUST 被支持. [RFC6090] 可用作实现方法. 与实现该 cipher suite 相关的一些指导可见 [W3CXMLSEC]. 在 TLS 中使用 raw public keys 的机制由 [RFC7250] 规定.
实现说明: 具体而言, 这意味着 Figure 14 中列出的 extensions 将以至少所列的值出现在 DTLS handshake 中.
Extension: elliptic_curves Type: elliptic_curves (0x000a) Length: 4 Elliptic Curves Length: 2 Elliptic curves (1 curve) Elliptic curve: secp256r1 (0x0017)
Extension: ec_point_formats Type: ec_point_formats (0x000b) Length: 2 EC point formats Length: 1 Elliptic curves point formats (1) EC point format: uncompressed (0)
Extension: signature_algorithms Type: signature_algorithms (0x000d) Length: 4 Data (4 bytes): 00 02 04 03 HashAlgorithm: sha256 (4) SignatureAlgorithm: ecdsa (3)
Figure 14: DTLS Extensions Present for
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
9.1.3.2.1. 配置
RawPublicKey 模式被设计为易于在 M2M 部署中进行 provisioning. 假定每个设备都安装了适当的非对称公钥对. 端点按 [RFC6920] Section 2 中的描述从公钥计算出一个 identifier. 所有支持检查 RawPublicKey identities 的实现 MUST 至少支持 sha-256-120 模式 (SHA-256 截断为 120 bits). 实现 SHOULD 也支持更长长度的 identifiers, 并 MAY 支持更短长度. 注意, 更短长度提供的抗攻击安全性更低, 因此其使用 NOT RECOMMENDED.
根据 identifiers 如何提供给验证它们的系统, 需要实现对 URI, binary 和/或 human-speakable format [RFC6920] 的支持. 所有实现 SHOULD 支持 binary mode, 具有用户界面的实现 SHOULD 也支持 human-speakable format.
在 provisioning 期间, 会收集每个节点的 identifier, 例如通过读取设备外部的条形码, 或通过获得预编译的 identifiers 列表. 然后这些 identifiers 被安装到相应端点中, 例如 M2M 数据收集服务器. identifier 有两个用途: 将端点与进一步的设备信息关联, 以及执行访问控制. 在 (初始和持续的) provisioning 期间, 还 SHOULD 安装并维护一个 identifiers 的 access control list, 该列表指示设备可以与哪些 identifiers 启动 DTLS sessions.
9.1.3.3. X.509 证书
Certificate Mode 中的实现 MUST 支持 [RFC7251], [RFC5246] 和 [RFC4492] 中规定的 mandatory-to-implement cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8. 也就是说, 证书包含 SubjectPublicKeyInfo, 其指示算法为带 namedCurves secp256r1 的 id-ecPublicKey [RFC5480]. 公钥格式为 uncompressed [RFC5480]. 哈希算法为 SHA-256. 如果包含 key usage extension, 则其指示 digitalSignature. 证书 MUST 使用 secp256r1 以 ECDSA 签名, 且签名 MUST 使用 SHA-256. 所用密钥 MUST 能用于 ECDSA. 曲线 secp256r1 MUST 被支持 [RFC4492]. 该曲线等价于 NIST P-256 曲线. 哈希算法为 SHA-256. 实现 MUST 使用 Supported Elliptic Curves 和 Supported Point Formats Extensions [RFC4492]. 未压缩点格式 MUST 被支持. [RFC6090] 可用作实现方法.
证书中的 subject 会由设备的长期唯一 identifier 构成, 例如 EUI-64 [EUI64]. subject 也可以基于用作 CoAP URI Host 部分的 Fully Qualified Domain Name (FQDN). 但是, 设备的 IP 地址通常不应被用作 subject, 因为它会随时间变化. 系统中使用的发现过程会建立给定设备的 IP 地址与每个设备 subject 之间的映射. 某些设备可能有多个 subject, 并且需要不止一个证书.
建立新连接时, 需要验证远程设备的证书. 如果 CoAP 节点具有绝对时间源, 则该节点 SHOULD 检查证书的有效日期是否在范围内. 证书 MUST 根据安全要求适当验证, 使用等价于 [RFC5280] Section 6 中规定算法的功能. 如果证书包含 SubjectAltName, 则 request URI 的 authority MUST 匹配 SubjectAltName 集合中 URI 类型字段内找到的任何 CoAP URI 的至少一个 authority. 如果证书中没有 SubjectAltName, 则 request URI 的 authority MUST 使用 [RFC3280] 中定义的匹配规则匹配证书中的 Common Name (CN), 但不允许带通配符的证书.
CoRE 对证书状态检查的支持需要进一步研究. 由于当前尚未定义 Online Certificate Status Protocol (OCSP) [RFC6960] 到 CoAP 的映射, 且 OCSP 也可能不易适用于所有环境, 替代方法可以是在可用时使用 TLS Certificate Status Request extension ([RFC6066] Section 8, 也称为 "OCSP stapling"), 或最好使用 Multiple Certificate Status Extension ([RFC6961]).
如果系统除证书外还有共享密钥, 则 SHOULD 使用包含该共享密钥的 cipher suite, 例如 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA [RFC5489].