1/*++ 2/* NAME 3/* hex_code 3 4/* SUMMARY 5/* encode/decode data, hexadecimal style 6/* SYNOPSIS 7/* #include <hex_code.h> 8/* 9/* VSTRING *hex_encode(result, in, len) 10/* VSTRING *result; 11/* const char *in; 12/* ssize_t len; 13/* 14/* VSTRING *hex_decode(result, in, len) 15/* VSTRING *result; 16/* const char *in; 17/* ssize_t len; 18/* DESCRIPTION 19/* hex_encode() takes a block of len bytes and encodes it as one 20/* upper-case null-terminated string. The result value is 21/* the result argument. 22/* 23/* hex_decode() performs the opposite transformation on 24/* lower-case, upper-case or mixed-case input. The result 25/* value is the result argument. The result is null terminated, 26/* whether or not that makes sense. 27/* DIAGNOSTICS 28/* hex_decode() returns a null pointer when the input contains 29/* characters not in the hexadecimal alphabet. 30/* LICENSE 31/* .ad 32/* .fi 33/* The Secure Mailer license must be distributed with this software. 34/* AUTHOR(S) 35/* Wietse Venema 36/* IBM T.J. Watson Research 37/* P.O. Box 704 38/* Yorktown Heights, NY 10598, USA 39/*--*/ 40 41/* System library. */ 42 43#include <sys_defs.h> 44#include <ctype.h> 45#include <string.h> 46 47/* Utility library. */ 48 49#include <msg.h> 50#include <mymalloc.h> 51#include <vstring.h> 52#include <hex_code.h> 53 54/* Application-specific. */ 55 56static const unsigned char hex_chars[] = "0123456789ABCDEF"; 57 58#define UCHAR_PTR(x) ((const unsigned char *)(x)) 59 60/* hex_encode - raw data to encoded */ 61 62VSTRING *hex_encode(VSTRING *result, const char *in, ssize_t len) 63{ 64 const unsigned char *cp; 65 int ch; 66 ssize_t count; 67 68 VSTRING_RESET(result); 69 for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) { 70 ch = *cp; 71 VSTRING_ADDCH(result, hex_chars[(ch >> 4) & 0xf]); 72 VSTRING_ADDCH(result, hex_chars[ch & 0xf]); 73 } 74 VSTRING_TERMINATE(result); 75 return (result); 76} 77 78/* hex_decode - encoded data to raw */ 79 80VSTRING *hex_decode(VSTRING *result, const char *in, ssize_t len) 81{ 82 const unsigned char *cp; 83 ssize_t count; 84 unsigned int hex; 85 unsigned int bin; 86 87 VSTRING_RESET(result); 88 for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) { 89 if (count < 2) 90 return (0); 91 hex = cp[0]; 92 if (hex >= '0' && hex <= '9') 93 bin = (hex - '0') << 4; 94 else if (hex >= 'A' && hex <= 'F') 95 bin = (hex - 'A' + 10) << 4; 96 else if (hex >= 'a' && hex <= 'f') 97 bin = (hex - 'a' + 10) << 4; 98 else 99 return (0); 100 hex = cp[1]; 101 if (hex >= '0' && hex <= '9') 102 bin |= (hex - '0'); 103 else if (hex >= 'A' && hex <= 'F') 104 bin |= (hex - 'A' + 10); 105 else if (hex >= 'a' && hex <= 'f') 106 bin |= (hex - 'a' + 10); 107 else 108 return (0); 109 VSTRING_ADDCH(result, bin); 110 } 111 VSTRING_TERMINATE(result); 112 return (result); 113} 114 115#ifdef TEST 116 117 /* 118 * Proof-of-concept test program: convert to hexadecimal and back. 119 */ 120 121#define STR(x) vstring_str(x) 122#define LEN(x) VSTRING_LEN(x) 123 124int main(int unused_argc, char **unused_argv) 125{ 126 VSTRING *b1 = vstring_alloc(1); 127 VSTRING *b2 = vstring_alloc(1); 128 char *test = "this is a test"; 129 130#define DECODE(b,x,l) { \ 131 if (hex_decode((b),(x),(l)) == 0) \ 132 msg_panic("bad hex: %s", (x)); \ 133 } 134#define VERIFY(b,t) { \ 135 if (strcmp((b), (t)) != 0) \ 136 msg_panic("bad test: %s", (b)); \ 137 } 138 139 hex_encode(b1, test, strlen(test)); 140 DECODE(b2, STR(b1), LEN(b1)); 141 VERIFY(STR(b2), test); 142 143 hex_encode(b1, test, strlen(test)); 144 hex_encode(b2, STR(b1), LEN(b1)); 145 hex_encode(b1, STR(b2), LEN(b2)); 146 DECODE(b2, STR(b1), LEN(b1)); 147 DECODE(b1, STR(b2), LEN(b2)); 148 DECODE(b2, STR(b1), LEN(b1)); 149 VERIFY(STR(b2), test); 150 151 hex_encode(b1, test, strlen(test)); 152 hex_encode(b2, STR(b1), LEN(b1)); 153 hex_encode(b1, STR(b2), LEN(b2)); 154 hex_encode(b2, STR(b1), LEN(b1)); 155 hex_encode(b1, STR(b2), LEN(b2)); 156 DECODE(b2, STR(b1), LEN(b1)); 157 DECODE(b1, STR(b2), LEN(b2)); 158 DECODE(b2, STR(b1), LEN(b1)); 159 DECODE(b1, STR(b2), LEN(b2)); 160 DECODE(b2, STR(b1), LEN(b1)); 161 VERIFY(STR(b2), test); 162 163 vstring_free(b1); 164 vstring_free(b2); 165 return (0); 166} 167 168#endif 169