1 /* Copyright 1999 Enhanced Software Technologies Inc.
2 * All Rights Reserved
3 *
4 * Released under a BSD-style license. See file LICENSE for info.
5 *
6 * bin2hex.c: binary to hex conversions.
7 *
8 * RCS CHANGE LOG
9 * $Log: bin2hex.c,v $
10 * Revision 1.1.1.1 2001/05/17 17:10:59 elgreen
11 * Initial checkin
12 *
13 * Revision 1.3 2000/12/12 16:41:21 eric
14 * aescrypt 0.6 (large patch by Peter Pentchev).
15 *
16 * Revision 1.2 2000/04/05 22:09:19 eric
17 * Daily checkin...
18 *
19 * Revision 1.1 2000/03/28 23:54:28 eric
20 * Initial checkin -- aescrypt/aesget
21 *
22 * Revision 1.4 1999/12/20 14:51:53 eric
23 * Added dstring.h to headers list.
24 *
25 * Revision 1.3 1999/11/18 16:23:36 eric
26 * More mods to make it work. Start of the 'rsh' functionality.
27 *
28 * Revision 1.2 1999/09/30 20:32:28 eric
29 * Refreshed after Richard foobared the CVS archive
30 *
31 * Revision 1.1 1999/09/23 00:09:34 eric
32 * Initial checkin
33 *
34 *
35 * $Date: 2001/05/17 17:10:59 $
36 */
37
38 /* #define DEBUG 1 */
39
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #include "bin2hex.h"
45 #include "dstring.h"
46
47 static char HEXSTR[]="0123456789ABCDEF";
48
49
unhexnib(unsigned char hexchar)50 unsigned int unhexnib(unsigned char hexchar) {
51 if (hexchar>='0' && hexchar <='9') {
52 return hexchar-'0';
53 }
54 if (hexchar>='A' && hexchar <='F') {
55 return hexchar-'A'+10;
56 }
57 if (hexchar>='a' && hexchar <='f') {
58 return hexchar-'a'+10;
59 }
60 return -1; /* ERROR! */
61 }
62
63
64 /***************************************************************************
65 * STRAIGHT BIG_ENDIAN FUNCTIONS
66 ***************************************************************************
67 * These do not attempt to switch between big endian/little endian byte
68 * order. We use these mostly when we are hexifying stuff that was
69 * created by mpz_t or etc...
70 **************************************************************************/
71
hexify_block(unsigned char * resultbuf,int length)72 unsigned char *hexify_block( unsigned char *resultbuf, int length ) {
73 unsigned char *resultstr;
74 int i;
75 int leftnib;
76 int rightnib;
77 unsigned int ch;
78
79 resultstr= (unsigned char *)malloc(length*2+1); /* 16 bytes * 2 + terminator */
80
81 /* if big endian, start at beginning & go up */
82 for (i=0;i<length;i++) {
83 ch=(unsigned int) *resultbuf++;
84 leftnib= (ch >> 4) & 0x0f ;
85 rightnib = ch & 0x0f;
86 resultstr[i*2]=HEXSTR[leftnib];
87 resultstr[i*2+1]=HEXSTR[rightnib];
88 }
89 resultstr[length*2]=0; /* terminate it! */
90 return resultstr;
91
92 }
93
94 /* Okay, new design: unhexify_block was not working right :-(. Thus
95 * here's what I am going to do:
96 * 1) take the incoming hex string and massage it to the right length
97 * 2) Do a straight left-to-right hex to decimal conversion!
98 */
99
unhexify_block(char * str,int length)100 char *unhexify_block(char *str, int length) {
101 char *source;
102 char *result;
103
104 int hexlen=length*2;
105 int len=strlen(str);
106
107 int i;
108
109 unsigned int ch;
110 int leftnib;
111 int rightnib;
112
113 /* Now to do it: */
114 result=(char *)malloc(length);
115
116 if (len < hexlen) {
117 source=d_lpad(str,'0',hexlen);
118 } else {
119 source=d_dup(str);
120 source[hexlen]=0; /* chop off the right hand side if needed! */
121 }
122
123 #ifdef DEBUG
124 printf("hex2bin: length=%d, source='%s'\n",length,source);
125 #endif
126 /* Now do straight left to right: */
127 for (i=0;i<length;i++) {
128 leftnib=unhexnib(source[i*2]);
129 rightnib=unhexnib(source[i*2+1]);
130 ch=(leftnib <<4) | rightnib;
131 #ifdef DEBUGDEBUG
132 printf("hex2bin: ch[%d]=%x\n",i,ch);
133 #endif
134 result[i]=(unsigned char) ch; /* voila! */
135 }
136
137 free(source); /* Get rid of memory leak! */
138
139 /* and return! */
140 return result;
141 }
142
143 #ifdef FOOFOOFOO
144
unhexify_block(unsigned char * str,int length)145 unsigned char *unhexify_block(unsigned char *str, int length) {
146 unsigned char *source;
147 unsigned char *result;
148 int hexlen = length*2;
149 int i;
150
151 unsigned int ch;
152 int leftnib;
153 int rightnib;
154
155
156 unsigned char *resultwalk;
157 unsigned char *strwalk;
158
159 if (strlen(str) < hexlen) {
160 source=d_lpad(str,'0',hexlen);
161 } else {
162 source=d_dup(str);
163 }
164
165 /* now allocate our space: */
166 result=(char *) malloc(length); /* has to be that length, divided by two. */
167 memset(result,0,length);
168
169 /* We always do big_endian, meaning that we must start at the LSB and come
170 * backwards to make sure we don't leave trailing zeros.
171 */
172 resultwalk=result+length-1;
173 strwalk=str+strlen(str)-2;
174 for (i=0;i<length;i++) {
175 leftnib=unhexnib(*strwalk++);
176 rightnib=unhexnib(*strwalk--);
177 strwalk-=2; /* go to previous... */
178 ch=(leftnib << 4) | rightnib;
179 *resultwalk-- = (unsigned char) ch; /* and set it! */
180 }
181 return result;
182 }
183 #endif
184