File Coverage

inc/matrixssl-3-9-3-open/crypto/keyformat/asn1fmt.c
Criterion Covered Total %
statement 0 113 0.0
branch 0 66 0.0
condition n/a
subroutine n/a
pod n/a
total 0 179 0.0


line stmt bran cond sub pod time code
1             /**
2             * @file x509dbg.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * ASN.1 Parsing: convenience functions for formatting ASN.1.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; you can redistribute it and/or modify
15             * it under the terms of the GNU General Public License as published by
16             * the Free Software Foundation; either version 2 of the License, or
17             * (at your option) any later version.
18             *
19             * This General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #if !defined USE_X509 && !defined USE_OCSP
36             # include "../cryptoImpl.h" /* MatrixSSL API interface and configuration. */
37             #endif
38              
39             #if (defined USE_X509 && defined USE_FULL_CERT_PARSE) || defined USE_OCSP
40              
41             # include /* for snprintf() */
42             # include /* for strlen() */
43              
44             /* Constants used in OID formatting code. */
45             # define OID_STR_BUF_LEN (129 * 4) /* Temporary string length. */
46             # define OID_STR_MAX_SEQ_LEN 64 /* Maximum octets in sequence. */
47              
48             /* Access bitarray containing 7 bits of data per octet. */
49 0           static unsigned char oid_get_bit7(const unsigned char *bitarray,
50             size_t n, int i)
51             {
52             unsigned char byte;
53 0           size_t a = (size_t) (i / 7);
54 0           int bitidx = i % 7;
55              
56 0 0         if (n <= a)
57             {
58 0           return 0;
59             }
60              
61 0           byte = bitarray[n - a - 1];
62 0           byte >>= bitidx;
63 0           return byte & 1;
64             }
65              
66             /* Perform conversion between OID encoded data (i.e. BER compressed
67             integer like perl pack("w"), and a long sequence of octets. */
68             static
69 0           unsigned int oid_double_dabble_workhorse(const unsigned char *b,
70             size_t n,
71             unsigned char t[],
72             int v_bits, size_t t_bytes)
73             {
74             int i;
75             size_t j;
76             unsigned int x;
77 0           unsigned int overflow = 0;
78 0           size_t t_bcdbytes = (t_bytes + 1) / 2;
79              
80 0 0         for (j = t_bcdbytes; j-- > 0; )
81             {
82 0           t[j] = 0;
83             }
84              
85             /* Compute BCD corresponding with Buc_p.
86             (double-dabble algorithm). */
87 0 0         for (i = v_bits; i-- > 0; )
88             {
89 0           unsigned char c = oid_get_bit7(b, n, i);
90 0           x = c;
91 0 0         for (j = t_bcdbytes; j-- > 0; )
92             {
93 0           x += (2 * (unsigned int) t[j]);
94 0           t[j] = x & 255;
95 0           x >>= 8;
96             }
97 0           overflow |= x;
98 0 0         if (i == 0)
99             {
100 0           break;
101             }
102 0 0         for (j = t_bcdbytes; j-- > 0; )
103             {
104             unsigned char a, add51, m;
105 0           a = t[j];
106 0           add51 = a + 51;
107 0           m = add51 & 0x88;
108 0           m |= m >> 2;
109 0           m |= m >> 1;
110 0           t[j] = (a & ~m) | (add51 & m);
111             }
112             }
113              
114             /* Convert BCD to decimal. */
115 0 0         if ((t_bytes & 1) == 1)
116             {
117             /* The result is shifted 4 bits; fix it. */
118 0           overflow |= t[0] >> 4;
119 0 0         for (j = t_bytes; j-- > 0; )
120             {
121 0 0         if (j & 1)
122             {
123 0           t[j] = '0' + (t[j / 2 + 1] >> 4);
124             }
125             else
126             {
127 0           t[j] = '0' + (t[j / 2] & 15);
128             }
129             }
130             }
131             else
132             {
133 0 0         for (j = t_bytes; j-- > 0; )
134             {
135 0 0         if (j & 1)
136             {
137 0           t[j] = '0' + (t[j / 2] & 15);
138             }
139             else
140             {
141 0           t[j] = '0' + (t[j / 2] >> 4);
142             }
143             }
144             }
145              
146 0           return overflow;
147             }
148              
149             /* Append to string s (assumed sufficiently long) a contiguous segment of
150             BER compressed integer like perl pack("w") unpacked. This function
151             processes at most 64 bytes at once (i.e. up-to 72683872429560689054932380
152             7888004534353641360687318060281490199180639288113397923326191050713763565
153             560762521606266177933534601628614655).
154             This range is sufficient for typical OIDs as well as UUID-based OIDs.
155             */
156 0           static size_t oid_part_append(char *s, const unsigned char *oid, size_t oidlen)
157             {
158             size_t pos;
159             unsigned long long ll;
160 0           const unsigned char *oid_orig = oid;
161              
162             /* The most common case: single byte oid segment. */
163 0 0         if (*oid < 128)
164             {
165 0           sprintf(s, ".%d", *oid);
166 0           return 1;
167             }
168 0 0         else if (*oid == 128)
169             {
170             /* Illegal: One of the highest bits shall be set. */
171 0           return 0;
172             }
173              
174             /* Handle oid parts smaller than 2**64-1. */
175 0           ll = *oid & 127;
176 0           pos = 1;
177 0 0         while (pos < oidlen)
178             {
179 0           oid++;
180 0           ll *= 128;
181 0           ll += *oid & 127;
182 0 0         if (*oid < 128)
183             {
184 0 0         if (pos < 8)
185             {
186 0           sprintf(s, ".%llu", ll);
187 0           return pos + 1;
188             }
189 0 0         else if (pos < OID_STR_MAX_SEQ_LEN)
190             {
191             size_t plen;
192             size_t ilen;
193             /* Precision may exceed capacity of unsigned long long.
194             Use variant of double-dabble that can do arbitrary
195             precision. */
196 0           pos += 1;
197 0           *s = '.';
198 0           memset(s + 1, 0, pos * 3 + 1);
199 0           oid_double_dabble_workhorse(oid_orig, pos,
200             (unsigned char *) (s + 1),
201             pos * 8, pos * 3);
202              
203             /* The string formatting generates extra zeroes. Remove them. */
204 0           s += 1; /* Skip '.' */
205 0           ilen = strlen(s);
206 0           plen = 0;
207 0 0         while (plen < ilen && plen < ilen - 1 && s[plen] == '0')
    0          
    0          
208             {
209 0           plen++;
210             }
211             /* Remove initial zeroes. */
212 0           memmove(s, s + plen, ilen + 1 - plen);
213 0           return pos;
214             }
215             else
216             {
217             /* Single OID component exceeds sizes required for any
218             known uses. These are not handled. */
219 0           return 0;
220             }
221             }
222 0           pos++;
223             }
224              
225 0           return 0; /* Unable to process. */
226             }
227              
228             /* Decrement 1 from number expressed in ascii. */
229 0           static void oid_asciidec(char *s, size_t l)
230             {
231             size_t i;
232 0           int dec = 1;
233              
234 0 0         for (i = l; i-- > 0; )
235             {
236 0           s[i] -= dec;
237 0 0         if (s[i] < '0')
238             {
239 0           s[i] = '9';
240             }
241             else
242             {
243 0           dec = 0;
244             }
245             }
246 0           }
247              
248             /* Format OID to string buffer. Returns position within the buffer
249             on successful execution or NULL on failure. */
250 0           static char *oid_to_string(const unsigned char *oid, size_t oidlen,
251             char str[OID_STR_BUF_LEN])
252             {
253 0           char *s = str;
254 0           int prefix = 0; /* Ignored bytes in beginning. */
255              
256 0           str[0] = 0;
257             /* Only process OID identifiers, and up-to 129 bytes long, with
258             correct length identifier. */
259 0 0         if (oidlen < 3 || oidlen > 129 || oid[0] != 0x06 || oid[1] != oidlen - 2)
    0          
    0          
    0          
260             {
261 0           return NULL;
262             }
263 0 0         if (oid[2] < 120)
264             {
265             /* Simple case, [012].x where x < 40. */
266 0           sprintf(s, "%d.%d", oid[2] / 40, oid[2] % 40);
267 0           s += strlen(s);
268 0           oid += 3;
269 0           oidlen -= 3;
270             }
271             else
272             {
273             /* Process 2.xxx, where xxx is arbitrary length number >= 40. */
274 0           size_t bytes = oid_part_append(s + 1, oid + 2, oidlen - 2);
275             int i;
276              
277 0 0         if (bytes < 2)
278             {
279 0           return NULL;
280             }
281              
282             /* Decrement tens eight time. */
283 0 0         for (i = 0; i < 8; i++)
284             {
285 0           oid_asciidec(s + 2, strlen(s + 2) - 1);
286             }
287              
288             /* Check if there were extra zeroes in s[2]. */
289 0 0         while (strlen(s + 2) && s[2] == '0')
    0          
290             {
291 0           s++;
292 0           prefix++;
293             }
294              
295 0           s[0] = '2';
296 0           s[1] = '.';
297 0           s += strlen(s);
298 0           oid += 2 + bytes;
299 0           oidlen -= 2 + bytes;
300             }
301 0 0         while (oidlen > 0)
302             {
303 0           size_t bytes = oid_part_append(s, oid, oidlen);
304 0 0         if (bytes == 0)
305             {
306 0           return NULL;
307             }
308 0           oidlen -= bytes;
309 0           oid += bytes;
310 0           s += strlen(s);
311             }
312 0           return str + prefix;
313             }
314              
315             # ifndef NO_ASN_FORMAT_OID
316             char *asnFormatOid(psPool_t *pool,
317             const unsigned char *oid, size_t oidlen)
318             {
319             /* Perform formatting for oid. */
320             char *out;
321             char str_tmp[OID_STR_BUF_LEN];
322             char *str = oid_to_string(oid, oidlen, str_tmp);
323              
324             if (str == NULL)
325             {
326             return NULL;
327             }
328              
329             /* Allocate dynamically new memory for the result. */
330             out = psMalloc(pool, strlen(str) + 1);
331             if (out)
332             {
333             memcpy(out, str, strlen(str) + 1);
334             }
335             return out;
336             }
337             # endif /* NO_ASN_FORMAT_OID */
338              
339             #endif /* compilation selector: full X.509 or OCSP enabled */
340