1 /*
2  * util.c
3  *
4  * Utilities used by the test apps
5  *
6  * John A. Foley
7  * Cisco Systems, Inc.
8  */
9 /*
10  *
11  * Copyright (c) 2014-2017, Cisco Systems, Inc.
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  *
18  *   Redistributions of source code must retain the above copyright
19  *   notice, this list of conditions and the following disclaimer.
20  *
21  *   Redistributions in binary form must reproduce the above
22  *   copyright notice, this list of conditions and the following
23  *   disclaimer in the documentation and/or other materials provided
24  *   with the distribution.
25  *
26  *   Neither the name of the Cisco Systems, Inc. nor the names of its
27  *   contributors may be used to endorse or promote products derived
28  *   from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41  * OF THE POSSIBILITY OF SUCH DAMAGE.
42  *
43  */
44 
45 #include "util.h"
46 
47 #include <string.h>
48 #include <stdint.h>
49 
50 char bit_string[MAX_PRINT_STRING_LEN];
51 
hex_char_to_nibble(uint8_t c)52 static inline int hex_char_to_nibble(uint8_t c)
53 {
54     switch (c) {
55     case ('0'):
56         return 0x0;
57     case ('1'):
58         return 0x1;
59     case ('2'):
60         return 0x2;
61     case ('3'):
62         return 0x3;
63     case ('4'):
64         return 0x4;
65     case ('5'):
66         return 0x5;
67     case ('6'):
68         return 0x6;
69     case ('7'):
70         return 0x7;
71     case ('8'):
72         return 0x8;
73     case ('9'):
74         return 0x9;
75     case ('a'):
76         return 0xa;
77     case ('A'):
78         return 0xa;
79     case ('b'):
80         return 0xb;
81     case ('B'):
82         return 0xb;
83     case ('c'):
84         return 0xc;
85     case ('C'):
86         return 0xc;
87     case ('d'):
88         return 0xd;
89     case ('D'):
90         return 0xd;
91     case ('e'):
92         return 0xe;
93     case ('E'):
94         return 0xe;
95     case ('f'):
96         return 0xf;
97     case ('F'):
98         return 0xf;
99     default:
100         return -1; /* this flags an error */
101     }
102     /* NOTREACHED */
103     return -1; /* this keeps compilers from complaining */
104 }
105 
nibble_to_hex_char(uint8_t nibble)106 uint8_t nibble_to_hex_char(uint8_t nibble)
107 {
108     char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
109                      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
110 
111     return buf[nibble & 0xF];
112 }
113 
114 /*
115  * hex_string_to_octet_string converts a hexadecimal string
116  * of length 2 * len to a raw octet string of length len
117  */
hex_string_to_octet_string(char * raw,char * hex,int len)118 int hex_string_to_octet_string(char *raw, char *hex, int len)
119 {
120     uint8_t x;
121     int tmp;
122     int hex_len;
123 
124     hex_len = 0;
125     while (hex_len < len) {
126         tmp = hex_char_to_nibble(hex[0]);
127         if (tmp == -1) {
128             return hex_len;
129         }
130         x = (tmp << 4);
131         hex_len++;
132         tmp = hex_char_to_nibble(hex[1]);
133         if (tmp == -1) {
134             return hex_len;
135         }
136         x |= (tmp & 0xff);
137         hex_len++;
138         *raw++ = x;
139         hex += 2;
140     }
141     return hex_len;
142 }
143 
octet_string_hex_string(const void * s,int length)144 char *octet_string_hex_string(const void *s, int length)
145 {
146     const uint8_t *str = (const uint8_t *)s;
147     int i;
148 
149     /* double length, since one octet takes two hex characters */
150     length *= 2;
151 
152     /* truncate string if it would be too long */
153     if (length > MAX_PRINT_STRING_LEN) {
154         length = MAX_PRINT_STRING_LEN - 1;
155     }
156 
157     for (i = 0; i < length; i += 2) {
158         bit_string[i] = nibble_to_hex_char(*str >> 4);
159         bit_string[i + 1] = nibble_to_hex_char(*str++ & 0xF);
160     }
161     bit_string[i] = 0; /* null terminate string */
162     return bit_string;
163 }
164 
165 static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
166                                "abcdefghijklmnopqrstuvwxyz0123456789+/";
167 
base64_block_to_octet_triple(char * out,char * in)168 static int base64_block_to_octet_triple(char *out, char *in)
169 {
170     unsigned char sextets[4] = { 0 };
171     int j = 0;
172     int i;
173 
174     for (i = 0; i < 4; i++) {
175         char *p = strchr(b64chars, in[i]);
176         if (p != NULL) {
177             sextets[i] = p - b64chars;
178         } else {
179             j++;
180         }
181     }
182 
183     out[0] = (sextets[0] << 2) | (sextets[1] >> 4);
184     if (j < 2) {
185         out[1] = (sextets[1] << 4) | (sextets[2] >> 2);
186     }
187     if (j < 1) {
188         out[2] = (sextets[2] << 6) | sextets[3];
189     }
190     return j;
191 }
192 
base64_string_to_octet_string(char * out,int * pad,char * in,int len)193 int base64_string_to_octet_string(char *out, int *pad, char *in, int len)
194 {
195     int k = 0;
196     int i = 0;
197     int j = 0;
198 
199     if (len % 4 != 0) {
200         return 0;
201     }
202 
203     while (i < len && j == 0) {
204         j = base64_block_to_octet_triple(out + k, in + i);
205         k += 3;
206         i += 4;
207     }
208     *pad = j;
209     return i;
210 }
211