2003-10-08 12:51:07 +00:00
|
|
|
/*
|
2024-01-12 17:03:59 -05:00
|
|
|
* Copyright (C) 2013-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
|
2019-01-25 10:15:50 -05:00
|
|
|
* Copyright (C) 2007-2013 Sourcefire, Inc.
|
2003-10-08 12:51:07 +00:00
|
|
|
*
|
2008-04-02 15:24:51 +00:00
|
|
|
* Authors: Tomasz Kojm
|
2020-01-03 15:44:07 -05:00
|
|
|
*
|
|
|
|
* Acknowledgements: The idea of number encoding comes from yyyRSA by
|
2018-03-05 16:34:35 -05:00
|
|
|
* Erik Thiele.
|
2003-10-08 12:51:07 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
2007-03-31 20:31:04 +00:00
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
2003-10-08 12:51:07 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2006-04-09 19:59:28 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301, USA.
|
2003-10-08 12:51:07 +00:00
|
|
|
*/
|
|
|
|
|
2004-02-06 13:46:08 +00:00
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
#include "clamav-config.h"
|
|
|
|
#endif
|
|
|
|
|
2003-10-08 12:51:07 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
2023-02-18 10:47:53 +01:00
|
|
|
#include <openssl/bn.h>
|
2003-10-08 12:51:07 +00:00
|
|
|
|
|
|
|
#include "clamav.h"
|
|
|
|
#include "others.h"
|
2004-03-19 14:57:03 +00:00
|
|
|
#include "dsig.h"
|
2004-07-19 17:54:40 +00:00
|
|
|
#include "str.h"
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2021-12-02 15:07:48 -08:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#else
|
|
|
|
#include "w32_stat.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
#include <termios.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2006-10-14 21:12:04 +00:00
|
|
|
#define CLI_NSTR "118640995551645342603070001658453189751527774412027743746599405743243142607464144767361060640655844749760788890022283424922762488917565551002467771109669598189410434699034532232228621591089508178591428456220796841621637175567590476666928698770143328137383952820383197532047771780196576957695822641224262693037"
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2006-10-14 21:12:04 +00:00
|
|
|
#define CLI_ESTR "100001027"
|
|
|
|
|
2022-01-24 21:03:20 -08:00
|
|
|
#define MP_GET(a) ((a)->used > 0 ? (a)->dp[0] : 0)
|
|
|
|
|
2010-01-15 16:26:39 +01:00
|
|
|
static char cli_ndecode(unsigned char value)
|
2003-10-08 12:51:07 +00:00
|
|
|
{
|
2018-12-03 12:40:13 -05:00
|
|
|
unsigned int i;
|
|
|
|
char ncodec[] = {
|
|
|
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
|
|
|
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
|
|
|
'y', 'z',
|
|
|
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
|
|
|
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
|
|
|
'Y', 'Z',
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
|
|
'+', '/'};
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
if (ncodec[i] == value)
|
|
|
|
return i;
|
2003-10-08 12:51:07 +00:00
|
|
|
|
|
|
|
cli_errmsg("cli_ndecode: value out of range\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
static unsigned char *cli_decodesig(const char *sig, unsigned int plen, BIGNUM *e, BIGNUM *n)
|
2003-10-08 12:51:07 +00:00
|
|
|
{
|
2018-12-03 12:40:13 -05:00
|
|
|
int i, slen = strlen(sig), dec;
|
2023-02-18 10:47:53 +01:00
|
|
|
unsigned char *plain = NULL, *ret_sig = NULL;
|
|
|
|
BIGNUM *r = NULL, *p = NULL, *c = NULL;
|
2023-04-07 09:30:05 -07:00
|
|
|
BN_CTX *bn_ctx = NULL;
|
2023-02-18 10:47:53 +01:00
|
|
|
unsigned int bn_bytes;
|
|
|
|
;
|
|
|
|
|
|
|
|
r = BN_new();
|
|
|
|
if (!r) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = BN_new();
|
|
|
|
if (!p) {
|
|
|
|
goto done;
|
|
|
|
}
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
c = BN_new();
|
|
|
|
if (!c) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
|
|
if (!bn_ctx) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
BN_zero(c);
|
2018-12-03 12:40:13 -05:00
|
|
|
for (i = 0; i < slen; i++) {
|
|
|
|
if ((dec = cli_ndecode(sig[i])) < 0) {
|
2023-02-18 10:47:53 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (!BN_set_word(r, dec)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (!BN_lshift(r, r, 6 * i)) {
|
|
|
|
goto done;
|
2018-12-03 12:40:13 -05:00
|
|
|
}
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
if (!BN_add(c, c, r)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!BN_mod_exp(p, c, e, n, bn_ctx)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
bn_bytes = BN_num_bytes(p);
|
|
|
|
/* Sometimes the size of the resulting BN (128) is larger than the expected
|
|
|
|
* length (16). The result does not match in this case. Instead of
|
|
|
|
* allocating memory and filling it, we fail early.
|
|
|
|
*/
|
|
|
|
if (plen < bn_bytes) {
|
|
|
|
cli_errmsg("cli_decodesig: Resulting signature too large (%d vs %d).\n",
|
|
|
|
bn_bytes, plen);
|
|
|
|
goto done;
|
|
|
|
}
|
Remove max-allocation limits where not required
The cli_max_malloc, cli_max_calloc, and cli_max_realloc functions
provide a way to protect against allocating too much memory
when the size of the allocation is derived from the untrusted input.
Specifically, we worry about values in the file being scanned being
manipulated to exhaust the RAM and crash the application.
There is no need to check the limits if the size of the allocation
is fixed, or if the size of the allocation is necessary for signature
loading, or the general operation of the applications.
E.g. checking the max-allocation limit for the size of a hash, or
for the size of the scan recursion stack, is a complete waste of
time.
Although we significantly increased the max-allocation limit in
a recent release, it is best not to check an allocation if the
allocation will be safe. It would be a waste of time.
I am also hopeful that if we can reduce the number allocations
that require a limit-check to those that require it for the safe
scan of a file, then eventually we can store the limit in the scan-
context, and make it configurable.
2024-01-08 22:48:28 -05:00
|
|
|
plain = calloc(plen, sizeof(unsigned char));
|
2018-12-03 12:40:13 -05:00
|
|
|
if (!plain) {
|
|
|
|
cli_errmsg("cli_decodesig: Can't allocate memory for 'plain'\n");
|
2023-02-18 10:47:53 +01:00
|
|
|
goto done;
|
2006-06-17 21:00:44 +00:00
|
|
|
}
|
2023-02-18 10:47:53 +01:00
|
|
|
if (!BN_bn2bin(p, plain)) {
|
|
|
|
goto done;
|
2003-10-08 12:51:07 +00:00
|
|
|
}
|
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
ret_sig = plain;
|
|
|
|
plain = NULL;
|
|
|
|
|
|
|
|
done:
|
|
|
|
BN_free(r);
|
|
|
|
BN_free(p);
|
|
|
|
BN_free(c);
|
|
|
|
BN_CTX_free(bn_ctx);
|
|
|
|
free(plain);
|
|
|
|
return ret_sig;
|
2006-10-14 21:12:04 +00:00
|
|
|
}
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2022-03-24 16:11:50 -07:00
|
|
|
char *cli_getdsig(const char *host, const char *user, const unsigned char *data, unsigned int datalen, unsigned short mode)
|
2021-12-02 15:07:48 -08:00
|
|
|
{
|
2022-03-02 02:34:05 +03:00
|
|
|
char buff[512], cmd[128], pass[31], *pt;
|
2021-12-02 15:07:48 -08:00
|
|
|
struct sockaddr_in server;
|
|
|
|
int sockd, bread, len;
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
struct termios old, new;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
memset(&server, 0x00, sizeof(struct sockaddr_in));
|
|
|
|
|
|
|
|
if ((pt = getenv("SIGNDPASS"))) {
|
|
|
|
strncpy(pass, pt, sizeof(pass));
|
|
|
|
pass[sizeof(pass) - 1] = '\0';
|
|
|
|
} else {
|
|
|
|
cli_infomsg(NULL, "Password: ");
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
if (tcgetattr(0, &old)) {
|
|
|
|
cli_errmsg("getdsig: tcgetattr() failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
new = old;
|
|
|
|
new.c_lflag &= ~ECHO;
|
|
|
|
if (tcsetattr(0, TCSAFLUSH, &new)) {
|
|
|
|
cli_errmsg("getdsig: tcsetattr() failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (scanf("%30s", pass) == EOF) {
|
|
|
|
cli_errmsg("getdsig: Can't get password\n");
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
tcsetattr(0, TCSAFLUSH, &old);
|
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
if (tcsetattr(0, TCSAFLUSH, &old)) {
|
|
|
|
cli_errmsg("getdsig: tcsetattr() failed\n");
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
cli_infomsg(NULL, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
|
|
perror("socket()");
|
|
|
|
cli_errmsg("getdsig: Can't create socket\n");
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
server.sin_family = AF_INET;
|
|
|
|
server.sin_addr.s_addr = inet_addr(host);
|
|
|
|
server.sin_port = htons(33101);
|
|
|
|
|
|
|
|
if (connect(sockd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
|
|
|
|
perror("connect()");
|
|
|
|
closesocket(sockd);
|
|
|
|
cli_errmsg("getdsig: Can't connect to ClamAV Signing Service at %s\n", host);
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memset(cmd, 0, sizeof(cmd));
|
|
|
|
|
|
|
|
if (mode == 1)
|
|
|
|
snprintf(cmd, sizeof(cmd) - datalen, "ClamSign:%s:%s:", user, pass);
|
|
|
|
else if (mode == 2)
|
|
|
|
snprintf(cmd, sizeof(cmd) - datalen, "ClamSignPSS:%s:%s:", user, pass);
|
|
|
|
else
|
|
|
|
snprintf(cmd, sizeof(cmd) - datalen, "ClamSignPSS2:%s:%s:", user, pass);
|
|
|
|
|
|
|
|
len = strlen(cmd);
|
|
|
|
pt = cmd + len;
|
|
|
|
memcpy(pt, data, datalen);
|
|
|
|
len += datalen;
|
|
|
|
|
|
|
|
if (send(sockd, cmd, len, 0) < 0) {
|
|
|
|
cli_errmsg("getdsig: Can't write to socket\n");
|
|
|
|
closesocket(sockd);
|
|
|
|
memset(cmd, 0, sizeof(cmd));
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(cmd, 0, sizeof(cmd));
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
memset(buff, 0, sizeof(buff));
|
|
|
|
|
|
|
|
if ((bread = recv(sockd, buff, sizeof(buff) - 1, 0)) > 0) {
|
|
|
|
buff[bread] = '\0';
|
|
|
|
if (!strstr(buff, "Signature:")) {
|
|
|
|
cli_errmsg("getdsig: Error generating digital signature\n");
|
|
|
|
cli_errmsg("getdsig: Answer from remote server: %s\n", buff);
|
|
|
|
closesocket(sockd);
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
cli_infomsg(NULL, "Signature received (length = %lu)\n", (unsigned long)strlen(buff) - 10);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cli_errmsg("getdsig: Communication error with remote server\n");
|
|
|
|
closesocket(sockd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
closesocket(sockd);
|
|
|
|
|
|
|
|
pt = buff;
|
|
|
|
pt += 10;
|
|
|
|
return strdup(pt);
|
|
|
|
}
|
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
cl_error_t cli_versig(const char *md5, const char *dsig)
|
2003-10-08 12:51:07 +00:00
|
|
|
{
|
2023-02-18 10:47:53 +01:00
|
|
|
BIGNUM *n = NULL, *e = NULL;
|
|
|
|
char *pt = NULL, *pt2 = NULL;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = CL_EMEM;
|
|
|
|
n = BN_new();
|
|
|
|
if (!n)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
e = BN_new();
|
|
|
|
if (!e)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = CL_EVERIFY;
|
|
|
|
if (!BN_dec2bn(&e, CLI_ESTR))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (!BN_dec2bn(&n, CLI_NSTR))
|
|
|
|
goto done;
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
if (strlen(md5) != 32 || !isalnum(md5[0])) {
|
|
|
|
/* someone is trying to fool us with empty/malformed MD5 ? */
|
|
|
|
cli_errmsg("SECURITY WARNING: MD5 basic test failure.\n");
|
2023-02-18 10:47:53 +01:00
|
|
|
goto done;
|
2003-10-08 12:51:07 +00:00
|
|
|
}
|
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
if (!(pt = (char *)cli_decodesig(dsig, 16, e, n)))
|
|
|
|
goto done;
|
2003-10-20 00:55:11 +00:00
|
|
|
|
2004-07-19 17:54:40 +00:00
|
|
|
pt2 = cli_str2hex(pt, 16);
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2006-10-14 21:12:04 +00:00
|
|
|
cli_dbgmsg("cli_versig: Decoded signature: %s\n", pt2);
|
2003-10-08 12:51:07 +00:00
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
if (strncmp(md5, pt2, 32)) {
|
|
|
|
cli_dbgmsg("cli_versig: Signature doesn't match.\n");
|
2023-02-18 10:47:53 +01:00
|
|
|
goto done;
|
2003-10-08 12:51:07 +00:00
|
|
|
}
|
|
|
|
|
2006-10-14 21:12:04 +00:00
|
|
|
cli_dbgmsg("cli_versig: Digital signature is correct.\n");
|
2023-02-18 10:47:53 +01:00
|
|
|
ret = CL_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
free(pt);
|
|
|
|
free(pt2);
|
|
|
|
BN_free(n);
|
|
|
|
BN_free(e);
|
|
|
|
return ret;
|
2003-10-08 12:51:07 +00:00
|
|
|
}
|
2010-01-20 15:02:13 +01:00
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
#define HASH_LEN 32
|
|
|
|
#define SALT_LEN 32
|
|
|
|
#define PAD_LEN (2048 / 8)
|
|
|
|
#define BLK_LEN (PAD_LEN - HASH_LEN - 1)
|
2010-01-20 15:02:13 +01:00
|
|
|
int cli_versig2(const unsigned char *sha256, const char *dsig_str, const char *n_str, const char *e_str)
|
|
|
|
{
|
2023-04-07 09:24:56 -07:00
|
|
|
unsigned char *decoded = NULL;
|
|
|
|
unsigned char digest1[HASH_LEN], digest2[HASH_LEN], digest3[HASH_LEN], *salt;
|
2018-12-03 12:40:13 -05:00
|
|
|
unsigned char mask[BLK_LEN], data[BLK_LEN], final[8 + 2 * HASH_LEN], c[4];
|
|
|
|
unsigned int i, rounds;
|
2014-02-28 12:12:30 -05:00
|
|
|
void *ctx;
|
2023-02-18 10:47:53 +01:00
|
|
|
BIGNUM *n, *e;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
n = BN_new();
|
|
|
|
e = BN_new();
|
|
|
|
|
|
|
|
if (!n || !e) {
|
|
|
|
ret = CL_EMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = CL_EVERIFY;
|
|
|
|
if (!BN_dec2bn(&e, e_str))
|
|
|
|
goto done;
|
2010-01-20 15:02:13 +01:00
|
|
|
|
2023-02-18 10:47:53 +01:00
|
|
|
if (!BN_dec2bn(&n, n_str))
|
|
|
|
goto done;
|
2010-01-20 15:02:13 +01:00
|
|
|
|
|
|
|
decoded = cli_decodesig(dsig_str, PAD_LEN, e, n);
|
2023-02-18 10:47:53 +01:00
|
|
|
if (!decoded) {
|
|
|
|
ret = CL_EVERIFY;
|
|
|
|
goto done;
|
|
|
|
}
|
2010-01-20 15:02:13 +01:00
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
if (decoded[PAD_LEN - 1] != 0xbc) {
|
2023-02-18 10:47:53 +01:00
|
|
|
ret = CL_EVERIFY;
|
2023-04-07 09:24:56 -07:00
|
|
|
goto done;
|
2010-01-20 15:02:13 +01:00
|
|
|
}
|
2023-02-18 10:47:53 +01:00
|
|
|
BN_free(n);
|
|
|
|
BN_free(e);
|
|
|
|
|
|
|
|
n = NULL;
|
|
|
|
e = NULL;
|
2010-01-20 15:02:13 +01:00
|
|
|
|
|
|
|
memcpy(mask, decoded, BLK_LEN);
|
|
|
|
memcpy(digest2, &decoded[BLK_LEN], HASH_LEN);
|
|
|
|
free(decoded);
|
2023-04-07 09:24:56 -07:00
|
|
|
decoded = NULL;
|
2010-01-20 15:02:13 +01:00
|
|
|
|
|
|
|
c[0] = c[1] = 0;
|
2018-12-03 12:40:13 -05:00
|
|
|
rounds = (BLK_LEN + HASH_LEN - 1) / HASH_LEN;
|
|
|
|
for (i = 0; i < rounds; i++) {
|
|
|
|
c[2] = (unsigned char)(i / 256);
|
|
|
|
c[3] = (unsigned char)i;
|
|
|
|
|
|
|
|
ctx = cl_hash_init("sha256");
|
|
|
|
if (!(ctx))
|
|
|
|
return CL_EMEM;
|
|
|
|
|
|
|
|
cl_update_hash(ctx, digest2, HASH_LEN);
|
|
|
|
cl_update_hash(ctx, c, 4);
|
|
|
|
cl_finish_hash(ctx, digest3);
|
|
|
|
if (i + 1 == rounds)
|
2010-01-20 15:02:13 +01:00
|
|
|
memcpy(&data[i * 32], digest3, BLK_LEN - i * HASH_LEN);
|
2018-12-03 12:40:13 -05:00
|
|
|
else
|
|
|
|
memcpy(&data[i * 32], digest3, HASH_LEN);
|
2010-01-20 15:02:13 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
for (i = 0; i < BLK_LEN; i++)
|
|
|
|
data[i] ^= mask[i];
|
2010-01-20 15:02:13 +01:00
|
|
|
data[0] &= (0xff >> 1);
|
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
if (!(salt = memchr(data, 0x01, BLK_LEN)))
|
|
|
|
return CL_EVERIFY;
|
2010-01-20 15:02:13 +01:00
|
|
|
salt++;
|
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
if (data + BLK_LEN - salt != SALT_LEN)
|
|
|
|
return CL_EVERIFY;
|
2010-01-20 15:02:13 +01:00
|
|
|
|
|
|
|
memset(final, 0, 8);
|
|
|
|
memcpy(&final[8], sha256, HASH_LEN);
|
|
|
|
memcpy(&final[8 + HASH_LEN], salt, SALT_LEN);
|
|
|
|
|
2014-02-28 12:12:30 -05:00
|
|
|
ctx = cl_hash_init("sha256");
|
2014-02-13 13:05:50 -05:00
|
|
|
if (!(ctx))
|
|
|
|
return CL_EMEM;
|
|
|
|
|
2018-12-03 12:40:13 -05:00
|
|
|
cl_update_hash(ctx, final, sizeof(final));
|
|
|
|
cl_finish_hash(ctx, digest1);
|
2010-01-20 15:02:13 +01:00
|
|
|
|
|
|
|
return memcmp(digest1, digest2, HASH_LEN) ? CL_EVERIFY : CL_SUCCESS;
|
2023-02-18 10:47:53 +01:00
|
|
|
|
|
|
|
done:
|
2023-04-07 09:24:56 -07:00
|
|
|
free(decoded);
|
2023-02-18 10:47:53 +01:00
|
|
|
BN_free(n);
|
|
|
|
BN_free(e);
|
|
|
|
return ret;
|
2010-01-20 15:02:13 +01:00
|
|
|
}
|