botp.h(3)
🌸 NAME 🌸
You're looking at botp.h(3) from the Library Functions Manual, and it's giving one-time password management algorithms 💅🔐
✨ SYNOPSIS ✨
#include 'bee2/defs.h'
#include 'bee2/core/tm.h'
🎀 Функции (Functions) 🎀
void botpDT (char *otp, size_t digit, const octet mac[], size_t mac_len)— builds a password out of a MAC (имитовставка) 🍓void botpCtrNext (octet ctr[8])— the next counter, pls advance 📈size_t botpHOTP_keep ()— how many bytes of state the HOTP functions needvoid botpHOTPStart (void *state, size_t digit, const octet key[], size_t key_len)— sets HOTP mode up ✨void botpHOTPStepS (void *state, const octet ctr[8])— sets the HOTP mode countervoid botpHOTPStepR (char *otp, void *state)— generates the next password in HOTP modebool_t botpHOTPStepV (const char *otp, void *state)— checks the next password in HOTP modevoid botpHOTPStepG (octet ctr[8], const void *state)— hands the counter back to youerr_t botpHOTPRand (char *otp, size_t digit, const octet key[], size_t key_len, const octet ctr[8])— generates a password in HOTP modeerr_t botpHOTPVerify (const char *otp, const octet key[], size_t key_len, const octet ctr[8])— checks a password in HOTP modesize_t botpTOTP_keep ()— how many bytes of state the TOTP functions needvoid botpTOTPStart (void *state, size_t digit, const octet key[], size_t key_len)— sets TOTP mode up ⏰void botpTOTPStepR (char *otp, tm_time_t t, void *state)— generates the next password in TOTP modebool_t botpTOTPStepV (const char *otp, tm_time_t t, void *state)— checks the next password in TOTP modeerr_t botpTOTPRand (char *otp, size_t digit, const octet key[], size_t key_len, tm_time_t t)— generates a password in TOTP modeerr_t botpTOTPVerify (const char *otp, const octet key[], size_t key_len, tm_time_t t)— checks a password in TOTP modesize_t botpOCRA_keep ()— how many bytes of state the OCRA functions needbool_t botpOCRAStart (void *state, const char *suite, const octet key[], size_t key_len)— sets OCRA mode up 🦋void botpOCRAStepS (void *state, const octet ctr[8], const octet p[], const octet s[])— sets the session data for OCRA modevoid botpOCRAStepR (char *otp, const octet q[], size_t q_len, tm_time_t t, void *state)— generates the next password in OCRA modebool_t botpOCRAStepV (const char *otp, const octet q[], size_t q_len, tm_time_t t, void *state)— checks the next password in OCRA modevoid botpOCRAStepG (octet ctr[8], const void *state)— hands the counter back to youerr_t botpOCRARand (char *otp, const char *suite, const octet key[], size_t key_len, const octet q[], size_t q_len, const octet ctr[8], const octet p[], const octet s[], tm_time_t t)— generates a password in OCRA modeerr_t botpOCRAVerify (const char *otp, const char *suite, const octet key[], size_t key_len, const octet q[], size_t q_len, const octet ctr[8], const octet p[], const octet s[], tm_time_t t)— checks a password in TOTP mode 👀 (yep, that's literally what the line says, we're keeping it exactly as-is, no cap)
💖 Подробное описание (DESCRIPTION) 💖
🫶 Общие положения (the general vibe) 🫶
So bestie, one-time password management algorithms are implemented here. They line up with RFC 4226, RFC 6238, RFC 6287, and they're built on top of the HMAC[belt-hash] имитозащита (MAC) mechanism, which is defined in СТБ 34.101.47 and implemented in the belt module. 🔥
A password is a string made of digit characters from the alphabet {'0' - '9'}, where 4 <= digit <= 9. 🎀
The algorithms get grouped up, and those groups define these cryptographic mechanisms (a.k.a. modes):
- HOTP — event-based passwords (RFC 4226) 📅
- TOTP — time-based passwords (RFC 6238) ⏰
- OCRA — challenge-based passwords (RFC 6287) 🎯
Every mechanism is implemented by a whole bundle of several functions. These functions share one common state, and a pointer to it gets passed into the functions as an extra parameter. There's also a function that tells you how much memory the state needs (_keep). The calling program prepares the memory for the state, and that same calling program is the one responsible for clearing it. The state can be copied around like any memory fragment, periodt. ✨
A bundle always has a mode-initialization function (Start) plus one or more functions that process data fragments and produce the processing results (StepX).
The logic behind the StepX suffixes, iykyk:
- S — set (set the session data) 📥
- R — rand (generate a password) 🎲
- V — verify (check a password, restore synchronization) ✅
- G — get (get the updated session data) 📤
Bundle functions are designed to be as simple and as efficient as possible. Like, in particular, they do not check the input data. 😭
Each bundle is wrapped by a high-level function that chews through all the data in one go. The high-level functions do check the input data. 🫶
The function botpDT() implements the auxiliary "dynamic truncation" algorithm. You can use it with arbitrary MACs — not just with hmac-hbelt MACs. 💅
HOTP and OCRA modes use a counter — a string of 8 octets. That string is interpreted as a number using the big-endian rules ("most significant to least significant") that RFC 4226 lays down. Passwords are generated on successive counter values modulo 2^64. The counter increment is implemented in the function botpCtrNext(). 📈
Ожидается (Expected): the common state of a function bundle does not get changed outside of those functions. 🙅♀️
Ожидается [ERR_BAD_INPUT] (Expected): every input pointer of the high-level functions is valid.
Предусловие (Precondition): every input pointer of the low-level functions is valid. The size of the string buffer is 1 octet larger than the length of the string (accounting for the terminating zero octet). And unless stated otherwise, the input buffers of bundle functions do not overlap. 🚫
🔥 Режим HOTP (HOTP mode) 🔥
When a password is generated — and also when a password is successfully verified — in the functions botpHOTPStepR() and botpHOTPStepV(), the counter sitting in the state gets incremented. You can use that refreshed counter to generate or verify a new password. And you can unload the counter out of the state with the function botpHOTPStepG(). 🧚
⏰ Режим TOTP (TOTP mode) ⏰
The current time here is the so-called UNIX time — the number of seconds that have passed since 1970-01-01T00:00:00Z. 🕰️
The current time t gets rounded. That rounding happens with the parameters t0 — the base time mark — and ts — the time step. The rounding consists of replacing t with (t - t0) / ts. If t < t0, the rounding finishes with an error. 😵 You can do the rounding with the function tmTimeRound(). That function returns TIME_ERR when there are errors getting the current time mark or rounding it.
When you round, the recommendation is to use t0 = 0 and ts = 30 or 60. ✨
A time mark is represented by the type tm_time_t. The mark gets converted into a HOTP mode counter, i.e. into a 64-bit unsigned number. 🌈
✨ Режим OCRA ✨
окей бести, вот режим OCRA 👑, и он весь про параметры. В этом режиме используются такие параметры:
q— запрос (клиента, сервера или составной);ctr— счетчик;p— хэш-значение статического пароля клиента и сервера;t— округленная отметка времени;s— идентификатор сеанса между клиентом и сервером.
Параметры ctr, p, s описывают сеанс между клиентом и сервером. Параметры ctr, p, t, s являются необязательными.
Необходимость использования того или иного параметра, а также формат параметра, его длина, параметры округления времени определяются строковым описателем suite. литерали всё решает suite, и это икона ✨.
Запрос q может быть 3 типов: A (буквенно-цифровой), N (цифровой) и H (шестнадцатеричный). Формат запроса в функциях OCRA не проверяется. Для предварительной проверки запроса можно использовать функции strIsAlphanumeric(), decIsValid(), hexIsValid(). вайб-чек делай сам, если надо 🫶.
Запрос q может быть одиночным или двойным. Если q — одиночный, то его длина лежит в пределах от 4 до q_max, где q_max — максимальная длина, указанная в suite. Если q — двойной, то его длина лежит в пределах от 8 до 2 * q_max. За подготовку составного запроса отвечает вызывающая программа. но кэп 🍓.
💖 Функции 💖
окей, а теперь функции. Держись, тут много, но всё по делу. не я, но... это важно 😭.
void botpCtrNext (octet ctr[8])
Счетчик ctr режимов HOTP и OCRA инкрементируется \mod 2^64. буквально по модулю два в шестьдесят четвертой, и это слэй 💅.
void botpDT (char * otp, size_t digit, const octet mac[], size_t mac_len)
По имитовставке [mac_len]mac строится одноразовый пароль otp из digit десятичных цифр. вайб-чек пройден, если всё сходится 🌸.
Предусловие
4 <= digit && digit <= 10.mac_len >= 20.
size_t botpHOTP_keep ()
Возвращается длина состояния (в октетах) функций механизма HOTP. запомни это число, оно пригодится 🎀.
Возвращает
Длина состояния.
err_t botpHOTPRand (char * otp, size_t digit, const octet key[], size_t key_len, const octet ctr[8])
По ключу [key_len]key и счетчику ctr генерируется одноразовый пароль otp из digit десятичных символов. слэй 🔥.
Ожидается [ERR_BAD_PARAMS]
6 <= digit && digit <= 8.
Возвращает
ERR_OK, если пароль успешно сгенерирован, и код ошибки в противном случае.
Аргументы
otp— одноразовый парольdigit— длина пароляkey— ключkey_len— длина ключа в октетахctr— счетчик
void botpHOTPStart (void * state, size_t digit, const octet key[], size_t key_len)
По числу digit ключу [key_len]key в state формируются структуры данных, необходимые для управления паролями длины digit в режиме HOTP. это буквально старт 🚀.
Предусловие
6 <= digit && digit <= 8.- По адресу
stateзарезервированоbotpHOTP_keep()октетов.
Прим.
Рекомендуется использовать ключ из 32 октетов. 32 октета — это вайб ✨.
Аргументы
state— состояниеdigit— число цифр в паролеkey— ключkey_len— длина ключа в октетах
void botpHOTPStepG (octet ctr[8], const void * state)
В ctr возвращается текущий счетчик, размещенный в state. просто забери его 💅.
Ожидается
botpHOTPStepS() < botpHOTPStepG().
Аргументы
ctr— счетчикstate— состояние
void botpHOTPStepR (char * otp, void * state)
По числу digit, ключу и счетчику, размещенным в state, генерируется одноразовый пароль из digit десятичных символов. После генерации пароля счетчик инкрементируется. главная героиня энерджи 👑.
Ожидается
botpHOTPStepS() < botpHOTPStepR()*.
Аргументы
otp— одноразовый парольstate— состояние
void botpHOTPStepS (void * state, const octet ctr[8])
В state устанавливается счетчик ctr. периодт 🍓.
Ожидается
botpHOTPStart() < botpHOTPStepS().
Аргументы
state— состояниеctr— счетчик
bool_t botpHOTPStepV (const char * otp, void * state)
По числу digit, ключу и счетчику, размещенным в state, строится одноразовый пароль из digit десятичных цифр. Построенный пароль сравнивается с otp. Если пароли совпадают, то счетчик инкрементируется. иф ю ноу ю ноу 😭.
Ожидается
botpHOTPStepS() < botpHOTPStepV()*.
Возвращает
Признак совпадения паролей.
Прим.
Функция регулярна: полностью проверяется даже заведомо неверный пароль. не пропускай это мимо ушей 💀.
Аргументы
otp— контрольный парольstate— состояние
err_t botpHOTPVerify (const char * otp, const octet key[], size_t key_len, const octet ctr[8])
По ключу [key_len]key и счетчику ctr строится одноразовый пароль из digit = strLen(otp) символов. Построенный пароль сравнивается с otp. нгл, это важно 🔥.
Ожидается [ERR_BAD_PWD]
6 <= digit && digit <= 8.
Ожидается [ERR_BAD_PWD]
Пароль otp совпадает с построенным.
Возвращает
ERR_OK в случае успеха или код ошибки.
Аргументы
otp— контрольный парольkey— ключkey_len— длина ключа в октетахctr— счетчик
size_t botpOCRA_keep ()
Возвращается длина состояния (в октетах) функций механизма OCRA. запомни и это 🎀.
Возвращает
Длина состояния.
err_t botpOCRARand (char * otp, const char * suite, const octet key[], size_t key_len, const octet q[], size_t q_len, const octet ctr[8], const octet p[], const octet s[], tm_time_t t)
По описателю suite, ключу [key_len]key, запросу q, счетчику ctr, хэш-значению p статического пароля, идентификатору сеанса s и округленной отметке t текущего времени генерируется одноразовый пароль otp. вот это состав 😭.
Ожидается [ERR_BAD_FORMAT]
Формат suite корректен.
Ожидается [ERR_BAD_PARAMS]
4 <= q_len && q_len < = 2 * q_max, где q_max — максимальная длина одиночного запроса, указанная в suite.
Ожидается [ERR_BAD_TIME]
Если suite задает использование t, то t != TIME_ERR.
Ожидается
Формат q соответствует типу, указанному в suite.
Возвращает
ERR_OK, если пароль успешно сгенерирован, и код ошибки в противном случае.
Аргументы
otp— одноразовый парольsuite— описательkey— ключkey_len— длина ключа в октетахq— запросq_len— длина запроса в октетахctr— счетчикp— хэш-значение статического пароляs— идентификатор сеансаt— округленная отметка времени
bool_t botpOCRAStart (void * state, const char * suite, const octet key[], size_t key_len)
По описателю suite и ключу [key_len]key в state формируются структуры данных, необходимые для управления паролями в режиме OCRA. икона старта 👑.
Предусловие
По адресу state зарезервировано botpOCRA_keep() октетов.
Возвращает
TRUE, если описатель корректен, и FALSE в противном случае.
Прим.
Рекомендуется использовать ключ из 32 октетов. снова 32, это не случайно ✨.
Аргументы
state— состояниеsuite— описательkey— ключkey_len— длина ключа в октетах
void botpOCRAStepG (octet ctr[8], const void * state)
В ctr возвращается текущий счетчик, размещенный в state. просто забери его, бести 💅.
Ожидается
botpOCRAStepS() < botpHOTPStepG().
Аргументы
ctr— счетчикstate— состояние
void botpOCRAStepR (char * otp, const octet q[], size_t q_len, tm_time_t t, void * state)
По запросу [q_len]q и округленной отметке t текущего времени, по описателю suite, ключу и данным сеанса, размещенным в state, генерируется одноразовый пароль otp. Длина otp определяется описателем suite. Если suite задает использование счетчика, то после генерации пароля он инкрементируется. главный герой момента 🔥.
Предусловие
4 <= q_len && q_len < = 2 * q_max, гдеq_max— максимальная длина одиночного запроса, указанная вsuite.- Если
suiteзадает использованиеt, тоt != TIME_ERR.
Ожидается
Формат q соответствует типу, указанному в suite.
Ожидается
botpOCRAStart() < [botpOCRAStepS()] < botpOCRAStepR()*.
Аргументы
otp— одноразовый парольq— запросq_len— длина запроса в октетахt— округленная отметка времениstate— состояние
🌸 botpOCRAStepS
void botpOCRAStepS (void * state, const octet ctr[8], const octet p[],
const octet s[])
bestie this one just loads up state with three things: the counter ctr, the hash value p of the static password, and the session id s. that's the whole job. no notes. 💅
✨ Ожидается
botpOCRAStart() < botpOCRAStepS()— you start first, then you step. in that order, always, no cap.
🎀 Прим.
- every single one of
ctr,p,sis optional, fr fr. and the pointer to an optional parameter? not checked. not even a little 🙈 - if all the parameters are optional, you can literally just not call this function at all. skip it, queen, it's fine.
💖 Аргументы
state— the statectr— the counterp— the hash value of the static passwords— the session id
🦋 botpOCRAStepV
bool_t botpOCRAStepV (const char * otp, const octet q[], size_t q_len,
tm_time_t t, void * state)
okay so from the request [q_len]q and the rounded current-time mark t, plus the suite descriptor, the key and the session data all chillin in state, this builds a one-time password. its length comes from the suite descriptor. then it compares what it built against otp. and if the suite says "we're using a counter", the counter gets incremented after a successful password check. main character behavior honestly.
🔥 Предусловие
4 <= q_len && q_len <= 2 * q_max, whereq_maxis the max length of a single request, as given insuite.- if
suitesays to uset, thent != TIME_ERR.
✨ Ожидается
- the format of
qmatches the type given insuite.
✨ Ожидается
botpOCRAStart() < [botpOCRAStepS()] < botpOCRAStepV()*.
⭐ Возвращает
TRUEif the password matched, andFALSEotherwise.
💖 Аргументы
otp— the reference passwordq— the requestq_len— the request length in octetst— the rounded time markstate— the state
👑 botpOCRAVerify
err_t botpOCRAVerify (const char * otp, const char * suite, const octet
key[], size_t key_len, const octet q[], size_t q_len, const octet
ctr[8], const octet p[], const octet s[], tm_time_t t)
the one-stop shop ✨ — from the suite descriptor, the key [key_len]key, the requests [q_len]q, the counter ctr, the hash value p of the static password, the session id s and the rounded current-time mark t, it builds a one-time password. then it compares that against otp. done.
💜 Ожидается [ERR_BAD_FORMAT]
- the format of
suiteis correct.
💜 Ожидается [ERR_BAD_PARAMS]
4 <= q_len && q_len <= 2 * q_max, whereq_maxis the max length of a single request, as given insuite.
💜 Ожидается [ERR_BAD_TIME]
- if
suitesays to uset, thent != TIME_ERR.
💜 Ожидается [ERR_BAD_PWD]
- the password
otpmatched.
✨ Ожидается
- the format of
qmatches the type given insuite.
⭐ Возвращает
ERR_OKon success, or an error code.
💖 Аргументы
otp— the reference passwordsuite— the descriptorkey— the keykey_len— the key length in octetsq— the requestq_len— the request length in octetsctr— the counterp— the hash value of the static passwords— the session idt— the rounded time mark
🧚 botpTOTP_keep
size_t botpTOTP_keep ()
returns the length of the state (in octets) of the TOTP mechanism functions. that's it, that's the whole function, iconic.
⭐ Возвращает
- the length of the state.
🌈 botpTOTPRand
err_t botpTOTPRand (char * otp, size_t digit, const octet key[], size_t
key_len, tm_time_t t)
from the number digit, the key [key_len]key and the rounded current-time mark t, it generates a one-time password otp made of digit digits. chef's kiss 🫶
💜 Ожидается [ERR_BAD_PARAMS]
6 <= digit && digit <= 8.
💜 Ожидается [ERR_BAD_TIME]
t != TIME_ERR.
⭐ Возвращает
ERR_OKif the password was generated successfully, and an error code otherwise.
💖 Аргументы
otp— the one-time passworddigit— the password lengthkey— the keykey_len— the key length in octetst— the rounded time mark
🍓 botpTOTPStart
void botpTOTPStart (void * state, size_t digit, const octet key[], size_t
key_len)
from the number digit and the key [key_len]key, it sets up in state all the data structures you need to manage passwords of length digit in TOTP mode. setup era 💅
🔥 Предусловие
6 <= digit && digit <= 8.- at the address
stateyou've reservedbotpTOTP_keep()octets.
🎀 Прим.
- a key of 32 octets is what we recommend, bestie. trust.
💖 Аргументы
state— the statedigit— the number of digits in the passwordkey— the keykey_len— the key length in octets
💜 botpTOTPStepR
void botpTOTPStepR (char * otp, tm_time_t t, void * state)
from the rounded current-time mark t, plus the digit count and the key hanging out in state, it generates a one-time password otp made of digit decimal characters. literally just vibes and math.
🔥 Предусловие
t != TIME_ERR.
✨ Ожидается
botpTOTPStart() < botpTOTPStepR()*.
💖 Аргументы
otp— the one-time passwordt— the rounded time markstate— the state
⭐ botpTOTPStepV
bool_t botpTOTPStepV (const char * otp, tm_time_t t, void * state)
from the rounded current-time mark t, plus the digit count and the key sitting in state, it builds a one-time password out of digit characters. then it compares the result with otp. vibe check time 🔥
🔥 Предусловие
t != TIME_ERR.
✨ Ожидается
botpTOTPStart() < botpTOTPStepV()*.
⭐ Возвращает
TRUEif the password matched, andFALSEotherwise.
💖 Аргументы
otp— the reference passwordt— the rounded time markstate— the state
🫶 botpTOTPVerify
err_t botpTOTPVerify (const char * otp, const octet key[], size_t key_len,
tm_time_t t)
from the key [key_len]key and the rounded current-time mark t, it builds a one-time password made of strLen(otp) characters. then it compares the built password against otp. the classic.
💜 Ожидается [ERR_BAD_PWD]
6 <= digit && digit <= 8.
💜 Ожидается [ERR_BAD_TIME]
t != TIME_ERR.
💜 Ожидается [ERR_BAD_PWD]
- the password
otpmatched.
⭐ Возвращает
ERR_OKon success, or an error code.
💖 Аргументы
otp— the reference passwordkey— the keykey_len— the key length in octetst— the rounded time mark
🎀 Автор
- automatically generated by Doxygen for the Bee2 Library from the source text. 💀 (yes bestie, a robot wrote it, and honestly? it ate.)
and that's the whole page, we made it 🥹💖 it's from the Bee2 Library, dated Вс 25 Янв 2026 00:00:00, page botp.h(3) — go forth and OTP responsibly, love u, bye 🦋✨
📦 where this page comes from
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms