| /* |
| * 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); |
| } |