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