Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
9216 dunkaist 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 .
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 .oneshot,
267
; .oneshot and .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 .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
 
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
 
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
 
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"