hardening: add MP_ZERO_BUFFER, MP_ZERO_DIGITS

* (!) Always zero buffer before freeing if MP_NO_ZERO_ON_FREE is not defined
* Add MP_NO_ZERO_ON_FREE to disable hardening
* Add MP_ZERO_BUFFER, MP_ZERO_DIGITS, MP_FREE_BUFFFER, MP_FREE_DIGITS
* Never use MP_FREE directly, use MP_FREE_DIGITS or MP_FREE_BUFFER
* Add MP_USE_MEMSET to use memset instead of loop
* Disable astyle backups which are annonying in the times of git
This commit is contained in:
Daniel Mendler 2019-05-11 10:22:20 +02:00
parent 55e312b1c1
commit 61d9e528a4
No known key found for this signature in database
GPG Key ID: D88ADB2A2693CA43
22 changed files with 68 additions and 74 deletions

View File

@ -4,6 +4,9 @@
# usage: # usage:
# astyle --options=astylerc *.[ch] # astyle --options=astylerc *.[ch]
# Do not create backup, annonying in the times of git
suffix=none
## Bracket Style Options ## Bracket Style Options
style=kr style=kr

View File

@ -85,9 +85,7 @@ int mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
c->sign = MP_ZPOS; c->sign = MP_ZPOS;
/* now zero to oldused */ /* now zero to oldused */
while (ix++ < oldused) { MP_ZERO_DIGITS(tmpc, oldused - ix);
*tmpc++ = 0;
}
mp_clamp(c); mp_clamp(c);
return MP_OKAY; return MP_OKAY;

View File

@ -29,9 +29,7 @@ int mp_and(const mp_int *a, const mp_int *b, mp_int *c)
} }
/* zero digits above the last from the smallest mp_int */ /* zero digits above the last from the smallest mp_int */
for (; ix < t.used; ix++) { MP_ZERO_DIGITS(t.dp + ix, t.used - ix);
t.dp[ix] = 0;
}
mp_clamp(&t); mp_clamp(&t);
mp_exch(c, &t); mp_exch(c, &t);

View File

@ -6,17 +6,10 @@
/* clear one (frees) */ /* clear one (frees) */
void mp_clear(mp_int *a) void mp_clear(mp_int *a)
{ {
int i;
/* only do anything if a hasn't been freed previously */ /* only do anything if a hasn't been freed previously */
if (a->dp != NULL) { if (a->dp != NULL) {
/* first zero the digits */
for (i = 0; i < a->used; i++) {
a->dp[i] = 0;
}
/* free ram */ /* free ram */
MP_FREE(a->dp, sizeof(mp_digit) * (size_t)a->alloc); MP_FREE_DIGITS(a->dp, a->alloc);
/* reset members to make debugging easier */ /* reset members to make debugging easier */
a->dp = NULL; a->dp = NULL;

View File

@ -38,9 +38,7 @@ int mp_copy(const mp_int *a, mp_int *b)
} }
/* clear high digits */ /* clear high digits */
for (; n < b->used; n++) { MP_ZERO_DIGITS(tmpb, b->used - n);
*tmpb++ = 0;
}
} }
/* copy used count and sign */ /* copy used count and sign */

View File

@ -40,10 +40,7 @@ int mp_div_2(const mp_int *a, mp_int *b)
} }
/* zero excess digits */ /* zero excess digits */
tmpb = b->dp + b->used; MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used);
for (x = b->used; x < oldused; x++) {
*tmpb++ = 0;
}
} }
b->sign = a->sign; b->sign = a->sign;
mp_clamp(b); mp_clamp(b);

View File

@ -58,9 +58,7 @@ top:
*tmpx1++ = mu; *tmpx1++ = mu;
/* zero words above m */ /* zero words above m */
for (i = m + 1; i < x->used; i++) { MP_ZERO_DIGITS(tmpx1, x->used - m - 1);
*tmpx1++ = 0;
}
/* clamp, sub and return */ /* clamp, sub and return */
mp_clamp(x); mp_clamp(x);

View File

@ -19,18 +19,18 @@ int mp_fwrite(const mp_int *a, int radix, FILE *stream)
} }
if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
MP_FREE(buf, len); MP_FREE_BUFFER(buf, (size_t)len);
return err; return err;
} }
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
if (fputc((int)buf[x], stream) == EOF) { if (fputc((int)buf[x], stream) == EOF) {
MP_FREE(buf, len); MP_FREE_BUFFER(buf, (size_t)len);
return MP_VAL; return MP_VAL;
} }
} }
MP_FREE(buf, len); MP_FREE_BUFFER(buf, (size_t)len);
return MP_OKAY; return MP_OKAY;
} }
#endif #endif

View File

@ -34,9 +34,7 @@ int mp_grow(mp_int *a, int size)
/* zero excess digits */ /* zero excess digits */
i = a->alloc; i = a->alloc;
a->alloc = size; a->alloc = size;
for (; i < a->alloc; i++) { MP_ZERO_DIGITS(a->dp + i, a->alloc - i);
a->dp[i] = 0;
}
} }
return MP_OKAY; return MP_OKAY;
} }

View File

@ -25,9 +25,9 @@ int mp_mod_2d(const mp_int *a, int b, mp_int *c)
} }
/* zero digits above the last digit of the modulus */ /* zero digits above the last digit of the modulus */
for (x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1); x < c->used; x++) { x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1);
c->dp[x] = 0; MP_ZERO_DIGITS(c->dp + x, c->used - x);
}
/* clear the digit that is not completely outside/inside the modulus */ /* clear the digit that is not completely outside/inside the modulus */
c->dp[b / MP_DIGIT_BIT] &= c->dp[b / MP_DIGIT_BIT] &=
((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1; ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1;

View File

@ -55,10 +55,7 @@ int mp_mul_2(const mp_int *a, mp_int *b)
/* now zero any excess digits on the destination /* now zero any excess digits on the destination
* that we didn't write to * that we didn't write to
*/ */
tmpb = b->dp + b->used; MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used);
for (x = b->used; x < oldused; x++) {
*tmpb++ = 0;
}
} }
b->sign = a->sign; b->sign = a->sign;
return MP_OKAY; return MP_OKAY;

View File

@ -49,9 +49,7 @@ int mp_mul_d(const mp_int *a, mp_digit b, mp_int *c)
++ix; ++ix;
/* now zero digits above the top */ /* now zero digits above the top */
while (ix++ < olduse) { MP_ZERO_DIGITS(tmpc, olduse - ix);
*tmpc++ = 0;
}
/* set used count */ /* set used count */
c->used = a->used + 1; c->used = a->used + 1;

View File

@ -114,7 +114,7 @@ static int s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_m
err = MP_OKAY; err = MP_OKAY;
error: error:
MP_FREE(tmp, bsize); MP_FREE_BUFFER(tmp, (size_t)bsize);
return err; return err;
} }

View File

@ -67,9 +67,8 @@ int mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
} }
/* zero excess digits */ /* zero excess digits */
while (ix++ < oldused) { MP_ZERO_DIGITS(tmpc, oldused - ix);
*tmpc++ = 0;
}
mp_clamp(c); mp_clamp(c);
return MP_OKAY; return MP_OKAY;
} }

View File

@ -6,15 +6,8 @@
/* set to zero */ /* set to zero */
void mp_zero(mp_int *a) void mp_zero(mp_int *a)
{ {
int n;
mp_digit *tmp;
a->sign = MP_ZPOS; a->sign = MP_ZPOS;
a->used = 0; a->used = 0;
MP_ZERO_DIGITS(a->dp, a->alloc);
tmp = a->dp;
for (n = 0; n < a->alloc; n++) {
*tmp++ = 0;
}
} }
#endif #endif

View File

@ -81,9 +81,7 @@ int s_mp_add(const mp_int *a, const mp_int *b, mp_int *c)
*tmpc++ = u; *tmpc++ = u;
/* clear digits above oldused */ /* clear digits above oldused */
for (i = c->used; i < olduse; i++) { MP_ZERO_DIGITS(tmpc, olduse - c->used);
*tmpc++ = 0;
}
} }
mp_clamp(c); mp_clamp(c);

View File

@ -49,8 +49,8 @@ int s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho)
} }
/* zero the high words of W[a->used..m->used*2] */ /* zero the high words of W[a->used..m->used*2] */
for (; ix < ((n->used * 2) + 1); ix++) { if (ix < ((n->used * 2) + 1)) {
*_W++ = 0; MP_ZERO_BUFFER(_W, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix));
} }
} }
@ -142,9 +142,7 @@ int s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho)
/* zero oldused digits, if the input a was larger than /* zero oldused digits, if the input a was larger than
* m->used+1 we'll have to clear the digits * m->used+1 we'll have to clear the digits
*/ */
for (; ix < olduse; ix++) { MP_ZERO_DIGITS(tmpx, olduse - ix);
*tmpx++ = 0;
}
} }
/* set the max used and clamp */ /* set the max used and clamp */

View File

@ -81,9 +81,7 @@ int s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
} }
/* clear unused digits [that existed in the old copy of c] */ /* clear unused digits [that existed in the old copy of c] */
for (; ix < olduse; ix++) { MP_ZERO_DIGITS(tmpc, olduse - ix);
*tmpc++ = 0;
}
} }
mp_clamp(c); mp_clamp(c);
return MP_OKAY; return MP_OKAY;

View File

@ -72,9 +72,7 @@ int s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int dig
} }
/* clear unused digits [that existed in the old copy of c] */ /* clear unused digits [that existed in the old copy of c] */
for (; ix < olduse; ix++) { MP_ZERO_DIGITS(tmpc, olduse - ix);
*tmpc++ = 0;
}
} }
mp_clamp(c); mp_clamp(c);
return MP_OKAY; return MP_OKAY;

View File

@ -88,9 +88,7 @@ int s_mp_sqr_fast(const mp_int *a, mp_int *b)
} }
/* clear unused digits [that existed in the old copy of c] */ /* clear unused digits [that existed in the old copy of c] */
for (; ix < olduse; ix++) { MP_ZERO_DIGITS(tmpb, olduse - ix);
*tmpb++ = 0;
}
} }
mp_clamp(b); mp_clamp(b);
return MP_OKAY; return MP_OKAY;

View File

@ -60,9 +60,7 @@ int s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
} }
/* clear digits above used (since we may not have grown result above) */ /* clear digits above used (since we may not have grown result above) */
for (i = c->used; i < olduse; i++) { MP_ZERO_DIGITS(tmpc, olduse - c->used);
*tmpc++ = 0;
}
} }
mp_clamp(c); mp_clamp(c);

View File

@ -10,6 +10,42 @@
extern "C" { extern "C" {
#endif #endif
/* Hardening libtommath
* --------------------
*
* By default memory is zeroed before calling
* MP_FREE to avoid leaking data. This is good
* practice in cryptographical applications.
*
* Note however that memory allocators used
* in cryptographical applications can often
* be configured by itself to clear memory,
* rendering the clearing in tommath unnecessary.
* See for example https://github.com/GrapheneOS/hardened_malloc
* and the option CONFIG_ZERO_ON_FREE.
*
* Furthermore there are applications which
* value performance more and want this
* feature to be disabled. For such applications
* define MP_NO_ZERO_ON_FREE during compilation.
*/
#ifdef MP_NO_ZERO_ON_FREE
# define MP_FREE_BUFFER(mem, size) MP_FREE((mem), (size))
# define MP_FREE_DIGITS(mem, digits) MP_FREE((mem), sizeof (mp_digit) * (digits))
#else
# define MP_FREE_BUFFER(mem, size) do { size_t fs_ = (size); void* fm_ = (mem); if (fm_) { MP_ZERO_BUFFER(fm_, fs_); MP_FREE(fm_, fs_); } } while (0)
# define MP_FREE_DIGITS(mem, digits) do { int fd_ = (digits); void* fm_ = (mem); if (fm_) { MP_ZERO_BUFFER(fm_, sizeof (mp_digit) * (size_t)fd_); MP_FREE(fm_, sizeof (mp_digit) * (size_t)fd_); } } while (0)
#endif
#ifdef MP_USE_MEMSET
# include <string.h>
# define MP_ZERO_BUFFER(mem, size) memset((mem), 0, (size))
# define MP_ZERO_DIGITS(mem, digits) do { int zd_ = (digits); if (zd_ > 0) { memset((mem), 0, sizeof (mp_digit) * (size_t)zd_); } } while (0)
#else
# define MP_ZERO_BUFFER(mem, size) do { size_t zs_ = (size); char* zm_ = (char*)(mem); while (zs_-- > 0) { *zm_++ = 0; } } while (0)
# define MP_ZERO_DIGITS(mem, digits) do { int zd_ = (digits); mp_digit* zm_ = (mem); while (zd_-- > 0) { *zm_++ = 0; } } while (0)
#endif
/* Tunable cutoffs /* Tunable cutoffs
* --------------- * ---------------
* *
@ -43,8 +79,8 @@ extern "C" {
/* default to libc stuff */ /* default to libc stuff */
# include <stdlib.h> # include <stdlib.h>
# define MP_MALLOC(size) malloc(size) # define MP_MALLOC(size) malloc(size)
# define MP_REALLOC(mem, oldsize, newsize) realloc(mem, newsize) # define MP_REALLOC(mem, oldsize, newsize) realloc((mem), (newsize))
# define MP_CALLOC(nmemb, size) calloc(nmemb, size) # define MP_CALLOC(nmemb, size) calloc((nmemb), (size))
# define MP_FREE(mem, size) free(mem) # define MP_FREE(mem, size) free(mem)
#else #else
/* prototypes for our heap functions */ /* prototypes for our heap functions */