在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Kernel密碼學算法的軟件框架和接口模型

Linux閱碼場 ? 來源:Linux閱碼場 ? 作者:baron ? 2022-05-09 10:22 ? 次閱讀

說明:
在默認情況下,本文講述的都是ARMV8-aarch64架構,linux kernel 5.14

思考:

1、Linux Kernel中支持哪些密碼學算法?分別都是怎么實現的?哪些是C語言實現?哪些是Neon指令實現?哪些是ARM Cryptography Extension硬件實現?這些不同的實現方式,他們之間的關系是怎樣的?并列關系?多選一?多選多?

2、應用程序的密碼學算法一般又是怎樣實現的?應用程序的密碼學算法實現,是否依賴Kernel底層的密碼學算法?

3、應用程序是如何調用到Kernel底層的密碼學算法?Kernel底層的其它模塊,如何調用密碼學算法?

4、如何在Kernel底層增加一種密碼學算法的實現?

5、Kernel的其它模塊中,有哪些需要使用密碼學算法的場景?
本文術語定義:算法 :算法的種類,如對稱密碼算法、非對稱密碼算法...算法實現 :具體的某一類算法,如aes-cbc、aes-ebc、sm4-cbc、twofish-ecb...

目錄

1、密碼學基礎知識

2、Kernel密碼學算法的軟件框架和接口模型

2.1、Userspace對底層密碼算法的訪問2.2、Kernelspace對底層密碼算法的訪問2.3、增加一個算法實現

3、kernel中實現的算法實現

4、crypto engine的實現

5、代碼導讀

1、密碼學基礎知識

基本概念,如下請自行學習和理解:

  • 對稱密碼

  • 非對稱密碼

  • 數字摘要

  • 隨機數

2、Kernel密碼學算法的軟件框架和接口模型

Linux Kernel系統中實現了很多算法,這些算法被統一歸納為:對稱密碼算法、數字摘要算法、隨機數算法、認證加密算法、非對稱密碼算法等,并在Kernel層提供了統一操作的接口,供kernel其他模塊調用。部分算法又被封裝到了網絡層,開放暴露給Userspace。其具體的結構/接口模型如下所示:

2bb928b8-cf2c-11ec-bce3-dac502259ad0.png

2.1、Userspace對底層密碼算法的訪問

Userspace通過netlink接口方式( PF_ALG)調用到底層算法的實現

2bd320e2-cf2c-11ec-bce3-dac502259ad0.png

在Userspace,需指定socket接口 PF_ALG,需指定算法名稱(如skcipher)、需指定具體調用的"算法實現"(如aes-cbc),這樣命令傳輸到Kernel層,就能根據這些信息跳轉到響應的算法實現層。注意akcipher算法沒有暴露給網絡層,也就沒有開放給Userspace了,所以在User程序中,是無法調用Kernel層的非對稱密碼算法的。

如下是一個Userspace程序調用kernel底層算法的示例:

(1)建立一個socket會話的流程:

socket(AF_ALG,...)bind()setsockoptacceptsendmsgrecvmsg

(2)相關代碼

static int linux_af_alg_socket(const char *type, const char *name){  struct sockaddr_alg sa;  int s;
  s = socket(AF_ALG, SOCK_SEQPACKET, 0);  if (s < 0) {    LogErr("%s: Failed to open AF_ALG socket: %s
",         __func__, strerror(errno));    return -1;  }
  os_memset(&sa, 0, sizeof(sa));  sa.salg_family = AF_ALG;  os_strlcpy((char *) sa.salg_type, type, sizeof(sa.salg_type));  os_strlcpy((char *) sa.salg_name, name, sizeof(sa.salg_name));  if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {    LogErr("%s: Failed to bind AF_ALG socket(%s,%s): %s
",__func__, (char *) sa.salg_type, (char *) sa.salg_name, strerror(errno));    close(s);    return -1;  }
  return s;}
static struct linux_af_alg_skcipher *linux_af_alg_skcipher(const char *alg, const u8 *key, size_t key_len){  struct linux_af_alg_skcipher *skcipher;
  skcipher = os_zalloc(sizeof(*skcipher));  if (!skcipher)    goto fail;  skcipher->t = -1;
  skcipher->s = linux_af_alg_socket(TYPE_NAME, alg);  if (skcipher->s < 0)    goto fail;
  if (setsockopt(skcipher->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {    LogErr("%s: setsockopt(ALG_SET_KEY) failed: %s
",         __func__, strerror(errno));    goto fail;  }
  skcipher->t = accept(skcipher->s, NULL, NULL);  if (skcipher->t < 0) {    LogErr("%s: accept on AF_ALG socket failed: %s
",         __func__, strerror(errno));    goto fail;  }
  return skcipher;fail:  linux_af_alg_skcipher_deinit(skcipher);  return NULL;}
static int aes_128_cbc_oper(char *alg_name, const u8 *key,size_t key_len, int enc, const u8 *iv, u8 *data, size_t data_len){  struct linux_af_alg_skcipher *skcipher;  char buf[100];  struct iovec io[1];  struct msghdr msg;  struct cmsghdr *hdr;  ssize_t ret;  u32 *op;  struct af_alg_iv *alg_iv;  size_t iv_len = AES_BLOCK_SIZE;
  skcipher = linux_af_alg_skcipher(alg_name, key, key_len);//alg_name = "__cbc-aes-asr-ce"  if (!skcipher)    return -1;
  io[0].iov_base = (void *) data;  io[0].iov_len = data_len;  os_memset(&msg, 0, sizeof(msg));  os_memset(buf, 0, sizeof(buf));  msg.msg_control = buf;  msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +    CMSG_SPACE(sizeof(*alg_iv) + iv_len);  msg.msg_iov = io;  msg.msg_iovlen = 1;
  hdr = CMSG_FIRSTHDR(&msg);  hdr->cmsg_level = SOL_ALG;  hdr->cmsg_type = ALG_SET_OP;  hdr->cmsg_len = CMSG_LEN(sizeof(u32));  op = (u32 *) CMSG_DATA(hdr);  *op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
  hdr = CMSG_NXTHDR(&msg, hdr);  hdr->cmsg_level = SOL_ALG;  hdr->cmsg_type = ALG_SET_IV;  hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);  alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);  if(NULL != iv){    alg_iv->ivlen = iv_len;    os_memcpy(alg_iv->iv, iv, iv_len);  }else  {    alg_iv->ivlen = 0;  }
  ret = sendmsg(skcipher->t, &msg, 0);  if (ret < 0) {    LogErr("%s: sendmsg failed: %s
",         __func__, strerror(errno));    linux_af_alg_skcipher_deinit(skcipher);    return -1;  }
  ret = recvmsg(skcipher->t, &msg, 0);  if (ret < 0) {    LogErr("%s: recvmsg failed: %s
",         __func__, strerror(errno));    linux_af_alg_skcipher_deinit(skcipher);    return -1;  }  if ((size_t) ret < data_len) {    LogErr(         "%s: recvmsg not return full data (%d/%d)
",         __func__, (int) ret, (int) data_len);    linux_af_alg_skcipher_deinit(skcipher);    return -1;  }
  //s_to_binary(data,data_len);  linux_af_alg_skcipher_deinit(skcipher);  return 0;}
2.2、Kernelspace對底層密碼算法的訪問

Kernel程序對底層算法的調用采用函數直接調用的方式。流程為:kernel程序--->算法中間層--->算法實現層. 算法中間層 就是暴露給kernel其它模塊的API函數。

如下是一個kernel中調用底層算法的一個示例(因skcipher為例):

static int test_skcipher(void){        struct crypto_skcipher *tfm = NULL;        struct skcipher_request *req = NULL;        u8 *data = NULL;        const size_t datasize = 512; /* data size in bytes */        struct scatterlist sg;        DECLARE_CRYPTO_WAIT(wait);        u8 iv[16];  /* AES-256-XTS takes a 16-byte IV */        u8 key[64]; /* AES-256-XTS takes a 64-byte key */        int err;
        /*         * Allocate a tfm (a transformation object) and set the key.         *         * In real-world use, a tfm and key are typically used for many         * encryption/decryption operations.  But in this example, we'll just do a         * single encryption operation with it (which is not very efficient).         */
        tfm = crypto_alloc_skcipher("xts(aes)", 0, 0);        if (IS_ERR(tfm)) {                pr_err("Error allocating xts(aes) handle: %ld
", PTR_ERR(tfm));                return PTR_ERR(tfm);        }
        get_random_bytes(key, sizeof(key));        err = crypto_skcipher_setkey(tfm, key, sizeof(key));        if (err) {                pr_err("Error setting key: %d
", err);                goto out;        }
        /* Allocate a request object */        req = skcipher_request_alloc(tfm, GFP_KERNEL);        if (!req) {                err = -ENOMEM;                goto out;        }
        /* Prepare the input data */        data = kmalloc(datasize, GFP_KERNEL);        if (!data) {                err = -ENOMEM;                goto out;        }        get_random_bytes(data, datasize);
        /* Initialize the IV */        get_random_bytes(iv, sizeof(iv));
        /*         * Encrypt the data in-place.         *         * For simplicity, in this example we wait for the request to complete         * before proceeding, even if the underlying implementation is asynchronous.         *         * To decrypt instead of encrypt, just change crypto_skcipher_encrypt() to         * crypto_skcipher_decrypt().         */        sg_init_one(&sg, data, datasize);        skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |                                           CRYPTO_TFM_REQ_MAY_SLEEP,                                      crypto_req_done, &wait);        skcipher_request_set_crypt(req, &sg, &sg, datasize, iv);        err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);        if (err) {                pr_err("Error encrypting data: %d
", err);                goto out;        }
        pr_debug("Encryption was successful
");out:        crypto_free_skcipher(tfm);        skcipher_request_free(req);        kfree(data);        return err;}
2.3、增加一個算法實現

增加一個"算法的實現" 只需要:

  • 定義一個算法的結構體變量并初始化,其實就是實現其中的成員函數

  • 將該算法實現注冊到系統中。

結構體的定義并初始化:

static struct skcipher_alg aes_algs[] = {   {    .base.cra_name    = "__ecb(aes)",    .base.cra_driver_name  = "__ecb-aes-neonbs",    .base.cra_priority  = 250,    .base.cra_blocksize  = AES_BLOCK_SIZE,    .base.cra_ctxsize  = sizeof(struct aesbs_ctx),    .base.cra_module  = THIS_MODULE,    .base.cra_flags    = CRYPTO_ALG_INTERNAL,
    .min_keysize    = AES_MIN_KEY_SIZE,    .max_keysize    = AES_MAX_KEY_SIZE,    .walksize    = 8 * AES_BLOCK_SIZE,    .setkey      = aesbs_setkey,    .encrypt    = ecb_encrypt,    .decrypt    = ecb_decrypt,  }, 
  {    .base.cra_name    = "__cbc(aes)",    .base.cra_driver_name  = "__cbc-aes-neonbs",    .base.cra_priority  = 250,    .base.cra_blocksize  = AES_BLOCK_SIZE,    .base.cra_ctxsize  = sizeof(struct aesbs_cbc_ctx),    .base.cra_module  = THIS_MODULE,    .base.cra_flags    = CRYPTO_ALG_INTERNAL,
    .min_keysize    = AES_MIN_KEY_SIZE,    .max_keysize    = AES_MAX_KEY_SIZE,    .walksize    = 8 * AES_BLOCK_SIZE,    .ivsize      = AES_BLOCK_SIZE,    .setkey      = aesbs_cbc_setkey,    .encrypt    = cbc_encrypt,    .decrypt    = cbc_decrypt,  }};

成員函數的實現,例如:

static int ecb_encrypt(struct skcipher_request *req){  return __ecb_crypt(req, aesbs_ecb_encrypt);}

將該算法實現注冊到系統中:

static int __init aes_init(void){...  err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));...}module_init(aes_init);
小小總結一下, 如果您要增加一個算法實現,那么您就是需要實現定義如下結構體,并調用 crypto_register_xxx()注冊到kernel系統中:
  • skcipher_alg
  • akcipher_alg
  • ahash_alg
  • rng_alg
  • aead_alg

3、kernel中實現的算法實現

思考:

  • 對稱密碼底層是怎樣實現的?純軟?硬件?Neon指令?CE指令?

  • 非對稱密碼底層是怎樣實現的?

  • Hash、rng、aead 又都是怎樣實現的?

實現算法的方式:

  • (1)在armv8/armv9的芯片中,有ARM-CE指令可以進行aes/hash/md5計算,

  • (2)在armv8/armv9的芯片中,也有ARM-NEON指令也可以進行aes/hash/md5計算

  • (3)arm的security IP中,有cryptocell之類的加密芯片

  • (4)另外SOC廠商也可能集成自己設計的crypto engine加解密芯片

  • (5)除此之外,還有C語言、匯編程序等編程語言實現的純軟實現

毫無疑問,在效率這塊肯定是:(3)(4) > (1) > (2) > (5).另外從"實現算法的方式" 來看,如果是rng、aead、rsa之類的算法,那么就不能用ARM-CE這種方式,只有編程語言實現、Neon指令實現、crypto engine(含arm security IP)這幾種方式了。

kernel怎么玩的?:

  • 針對 crypto engine(含arm security IP) 這種,先當SOC硬件不支持,跳過此場景。

  • 針對rng、aead、rsa,那么kernel有一套純軟的實現 (似乎沒有看到arm neon指令的實現)

  • 針對aes、hash,有arm-ce的實現、arm neon指令的實現、純軟的實現,三者三選一(通過宏開關,只能選1)

crypto engine的實現:如果自定義了crypto engine的實現,那么要看你具體的設計,是設計成“取代原有算法實現”,還是設計成“新增算法實現”。如果是前者,那么對于aes/hash,則變成了四選一的了(crypto engine實現、arm-ce的實現、arm neon指令的實現、純軟)。如果是后者,這和原有實現不沖突。

有關aes/hash底層實現三選一的開關

(1) 開啟下面兩個宏,使用ARM Neon指令的實現 CONFIG_CRYPTO_AES_ARM64_CE_BLK CONFIG_CRYPTO_AES_ARM64_NEON_BLK(2) 在(1) 的基礎之上,再開啟如下宏,使用ARM CE指令的實現 USE_V8_CRYPTO_EXTENSIONS(3) 以上三個宏都不開啟的情況下,使用默認的純軟實現

4、crypto engine的實現

(以ARM Security IP的cryptocell 712為例)

2bf47fbc-cf2c-11ec-bce3-dac502259ad0.png

在Linux Kernel中開啟 CONFIG_CRYPTO_DEV_CCREE宏控即可起用該實現, 代碼路徑如下:

2c0e11ca-cf2c-11ec-bce3-dac502259ad0.png

以為aes-cbc為例,其實現的名字 和 Kernel中默認是算法實現的名字是一致的,即使這種實現方式是取代原有算法實現


{  .name = "cbc(aes)",  .driver_name = "cbc-aes-ccree",  .blocksize = AES_BLOCK_SIZE,  .template_skcipher = {    .setkey = cc_cipher_setkey,    .encrypt = cc_cipher_encrypt,    .decrypt = cc_cipher_decrypt,    .min_keysize = AES_MIN_KEY_SIZE,    .max_keysize = AES_MAX_KEY_SIZE,    .ivsize = AES_BLOCK_SIZE,  },  .cipher_mode = DRV_CIPHER_CBC,  .flow_mode = S_DIN_to_AES,  .min_hw_rev = CC_HW_REV_630,  .std_body = CC_STD_NIST,}

4、代碼導讀

在網絡層、算法中間層、算法實現層有著豐富的結構體類型?那么怎么去閱讀代碼?怎弄清各個層面之間的邏輯呢?事實上我們只要理清這些結構體之間的關系,將其抽象成模型,就會變得更加容易理解了。

如下是以Userspace調用底層的對稱密碼函數為例總結的一張數據結構圖:

2c29c6e0-cf2c-11ec-bce3-dac502259ad0.png

sock通信進入網絡層后(algifskcipher.c),構建skcipherrequest結構體,通過該結構體,就能尋址到底層的算法實現,繼而完成算法實現的調用。這些總結一下就是:

  • skcipher_request //網絡層構建的結構體

  • cryptoskcipher // kernel中間層構建的結構體,如果是kernel層調用底層算法,那么就從構建cryptocipher結構體開始。

  • skcipher_alg //算法實現層的結構體,描述著具體的算法實現,有實現廠商自己添加。

上述復雜的結構體流程,進一步抽象,就變成如下這個樣子:

2c495140-cf2c-11ec-bce3-dac502259ad0.png

既然如此,那么我們還可以舉一反三一下:

2c5cddc8-cf2c-11ec-bce3-dac502259ad0.png

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 算法
    +關注

    關注

    23

    文章

    4625

    瀏覽量

    93142
  • Linux
    +關注

    關注

    87

    文章

    11332

    瀏覽量

    210023
  • 代碼
    +關注

    關注

    30

    文章

    4814

    瀏覽量

    68849

原文標題:一文了解Linux Kernel中密碼學算法的設計與應用

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    商湯參與基于昇思AI框架的大模型原生開發成果發布

    近日,昇思人工智能框架峰會暨成果發布會在北京舉辦。AI框架作為大模型開發及產業落地的基礎軟件,在人工智能技術棧中起到使能算法開發、釋放硬件性
    的頭像 發表于 12-17 15:04 ?349次閱讀

    對稱加密技術在實際應用中如何保障數據安全?

    ,如使用安全的密鑰協商和密鑰分發方式,定期更換密鑰等。 密碼學原理的安全性: 對稱加密算法的安全性基于密碼學原理,需要確保密碼學原理的安全性,如避免使用弱
    的頭像 發表于 12-16 13:59 ?226次閱讀

    大語言模型開發框架是什么

    大語言模型開發框架是指用于訓練、推理和部署大型語言模型軟件工具和庫。下面,AI部落小編為您介紹大語言模型開發
    的頭像 發表于 12-06 10:28 ?160次閱讀

    AI算法/模型/框架/模型庫的含義、區別與聯系

    在人工智能(Artificial Intelligence,簡稱AI)的廣闊領域中,算法模型框架模型庫是構成其技術生態的重要基石。它們各自承擔著不同的角色,但又緊密相連,共同推動
    的頭像 發表于 07-17 17:11 ?4453次閱讀

    AI大模型與AI框架的關系

    多個領域取得顯著成果。而AI框架則是為開發和訓練AI模型提供的一套標準接口、特性庫和工具包,它集成了算法的封裝、數據的調用以及計算資源的使用,是AI
    的頭像 發表于 07-15 11:42 ?1194次閱讀

    鴻蒙開發:Universal Keystore Kit密鑰管理服務 密鑰派生介紹及算法規格

    密碼學中,密鑰派生函數(Key derivation function,KDF)使用偽隨機函數從諸如主密碼密碼的秘密值中派生出一個或多個密鑰。
    的頭像 發表于 07-11 16:30 ?357次閱讀

    鴻蒙開發接口安全:【@ohos.security.huks (通用密鑰庫系統)】

    向應用提供密鑰庫能力,包括密鑰管理及密鑰的密碼學操作等功能。 HUKS所管理的密鑰可以由應用導入或者由應用調用HUKS接口生成。
    的頭像 發表于 06-05 17:40 ?1373次閱讀
    鴻蒙開發<b class='flag-5'>接口</b>安全:【@ohos.security.huks (通用密鑰庫系統)】

    RED Semiconductor宣布推出算法微處理器ISA和硬件設計RISC-V

    4月2日,RED Semiconductor(以下簡稱 "RED")宣布推出算法微處理器 ISA(指令集架構)和硬件設計 VISC,將 RISC-V 的功能擴展到邊緣人工智能、自動駕駛和密碼學領域。
    的頭像 發表于 04-03 17:31 ?662次閱讀

    NVIDIA宣布推出基于Omniverse Cloud API構建的全新軟件框架

    NVIDIA 在 GTC 大會上宣布推出基于 Omniverse Cloud API(應用編程接口)構建的全新軟件框架
    的頭像 發表于 03-25 09:09 ?560次閱讀

    恩智浦:向后量子密碼學遷移,我們應該怎么做?

    在之前的博文中,我們介紹了由美國國家標準與技術研究院 (NIST) 主導的后量子密碼學 (PQC) 標準化進程,以及未來可能采用的部分PQC標準。在這篇博文中,我們探討PQC遷移過程中面臨的一些挑戰
    的頭像 發表于 03-22 09:39 ?1683次閱讀
    恩智浦:向后量子<b class='flag-5'>密碼學</b>遷移,我們應該怎么做?

    OpenVINO?協同Semantic Kernel:優化大模型應用性能新路徑

    作為主要面向 RAG 任務方向的框架,Semantic Kernel 可以簡化大模型應用開發過程,而在 RAG 任務中最常用的深度學習模型就是 Embedding 和 Text com
    的頭像 發表于 03-08 10:41 ?763次閱讀
    OpenVINO?協同Semantic <b class='flag-5'>Kernel</b>:優化大<b class='flag-5'>模型</b>應用性能新路徑

    自制測試框架(設置界面密碼1)

    (設置界面密碼為1) 目前支持的指令如下: 1.沒有任何編程基礎的人快速實現簡易自動化制作; 2.測試后可以直接把數據和結果直接寫入到MES; 3.可持續增加新的功能及模塊; 4.快速實現點
    發表于 03-02 19:33

    谷歌模型框架是什么軟件?谷歌模型框架怎么用?

    谷歌模型框架通常指的是谷歌開發的用于機器學習和人工智能的軟件框架,其中最著名的是TensorFlow。TensorFlow是一個開源的機器學習框架
    的頭像 發表于 03-01 16:25 ?932次閱讀

    數據語料庫、算法框架和算力芯片在AI大模型中的作用和影響

    數據語料庫、算法框架和算力芯片的確是影響AI大模型發展的三大重要因素。
    的頭像 發表于 03-01 09:42 ?1222次閱讀

    谷歌模型框架是什么?有哪些功能和應用?

    谷歌模型框架(Google Model Framework)并不是一個特定的框架,而是指谷歌開發的一系列軟件框架,用于支持機器學習和人工智能
    的頭像 發表于 02-29 18:11 ?1552次閱讀
    主站蜘蛛池模板: 亚在线| 久久97精品久久久久久久看片| 韩国理论片2023现在观看| 精品四虎免费观看国产高清午夜| 亚洲网色| 热re99久久国产精品| 哥也操| 日日日干干干| www.嫩草影院| 老色批在线播放视频网站免费| 五月激情五月婷婷| 中文字幕在线观看第一页| h视频在线免费看| 999久久久国产精品| 天堂中文最新版www| 一级一级一片免费高清| 国产三级黄色毛片| 黄视频福利| 六月丁香婷婷激情| 国产乱辈通伦影片在线播放亚洲| 在线观看黄a| 九九热在线免费观看| 男人cao女人视频在线观看| 91精品啪国产在线观看免费牛牛| 717影院理伦午夜论八戒| 手机在线观看免费视频| 岛国午夜精品视频在线观看| 男操女视频在线观看| 国产成人精品日本亚洲语音1| 日本在线亚洲| 18videosex欧美69| 69精品在线| 亚偷熟乱区视频在线观看| 日本色图网站| 嫩草黄色影院| 免费永久欧美性色xo影院| 女人张开腿让男人桶视频免费大全| 国产一区二区高清| 超色视频| 夜夜夜夜夜夜夜猛噜噜噜噜噜噜| 综综综综合网|