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.
This commit is contained in:
parent
ee89c82dd3
commit
c039b52fc3
6 changed files with 186 additions and 90 deletions
|
@ -48,17 +48,14 @@ encodefmt(Fmt *f)
|
|||
// convert
|
||||
out = buf;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
rv = enc32(out, len, b, ilen);
|
||||
break;
|
||||
case '[':
|
||||
rv = enc64(out, len, b, ilen);
|
||||
break;
|
||||
case '<':
|
||||
rv = enc32(out, len, b, ilen);
|
||||
break;
|
||||
case 'H':
|
||||
rv = enc16(out, len, b, ilen);
|
||||
if(rv >= 0 && (f->flags & FmtLong))
|
||||
for(p = buf; *p; p++)
|
||||
*p = tolower(*p);
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
|
@ -67,6 +64,10 @@ encodefmt(Fmt *f)
|
|||
if(rv < 0)
|
||||
goto error;
|
||||
|
||||
if((f->flags & FmtLong) != 0 && f->r != '[')
|
||||
for(p = buf; *p; p++)
|
||||
*p = tolower(*p);
|
||||
|
||||
fmtstrcpy(f, buf);
|
||||
if(buf != obuf)
|
||||
free(buf);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,21 +1,44 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
#define between(x,min,max) (((min-1-x) & (x-max-1))>>8)
|
||||
|
||||
int
|
||||
enc32chr(int o)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = between(o, 0, 25) & ('A'+o);
|
||||
c |= between(o, 26, 31) & ('2'+(o-26));
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
dec32chr(int c)
|
||||
{
|
||||
int o;
|
||||
|
||||
o = between(c, 'A', 'Z') & (1+(c-'A'));
|
||||
o |= between(c, 'a', 'z') & (1+(c-'a'));
|
||||
o |= between(c, '2', '7') & (1+26+(c-'2'));
|
||||
return o-1;
|
||||
}
|
||||
|
||||
int
|
||||
dec32(uchar *dest, int ndest, char *src, int nsrc)
|
||||
{
|
||||
char *s, *tab;
|
||||
uchar *start;
|
||||
int i, u[8];
|
||||
int i, j, u[8];
|
||||
|
||||
if(ndest+1 < (5*nsrc+7)/8)
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=8){
|
||||
for(i=0; i<8; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
j = dec32chr(src[i]);
|
||||
if(j < 0)
|
||||
j = 0;
|
||||
u[i] = j;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
|
@ -29,8 +52,10 @@ dec32(uchar *dest, int ndest, char *src, int nsrc)
|
|||
if(nsrc == 1 || nsrc == 3 || nsrc == 6)
|
||||
return -1;
|
||||
for(i=0; i<nsrc; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
j = dec32chr(src[i]);
|
||||
if(j < 0)
|
||||
j = 0;
|
||||
u[i] = j;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
if(nsrc == 2)
|
||||
|
@ -50,60 +75,57 @@ out:
|
|||
int
|
||||
enc32(char *dest, int ndest, uchar *src, int nsrc)
|
||||
{
|
||||
char *tab, *start;
|
||||
char *start;
|
||||
int j;
|
||||
|
||||
if(ndest <= (8*nsrc+4)/5 )
|
||||
if(ndest <= (8*nsrc+4)/5)
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=5){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1f & (src[1]>>1));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1f & (src[4]));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
src += 5;
|
||||
nsrc -= 5;
|
||||
}
|
||||
if(nsrc){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1c & (src[0]<<2));
|
||||
if(nsrc == 1)
|
||||
goto out;
|
||||
j |= (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1f & (src[1]>>1));
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x10 & (src[1]<<4));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4));
|
||||
j |= (0x0f & (src[2]>>4));
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1e & (src[2]<<1));
|
||||
if(nsrc == 3)
|
||||
goto out;
|
||||
j |= (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
j |= (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
j = (0x18 & (src[3]<<3));
|
||||
out:
|
||||
*dest++ = tab[j];
|
||||
*dest++ = enc32chr(j);
|
||||
}
|
||||
*dest = 0;
|
||||
return dest-start;
|
||||
|
|
|
@ -1,29 +1,33 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
enum {
|
||||
INVAL= 255
|
||||
};
|
||||
#define between(x,min,max) (((min-1-x) & (x-max-1))>>8)
|
||||
|
||||
static uchar t64d[256] = {
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
|
||||
};
|
||||
static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int
|
||||
enc64chr(int o)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = between(o, 0, 25) & ('A'+o);
|
||||
c |= between(o, 26, 51) & ('a'+(o-26));
|
||||
c |= between(o, 52, 61) & ('0'+(o-52));
|
||||
c |= between(o, 62, 62) & ('+');
|
||||
c |= between(o, 63, 63) & ('/');
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
dec64chr(int c)
|
||||
{
|
||||
int o;
|
||||
|
||||
o = between(c, 'A', 'Z') & (1+(c-'A'));
|
||||
o |= between(c, 'a', 'z') & (1+26+(c-'a'));
|
||||
o |= between(c, '0', '9') & (1+52+(c-'0'));
|
||||
o |= between(c, '+', '+') & (1+62);
|
||||
o |= between(c, '/', '/') & (1+63);
|
||||
return o-1;
|
||||
}
|
||||
|
||||
int
|
||||
dec64(uchar *out, int lim, char *in, int n)
|
||||
|
@ -36,9 +40,8 @@ dec64(uchar *out, int lim, char *in, int n)
|
|||
b24 = 0;
|
||||
i = 0;
|
||||
while(n-- > 0){
|
||||
|
||||
c = t64d[*(uchar*)in++];
|
||||
if(c == INVAL)
|
||||
c = dec64chr(*in++);
|
||||
if(c < 0)
|
||||
continue;
|
||||
switch(i){
|
||||
case 0:
|
||||
|
@ -58,8 +61,8 @@ dec64(uchar *out, int lim, char *in, int n)
|
|||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
*out++ = b24;
|
||||
i = -1;
|
||||
break;
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -89,34 +92,34 @@ enc64(char *out, int lim, uchar *in, int n)
|
|||
char *e = out + lim;
|
||||
|
||||
for(i = n/3; i > 0; i--){
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in++)<<8;
|
||||
b24 = *in++<<16;
|
||||
b24 |= *in++<<8;
|
||||
b24 |= *in++;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = t64e[(b24)&0x3f];
|
||||
*out++ = enc64chr(b24>>18);
|
||||
*out++ = enc64chr((b24>>12)&0x3f);
|
||||
*out++ = enc64chr((b24>>6)&0x3f);
|
||||
*out++ = enc64chr(b24&0x3f);
|
||||
}
|
||||
|
||||
switch(n%3){
|
||||
case 2:
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in)<<8;
|
||||
b24 = *in++<<16;
|
||||
b24 |= *in<<8;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = enc64chr(b24>>18);
|
||||
*out++ = enc64chr((b24>>12)&0x3f);
|
||||
*out++ = enc64chr((b24>>6)&0x3f);
|
||||
*out++ = '=';
|
||||
break;
|
||||
case 1:
|
||||
b24 = (*in)<<16;
|
||||
b24 = *in<<16;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = enc64chr(b24>>18);
|
||||
*out++ = enc64chr((b24>>12)&0x3f);
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue