diff --git a/cmd/bsum/bsum.c b/cmd/bsum/bsum.c index 3a1a8366..014533a3 100644 --- a/cmd/bsum/bsum.c +++ b/cmd/bsum/bsum.c @@ -4,7 +4,7 @@ \brief Hash files using belt-hash / bash-hash \project bee2/cmd \created 2014.10.28 -\version 2024.01.22 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -182,7 +182,14 @@ static int bsumHash(octet hash[], size_t hid, const char* filename) printf("%s: FAILED [read]\n", filename); return -1; } - fclose(fp); + // закрыть файл + if (fclose(fp) != 0) + { + memWipe(buf, sizeof(buf)); + memWipe(state, sizeof(state)); + printf("%s: FAILED [close]\n", filename); + return -1; + } // возвратить хэш-значение if (hid == 0) beltHashStepG(hash, state); @@ -228,7 +235,7 @@ static int bsumCheck(size_t hid, const char* filename) size_t bad_hashes = 0; // длина хэш-значения в байтах hash_len = bsumHidHashLen(hid); - // открыть checksum_file + // открыть файл контрольных сумм fp = fopen(filename, "rb"); if (!fp) { @@ -266,7 +273,13 @@ static int bsumCheck(size_t hid, const char* filename) } printf("%s: OK\n", str + 2 * hash_len + 2); } - fclose(fp); + // закрыть файл контрольных сумм + if (fclose(fp) != 0) + { + printf("%s: FAILED [close]\n", filename); + return -1; + } + // печать предупреждений if (bad_lines) fprintf(stderr, bad_lines == 1 ? "WARNING: %lu input line (out of %lu) is improperly formatted\n" : diff --git a/cmd/cmd.h b/cmd/cmd.h index 17673a96..64a86d0a 100644 --- a/cmd/cmd.h +++ b/cmd/cmd.h @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2 \project bee2/cmd \created 2022.06.09 -\version 2023.12.17 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -338,13 +338,15 @@ cmdPwdRead(). Схема возврата [pwd_len?]pwd не используе Пароль задается в командной строке в стиле OpenSSL: - обычно после аргумента "-pass" / "-passin" / "-passout" / ...; - имеется несколько схем задания пароля; -- схема pass предлназначена для задания пароля прямо в командной строке: +- схема pass предназначена для задания пароля прямо в командной строке: "-pass pass:password"; -- схема share предлназначена для задания пароля с помощью методов +- схема env предназначена для задания пароля через переменную окружения: + "-pass env:ENV_VAR"; +- схема share предназначена для задания пароля с помощью методов разделения секрета в соответствии с правилами СТБ 34.101.78: - "-pass share:\"share_descr\""; + "-pass share:\"share_descr\"". -В последнем случае параметры share_args, которые описывают настройку разделения +В схеме share параметры share_args, которые описывают настройку разделения секрета, имеют следующий синтаксис: \code [-t] [-l] -pass .... @@ -356,8 +358,8 @@ cmdPwdRead(). Схема возврата [pwd_len?]pwd не используе - , ,... -- файлы с частичными секретами (их число должно быть не меньше порога и не больше 16). -\todo Поддержать опции "env:var", "file:pathname", "fd:number" и "stdin", -реализованные в OpenSSL +\todo Поддержать опции "file:pathname", "fd:number" и "stdin", реализованные +в OpenSSL (https://www.openssl.org/docs/manmaster/man1/openssl-passphrase-options.html). \todo Поддержать правила кодирования паролей, реализованные в OpenSSL @@ -401,13 +403,12 @@ void cmdPwdClose( /*! \brief Длина пароля */ #define cmdPwdLen strLen -/*! \brief Построение пароля +/*! \brief Генерация пароля - По инструкциям во фрагменте cmdline командной строки строится пароль pwd. - \pre При использовании некоторых опций, в частности "share", должен быть - проинициализирован штатный ГСЧ: rngIsValid() == TRUE. - \return ERR_OK, если пароль успешно построен, и код ошибки - в противном случае. + По инструкциям во фрагменте cmdline командной строки генерируется пароль pwd. + \expect{ERR_NOT_IMPLEMENTED} Используется парольная схема share. + \return ERR_OK, если пароль успешно сгенерирован, и код ошибки в противном + случае. \remark За закрытие пароля отвечает вызывающая программа. */ err_t cmdPwdGen( diff --git a/cmd/core/cmd_file.c b/cmd/core/cmd_file.c index 2fcb1ce3..4e353b16 100644 --- a/cmd/core/cmd_file.c +++ b/cmd/core/cmd_file.c @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2: file management \project bee2/cmd \created 2022.06.08 -\version 2023.06.23 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -38,8 +38,9 @@ size_t cmdFileSize(const char* file) return SIZE_MAX; } size = ftell(fp); - fclose(fp); - return (size == -1L) ? SIZE_MAX : (size_t)size; + if (fclose(fp) != 0) + size = -1; + return (size < 0) ? SIZE_MAX : (size_t)size; } /* @@ -50,39 +51,44 @@ size_t cmdFileSize(const char* file) err_t cmdFileWrite(const char* file, const void* buf, size_t count) { - err_t code; FILE* fp; // pre ASSERT(strIsValid(file)); ASSERT(memIsValid(buf, count)); // записать - code = (fp = fopen(file, "wb")) ? ERR_OK : ERR_FILE_CREATE; - ERR_CALL_CHECK(code); - code = count == fwrite(buf, 1, count, fp) ? ERR_OK : ERR_FILE_WRITE; - fclose(fp); - // завершить - return code; + if (!(fp = fopen(file, "wb"))) + return ERR_FILE_CREATE; + if (count != fwrite(buf, 1, count, fp)) + { + fclose(fp); + return ERR_FILE_WRITE; + } + if (fclose(fp) != 0) + return ERR_BAD_FILE; + return ERR_OK; } err_t cmdFileAppend(const char* file, const void* buf, size_t count) { - err_t code; FILE* fp; // pre ASSERT(strIsValid(file)); ASSERT(memIsValid(buf, count)); - // записать - code = (fp = fopen(file, "ab")) ? ERR_OK : ERR_FILE_OPEN; - ERR_CALL_CHECK(code); - code = count == fwrite(buf, 1, count, fp) ? ERR_OK : ERR_FILE_WRITE; - fclose(fp); - // завершить - return code; + // дописать + if (!(fp = fopen(file, "ab"))) + return ERR_FILE_OPEN; + if (count != fwrite(buf, 1, count, fp)) + { + fclose(fp); + return ERR_FILE_WRITE; + } + if (fclose(fp) != 0) + return ERR_BAD_FILE; + return ERR_OK; } err_t cmdFileReadAll(void* buf, size_t* count, const char* file) { - err_t code; // pre ASSERT(memIsValid(count, O_PER_S)); ASSERT(strIsValid(file)); @@ -91,21 +97,25 @@ err_t cmdFileReadAll(void* buf, size_t* count, const char* file) { FILE* fp; ASSERT(memIsValid(buf, *count)); - code = (fp = fopen(file, "rb")) ? ERR_OK : ERR_FILE_OPEN; - ERR_CALL_CHECK(code); + if (!(fp = fopen(file, "rb"))) + return ERR_FILE_OPEN; if (fread(buf, 1, *count, fp) != *count || getc(fp) != EOF) - code = ERR_FILE_READ; - fclose(fp); + { + fclose(fp); + return ERR_FILE_READ; + } + if (fclose(fp) != 0) + return ERR_BAD_FILE; } // определить длину файла else { - size_t size = cmdFileSize(file); - code = size != SIZE_MAX ? ERR_OK : ERR_FILE_READ; - ERR_CALL_CHECK(code); + size_t size; + if ((size = cmdFileSize(file)) == SIZE_MAX) + return ERR_FILE_READ; *count = size; } - return code; + return ERR_OK; } /* @@ -160,17 +170,20 @@ err_t cmdFileDup(const char* ofile, const char* ifile, size_t skip, } // дублировать все else - while (code == ERR_OK) + while (count && code == ERR_OK) { - size_t c = fread(buf, 1, buf_size, ifp); - if (c != buf_size && !feof(ifp)) + count = fread(buf, 1, buf_size, ifp); + if (count != buf_size && !feof(ifp)) code = ERR_FILE_READ; - else if (fwrite(buf, 1, c, ofp) != c) + else if (fwrite(buf, 1, count, ofp) != count) code = ERR_FILE_WRITE; } // завершить cmdBlobClose(buf); - fclose(ofp), fclose(ifp); + if (fclose(ofp) != 0) + code = (code != ERR_OK) ? code : ERR_BAD_FILE; + if (fclose(ifp) != 0) + code = (code != ERR_OK) ? code : ERR_BAD_FILE; return code; } @@ -189,8 +202,10 @@ err_t cmdFileValNotExist(int count, char* files[]) ASSERT(strIsValid(*files)); if (fp = fopen(*files, "rb")) { - fclose(fp); - printf("Some files already exist. Overwrite [y/n]?"); + if (fclose(fp) != 0) + return ERR_BAD_FILE; + if (printf("Some files already exist. Overwrite [y/n]?") < 0) + return ERR_FILE_EXISTS; do ch = cmdTermGetch(); while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n' && ch != '\n'); @@ -211,7 +226,8 @@ err_t cmdFileValExist(int count, char* files[]) ASSERT(strIsValid(*files)); if (!(fp = fopen(*files, "rb"))) return ERR_FILE_NOT_FOUND; - fclose(fp); + if (fclose(fp) != 0) + return ERR_BAD_FILE; } return ERR_OK; } diff --git a/cmd/core/cmd_privkey.c b/cmd/core/cmd_privkey.c index 20f24080..5392e830 100644 --- a/cmd/core/cmd_privkey.c +++ b/cmd/core/cmd_privkey.c @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2: managing private keys \project bee2/cmd \created 2022.06.20 -\version 2023.06.18 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -38,16 +38,12 @@ err_t cmdPrivkeyWrite(const octet privkey[], size_t privkey_len, octet* salt; octet* epki; size_t epki_len; - FILE* fp; // pre ASSERT(privkey_len == 24 || privkey_len == 32 || privkey_len == 48 || privkey_len == 64); ASSERT(memIsValid(privkey, privkey_len)); ASSERT(strIsValid(file)); ASSERT(cmdPwdIsValid(pwd)); - // входной контроль - if (!rngIsValid()) - return ERR_BAD_RNG; // определить длину контейнера code = bpkiPrivkeyWrap(0, &epki_len, 0, privkey_len, 0, 0, 0, iter); ERR_CALL_CHECK(code); @@ -56,18 +52,16 @@ err_t cmdPrivkeyWrite(const octet privkey[], size_t privkey_len, ERR_CALL_CHECK(code); salt = (octet*)stack; epki = salt + 8; + // запустить ГСЧ + code = cmdRngStart(TRUE); + ERR_CALL_HANDLE(code, cmdBlobClose(stack)); // установить защиту rngStepR(salt, 8, 0); code = bpkiPrivkeyWrap(epki, 0, privkey, privkey_len, (const octet*)pwd, cmdPwdLen(pwd), salt, iter); ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - // открыть файл для записи - fp = fopen(file, "wb"); - code = fp ? ERR_OK : ERR_FILE_CREATE; - ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - // записать - code = fwrite(epki, 1, epki_len, fp) == epki_len ? ERR_OK : ERR_FILE_WRITE; - fclose(fp); + // записать в файл + code = cmdFileWrite(file, epki, epki_len); // завершить cmdBlobClose(stack); return code; @@ -89,7 +83,6 @@ err_t cmdPrivkeyRead(octet privkey[], size_t* privkey_len, const char* file, size_t epki_len_max; void* stack; octet* epki; - FILE* fp; // pre ASSERT(memIsNullOrValid(privkey_len, sizeof(size_t))); ASSERT(!privkey_len || *privkey_len == 0 || *privkey_len == 24 || @@ -135,14 +128,16 @@ err_t cmdPrivkeyRead(octet privkey[], size_t* privkey_len, const char* file, code = cmdBlobCreate(stack, epki_len_max + 1); ERR_CALL_CHECK(code); epki = (octet*)stack; - // прочитать контейнер - code = (fp = fopen(file, "rb")) ? ERR_OK : ERR_FILE_OPEN; + // определить длину контейнера + code = cmdFileReadAll(0, &epki_len, file); ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - epki_len = fread(epki, 1, epki_len_max + 1, fp); - fclose(fp); + // проверить длину code = (epki_len_min <= epki_len && epki_len <= epki_len_max) ? ERR_OK : ERR_BAD_FORMAT; ERR_CALL_HANDLE(code, cmdBlobClose(stack)); + // читать + code = cmdFileReadAll(epki, &epki_len, file); + ERR_CALL_HANDLE(code, cmdBlobClose(stack)); // снять защиту code = bpkiPrivkeyUnwrap(privkey, &epki_len_min, epki, epki_len, (const octet*)pwd, cmdPwdLen(pwd)); diff --git a/cmd/core/cmd_pwd.c b/cmd/core/cmd_pwd.c index d634fef9..4e48d56c 100644 --- a/cmd/core/cmd_pwd.c +++ b/cmd/core/cmd_pwd.c @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2: password management \project bee2/cmd \created 2022.06.13 -\version 2023.06.05 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -24,6 +24,7 @@ #include #include #include +#include /* ******************************************************************************* @@ -115,16 +116,53 @@ err_t pwdSelfTest() static err_t cmdPwdGenPass(cmd_pwd_t* pwd, const char* cmdline) { - ASSERT(memIsValid(pwd, sizeof(blob_t*))); + return ERR_NOT_IMPLEMENTED; +} + +static err_t cmdPwdReadPass(cmd_pwd_t* pwd, const char* cmdline) +{ + ASSERT(memIsValid(pwd, sizeof(cmd_pwd_t))); ASSERT(strIsValid(cmdline)); // создать пароль - if (!(*pwd = blobCreate(strLen(cmdline) + 1))) + if (!(*pwd = cmdPwdCreate(strLen(cmdline)))) return ERR_OUTOFMEMORY; strCopy(*pwd, cmdline); return ERR_OK; } -#define cmdPwdReadPass cmdPwdGenPass +/* +******************************************************************************* +Управление паролями: схема env +******************************************************************************* +*/ + +static const char* cmdEnvGet(const char* name) +{ + const char* val; + val = getenv(name); + return strIsValid(val) ? val : 0; +} + +static err_t cmdPwdGenEnv(cmd_pwd_t* pwd, const char* cmdline) +{ + return ERR_NOT_IMPLEMENTED; +} + +static err_t cmdPwdReadEnv(cmd_pwd_t* pwd, const char* cmdline) +{ + const char* val; + // pre + ASSERT(memIsValid(pwd, sizeof(cmd_pwd_t))); + ASSERT(strIsValid(cmdline)); + // читать пароль из переменной окружения + if (!(val = cmdEnvGet(cmdline))) + return ERR_BAD_ENV; + // возвратить пароль + if (!(*pwd = cmdPwdCreate(strLen(val)))) + return ERR_OUTOFMEMORY; + strCopy(*pwd, val); + return ERR_OK; +} /* ******************************************************************************* @@ -154,15 +192,15 @@ static err_t cmdPwdGenShare_internal(cmd_pwd_t* pwd, size_t scount, ASSERT(!crc || len != 16); // пароль пока не создан *pwd = 0; - // входной контроль - if (!rngIsValid()) - return ERR_BAD_RNG; // определить длину пароля if (len == 0) len = 32; // определить длину контейнера с частичным секретом code = bpkiShareWrap(0, &epki_len, 0, len + 1, 0, 0, 0, iter); ERR_CALL_CHECK(code); + // запустить ГСЧ + code = cmdRngStart(TRUE); + ERR_CALL_CHECK(code); // выделить память и разметить ее code = cmdBlobCreate(stack, len + utilMax(2, @@ -173,7 +211,7 @@ static err_t cmdPwdGenShare_internal(cmd_pwd_t* pwd, size_t scount, state = share = pwd_bin + len; salt = share + scount * (len + 1); epki = salt + 8; - // сгенерировать пароль + // генерировать пароль if (crc) { rngStepR(pwd_bin, len - 8, 0); @@ -191,21 +229,13 @@ static err_t cmdPwdGenShare_internal(cmd_pwd_t* pwd, size_t scount, // защитить частичные секреты for (; scount--; share += (len + 1), ++shares) { - FILE* fp; // установить защиту rngStepR(salt, 8, 0); code = bpkiShareWrap(epki, 0, share, len + 1, (const octet*)spwd, cmdPwdLen(spwd), salt, iter); ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - // открыть файл для записи - ASSERT(strIsValid(*shares)); - fp = fopen(*shares, "wb"); - code = fp ? ERR_OK : ERR_FILE_CREATE; - ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - // записать - code = fwrite(epki, 1, epki_len, fp) == epki_len ? - ERR_OK : ERR_FILE_WRITE; - fclose(fp); + // записать в файл + code = cmdFileWrite(*shares, epki, epki_len); ERR_CALL_HANDLE(code, cmdBlobClose(stack)); } // создать выходной (текстовый) пароль @@ -274,18 +304,17 @@ static err_t cmdPwdReadShare_internal(cmd_pwd_t* pwd, size_t scount, // прочитать частичные секреты for (pos = 0; pos < scount; ++pos, ++shares) { - FILE* fp; size_t share_len; - // открыть файл для чтения - ASSERT(strIsValid(*shares)); - code = (fp = fopen(*shares, "rb")) ? ERR_OK : ERR_FILE_OPEN; + // определить длину контейнера + code = cmdFileReadAll(0, &epki_len, *shares); ERR_CALL_HANDLE(code, cmdBlobClose(stack)); - // читать - epki_len = fread(epki, 1, epki_len_max + 1, fp); - fclose(fp); + // проверить длину code = (epki_len_min <= epki_len && epki_len <= epki_len_max) ? ERR_OK : ERR_BAD_FORMAT; ERR_CALL_HANDLE(code, cmdBlobClose(stack)); + // читать + code = cmdFileReadAll(epki, &epki_len, *shares); + ERR_CALL_HANDLE(code, cmdBlobClose(stack)); // декодировать code = bpkiShareUnwrap(share + pos * (len + 1), &share_len, epki, epki_len, (const octet*)spwd, cmdPwdLen(spwd)); @@ -562,6 +591,8 @@ err_t cmdPwdGen(cmd_pwd_t* pwd, const char* cmdline) { if (strStartsWith(cmdline, "pass:")) return cmdPwdGenPass(pwd, cmdline + strLen("pass:")); + else if (strStartsWith(cmdline, "env:")) + return cmdPwdGenEnv(pwd, cmdline + strLen("env:")); else if (strStartsWith(cmdline, "share:")) return cmdPwdGenShare(pwd, cmdline + strLen("share:")); return ERR_CMD_PARAMS; @@ -571,6 +602,8 @@ err_t cmdPwdRead(cmd_pwd_t* pwd, const char* cmdline) { if (strStartsWith(cmdline, "pass:")) return cmdPwdReadPass(pwd, cmdline + strLen("pass:")); + else if (strStartsWith(cmdline, "env:")) + return cmdPwdReadEnv(pwd, cmdline + strLen("env:")); else if (strStartsWith(cmdline, "share:")) return cmdPwdReadShare(pwd, cmdline + strLen("share:")); return ERR_CMD_PARAMS; diff --git a/cmd/core/cmd_rng.c b/cmd/core/cmd_rng.c index aae2cf43..38250568 100644 --- a/cmd/core/cmd_rng.c +++ b/cmd/core/cmd_rng.c @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2: random number generation \project bee2/cmd \created 2022.06.08 -\version 2023.12.16 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -140,6 +140,10 @@ static err_t prngEchoRead(size_t* read, void* buf, size_t count, void* state) err_t cmdRngStart(bool_t verbose) { err_t code; + // ГСЧ уже запущен? + if (rngIsValid()) + return ERR_OK; + // печать информации об источниках if (verbose) { const char* sources[] = { "trng", "trng2", "sys", "sys2", "timer" }; @@ -152,9 +156,11 @@ err_t cmdRngStart(bool_t verbose) printf(count++ ? ", %s" : "%s", sources[pos]); printf("]... "); } + // энтропии достаточно? code = rngESHealth(); if (code == ERR_OK) code = rngCreate(0, 0); + // нет, подключить клавиатурный источник else if (code == ERR_NOT_ENOUGH_ENTROPY) { void* stack; diff --git a/cmd/core/cmd_sig.c b/cmd/core/cmd_sig.c index 62c7802f..20e620f0 100644 --- a/cmd/core/cmd_sig.c +++ b/cmd/core/cmd_sig.c @@ -4,7 +4,7 @@ \brief Command-line interface to Bee2: signing files \project bee2/cmd \created 2022.08.20 -\version 2024.05.22 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -235,7 +235,8 @@ err_t cmdSigRead(cmd_sig_t* sig, size_t* sig_len, const char* sig_file) ERR_OK : ERR_FILE_READ; ERR_CALL_HANDLE(code, (cmdBlobClose(der), fclose(fp))); code = fread(der, 1, count, fp) == count ? ERR_OK : ERR_FILE_READ; - fclose(fp); + ERR_CALL_HANDLE(code, (cmdBlobClose(der), fclose(fp))); + code = (fclose(fp) == 0) ? ERR_OK : ERR_BAD_FILE; ERR_CALL_HANDLE(code, cmdBlobClose(der)); // декодировать memRev(der, count); @@ -309,7 +310,8 @@ static err_t cmdSigHash(octet hash[], size_t hash_len, const char* file, else bashHashStepH(stack, count, state); } - fclose(fp); + code = (fclose(fp) == 0) ? ERR_OK : ERR_BAD_FILE; + ERR_CALL_HANDLE(code, cmdBlobClose(stack)); // хэшировать сертификаты и дату if (hash_len <= 32) { diff --git a/cmd/csr/csr.c b/cmd/csr/csr.c index ce183fd5..c32ba771 100644 --- a/cmd/csr/csr.c +++ b/cmd/csr/csr.c @@ -4,7 +4,7 @@ \brief Manage certificate signing requests \project bee2/cmd \created 2023.12.19 -\version 2024.01.22 +\version 2024.06.13 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -145,7 +145,7 @@ static err_t csrRewrap(int argc, char* argv[]) ++argv, --argc; if (!argc) { - code = ERR_BAD_PARAMS; + code = ERR_CMD_PARAMS; break; } code = cmdPwdRead(&pwd, *argv); diff --git a/cmd/es/es.c b/cmd/es/es.c index 8f8ea080..527f6ade 100644 --- a/cmd/es/es.c +++ b/cmd/es/es.c @@ -4,7 +4,7 @@ \brief Dealing with entropy sources \project bee2/cmd \created 2021.04.20 -\version 2023.12.16 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -205,7 +205,8 @@ static err_t esRead(int argc, char *argv[]) count -= read; } // завершение - fclose(fp); + if (fclose(fp) != 0) + return ERR_BAD_FILE; return ERR_OK; } diff --git a/cmd/kg/kg.c b/cmd/kg/kg.c index 498b5f9a..2b1c4a47 100644 --- a/cmd/kg/kg.c +++ b/cmd/kg/kg.c @@ -4,7 +4,7 @@ \brief Generate and manage private keys \project bee2/cmd \created 2022.06.08 -\version 2023.12.19 +\version 2024.06.13 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -354,9 +354,6 @@ static err_t kgChp(int argc, char* argv[]) code = cmdPrivkeyRead(privkey, &len, argv[0], pwdin); cmdPwdClose(pwdin); ERR_CALL_HANDLE(code, (cmdBlobClose(privkey), cmdPwdClose(pwdout))); - // запустить ГСЧ - code = cmdRngStart(TRUE); - ERR_CALL_HANDLE(code, (cmdBlobClose(privkey), cmdPwdClose(pwdout))); // сохранить личный ключ code = cmdPrivkeyWrite(privkey, len, argv[0], pwdout); cmdBlobClose(privkey); @@ -461,7 +458,7 @@ static err_t kgExtr(int argc, char* argv[]) ++argv, --argc; if (!argc) { - code = ERR_BAD_PARAMS; + code = ERR_CMD_PARAMS; break; } code = cmdPwdRead(&pwd, *argv); @@ -544,7 +541,7 @@ static err_t kgPrint(int argc, char* argv[]) ++argv, --argc; if (!argc) { - code = ERR_BAD_PARAMS; + code = ERR_CMD_PARAMS; break; } code = cmdPwdRead(&pwd, *argv); diff --git a/cmd/pwd/pwd.c b/cmd/pwd/pwd.c index 0d6098b9..f4d134f3 100644 --- a/cmd/pwd/pwd.c +++ b/cmd/pwd/pwd.c @@ -4,7 +4,7 @@ \brief Generate and manage passwords \project bee2/cmd \created 2022.06.23 -\version 2023.12.17 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -64,6 +64,7 @@ static int pwdUsage() " print a password built by \n" " schemas:\n" " pass: -- direct password\n" + " env: -- password in environment variable \n" " share:\"[options] ...\" -- shared password\n" " options:\n" " -t --- threshold (2 <= <= 16, 2 by default)\n" @@ -149,13 +150,10 @@ static err_t pwdGen(int argc, char* argv[]) cmd_pwd_t pwd = 0; // верное число параметров? if (argc != 1) - return ERR_BAD_PARAMS; + return ERR_CMD_PARAMS; // самотестирование code = pwdSelfTest(); ERR_CALL_CHECK(code); - // запустить ГСЧ - code = cmdRngStart(TRUE); - ERR_CALL_CHECK(code); // генерировать пароль code = cmdPwdGen(&pwd, *argv); cmdPwdClose(pwd); @@ -176,7 +174,7 @@ static err_t pwdVal(int argc, char* argv[]) cmd_pwd_t pwd = 0; // верное число параметров? if (argc != 1) - return ERR_BAD_PARAMS; + return ERR_CMD_PARAMS; // самотестирование code = pwdSelfTest(); ERR_CALL_CHECK(code); @@ -200,7 +198,7 @@ static err_t pwdPrint(int argc, char* argv[]) cmd_pwd_t pwd = 0; // верное число параметров? if (argc != 1) - return ERR_BAD_PARAMS; + return ERR_CMD_PARAMS; // определить пароль code = cmdPwdRead(&pwd, *argv); ERR_CALL_CHECK(code); diff --git a/cmd/test/test.cmd b/cmd/test/test.cmd index 63ab4a6c..df750367 100644 --- a/cmd/test/test.cmd +++ b/cmd/test/test.cmd @@ -3,7 +3,7 @@ rem =========================================================================== rem \brief Testing command-line interface rem \project bee2evp/cmd rem \created 2022.06.24 -rem \version 2024.01.22 +rem \version 2024.06.14 rem \pre The working directory contains zed.csr. rem =========================================================================== @@ -85,11 +85,35 @@ echo ****** Testing bee2cmd/pwd... del /q s1 s2 s3 s4 s5 2> nul bee2cmd pwd gen pass:zed +if %ERRORLEVEL% equ 0 goto Error + +bee2cmd pwd val pass:zed +if %ERRORLEVEL% neq 0 goto Error + +bee2cmd pwd val pass:"zed" if %ERRORLEVEL% neq 0 goto Error -bee2cmd pwd gen pass:"zed" +for /f %%i in ('bee2cmd pwd print pass:zed') do ( + if "%%i" neq "zed" goto Error +) + +bee2cmd pwd gen env:BEE2_CMD_TEST +if %ERRORLEVEL% equ 0 goto Error + +set BEE2_CMD_TEST= + +bee2cmd pwd val env:BEE2_CMD_TEST +if %ERRORLEVEL% equ 0 goto Error + +set BEE2_CMD_TEST=zed + +bee2cmd pwd val env:BEE2_CMD_TEST if %ERRORLEVEL% neq 0 goto Error +for /f %%i in ('bee2cmd pwd print env:BEE2_CMD_TEST') do ( + if "%%i" neq "zed" goto Error +) + bee2cmd pwd gen share:"-t2 -t3 -pass pass:zed s1 s2" if %ERRORLEVEL% equ 0 goto Error diff --git a/cmd/test/test.sh b/cmd/test/test.sh index 6d806235..5b018559 100755 --- a/cmd/test/test.sh +++ b/cmd/test/test.sh @@ -3,7 +3,7 @@ # \brief Testing command-line interface # \project bee2evp/cmd # \created 2022.06.24 -# \version 2024.01.22 +# \version 2024.06.14 # \pre The working directory contains zed.csr. # ============================================================================= @@ -70,10 +70,31 @@ test_bsum() { test_pwd() { rm -rf s1 s2 s3 s4 s5 ss1 ss2 ss3 \ || return 2 + # pass $bee2cmd pwd gen pass:zed \ + && return 1 + $bee2cmd pwd val pass:zed \ + || return 1 + $bee2cmd pwd val pass:"zed" \ || return 1 - $bee2cmd pwd gen pass:"zed" \ + if [ $($bee2cmd pwd print pass:zed) != "zed" ]; then + return 1 + fi + # env + $bee2cmd pwd gen env:BEE2_CMD_TEST \ + && return 1 + unset BEE2_CMD_TEST \ + || return 2 + $bee2cmd pwd val env:BEE2_CMD_TEST \ + && return 1 + export BEE2_CMD_TEST=zed \ + || return 2 + $bee2cmd pwd val env:BEE2_CMD_TEST \ || return 1 + if [ $($bee2cmd pwd print env:BEE2_CMD_TEST) != "zed" ]; then + return 1 + fi + # share $bee2cmd pwd gen share:"-t2 -t3 -pass pass:zed s1 s2" \ && return 1 $bee2cmd pwd gen share:"-t3 -pass pass:zed s1 s2" \ @@ -328,7 +349,7 @@ test_sig(){ || return 1 $bee2cmd sig extr -body ff body \ || return 1 - if [[ $(< body) != "test" ]]; then + if [ $(< body) != "test" ]; then return 1 fi $bee2cmd sig extr -sig ff sig \ diff --git a/include/bee2/core/err.h b/include/bee2/core/err.h index 27194d0c..45a24cb7 100644 --- a/include/bee2/core/err.h +++ b/include/bee2/core/err.h @@ -4,7 +4,7 @@ \brief Errors \project bee2 [cryptographic library] \created 2012.07.09 -\version 2023.09.25 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -60,36 +60,38 @@ Sys #define ERR_BAD_FILE _ERR_REG(103) /* некорректный таймер */ #define ERR_BAD_TIMER _ERR_REG(104) +/* некорректная переменная окружения */ +#define ERR_BAD_ENV _ERR_REG(105) /* некорректная функция */ -#define ERR_BAD_FUNCTION _ERR_REG(105) +#define ERR_BAD_FUNCTION _ERR_REG(106) /* некорректная команда */ -#define ERR_BAD_COMMAND _ERR_REG(106) +#define ERR_BAD_COMMAND _ERR_REG(107) /* некорректная длина */ -#define ERR_BAD_LENGTH _ERR_REG(107) +#define ERR_BAD_LENGTH _ERR_REG(108) /* некорректные входные данные */ -#define ERR_BAD_INPUT _ERR_REG(108) +#define ERR_BAD_INPUT _ERR_REG(109) /* не хватает памяти */ -#define ERR_OUTOFMEMORY _ERR_REG(109) +#define ERR_OUTOFMEMORY _ERR_REG(110) /* переполнение */ -#define ERR_OVERFLOW _ERR_REG(110) +#define ERR_OVERFLOW _ERR_REG(111) /* объект не найден */ -#define ERR_NOT_FOUND _ERR_REG(111) +#define ERR_NOT_FOUND _ERR_REG(112) /* объект уже существует */ -#define ERR_ALREADY_EXISTS _ERR_REG(112) +#define ERR_ALREADY_EXISTS _ERR_REG(113) /* доступ запрещен */ -#define ERR_ACCESS_DENIED _ERR_REG(113) +#define ERR_ACCESS_DENIED _ERR_REG(114) /* устройство не готово */ -#define ERR_NOT_READY _ERR_REG(114) +#define ERR_NOT_READY _ERR_REG(115) /* запрашиваемый ресурс занят */ -#define ERR_BUSY _ERR_REG(115) +#define ERR_BUSY _ERR_REG(116) /* таймаут */ -#define ERR_TIMEOUT _ERR_REG(116) +#define ERR_TIMEOUT _ERR_REG(117) /* без результата */ -#define ERR_NO_RESULT _ERR_REG(117) +#define ERR_NO_RESULT _ERR_REG(118) /* не реализовано */ -#define ERR_NOT_IMPLEMENTED _ERR_REG(118) +#define ERR_NOT_IMPLEMENTED _ERR_REG(119) /* последствия предыдущих ошибок */ -#define ERR_AFTER _ERR_REG(119) +#define ERR_AFTER _ERR_REG(120) /* ******************************************************************************* @@ -99,7 +101,7 @@ File /* ошибка при создании файла */ #define ERR_FILE_CREATE _ERR_REG(201) -/* ошибка при создании файла */ +/* файл не найден */ #define ERR_FILE_NOT_FOUND _ERR_REG(202) /* ошибка при открытии файла */ #define ERR_FILE_OPEN _ERR_REG(203) @@ -228,7 +230,6 @@ Cmd /* повтор параметров команды */ #define ERR_CMD_DUPLICATE _ERR_REG(604) - /* ******************************************************************************* Обработка ошибок diff --git a/src/core/err.c b/src/core/err.c index 3e143ae3..41593c27 100644 --- a/src/core/err.c +++ b/src/core/err.c @@ -4,7 +4,7 @@ \brief Errors \project bee2 [cryptographic library] \created 2012.07.09 -\version 2023.09.25 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -31,6 +31,7 @@ static const err_msg _messages[] = { {ERR_BAD_UNIT, "Invalid device"}, {ERR_BAD_FILE, "Invalid file"}, {ERR_BAD_TIMER, "Invalid timer"}, + {ERR_BAD_ENV, "Invalid environment variable"}, {ERR_BAD_FUNCTION, "Invalid function"}, {ERR_BAD_COMMAND, "Invalid command"}, {ERR_BAD_LENGTH, "Invalid length"}, diff --git a/src/core/rng.c b/src/core/rng.c index b5ce52ff..012f5ed9 100644 --- a/src/core/rng.c +++ b/src/core/rng.c @@ -4,7 +4,7 @@ \brief Entropy sources and random number generators \project bee2 [cryptographic library] \created 2014.10.13 -\version 2023.12.19 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -630,7 +630,7 @@ err_t rngESHealth() const char* sources[] = { "sys", "sys2", "timer" }; size_t valid_sources = 0; size_t pos; - // есть физический источник? + // есть работоспособный физический источник? if (rngESHealth2() == ERR_OK) return ERR_OK; // проверить остальные источники @@ -638,11 +638,10 @@ err_t rngESHealth() { if (rngESTest(sources[pos]) != ERR_OK) continue; - valid_sources++; + // два работоспособных источника? + if (++valid_sources == 2) + return ERR_OK; } - // не менее двух работоспосбных источников? - if (valid_sources >= 2) - return ERR_OK; // только один? if (valid_sources == 1) return ERR_NOT_ENOUGH_ENTROPY; diff --git a/src/core/str.c b/src/core/str.c index 0d2af3f2..1b709c52 100644 --- a/src/core/str.c +++ b/src/core/str.c @@ -4,7 +4,7 @@ \brief Strings \project bee2 [cryptographic library] \created 2013.02.04 -\version 2023.09.18 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -19,6 +19,10 @@ Характеристики / проверка \warning В strLen() нельзя вызывать strIsValid() -- будет рекурсия. + +\remark Комментарий перед функцией strIsValid() -- это декларация для +Coverity Scan о том, что функция является санитайзером строк +(https://community.synopsys.com/s/article/From-Case-Clearing-TAINTED-STRING). ******************************************************************************* */ @@ -33,6 +37,7 @@ size_t strLen2(const char* str, size_t count) return str ? strnlen(str, count) : SIZE_0; } +// coverity[ +tainted_string_sanitize_content : arg-0 ] bool_t strIsValid(const char* str) { return memIsValid(str, strLen(str) + (str ? 1 : 0)); diff --git a/src/math/pri.c b/src/math/pri.c index 372e4449..47288411 100644 --- a/src/math/pri.c +++ b/src/math/pri.c @@ -4,7 +4,7 @@ \brief Prime numbers \project bee2 [cryptographic library] \created 2012.08.13 -\version 2024.02.28 +\version 2024.06.14 \copyright The Bee2 authors \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt). ******************************************************************************* @@ -426,7 +426,6 @@ bool_t priIsSieved(const word a[], size_t n, size_t base_count, void* stack) --base_count; // раскладка stack mods = (word*)stack; - stack = mods + base_count; // найти остатки priBaseMod(mods, a, n, base_count); // есть нулевые остатки? @@ -448,7 +447,6 @@ bool_t priIsSmooth(const word a[], size_t n, size_t base_count, void* stack) register word mod; // переменные в stack word* t = (word*)stack; - stack = t + n; // pre ASSERT(base_count <= priBaseSize()); // t <- a