0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入分析Linux kernel安全特性: 內(nèi)核模塊簽名

冬至子 ? 來(lái)源:乾越 ? 作者:乾越 ? 2023-10-18 12:32 ? 次閱讀

概述

顧名思義,在開(kāi)啟該功能之后,內(nèi)核在加載內(nèi)核模塊時(shí),會(huì)對(duì)內(nèi)核模塊的簽名進(jìn)行檢查。

如果內(nèi)核模塊本身沒(méi)有經(jīng)過(guò)簽名,或者簽名值與預(yù)期值不符,這兩種情況都會(huì)被認(rèn)為是簽名認(rèn)證失敗。根據(jù)策略的不同,簽名認(rèn)證失敗可能會(huì)導(dǎo)致模塊被拒絕加載,也可能是繼續(xù)正常加載但內(nèi)核會(huì)顯示一條警告信息。

內(nèi)核模塊簽名功能的本質(zhì)是限制root用戶載入惡意的內(nèi)核模塊。當(dāng)root用戶加載一個(gè)內(nèi)核模塊時(shí),內(nèi)核在分辨是系統(tǒng)管理員還是攻擊者的時(shí)候,依靠的就是能夠進(jìn)行身份認(rèn)證的可信的X.509證書(shū)和與之對(duì)應(yīng)的私鑰。只要私鑰存儲(chǔ)妥當(dāng)不發(fā)生泄露,攻擊者就無(wú)法偽造X.509證書(shū),因此也就不可能提供含有正確簽名的內(nèi)核模塊;而系統(tǒng)管理員是唯一合法的X.509證書(shū)的使用者,是可以用合法的證書(shū)對(duì)應(yīng)的私鑰對(duì)內(nèi)核模塊進(jìn)行簽名的。

最佳實(shí)踐

  • 用openssl命令生成PEM格式的簽名key文件。
openssl req -new -nodes -utf8 -sha256 -days 36500 
        -batch -x509 -config x509.genkey 
        -outform PEM -out system_key.pem 
        -keyout system_key.pem

其中x509.genkey的內(nèi)容如下:

[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_req

[ req_distinguished_name ]
O = Alibaba Group
OU = < your_organization >
CN = Test modsign key
emailAddress = < your_user_name >@alibaba-inc.com

[ v3_req ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always
  • 配置內(nèi)核
    CONFIG_MODULE_SIG=y
    CONFIG_MODULE_SIG_FORCE=y
    CONFIG_MODULE_SIG_KEY=<前一個(gè)步驟生成的system_key.pem文件的路徑>
    CONFIG_MODULE_SIG_HASH="sha256"
    CONFIG_MODULE_SIG_SHA256=y
    CONFIG_CRYPTO_SHA256=y
    CONFIG_MODULE_SIG_ALL=y
  • 編譯內(nèi)核和模塊
make bzImage modules
  • 安裝內(nèi)核和內(nèi)核模塊
sudo make modules_install install
  • 對(duì)內(nèi)核模塊進(jìn)行簽名

在指定了CONFIG_MODULE_SIG_ALL=y的情況下,kbuild系統(tǒng)可以自動(dòng)對(duì)模塊進(jìn)行簽名,而且該步驟通常無(wú)需手動(dòng)運(yùn)行,會(huì)在module_install時(shí)自動(dòng)執(zhí)行簽名。

make modules_sign
  • 用openssl全手動(dòng)簽名和驗(yàn)簽
openssl smime -sign -nocerts -noattr -binary -in < module > -inkey 
    < key > -signer < x509 > -outform der -out < raw sig >

openssl smime -verify -in < raw sig > -inform der -content < module > 
    -certfile < x509 > -noverify -out /dev/null

內(nèi)核配置選項(xiàng)

CONFIG_MODULE_SIG:Module signature verification
如果開(kāi)啟了該選項(xiàng),在內(nèi)核在加載內(nèi)核模塊時(shí),會(huì)對(duì)內(nèi)核模塊的簽名進(jìn)行檢查。

默認(rèn)情況下,在加載沒(méi)有簽名或者是簽名不正確的內(nèi)核模塊時(shí),內(nèi)核僅僅是打印一條提示信息,比如:

k_netlink: module verification failed: signature and/or required key missing - tainting kernel

同時(shí)將內(nèi)核標(biāo)記為tainted,然后繼續(xù)正常加載簽名有問(wèn)題的模塊。

CONFIG_MODULE_SIG_FORCE: Require modules to be validly signed
如果開(kāi)啟了該選項(xiàng),在加載沒(méi)有簽名或者是簽名不正確的內(nèi)核模塊時(shí),內(nèi)核會(huì)直接拒絕加載簽名有問(wèn)題的內(nèi)核模塊。

CONFIG_MODULE_SIG_HASH: Which hash algorithm should modules be signed with?
該選項(xiàng)用于決定簽名時(shí)使用的摘要算法。每一種算法都有對(duì)應(yīng)的內(nèi)核選項(xiàng):

  • CONFIG_MODULE_SIG_SHA1:sha1
  • CONFIG_MODULE_SIG_SHA224:sha224
  • CONFIG_MODULE_SIG_SHA256:sha256
  • CONFIG_MODULE_SIG_SHA384:sha384
  • CONFIG_MODULE_SIG_SHA512:sha512

注意:內(nèi)核會(huì)使用crypto子系統(tǒng)中實(shí)現(xiàn)的摘要算法內(nèi)核模塊來(lái)計(jì)算摘要值,這就意味著這些實(shí)現(xiàn)摘要算法的模塊必須已經(jīng)事先編譯為內(nèi)置,否則就會(huì)發(fā)生“為了計(jì)算簽名摘要值而要加載對(duì)應(yīng)的模塊但該模塊的簽名因缺少摘要算法模塊而無(wú)法計(jì)算“的窘?jīng)r。

CONFIG_MODULE_SIG_KEY: File name or PKCS#11 URI of module signing key

該選項(xiàng)指定了用于對(duì)內(nèi)核模塊簽名的PEM格式的簽名key文件的路徑,或者是一個(gè)PKCS#11 URI(在實(shí)際進(jìn)行簽名前,簽名工具會(huì)先把這個(gè)URI指定的key下載下來(lái))。該選項(xiàng)的默認(rèn)值是"certs/signing_key.pem"。如果沒(méi)有修改這個(gè)默認(rèn)值,內(nèi)核會(huì)自動(dòng)創(chuàng)建"certs/signing_key.pem"文件用于內(nèi)核模塊簽名。

kbuild會(huì)將這個(gè)X.509證書(shū)文件轉(zhuǎn)換為system certificate list并編譯進(jìn)內(nèi)核中,然后在system trusted keyring初始化階段將這個(gè)list中的每一個(gè)X.509證書(shū)都添加到builtin trusted keyring中。此時(shí),每一個(gè)X.509證書(shū)就是一把system trusted key。因此,該選項(xiàng)指定的key文件中的所有X.509證書(shū)還可以當(dāng)成system trusted key]來(lái)用。key文件至少包含一個(gè)PEM格式的私鑰和與之關(guān)聯(lián)的、PEM格式的X.509證書(shū)??梢酝ㄟ^(guò)級(jí)聯(lián)的方式將更多的X.509證書(shū)添加到該key文件中。

但是反過(guò)來(lái)卻是不成立的:并不是所有的system trusted key都可以用來(lái)驗(yàn)證內(nèi)核模塊的簽名,比如secondary trusted keyring中的key就不能用來(lái)驗(yàn)證內(nèi)核模塊的簽名;只有builtin trusted keyring中的key才可以用來(lái)驗(yàn)證內(nèi)核模塊的簽名。

最后要提醒的是,用于模塊簽名的簽名key可以是自簽名的,也可以不是。如果不是自簽名的,只要確保簽名key和父key能被導(dǎo)入到builtin trusted keyring即可。不要求父key的父key也必須在builtin trusted keyring中。

CONFIG_MODULE_SIG_ALL: Automatically sign all modules

選中該選項(xiàng)后,kbuild會(huì)在執(zhí)行make modules_install的時(shí)候?qū)λ械膬?nèi)核模塊進(jìn)行簽名。如果沒(méi)有選中該選項(xiàng),則需要使用者自己手動(dòng)調(diào)用scripts/sign-file簽名工具對(duì)內(nèi)核模塊進(jìn)行簽名。

內(nèi)核啟動(dòng)參數(shù)

module.sig_enforce

如果將該參數(shù)傳給內(nèi)核,表示強(qiáng)制驗(yàn)證內(nèi)核模塊簽名,效果上等價(jià)于CONFIG_MODULE_SIG_FORCE=y。如果內(nèi)核在編譯時(shí)已經(jīng)將CONFIG_MODULE_SIG_FORCE設(shè)為了y,那這里的內(nèi)核選項(xiàng)是不會(huì)起任何作用的。

該選項(xiàng)為內(nèi)核強(qiáng)制驗(yàn)證功能在策略上提供了一定的靈活性,比如運(yùn)行系統(tǒng)需要DKMS或者SystemTap支持的話,如果沒(méi)有實(shí)現(xiàn)配套的PKI簽名服務(wù)機(jī)制,最好將CONFIG_MODULE_SIG_FORCE設(shè)為n,同時(shí)為了保證安全在內(nèi)核命令行參數(shù)中指定module.sig_enforce。在必要時(shí),可以臨時(shí)去掉module.sig_enforce,以便系統(tǒng)維護(hù)或調(diào)試。

實(shí)現(xiàn)細(xì)節(jié)

內(nèi)核編譯階段

如果CONFIG_MODULE_SIG_KEY參數(shù)為默認(rèn)值,自動(dòng)生成內(nèi)核模塊簽名key文件certs/signing_key.pem

如果CONFIG_MODULE_SIG_KEY的值為默認(rèn)值certs/signing_key.pem,表示用戶希望使用由kbuild自動(dòng)生成的key文件對(duì)內(nèi)核模塊進(jìn)行簽名。

kbuild會(huì)自動(dòng)執(zhí)行以下命令生成key文件:

openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 
    -batch -x509 -config certs/x509.genkey 
    -outform PEM -out $(obj)/signing_key.pem 
    -keyout certs/signing_key.pem

該命令的含義是:根據(jù)X509證書(shū)請(qǐng)求配置模板文件的內(nèi)容,生成一個(gè)自簽名的X509證書(shū)。生成的key文件保存為certs/signing_key.pem, 同時(shí)將自簽名的X509證書(shū)附在key內(nèi)容的后面。

其中生成X509證書(shū)請(qǐng)求時(shí)使用的配置模板文件的內(nèi)容為:

[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts

[ req_distinguished_name ]
#O = Unspecified company
CN = Build time autogenerated kernel key
#emailAddress = unspecified.user@unspecified.company

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid

將內(nèi)核模塊簽名key文件build到system certificate list中

kbuild會(huì)調(diào)用scripts/extract-cert程序?qū)ONFIG_MODULE_SIG_KEY指定的PEM格式的X.509證書(shū)文件轉(zhuǎn)換為DER格式的certs/signing_key.x509文件:

scripts/extract-cert $(CONFIG_MODULE_SIG_KEY) signing_key.x509

如果CONFIG_MODULE_SIG_KEY指定的一個(gè)PKCS#11 URI,scripts/extract-cert程序也會(huì)在簽名之前先下載好再使用。

接下來(lái),上一個(gè)步驟生成的certs/signing_key.x509文件會(huì)連同system_certificates.S一起被編譯為certs/system_certificates.o。該object文件的內(nèi)容會(huì)被包含到內(nèi)核image的.init.rodata節(jié)中。

__INITRODATA

        .align 8
        .globl VMLINUX_SYMBOL(system_certificate_list)
VMLINUX_SYMBOL(system_certificate_list):
__cert_list_start:
#ifdef CONFIG_MODULE_SIG
        .incbin "certs/signing_key.x509"
#endif
        .incbin "certs/x509_certificate_list"
__cert_list_end:

該system certificate list中的所有X.509證書(shū)最終都會(huì)被加載到builtin trusted keyring中,并作為system trusted key來(lái)使用。

順便一提,由內(nèi)核選項(xiàng)CONFIG_SYSTEM_TRUSTED_KEYS指定的system trusted key文件(即certs/x509_certificate_list)也會(huì)成為system certificate list的一部分。準(zhǔn)確來(lái)說(shuō),它會(huì)在內(nèi)核初始化system trusted klseyring時(shí)加入到builtin trusted keyring中。

Kernel啟動(dòng)階段

初始化system trusted keyrings

由內(nèi)核選項(xiàng)CONFIG_MODULE_SIG_KEY指定的對(duì)內(nèi)核模塊進(jìn)行簽名的key文件會(huì)在這個(gè)階段被加載到builtin trusted keyring中。

用戶態(tài)運(yùn)行時(shí)階段

加載內(nèi)核模塊

  • 當(dāng)加載內(nèi)核模塊時(shí),會(huì)對(duì)內(nèi)核模塊的簽名進(jìn)行認(rèn)證。最終認(rèn)證的結(jié)果會(huì)保存在info->sig_ok中。
static int load_module(struct load_info *info, const char __user *uargs,
                       int flags)
...
        err = module_sig_check(info, flags);
        if (err)
                goto free_copy;
...
  • 如果認(rèn)證失敗,info->sig_ok返回0,因此內(nèi)核會(huì)打印一條信息:: module verification failed: signature and/or required key missing - tainting kernel,然后會(huì)將kernel狀態(tài)標(biāo)記為TAINT_UNSIGNED_MODULE。
...
#ifdef CONFIG_MODULE_SIG
        mod- >sig_ok = info- >sig_ok;
        if (!mod- >sig_ok) {
                pr_notice_once("%s: module verification failed: signature "
                               "and/or required key missing - tainting "
                               "kerneln", mod- >name);
                add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
        }
#endif
  • 對(duì)內(nèi)核模塊的簽名認(rèn)證的過(guò)程如下:
  1. 首先檢查flags是否為0。當(dāng)執(zhí)行modprobe -f時(shí),會(huì)要求內(nèi)核忽略所有的版本檢查。這會(huì)導(dǎo)致作為內(nèi)核模塊的數(shù)據(jù)的一部分的版本信息將被完全忽略。因此如果一個(gè)曾經(jīng)簽過(guò)名的模塊有安全漏洞,那么攻擊者可以在新內(nèi)核上強(qiáng)行加載這個(gè)有漏洞的模塊以便攻擊新內(nèi)核。因此,內(nèi)核認(rèn)為flags為非0值的時(shí)候,是可能存在上述跨內(nèi)核版本攻擊的可能性的,因此執(zhí)行modprobe -f一定會(huì)導(dǎo)致簽名認(rèn)證失敗。
  2. 檢查內(nèi)核模塊尾部的mark字段是否為“MODULE_SIG_STRINGn”。
  3. 如果mark字段存在,進(jìn)行簽名檢查。
  4. 如果mark不存在,根據(jù)當(dāng)前的模塊簽名檢查策略,決定返回值;如果使用了強(qiáng)制簽名檢查策略(CONFIG_MODULE_SIG_FORCE=y或指定了module.sig_enforce),則返回-ENOKEY;如果沒(méi)有使用強(qiáng)制簽名檢查策略,返回0。
  5. 檢查flags是否為0

結(jié)論:執(zhí)行modprobe -f一定會(huì)導(dǎo)致簽名認(rèn)證失敗, 這一點(diǎn)所有的責(zé)任人都要注意。原因是:作為內(nèi)核模塊的數(shù)據(jù)的一部分的版本信息將被modprobe -f完全忽略,如果一個(gè)曾經(jīng)簽過(guò)名的模塊有安全漏洞,那么攻擊者可以在新內(nèi)核上強(qiáng)行加載這個(gè)有漏洞的模塊以便攻擊新內(nèi)核。

#ifdef CONFIG_MODULE_SIG
static int module_sig_check(struct load_info *info, int flags)
{
        int err = -ENOKEY;
        const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
        const void *mod = info- >hdr;

        /*
         * Require flags == 0, as a module with version information
         * removed is no longer the module that was signed
         */
        if (flags == 0 &&
            info- >len > markerlen &&
            memcmp(mod + info- >len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
                /* We truncate the module to discard the signature */
                info- >len -= markerlen;
                err = mod_verify_sig(mod, &info- >len);
        }

        if (!err) {
                info- >sig_ok = true;
                return 0;
        }

        /* Not having a signature is only an error if we're strict. */
        if (err == -ENOKEY && !sig_enforce)
                err = 0;

        return err;
}
#endif
  • 檢查module簽名格式中的各個(gè)字段,然后調(diào)用verify_pkcs7_signature()驗(yàn)證PKCS#7消息。
int mod_verify_sig(const void *mod, unsigned long *_modlen)
{
        struct module_signature ms;
        size_t modlen = *_modlen, sig_len;

        pr_devel("== >%s(,%zu)n", __func__, modlen);

        if (modlen <= sizeof(ms))
                return -EBADMSG;

        memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
        modlen -= sizeof(ms);  // modlen包括模塊內(nèi)容+PKCS#7消息

        sig_len = be32_to_cpu(ms.sig_len); // PKCS#7消息的長(zhǎng)度
        if (sig_len >= modlen)
                return -EBADMSG;
        modlen -= sig_len; // 僅包含模塊內(nèi)容的長(zhǎng)度
        *_modlen = modlen; // 返回模塊內(nèi)容的長(zhǎng)度

        if (ms.id_type != PKEY_ID_PKCS7) {
                pr_err("Module is not signed with expected PKCS#7 messagen");
                return -ENOPKG;
        }

        if (ms.algo != 0 ||
            ms.hash != 0 ||
            ms.signer_len != 0 ||
            ms.key_id_len != 0 ||
            ms.__pad[0] != 0 ||
            ms.__pad[1] != 0 ||
            ms.__pad[2] != 0) {
                pr_err("PKCS#7 signature info has unexpected non-zero paramsn");
                return -EBADMSG;
        }

        return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
                                      NULL, VERIFYING_MODULE_SIGNATURE,
                                      NULL, NULL);
}
  • 對(duì)內(nèi)核模塊中的PKCS#7格式的消息進(jìn)行驗(yàn)證。注意其中的trusted_keys參數(shù)為NULL,因此能夠用于驗(yàn)證內(nèi)核模塊簽名的,僅限builtin trusted keyring中的key;而導(dǎo)入到secondary trusted keyring中的key是不能用于內(nèi)核模塊簽名的。
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION

/**
 * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
 * @data: The data to be verified (NULL if expecting internal data).
 * @len: Size of @data.
 * @raw_pkcs7: The PKCS#7 message that is the signature.
 * @pkcs7_len: The size of @raw_pkcs7.
 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
 *                                      (void *)1UL for all trusted keys).
 * @usage: The use to which the key is being put.
 * @view_content: Callback to gain access to content.
 * @ctx: Context for callback.
 */
int verify_pkcs7_signature(const void *data, size_t len,
                           const void *raw_pkcs7, size_t pkcs7_len,
                           struct key *trusted_keys,
                           enum key_being_used_for usage,
                           int (*view_content)(void *ctx,
                                               const void *data, size_t len,
                                               size_t asn1hdrlen),
                           void *ctx)
{
        struct pkcs7_message *pkcs7;
        int ret;

        // 解析內(nèi)核模塊簽名中的PKCS#7消息(DER格式),并將相關(guān)字段
        // 填充到pkcs7數(shù)據(jù)結(jié)構(gòu)中。
        // struct pkcs7_message {
        //     PKCS#7中的signer證書(shū)列表(可以為空)
        //     struct x509_certificate *certs;
        //     證書(shū)撤銷列表CRL(可以為空)
        //     struct x509_certificate *crl;
        //     Signer信息列表
        //     struct pkcs7_signed_info *signed_infos;
        //     PKCS#7消息格式版本號(hào)。1:  PKCS#7或CMS; 3:CMS
        //     u8       version;
        //     表示PKCS#7消息中是否包含authenticatedAttributes字段
        //     bool     have_authattrs;
        //     內(nèi)容類型
        //     enum OID data_type;
        //     被簽名的內(nèi)容的長(zhǎng)度
        //     size_t       data_len;
        //     被簽名的內(nèi)容的ASN.1 header的長(zhǎng)度
        //     size_t       data_hdrlen;
        //     被簽名的內(nèi)容(如果為NULL表示是detached content)
        //     const void   *data;
        // };
        // 
        // Signer信息
        // struct pkcs7_signed_info {
        //   指向下一個(gè)signer信息
        //   struct pkcs7_signed_info *next;
        //   指向位于pkcs7_message.certs的signer證書(shū)(如果有的話)
        //   struct x509_certificate *signer;
        //   當(dāng)前signer信息在signer信息列表中的位置
        //   unsigned   index;
        //   True if not usable due to missing crypto
        //   bool       unsupported_crypto;
        //
        //   Auth屬性值: Message digest - the digest of the Content Data (or NULL)
        //   const void *msgdigest;
        //   unsigned   msgdigest_len;
        //
        //   Authenticated Attribute data (or NULL) */
        //   unsigned   authattrs_len;
        //   const void *authattrs;
        //
        //   Auth屬性值
        //   unsigned long  aa_set;
        //   Auth屬性值
        //   time64_t   signing_time;
        //
        //   指向signer生成的簽名信息
        //   struct public_key_signature *sig;
        // };
        //   
        // struct public_key_signature {
        //   [0]包含的是由signer的issuerAndSerialNumber字段生成的key id
        //   [1]包含的則是skid(可以在X.509證書(shū)中的X509v3 Subject Key Identifier字段找到該值)
        //   struct asymmetric_key_id *auth_ids[2];
        //   具體的簽名值
        //   u8 *s;
        //   簽名值的長(zhǎng)度
        //   u32 s_size;
        //   摘要值
        //   u8 *digest;
        //   摘要值的長(zhǎng)度
        //   u8 digest_size;
        //   簽名算法,目前僅支持"rsa"
        //   const char *pkey_algo;
        //   摘要算法,比如"sha256"等
        //   const char *hash_algo;
        // };
        pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
        if (IS_ERR(pkcs7))
                return PTR_ERR(pkcs7);

        /* The data should be detached - so we need to supply it. */
        // 對(duì)于內(nèi)核模塊來(lái)說(shuō),content總是detached的。
        if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
                pr_err("PKCS#7 signature with non-detached datan");
                ret = -EBADMSG;
                goto error;
        }

        // 驗(yàn)證PKCS#7簽名。過(guò)程如下:
        // 1. 計(jì)算內(nèi)核模塊主體內(nèi)容的摘要值
        // 2. 遍歷每一個(gè)signer信息,如果PKCS#7中包含了signer的X.509證書(shū)的話,使用其
        //     證書(shū)中的公鑰驗(yàn)證signer的簽名值
        // 3. 如果signer信息中不包含signer的X.509證書(shū)的話,這里同樣也會(huì)返回0,目的是
        //     為了讓接下來(lái)的system trusted key來(lái)驗(yàn)證signer中的的簽名值
        ret = pkcs7_verify(pkcs7, usage);
        if (ret < 0)
                goto error;

        // 確定驗(yàn)證簽名的、且可信的issuer證書(shū)的來(lái)源
        if (!trusted_keys) {
                trusted_keys = builtin_trusted_keys;
        } else if (trusted_keys == (void *)1UL) {
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
                trusted_keys = secondary_trusted_keys;
#else
                trusted_keys = builtin_trusted_keys;
#endif
        }

        // 用system trusted keyring中的system trusted key作為signer的X.509證書(shū)來(lái)驗(yàn)證
        // PKCS#7中包含的每一個(gè)signer的簽名值。這里的邏輯很簡(jiǎn)單,既然PKCS#7中可能
        // 沒(méi)有包含signer的證書(shū),那么如果能在system trusted keyring中找到signer的證書(shū)
        // 來(lái)驗(yàn)證每一個(gè)signer的簽名值也是可以的。
        // 這里只考慮最簡(jiǎn)單的情況:signer信息中不包含X.509證書(shū)的情況。
        // 首先用auth_ids[0]、即通過(guò)signer.IssuerAndSerialNumbe字段
        // 計(jì)算出的key id在system trusted keyring中搜索與之匹配的system trusted key。
        // 如果沒(méi)有找到,返回-ENOKEY,同時(shí)打印錯(cuò)誤;如果找到匹配的system trusted key,
        // 則使用該key驗(yàn)證PKCS#7中的簽名。
        ret = pkcs7_validate_trust(pkcs7, trusted_keys);
        if (ret < 0) {
                if (ret == -ENOKEY)
                        pr_err("PKCS#7 signature not signed with a trusted keyn");
                goto error;
        }

        if (view_content) {
                size_t asn1hdrlen;

                ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
                if (ret < 0) {
                        if (ret == -ENODATA)
                                pr_devel("PKCS#7 message does not contain datan");
                        goto error;
                }

                ret = view_content(ctx, data, len, asn1hdrlen);
        }

error:
        pkcs7_free_message(pkcs7);
        pr_devel("<==%s() = %dn", __func__, ret);
        return ret;
}
EXPORT_SYMBOL_GPL(verify_pkcs7_signature);

#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */

查看builtin trusted keyring

$ sudo keyctl list %:.builtin_trusted_keys
6 keys in keyring:
...

所有builtin trusted keyring中的key都可以用來(lái)對(duì)內(nèi)核模塊進(jìn)行簽名。

FAQ

如何判斷一個(gè)內(nèi)核模塊是否簽過(guò)名?
有一種不太準(zhǔn)確的方法是直接檢查內(nèi)核模塊的二進(jìn)制內(nèi)容:

tail < module.ko >

如果有出現(xiàn)“ Module signature appended ”字樣,大多數(shù)情況下可以認(rèn)為該內(nèi)核模塊是有簽名的。之所以這里的措辭很謹(jǐn)慎,原因是這里沒(méi)有用科學(xué)的方法去解析該模塊的簽名格式是否正確,也沒(méi)有去驗(yàn)證里面的key是否真的有效。

如果添加額外的內(nèi)核模塊簽名key?

  • 在重編內(nèi)核的前提下,向CONFIG_MODULE_SIG_KEY指定的key文件級(jí)聯(lián)更多的key即可。
  • 在不重編內(nèi)核的前提下,借用CONFIG_SYSTEM_EXTRA_CERTIFICATE可以添加額外的內(nèi)核模塊簽名key。這種方法要求內(nèi)核在build時(shí)要事先保留足夠大的空間。如果該空間的總?cè)萘勘旧砭秃苄?,拿只能精?jiǎn)要導(dǎo)入的X.509證書(shū)的內(nèi)容;如果是因?yàn)橐呀?jīng)添加過(guò)別的額外的system trusted key或內(nèi)核模塊簽名key導(dǎo)致空間不足的話,可以考慮從內(nèi)核image中刪除其他不再使用的key。

如何刪除內(nèi)核模塊的簽名?

strip --keep-file-symbols < module_name >

Troubleshooting

加載內(nèi)核模塊時(shí)出現(xiàn)錯(cuò)誤“module verification failed: signature and/or required key missing - tainting kernel”
該錯(cuò)誤信息表示該內(nèi)核模塊沒(méi)有經(jīng)過(guò)簽名,但是由于內(nèi)核沒(méi)有開(kāi)啟強(qiáng)制驗(yàn)證,因此該內(nèi)核模塊還是被加載了。

加載內(nèi)核模塊時(shí)出現(xiàn)錯(cuò)誤“ERROR: could not insert module : Required key not available”(errno為-ENOKEY)
如果伴隨著這個(gè)錯(cuò)誤的同時(shí),內(nèi)核還報(bào)“PKCS#7 signature not signed with a trusted key”這個(gè)錯(cuò)誤的話,說(shuō)明被加載的模塊雖然經(jīng)過(guò)了簽名,但簽名key并不存在于builtin trusted keyring中,因此內(nèi)核無(wú)法驗(yàn)證簽名的有效性。

如果內(nèi)核沒(méi)有報(bào)“PKCS#7 signature not signed with a trusted key”這個(gè)錯(cuò)誤,說(shuō)明被加載的模塊根本沒(méi)有經(jīng)過(guò)簽名。

加載內(nèi)核模塊時(shí)出現(xiàn)錯(cuò)誤“ERROR: could not insert module : Key was rejected by service”(errno為-EKEYREJECTED)

說(shuō)明被加載的模塊雖然經(jīng)過(guò)了簽名,但簽名key并不存在于builtin system trusted keyring中,因此內(nèi)核拒絕加載該內(nèi)核模塊。

注意這個(gè)錯(cuò)誤與錯(cuò)誤“Required key not available”+“PKCS#7 signature not signed with a trusted key”的區(qū)別:后者表示簽名key與位于builtin system trusted keyring中的key是有關(guān)聯(lián)的,比如builtin system trusted keyring中只包含了父key,而簽名key是由父key簽發(fā)的;或者是builtin system trusted keyring中只包含了由父key簽發(fā)的簽名key,而簽名key是父key。前者則表示簽名key與位于builtin system trusted keyring中的key(如果有key的話)是沒(méi)有任何關(guān)聯(lián)性的。

另外之前碰到過(guò)一個(gè)case也會(huì)返回-EKEYREJECTED:trusted keyring里帶了2個(gè)不同的證書(shū),但是卻具有相同的issuer和serial number。問(wèn)題現(xiàn)象是:用這2個(gè)證書(shū)對(duì)應(yīng)的私鑰來(lái)簽名,總有一個(gè)會(huì)失敗。根因是認(rèn)證PKCS#7 signer簽名的時(shí)候,是用生成簽名的證書(shū)key id(issuer+證書(shū)序列號(hào))作為KEY來(lái)search trusted keyring的。因此,如果用第一個(gè)被search到的證書(shū)key id對(duì)應(yīng)的證書(shū)不是生成簽名的證書(shū),就會(huì)導(dǎo)致-EKEYREJECTED錯(cuò)誤。解決方法很簡(jiǎn)單:用不同的serial number來(lái)生成同一個(gè)CA生成的子證書(shū)。

對(duì)內(nèi)核模塊簽名后又strip導(dǎo)致內(nèi)核模塊簽名驗(yàn)證失敗

模塊一旦被簽名好,再次對(duì)其內(nèi)容的修改會(huì)導(dǎo)致簽名驗(yàn)證失敗。

這種修改可能有多種來(lái)源: - rpmbuild可能會(huì)考慮到減小initramfs的尺寸進(jìn)而在打包時(shí)strip掉內(nèi)核模塊的debuginfo。

RHEL 3.10的內(nèi)核模塊簽名格式

RHEL 3.10的簽名格式是redhat自己弄的,和standard linux kernel的格式不兼容。

連modinfo這個(gè)開(kāi)源工具,對(duì)模塊簽名格式的支持的code,也是redhat寫的。最新的modinfo對(duì)5.x的模塊簽名都不支持顯示,但能正確顯示3.10的redhat自己實(shí)現(xiàn)和port的模塊簽名的格式。

TODO

使用PKCS#11 URI進(jìn)行內(nèi)核模塊簽名

PKCS#11由RFC7512定義。它主要是定義了HSM的使用接口。雖然使用HSM不太方便,但是安全性還是有一定保障的,而且如果現(xiàn)場(chǎng)出了嚴(yán)重,必須親自上陣的話,用HSM可能反而是最穩(wěn)妥的辦法。

BUG

  • 如果內(nèi)核不支持內(nèi)核模塊簽名,但插入的內(nèi)核模塊是經(jīng)過(guò)簽名的,則插入失敗并返回-ENOPKG。
  • 在沒(méi)有啟用內(nèi)核簽名強(qiáng)制驗(yàn)證的情況下,如果模塊的簽名key不在builtin trusted keyring中,會(huì)被拒絕加載。
  • 在啟用內(nèi)核簽名強(qiáng)制驗(yàn)證的情況下,如果模塊沒(méi)有簽名的話,會(huì)報(bào)“PKCS#7 signature not signed with a trusted key”這個(gè)有誤導(dǎo)性的錯(cuò)誤信息。

附錄

簽名工具sign-file
sign-file工具的源碼位于kernel源碼目錄中的script目錄下。

用法

scripts/sign-file [-dp] < hash_algo > < private_key_name > 
    < x509_name > < module_name > [< dest_name >]
scripts/sign-file -s < raw_sig_name > < hash_algo > < x509_name > < module_name > [< dest >]

是簽名使用的摘要算法;是簽名的私鑰文件,支持pkcs#11或PEM格式;是與私鑰文件關(guān)聯(lián)的X.509證書(shū)文件(PEM或DER格式都可以);是被簽名的內(nèi)核模塊的名字;是簽名后的內(nèi)核模塊文件。

參數(shù)

-k
沒(méi)有指定-k參數(shù)的話,OpenSSL使用issuer name和issuer序列號(hào)來(lái)標(biāo)識(shí)簽名證書(shū);如果指定了-k參數(shù)的話,則使用subject key identifier(SKID)來(lái)標(biāo)識(shí)簽名證書(shū)。(注釋:證書(shū)的AKID表示父CA證書(shū)的SKID;如果一個(gè)證書(shū)的AKID等于SKID,表示該證書(shū)是自簽名的;因?yàn)閕ssuer name和issuer都存在重名的情況,因此x509 v3增加了SKID和AKID擴(kuò)展)。

默認(rèn)情況下,kbuild沒(méi)有設(shè)置該參數(shù)。

具體來(lái)說(shuō),在認(rèn)證PKCS#7 signer簽名的時(shí)候,是用生成簽名的證書(shū)key id(issuer+證書(shū)序列號(hào),由于沒(méi)有指定-k參數(shù))作為KEY來(lái)search trusted keyring的。

-p
將PKCS#7消息單獨(dú)存為以.p7s為后綴的文件??梢杂胦penssl pkcs7 -text -print -inform der -in .p7s來(lái)查看PKCS#7消息的詳細(xì)內(nèi)容。

默認(rèn)情況下,kbuild沒(méi)有設(shè)置該參數(shù)。

-s
指定由-p參數(shù)生成的.p7s文件作為內(nèi)核模塊簽名中的部分。

默認(rèn)情況下,kbuild沒(méi)有設(shè)置該參數(shù)。

-d
只是走一下簽名的流程,并不真的對(duì)模塊進(jìn)行簽名;同時(shí)兼具-p的功能。

默認(rèn)情況下,kbuild沒(méi)有設(shè)置該參數(shù)。

環(huán)境變量

KBUILD_SIGN_PIN:
該環(huán)境變量有兩個(gè)作用: - 在不使用PKCS#11訪問(wèn)簽名用私鑰的情況下,用來(lái)指定私鑰文件的解密口令。 - 在使用PKCS#11訪問(wèn)簽名用私鑰的情況下,用來(lái)指定PKCS#11的PIN碼。

源碼分析

sign-file會(huì)使用X.509證書(shū)中的issuer和serial來(lái)設(shè)置PKCS#7 signer info中的issuer和serial中的字段。因此,如果內(nèi)核模塊是由子key簽的,但放到system trusted keyring中只有父key的話,內(nèi)核在驗(yàn)證簽名時(shí)會(huì)使用issuer為父key+序號(hào)為子key證書(shū)的key id組合到system trusted keyring中查找匹配的key,結(jié)果肯定是不匹配。

模塊簽名的格式

< 內(nèi)核模塊的內(nèi)容 >
< PKCS#7消息 >
< 模塊簽名 >
< Mark字符串"~Module signature appended~n"(共28字節(jié),不包括結(jié)尾的NULL字符) >

PKCS#7消息的格式

PKCS#7是一種加密消息的語(yǔ)法標(biāo)準(zhǔn),由RSA安全體系在公鑰加密系統(tǒng)中交換數(shù)字證書(shū)產(chǎn)生的一種加密標(biāo)準(zhǔn)。有關(guān)其詳細(xì)格式,請(qǐng)參考RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5。

PKCS#7消息的格式的主體是content,共支持6種content類型:

  • data
  • signedData
  • envelopedData
  • signedAndEnvelopedData
  • digestedData
  • encryptedData

content的具體格式由content類型的定義來(lái)決定。目前內(nèi)核中的PKCS#7 parser僅支持content類型為signedData的PKCS#7消息。

下面是PKCS#7的格式定義:

ContentInfo ::= SEQUENCE {
     // 定義了content的類型。
     // 該字段的類型為:ContentType ::= OBJECT IDENTIFIER
     contentType ContentType,
     // content的具體格式由contentType字段的定義來(lái)決定。
     content
       [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }

生成signedData類型的PKCS#7消息

生成signedData類型的PKCS#7消息的過(guò)程如下:

  • Signer選定digest-encryption算法。
  • Signer將被簽名的數(shù)據(jù)以及authenticated attribute(如果有的話)作為輸入,計(jì)算出摘要值。 注意:authenticated attribute中真正參與摘要計(jì)算的只有DER格式的Attributes的值:
authenticatedAttributes
          [0] IMPLICIT Attributes OPTIONAL,

Attributes值的tag是SET OF,不包括前面的IMPLICIT [0] tag。

  • Signer將計(jì)算出來(lái)的摘要值和使用的摘要算法組織成下面的BER格式:
DigestInfo ::= SEQUENCE {
     digestAlgorithm DigestAlgorithmIdentifier, // 摘要算法OID
     digest Digest // 摘要值, 類型為OCTET STRING
   }
  • Signer用自己的私鑰對(duì)DigestInfo進(jìn)行加密。
  • 上述操作通常無(wú)需signer自己手動(dòng)完成,因?yàn)镻KCS#1 v1.5在底層會(huì)自動(dòng)完成上述操作。
  • 將Signer的證書(shū)以及關(guān)聯(lián)的issuer證書(shū)以及其他相關(guān)信息封裝成PKCS#7消息格式。

PKCS#7允許多個(gè)signer對(duì)相同的輸入內(nèi)容進(jìn)行簽名,每個(gè)簽名以及signer信息都會(huì)封裝到PKCS#7消息中。因此一個(gè)PKCS#7消息可以同時(shí)對(duì)多個(gè)signer進(jìn)行認(rèn)證。

signedData類型的PKCS#7消息格式詳解

signedData類型的PKCS#7消息由一組signer信息以及一組signer/issuer的證書(shū)組成。signer信息包括特定signer提供的簽名值,signer證書(shū)包括signer的實(shí)體信息以及公鑰。issuer證書(shū)用于對(duì)signer進(jìn)行身份認(rèn)證。

// PKCS#7類型為signedData的格式定義
   SignedData ::= SEQUENCE {
     // 表示PKCS#7消息格式語(yǔ)法的版本號(hào)
     // 該字段的類型為:Version ::= INTEGER
     version Version,

     // 表示所有signer使用的摘要算法的集合。
     // 該字段的類型為:
     // DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
     // DigestAlgorithmIdentifier ::= AlgorithmIdentifier
     digestAlgorithms DigestAlgorithmIdentifiers,

     // 包含被簽名的內(nèi)容。
     // contentType表示內(nèi)容的類型;content表示實(shí)際被簽名的內(nèi)容。
     // 注意:真正被簽名的只有content自身,不包括DER編碼中的id和長(zhǎng)度字段。
     // 如果content置空,表示真正被簽名的content不在PKCS#7中,這種情況被稱
     // 為detached content。
     // 該字段的類型為:
     // ContentInfo ::= SEQUENCE {
     //   contentType ContentType,
     //   content
     //     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
     contentInfo ContentInfo,

     // 一組證書(shū)PKCS#6格式的擴(kuò)展證書(shū)或X.509證書(shū)。理論上來(lái)說(shuō),signer的
     // 證書(shū),以及所有與signer相關(guān)聯(lián)的全部issuer證書(shū)甚至連根證書(shū)都可以放
     // 在該字段中,從而構(gòu)成一個(gè)證書(shū)層級(jí)結(jié)構(gòu);但實(shí)際上該字段也是可以為空的。
     // 該字段的類型為:
     // ExtendedCertificatesAndCertificates ::=
     //   SET OF ExtendedCertificateOrCertificate
     //   可以是PKCS#6格式的擴(kuò)展證書(shū)或X.509證書(shū)。
     //   ExtendedCertificateOrCertificate ::= CHOICE {
     //     certificate Certificate, -- X.509
     //     extendedCertificate [0] IMPLICIT ExtendedCertificate }
     certificates
        [0] IMPLICIT ExtendedCertificatesAndCertificates
          OPTIONAL,

     // 包含一組撤銷證書(shū)。
     // 該字段的類型為:
     // CertificateRevocationLists ::= SET OF CertificateRevocationList
     crls
       [1] IMPLICIT CertificateRevocationLists OPTIONAL,

     // 包含一組signer的相關(guān)信息
     signerInfos SignerInfos
   }

   // 包含一組signer的相關(guān)信息
   SignerInfos ::= SET OF SignerInfo
      // 包含每個(gè)signer的相關(guān)信息:signer使用的簽名證書(shū),摘要算法,
      // 簽名算法,簽名以及屬性字段等。
      SignerInfo ::= SEQUENCE {
        // 表示PKCS#7消息格式語(yǔ)法的版本號(hào)
        // 本字段的類型為: Version ::= INTEGER
        version Version,

        // 每個(gè)證書(shū)issuer都會(huì)為其所頒發(fā)的證書(shū)分配一個(gè)證書(shū)序列號(hào),且該
        // 序列號(hào)在其所頒發(fā)的所有證書(shū)中是唯一的。因此在給定證書(shū)issuer的
        // 專有名稱以及其頒發(fā)的證書(shū)序列號(hào)的共同作用下,本字段可以為用
        // 于唯一標(biāo)識(shí)指定證書(shū)issuer頒發(fā)的某個(gè)特定的證書(shū)。
        // 本字段的類型為: 
        // IssuerAndSerialNumber ::= SEQUENCE {
        //   issuer Name,  證書(shū)issuer的專有名稱
        //   serialNumber CertificateSerialNumber
        //  }
        issuerAndSerialNumber IssuerAndSerialNumber,

        // Signer使用的摘要算法
        // 本字段的類型為: DigestAlgorithmIdentifier ::= AlgorithmIdentifier
        digestAlgorithm DigestAlgorithmIdentifier,

        // 一組經(jīng)過(guò)簽名或認(rèn)證的屬性信息
        authenticatedAttributes
          [0] IMPLICIT Attributes OPTIONAL,

        //  Signer使用的簽名算法,比如PKCS#1 RSA。
        // 本字段的類型為: 
        //   DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
        digestEncryptionAlgorithm
          DigestEncryptionAlgorithmIdentifier,

        // 用signer的私鑰加密后的結(jié)果,即所謂的簽名值
        encryptedDigest EncryptedDigest,

        // 一組未經(jīng)簽名或認(rèn)證的屬性信息
        unauthenticatedAttributes
          [1] IMPLICIT Attributes OPTIONAL }

內(nèi)核模塊簽名中的PKCS#7消息

內(nèi)核對(duì)內(nèi)核模塊簽名中的PKCS#7消息格式有如下硬性要求:

  • PKCS#7消息的content類型必須是signedData。
  • contentInfo包含的data的content類型必須是data。
  • 版本號(hào)必須為1(表示PKCS#7 v1, 見(jiàn)RFC2315 9.1節(jié);或CMS v1,見(jiàn)RFC5652 5.1節(jié))或3( CMS v 3 RFC2315 5.1節(jié))。
  • 必須包含至少一個(gè)signer的信息。
  • 所有的signer信息都不能包含authenticatedAttributes字段。
  • 忽略所有的unauthenticatedAttributes字段。
  • 簽名算法必須是PKCS#1 RSA加密算法。

module_signature的格式

該簽名格式包含了模塊簽名的各種元數(shù)據(jù),并采用big endian編碼。

struct module_signature {
        uint8_t         algo;           /* Public-key crypto algorithm [0] */
        uint8_t         hash;           /* Digest algorithm [0] */
        uint8_t         id_type;        /* Key identifier type [PKEY_ID_PKCS7] */
        uint8_t         signer_len;     /* Length of signer's name [0] */
        uint8_t         key_id_len;     /* Length of key identifier [0] */
        uint8_t         __pad[3];
        uint32_t        sig_len;        /* Length of signature data */ htonl(size of .p7s)
};
  • algo 表示簽名算法ID,必須為0。
  • hash 表示摘要算法ID,必須為0。
  • id_type module的簽名格式,當(dāng)前僅支持PKEY_ID_PKCS7(2)。
  • signer_len 未使用,必須為0。
  • key_id_len 未使用,必須為0。
  • __pad[3] 填充字段,不使用,必須為0.
  • sig_len 表示PKCS#7消息字段的字節(jié)長(zhǎng)度。
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21608
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核

    ,需要了解Linux內(nèi)核的基本概念和API。以下是一些關(guān)鍵概念: 1.1 內(nèi)核模塊Linux內(nèi)核模塊是一種動(dòng)態(tài)加載和卸載的代碼,可以在不重
    的頭像 發(fā)表于 08-30 15:02 ?347次閱讀

    linux驅(qū)動(dòng)程序的編譯方法是什么

    Linux驅(qū)動(dòng)程序的編譯方法主要包括兩種: 與內(nèi)核一起編譯 和 編譯成獨(dú)立的內(nèi)核模塊 。以下是對(duì)這兩種方法的介紹: 一、與內(nèi)核一起編譯 與內(nèi)核
    的頭像 發(fā)表于 08-30 14:46 ?359次閱讀

    Linux內(nèi)核測(cè)試技術(shù)

    Linux 內(nèi)核Linux操作系統(tǒng)的核心部分,負(fù)責(zé)管理硬件資源和提供系統(tǒng)調(diào)用接口。隨著 Linux 內(nèi)核的不斷發(fā)展和更新,其復(fù)雜性和代碼規(guī)
    的頭像 發(fā)表于 08-13 13:42 ?406次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>測(cè)試技術(shù)

    NVIDIA全面轉(zhuǎn)向開(kāi)源GPU內(nèi)核模塊

    借助 R515 驅(qū)動(dòng)程序,NVIDIA 于 2022 年 5 月發(fā)布了一套開(kāi)源的 Linux GPU 內(nèi)核模塊,該模塊采用雙許可證,即 GPL 和 MIT 許可。初始版本主要面向數(shù)據(jù)中心計(jì)算 GPU,而 GeForce 和工作站
    的頭像 發(fā)表于 07-25 09:56 ?346次閱讀
    NVIDIA全面轉(zhuǎn)向開(kāi)源GPU<b class='flag-5'>內(nèi)核模塊</b>

    esp32c3安全啟動(dòng)文檔里的簽名,使用與計(jì)算的簽名和使用idf.py簽名有什么不同?

    esp32c3安全啟動(dòng)文檔里的簽名,使用與計(jì)算的簽名和使用idf.py簽名有什么不同?預(yù)簽名用的是--pub-key,普通的
    發(fā)表于 07-23 08:15

    英偉達(dá)將全面轉(zhuǎn)向開(kāi)源GPU內(nèi)核模塊

    英偉達(dá)公司近期宣布了一項(xiàng)重大決策,即全面轉(zhuǎn)向開(kāi)源GPU內(nèi)核模塊,并計(jì)劃最終以此取代閉源驅(qū)動(dòng)程序。這一戰(zhàn)略轉(zhuǎn)變標(biāo)志著英偉達(dá)在開(kāi)源領(lǐng)域邁出了重要一步,旨在為用戶提供更強(qiáng)大、更全面的Linux支持。
    的頭像 發(fā)表于 07-19 15:26 ?526次閱讀

    微軟發(fā)布Linux內(nèi)核Rust模塊優(yōu)化補(bǔ)丁

    在此之前,Linux 內(nèi)核中要想實(shí)現(xiàn)模塊初始化,必須先創(chuàng)建一個(gè)實(shí)例,再將其移至特定內(nèi)存空間。然而,經(jīng)過(guò)新補(bǔ)丁調(diào)整后,各模塊可直接在預(yù)設(shè)定好的內(nèi)存地址上完成初始化工作。
    的頭像 發(fā)表于 04-02 15:11 ?425次閱讀

    深入分析運(yùn)放的作用

    深入分析了4-20mA的運(yùn)放選型、A/D基準(zhǔn)電壓對(duì)測(cè)量精度影響等問(wèn)題。
    的頭像 發(fā)表于 01-15 13:47 ?3435次閱讀
    <b class='flag-5'>深入分析</b>運(yùn)放的作用

    RZ/G2L Linux系統(tǒng)如何添加新的內(nèi)核模塊

    RZ/G2L Linux系統(tǒng)的鏡像基于yocto構(gòu)建,本篇介紹如何添加新的內(nèi)核模塊。
    的頭像 發(fā)表于 01-04 12:19 ?1653次閱讀
    RZ/G2L <b class='flag-5'>Linux</b>系統(tǒng)如何添加新的<b class='flag-5'>內(nèi)核模塊</b>

    TQT507開(kāi)發(fā)板如何修改和保存內(nèi)核配置

    ,如果不存在,則使用默認(rèn)配置單。編譯前請(qǐng)使用原廠的配置單配置內(nèi)核。 進(jìn)入/Embedsky/TQT507/CoreA/longan/kernel/linux-4.9/arch/arm64
    的頭像 發(fā)表于 12-28 14:13 ?407次閱讀
    TQT507開(kāi)發(fā)板如何修改和保存<b class='flag-5'>內(nèi)核</b>配置

    【飛騰派4G版免費(fèi)試用】2.手把手實(shí)戰(zhàn)編譯Linux內(nèi)核

    modules.order# 內(nèi)核模塊加載順序的文件 scripts # 內(nèi)核腳本目錄 usr# 用戶空間的目錄 build_kernel.sh# 編譯內(nèi)核的腳本 Documenta
    發(fā)表于 12-16 23:28

    I.MX6ULL-ElfBoard ELF1板卡 獲取內(nèi)核源碼的方法。

    大家應(yīng)該對(duì)Linux操作系統(tǒng)有一定的了解,但可能還不知道我們拿到手的內(nèi)核源碼都經(jīng)歷了什么。 linux有一個(gè)龐大的開(kāi)源社區(qū),每個(gè)人都可以向開(kāi)源社區(qū)提交代碼。由于linux
    發(fā)表于 12-16 09:41

    獲取Linux內(nèi)核源碼的方法

    (ELF1/ELF1S開(kāi)發(fā)板及顯示屏)Linux內(nèi)核是操作系統(tǒng)中最核心的部分,它負(fù)責(zé)管理計(jì)算機(jī)硬件資源,并提供對(duì)應(yīng)用程序和其他系統(tǒng)組件的訪問(wèn)接口,控制著計(jì)算機(jī)的內(nèi)存、處理器、設(shè)備驅(qū)動(dòng)程序和文件系統(tǒng)等
    的頭像 發(fā)表于 12-13 09:49 ?606次閱讀
    獲取<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>源碼的方法

    Linux內(nèi)核自解壓過(guò)程分析

    uboot完成系統(tǒng)引導(dǎo)以后,執(zhí)行環(huán)境變量bootm中的命令;即,將Linux內(nèi)核調(diào)入內(nèi)存中并調(diào)用do_bootm函數(shù)啟動(dòng)內(nèi)核,跳轉(zhuǎn)至kernel的起始位置。
    的頭像 發(fā)表于 12-08 14:00 ?829次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>自解壓過(guò)程<b class='flag-5'>分析</b>

    Linux內(nèi)核slab性能優(yōu)化的核心思想

    今天分享一篇內(nèi)存性能優(yōu)化的文章,文章用了大量精美的圖深入淺出地分析Linux內(nèi)核slab性能優(yōu)化的核心思想,slab是Linux
    的頭像 發(fā)表于 11-13 11:45 ?584次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>slab性能優(yōu)化的核心思想