Subversion Repositories Kolibri OS

Rev

Rev 9067 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; libcrash -- cryptographic hash (and other) functions
  2. ;
  3. ; Copyright (C) <2012-2014,2016,2019,2021> Ivan Baravy
  4. ;
  5. ; SPDX-License-Identifier: GPL-2.0-or-later
  6. ;
  7. ; This program is free software: you can redistribute it and/or modify it under
  8. ; the terms of the GNU General Public License as published by the Free Software
  9. ; Foundation, either version 2 of the License, or (at your option) any later
  10. ; version.
  11. ;
  12. ; This program is distributed in the hope that it will be useful, but WITHOUT
  13. ; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  14. ; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  15. ;
  16. ; You should have received a copy of the GNU General Public License along with
  17. ; this program. If not, see <http://www.gnu.org/licenses/>.
  18.  
  19. format MS COFF
  20.  
  21. public @EXPORT as 'EXPORTS'
  22.  
  23. include 'proc32.inc'
  24. include 'struct.inc'
  25. include 'macros.inc'
  26. include 'kglobals.inc'
  27.  
  28. purge section,mov,add,sub
  29. section '.flat' code readable align 16
  30.  
  31. include 'libcrash.inc'
  32. include 'hash/crc32.asm'
  33. include 'hash/md5.asm'
  34. include 'hash/sha1.asm'
  35. include 'hash/sha2_224_256.asm'
  36. include 'hash/sha2_384_512.asm'
  37. include 'hash/sha3.asm'
  38. include 'mac/poly1305.asm'
  39. include 'mac/hmac.asm'
  40. include 'cipher/chacha20.asm'
  41. include 'cipher/mode/ctr.asm'
  42. include 'cipher/mode/cbc.asm'
  43. include 'cipher/aes.asm'
  44. include 'cipher/aes_ctr.asm'
  45. include 'cipher/aes_cbc.asm'
  46.  
  47. LIBCRASH_BUF_SIZE = 0x1000
  48.  
  49. struct hash_item
  50.         init    dd ?
  51.         update  dd ?
  52.         finish  dd ?
  53.         oneshot dd ?
  54.         ctx_size dd ?
  55.         out_size dd ?
  56. ends
  57.  
  58. struct mac_item
  59.         init    dd ?
  60.         update  dd ?
  61.         finish  dd ?
  62.         oneshot dd ?
  63.         ctx_size dd ?
  64.         out_size dd ?
  65. ends
  66.  
  67. struct cipher_item      ; FIXME merge *_item, why not
  68.         init    dd ?
  69.         update  dd ?
  70.         finish  dd ?
  71.         oneshot dd ?
  72.         ctx_size dd ?
  73.                  dd ?   ; placeholder for out_size
  74. ends
  75.  
  76. ; Initialize the library.
  77. ; This must be the first called function of the library.
  78. ; Parameters:
  79. ; eax = function pointer to allocate memory:
  80. ;       stdcall void *alloc(size_t size)
  81. ; ebx = function pointer to free memory:
  82. ;       stdcall void free(void *ptr)
  83. ; Return value: none
  84. proc crash.init
  85.         mov     [mem.alloc], eax
  86.         mov     [mem.free], ebx
  87.         ret
  88. endp
  89.  
  90. ; Hash data read by a callback read function.
  91. ; The function calls the read callback until it returns 0, and hashes the read
  92. ; data with the specified algorithm. The result is written to the specified
  93. ; buffer in binary format.
  94. ; Parameters:
  95. ; [_id] = ID of a hash function to use.
  96. ; [_clbk_read] = function pointer to read data:
  97. ;                stdcall ssize_t clbk_read(void *user, void *buf, size_t size)
  98. ; [_user] = pointer to user-specified data passed to the read callback as is.
  99. ; [_out] = buffer pointer where a hash value is to be written to.
  100. ; Return value:
  101. ; binary hash value in [_out] buffer.
  102. proc crash.hash uses ebx esi edi, _id, _clbk_read, _user, _out
  103. locals
  104.         .ctx dd ?
  105.         .buf dd ?
  106. endl
  107.         ; alloc buf
  108.         mov     eax, [io_buf_size]
  109.         add     eax, LIBCRASH_MAX_PAD_LEN
  110.         stdcall [mem.alloc], eax
  111.         test    eax, eax
  112.         jz      .quit
  113.         mov     [.buf], eax
  114.         ; alloc ctx
  115.         mov     eax, [_id]
  116.         imul    eax, sizeof.hash_item
  117.         lea     ebx, [crash._.hash_table+eax]
  118.         stdcall [mem.alloc], [ebx+hash_item.ctx_size]
  119.         test    eax, eax
  120.         jz      .quit_free_buf
  121.         mov     [.ctx], eax
  122.  
  123.         stdcall [ebx+hash_item.init], [.ctx]
  124. .update:
  125.         stdcall [_clbk_read], [_user], [.buf], [io_buf_size]
  126.         test    eax, eax
  127.         jz      .finish
  128.         stdcall [ebx+hash_item.update], [.ctx], [.buf], eax
  129.         jmp     .update
  130. .finish:
  131.         stdcall [ebx+hash_item.finish], [.ctx]
  132.         mov     esi, [.ctx]
  133.         mov     edi, [_out]
  134.         mov     ecx, [ebx+hash_item.out_size]
  135.         rep movsd
  136. .quit_free_buf_ctx:
  137.         stdcall [mem.free], [.ctx]
  138. .quit_free_buf:
  139.         stdcall [mem.free], [.buf]
  140. .quit:
  141.         ret
  142. endp
  143.  
  144. ; Calculate MAC of data read by a callback read function.
  145. ; The function calls the read callback until it returns 0, and calculates a MAC
  146. ; using a specified algorithm and a key. The result is written to the specified
  147. ; buffer.
  148. ; Parameters:
  149. ; [_id] = ID of a MAC function to use.
  150. ; [_key] = key pointer, no NULL terminator is needed
  151. ; [_key_len] = length of the [_key] data, in bytes
  152. ; [_clbk_read] = function pointer to read data:
  153. ;                stdcall ssize_t clbk_read(void *user, void *buf, size_t size)
  154. ; [_user] = pointer to user-specified data passed to the read callback as is.
  155. ; [_out] = buffer pointer where a MAC value is to be written to.
  156. ; Return value:
  157. ; Binary MAC value in [_out] buffer.
  158. proc crash.mac uses ebx esi edi, _id, _key, _key_len, _clbk_read, _user, _out
  159. locals
  160.         .ctx dd ?
  161.         .buf dd ?
  162. endl
  163.         ; alloc buf
  164.         mov     eax, [io_buf_size]
  165.         add     eax, LIBCRASH_MAX_PAD_LEN
  166.         stdcall [mem.alloc], eax
  167.         test    eax, eax
  168.         jz      .quit
  169.         mov     [.buf], eax
  170.         ; alloc ctx
  171.         mov     eax, [_id]
  172.         imul    eax, sizeof.mac_item
  173.         lea     ebx, [crash._.mac_table+eax]
  174.         stdcall [mem.alloc], [ebx+mac_item.ctx_size]
  175.         test    eax, eax
  176.         jz      .quit_free_buf
  177.         mov     [.ctx], eax
  178.  
  179.         stdcall [ebx+mac_item.init], [.ctx], [_key], [_key_len]
  180. .update:
  181.         stdcall [_clbk_read], [_user], [.buf], [io_buf_size]
  182.         test    eax, eax
  183.         jz      .finish
  184.         stdcall [ebx+mac_item.update], [.ctx], [.buf], eax
  185.         jmp     .update
  186. .finish:
  187.         stdcall [ebx+mac_item.finish], [.ctx]
  188.         mov     esi, [.ctx]
  189.         mov     edi, [_out]
  190.         mov     ecx, [ebx+mac_item.out_size]
  191.         rep movsd
  192. .quit_free_buf_ctx:
  193.         stdcall [mem.free], [.ctx]
  194. .quit_free_buf:
  195.         stdcall [mem.free], [.buf]
  196. .quit:
  197.         ret
  198. endp
  199.  
  200. ; Encrypt or decrypt data read by a callback read function.
  201. ; The function calls the read callback until it returns 0, and encrypts or
  202. ; decrypts the data using a specified algorithm, a key and an input vector.
  203. ; The result is passed to the write callback function.
  204. ; * The maximum difference in input/output data lengths is LIBCRASH_MAX_PAD_LEN.
  205. ; * The input and output buffers can sometimes be the same buffer depending on
  206. ; the cipher. If unsure, use different buffers.
  207. ; Parameters:
  208. ; [_id] = ID of a MAC function to use.
  209. ; [_flags] = see LIBCRASH_CIPHER_* in libcrash.inc
  210. ; [_key] = key pointer, NULL terminated
  211. ; [_iv] = input vector pointer, no NULL terminator is needed
  212. ; [_clbk_read] = function pointer to read data:
  213. ;                stdcall ssize_t clbk_read(void *user, void *buf, size_t size)
  214. ; [_user_read] = pointer to user-specified data passed to the read callback.
  215. ; [_clbk_write] = function pointer to write data:
  216. ;                 stdcall void clbk_write(void *user, void *buf, size_t size)
  217. ; [_user_write] = pointer to user-specified data passed to the write callback.
  218. ; Return value: none
  219. proc crash.crypt uses ebx esi edi, _id, _flags, _key, _iv, _clbk_read, \
  220.                                    _user_read, _clbk_write, _user_write
  221. locals
  222.         .ctx dd ?
  223.         .buf dd ?
  224.         .buf_in dd ?
  225.         .buf_out dd ?
  226. endl
  227.         ; alloc buf
  228.         mov     eax, [io_buf_size]
  229.         mov     [.buf_out], eax
  230.         shl     eax, 1
  231.         add     eax, LIBCRASH_MAX_PAD_LEN
  232.         stdcall [mem.alloc], eax
  233.         test    eax, eax
  234.         jz      .quit
  235.         mov     [.buf], eax
  236.         mov     [.buf_in], eax
  237.         add     [.buf_out], eax
  238.         ; alloc ctx
  239.         mov     eax, [_id]
  240.         imul    eax, sizeof.cipher_item
  241.         lea     ebx, [crash._.cipher_table+eax]
  242.         stdcall [mem.alloc], [ebx+cipher_item.ctx_size]
  243.         test    eax, eax
  244.         jz      .quit_free_buf
  245.         mov     [.ctx], eax
  246.  
  247.         stdcall [ebx+cipher_item.init], [.ctx], [_key], [_iv], [_flags]
  248. .update:
  249.         stdcall [_clbk_read], [_user_read], [.buf_in], [io_buf_size]
  250.         test    eax, eax
  251.         jz      .finish
  252.         stdcall [ebx+cipher_item.update], [.ctx], [.buf_in], eax, [.buf_out]
  253.         stdcall [_clbk_write], [_user_write], [.buf_out], eax
  254.         jmp     .update
  255. .finish:
  256.         stdcall [ebx+cipher_item.finish], [.ctx], [.buf_out]
  257.         stdcall [_clbk_write], [_user_write], [.buf_out], eax
  258. .quit_free_buf_ctx:
  259.         stdcall [mem.free], [.ctx]
  260. .quit_free_buf:
  261.         stdcall [mem.free], [.buf]
  262. .quit:
  263.         ret
  264. endp
  265.  
  266. ; These crash.*_oneshot functions below are wrappers to <hash_name>.oneshot,
  267. ; <mac_name>.oneshot and <cipher_name>.oneshot functions. The functions pop
  268. ; [_id] argument from the stack and jump to the oneshot function of the
  269. ; corresponding algorithm with all the other arguments in place.
  270. ; You can also call <hash_name/mac_name/cipher_name>.oneshot functions directly.
  271.  
  272. ; Hash data in a buffer.
  273. ; The function hashes data in the specified buffer with the specified algorithm.
  274. ; The result is written to the very beginning of the specified context buffer in
  275. ; binary format.
  276. ; Parameters:
  277. ; [_id] = ID of a hash function to use.
  278. ; [_ctx] = buffer pointer for internal use, LIBCRASH_CTX_LEN bytes is enough.
  279. ; [_in] = pointer to input data
  280. ; [_len] = length of input data
  281. ; Return value:
  282. ; binary hash value in [_ctx] buffer.
  283. crash.hash_oneshot:     ; _id, _ctx, _in, _len
  284.         pop     eax
  285.         xchg    eax, [esp]
  286.         imul    eax, sizeof.hash_item
  287.         lea     eax, [crash._.hash_table+eax]
  288.         jmp     [eax+hash_item.oneshot]
  289.  
  290. ; Calculate MAC of data in the buffer.
  291. ; The function calculates a MAC of data in the specified buffer with the
  292. ; specified algorithm and key. The result is written to the very beginning of
  293. ; the specified context buffer in binary format.
  294. ; Parameters:
  295. ; [_id] = ID of a hash function to use.
  296. ; [_ctx] = buffer pointer for internal use, LIBCRASH_CTX_LEN bytes is enough.
  297. ; [_in] = pointer to input data
  298. ; [_len] = length of input data
  299. ; [_key] = key pointer, no NULL terminator is needed
  300. ; [_key_len] = length of the [_key] data, in bytes
  301. ; Return value:
  302. ; binary MAC value in [_ctx] buffer.
  303. crash.mac_oneshot:      ; _id, _ctx, _in, _len, _key, _key_len
  304.         pop     eax
  305.         xchg    eax, [esp]
  306.         imul    eax, sizeof.mac_item
  307.         lea     eax, [crash._.mac_table+eax]
  308.         jmp     [eax+mac_item.oneshot]
  309.  
  310. ; Encrypt or decrypt data in buffer.
  311. ; The function encrypts or decrypts data in the specified buffer using a
  312. ; specified algorithm, a key and an input vector. The result is written to
  313. ; another specified buffer.
  314. ; * The input and output buffers can sometimes be the same buffer depending on
  315. ; the cipher. If unsure, use different buffers.
  316. ; * The maximum difference in input/output data lengths is LIBCRASH_MAX_PAD_LEN.
  317. ; Parameters:
  318. ; [_id] = ID of a MAC function to use.
  319. ; [_ctx] = buffer pointer for internal use, LIBCRASH_CTX_LEN bytes is enough.
  320. ; [_key] = key pointer, NULL terminated
  321. ; [_iv] = input vector pointer, no NULL terminator is needed
  322. ; [_flags] = see LIBCRASH_CIPHER_* in libcrash.inc
  323. ; [_in] = pointer to input data
  324. ; [_len] = length of input data
  325. ; [_out] = pointer to output data
  326. ; Return value: none
  327. crash.crypt_oneshot:    ; _id, _ctx, _key, _iv, _flags, _in, _len, _out
  328.         pop     eax
  329.         xchg    eax, [esp]
  330.         imul    eax, sizeof.cipher_item
  331.         lea     eax, [crash._.cipher_table+eax]
  332.         jmp     [eax+cipher_item.oneshot]
  333.  
  334. section '.data' writeable align 16
  335. mem.alloc dd ?
  336. mem.free dd ?
  337. io_buf_size dd LIBCRASH_BUF_SIZE
  338. ; FIXME: IDs shouldn't be indexes, should they?
  339. align 4
  340. crash._.hash_table dd \
  341.         crc32.init,    crc32.update,    crc32.finish,    crc32.oneshot, \
  342.         sizeof.ctx_crc32,       CRC32_LEN/4, \
  343.         md5.init,      md5.update,      md5.finish,      md5.oneshot, \
  344.         sizeof.ctx_md5,         MD5_LEN/4, \
  345.         sha1.init,     sha1.update,     sha1.finish,     sha1.oneshot, \
  346.         sizeof.ctx_sha1,        SHA1_LEN/4, \
  347.         sha2_224.init, sha2_224.update, sha2_224.finish, sha2_224.oneshot, \
  348.         sizeof.ctx_sha2_224256, SHA2_224_LEN/4, \
  349.         sha2_256.init, sha2_256.update, sha2_256.finish, sha2_256.oneshot, \
  350.         sizeof.ctx_sha2_224256, SHA2_256_LEN/4, \
  351.         sha2_384.init, sha2_384.update, sha2_384.finish, sha2_384.oneshot, \
  352.         sizeof.ctx_sha2_384512, SHA2_384_LEN/4, \
  353.         sha2_512.init, sha2_512.update, sha2_512.finish, sha2_512.oneshot, \
  354.         sizeof.ctx_sha2_384512, SHA2_512_LEN/4, \
  355.         sha3_224.init, sha3.update,     sha3.finish,     sha3_224.oneshot, \
  356.         sizeof.ctx_sha3,        SHA3_224_LEN/4, \
  357.         sha3_256.init, sha3.update,     sha3.finish,     sha3_256.oneshot, \
  358.         sizeof.ctx_sha3,        SHA3_256_LEN/4, \
  359.         sha3_384.init, sha3.update,     sha3.finish,     sha3_384.oneshot, \
  360.         sizeof.ctx_sha3,        SHA3_384_LEN/4, \
  361.         sha3_512.init, sha3.update,     sha3.finish,     sha3_512.oneshot, \
  362.         sizeof.ctx_sha3,        SHA3_512_LEN/4, \
  363.         0
  364.  
  365. align 4
  366. crash._.mac_table dd \
  367.         poly1305.init,      poly1305.update,      poly1305.finish, \
  368.         poly1305.oneshot,      sizeof.ctx_poly1305, POLY1305_LEN/4, \
  369.         hmac_sha2_256.init, hmac_sha2_256.update, hmac_sha2_256.finish, \
  370.         hmac_sha2_256.oneshot, sizeof.ctx_hmac,     HMAC_SHA2_256_LEN/4, \
  371.         hmac_sha2_512.init, hmac_sha2_512.update, hmac_sha2_512.finish, \
  372.         hmac_sha2_512.oneshot, sizeof.ctx_hmac,     HMAC_SHA2_512_LEN/4, \
  373.         0
  374.  
  375. align 4
  376. crash._.cipher_table dd \
  377.         chacha20.init,  chacha20.update,  chacha20.finish,  chacha20.oneshot, \
  378.         sizeof.ctx_chacha20, 0, \
  379.         aes256ctr.init, aes256ctr.update, aes256ctr.finish, aes256ctr.oneshot, \
  380.         sizeof.ctx_aes_ctr,  0, \
  381.         aes256cbc.init, aes256cbc.update, aes256cbc.finish, aes256cbc.oneshot, \
  382.         sizeof.ctx_aes_cbc,  0, \
  383.         0
  384.  
  385. IncludeIGlobals
  386.  
  387. align 4
  388. @EXPORT:
  389.  
  390. export \
  391.         crash.init, "lib_init", \
  392.         crash.hash, "crash_hash", \
  393.         crash.mac, "crash_mac", \
  394.         crash.crypt, "crash_crypt", \
  395.         crash.hash_oneshot, "crash_hash_oneshot", \
  396.         crash.mac_oneshot, "crash_mac_oneshot", \
  397.         crash.crypt_oneshot, "crash_crypt_oneshot", \
  398.         \
  399.         crc32.init, "crc32_init", \
  400.         crc32.update, "crc32_update", \
  401.         crc32.finish, "crc32_finish", \
  402.         crc32.oneshot, "crc32_oneshot", \
  403.         md5.init, "md5_init", \
  404.         md5.update, "md5_update", \
  405.         md5.finish, "md5_finish", \
  406.         md5.oneshot, "md5_oneshot", \
  407.         sha1.init, "sha1_init", \
  408.         sha1.update, "sha1_update", \
  409.         sha1.finish, "sha1_finish", \
  410.         sha1.oneshot, "sha1_oneshot", \
  411.         sha2_224.init, "sha2_224_init", \
  412.         sha2_224.update, "sha2_224_update", \
  413.         sha2_224.finish, "sha2_224_finish", \
  414.         sha2_224.oneshot, "sha2_224_oneshot", \
  415.         sha2_256.init, "sha2_256_init", \
  416.         sha2_256.update, "sha2_256_update", \
  417.         sha2_256.finish, "sha2_256_finish", \
  418.         sha2_256.oneshot, "sha2_256_oneshot", \
  419.         sha2_384.init, "sha2_384_init", \
  420.         sha2_384.update, "sha2_384_update", \
  421.         sha2_384.finish, "sha2_384_finish", \
  422.         sha2_384.oneshot, "sha2_384_oneshot", \
  423.         sha2_512.init, "sha2_512_init", \
  424.         sha2_512.update, "sha2_512_update", \
  425.         sha2_512.finish, "sha2_512_finish", \
  426.         sha2_512.oneshot, "sha2_512_oneshot", \
  427.         sha3_224.init, "sha3_224_init", \
  428.         sha3_224.update, "sha3_224_update", \
  429.         sha3_224.finish, "sha3_224_finish", \
  430.         sha3_224.oneshot, "sha3_224_oneshot", \
  431.         sha3_256.init, "sha3_256_init", \
  432.         sha3_256.update, "sha3_256_update", \
  433.         sha3_256.finish, "sha3_256_finish", \
  434.         sha3_256.oneshot, "sha3_256_oneshot", \
  435.         sha3_384.init, "sha3_384_init", \
  436.         sha3_384.update, "sha3_384_update", \
  437.         sha3_384.finish, "sha3_384_finish", \
  438.         sha3_384.oneshot, "sha3_384_oneshot", \
  439.         sha3_512.init, "sha3_512_init", \
  440.         sha3_512.update, "sha3_512_update", \
  441.         sha3_512.finish, "sha3_512_finish", \
  442.         sha3_512.oneshot, "sha3_512_oneshot", \
  443.         \
  444.         poly1305.init, "poly1305_init", \
  445.         poly1305.update, "poly1305_update", \
  446.         poly1305.finish, "poly1305_finish", \
  447.         poly1305.oneshot, "poly1305_oneshot", \
  448.         hmac_sha2_256.init, "hmac_sha2_256_init", \
  449.         hmac_sha2_256.update, "hmac_sha2_256_update", \
  450.         hmac_sha2_256.finish, "hmac_sha2_256_finish", \
  451.         hmac_sha2_256.oneshot, "hmac_sha2_256_oneshot", \
  452.         hmac_sha2_512.init, "hmac_sha2_512_init", \
  453.         hmac_sha2_512.update, "hmac_sha2_512_update", \
  454.         hmac_sha2_512.finish, "hmac_sha2_512_finish", \
  455.         hmac_sha2_512.oneshot, "hmac_sha2_512_oneshot", \
  456.         \
  457.         chacha20.init, "chacha20_init", \
  458.         chacha20.update, "chacha20_update", \
  459.         chacha20.finish, "chacha20_finish", \
  460.         chacha20.oneshot, "chacha20_oneshot", \
  461.         aes256ctr.init, "aes256ctr_init", \
  462.         aes256ctr.update, "aes256ctr_update", \
  463.         aes256ctr.finish, "aes256ctr_finish", \
  464.         aes256ctr.oneshot, "aes256ctr_oneshot", \
  465.         aes256cbc.init, "aes256cbc_init", \
  466.         aes256cbc.update, "aes256cbc_update", \
  467.         aes256cbc.finish, "aes256cbc_finish", \
  468.         aes256cbc.oneshot, "aes256cbc_oneshot"
  469.