--- ssss-0.5/ssss.c.bak 2021-10-28 17:17:26.682899810 +0300 +++ ssss-0.5/ssss.c 2021-10-28 17:17:41.339826427 +0300 @@ -47,15 +47,32 @@ #include #include #include +#include #include #define VERSION "0.5" -#define RANDOM_SOURCE "/dev/random" #define MAXDEGREE 1024 #define MAXTOKENLEN 128 #define MAXLINELEN (MAXTOKENLEN + 1 + 10 + 1 + MAXDEGREE / 4 + 10) +#define barrier() asm volatile("": : :"memory") + +/** + * memzero_explicit - Fill a region of memory (e.g. sensitive + * keying data) with 0s. + * @s: Pointer to the start of the area. + * @count: The size of the area. + * + * memzero_explicit() doesn't need an arch-specific version as + * it just invokes the one of memset() implicitly. + */ +static inline void memzero_explicit(void *s, size_t count) +{ + memset(s, 0, count); + barrier(); +} + /* coefficients of some irreducible polynomials over GF(2) */ static const unsigned char irred_coeff[] = { 4,3,1,5,3,1,4,3,1,7,3,2,5,4,3,5,3,2,7,4,2,4,3,1,10,9,3,9,4,2,7,6,2,10,9, @@ -101,8 +118,9 @@ void fatal(char *msg) void warning(char *msg) { - if (! opt_QUIET) + if (! opt_QUIET) { fprintf(stderr, "%sWARNING: %s.\n", isatty(2) ? "\a" : "", msg); + } } /* field arithmetic routines */ @@ -143,13 +161,13 @@ void field_import(mpz_t x, const char *s warning("input string too short, adding null padding on the left"); if (mpz_set_str(x, s, 16) || (mpz_cmp_ui(x, 0) < 0)) fatal("invalid syntax"); - } - else { + } else { int i; int warn = 0; + if (strlen(s) > degree / 8) fatal("input string too long"); - for(i = strlen(s) - 1; i >= 0; i--) + for (i = strlen(s) - 1; i >= 0; i--) warn = warn || (s[i] < 32) || (s[i] >= 127); if (warn) warning("binary data detected, use -x mode instead"); @@ -160,20 +178,21 @@ void field_import(mpz_t x, const char *s void field_print(FILE* stream, const mpz_t x, int hexmode) { int i; + if (hexmode) { - for(i = degree / 4 - mpz_sizeinbase(x, 16); i; i--) + for (i = degree / 4 - mpz_sizeinbase(x, 16); i; i--) fprintf(stream, "0"); mpz_out_str(stream, 16, x); fprintf(stream, "\n"); - } - else { + } else { char buf[MAXDEGREE / 8 + 1]; size_t t; unsigned int i; int printable, warn = 0; - memset(buf, degree / 8 + 1, 0); + + memset(buf, 0, degree / 8 + 1); mpz_export(buf, &t, 1, 1, 0, 0, x); - for(i = 0; i < t; i++) { + for (i = 0; i < t; i++) { printable = (buf[i] >= 32) && (buf[i] < 127); warn = warn || ! printable; fprintf(stream, "%c", printable ? buf[i] : '.'); @@ -195,13 +214,16 @@ void field_mult(mpz_t z, const mpz_t x, { mpz_t b; unsigned int i; + assert(z != y); mpz_init_set(b, x); - if (mpz_tstbit(y, 0)) + if (mpz_tstbit(y, 0)) { mpz_set(z, b); - else + } else { mpz_set_ui(z, 0); - for(i = 1; i < degree; i++) { + } + + for (i = 1; i < degree; i++) { mpz_lshift(b, b, 1); if (mpz_tstbit(b, degree)) mpz_xor(b, b, poly); @@ -215,12 +237,14 @@ void field_invert(mpz_t z, const mpz_t x { mpz_t u, v, g, h; int i; + assert(mpz_cmp_ui(x, 0)); mpz_init_set(u, x); mpz_init_set(v, poly); mpz_init_set_ui(g, 0); mpz_set_ui(z, 1); mpz_init(h); + while (mpz_cmp_ui(u, 1)) { i = mpz_sizeinbits(u) - mpz_sizeinbits(v); if (i < 0) { @@ -238,29 +262,20 @@ void field_invert(mpz_t z, const mpz_t x /* routines for the random number generator */ -void cprng_init(void) -{ - if ((cprng = open(RANDOM_SOURCE, O_RDONLY)) < 0) - fatal("couldn't open " RANDOM_SOURCE); -} - -void cprng_deinit(void) -{ - if (close(cprng) < 0) - fatal("couldn't close " RANDOM_SOURCE); -} - void cprng_read(mpz_t x) { char buf[MAXDEGREE / 8]; - unsigned int count; - int i; - for(count = 0; count < degree / 8; count += i) - if ((i = read(cprng, buf + count, degree / 8 - count)) < 0) { - close(cprng); - fatal("couldn't read from " RANDOM_SOURCE); - } - mpz_import(x, degree / 8, 1, 1, 0, 0, buf); + size_t toread = degree / 8; + ssize_t i; + + do { + i = getrandom(buf, toread, 0); + } while ((i == -1) && (errno == EINTR)); + if (i != toread) { + fatal("getrandom failed"); + } + mpz_import(x, toread, 1, 1, 0, 0, buf); + memzero_explicit(buf, sizeof(buf)); } /* a 64 bit pseudo random permutation (based on the XTEA cipher) */ @@ -269,7 +284,8 @@ void encipher_block(uint32_t *v) { uint32_t sum = 0, delta = 0x9E3779B9; int i; - for(i = 0; i < 32; i++) { + + for (i = 0; i < 32; i++) { v[0] += (((v[1] << 4) ^ (v[1] >> 5)) + v[1]) ^ sum; sum += delta; v[1] += (((v[0] << 4) ^ (v[0] >> 5)) + v[0]) ^ sum; @@ -280,7 +296,8 @@ void decipher_block(uint32_t *v) { uint32_t sum = 0xC6EF3720, delta = 0x9E3779B9; int i; - for(i = 0; i < 32; i++) { + + for (i = 0; i < 32; i++) { v[1] -= ((v[0] << 4 ^ v[0] >> 5) + v[0]) ^ sum; sum -= delta; v[0] -= ((v[1] << 4 ^ v[1] >> 5) + v[1]) ^ sum; @@ -292,12 +309,14 @@ void encode_slice(uint8_t *data, int idx { uint32_t v[2]; int i; - for(i = 0; i < 2; i++) + + for (i = 0; i < 2; i++) { v[i] = data[(idx + 4 * i) % len] << 24 | - data[(idx + 4 * i + 1) % len] << 16 | - data[(idx + 4 * i + 2) % len] << 8 | data[(idx + 4 * i + 3) % len]; + data[(idx + 4 * i + 1) % len] << 16 | + data[(idx + 4 * i + 2) % len] << 8 | data[(idx + 4 * i + 3) % len]; + } process_block(v); - for(i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) { data[(idx + 4 * i + 0) % len] = v[i] >> 24; data[(idx + 4 * i + 1) % len] = (v[i] >> 16) & 0xff; data[(idx + 4 * i + 2) % len] = (v[i] >> 8) & 0xff; @@ -312,16 +331,20 @@ void encode_mpz(mpz_t x, enum encdec enc uint8_t v[(MAXDEGREE + 8) / 16 * 2]; size_t t; int i; + memset(v, 0, (degree + 8) / 16 * 2); mpz_export(v, &t, -1, 2, 1, 0, x); - if (degree % 16 == 8) + if (degree % 16 == 8) { v[degree / 8 - 1] = v[degree / 8]; - if (encdecmode == ENCODE) /* 40 rounds are more than enough!*/ - for(i = 0; i < 40 * ((int)degree / 8); i += 2) + } + if (encdecmode == ENCODE) { + /* 40 rounds are more than enough!*/ + for (i = 0; i < 40 * ((int)degree / 8); i += 2) encode_slice(v, i, degree / 8, encipher_block); - else - for(i = 40 * (degree / 8) - 2; i >= 0; i -= 2) + } else { + for (i = 40 * (degree / 8) - 2; i >= 0; i -= 2) encode_slice(v, i, degree / 8, decipher_block); + } if (degree % 16 == 8) { v[degree / 8] = v[degree / 8 - 1]; v[degree / 8 - 1] = 0; @@ -336,7 +359,8 @@ void horner(int n, mpz_t y, const mpz_t { int i; mpz_set(y, x); - for(i = n - 1; i; i--) { + + for (i = n - 1; i; i--) { field_add(y, y, coeff[i]); field_mult(y, y, x); } @@ -352,24 +376,26 @@ int restore_secret(int n, mpz_t (*A)[n], { mpz_t (*AA)[n] = (mpz_t (*)[n])A; int i, j, k, found; + mpz_t h; mpz_init(h); - for(i = 0; i < n; i++) { + for (i = 0; i < n; i++) { if (! mpz_cmp_ui(AA[i][i], 0)) { - for(found = 0, j = i + 1; j < n; j++) + for (found = 0, j = i + 1; j < n; j++) { if (mpz_cmp_ui(AA[i][j], 0)) { found = 1; break; } + } if (! found) return -1; - for(k = i; k < n; k++) + for (k = i; k < n; k++) MPZ_SWAP(AA[k][i], AA[k][j]); MPZ_SWAP(b[i], b[j]); } - for(j = i + 1; j < n; j++) { + for (j = i + 1; j < n; j++) { if (mpz_cmp_ui(AA[i][j], 0)) { - for(k = i + 1; k < n; k++) { + for (k = i + 1; k < n; k++) { field_mult(h, AA[k][i], AA[i][j]); field_mult(AA[k][j], AA[k][j], AA[i][i]); field_add(AA[k][j], AA[k][j], h); @@ -394,7 +420,8 @@ void split(void) mpz_t x, y, coeff[opt_threshold]; char buf[MAXLINELEN]; int deg, i; - for(fmt_len = 1, i = opt_number; i >= 10; i /= 10, fmt_len++); + + for (fmt_len = 1, i = opt_number; i >= 10; i /= 10, fmt_len++); if (! opt_quiet) { printf("Generating shares using a (%d,%d) scheme with ", opt_threshold, opt_number); @@ -422,8 +449,9 @@ void split(void) if (! field_size_valid(opt_security)) fatal("security level invalid (secret too long?)"); if (! opt_quiet) - fprintf(stderr, "Using a %d bit security level.\n", opt_security); + fprintf(stderr, "Using a %d bit security level.", opt_security); } + fprintf(stderr, "\n"); field_init(opt_security); @@ -437,16 +465,14 @@ void split(void) warning("security level too small for the diffusion layer"); } - cprng_init(); - for(i = 1; i < opt_threshold; i++) { + for (i = 1; i < opt_threshold; i++) { mpz_init(coeff[i]); cprng_read(coeff[i]); } - cprng_deinit(); mpz_init(x); mpz_init(y); - for(i = 0; i < opt_number; i++) { + for (i = 0; i < opt_number; i++) { mpz_set_ui(x, i + 1); horner(opt_threshold, y, x, (const mpz_t*)coeff); if (opt_token) @@ -457,7 +483,7 @@ void split(void) mpz_clear(x); mpz_clear(y); - for(i = 0; i < opt_threshold; i++) + for (i = 0; i < opt_threshold; i++) mpz_clear(coeff[i]); field_deinit(); } @@ -504,7 +530,7 @@ void combine(void) fatal("invalid share"); mpz_set_ui(x, j); mpz_init_set_ui(A[opt_threshold - 1][i], 1); - for(j = opt_threshold - 2; j >= 0; j--) { + for (j = opt_threshold - 2; j >= 0; j--) { mpz_init(A[j][i]); field_mult(A[j][i], A[j + 1][i], x); } @@ -613,8 +639,7 @@ int main(int argc, char *argv[]) fatal("invalid parameters: token too long"); split(); - } - else { + } else { if (opt_help || opt_showversion) { puts("Combine shares using Shamir's Secret Sharing Scheme.\n" "\n"