diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-12-31 09:06:42 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-12-31 09:06:42 +0100 |
commit | c039b52fc3d7c225fe8b6f88f21df83ac26d5984 (patch) | |
tree | bed796d3111679d359851521644fbbee2378f200 /sys/src/libc/port/u16.c | |
parent | ee89c82dd35475b93dd67773b7d10e461921a734 (diff) |
libc: constant time implementation for encode(2) routines, fix base32
the string encoding functions touch secret key material
in a bunch of places (devtls, devcap), so make sure we do
not leak information by cache timing side channels, making
the encoding and decoding routines constant time.
we also expose the alphabets through encXchr()/decXchr()
functions so caller can find the end of a encoded string
before calling decode function (for libmp).
the base32 encoding was broken in several ways. inputs
lengths of len%5 == [2,3,4] had output truncated and
it was using non-standard alphabet. documenting the alphabet
change in the manpage.
Diffstat (limited to 'sys/src/libc/port/u16.c')
-rw-r--r-- | sys/src/libc/port/u16.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/src/libc/port/u16.c b/sys/src/libc/port/u16.c index 4e1637120..60ffa72c8 100644 --- a/sys/src/libc/port/u16.c +++ b/sys/src/libc/port/u16.c @@ -1,6 +1,28 @@ #include <u.h> #include <libc.h> -static char t16e[] = "0123456789ABCDEF"; + +#define between(x,min,max) (((min-1-x) & (x-max-1))>>8) + +int +enc16chr(int o) +{ + int c; + + c = between(o, 0, 9) & ('0'+o); + c |= between(o, 10, 15) & ('A'+(o-10)); + return c; +} + +int +dec16chr(int c) +{ + int o; + + o = between(c, '0', '9') & (1+(c-'0')); + o |= between(c, 'A', 'F') & (1+10+(c-'A')); + o |= between(c, 'a', 'f') & (1+10+(c-'a')); + return o-1; +} int dec16(uchar *out, int lim, char *in, int n) @@ -10,14 +32,8 @@ dec16(uchar *out, int lim, char *in, int n) uchar *eout = out + lim; while(n-- > 0){ - c = *in++; - if('0' <= c && c <= '9') - c = c - '0'; - else if('a' <= c && c <= 'z') - c = c - 'a' + 10; - else if('A' <= c && c <= 'Z') - c = c - 'A' + 10; - else + c = dec16chr(*in++); + if(c < 0) continue; w = (w<<4) + c; i++; @@ -44,8 +60,8 @@ enc16(char *out, int lim, uchar *in, int n) c = *in++; if(out + 2 >= eout) goto exhausted; - *out++ = t16e[c>>4]; - *out++ = t16e[c&0xf]; + *out++ = enc16chr(c>>4); + *out++ = enc16chr(c&15); } exhausted: *out = 0; |