关于信息安全:OpenSSL-300-设计三|FIPS-模块

9次阅读

共计 11410 个字符,预计需要花费 29 分钟才能阅读完成。

译|王祖熙 (花名:金九 )

蚂蚁团体开发工程师

负责国产化明码库 Tongsuo 的开发和保护

专一于密码学、高性能网络、网络安全等畛域

本文 9658 字 浏览 20 分钟

本文翻译 OpenSSL 官网文档:https://www.openssl.org/docs/OpenSSL300Design.html

Tongsuo-8.4.0 是基于 OpenSSL-3.0.3 开发,所以本文对 Tongsuo 开发者同样实用,内容丰盛,值得一读!

因为文章篇幅较长,明天带来的是 《FIPS 模块》 局部内容,已公布文章《介绍、术语与架构》、《Core 和 Provider 设计》可看发表记录。后续内容将随每周推送残缺公布,请继续关注 铜锁

FIPS 模块

这是一个通过 FIPS 140-2 验证的加密模块,它是一个只蕴含通过 FIPS 验证 / 批准的加密算法的 Provider,非 FIPS 算法将由默认 Provider(而不是 FIPS 模块)提供。

该模块是能够动静加载的,不反对动态链接。

FIPS 模块自身不会有 “FIPS 模式 ”,能够应用 FIPS Provider 的 OpenSSL 将具备与 FIPS-Module-2.0.0 兼容的 ” 模式 ” 概念。

FIPS 模块版本编号

版本将为 FIPS-Module-3.0。

任何后续的订正版本将以与先前公布相似的形式进行标记,例如 3.0.x。

对于更改告诉或从新验证,FIPS 模块的版本号将更新以匹配以后的 OpenSSL 库版本。

检测 FIPS 边界内的变更

为了进行验证,咱们须要检测是否有任何相干的源代码产生了变动。

能够应用一个脚本来对 C 源代码进行标记化解决,就像 C 预处理器一样,但还要教会它疏忽源代码中的某些局部:

  • 零碎的 #include 指令。
  • 在 FIPS 模式下被条件排除的代码(如下文中所述的条件代码)。

(揭示:C 预处理器能够将所有非换行空白字符合并,并在每个标记之间留下规范的单个空格,对于此目标,正文被视为空白字符)

标记化解决的后果能够通过校验和进行解决,该校验和存储在与源代码文件绝对应的文件中,并最终进行版本控制。

该过程大抵如下(并非完全相同,这只是一个代码示例,用于展现整个过程):

    for f in $(FIPS_SOURCES); do
        perl ./util/fips-tokenize $f | openssl sha256 -r
    done | openssl sha256 -hex -out fips.checksum

还会有一些机制来揭示咱们无关变动的信息,以便咱们能够采取适当的措施。例如:

    git diff --quiet fips.checksum || \
        (git rev-parse HEAD > fips.commit; scream)

对于 scream 的具体操作尚待确定。

更新 fips.checksum 应该作为失常的 make update 的一部分进行,这是通常用于更改和查看版本控制文件的办法,OpenSSL 的继续集成曾经运行了此命令,以确保没有脱漏任何内容,并且如果有内容被更改,将中断构建过程,运行 make update 也是失常的 OpenSSL 公布流程的一部分。

如何对已签名校验和的更改做出反馈

只管产生了变更,但咱们仓库中的校验和更改自身并没有什么大不了的,它只是揭示咱们须要额定关注 FIPS 源代码。

有两种可能的状况:

  1. 当即将公布新版本,并且 fips.checksum 不再蕴含上一个通过验证的源代码的校验和时,将 FIPS 源代码发送给实验室,并开始更新验证流程。
  2. 在公布新版本的同时,fips.checksum 不再蕴含上一个通过验证的源代码的校验和时,将 FIPS 源代码(包含 diff 文件和变更列表)发送给实验室,并启动相应的更新验证流程。

已验证的校验和列表将在其余中央列出(稍后确定具体位置)。

编译

对于每个 FIPS Provider 的源文件,咱们计算该文件的校验和,并将其与 fips.checksum 中收集的校验和进行比对,如果存在不匹配,将回绝编译。

FIPS 模式

FIPS 模块仅蕴含通过 FIPS 验证的明码算法,任何 FIPS 模式的“切换逻辑”将位于 FIPS 模块边界之外 – 这将由“fips”属性解决。

与 FIPS 模式相干的条件代码在独自的局部中探讨。

以下的 FIPS API 将持续可供应用程序应用(为了放弃一致性,应用了与 1.1.1 版本中雷同的名称):

  • int FIPS_mode_set(int on)

确保以后全局属性设置中设置了“fips=yes”(当 on != 0 时),或者未设置“fips”(当 on == 0 时)。这还将尝试应用属性“fips=yes”获取 HMAC-SHA256 算法,并确保它胜利返回。

  • int FIPS_mode(void)

如果以后的全局属性字符串蕴含属性“fips=yes”(或“fips”),则返回 1,否则返回 0。

咱们能够查看以后是否有提供 FIPS 算法的 Provider 可用,并略微以不同的形式解决。

  • int FIPS_self_test(void)

如果 FIPS_mode() 返回 true,则运行 KATs。

完整性测试将不在此处涵盖,如果咱们决定提供它,它将是一个独自的函数。

胜利时返回 1,失败或没有 OpenSSL FIPS Provider 时返回 0。

留神:这些函数只能在 OpenSSL FIPS Provider 的上下文中运行,而不能在其余任何 FIPS Provider 的上下文中运行。这些是过期的遗留接口,应应用 EVP_set_default_alg_properties() 函数进行非遗留配置。

角色和身份认证

有两个隐含的角色 – 明码官(CO)和用户。这两个角色都反对雷同的服务,惟一的区别是 CO 负责装置软件,该模块不应反对用户身份验证(对于 1 级而言不是必须的),所有这些都能够在安全策略中解释,而无需编写具体的代码。

无限状态模型(FIPS 140- 2 第 4.4 节)

须要定义一个状态机。

咱们将须要以下状态:

  • 自检状态 – 初始化、运行、自检、谬误、敞开(可能还包含后触发状态)
  • 谬误状态 – 如果自检失败,模块应返回该操作的谬误。能够尝试革除谬误并反复操作,如果失败依然存在,模块应进入谬误状态,这能够是一个硬错误状态,其中所有加密操作都失败,或者是一个性能降级状态,其中失败的组件仅在应用时返回谬误。

触发自检失败的形式包含:

    1. 间断测试(生成密钥对的成对测试(签名 / 验证)和从熵源比拟测试中验证输出到 DRBG 的随机数不雷同)。
    2. DRBG 衰弱测试 – 这能够始终在 RNG 中引发谬误(而不是设置全局谬误状态)。
    3. 装置、启动或按需的 POST 完整性测试失败。
    4. 启动或按需的 POST KAT 失败。

将提供一个外部 API 来设置上述情况的失败状态。

状态机

在状态机中未显示的状态以虚线示意。进入和来到谬误状态的边缘以虚线示意,以表明不心愿遍历这些边缘。

| 状态模型由这些状态组成:1. 电源敞开(Power Off):FIPS 模块未加载到应用程序中,共享库不在内存中。

  1. 电源开启(Power On):FIPS 模块已被应用程序加载,并且共享库在内存中。默认入口点构造函数将被启动。
  2. 初始化(Initialisation):调用 OSSL_provider_init。
  3. 完整性检查(Integrity Check)(POST 完整性):模块对本身进行校验,并验证其是否被歹意更改。(在 FIPS 提供程序的 OSSL_provider_init() 期间运行)。
  4. 自检(Self Test)(POST KAT):FIPS 模块在装置期间执行其自检,或者在通过 API 调用进行按需自检。
  5. 运行(Running):FIPS 模块处于失常运行状态,能够应用所有 API,并进行间断测试。
  6. 谬误(Error):FIPS 模块进入谬误状态,调用所有加密 API 将返回谬误。
  7. 敞开(Shutdown):FIPS 模块正在被终止并从应用应用程序中卸载。

状态之间的边缘关系如下:

  1. 从电源敞开(Power Off)到电源开启(Power On):此转换由操作系统在将共享库加载到应用程序时执行。
  2. 从电源开启(Power On)到初始化(Initialisation):当调用共享库的构造函数时产生此转换。
  3. 从电源开启(Power On)到敞开(Shutdown):如果无奈调用构造函数或构造函数失败,将触发此转换。
  4. 从初始化(Initialisation)到完整性检查(Integrity Check):此转换在初始化代码实现后产生,计算模块完整性校验和,并与预期值进行比拟。
  5. 从初始化(Initialisation)到谬误(Error):如果初始化代码在启动自测之前遇到谬误,将触发此转换。
  6. 从完整性检查(Integrity Check)到运行(Running):对于所有启动过程中完整性检查胜利的状况,产生此转换。
  7. 从完整性检查(Integrity Check)到自测(Self Test):在装置过程中,如果完整性检查胜利,产生此转换。
  8. 从完整性检查(Integrity Check)到谬误(Error):如果完整性检查失败,将触发此转换。
  9. 从运行(Running)到敞开(Shutdown):当 FIPS 模块最终化时产生此转换。
  10. 从运行(Running)到谬误(Error):如果间断测试中的任何一个失败,将触发此转换。
  11. 从运行(Running)到自测(Self Test):应用程序手动启动自测时触发此转换。不从新运行完整性检查。
  12. 从自测(Self Test)到运行(Running):自测通过时产生此转换。
  13. 从自测(Self Test)到谬误(Error):如果自测失败,将触发此转换。
  14. 从敞开(Shutdown)到电源敞开(Power Off):当 FIPS 模块从应用程序的内存中卸载时产生此转换。
  15. 从谬误(Error)到敞开(Shutdown):当 FIPS 模块最终化时产生此转换。

如果可能的话,咱们应该尽量在运行状态下注册算法,任何进入运行状态的转换都应该容许注册 / 缓存明码算法,而任何进入谬误或敞开状态的转换都应该革除 libcrypto 中的所有缓存算法,通过采纳这种办法,咱们能够防止在所有明码工厂函数中查看状态,这样能够防止为自我测试(手动启动时)提供非凡状况拜访权限,同时阻止内部调用者的拜访。

服务

FIPS 模块提供以下服务。

  • 显示状态。如果“运行”状态处于活动状态,则返回 1,否则返回 0。
  • 明码服务,如 HMAC、SHS、加密。请参阅附录 3 - 算法。
  • 自检(按需执行)- libcrypto 中提供了一个名为 FIPS_self_test() 的公共 API 来拜访此办法。所应用的办法必须与初始化时触发的办法雷同,安全策略将指明只有在没有其余明码服务运行时能力拜访此办法。
  • 密钥清零。请参阅 CSP/Key 清零。

这些服务仅在运行状态下运行,在任何其余状态下尝试拜访服务将返回谬误,如果自检失败,则任何尝试拜访任何服务的操作都应返回谬误。

自测试

自测试包含上电自测试(POST)和运行时测试(例如,确保熵不会反复作为 RNG 的输出)。

POST 包含模块完整性检查(每次运行应用 FIPS 的应用程序时运行)以及算法 KAT(能够在装置时运行一次)。

POST 测试在调用 FIPS 模块的 OSSL_provider_init() 入口点时运行。

为了依照正确的程序实现完整性测试和 KAT,模块须要拜访以下数据项:

  1. 库的门路;
  2. 库内容的 HMAC-SHA256(或蕴含该值的文件的门路);
  3. 批示库已装置并通过 KAT 的指示器;
  4. 该指示器的 HMAC-SHA256。

这些值将成为能够通过 OSSL_PROVIDER 对象和相干的 OSSL_PARAM getter 获取的参数的一部分。将应用一个“更平安”的获取值函数来获取这些值,该函数不会开展环境变量等。此外,还须要传递用于拜访和返回库内容的函数(可能是基于 BIO 的,通过将 Core 传递给模块的调度表中的大量 BIO 函数来实现),以便模块能够生成本人的库摘要。

新的 OpenSSL“fips”应用程序将提供装置(运行 KAT 并输入配置文件数据)和查看(查看配置文件中的值是否无效)的性能。

模块的默认入口点(DEP),即 Linux 库中的“.init”函数,将设置一个模块变量(可能是状态变量),在 OSSL_provider_init() 中将查看此变量,并且如果设置了(通常会设置),则验证文件中的值。这个两步过程满足了 FIPS 要求,即 DEP 确保测试运行,但容许咱们在失常运行时初始化模块的其余部分时实现这些测试。

作为构建过程的一部分,必须将 FIPS 模块的完整性校验和保留到文件中,这能够通过脚本实现,它只是应用已知固定密钥对整个 FIPS 模块文件进行 HMAC_SHA256 运算的后果,如果库已签名,则必须在利用签名之后计算校验和。

至多具备 112 位的固定密钥将嵌入到 FIPS 模块中,用于所有 HMAC 完整性操作,这个密钥也将提供给内部构建脚本。

出于测试目标,即便其中一个或多个测试失败,所有流动的 POST 测试也会运行。

完整性校验和的地位

完整性校验和将在装置过程中保留到一个独自的文件中,默认状况下,该文件将与 FIPS 模块自身位于雷同的地位,但能够配置为位于不同的地位。

已知答案测试

KAT 的目标是对明码模块进行健康检查,以辨认在电源周期之间的模块的重大故障或变动,而不是验证实现是否正确。

FIPS 140-2 IG 的规定指定了须要测试每个已反对的算法(不是每个模式),如果一个算法作为另一个测试的组成部分进行了测试,则不须要独自的测试,以下是须要进行测试的算法列表:

  • 加密 / 解密算法
    • AES_128_GCM2
    • TDES_CBC
  • 哈希算法
    • SHA1
    • SHA256 在其余中央曾经要求测试
    • SHA512
    • SHA3-256
  • 签名 / 验证测试
    • DSA_2048
    • RSA_SHA256(应用 PKCS #1 v1.5 填充)
    • ECDSA P256
  • 任何反对的 DRBG 机制的 DRBG 衰弱测试
    • CTR(AES_128_CTR)
    • HASH – SHA256
    • HMAC – SHA256
  • 派生测试(计算 Z)
    • ECDSA P256
    • ECDH
    • KDF(密钥派生函数)
    • KBKDF(用于 TLS 的 HKDF)

留神:完整性测试应用 HMAC-SHA-256,因而不须要独自进行 HMAC 测试。

接口拜访

为了不便批改和更改运行的自测试,自测试应该是数据驱动的,POST 测试在注册任何办法之前运行,但办法表依然能够间接应用,依然须要较低级别的 API 来设置密钥(参数、公钥 / 私钥),密钥加载代码应该在一个独自的函数中进行隔离。

须要一个初始化办法来为高级函数设置所需的依赖项,例如在执行根本调用之前可能须要调用 set_cpuid。

应为摘要、明码、签名、DRBG、KDF、HMAC 提供不同类型的自测试 API。

传递给这些测试的参数是 KAT 数据。

平安强度

SP 800-131A rev2 在某些日期之后禁止应用特定的算法和密钥长度,这些我的项目与平安强度相关联。

容许具备至多 112 位平安强度的算法。

对于签名验证,为了遗留目标,容许应用平安强度至多为 80 且低于 112 的算法。

这两个值能够在 FIPS 模块中定义和执行,也能够在安全策略文档中更简略地解决。

能够通过公共 API 定义这些最小值,并容许设置它们。

还应增加指标平安强度的概念,该值将在密钥生成算法中应用,这些算法通过其规范指定了指标平安强度参数。

SP800-56A & 56B

这些规范蕴含密钥协商协定,为了测试这些协定,加密模块须要蕴含以下低级原语。

  • 计算密钥办法 – 这些曾经存在。(例如 DH_compute_key())。
  • 密钥生成 –(目前短少 RSA FIPS 186-4 密钥生成)。
  • 密钥验证 –(大部分曾经实现)。

FIPS 186-4 RSA 密钥生成

  • 曾经编写了 RSA 密钥生成的初始代码(https://github.com/openssl/openssl/pull/6652);

尚未实现的工作是将其整合到 FIPS 模块中,OpenSSL FIPS Provider 将具备强制密钥大小限度的逻辑;

  • 对于 RSA、DSA 和 ECDSA 密钥对生成,须要进行成对一致性测试(条件自检)。因为在密钥生成过程中无奈确定密钥的用处,FIPS 140-2 IG 规定雷同的成对测试能够用于签名和加密两种模式;
  • 不容许应用 1024 位的 RSA 密钥生成;
  • 密钥生成算法具备指标平安强度的概念。例如,RSA 的密钥生成代码须要进行以下查看:
if (target_strength < 112
    || target_strength > 256
    || BN_security_bits(nbits) < target_strength)
    return 0;

DH 密钥生成

  • DH 密钥生成 – 可能须要将其拆分为符合标准步骤的模式。目前它是一个相当简单用时也用于验证的整体函数。

密钥验证

  • RSA SP 800-56B 密钥验证 – 公钥、私钥和密钥对的查看已增加到 PR#6652,符合标准的要求;
  • 须要查看 DH 密钥验证是否符合标准;
  • EC 密钥验证符合标准要求;
  • AES-XTS 模式须要进行扭曲密钥查看。

对于 KAS DH 参数,反对两种类型:

  1. 已批准的平安素数群如下:

(其中 g=2,q=(p-1)/2,priv=[1, q-1],pub=[2, p-2])

TLS:(ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144, ffdhe8192)

IKE:(modp-2048, modp-3072, modp-4096, modp-6144, modp-8192)

只有上述平安素数能够进行验证 - 其余任何素数都应该失败。

平安素数可用于至多 112 位的平安强度,可能须要进行 FIPS 特定的查看以验证群组。

  1. FIPS 186-4 参数集仅用于向后兼容性,平安强度仅为 112 位。群组为 FB (2048, 224) 和 FC (2048, 256)。这须要保留种子和计数器以进行验证。

如果须要同时反对两种类型,则须要不同的密钥验证代码。

现有的 DH_Check() 须要进行 FIPS 特定的查看来验证批准的类型。

密钥生成对于两者来说是雷同的(平安强度和私钥的最大位长度是输出)。

DSA 在 FIPS 186-4 中定义为“FFC”,DSA 密钥生成 / 密钥验证能够从新设计,以更好地匹配规范步骤,这将有助于密钥验证,并且如果须要,能够在 DH 状况下进行重用。

GCM IV 生成

对于 FIPS 模块,AES GCM 有与惟一密钥 /IV 对相干的要求,即:

  • 加密时密钥 /IV 对必须是惟一的;
  • IV 必须在 FIPS 边界内生成;
  • 对于 TLS,IV 的计数局部必须由模块设置,模块必须确保当计数用尽时返回谬误;
  • 对于给定的密钥(对于任何 IV 长度),认证加密函数的总调用次数必须小于;
  • 模块断电不应导致 IV 的重复使用。

IV 生成将应用随机构造方法(来自 SP 800-38D),其中包含一个自在字段(将为 NULL)和一个随机字段,随机字段将应用一个能提供至多 96 位熵强度的 DRBG,该 DRBG 须要由模块进行种子生成。

现有代码须要批改,以便在 init() 阶段未设置 IV 时生成 IV,而后能够应用 do_cipher() 办法在须要时生成 IV。

int aes_gcm_cipher()
{
    ....
    /* old code just returned -1 if iv_set was zero */
    if (!gctx->iv_set) {if (ctx->encrypt) {if (!aes_gcm_iv_generate(gctx, 0))
               return -1;
           } else {return -1;}
        }
    }
}

生成代码如下所示:

#define AES_GCM_IV_GENERATE(gctx, offset)                   \
    if (!gctx->iv_set) {                                    \
        int sz = gctx->ivlen - offset;                      \
        if (sz <= 0)                                        \
            return -1;                                      \
        /* Must be at least 96 bits */                      \
        if (gctx->ivlen < 12)                               \
            return -1;                                      \
        /* Use DRBG to generate random iv */                \
        if (RAND_bytes(gctx->iv + offset, sz) <= 0)         \
            return -1;                                      \
        gctx->iv_set = 1;                                   \
    }

生成的 IV 能够通过 EVP_CIPHER_CTX_iv() 办法获取,因而不须要应用 ctrl id。

现实状况下,在 FIPS 模式下尝试设置 GCM IV 参数将导致谬误。实际上,可能依然有一些应用程序须要设置 IV,因而倡议将其指定为安全策略项。

安全策略还须要阐明以下内容:(参见 FIPS 140-2 IG A.5)

  • 当电源断开而后复原时,应建设一个新的用于 AES GCM 加密的密钥;
  • 应用雷同密钥的总调用次数必须小于;
  • 场景 1:IV 生成合乎 TLS 协定;
  • 场景 2:应用 NIST SP 800-38D(第 8.2.2 节)的 IV 生成办法。

CSP/Key 清零

当不再须要临界平安参数(CSP)时,咱们必须将其全副设置为零,这可能会在不同的上下文中产生:

  • 长期的 CSP 正本可能是栈或堆调配的,并且将在其应用范畴内的相干函数中被清零;
  • 一些 CSP 将与 OpenSSL 对象(如 EVP_PKEY 或 EVP_CIPHER_CTX)关联,具备与之相关联的生命周期,在这种状况下,当这些对象被开释时,CSP 将在该点被清零。在某些状况下,对象可能会被复用(例如,EVP_CIPHER_CTX 能够用于多个加密操作),在这种状况下,对象中仍存在的任何 CSP 将在其从新初始化为新操作时被清零。
  • 一些 CSP(例如外部 DRBG 状态)可能会在加载 OpenSSL FIPS 模块的整个工夫内存在,在这种状况下,状态将封装在 OpenSSL 对象中。所有 OpenSSL Provider(包含 FIPS 模块 Provider)都具备注册“卸载”函数的能力,该函数在敞开 OpenSSL 时(或因其余起因卸载模块)时将被调用,该卸载函数将开释(因而将清零)蕴含 CSP 的对象。
  • 依据 FIPS 140-2 IG 4.7 的规定:仅用于执行 FIPS 140-2 第 4.9.1 节上电测试的明码模块应用的明码密钥不被视为 CSP,因而不须要满足 FIPS 140-2 第 4.7.6 节的清零要求。

OpenSSL FIPS 模块将蕴含其本人的规范 OPENSSL_cleanse() 函数的副原本执行清零操作,这是应用特定于平台的汇编语言实现的。

DRBG

在旧的 FIPS 模块中存在以下 API,可能须要从新增加:

  • FIPS_drbg_health_check:按需运行 DRBG KAT 测试,咱们须要使其可用。
  • FIPS_drbg_set_check_interval:设置运行 DRBG KAT 测试之间的距离(生成调用的次数)。这仿佛不是必须的,这些测试在上电时运行,但后续不须要运行,但这个调用对于故障测试很有用。

推导函数

依据 FIPS 140-2 IG 14.5 中的第 2 点要求,CTR DRBG 将无条件反对派生函数,如果禁用派生函数,以后的代码在从新生成种子时会呈现问题。此外,如果没有派生函数,须要从实验室取得额定的理由反对。

测试要求

  • uninstantiate() 函数中须要证实外部状态已被清零;
  • 故障测试须要一个函数,使 DRBG 始终产生雷同的输入。

其余须要思考的事项

除了上面形容的熵之外,还须要思考以下几点:

  • 应思考施行 NIST SP 800-90C 10.1.2 中的熵扩大;
  • 须要更好的 DRBG 抉择机制,以在可用的 DRBG 之间进行抉择;
  • 反对预测抵制,即在申请时尝试从咱们的起源收集更多熵。
  • 咱们须要弄清楚 DRBG 层将是什么样子,代码的很大一部分须要放在 FIPS 模块内。目前,此代码拜访 EVP 性能,而这些性能可能不会在模块外部公开。例如,drbg_ctr_init() 从 NID 解析 EVP_CIPHER,而后设置一个 EVP_CIPHER_CTX。

对于所有平台,操作系统将提供熵。对于某些平台,还能够应用内置的硬件随机数生成器,但这将引入额定的验证需要。

对于类 UNIX 零碎,将应用零碎调用 getrandomgetentropy 或随机设施 /dev/random 作为熵源,优先思考应用零碎调用。能够代替 /dev/random 的其余强随机设施包含:/dev/srandom/dev/hwrng。请留神,/dev/urandom/dev/prandom/dev/wrandom/dev/arandom在没有额定的证实的状况下不能用于 FIPS 操作。

在 Windows 上,将应用 BCryptGenRandomCryptGenRandom作为熵源。

在 VMS 上,将应用各种零碎状态信息作为熵源。请留神,这将须要证实和剖析以证实源的品质。

对于 iOS,将应用 SecRandomCopyBytes 生成具备密码学安全性的随机字节。

FIPS 仅容许将一个熵源归因于模块,因而 FIPS 模块将齐全依赖于前述的操作系统源,不会应用其余起源,例如 egd、硬件设施等。

实现熵解决方案的工作

须要将 DRBG 衰弱检测增加到随机框架中,以查看输出到 DRBG 的种子资料,查看的目标是确保没有间断的两个种子资料块是雷同的,该查看在所有熵源被合并在一起后进行,如果查看失败,则 DRBG 的种子从新生成操作将永远失败。咱们能够定义应用的块大小为 64 位,这是在意外接管到反复块的概率()和从操作系统中获取过多熵量之间的均衡(因为第一个块会被抛弃),其余显著可用的块大小包含 128 位和 256 位。

应用后,初始数据块必须被清零和抛弃。

GCM 的初始化向量(IV)

FIPS 140-2 IG A.5 的最新更新指出,如果模块声称为 GCM 生成随机 IV,则须要提供证实,咱们须要证实模块可能从操作系统获取所需的 96 位熵,如果应用阻塞调用操作系统的随机性源,并且至多应用这么多熵素材作为 DRBG 的种子资料,那么这应该不是无奈解决的问题。

FIPS 模块边界

一旦进入 FIPS 模块提供的算法,在任何其余的加密操作中咱们必须依然放弃在 FIPS 模块外部。依据 FIPS 规定,容许一个 FIPS 模块应用另一个 FIPS 模块。然而,在 3.0 设计中,为了简化起见,咱们假如不容许这样做。例如,EVP_DigestSign*实现同时应用签名算法和摘要算法,咱们不容许其中一个算法来自 FIPS 模块,另一个来自其余 Provider。

所有 Provider 在初始化时都被调配一个惟一的 OSSL_PROVIDER 对象,当 FIPS 模块被要求应用某个算法时,它会验证该算法的实现 OSSL_PROVIDER 对象是否与本人的 OSSL_PROVIDER 对象雷同 (即传递给 OSSL_provider_init 的对象),例如,思考应用 RSA 和 SHA256 的 EVP_DigestSign* 的状况,两个算法都会通过 Core 在 FIPS 模块内部进行查找,RSA 签名算法是第一个入口点,”init” 调用将被传递给要应用的 SHA256 算法的援用,FIPS 模块的实现将查看与其被要求应用的 SHA256 实现关联的 OSSL_PROVIDER 对象是否也在 FIPS 模块边界内,如果不是,则 “init” 操作将失败。上面的图示从 FIPS 模块的角度阐明了这个操作。

请留神,在 FIPS 模块外部,咱们应用了 EVP 的概念(如 EVP_MD_CTXEVP_PKEY_CTX 等)来实现这一点,这些是 libcrypto 中 EVP 实现的正本,FIPS 模块没有与 libcrypto 进行链接,这是为了确保残缺的操作都在 FIPS 模块的边界内进行,而不调用内部的代码。

ASN.1 代码

ASN.1 DER (Distinguished Encoding Rules) 用于:

  • 序列化 密钥 参数
  • 序列化由两个值 r 和 s 组成的 DSA 和 ECDSA 签名
  • 编码搁置在 RSA PKCS#1 填充中的签名摘要 OBJECT IDENTIFIER(OID)
  • 序列化 X.509 证书和证书撤销列表(CRL)
  • 其余 PDU,如 PKCS #7/CMS、OCSP、PKCS #12 等。

FIPS 模块不会蕴含 ASN.1 DER 编码器 / 解析器的正本,也不会要求任何 Provider 对由 OpenSSL 实现的算法执行 ASN.1 序列化 / 反序列化。

所有 ASN.1 序列化 / 反序列化操作将在 libcrypto 中执行,复合值的 密钥 参数和签名 构造将作为项数组越过 Core/Provider 边界,应用 附录 2 – 参数传递 中定义的公共数据结构进行传递。

用于 RSA PKCS#1 填充的编码摘要 OID 将事后生成(与旧 FIPS 模块应用 SHA_DATA 宏雷同)或依据须要应用简略函数生成,这个函数仅为 PKCS #1 填充反对的小型摘要汇合生成编码的 OID,这些摘要 OID 在“OID 树”下的一个公共节点下,验证填充时将获取预期摘要的编码 OID,并将其字节与填充中的字节进行比拟;不须要进行 DER 解析 / 解码。

正文完
 0