Skip to content

Instantly share code, notes, and snippets.

@guidovranken
Created June 27, 2022 04:30
Show Gist options
  • Select an option

  • Save guidovranken/b1c46bd9e42e959519009681b261a896 to your computer and use it in GitHub Desktop.

Select an option

Save guidovranken/b1c46bd9e42e959519009681b261a896 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/bn.h>
#if 1 /* Taken from OpenSSL */
#define BN_MASK2 (0xffffffffffffffffLL)
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n)
{
BN_ULONG t1, t2;
int c = 0;
assert(n >= 0);
if (n <= 0)
return (BN_ULONG)0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
a += 4;
b += 4;
r += 4;
n -= 4;
}
#endif
while (n) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
a++;
b++;
r++;
n--;
}
return c;
}
/* Convenience method for uint64_t. */
static uint64_t value_barrier_64(uint64_t a)
{
volatile uint64_t r = a;
return r;
}
static uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
uint64_t b)
{
return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b);
}
static void bn_select_words(BN_ULONG *r, BN_ULONG mask,
const BN_ULONG *a,
const BN_ULONG *b, size_t num)
{
size_t i;
for (i = 0; i < num; i++) {
r[i] = constant_time_select_64(mask, a[i], b[i]);
}
}
static BN_ULONG bn_reduce_once_in_place(BN_ULONG *r,
BN_ULONG carry,
const BN_ULONG *m,
BN_ULONG *tmp, size_t num)
{
carry -= bn_sub_words(tmp, r, m, num);
bn_select_words(r, carry, r /* tmp < 0 */, tmp /* tmp >= 0 */, num);
return carry;
}
#endif
#define TOTAL_SIZE 1024
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if ( size < TOTAL_SIZE * 8 * 4 ) {
return 0;
}
BN_ULONG storage[TOTAL_SIZE];
BN_ULONG res1[TOTAL_SIZE];
BN_ULONG m1[TOTAL_SIZE];
BN_ULONG res2[TOTAL_SIZE];
BN_ULONG m2[TOTAL_SIZE];
BN_ULONG res1_before[TOTAL_SIZE];
BN_ULONG res2_before[TOTAL_SIZE];
memcpy(&res1[0], data + (TOTAL_SIZE * 0), TOTAL_SIZE * 8);
memcpy(&m1[0], data + (TOTAL_SIZE * 1), TOTAL_SIZE * 8);
memcpy(&res2[0], data + (TOTAL_SIZE * 2), TOTAL_SIZE * 8);
memcpy(&m2[0], data + (TOTAL_SIZE * 3), TOTAL_SIZE * 8);
const int res1_gte = res1[TOTAL_SIZE-1] >= m1[TOTAL_SIZE-1];
const int res2_gte = res2[TOTAL_SIZE-1] >= m2[TOTAL_SIZE-1];
memcpy(res1_before, res1, sizeof(res1));
memcpy(res2_before, res2, sizeof(res2));
bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, TOTAL_SIZE);
bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, TOTAL_SIZE);
if ( !res1_gte ) {
assert(memcmp(res1, res1_before, sizeof(res1)) == 0);
}
if ( !res2_gte ) {
assert(memcmp(res2, res2_before, sizeof(res2)) == 0);
}
for (size_t i = 0; i < TOTAL_SIZE; i++) {
assert(
storage[i] == ~(m2[i] - res2_before[i]) ||
storage[i] == ~(m2[i] - res2_before[i]) + 1
);
assert(
res1[i] == res1_before[i] ||
res1[i] == res1_before[i] - m1[i] ||
res1[i] == res1_before[i] - m1[i] - 1
);
assert(
res2[i] == res2_before[i] ||
res2[i] == res2_before[i] - m2[i] ||
res2[i] == res2_before[i] - m2[i] - 1
);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment