Re: RELIC Library Bug: bn_read_bin() Crashes on Empty Input

4 views
Skip to first unread message

Diego F. Aranha

unread,
Mar 8, 2026, 1:31:21 PMMar 8
to relic-...@googlegroups.com
Hi,

Thank you for the report!

What version of the library are you running?

I believe this was already fixed, but still pushed a few changes to HEAD to clarify the intended behavior.

Best,
--
Diego F. Aranha
Associate Professor at Computer Science Aarhus University, Denmark

Åbogade 34, Building 5335 (Office 291 at Nygaard)
8200 Aarhus N, Denmark





On Sun, Mar 8, 2026 at 8:36 AM Arjuna Arya <arjunaaj...@gmail.com> wrote:
found a bug in RELIC's bn_read_bin() while messing around with some crypto code. figured i'd document it since it's actually pretty easy to crash things with this.

the issue is in src/bn/relic_bn_util.c. bn_read_bin() takes a buffer and length, but if you pass len=0 it messes up the internal state.

code looks like this:

```c
void bn_read_bin(bn_t a, const uint8_t *bin, size_t len) {
    int digs = (len % d == 0 ? len / d : len / d + 1);
   
    bn_grow(a, digs);
    bn_zero(a);        // this sets used = 1 correctly
    a->used = digs;    // but then this overwrites with 0 if len was 0!
    // ...
}
```

so bn_zero() does the right thing and sets used=1, then the assignment just stomps it with 0. now you have a big int with used=0 which breaks assumptions all over the place.

other functions access a->dp[a->used - 1] thinking used is at least 1. when it's 0, you get a->dp[-1] which is reading before the buffer. oob read.

bn_size_bin() is one that crashes:

```c
size_t bn_size_bin(const bn_t a) {
    digits = (a->used - 1) * (RLC_DIG / 8);  // underflows
    d = a->dp[a->used - 1];                   // reads dp[-1], segfault
```

you can trigger this through cp_bbs_sig() and similar functions. they have a hash flag - if you set hash=1 it calls bn_read_bin directly on your input without hashing first. so pass empty message with hash=1 and len=0, boom.

```c
cp_bbs_sig(s, msg, 0, 1, d);  // len=0, hash=1, crash incoming
```

same with cp_bbs_ver, cp_zss_sig, cp_zss_ver. all have the same pattern.

can definitely crash a service if they're using RELIC and accepting signatures. it's just a DoS though, not rce. medium severity id say.

trivial to fix. either check len at the start:

```c
if (len == 0) {
    bn_zero(a);
    return;
}
```

or make sure used cant be zero:

```c
a->used = digs == 0 ? 1 : digs;
```

thats it really. simple bug but annoying if youre running a service that processes crypto stuff with this library.

test case to see it crash:

```c
#include "relic.h"
#include <stdio.h>

int main() {
    core_init();
    bn_t a;
    bn_new(a);
   
    bn_read_bin(a, (uint8_t*)"x", 0);  // len 0
    printf("used = %zu\n", a->used);     // shows 0, bad
   
    bn_size_bin(a);  // segfault here
    return 0;
}
```

compile and run, watch it die on bn_size_bin.

found this while bored and looking at crypto libs. not sponsored or anything. patch your stuff if you use RELIC.

--

---
You received this message because you are subscribed to the Google Groups "relic-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to relic-discus...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/relic-discuss/93e5c919-1350-4c60-a77d-d01197b99bd9n%40googlegroups.com.

Arjuna Arya

unread,
Mar 8, 2026, 1:42:29 PMMar 8
to relic-...@googlegroups.com
my bad, was running an older version. thanks for the quick response and the fixes! 👍

should've checked HEAD first before digging in lol. appreciate you clarifying the behavior too - makes it more obvious what the function expects.

keep up the good work on RELIC!

cheers

Reply all
Reply to author
Forward
0 new messages