[0]ã€ã³ãã
ã«ãŒãã«ããŒãžã§ã³2.5.45ããå°å
¥ãããLinuxæå·åAPI ã ãã以æ¥ã Crypto APIã¯ãã¹ãŠã®äžè¬çãªïŒã ãã§ãªãïŒåœéæšæºãè¶
ããŠæé·ããŸããã
- 察称æå·åïŒ AES ã Blowfish ã...
- ããã·ã¥ïŒ SHA1 / 256/512 ã MD5 ã...
- æš¡é å ïŒ hMAC-SHA1 / 256 / 512 ã hMAC-MD5 ã...
- AEAD ïŒ AES-GCM ã ChaCha20-Poly1305 ã...
- æ¬äŒŒä¹±æ°çæïŒ FIPS ã...
- é察称æå·åïŒ RSA
- éµåæïŒ DH ã ECDH
- å§çž®ïŒ Deflate ã ZLIB
ãã®æå·åã¯ã IPsec ã dm-cryptãªã©ãããŸããŸãªã«ãŒãã«ãµãã·ã¹ãã ïŒ ã«ãŒãã«ã¹ããŒã¹å
ïŒã§äž»ã«äœ¿çšãããŸãã ãŠãŒã¶ãŒç©ºéããã®Crypto API颿°ã®äœ¿çšã¯ãããŒãžã§ã³ããå§ãŸãNetlinkã€ã³ã¿ãŒãã§ãŒã¹ã§ãå¯èœã§ãã 2.6.38ã«ãŒãã«ã¯ã_AF ALGãã¡ããªãŒãå°å
¥ãã ãŠãŒã¶ãŒç©ºéã³ãŒãããã«ãŒãã«æå·åãžã®ã¢ã¯ã»ã¹ãæäŸããŸãã ãã ããæ¢åã®æ©èœã§ã¯ååã§ãªãå Žåããããããæ°ããã¢ã«ãŽãªãºã ã䜿çšããŠCrypto APIãæ¡åŒµããå¿
èŠããããŸãã
ãã®ãããçŽ2幎åãç§ã¯Linuxã«ãŒãã« ïŒããŒãžã§ã³3.13ïŒã®IPsecå®è£
ã«ïŒãã©ã«ãŒã·å
±ååœã®ïŒåœå®¶æå·åãçµã¿èŸŒããšãã課é¡ã«çŽé¢ããŸããã åœæãç§ã¯ã«ãŒãã«ç©ºéã§ããã°ã©ãã³ã°ãè¡ã£ãããšããªãããããã«ãŒãã«ã¢ãžã¥ãŒã«ãæžããåããŠã®çµéšã§ããã Robert Loveã®èæž ã The Linux KernelãDevelopment Processã®èª¬æãã¯ç§ã倧ãã«å©ããŠãããŸããã Crypto APIèªäœã«å¯ŸåŠããããšã¯ã¯ããã«å°é£ã§ãã-èšåãããæ¬ã§ã¯ããã®åé¡ã¯ååãšããŠã«ããŒãããŠãããã å
¬åŒããã¥ã¡ã³ãã§ã¯ãã¢ãŒããã¯ãã£ã®ããªã詳现ãªèª¬æãæäŸãããŠããŸãããæ°ããã¢ã«ãŽãªãºã ã®å®è£
ã«é¢ããæ
å ±ã¯å®è³ªçã«ãããŸããã ç§ã®æ€çŽ¢ã§ã¯ãHackerãã¬ãžã³ã§ãCrypto APIã®äœ¿ç𿹿³ã«ã€ããŠäžè¬çã«èªãçŽ æŽãããèšäºã«åºäŒããŸãããããã®æ¡åŒµã«ã€ããŠã®èšèã¯ãããŸããã æåŸã«ãå¿
èŠãªç¥èãåŸãããã«ããœãŒã¹ïŒã«ãŒãã«ã³ãŒãïŒã«ç®ãåããåé¡ã解決ããŸããã
ãããããã°ããçµã¡ãŸããããä»ã«ãªã£ãŠããããç¥èãæŽæ°ãããã®ããã¹ããæžãå§ããŸããã Crypto APIã«ã€ããŠã§ãã å
·äœçãªäŸãšããŠãä»»æã®ã¢ã«ãŽãªãºã ãCrypto APIã«åãèŸŒãæ¹æ³ãããã³ã«ãŒãã«ç©ºéãšãŠãŒã¶ãŒç©ºéã®äž¡æ¹ãããããã«ã¢ã¯ã»ã¹ããæ¹æ³ã確èªããŸãã ãã®è³æã¯ãåæ§ã®åé¡ã«çŽé¢ããŠããéçºè
ã«ãšã£ãŠéåžžã«åœ¹ç«ã€ãšç¢ºä¿¡ããŠããŸãããã«ãžã¥ã¢ã«ãªèªè
ãããã§èªåã«ãšã£ãŠè峿·±ããã®ãèŠã€ããããããšãé¡ã£ãŠããŸãã ç«ãžããããïŒ
PSç§ã®ããã°ã©ã ã®ã³ã³ãã€ã«ããããœãŒã¹ã¯ããã®æçã¯ä»¥äžã«ãããŸããã githubã§å
¥æã§ããŸãã ãã®èšäºã®ãœãŒã¹ããããŸãã ãã¹ãŠã®ã³ãŒãã¯ãã«ãŒãã«ããŒãžã§ã³4.13.0-32-genericã䜿çšãããã¹ã¯ãããUbuntu 16.04 LTSã§äœæããã³ãã¹ããããŠããŸãã ã¢ãžã¥ãŒã«ã§äœ¿çšããã€ã³ã¿ãŒãã§ã€ã¹ã®ããã€ãã¯4ã€ã®ã«ãŒãã«ããŒãžã§ã³ã§å°å
¥ãããããã3ãã«ãŒãã«*ééããªãã³ã³ãã€ã«ãããŸãã ã
[1] Crypto APIã¢ãŒããã¯ãã£
ã³ãŒããæžãå§ããåã«ã Crypto APIã§ãã¹ãŠãã©ã®ããã«æ©èœãããã«ã€ããŠå°ã話ããŸãããã ãããããããã¯ç§ã®åã®ããã¥ã¡ã³ãã§è©³çްã«èª¬æãããŠããŸããããç§ã¯é çªã«ãææãçè§£ããã®ã«ååãªã¯ãã§ããå§æŸãäžããã ãã§ãã ããã«äºçŽããŸãããã®åŸãäž»ã«å¯Ÿç§°æå·åãä»ã®ã¿ã€ãã®æå·å€æãäž»ã«åŠçããŸãããäžè¬çã«ã¯åæ§ã«æ©èœããŸãããå€ãã®ãã¥ã¢ã³ã¹ããã¹ãŠãéåžžã«è€éã«ããŸãã
ãããã£ãŠãå°å
¥ãããã«ãŒãã«ã®æå·åãµãã·ã¹ãã ã«ã¯æå·åã¢ã«ãŽãªãºã ã®å€ãã®å®è£
ãå«ãŸããŠããããŠãŒã¶ãŒãã¢ã¯ã»ã¹ã§ããã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŠããããšããã§ã«ããã£ãŠããŸãïŒä»¥äžããŠãŒã¶ãŒãšéçºè
ã¯ããããAPIãŠãŒã¶ãŒãšAPIéçº è
ãæå³ããŸã ïŒã Crypto APIã«é¢ããŠã¯ãã¢ã«ãŽãªãºã ã¯ã倿ããšåŒã°ãããããããŸããŸãªã¿ã€ãã®å€æã«ã¯ç¬èªã®ãµãAPIãããã倿èšè¿°åïŒãã³ãã«ïŒã«ã¯éåžžã tfm ããšããååãä»ããããŸãã
struct crypto_cipher *tfm = crypto_alloc_cipher("aes", 0, 0);
ããã§ã tfmã¯äœããã®å€æããã®å Žåã¯AESã¢ã«ãŽãªãºã ã䜿çšããããŒã¿ãããã¯ã®æå·åã®ãã³ãã«ã§ãã Crypto APIãã³ãã«ã®ã©ã€ããµã€ã¯ã«ã¯3段éã«ççž®ãããŸã ã
- ãã³ãã«ã®äœæ/åæå
- ãã³ãã«ãä»ããŠã¢ã¯ã»ã¹å¯èœãªå¿
èŠãªæå·åæäœãå®è¡ãã
- ç Žå£ãæ±ã
䜿çšãããã¢ã«ãŽãªãºã ã«é¢ä¿ãªãã 1ã€ã®ããŒã¿ãããã¯ã®åºæ¬çãªæå·åæ©èœã®å®è£
ã¯ã crypto_cipher
ã¿ã€ãã®ãã³ãã«ãä»ããŠå©çšã§ããŸãã察å¿ããAPI ïŒ ã·ã³ã°ã«ãããã¯æå·API ïŒã¯ãããŒãèšå®ãããããã¯ãæå·å/埩å·åããããã®ã¡ãœãããæäŸããŸãã ç¬ç«ããAPIã§ããããããŠãŒã¶ãŒã«ãšã£ãŠå€§ããªé¢å¿ã¯ãããŸããããéçºè
ã®èгç¹ããã¯ã Crypto APIã®éèŠãªæŠå¿µãããããããã³ãã¬ãŒããã䜿çšãããããéèŠã§ãã ãã³ãã¬ãŒãã¯åºæ¬æ©èœãšçµã¿åãããŠäœ¿çšââããã以äžãå®è£
ããŸãã
- ãããã¯æå·åã¢ãŒãïŒ ECB ã CBC ã CFB ã CTR ã...ïŒ
- ããŒããã·ã¥ã¢ãŒãïŒ hMAC ïŒ
- AEADæå·åã¢ãŒã
- 䞊ååïŒ pcrypt ïŒãªã©ãããŒã¿ã®çŽæ¥æå·åŠçã«é¢é£ããªãæ©èœ
ãã³ãã«ãäœæãããšãïŒäžèšã®äŸãåç
§ïŒãå¿
èŠãªã¢ã«ãŽãªãºã ã¯è¡ã§æå®ãããŸã-ã¢ã«ãŽãªãºã ã®ååããã®è¡ã«ã¯æ¬¡ã®ã»ãã³ãã£ã¯ã¹ããããŸãã
template(single block cipher/message digest)
ããã«ãå¿
èŠã«å¿ããŠããã³ãã¬ãŒããä»ã®ãã³ãã¬ãŒãã«ãã©ãããã§ããŸãã
template_a(template_b(single block cipher/message digest))
ãã ããåºæ¬çãªã¢ã«ãŽãªãºã ãªãã§ãã³ãã¬ãŒãã䜿çšããããšã¯ã§ããŸããã ããã€ãäŸãæããŸãã
- aes-åºæ¬çãªAESãããã¯æå·åã¢ã«ãŽãªãºã
- cbcïŒaesïŒ -çµåãããã¯æå·ïŒ CBC ïŒã¢ãŒãã®AESæå·åã¢ã«ãŽãªãºã
- sha1 - SHA1ããã·ã¥ã¢ã«ãŽãªãºã
- hmacïŒsha1ïŒ -SHA1ããã·ã¥é¢æ°ã䜿çšããããŒããã·ã¥ã¢ã«ãŽãªãºã ïŒã»ãã¥ãªãã£ïŒ
- authencïŒhmacïŒsha1ïŒãcbcïŒaesïŒïŒ - AES-CBCæå·åã¢ã«ãŽãªãºã ãšhMACïŒSHA1ïŒã»ãã¥ãªãã£ã¢ã«ãŽãªãºã ã䜿çšããAEAD
ä»»æã®ã¢ãŒãã§ã®å¯Ÿç§°ãããã¯æå·ã®äœ¿çšã¯ãå¥åã®APIãä»ããŠå®è¡ãããŸã ã ã«ãŒãã«ã«ã¯ãã®ãããªAPIã3ã€ãããŸããããã®ãã¡2ã€ã¯éæšå¥šã§ããã Symmetric Key Cipher APIãé¢é£ããŠããããšã«æ³šæããŠãã ããã ãã®APIã¯ãä»»æã®é·ãã®ããŒ/åæããã³æå·å/埩å·åã®ããŒã¿ãèšå®ããã¡ãœããããŠãŒã¶ãŒã«æäŸããŸãããŸãã éããããã³ã° ïŒéåæïŒã§ããæå·åã¡ãœããã¯ãéç¥ã«äœ¿çšãããæå·æäœãšã³ãŒã«ããã¯é¢æ°ã®ãªã¯ãšã¹ããåŒã³åºãå
ã«ã§ããã ãæ©ãå¶åŸ¡ãè¿ããŸãæäœã®å®äºã«é¢ãããŠãŒã¶ãŒã¯ãã·ã¹ãã ã¹ã±ãžã¥ãŒã©ã«éä¿¡ãããŸãã Symmetric Key Cipher APIã¯ãçµã¿èŸŒã¿ã¢ã«ãŽãªãºã ããã¹ãããã«ãŒãã«ã¢ãžã¥ãŒã«ã®äœæã«é²ããšãã«è©³çŽ°ã«æ€èšãããŸãã
2ã€ã®ååã«å ããŠã Crypto APIã«ã¯æ¬¡ã®ãµãAPIããããŸã ã
éçºè
ã«ãšã£ãŠã Crypto APIã«ãã³ãã¬ãŒããååšãããšããããšã¯ãæ°ãã察称æå·åã¢ã«ãŽãªãºã ãçµã¿èŸŒãããšã§ãåºæ¬çãªãããã¯æå·åæ©èœã®ã¿ãå®è£
ããã°ååã§ããã察å¿ãããã³ãã¬ãŒãã«ã«ãã»ã«åããŠå¿
èŠãªã¢ãŒããååŸã§ããããšãæå³ããŸãã ããããããã¯å®å
šã«çå®ã§ã¯ãããŸããã å®éãã«ãŒãã«ã«å«ãŸããã¢ã«ãŽãªãºã ã®ãœãŒã¹ã³ãŒãïŒ crypto / aes_generic.c ã crypto / blowfish_generic.c ã...ïŒãèŠããšãåºæ¬çãªæ©èœã®ã¿ãå®è£
ãããŠããããšãããããŸãã ãã ããåãæ¹æ³ã§åŸæ¥ã®GOST 28147-89ãããã¯ã®æå·åæ©èœãå®è£
ãããããã²ãŒãã³ã°ã¢ãŒãïŒ CTRãã³ãã¬ãŒãïŒã§ãã©ããããããã¹ãã·ãŒã±ã³ã¹ã§çµæã®ã¢ã«ãŽãªãºã ããã§ãã¯ãããšãééã£ãçµæãåŸãããŸãã åé¡ã¯ã GOSTã§èª¬æãããŠããã¬ã³ãã¢ãŒããã CTRãã³ãã¬ãŒãã«å®è£
ãããŠããã¬ã³ãã¢ã«ãŽãªãºã ãšç°ãªãããšã§ãã ç§ãæ±ã£ãä»ã®åœå®¶ã¢ã«ãŽãªãºã ã«ã€ããŠãåãããšãèšããŸãã ãã®ãããªå Žåãããšãã°AESã¢ã«ãŽãªãºã ã®æé©åãããå®è£
ïŒ AES-NI - arch / x86 / crypto / aesni-intel_glue.c ïŒã§è¡ãããŠããããã«ãå¿
èŠãªã¢ãŒãã§æ¬æ Œçãªãããã¯æå·ãåã蟌ãå¿
èŠããããŸãã åŸã§ãåã蟌ã¿ã®äž¡æ¹ã®ãªãã·ã§ã³ãæ€èšããŸãã
ãããããããç§ã建ç¯ã«ã€ããŠèšãããã£ãããšã®ãã¹ãŠã§ãã ãã詳现ãªèª¬æã«èå³ããã人ã¯ã ããã¥ã¡ã³ããåç
§ããå¿
èŠããããç§ã®ãã¬ãŒã³ããŒã·ã§ã³ã¯ç§ãã¡ãå
ã«é²ãããšãã§ããããã«ååã§ãªããã°ãªããŸããã
[2]åå£ã®æºå
ãããã£ãŠã Crpyto APIã«ããã€ãã®æ°ããã¢ã«ãŽãªãºã ãçµã¿èŸŒãæºåãæŽããŸãããçµ±åã§ããã¢ã«ãŽãªãºã ã¯ãŸã ãªããšããèŠåããããŸãã ãã®èšäºã§ã¯ããå®éã®ãæå·åã¢ã«ãŽãªãºã ãå®è£
ããããšãæ°ã«ããŸããã§ããã宿§çã«è¡ãããšã¯ã»ãšãã©ã§ããªãã£ãããã§ãïŒæå·äœæè
ã«ä»»ããŠãã ããïŒã äžæ¹ã ãã«æå·ãäœæããããšã¯ãç¹ã«ã«ãŒãã«ã«ãã§ã«ãããããããã»ã©è峿·±ããã®ã§ã¯ãããŸããã ãããã£ãŠãåºæ¬æå·åã¢ã«ãŽãªãºã ã®å®è£
ã劥åããŠèšè¿°ããŸãã
ã©ãã§ïŒ
-æå·æãããã¯
-å¹³æãããã¯
-ããŒ
-æä»çORæŒç®ïŒ XOR ïŒ
ãã®ã¢ã«ãŽãªãºã ã®ãããã¯ãšããŒã®ãµã€ãºã¯ã128ãããïŒ16ãã€ãïŒã«çãããšæ³å®ãããŠããŸãã
å®è£
ãéå§ã§ããŸãã ã¢ã«ãŽãªãºã ã®æå·ã³ã³ããã¹ããšãã³ã³ããã¹ããäœæ/ç Žæ£ããæ©èœãå®çŸ©ããŸãã
#define XOR_CIPHER_KEY_SIZE 16 typedef struct xor_cipher_ctx xor_cipher_ctx; struct xor_cipher_ctx { uint8_t key[XOR_CIPHER_KEY_SIZE]; }; xor_cipher_ctx* xor_cipher_allocate() { xor_cipher_ctx *cipher = calloc(1, sizeof(xor_cipher_ctx)); return cipher; } void xor_cipher_free(xor_cipher_ctx *ctx) { memset(ctx->key, 0xFF, XOR_CIPHER_KEY_SIZE); free(ctx); }
ããŒãèšå®ãããããã¯ãæå·å/埩å·åããã¡ãœããã远å ããŸãã
#define XOR_CIPHER_BLOCK_SIZE 16 void xor_cipher_set_key(xor_cipher_ctx *ctx, uint8_t *key) { memmove(ctx->m_key, key, XOR_CIPHER_KEY_SIZE); } void xor_cipher_crypt_block(xor_cipher_ctx *ctx, uint8_t *dst, uint8_t *src) { for (int i = 0; i < XOR_CIPHER_BLOCK_SIZE; i++) { dst[i] = src[i] ^ ctx->key[i]; } }
XORæäœã®å¯éæ§ãèãããšã xor_cipher_crypt_block
ã¡ãœããxor_cipher_crypt_block
䜿çšããŠæå·åãšåŸ©å·åãåæã«è¡ããŸãã
ãããã¯æå·åã¯åªããŠããŸããããããã¯æå·åã¢ãŒãã®äžéšãããšãã°æå·ãããã¯ãããã¯çµåã¢ãŒãïŒ CBC ïŒãå®è£
ãããšããã«è¯ããªããŸã ã
ã©ãã§ïŒ
-åæããã±ãŒãž
ã
-ããŒäžã®ãããã¯ã®æå·åããã³åŸ©å·åã®æ©èœ
ããã«å¿ããŠ
åŒãç¶ãåäœããŸããæå·ã®ãããã¯ãçµåããã¢ãŒãã§æå·åããã³åŸ©å·åã®ã¡ãœãããå®è£
ããŸãã
æå·å void xor_cipher_encrypt_cbc(xor_cipher_ctx *ctx, uint8_t *_dst, uint32_t len, uint8_t *_src, uint8_t *_iv) { uint32_t blocks = len / XOR_CIPHER_BLOCK_SIZE; uint32_t leftover = len - (blocks * XOR_CIPHER_BLOCK_SIZE); uint8_t *dst = _dst, *src = _src, *iv = _iv; for (uint32_t i = 0; i < blocks; i++) { memmove(dst, src, XOR_CIPHER_BLOCK_SIZE); for (int j = 0; j < XOR_CIPHER_BLOCK_SIZE; j++) { dst[j] ^= iv[j]; } xor_cipher_crypt_block(ctx, dst, dst); iv = dst; dst += XOR_CIPHER_BLOCK_SIZE; src += XOR_CIPHER_BLOCK_SIZE; } if (leftover) { memmove(dst, src, leftover); for (uint32_t i = 0; i < leftover; i++) { dst[i] ^= iv[i]; dst[i] ^= ctx->key[i]; } } }
è§£èª void xor_cipher_decrypt_cbc(xor_cipher_ctx *ctx, uint8_t *_dst, uint32_t len, uint8_t *_src, uint8_t *_iv) { uint32_t blocks = len / XOR_CIPHER_BLOCK_SIZE; uint32_t leftover = len - (blocks * XOR_CIPHER_BLOCK_SIZE); uint8_t u[XOR_CIPHER_BLOCK_SIZE], iv[XOR_CIPHER_IV_SIZE]; uint8_t *dst = _dst, *src = _src; memmove(iv, _iv, XOR_CIPHER_IV_SIZE); for (uint32_t i = 0; i < blocks; i++) { memmove(u, src, XOR_CIPHER_BLOCK_SIZE); xor_cipher_crypt_block(ctx, dst, src); for (int j = 0; j < XOR_CIPHER_BLOCK_SIZE; j++) { dst[j] ^= iv[j]; } memmove(iv, u, XOR_CIPHER_IV_SIZE); dst += XOR_CIPHER_BLOCK_SIZE; src += XOR_CIPHER_BLOCK_SIZE; } if (leftover) { for (uint32_t i = 0; i < leftover; i++) { dst[i] = src[i] ^ ctx->key[i]; dst[i] ^= iv[i]; } } }
ããã¯ãã§ã«ãã£ãšé¢çœãã§ãïŒ ããã§ããã®å®è£
ã䜿çšããŠããã¹ãã·ãŒã±ã³ã¹ãæºåã§ããŸãããã¹ãã·ãŒã±ã³ã¹ã§ã¯ãå°æ¥ãã«ãŒãã«å
ã®åãã¢ã«ãŽãªãºã ã®å®è£
ã確èªããŸãã ãã¿ãã¬ã®äžã«äœ¿çšããå€ããããŸãã
ãã¹ãã·ãŒã±ã³ã¹ãããã¯æå·å | |
---|
ã㌠| 2f 1b 1a c6 d1 be cb a2 f8 45 66 0d d2 97 5c a3 |
ãã¹ãçªå·1 | |
å
¥åããŒã¿ | cc 6b 79 0c db 55 4f e5 a0 69 05 96 11 be 8c 15 |
ã€ã³ããªã³ã | e3 70 63 ca 0a eb 84 47 58 2c 63 9b c3 29 d0 b6 |
ãã¹ãçªå·2 | |
å
¥åããŒã¿ | 53 f5 f1 ef 67 a5 ba 6c 68 09 b5 7a 24 de 82 5f |
ã€ã³ããªã³ã | 7c ee eb 29 b6 1b 71 ce 90 4c d3 77 f6 49 de fc |
CBCæå·å | |
---|
ã㌠| ec 8d 93 30 69 7e f8 63 0b f5 58 ec de 78 24 f2 |
åæããã±ãŒãž | db 02 1f a8 5a 22 15 cf 49 f7 80 8b 7c 24 a1 f3 |
å¹³æ | 6e 96 50 42 84 d2 7e e8 44 9b 75 1d e0 ac 0a 58 ee 40 24 cc 32 fc 6e c4 e2 fc d1 f5 76 6a 45 9a e4 88 ba d6 12 07 28 86 |
æå·æ | 59 19 dc da b7 8e 93 44 06 99 ad 7a 42 f0 8f 59 5b d4 6b 26 ec 0c 05 e3 ef 90 24 63 ea e2 ee 31 53 d1 42 c0 97 75 d5 06 |
CBC埩å·å | |
---|
ã㌠| ec 8d 93 30 69 7e f8 63 0b f5 58 ec de 78 24 f2 |
åæããã±ãŒãž | db 02 1f a8 5a 22 15 cf 49 f7 80 8b 7c 24 a1 f3 |
æå·æ | db e9 1d c6 1f 13 1a 5a 34 2b 90 1e c3 b1 6f e9 52 1b 91 7f 8d 8f 6d b4 42 87 ad 85 5f 2d 89 7d |
å¹³æ | ec 66 91 5e 2c 4f f7 f6 76 29 48 79 61 ed ea e8 65 7f 1f 89 fb e2 8f 8d 7d 59 65 77 42 e4 c2 66 |
ã¢ã«ãŽãªãºã ãšãã¹ãããã°ã©ã ã®å®è£
ã®ãœãŒã¹ã³ãŒãã¯ããããå
¥æã§ããŸã ã ã«ãŒãã«ã¹ããŒã¹ã«è¡ãæºåã¯ã»ãŒæŽã£ãŠããŸãã ããã®åã«éèŠãªãã€ã³ãã«æ³šæãåããããšæããŸãã å®éãå€ãã®æåãªæå·åã¢ã«ãŽãªãºã ã¯ãå
¥åããŒã¿ã®æåŸã®äžå®å
šãªãããã¯ã®åŠçãå¿
èŠãšããŸããã ãããã£ãŠãããšãã°ãå
¥åããŒã¿ã®ãµã€ãºããããã¯ãµã€ãºã®åæ°ã§ãªãå Žåã GOST 28147-89ã¢ã«ãŽãªãºã ã®å®è£
ã¯ãšã©ãŒãã©ã°ãè¿ããªããã°ãªããŸããã ã ãã«ããã©ã«ãŒã·èªã¯ãã®ãããªåŠçãæäŸããŸãã ç§ã®ã¢ã«ãŽãªãºã ããããæäŸããŸãïŒã¯ããã¯ããã±ãŒãžã®ããŒãšçŸåšã®å€ã¯ãäžå®å
šãªãããã¯ã®ãµã€ãºã«åãæšãŠãããŸãïŒã ãã®äºå®ã¯å°ãåŸã§åœ¹å²ãæãããŸãããããªãã¯ãããèŠããŠããå¿
èŠããããŸãã
[3]ã³ã¢ãžã®æµžæŒ¬
ã¢ã¯ã·ã§ã³ã¯ã«ãŒãã«ç©ºéã«è»¢éãããŸãã ã«ãŒãã«ã§ã®ããã°ã©ãã³ã°ã¯ããŠãŒã¶ãŒç©ºéã§ã®ããã°ã©ãã³ã°ãšã¯å€å°ç°ãªãããããã°ã®è€éãã®ããã«ãããªãæéããããããã»ã¹ã§ãã ãã ãããã®è³æã«åãçµãã§ããéãç§ã¯èªè
ã«ã«ãŒãã«ã¢ãžã¥ãŒã«ã®ããã°ã©ãã³ã°ã®åºæ¬ãçè§£ãããšããã¿ã¹ã¯ãèšå®ããŸããã§ãããããã¯ã Habré ïŒ more ; and more ïŒãªã©ãç§ãªãã§ããã«é¢ããå€ãã®æ
å ±ãããããã§ãã ãããã£ãŠãèªè
ãã¢ãžã¥ãŒã«ã®äœæã«å®å
šã«æ
£ããŠããªãå Žåã¯ãæåã«äžèšã§åŒçšããè³æã確èªããããèªåã§ç¢ºèªããããšããå§ãããŸãïŒããã«ã¯æéãããããŸããïŒã ãããŠãããã«å
ãžé²ãæºåãã§ããŠãã人ãã¡ãšäžç·ã«ã Crypto APIãæ·±ãç ç©¶ãå§ããŸã ã
ããã§ãã¢ã«ãŽãªãºã ãããããããã«ãŒãã«ã«åã蟌ã¿ããã®ã§ãããã©ãããå§ããã°ããã®ã§ããããïŒ ãã¡ãããããã¥ã¡ã³ãä»ãã æ®å¿µãªããšã«ã ã¢ã«ãŽãªãºã ã®éçº/åã蟌ã¿ã«é¢ããã»ã¯ã·ã§ã³ã§ã¯ããã®ããã»ã¹ã«é¢ããéåžžã«äžè¬çãªç¥èããåŸãããŸããããå°ãªããšãæ£ããæ¹åã«é²ãã«ã¯åœ¹ç«ã¡ãŸãã å
·äœçã«ã¯ãã«ãŒãã«å
ã®ã¢ã«ãŽãªãºã ã®ç»é²ããã³ç»é²è§£é€ã«é¢äžãã颿°ã®ååšã«ã€ããŠåŠç¿ããŸãã çè§£ããŸãããïŒ
int crypto_register_alg(struct crypto_alg *alg); int crypto_register_algs(struct crypto_alg *algs, int count); int crypto_unregister_alg(struct crypto_alg *alg); int crypto_unregister_algs(struct crypto_alg *algs, int count);
ãããã®é¢æ°ã¯ããšã©ãŒã®å Žåã¯è² ã®å€ãè¿ããæåããå Žåã¯0ãè¿ããŸããç»é²ãããã¢ã«ãŽãªãºã ã¯ã crypto_alg
æ§é äœã«ãã£ãŠèšè¿°ãããŸãïŒãã®å®çŸ©ïŒ include / linux / crypto.h ïŒãåç
§ ïŒã
struct crypto_alg { struct list_head cra_list; struct list_head cra_users; u32 cra_flags; unsigned int cra_blocksize; unsigned int cra_ctxsize; unsigned int cra_alignmask; int cra_priority; atomic_t cra_refcnt; char cra_name[CRYPTO_MAX_ALG_NAME]; char cra_driver_name[CRYPTO_MAX_ALG_NAME]; const struct crypto_type *cra_type; union { struct ablkcipher_alg ablkcipher; struct blkcipher_alg blkcipher; struct cipher_alg cipher; struct compress_alg compress; } cra_u; int (*cra_init)(struct crypto_tfm *tfm); void (*cra_exit)(struct crypto_tfm *tfm); void (*cra_destroy)(struct crypto_alg *alg); struct module *cra_module; } CRYPTO_MINALIGN_ATTR;
幞ããªããšã«ããã®æ§é ã¯éåžžã«ããææžåãããŠããããã®ãã£ãŒã«ããŸãã¯ãã®ãã£ãŒã«ãã®å€ãæšæž¬ããå¿
èŠã¯ãããŸããã
cra_flags
ïŒã¢ã«ãŽãªãºã ãèšè¿°ãããã©ã°ã®ã»ããã ãã©ã°ã¯ã include / linux / crypto.hã® ã CRYPTO_ALG_
ãã§å§ãŸã宿°ã«ãã£ãŠå®çŸ©ãããã¢ã«ãŽãªãºã ã®èª¬æã埮調æŽããããã«äœ¿çšãããŸãcra_blocksize
ïŒã¢ã«ãŽãªãºã ã®ãã€ããããã¯ãµã€ãºã ããã·ã¥ãé€ããã¹ãŠã®ã¿ã€ãã®å€æã¯ããã®å€ããå°ããããŒã¿ãåŠçããããšãããšãšã©ãŒãè¿ããŸãcra_ctxsize
ïŒ cra_ctxsize
ãã€ããµã€ãºã ã«ãŒãã«ã¯ãã³ã³ããã¹ãã«ã¡ã¢ãªãå²ãåœãŠããšãã«ãã®å€ã䜿çšããŸããcra_alignmask
ïŒå
¥åããã³åºåã®ã¢ã©ã€ã¡ã³ããã¹ã¯ã ã¢ã«ãŽãªãºã ã®å
¥åããã³åºåçšã®ãããã¡ã¯ããã®ãã¹ã¯ã«æããå¿
èŠããããŸãã ããã¯ãä»»æã®ã¢ãã¬ã¹ã®ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããªãããŒããŠã§ã¢ã§å®è¡ãããã¢ã«ãŽãªãºã ã«å¿
èŠã§ããcra_priority
ïŒãã®ã¢ã«ãŽãªãºã ã®å®è£
ã®åªå
床ã åãcra_name
æã€è€æ°ã®ãã©ã³ã¹ãã©ãŒã ãã«ãŒãã«ã«ç»é²ãããŠããå Žåããã®ååã§ã¢ã¯ã»ã¹ãããšãæé«ã®åªå
床ãæã€ã¢ã«ãŽãªãºã ãè¿ãããŸãcra_name
ïŒã¢ã«ãŽãªãºã ã®ååã ã«ãŒãã«ã¯ãã®ãã£ãŒã«ãã䜿çšããŠå®è£
ãæ€çŽ¢ããŸããcra_driver_name
ïŒã¢ã«ãŽãªãºã ã®å®è£
ã®äžæã®ååã åãcra_name
è€æ°ã®å€æãã«ãŒãã«ã«ç»é²ãããŠãããããäœãåªå
床ã®ã¢ã«ãŽãªãºã ãèŠæ±ããå¿
èŠãããå Žåããã®ååã䜿çšããå¿
èŠããããŸãcra_type
ïŒæå·cra_type
ã¿ã€ãã ãã¹ãŠã®ã¿ã€ãã®å€æã«å
±éã®ã³ãŒã«ããã¯é¢æ°ãå®è£
ããã¿ã€ãcrypto_type
æ§é äœã®ã€ã³ã¹ã¿ã³ã¹ãžã®ãã€ã³ã¿ãŒã å©çšå¯èœãªãªãã·ã§ã³ïŒ &crypto_blkcipher_type
ã &crypto_ablkcipher_type
ã &crypto_ahash_type
ã &crypto_rng_type
ã æ¬¡ã®ã¿ã€ãã®å€æã®å Žåããã®ãã£ãŒã«ãã¯ç©ºçœã®ãŸãŸã«ããŠãã ããïŒãããã¯æå·åïŒ cipher
ïŒãå§çž®ïŒ compress
ïŒãããããã³ã°ããã·ã¥ïŒ shash
ïŒcra_u
ïŒå®éã«ã¯ãã¢ã«ãŽãªãºã ã®å®è£
ã ãŠããªã³ã®æ§é ã®1ã€ã¯ã倿ã®ã¿ã€ãã«ãã£ãŠæ±ºå®ãããç¹å®ã®é¢æ°ã§æºããããå¿
èŠããããŸãã ãã®ãã£ãŒã«ãã¯ããããã¯ããã³éãããã¯ããã·ã¥ïŒ ahash
ïŒã®ããã«ç©ºçœã®ãŸãŸã«ããŠãã ãããcra_init
ïŒã€ã³ã¹ã¿ã³ã¹åæå颿°ã倿ããŸãã ãã®é¢æ°ã¯ãã€ã³ã¹ã¿ã³ã¹ã®äœæäžïŒæå·ã³ã³ããã¹ãã«ã¡ã¢ãªãå²ãåœãŠãçŽåŸïŒã«1ååŒã³åºãããŸãã ãã®æ©èœã§ã¯ãå¿
èŠã«å¿ããŠããŸããŸãªæºåã¢ã¯ã·ã§ã³ãå®è¡ããå¿
èŠããããŸãïŒããšãã°ã远å ã¡ã¢ãªã®å²ãåœãŠãããŒããŠã§ã¢æ©èœã®ç¢ºèªïŒã ãã以å€ã®å Žåããã£ãŒã«ãã¯ç©ºçœã®ãŸãŸã«ã§ããŸããcra_exit
ïŒå€æã€ã³ã¹ã¿ã³ã¹ã®åæåè§£é€ã ãã®é¢æ°ã§ã¯ã cra_init
ã§è¡ãããããšãšå察ã®ããšãå®è¡ããå¿
èŠããããŸãïŒååšããå ŽåïŒã ãã以å€ã®å Žåããã£ãŒã«ãã¯ç©ºçœã®ãŸãŸã«ã§ããŸããcra_module
ïŒãã®å€æå®è£
ã®ææè
ã å€ãTHIS_MODULE
èšå®ããŸã
ææžåãããŠããªãæ®ãã®ãã£ãŒã«ãã¯å
éšäœ¿çšã®ããã®ãã®ã§ãããå
¥åããªãã§ãã ããã è€éãªããšã¯äœããªãããã§ãã ãŸãããããã¯æå·åã¢ã«ãŽãªãºã ã®å®è£
ãçµã¿èŸŒã¿ããã®ã§ã cra_u
ãŠããªã³ã®cipher_alg
æ§é ãèŠãŠã¿ãŸãããã
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); };
ããã§ã¯ãŸã ç°¡åã§ãç§ã«ã¯æããã®ã§èª¬æã¯äžèŠã§ãã ããã§ãããããã¹ãŠãå®éã«ã©ã®ããã«æ©èœãããã確èªããæºåãã§ããŸããã ã¡ãªã¿ã«ã cipher_alg
æ§é äœã®é¢æ°ã®ã·ã°ããã£ã¯ ã2ããŒãã¢ã«ãŽãªãºã ã®APIã®é¢æ°ã®ã·ã°ããã£ã«äŒŒãŠããããšã«æ³šæããŠãã ããã
ã«ãŒãã«ã¢ãžã¥ãŒã«ãäœæããŸãã 眲åcipher_alg.cia_setkey
ã«åŸã£ãŠã cipher_alg.cia_setkey
ãšããŒã€ã³ã¹ããŒã«é¢æ°ã決å®ããŸãã
#define XOR_CIPHER_KEY_SIZE 16 struct xor_cipher_ctx { u8 key[XOR_CIPHER_KEY_SIZE]; }; static int xor_cipher_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len) { struct xor_cipher_ctx *ctx = crypto_tfm_ctx(tfm); u32 *flags = &tfm->crt_flags; if (len != XOR_CIPHER_KEY_SIZE) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } memmove(ctx->key, key, XOR_CIPHER_KEY_SIZE); return 0; }
ã¢ã«ãŽãªãºã ã®APIã§ã¯ãcryptocontextã颿°ã«çŽæ¥æž¡ãããŸãããããã§ã颿°ã¯tfm
ã¢ã«ãŽãªãºã ã®ãã³ãã«ãtfm
ãŸãtfm
ã¢ã«ãŽãªãºã ããã crypto_tfm_ctx
颿°ã䜿çšããŠã³ã³ããã¹ããæœåºãããŸãã ãŸããããã§ã¯ãéä¿¡ãããããŒã®é·ãã確èªããŸãã é·ããæ£ãããªãå Žåã察å¿ãããã©ã°ïŒ CRYPTO_TFM_RES_BAD_KEY_LEN
ïŒãèšå®ãã EINVAL
ã³ãŒãïŒ22ïŒ Invalid argument ïŒãè¿ããŸã ã
次ã«ã cipher_alg.cia_encrypt
ã«åŸã£ãŠãããã¯æå·å颿°ãå®çŸ©ããŸãã
static void xor_cipher_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct xor_cipher_ctx *ctx = crypto_tfm_ctx(tfm); int i; for (i = 0; i < XOR_CIPHER_BLOCK_SIZE; i++) { out[i] = in[i] ^ ctx->key[i]; } }
ããã«æ°ãããã®ã¯ãããŸããã å
ã®APIã®ããã«ã埩å·åã®ããã®è¿œå ã®é¢æ°ã¯å®çŸ©ããã cipher_alg.cia_decrypt
ãã€ã³ã¿ãŒãcipher_alg.cia_decrypt
颿°ã§åæåããŸãã
æåŸã«ãã¢ãžã¥ãŒã«ã®ããŒãåŸããã³ã¢ã³ããŒãåã«ã crypto_alg
æ§é äœã®ã€ã³ã¹ã¿ã³ã¹ãå®çŸ©ãããããå
¥åããŠãã¢ã«ãŽãªãºã ã®ç»é²ããã³ç»é²crypto_alg
颿°ãããããåŒã³åºããŸãã
static struct crypto_alg xor_cipher = { .cra_name = "xor-cipher", .cra_driver_name = "xor-cipher-generic", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XOR_CIPHER_BLOCK_SIZE, .cra_ctxsize = sizeof(struct xor_cipher_ctx), .cra_module = THIS_MODULE, .cra_u = { .cipher = { .cia_min_keysize = XOR_CIPHER_KEY_SIZE, .cia_max_keysize = XOR_CIPHER_KEY_SIZE, .cia_setkey = xor_cipher_setkey, .cia_encrypt = xor_cipher_crypt, .cia_decrypt = xor_cipher_crypt } } }; static int __init xor_cipher_init(void) { return crypto_register_alg(&xor_cipher); } static void __exit xor_cipher_exit(void) { crypto_unregister_alg(&xor_cipher); }
äžèšã®ãã¹ãŠãèæ
®ãããšãããã§çåãçããããšã¯ãããŸããã ãã®ãããªã¢ãžã¥ãŒã«ãã³ã³ãã€ã«ããã³ããŠã³ããŒãããåŸãã¿ãŒããã«ã§ã³ãã³ãã cat /proc/crypto
ããå®è¡ãããšãç»é²æžã¿ã¢ã«ãŽãªãºã ã®ãªã¹ãã§ç¬èªã®ã¢ã«ãŽãªãºã ãèŠã€ããããšãã§ããŸãã
name : xor-cipher driver : xor-cipher-generic module : xor_cipher priority : 100 refcnt : 1 selftest : passed internal : no type : cipher blocksize : 16 min keysize : 16 max keysize : 16
æªããªãã§ããïŒ ããããããã¯ã»ãã®å§ãŸãã«éãããçè«çã«ã¯ãã¢ã«ãŽãªãºã ããã¹ãããã¢ãžã¥ãŒã«ã®äœæã«é²ãå¿
èŠããããŸããããããã§ããåã蟌ã¿ãšäœ¿çšã®åé¡ãæ··åããªãããšã«ããŸããã ãããã£ãŠãåŸã§ãã¹ãããŸããæ¬¡ã®ããŒãã§ã¯ãæå·ã®ãããã¯ãçµåããã¢ãŒãã§ã¢ã«ãŽãªãºã ã®å®è£
ãã©ã®ããã«çµã¿èŸŒãããšãã§ãããã説æããŸãã
[3.1]ã³ã¢ãžã®ãããå°ãæ·±ããæµžæŒ¬
å°ãå
ã«èµ°ããŸãã æ³šææ·±ãèªè
ã¯ããã¿ãŒã³ã®ååšãèŠããŠããŸãã ãããã£ãŠãæåŸã®éšåã§ãããã¯æå·åãå®è£
ãããšããã®å®è£
ãCBCãã³ãã¬ãŒãã§ç°¡åã«ã©ããããæå·ãããã¯ããããã¯ããã¢ãŒãã§ã¢ã«ãŽãªãºã ã®å®è£
ãååŸã§ããŸãããã·ãŒã±ã³ã¹ã§ãã¹ãããããšã«ããã CBCã¢ãŒãã§æå·åãåŒã³åºããšãšã©ãŒã³ãŒã22ïŒ EINVAL
ïŒ æ¬¡ã«ãå
¥åããŒã¿ã®äžå®å
šãªãããã¯ãšcrypto_alg.cra_blocksize
ãã£ãŒã«ãã®åŠçã«ã€ããŠèšã£ãããšãæãåºããŸãã å®éã CBCã«ãŒãã«ã¢ãŒãã®å®è£
ã«ã¯ãäžå®å
šãªãããã¯ãåŠçããæ¹æ³ãããããŸããã ããã«ãã¢ã«ãŽãªãºã ãCBCã¢ãŒãã«å€æŽãããšãã«ãŒãã«ã¯æ°ããã¢ã«ãŽãªãºã ãç»é²ããŸãããã®ãããã¯ãµã€ãºã¯ãåºæ¬ã¢ã«ãŽãªãºã ã®ãããã¯ãµã€ãºãšåãã§ãã cbcïŒxor-cipherïŒã¢ã«ãŽãªãºã ã䜿çšããŠãæå·åãæå·å颿°ãåŒã³åºããåŸãå
¥åããŒã¿ã®ãµã€ãºã¯ãããã¯ãµã€ãºã«ãã£ãŠå€é床ããã§ãã¯ãããè€æ°ã§ãªãå Žåã颿°ã¯EINVAL
è¿ããŸãã CBCã¢ãŒãã§ã®æå·åã®ãã¹ããã¯ãã«ã®ãµã€ãºïŒ40ãã€ãïŒã¯ããããã¯ãµã€ãºã®åæ°ã§ã¯ãªãããã«æå³çã«éžæãããŠããŸãã ç§ã®æèŠã§ã¯ãæå·åæšæºãäžå®å
šãªãããã¯ã®åŠçãæäŸããå®è£
ãããããªãå Žåããã®ãããªå®è£
ã¯ãå€é床æ¡ä»¶ãæºãããããšãã«å®è£
ãæ£ããçµæãäžãããšããŠããæšæºãžã®æºæ ã®ãã§ãã¯ã«åæ Œããå¯èœæ§ã¯äœãã§ãïŒãã®å Žåãããã¯ããã§ãïŒã ãããã£ãŠãããã§ãã¢ã«ãŽãªãºã ã®æå·ãããã¯ã®çµåã¢ãŒããå®å
šã«å®è£
ããŸãã 2幎åã«ãããè¡ã£ããšããä»ã§ã¯æä»£é
ãã®ããããã³ã°å¯Ÿç§°æå·å APIãä»ããŠãããã䜿çšããããšãæåŸ
ããŠã¢ã«ãŽãªãºã ãçµã¿èŸŒã¿ãŸããããåœæã¯éããããã³ã°APIãæãŸãããšèããããŠããŸãããããããä»ã§ã¯æä»£é
ãã§ãã Symmetric Key Cipher API .
, , , , Crypto API , . , ( arch/x86/crypto/aesni-intel_glue.c ), , , . , / :
int crypto_register_skcipher(struct skcipher_alg *alg); int crypto_register_skciphers(struct skcipher_alg *algs, int count); void crypto_unregister_skcipher(struct skcipher_alg *alg); void crypto_unregister_skciphers(struct skcipher_alg *algs, int count);
skcipher_alg
:
struct skcipher_alg { int (*setkey)(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int (*encrypt)(struct skcipher_request *req); int (*decrypt)(struct skcipher_request *req); int (*init)(struct crypto_skcipher *tfm); void (*exit)(struct crypto_skcipher *tfm); unsigned int min_keysize; unsigned int max_keysize; unsigned int ivsize; unsigned int chunksize; unsigned int walksize; struct crypto_alg base; };
, include/crypto/skcipher.h . , struct crypto_alg
, , , init
exit
, crypto_alg
. , , chunksize
walksize
:
chunksize
: , , ( stream cipher ), , , , ( underlying ) . , , . ( skcipher_alg.base.cra_blocksize
) , chunksize
,walksize
: chunksize
, , , walksize
, chunksize
,
encrypt
decrypt
. skcipher_request
, : / , . , - API , , , , .
, Crypto API . , - API / ( API ), scatterlist
. , , Synchronous Block Cipher API :
int crypto_blkcipher_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes);
skcipher_request
struct scatterlist *src
struct scatterlist *dst
. scatterlist
:
struct scatterlist { unsigned long page_link; unsigned int offset; unsigned int length; };
. , sg_init_one
:
void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen);
:
, "" buf ( page_link
), buf ( offset
).
, . , :
struct crypto_blkcipher *tfm; struct blkcipher_dest desc; struct scatterlist sg[2]; u8 *first_segment, *second_segment; sg_init_table(sg, 2); sg_set_buf(&sg[0], first_segment, len); sg_set_buf(&sg[1], second_segment, len); crypto_blkcipher_encrypt(&desc, &sg, &sg, 2*len);
, first_segment
second_segment
, . , Crypto API ( ) "" scatterlist
-, "" ( scattered ) . Crypto API IPsec :
One of the initial goals of this design was to readily support IPsec, so that processing can be applied to paged skb's without the need for linearization.
, scatterlist
API / ( Direct Memory Access , DMA I/O ). / , "" , , , .
. , :
static int xor_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int len) { return xor_cipher_setkey(crypto_skcipher_tfm(tfm), key, len); }
. CBC ( struct xor_cipher_ctx
), , , .
.
static int cbc_encrypt(struct skcipher_request *req) { struct crypto_tfm *tfm = crypto_skcipher_tfm(crypto_skcipher_reqtfm(req)); struct xor_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct skcipher_walk walk; u32 nbytes; int i, blocks; u8 *src, *dst, *iv; skcipher_walk_virt(&walk, req, true); iv = walk.iv; while ((nbytes = walk.nbytes) >= XOR_CIPHER_BLOCK_SIZE) { src = (u8*)walk.src.virt.addr; dst = (u8*)walk.dst.virt.addr; blocks = nbytes / XOR_CIPHER_BLOCK_SIZE; while (blocks) { for (i = 0; i < XOR_CIPHER_BLOCK_SIZE; i++) { dst[i] = src[i] ^ iv[i]; } xor_cipher_crypt(tfm, dst, dst); iv = dst; src += XOR_CIPHER_BLOCK_SIZE; dst += XOR_CIPHER_BLOCK_SIZE; blocks--; } nbytes &= XOR_CIPHER_BLOCK_SIZE - 1; skcipher_walk_done(&walk, nbytes); } if ((nbytes = walk.nbytes)) { src = (u8*)walk.src.virt.addr; dst = (u8*)walk.dst.virt.addr; for (i = 0; i < nbytes; i++) { dst[i] = src[i] ^ iv[i]; dst[i] ^= ctx->key[i]; } skcipher_walk_done(&walk, 0); } return 0; }
#define XOR_CIPHER_IV_SIZE 16 static int cbc_decrypt(struct skcipher_request *req) { struct crypto_tfm *tfm = crypto_skcipher_tfm(crypto_skcipher_reqtfm(req)); struct xor_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct skcipher_walk walk; u8 u[XOR_CIPHER_BLOCK_SIZE], iv[XOR_CIPHER_BLOCK_SIZE]; u32 nbytes; int i, blocks; u8 *src, *dst; skcipher_walk_virt(&walk, req, true); memmove(iv, walk.iv, XOR_CIPHER_IV_SIZE); while ((nbytes = walk.nbytes) >= XOR_CIPHER_BLOCK_SIZE) { src = (u8*)walk.src.virt.addr; dst = (u8*)walk.dst.virt.addr; blocks = nbytes / XOR_CIPHER_BLOCK_SIZE; while (blocks) { memmove(u, src, XOR_CIPHER_BLOCK_SIZE); xor_cipher_crypt(tfm, dst, src); for (i = 0; i < XOR_CIPHER_BLOCK_SIZE; i++) { dst[i] ^= iv[i]; } memmove(iv, u, XOR_CIPHER_IV_SIZE); dst += XOR_CIPHER_BLOCK_SIZE; src += XOR_CIPHER_BLOCK_SIZE; blocks--; } nbytes &= XOR_CIPHER_BLOCK_SIZE - 1; skcipher_walk_done(&walk, nbytes); } if ((nbytes = walk.nbytes)) { src = (u8*)walk.src.virt.addr; dst = (u8*)walk.dst.virt.addr; for (i = 0; i < nbytes; i++) { dst[i] = src[i] ^ ctx->key[i]; dst[i] ^= iv[i]; } skcipher_walk_done(&walk, 0); } return 0; }
, , , "" skcipher_walk
. , skcipher_walk
skcipher_walk_virt
, skcipher_walk_done
"" / ( walk.src.virt.addr
walk.dst.virt.addr
) walk.nbytes
, scatterlist
-.
skcipher_alg
, / :
static struct skcipher_alg cbc_xor_cipher = { .base = { .cra_name = "cbc(xor-cipher)", .cra_driver_name = "cbc-xor-cipher", .cra_priority = 400, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = 1, .cra_ctxsize = sizeof(struct xor_cipher_ctx), .cra_module = THIS_MODULE, }, .min_keysize = XOR_CIPHER_KEY_SIZE, .max_keysize = XOR_CIPHER_KEY_SIZE, .ivsize = XOR_CIPHER_IV_SIZE, .setkey = xor_skcipher_setkey, .encrypt = cbc_encrypt, .decrypt = cbc_decrypt, .chunksize = XOR_CIPHER_BLOCK_SIZE, }; static int __init xor_cipher_init(void) { crypto_register_alg(&xor_cipher); return crypto_register_skcipher(&cbc_xor_cipher); } static void __exit xor_cipher_exit(void) { crypto_unregister_alg(&xor_cipher); crypto_unregister_skcipher(&cbc_xor_cipher); }
cra_blocksize
. , , skcipher_walk_done
"" , .
, /proc/crypto
:
name : cbc(xor-cipher) driver : cbc-xor-cipher module : xor_cipher priority : 400 refcnt : 1 selftest : passed internal : no type : skcipher async : yes blocksize : 1 min keysize : 16 max keysize : 16 ivsize : 16 chunksize : 16
( ) : " xor-cipher
" ( ) " cbc(xor-cipher)
" ( ). , , . , ( arch/x86/crypto ), .
[4]
, , "", , , , . , , â , : , , Crypto API . , , , .
. cipher_testvec_t
:
typedef enum test_t { TEST_BLK_ENCRYPT = 0, TEST_BLK_DECRYPT, TEST_CBC_ENCRYPT, TEST_CBC_DECRYPT, TEST_END, } test_t; struct cipher_testvec_t { test_t test; u32 len; char *key; char *iv; char *in; char *result; };
: in
, len
, ( .test = TEST_BLK_*
) ( .test = TEST_CBC_*
), key
, , iv
. result
. TEST_END
cipher_testvec_t
.
â :
static int test_blk(cipher_testvec_t *testvec) { struct crypto_cipher *tfm = NULL; int encrypt = (testvec->test == TEST_BLK_ENCRYPT) ? 1 : 0; u8 dst[16]; tfm = crypto_alloc_cipher("xor-cipher", 0, 0); if (IS_ERR(tfm)) { pr_err("error allocating xor-cipher: %ld\n", PTR_ERR(tfm)); return 0; } crypto_cipher_setkey(tfm, (u8*)testvec->key, 16); if (encrypt) { crypto_cipher_encrypt_one(tfm, dst, (u8*)testvec->in); } else { crypto_cipher_decrypt_one(tfm, dst, (u8*)testvec->in); } crypto_free_cipher(tfm); if (memcmp(dst, testvec->result, 16)) { pr_err("block %sciphering test failed!\n", encrypt ? "" : "de"); dumpb((u8*)testvec->key, 16, "key"); dumpb((u8*)testvec->in, 16, "in"); dumpb(dst, 16, "result"); dumpb((u8*)testvec->result, 16, "should be"); return 0; } return 1; }
, Single Block Cipher API . , crypto_alloc_cipher
, " xor-cpher ". , ( crypto_cipher_setkey
), , , ( crypto_cipher_encrypt_one
) ( crypto_cipher_decrypt_one
) . , ( crypto_free_cipher
) .
CBC .
CBC static int test_cbc(cipher_testvec_t *testvec) { struct scatterlist sg; struct cb_data_t cb_data; struct crypto_skcipher *tfm = NULL; struct skcipher_request *req = NULL; int encrypt = (testvec->test == TEST_CBC_ENCRYPT) ? 1 : 0; u32 err; u8 *buf = NULL; tfm = crypto_alloc_skcipher("cbc-xor-cipher", 0, 0); if (IS_ERR(tfm)) { pr_err("error allocating cbc-xor-cipher: %ld\n", PTR_ERR(tfm)); goto exit; } req = skcipher_request_alloc(tfm, GFP_KERNEL); if (!req) { pr_err("error allocating skcipher request\n"); goto exit; } buf = kmalloc(testvec->len, GFP_KERNEL); if (!buf) { pr_err("memory allocation error\n"); goto exit; } memmove(buf, (u8*)testvec->in, testvec->len); sg_init_one(&sg, buf, testvec->len); crypto_skcipher_setkey(tfm, (u8*)testvec->key, 16); skcipher_request_set_crypt(req, &sg, &sg, testvec->len, (u8*)testvec->iv); skcipher_request_set_callback(req, 0, skcipher_cb, &cb_data); init_completion(&cb_data.completion); err = (encrypt) ? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req); switch (err) { case 0: break; case -EINPROGRESS: case -EBUSY: wait_for_completion(&cb_data.completion); err = cb_data.err; if (!err) { break; } default: pr_err("failed with error: %d\n", err); goto exit; } if (memcmp(buf, testvec->result, testvec->len)) { pr_err("cbc %sciphering test failed!\n", encrypt ? "" : "de"); dumpb((u8*)testvec->key, 16, "key"); dumpb((u8*)testvec->iv, 16, "iv"); dumpb((u8*)testvec->in, testvec->len, "in"); dumpb(buf, testvec->len, "result"); dumpb((u8*)testvec->result, testvec->len, "should be"); goto exit; } skcipher_request_free(req); crypto_free_skcipher(tfm); kfree(buf); return 1; exit: if (buf) { kfree(buf); } if (req) { skcipher_request_free(req); } if (tfm) { crypto_free_skcipher(tfm); } return 0; }
: API ( Symmetric Key Cipher API ), .
test_cbc
:
- , :
cb_data_t
, - : " cbc-xor-cipher " (
crypto_alloc_skcipher
) skcipher_requset
( skcipher_request_alloc
) - / : (
kmalloc
) , , ; scatterlist
( sg_init_one
) - (
crypto_skcipher_setkey
) skcipher_requset
( skcipher_request_set_crypt
). skcipher_request_set_crypt
, , . scatterlist
, , " ", buf
- , (
skcipher_request_set_callback
)
. API , , , . , , , . skcipher_request_set_callback
. cb_data_t
, ( skcipher_cb
) :
struct cb_data_t { struct completion completion; int err; }; static void skcipher_cb(struct crypto_async_request *req, int error) { struct cb_data_t *data = req->data; if (error == -EINPROGRESS) { return; } data->err = error; complete(&data->completion); }
completion
test_cbc
, . , , test_cbc
. , test_cbc
, :
completion
( init_completion
),- , (
crypto_skcipher_encrypt
) ( crypto_skcipher_decrypt
) - :
-EINPROGRESS
-EBUSY
, . , completion
( complete
wait_for_completion
),
switch
-a . . , ( , ), - :
insmod: ERROR: could not insert module xor_cipher_testing.ko: Operation not permitted
( dmesg
) :
[---] done 4 tests, passed: 4, failed: 0
, SK Cipher API , . â "", Asynchronous Block Cipher API , . -, -, , .
[4.1] user-space
, . , , , , , , Linux . libkcapi , Crypto API ( ). "" Netlink -, "" Netlink API . , , , , , ( 1.0.3).
, . , , , ( ), Crypto API . af_alg Strongswan , .
, . , , . , , . , test_cbc
.
CBC user-space static int test_cbc(cipher_testvec_t *testvec) { uint8_t dst[testvec->len]; int encrypt = (testvec->test == TEST_CBC_ENCRYPT) ? 1 : 0; struct af_alg_skcipher *tfm = NULL; tfm = af_alg_allocate_skcipher("cbc-xor-cipher"); if (!tfm) { fprintf(stderr, "error allocating \"cbc-xor-cipher\"\n"); goto err; } if (!af_alg_skcipher_setkey(tfm, (uint8_t*)testvec->key, XOR_CIPHER_KEY_SIZE)) { fprintf(stderr, "can't set \"cbc-xor-cipher\" key\n"); goto err; } if (!af_alg_skcipher_crypt(tfm, encrypt, dst, testvec->len, (uint8_t*)testvec->in, (uint8_t*)testvec->iv, XOR_CIPHER_IV_SIZE)) { goto err; } af_alg_free_skcipher(tfm); if (memcmp(dst, (uint8_t*)testvec->result, testvec->len)) { fprintf(stderr, "cbc %sciphering test failed!\n", encrypt ? "" : "de"); dumpb((uint8_t*)testvec->key, XOR_CIPHER_KEY_SIZE, "key"); dumpb((uint8_t*)testvec->iv, XOR_CIPHER_IV_SIZE, "iv"); dumpb((uint8_t*)testvec->in, testvec->len, "in"); dumpb(dst, testvec->len, "result"); dumpb((uint8_t*)testvec->result, testvec->len, "should be"); return 0; } return 1; err: if (tfm) { af_alg_free_skcipher(tfm); } return 0; }
. , , , , , . af_alg_skcipher
af_alg_*
. .
struct af_alg_skcipher { int sockfd; }; static struct af_alg_skcipher* af_alg_allocate_skcipher(char *name) { struct af_alg_skcipher *tfm = NULL; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "skcipher", }; strncpy((char*)sa.salg_name, name, sizeof(sa.salg_name)); tfm = calloc(1, sizeof(struct af_alg_skcipher)); if (!tfm) { errno = ENOMEM; goto err; } tfm->sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0); if (tfm->sockfd == -1) { goto err; } if (bind(tfm->sockfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { goto err; } return tfm; err: if (tfm->sockfd > 0) { close(tfm->sockfd); } if (tfm) { free(tfm); } return NULL; }
:
sockaddr_alg
( )- (
calloc
) - Crypto API (
socket
)
socket
, "" . AF_ALG Crypto API . AF_ALG , , sys/socket.h , , :
#ifndef AF_ALG #define AF_ALG 38 #endif
sockaddr_alg
, bind
:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockadr
:
struct sockaddr { sa_family_t sa_family; char sa_data[14]; }
, , ( sa_family
), AF_ALG :
struct sockaddr_alg { __u16 salg_family; __u8 salg_type[14]; __u32 salg_feat; __u32 salg_mask; __u8 salg_name[64]; };
:
salg_family
: .salg_type
: : " skcipher
" â , " hash
" â , " aead
" â , AEAD , "rng" âsalg_name
: ( cra_name
cra_driver_name
)
, bind
-1, errno
ENOENT
.
, af_alg_allocate_skcipher
, . .
:
static int af_alg_skcipher_setkey(struct af_alg_skcipher *tfm, uint8_t *key, uint32_t keylen) { return (setsockopt(tfm->sockfd, SOL_ALG, ALG_SET_KEY, key, keylen) == -1) ? 0 : 1; }
setsockopt
, man - . , SOL_ALG
ALG_SET_KEY
, , sys/socket.h linux/af_alg.h , , , , :
#ifndef SOL_ALG #define SOL_ALG 279 #endif #ifndef ALG_SET_KEY #define ALG_SET_KEY 1 #endif
, .
static int af_alg_skcipher_crypt(struct af_alg_skcipher *tfm, int encrypt, uint8_t *_dst, uint32_t _len, uint8_t *_src, uint8_t *iv, uint32_t ivlen) { int type = encrypt ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT; struct msghdr msg = {}; struct cmsghdr *cmsg; struct af_alg_iv *ivm; struct iovec iov; char buf[CMSG_SPACE(sizeof(type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + ivlen)]; int op = 0; ssize_t len, remainig = _len; uint8_t *src = _src, *dst = _dst; op = accept(tfm->sockfd, NULL, 0); if (op == -1) { goto end; } memset(buf, 0, sizeof(buf)); msg.msg_control = buf; msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_ALG; cmsg->cmsg_type = ALG_SET_OP; cmsg->cmsg_len = CMSG_LEN(sizeof(type)); memmove(CMSG_DATA(cmsg), &type, sizeof(type)); cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg->cmsg_level = SOL_ALG; cmsg->cmsg_type = ALG_SET_IV; cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + ivlen); ivm = (void*)CMSG_DATA(cmsg); ivm->ivlen = ivlen; memmove(ivm->iv, iv, ivlen); msg.msg_iov = &iov; msg.msg_iovlen = 1; while (remainig) { iov.iov_base = src; iov.iov_len = remainig; len = sendmsg(op, &msg, 0); if (len == -1) { if (errno == EINTR) { continue; } goto end; } while (read(op, dst, len) != len) { if (errno != EINTR) { goto end; } } src += len; remainig -= len; msg.msg_controllen = 0; } close(op); return 1; end: if (op > 0) { close(op); } return 0; }
, . , , , , , . , 3 :
- ,
accept
, , , , - , (
msghdr
), ( cmsghdr
) , , / ( iovec
)
( ALG_SET_OP
): ( ALG_OP_ENCRYPT
) ( ALG_OP_DECRYPT
), ( ALG_SET_IV
, af_alg_iv
). , , linux/if_alg.h , , , :
#ifndef ALG_SET_IV #define ALG_SET_IV 2 #endif #ifndef ALG_SET_OP #define ALG_SET_OP 3 #endif #ifndef ALG_OP_DECRYPT #define ALG_OP_DECRYPT 0 #endif #ifndef ALG_OP_ENCRYPT #define ALG_OP_ENCRYPT 1 #endif
- , ,
sendmsg
read
, , accept
, , , /
以äžã§ãã . , :
done 2 tests, passed: 2, failed: 0
â , .
[5] ?
, , , , , , , , . , , . .
â . , , , . , Crypto API . , - API , . , , , , .
, : , , , . , github . !
, "" , â . ! . , xor-cipher , , CBC , ( SK Cipher API , â ):
struct crypto_skcipher *tfm = crypto_alloc_skcipher("cbc(xor-cipher)", 0, 0);
xor-cipher , ( crypto/cbc.c ).
" ! â . â , cbc(xor-cipher) ?". " ", â . , .
, :
. "" . , " cbc ", :
.cra_name = "xor-cipher"; .cra_driver_name = "xor-cipher-generic";
:
.cra_name = "cbc(xor-cipher)"; .cra_driver_name = "cbc(xor-cipher-generic)";
, crypto_alg
, , cra_driver_name
, . , , cra_driver_name
" cbc(xor-cipher-generic) ", :
struct crypto_skcipher *tfm = crypto_alloc_skcipher("cbc(xor-cipher-generic)", 0, 0);
, , , . , Crypto API , , .
tcrypt ( crypto/tcrypt.c ) . , crypto/tcrypt.c , , crypto/testmgr.c . , testmgr , ( ).
, tcrypt . "" tcrypt testmgr , Makefile , â tcryptext (tcrypt External) . .
tcryptext ( tcrypt , ), - , . ( README.md , ).
testmgr.c Crypto API .
, Linux-based . ( ) .
. " crypto " crypto/Kconfig Makefile . , crypto xor_cipher.c , crypto/Kconfig ( comment "Ciphers" ) :
... config CRYPTO_XOR_CIPHER tristate "XOR cipher algorithm" help Custom XOR cipher algorithm. ...
crypto/Makefile :
... obj-$(CONFIG_CRYPTO_XOR_CIPHER) += xor_cipher.o ...
( " Cryptographic API ") . , .
tcrypt testmgr .
䟿å©ãªãªã³ã¯
:
Git: