blob: 76d4e5800e3c5a709c7608445ed7ec84f4d80be8 [file] [log] [blame]
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
/*#define _POSIX_SOURCE*/
#include <stdio.h>
#include "t_defines.h"
#include "cstr.h"
static int
hexDigitToInt(char c)
{
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
else
return 0;
}
/*
* Convert a hex string to a string of bytes; return size of dst
*/
_TYPE( int )
t_fromhex(char *dst, const char *src)
{
register char *chp = dst;
register unsigned size = strlen(src);
/* FIXME: handle whitespace and non-hex digits by setting size and src
appropriately. */
if(size % 2 == 1) {
*chp++ = hexDigitToInt(*src++);
--size;
}
while(size > 0) {
*chp++ = (hexDigitToInt(*src) << 4) | hexDigitToInt(*(src + 1));
src += 2;
size -= 2;
}
return chp - dst;
}
/*
* Convert a string of bytes to their hex representation
*/
_TYPE( char * )
t_tohex(char *dst, const char *src, unsigned size)
{
int notleading = 0;
register char *chp = dst;
*dst = '\0';
if (size != 0) do {
if(notleading || *src != '\0') {
if(!notleading && (*src & 0xf0) == 0) {
sprintf(chp, "%.1X", * (unsigned char *) src);
chp += 1;
}
else {
sprintf(chp, "%.2X", * (unsigned char *) src);
chp += 2;
}
notleading = 1;
}
++src;
} while (--size != 0);
return dst;
}
_TYPE( char * )
t_tohexcstr(cstr *dst, const char *src, unsigned size)
{
cstr_set_length(dst, 2 * size + 1);
return t_tohex(dst->data, src, size);
}
static char b64table[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
/*
* Convert a base64 string into raw byte array representation.
*/
_TYPE( int )
t_fromb64(char *dst, const char *src)
{
unsigned char *a;
char *loc;
int i, j;
unsigned int size;
while(*src && (*src == ' ' || *src == '\t' || *src == '\n'))
++src;
size = strlen(src);
a = malloc((size + 1) * sizeof(unsigned char));
if(a == (unsigned char *) 0)
return -1;
i = 0;
while(i < size) {
loc = strchr(b64table, src[i]);
if(loc == (char *) 0)
break;
else
a[i] = loc - b64table;
++i;
}
size = i;
i = size - 1;
j = size;
while(1) {
a[j] = a[i];
if(--i < 0)
break;
a[j] |= (a[i] & 3) << 6;
--j;
a[j] = (unsigned char) ((a[i] & 0x3c) >> 2);
if(--i < 0)
break;
a[j] |= (a[i] & 0xf) << 4;
--j;
a[j] = (unsigned char) ((a[i] & 0x30) >> 4);
if(--i < 0)
break;
a[j] |= (a[i] << 2);
a[--j] = 0;
if(--i < 0)
break;
}
while(a[j] == 0 && j <= size)
++j;
memcpy(dst, a + j, size - j + 1);
free(a);
return size - j + 1;
}
_TYPE( int )
t_cstrfromb64(cstr *dst, const char *src)
{
int len;
cstr_set_length(dst, (strlen(src) * 6 + 7) / 8);
len = t_fromb64(dst->data, src);
cstr_set_length(dst, len);
return len;
}
/*
* Convert a raw byte string into a null-terminated base64 ASCII string.
*/
_TYPE( char * )
t_tob64(char *dst, const char *src, unsigned size)
{
int c, pos = size % 3;
unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
char *olddst = dst;
switch(pos) {
case 1:
b2 = src[0];
break;
case 2:
b1 = src[0];
b2 = src[1];
break;
}
while(1) {
c = (b0 & 0xfc) >> 2;
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
c = b2 & 0x3f;
if(notleading || c != 0) {
*dst++ = b64table[c];
notleading = 1;
}
if(pos >= size)
break;
else {
b0 = src[pos++];
b1 = src[pos++];
b2 = src[pos++];
}
}
*dst++ = '\0';
return olddst;
}
_TYPE( char * )
t_tob64cstr(cstr *dst, const char *src, unsigned int sz)
{
cstr_set_length(dst, (sz * 8 + 5) / 6 + 1);
return t_tob64(dst->data, src, sz);
}