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