例子

  • aes_generic.c - crypto/aes_generic.c - Linux source code (v5.15.11) - Bootlin
static struct crypto_alg aes_alg = {.cra_name       =  "aes",.cra_driver_name    =  "aes-generic",.cra_priority       =  100,.cra_flags      =  CRYPTO_ALG_TYPE_CIPHER,.cra_blocksize       =  AES_BLOCK_SIZE,.cra_ctxsize     =  sizeof(struct crypto_aes_ctx),.cra_module       =  THIS_MODULE,.cra_u          =  {.cipher = {.cia_min_keysize   =  AES_MIN_KEY_SIZE,.cia_max_keysize   =  AES_MAX_KEY_SIZE,.cia_setkey        =  crypto_aes_set_key,.cia_encrypt     =  crypto_aes_encrypt,.cia_decrypt     =  crypto_aes_decrypt}}
};
  • 从上述定义可知AES算法的属性信息,如下所示:

    • a)算法名为"aes",算法驱动名为"aes-generic"。
    • b)算法的优先级为100  使用的时候,如未特殊指定,按照优先级高低进行使用
    • c)算法的分组长度为AES_BLOCK_SIZE(16)字节
    • d)算法类型为CRYPTO_ALG_TYPE_CIPHER(即分组算法),其个性化属性数据结构为struct cipher_alg,定义如下所示:

cipher_alg

/*** DOC: Block Cipher Algorithm Definitions** These data structures define modular crypto algorithm implementations,* managed via crypto_register_alg() and crypto_unregister_alg().*//*** struct cipher_alg - single-block symmetric ciphers definition* @cia_min_keysize: Minimum key size supported by the transformation. This is*          the smallest key length supported by this transformation*           algorithm. This must be set to one of the pre-defined*          values as this is not hardware specific. Possible values*           for this field can be found via git grep "_MIN_KEY_SIZE"*             include/crypto/* @cia_max_keysize: Maximum key size supported by the transformation. This is*         the largest key length supported by this transformation*            algorithm. This must be set to one of the pre-defined values*           as this is not hardware specific. Possible values for this*         field can be found via git grep "_MAX_KEY_SIZE"*          include/crypto/* @cia_setkey: Set key for the transformation. This function is used to either*         program a supplied key into the hardware or store the key in the*           transformation context for programming it later. Note that this*            function does modify the transformation context. This function*         can be called multiple times during the existence of the*           transformation object, so one must make sure the key is properly*           reprogrammed into the hardware. This function is also*          responsible for checking the key length for validity.* @cia_encrypt: Encrypt a single block. This function is used to encrypt a*        single block of data, which must be @cra_blocksize big. This*      always operates on a full @cra_blocksize and it is not possible*       to encrypt a block of smaller size. The supplied buffers must*      therefore also be at least of @cra_blocksize size. Both the*       input and output buffers are always aligned to @cra_alignmask.*        In case either of the input or output buffer supplied by user*      of the crypto API is not aligned to @cra_alignmask, the crypto*        API will re-align the buffers. The re-alignment means that a*       new buffer will be allocated, the data will be copied into the*         new buffer, then the processing will happen on the new buffer,*         then the data will be copied back into the original buffer and*         finally the new buffer will be freed. In case a software*       fallback was put in place in the @cra_init call, this function*        might need to use the fallback if the algorithm doesn't support*       all of the key sizes. In case the key was stored in*        transformation context, the key might need to be re-programmed*         into the hardware in this function. This function shall not*        modify the transformation context, as this function may be*         called in parallel with the same transformation object.* @cia_decrypt: Decrypt a single block. This is a reverse counterpart to*       @cia_encrypt, and the conditions are exactly the same.** All fields are mandatory and must be filled.*/
struct cipher_alg {unsigned int cia_min_keysize;unsigned int cia_max_keysize;int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,unsigned int keylen);void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
};

分组算法个性化属性包括2个参数和3个算法 接口,如上所示:

2个参数

  • 分组算法输入密钥长度的下限cia_min_keysize和上限cia_max_keysize
  • AES算法密钥长度的下限和上限分别为AES_MIN_KEY_SIZE(16)、AES_MAX_KEY_SIZE(32),但实际上AES算法只支持16B(128bit)、24B(192bit)和32B(256bit)三种密钥长度,如果输入密钥的长度为其他值,在进行密钥扩展(crypto_aes_expand_key)时将返回参数错误,如下所示:

三个算法接口

  • 分组算法的算法接口,包括密钥设置接口cia_setkey、加密接口cia_encrypt和解密接口cia_decrypt,算法运行的上下文空间由算法实例tfm提供。
  • AES算法的三个算法接口分别为crypto_aes_set_key、aes_encrypt和aes_decrypt。从AES算法加密接口和解密接口的实现流程来看,每次处理一个分组(16B)的数据。
  • AES算法运行的上下文空间是数据结构struct crypto_aes_ctx的一个实例,该数据结构定义(root/include/crypto/aes.h)如下所示:
  • aes.h - include/crypto/aes.h - Linux source code (v5.15.11) - Bootlin

crypto_aes_ctx

/** Please ensure that the first two fields are 16-byte aligned* relative to the start of the structure, i.e., don't move them!*/
struct crypto_aes_ctx {u32 key_enc[AES_MAX_KEYLENGTH_U32];u32 key_dec[AES_MAX_KEYLENGTH_U32];u32 key_length;
};
  • AES算法上下文数据结构包括密钥扩展后的加密密钥key_enc和解密密钥key_dec以及输入的密钥长度key_length。
  • 注:由于算法应用不会直接使用AES算法的算法接口,因此其算法说明aes_alg未设置算法类型常量cra_type。

crypto_aes_set_key

aes_expandkey

  • aes.c - lib/crypto/aes.c - Linux source code (v5.15.11) - Bootlin
/*** aes_expandkey - Expands the AES key as described in FIPS-197* @ctx:    The location where the computed key will be stored.* @in_key:  The supplied key.* @key_len:   The length of the supplied key.** Returns 0 on success. The function fails only if an invalid key size (or* pointer) is supplied.* The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes* key schedule plus a 16 bytes key which is used before the first round).* The decryption key is prepared for the "Equivalent Inverse Cipher" as* described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is* for the initial combination, the second slot for the first round and so on.*/
int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,unsigned int key_len)
{u32 kwords = key_len / sizeof(u32);u32 rc, i, j;int err;err = aes_check_keylen(key_len);if (err)return err;ctx->key_length = key_len;for (i = 0; i < kwords; i++)ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32));for (i = 0, rc = 1; i < 10; i++, rc = mul_by_x(rc)) {u32 *rki = ctx->key_enc + (i * kwords);u32 *rko = rki + kwords;rko[0] = ror32(subw(rki[kwords - 1]), 8) ^ rc ^ rki[0];rko[1] = rko[0] ^ rki[1];rko[2] = rko[1] ^ rki[2];rko[3] = rko[2] ^ rki[3];if (key_len == AES_KEYSIZE_192) {if (i >= 7)break;rko[4] = rko[3] ^ rki[4];rko[5] = rko[4] ^ rki[5];} else if (key_len == AES_KEYSIZE_256) {if (i >= 6)break;rko[4] = subw(rko[3]) ^ rki[4];rko[5] = rko[4] ^ rki[5];rko[6] = rko[5] ^ rki[6];rko[7] = rko[6] ^ rki[7];}}/** Generate the decryption keys for the Equivalent Inverse Cipher.* This involves reversing the order of the round keys, and applying* the Inverse Mix Columns transformation to all but the first and* the last one.*/ctx->key_dec[0] = ctx->key_enc[key_len + 24];ctx->key_dec[1] = ctx->key_enc[key_len + 25];ctx->key_dec[2] = ctx->key_enc[key_len + 26];ctx->key_dec[3] = ctx->key_enc[key_len + 27];for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) {ctx->key_dec[i]     = inv_mix_columns(ctx->key_enc[j]);ctx->key_dec[i + 1] = inv_mix_columns(ctx->key_enc[j + 1]);ctx->key_dec[i + 2] = inv_mix_columns(ctx->key_enc[j + 2]);ctx->key_dec[i + 3] = inv_mix_columns(ctx->key_enc[j + 3]);}ctx->key_dec[i]     = ctx->key_enc[0];ctx->key_dec[i + 1] = ctx->key_enc[1];ctx->key_dec[i + 2] = ctx->key_enc[2];ctx->key_dec[i + 3] = ctx->key_enc[3];return 0;
}
EXPORT_SYMBOL(aes_expandkey);

aes_encrypt

  • aes.c - lib/crypto/aes.c - Linux source code (v5.15.11) - Bootlin
/*** aes_encrypt - Encrypt a single AES block* @ctx:    Context struct containing the key schedule* @out:  Buffer to store the ciphertext* @in:       Buffer containing the plaintext*/
void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in)
{const u32 *rkp = ctx->key_enc + 4;int rounds = 6 + ctx->key_length / 4;u32 st0[4], st1[4];int round;st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in);st0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4);st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8);st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12);/** Force the compiler to emit data independent Sbox references,* by xoring the input with Sbox values that are known to add up* to zero. This pulls the entire Sbox into the D-cache before any* data dependent lookups are done.*/st0[0] ^= aes_sbox[ 0] ^ aes_sbox[ 64] ^ aes_sbox[134] ^ aes_sbox[195];st0[1] ^= aes_sbox[16] ^ aes_sbox[ 82] ^ aes_sbox[158] ^ aes_sbox[221];st0[2] ^= aes_sbox[32] ^ aes_sbox[ 96] ^ aes_sbox[160] ^ aes_sbox[234];st0[3] ^= aes_sbox[48] ^ aes_sbox[112] ^ aes_sbox[186] ^ aes_sbox[241];for (round = 0;; round += 2, rkp += 8) {st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0];st1[1] = mix_columns(subshift(st0, 1)) ^ rkp[1];st1[2] = mix_columns(subshift(st0, 2)) ^ rkp[2];st1[3] = mix_columns(subshift(st0, 3)) ^ rkp[3];if (round == rounds - 2)break;st0[0] = mix_columns(subshift(st1, 0)) ^ rkp[4];st0[1] = mix_columns(subshift(st1, 1)) ^ rkp[5];st0[2] = mix_columns(subshift(st1, 2)) ^ rkp[6];st0[3] = mix_columns(subshift(st1, 3)) ^ rkp[7];}put_unaligned_le32(subshift(st1, 0) ^ rkp[4], out);put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4);put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8);put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12);
}
EXPORT_SYMBOL(aes_encrypt);

aes_decrypt

  • aes.c - lib/crypto/aes.c - Linux source code (v5.15.11) - Bootlin
/*** aes_decrypt - Decrypt a single AES block* @ctx:    Context struct containing the key schedule* @out:  Buffer to store the plaintext* @in:        Buffer containing the ciphertext*/
void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in)
{const u32 *rkp = ctx->key_dec + 4;int rounds = 6 + ctx->key_length / 4;u32 st0[4], st1[4];int round;st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in);st0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4);st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8);st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12);/** Force the compiler to emit data independent Sbox references,* by xoring the input with Sbox values that are known to add up* to zero. This pulls the entire Sbox into the D-cache before any* data dependent lookups are done.*/st0[0] ^= aes_inv_sbox[ 0] ^ aes_inv_sbox[ 64] ^ aes_inv_sbox[129] ^ aes_inv_sbox[200];st0[1] ^= aes_inv_sbox[16] ^ aes_inv_sbox[ 83] ^ aes_inv_sbox[150] ^ aes_inv_sbox[212];st0[2] ^= aes_inv_sbox[32] ^ aes_inv_sbox[ 96] ^ aes_inv_sbox[160] ^ aes_inv_sbox[236];st0[3] ^= aes_inv_sbox[48] ^ aes_inv_sbox[112] ^ aes_inv_sbox[187] ^ aes_inv_sbox[247];for (round = 0;; round += 2, rkp += 8) {st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0];st1[1] = inv_mix_columns(inv_subshift(st0, 1)) ^ rkp[1];st1[2] = inv_mix_columns(inv_subshift(st0, 2)) ^ rkp[2];st1[3] = inv_mix_columns(inv_subshift(st0, 3)) ^ rkp[3];if (round == rounds - 2)break;st0[0] = inv_mix_columns(inv_subshift(st1, 0)) ^ rkp[4];st0[1] = inv_mix_columns(inv_subshift(st1, 1)) ^ rkp[5];st0[2] = inv_mix_columns(inv_subshift(st1, 2)) ^ rkp[6];st0[3] = inv_mix_columns(inv_subshift(st1, 3)) ^ rkp[7];}put_unaligned_le32(inv_subshift(st1, 0) ^ rkp[4], out);put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4);put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8);put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12);
}
EXPORT_SYMBOL(aes_decrypt);

Linux加密框架crypto AES代码相关相关推荐

  1. Linux加密框架 crypto算法模板 以及CBC算法模板实例

    参考链接 Linux加密框架中的主要数据结构(四)_家有一希的博客-CSDN博客 algapi.h - include/crypto/algapi.h - Linux source code (v5. ...

  2. linux加密框架 crypto 算法管理 - 哈希算法应用实例

    参考链接 Linux加密框架应用示例(二)_家有一希的博客-CSDN博客 linux加密框架 crypto 算法管理 - 应用角度讲解加密框架的运行流程_CHYabc123456hh的博客-CSDN博 ...

  3. linux加密框架 crypto 算法管理 - 算法查找接口 crypto_find_alg

    算法查找接口crypto_find_alg 算法实例tfm是算法的一个可运行的副本,因此在创建算法实例前首先要查找确认算法是否已经注册有效,此时算法查找由函数crypto_find_alg实现. 补充 ...

  4. linux加密框架 crypto 算法管理 - 算法查找接口

    参考链接 Linux加密框架的算法管理(二)_家有一希的博客-CSDN博客 linux加密框架 crypto 算法管理 - 算法查找接口 crypto_find_alg_CHYabc123456hh的 ...

  5. linux加密框架 crypto 算法管理 - 算法查找接口 crypto_alg_mod_lookup

    参考链接 Linux加密框架的算法管理(二)_家有一希的博客-CSDN博客 linux加密框架 crypto 算法管理 - 算法查找接口 crypto_find_alg_CHYabc123456hh的 ...

  6. Linux加密框架 crypto 算法模板 HMAC模板举例

    参考链接 Linux加密框架中的主要数据结构(三)_家有一希的博客-CSDN博客 Linux加密框架 crypto 算法模板_CHYabc123456hh的博客-CSDN博客 HMAC算法模板 hma ...

  7. Linux加密框架 crypto 哈希算法举例 MD5

    参考链接 Linux加密框架 crypto 哈希算法说明 同步哈希shash_alg | 异步哈希 ahash_alg | 通用部分抽象 hash_alg_common_CHYabc123456hh的 ...

  8. Linux crypto相关知识的汇总 Linux加密框架crypto对称算法和哈希算法加密模式

    参考链接 Linux加密框架中的算法和算法模式(二)_家有一希的博客-CSDN博客 对称算法 分组算法模式 ECB模式 ECB模式下,明文数据被分为大小合适的分组,然后对每个分组独立进行加密或解密 如 ...

  9. linux加密框架 crypto 算法管理 - 动态和静态算法管理

    参考链接 Linux加密框架的算法管理(三)_家有一希的博客-CSDN博客 动态和静态算法管理 静态算法 加密框架中的算法分为静态算法和动态算法两种,其中静态算法指的是以"算法名.ko&qu ...

最新文章

  1. VS.NET 学习方法论
  2. java中原生方法_java中原生(native)函数的用法
  3. Python大佬 | 菜鸟进阶必备的九大技能!
  4. 【Android 逆向】ptrace 函数 ( C 标准库 ptrace 函数简介 | ptrace 函数真实作用 )
  5. 《漫画算法》源码整理-4 大顶堆 小顶堆 优先队列
  6. android 提高性能点
  7. jQuery中DOM操作方法 之 html,text,val
  8. createprocess重启程序_C++_VC程序设计中CreateProcess用法注意事项,对于windows程序设计来说,启动 - phpStudy...
  9. 鼠标点击时隐藏java代码,js实现点击展开隐藏效果(实例代码)
  10. 详述由ENQ:TX – ROW LOCK CONTENTION引起的全局死锁处理过程
  11. c语言输入相应的成绩评定信息,C语言机练习题记答案.doc
  12. SQL里面也能用Split()
  13. python的copy模块是哪个模块_每周一个 Python 模块 | copy
  14. php常用加密函数总结
  15. php--变量与常量
  16. PB设置表格背景颜色
  17. 携程网今日瘫痪 官方称遭到不明攻击
  18. 【深坑】记一次MacBook pro 恢复出厂设置抹盘重装系统
  19. 信息学奥赛一本通2066
  20. Java的“小心心”

热门文章

  1. qr分解求线性方程组_梯度下降求解线性方程组算例设计
  2. 【转】三、QT例子-打开一个图片并且显示
  3. 【转】WebApi 身份认证解决方案:Basic基础认证
  4. 【转】c#中@的3种作用
  5. C#多线程之旅(七)——终止线程
  6. 【转】TFS上分支和标签的用法
  7. ssh中c3p0连接mysql_ssh 中使用c3p0 的连接池配置 | 学步园
  8. 关于报错:'nvidia-smi' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  9. c/c++,字符,字符串,各种方式读入与对空格,回车的处理
  10. Coursera自动驾驶课程第5讲:Vehicle Dynamic Modeling