bee2-rs 0.2.3

Bindings for cryptographic library Bee2
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
/*
*******************************************************************************
\file defs.h
\brief Basic definitions
\project bee2 [cryptographic library]
\created 2012.04.01
\version 2025.06.09
\copyright The Bee2 authors
\license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
*******************************************************************************
*/

/*!
*******************************************************************************
\file defs.h
\brief Базовые определения
*******************************************************************************
*/

#ifndef __BEE2_DEFS_H
#define __BEE2_DEFS_H

#include <limits.h>
#include <stddef.h>

#ifndef SIZE_MAX
	#include <stdint.h>
#endif

/*!
*******************************************************************************
\file defs.h

\section defs-types Типы данных

\pre Длина машинного слова в битах (B_PER_W) равняется 16, 32 или 64.

\pre Длина слова типа size_t в битах не менее 16.

\pre Обязательно поддерживаются типы u16, u32.

Могут поддерживаться типы u64, u128.

\remark Поддержка B_PER_W == 16 полезна для организации тестирования
арифметики больших чисел и арифметики многочленов: как правило, ошибки в
функциях арифметики возникают с вероятностями, близкими к 1 / 2^B_PER_W.

\remark При разборе платформ для определения порядка октетов использован код
Брайана Гладмана (Brian Gladman, http://www.gladman.me.uk/) и ресурс
https://sourceforge.net/p/predef/wiki/Endianness/.

\remark Платформа EMSCRIPTEN (https://emscripten.org) является виртуальной, на 
ней выполняется компиляция в asm.js. 

\section defs-arrays Массивы

Массив элементов типа T, как правило, передается в функцию в виде пары
(указатель in на элементы массива, длина массива in_len). Здесь in имеет тип
const T*, а in_len -- тип size_t. При документировании массива используется
запись [in_len]in. При T == void запись имеет такой же смысл, как при
T == octet.

Если длина in_len заранее известна, то она может не передаваться в функцию.

Массив элементов типа T заранее известного размера возвращается из функций
через буфер, на который ссылается указатель out типа T*.

Если длина массива заранее неизвестна, то для его возврата используется пара
(указатель out, размер out_len), где out_len имеет тип size_t*.
Если обратиться к функции с нулевым out, то по адресу out_len будет
размещена длина возвращаемого массива. При обращении с ненулевым out по
адресу out_len должно быть указано число элементов типа T, зарезервированных
в буфере out. В результате выполнения функции число по адресу out_len 
корректируется -- устанавливается равным актуальному числу элементов,
записанных в массив out. Размер буфера может контролироваться предусловиями.
О недостаточности размера функция может сообщать через коды возврата.

При документировании описанной логики возврата массива используется
запись [?out_len]out. При T == void запись имеет такой же смысл,
как при T == octet.

Имеется схожий синтаксис [out_len?]out. Отличие в том, что при обращении
к функции с ненулевым указателем out значение по адресу out_len не
определено, более того, адрес out_len при дополнительных оговорках
может быть нулевым.

Выражение out_len? может входить в арифметическое выражение, которое уточняет
требуемый объем памяти. Например, запись [out_len? + 1]str означает, что
для буфера (строки) str требуется один дополнительный к out_len октет
(в него будет записан завершающий нулевой символ).

\section defs-seqs Последовательности вызовов

Ограничения на последовательность вызовов определенных функций документируются
с помощью знаков "<", "*" и "<<".

Запись "f1() < f2()" означает, что функция f2() должна вызываться после f1().

Запись "f1() < [f2()] < f3()" означает, что функция f2() должна вызываться 
после f1(), f3() после f2(), и вызов f2() может быть пропущен.

Запись "f()*" означает, что функция f() может вызываться последовательно
произвольное число раз.

Запись "f1()* < f2()" означает, что несколько вызовов f1() завершаются
вызовом f2().

Запись "(f1()* < f2())*" означает, что каскад "несколько раз f1(), затем f2()"
может повторяться произвольное число раз. Например, возможность
инкрементального хэширования, при котором можно рассчитывать хэш-значение
все более длинного фрагмента, обозначается следующим образом:
\code
(hash_step()* < hash_get())*.
\endcode

Знак "<<" используется при документировании протоколов. Запись "f1() << f2()"
означает, что перед вызовом функции f2() стороной A сторона B должна вызвать
функцию f1() и переслать результаты ее работы стороне B.
*******************************************************************************
*/

/*!
*******************************************************************************
\def OCTET_ORDER
\brief Порядок октетов в машинном слове

\def LITTLE_ENDIAN
\brief Порядок "от младших к старшим"

\def BIG_ENDIAN
\brief Порядок "от старших к младшим"
*******************************************************************************
*/

#ifndef LITTLE_ENDIAN
	#define LITTLE_ENDIAN 1234
#endif

#ifndef BIG_ENDIAN
	#define BIG_ENDIAN 4321
#endif

#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) ||\
	defined(__LITTLE_ENDIAN__) ||\
	defined(__M_IX86) || defined(_X86_) || defined(i386) ||\
	defined(__i386__) || defined(_M_I86)  || defined(_M_IX86) ||\
	defined(_M_IA64) || defined(__ia64__) || defined(_M_X64) ||\
	defined(_M_AMD64) || defined(__amd64__) || defined(__amd64) ||\
	defined(__x86_64__) ||\
	defined(_MIPSEL) || defined (__MIPSEL) || defined (__MIPSEL__) ||\
	defined(__arm__) || defined(__ARMEL__) || defined(__AARCH64EL__) ||\
	defined(_M_ARM) || defined(_M_ARM64) ||\
	defined (__THUMBEB__) ||\
	defined(_M_ALPHA) || defined(__alpha__) || defined(__alpha) ||\
	defined(__OS2__) || defined(sun386) || defined(vax) ||\
	defined(vms) || defined(VMS) || defined(__VMS) ||\
	defined(__EMSCRIPTEN__)
	#define OCTET_ORDER LITTLE_ENDIAN
#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) ||\
	defined(__BIG_ENDIAN__) ||\
	defined(_MIPSEB) || defined (__MIPSEB) || defined (__MIPSEB__) ||\
	defined(__ARMEB__) || defined(__AARCH64EB__) ||\
	defined(__THUMBEB__) ||\
	defined(__s390__) || defined(__s390x__) || defined(__zarch__) ||\
	defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) ||\
	defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) ||\
	defined(AMIGA) || defined(applec) || defined(__AS400__) ||\
	defined(_CRAY) || defined(__hppa) || defined(__hp9000) ||\
	defined(ibm370) || defined(mc68000) || defined(m68k) ||\
	defined(__MRC__) || defined(__MVS__) || defined(__MWERKS__) ||\
	defined(sparc) || defined(__sparc) ||\
	defined(__VOS__) || defined(__TIGCC__) || defined(__TANDEM) ||\
	defined(THINK_C) || defined(__VMCMS__) || defined(_AIX)
	#define OCTET_ORDER BIG_ENDIAN
#else
	#error "Platform undefined"
#endif

/*!
*******************************************************************************
\def OS_WIN
\brief Операционная система Windows

\def OS_UNIX
\brief Операционная система Unix

\def OS_LINUX
\brief Операционная система Linux
\remark Подсистема OS_UNIX

\def OS_ANDROID
\brief Операционная система Android
\remark Подсистема OS_LINUX

\def OS_APPLE
\brief Операционная система macOS / iOS
\remark Подсистема OS_UNIX

\def OS_IPHONE
\brief Операционная система iOS для iPhone
\remark Подсистема OS_APPLE

\remark Тип операционной системы определяется в соответствии с
* https://sourceforge.net/p/predef/wiki/OperatingSystems/;
* https://stackoverflow.com/questions/5919996.
*******************************************************************************
*/

#undef OS_WIN
#undef OS_UNIX
#undef OS_LINUX
#undef OS_ANDROID
#undef OS_APPLE
#undef OS_IPHONE

#if defined(_WIN32) || defined(_WIN64) || defined(__WINNT) ||\
	defined(__WIN32__) || defined(__WIN64__)  || defined(__WINNT__)
	#define OS_WIN
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
	#define OS_UNIX
	#if defined(__linux__) || defined (linux) || defined(__linux)
		#define OS_LINUX
		#if defined(__ANDROID__)
			#define OS_ANDROID
		#endif
	#elif defined(__APPLE__)
		#include <TargetConditionals.h>
		#define OS_APPLE
		#if defined(TARGET_OS_IPHONE)
			#define OS_IPHONE
		#endif
	#endif
#endif

/*!
*******************************************************************************
\typedef octet
\brief Октет

\typedef u8
\brief 8-разрядное беззнаковое целое

\typedef i8
\brief 8-разрядное знаковое целое

\typedef u16
\brief 16-разрядное беззнаковое целое

\typedef i16
\brief 16-разрядное знаковое целое

\typedef u32
\brief 32-разрядное беззнаковое целое

\typedef i32
\brief 32-разрядное знаковое целое
*******************************************************************************
*/

#undef U8_SUPPORT
#undef U16_SUPPORT
#undef U32_SUPPORT
#undef U64_SUPPORT
#undef U128_SUPPORT

#if (UCHAR_MAX == 255)
	typedef unsigned char u8;
	typedef signed char i8;
	typedef u8 octet;
	#define U8_SUPPORT
#else
	#error "Unsupported char size"
#endif

#if (USHRT_MAX == 65535)
	typedef unsigned short u16;
	typedef signed short i16;
	#define U16_SUPPORT
#else
	#error "Unsupported short size"
#endif

#if (UINT_MAX == 65535u)
	#if (ULONG_MAX == 4294967295ul)
		typedef unsigned long u32;
		typedef signed long i32;
		#define U32_SUPPORT
	#else
		#error "Unsupported long size"
	#endif
#elif (UINT_MAX == 4294967295u)
	typedef unsigned int u32;
	typedef signed int i32;
	#define U32_SUPPORT
	#if (ULONG_MAX == 4294967295ul)
		#if !defined(ULLONG_MAX) || (ULLONG_MAX == 4294967295ull)
			#error "Unsupported int/long/long long configuration"
		#elif (ULLONG_MAX == 18446744073709551615ull)
			typedef unsigned long long u64;
			typedef signed long long i64;
			#define U64_SUPPORT
			#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
				typedef __int128 i128;
				typedef unsigned __int128 u128;
				#define U128_SUPPORT
			#endif
		#else
			#error "Unsupported int/long/long long configuration"
		#endif
	#elif (ULONG_MAX == 18446744073709551615ul)
		typedef unsigned long u64;
		typedef signed long i64;
		#define U64_SUPPORT
		#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
			typedef __int128 i128;
			typedef unsigned __int128 u128;
			#define U128_SUPPORT
		#endif
	#else
		#error "Unsupported int/long configuration"
	#endif
#elif (UINT_MAX == 18446744073709551615u)
	#if (ULONG_MAX == 18446744073709551615ul)
		#if !defined(ULLONG_MAX) || (ULLONG_MAX == 18446744073709551615ull)
			#error "Unsupported int/long/long long configuration"
		#elif (ULLONG_MAX == 340282366920938463463374607431768211455ull)
			typedef unsigned long long u128;
			typedef signed long long i128;
			#define U128_SUPPORT
		#else
			#error "Unsupported int/long/long long configuration"
		#endif
	#elif (ULONG_MAX == 340282366920938463463374607431768211455ul)
		typedef unsigned long u128;
		typedef signed long i128;
		#define U128_SUPPORT
	#else
		#error "Unsupported long size"
	#endif
#else
	#error "Unsupported int size"
#endif

#if !defined(U8_SUPPORT) || !defined(U16_SUPPORT) || !defined(U32_SUPPORT)
	#error "One of the base types is not supported"
#endif

/*!
*******************************************************************************
\def B_PER_W
\brief Число битов в машинном слове

\def O_PER_W
\brief Число октетов в машинном слове

\def B_PER_S
\brief Число битов в size_t

\def O_PER_S
\brief Число октетов в size_t

\typedef word
\brief Машинное слово

\typedef dword
\brief Двойное машинное слово
*******************************************************************************
*/

#if defined(U128_SUPPORT)
	#define B_PER_W 64
	typedef u64 word;
	typedef u128 dword;
#elif defined(U64_SUPPORT)
	#define B_PER_W 32
	typedef u32 word;
	typedef u64 dword;
#else
	#define B_PER_W 16
	typedef u16 word;
	typedef u32 dword;
#endif

#if (B_PER_W != 16 && B_PER_W != 32 && B_PER_W != 64)
	#error "Unsupported word size"
#endif

#define O_PER_W (B_PER_W / 8)
#define O_PER_S (B_PER_S / 8)

#define SIZE_0 ((size_t)0)
#define SIZE_1 ((size_t)1)
#ifndef SIZE_MAX
	#define SIZE_MAX ((size_t)(SIZE_0 - SIZE_1))
#endif

#if (SIZE_MAX == 65535u)
	#define B_PER_S 16
#elif (SIZE_MAX == 4294967295u)
	#define B_PER_S 32
#elif (SIZE_MAX == 18446744073709551615u)
	#define B_PER_S 64
#else
	#error "Unsupported size_t size"
#endif

/*
*******************************************************************************
Макросы конвертации
*******************************************************************************
*/

/*!	\brief Число октетов для размещения nb битов */
#define O_OF_B(nb) (((nb) + 7) / 8)

/*!	\brief Число машинных слов для размещения nb битов */
#define W_OF_B(nb) (((nb) + B_PER_W - 1) / B_PER_W)

/*!	\brief Число битов для размещения no октетов */
#define B_OF_O(no) ((no) * 8)

/*!	\brief Число машинных слов для размещения no октетов */
#define W_OF_O(no) (((no) + O_PER_W - 1) / O_PER_W)

/*!	\brief Число октетов для размещения nw машинных слов */
#define O_OF_W(nw) ((nw) * O_PER_W)

/*!	\brief Число битов для размещения nw машинных слов */
#define B_OF_W(nw) ((nw) * B_PER_W)

/*
*******************************************************************************
Булевы данные
*******************************************************************************
*/

/*!	\brief Булев тип */
typedef int bool_t;

#ifndef TRUE
	#define TRUE ((bool_t)1)
#endif

#ifndef FALSE
	#define FALSE ((bool_t)0)
#endif

/*
*******************************************************************************
Ошибки
*******************************************************************************
*/

/*!	\brief Коды ошибок
	\remark Высокоуровневые функции возвращают значения типа err_t.
	Возврат ERR_OK означает, что функция завершена успешно. Код ERR_MAX
	зарезервирован для описания специальных особых ситуаций.
	Возврат других значений означает ошибку при выполнении функции.
*/
typedef u32 err_t;

/*!	\brief Код успешного завершения */
#define ERR_OK	((err_t)0)

/*!	\brief Максимальный код ошибки */
#define ERR_MAX	(ERR_OK - (err_t)1)

/*!
*******************************************************************************
\brief Невозможное событие

Событие, вероятность наступления которого <= 2^{-B_PER_IMPOSSIBLE}, считается 
невозможным.

\remark Э. Борель: "событие, вероятность которого ниже
10^{-50} \approx 2^{-166}, не произойдет никогда, сколько бы возможностей
ни представилось" [Probability and Life, 1962].
*******************************************************************************
*/

#define B_PER_IMPOSSIBLE 64

/*!
*******************************************************************************
\brief Интерфейс генерации

Функция интерфейса gen_i генерирует count октетов и записывает их в буфер buf.
При генерации может использоваться и изменяться вспомогательная память
(состояние) state.

Функция интерфейса gen_i интерпретируется как генератор с состоянием state.
Используются генераторы двух типов:
-	rng (random number generator): генераторы случайных или
	псевдослучайных чисел;
-	ang (arbitrary number generator): генераторы произвольных чисел,
	которые реализуют принцип "выбрать произвольным образом". Генерируемые
	числа (октеты) могут строиться по меткам времени, значениям монотонного
	счетчика, случайным или псевдослучайным числам. Числа могут использоваться
	в криптографических протоколах для построения синхропосылок, нонсов,
	затравочных значений (seed), "соли" (salt).
.
\pre Буфер buf корректен.
\pre Состояние state корректно.
\expect Состояние state поддерживается постоянным между последовательными
обращениями к функции.
\expect Октеты, формируемые генераторами rng, обладают минимальным
статистическим качеством: каждое значение встречается с примерно равной
частотой.
\expect Октеты, формируемые генераторами ang, почти не повторяются
(повторяются только с пренебрежимо малыми вероятностями или только
на недостижимо больших интервалах наблюдения).
\remark Функция интерфейса gen_i всегда генерирует все запрашиваемые октеты.
Ошибки при генерации не предусмотрены.
*******************************************************************************
*/

typedef void (*gen_i)(
	void* buf,			/*!< [out] случайные числа */
	size_t count,		/*!< [in] число октетов */
	void* state			/*!< [in,out] cостояние */
);

/*!
*******************************************************************************
\brief Интерфейс чтения

Функция интерфейса read_i читает данные из файла file в буфер [count]buf.
По адресу read возвращается число прочитанных октетов.
\pre Буфер buf корректен.
\pre Указатель read корректен.
\pre Файл file корректен.
\return ERR_OK, если прочитано определенное число октетов (возможно меньшее
count и возможно нулевое) и конец файла не достигнут, ERR_MAX, если прочитано
меньше чем count октетов и достигнут конец файла, или другой код ошибки.
\remark Файл -- это произвольный массив или поток данных на произвольном
устройстве. В качестве файла может выступать обычный дисковый файл, сетевое
соединение, источник случайности и т.д.
\remark Для файлов некоторых устройств ошибкой не считается ситуация,
когда прочитано меньше чем count октетов. Данная ситуация может быть связана
с ожиданием данных в канале связи.
\remark Передавая count == 0, можно проверить наличие файла.
*******************************************************************************
*/

typedef err_t (*read_i)(
	size_t* read,		/*!< [out] число прочитанных октетов */
	void* buf,			/*!< [out] прочитанные данные */
	size_t count,		/*!< [in] длина buf в октетах */
	void* file			/*!< [in,out] описание файла */
);

/*!
*******************************************************************************
\brief Интерфейс записи

Функция интерфейса write_i записывает буфер [count]buf в файл file.
По адресу written возвращается число записанных в файл октетов.
\pre Указатель written корректен.
\pre Буфер buf корректен.
\pre Файл file корректен.
\return ERR_OK, если записаны все октеты buf, и код ошибки в противном случае.
*******************************************************************************
*/

typedef err_t (*write_i)(
	size_t* written,	/*!< [out] число записанных октетов */
	const void* buf,	/*!< [in] записываемые данные */
	size_t count,		/*!< [in] длина buf в октетах */
	void* file			/*!< [in,out] описание файла */
);

#endif /* __BEE2_DEFS_H */