1 /* util.c
2 * Copyright (C) 2001, 2009, 2012 g10 Code GmbH
3 *
4 * This file is part of KSBA.
5 *
6 * KSBA is free software; you can redistribute it and/or modify
7 * it under the terms of either
8 *
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
12 *
13 * or
14 *
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
18 *
19 * or both in parallel, as here.
20 *
21 * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 * License for more details.
25 *
26 * You should have received a copies of the GNU General Public License
27 * and the GNU Lesser General Public License along with this program;
28 * if not, see <http://www.gnu.org/licenses/>.
29 */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <errno.h>
37
38 #include "util.h"
39
40 static void *(*alloc_func)(size_t n) = malloc;
41 static void *(*realloc_func)(void *p, size_t n) = realloc;
42 static void (*free_func)(void*) = free;
43 static gpg_error_t (*hash_buffer_fnc)(void *arg, const char *oid,
44 const void *buffer, size_t length,
45 size_t resultsize,
46 unsigned char *result, size_t *resultlen);
47 static void *hash_buffer_fnc_arg;
48
49
50
51 /* Note, that we expect that the free fucntion does not change
52 ERRNO. */
53 void
ksba_set_malloc_hooks(void * (* new_alloc_func)(size_t n),void * (* new_realloc_func)(void * p,size_t n),void (* new_free_func)(void *))54 ksba_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
55 void *(*new_realloc_func)(void *p, size_t n),
56 void (*new_free_func)(void*) )
57 {
58 alloc_func = new_alloc_func;
59 realloc_func = new_realloc_func;
60 free_func = new_free_func;
61 }
62
63
64 /* Register a has function for general use by libksba. This is
65 required to avoid dependencies to specific low-level
66 crypolibraries. The function should be used right at the startup
67 of the main program, similar to ksba_set_malloc_hooks.
68
69 The function provided should behave like this:
70
71 gpg_error_t hash_buffer (void *arg, const char *oid,
72 const void *buffer, size_t length,
73 size_t resultsize,
74 unsigned char *result,
75 size_t *resultlen);
76
77 Where ARG is the same pointer as set along with the fucntion, OID
78 is an OID string telling the hash algorithm to be used - SHA-1
79 shall be used if OID is NULL. The text to hash is expected in
80 BUFFER of LENGTH and the result will be placed into the provided
81 buffer RESULT which has been allocated by the caller with at LEAST
82 RESULTSIZE bytes; the actual length of the result is put into
83 RESULTLEN.
84
85 The function shall return 0 on success or any other appropriate
86 gpg-error.
87 */
88 void
ksba_set_hash_buffer_function(gpg_error_t (* fnc)(void * arg,const char * oid,const void * buffer,size_t length,size_t resultsize,unsigned char * result,size_t * resultlen),void * fnc_arg)89 ksba_set_hash_buffer_function ( gpg_error_t (*fnc)
90 (void *arg, const char *oid,
91 const void *buffer, size_t length,
92 size_t resultsize,
93 unsigned char *result,
94 size_t *resultlen),
95 void *fnc_arg)
96 {
97 hash_buffer_fnc = fnc;
98 hash_buffer_fnc_arg = fnc_arg;
99 }
100
101 /* Hash BUFFER of LENGTH bytes using the algorithjm denoted by OID,
102 where OID may be NULL to demand the use od SHA-1. The resulting
103 digest will be placed in the provided buffer RESULT which must have
104 been allocated by the caller with at LEAST RESULTSIZE bytes; the
105 actual length of the result is put into RESULTLEN.
106
107 The function shall return 0 on success or any other appropriate
108 gpg-error.
109 */
110 gpg_error_t
_ksba_hash_buffer(const char * oid,const void * buffer,size_t length,size_t resultsize,unsigned char * result,size_t * resultlen)111 _ksba_hash_buffer (const char *oid, const void *buffer, size_t length,
112 size_t resultsize, unsigned char *result, size_t *resultlen)
113 {
114 if (!hash_buffer_fnc)
115 return gpg_error (GPG_ERR_CONFIGURATION);
116 return hash_buffer_fnc (hash_buffer_fnc_arg, oid, buffer, length,
117 resultsize, result, resultlen);
118 }
119
120
121 /* Wrapper for the common memory allocation functions. These are here
122 so that we can add hooks. The corresponding macros should be used.
123 These macros are not named xfoo() because this name is commonly
124 used for function which die on errror. We use macronames like
125 xtryfoo() instead. */
126
127 void *
ksba_malloc(size_t n)128 ksba_malloc (size_t n )
129 {
130 return alloc_func (n);
131 }
132
133 void *
ksba_calloc(size_t n,size_t m)134 ksba_calloc (size_t n, size_t m )
135 {
136 size_t nbytes;
137 void *p;
138
139 nbytes = n * m;
140 if ( m && nbytes / m != n)
141 {
142 gpg_err_set_errno (ENOMEM);
143 p = NULL;
144 }
145 else
146 p = ksba_malloc (nbytes);
147 if (p)
148 memset (p, 0, nbytes);
149 return p;
150 }
151
152 void *
ksba_realloc(void * mem,size_t n)153 ksba_realloc (void *mem, size_t n)
154 {
155 return realloc_func (mem, n );
156 }
157
158
159 char *
ksba_strdup(const char * str)160 ksba_strdup (const char *str)
161 {
162 char *p = ksba_malloc (strlen(str)+1);
163 if (p)
164 strcpy (p, str);
165 return p;
166 }
167
168
169 /* This is safe version of realloc useful for reallocing a calloced
170 * array. There are two ways to call it: The first example
171 * reallocates the array A to N elements each of SIZE but does not
172 * clear the newly allocated elements:
173 *
174 * p = _ksba_reallocarray (a, n, n, nsize);
175 *
176 * Note that when NOLD is larger than N no cleaning is needed anyway.
177 * The second example reallocates an array of size NOLD to N elements
178 * each of SIZE but clear the newly allocated elements:
179 *
180 * p = _ksba_reallocarray (a, nold, n, nsize);
181 *
182 * Note that gpgrt_reallocarray (NULL, 0, n, nsize) is equivalent to
183 * _ksba_calloc (n, nsize).
184 *
185 */
186 void *
_ksba_reallocarray(void * a,size_t oldnmemb,size_t nmemb,size_t size)187 _ksba_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size)
188 {
189 size_t oldbytes, bytes;
190 char *p;
191
192 bytes = nmemb * size; /* size_t is unsigned so the behavior on overflow
193 * is defined. */
194 if (size && bytes / size != nmemb)
195 {
196 gpg_err_set_errno (ENOMEM);
197 return NULL;
198 }
199
200 p = ksba_realloc (a, bytes);
201 if (p && oldnmemb < nmemb)
202 {
203 /* OLDNMEMBS is lower than NMEMB thus the user asked for a
204 calloc. Clear all newly allocated members. */
205 oldbytes = oldnmemb * size;
206 if (size && oldbytes / size != oldnmemb)
207 {
208 xfree (p);
209 gpg_err_set_errno (ENOMEM);
210 return NULL;
211 }
212 memset (p + oldbytes, 0, bytes - oldbytes);
213 }
214 return p;
215 }
216
217
218 void
ksba_free(void * a)219 ksba_free ( void *a )
220 {
221 if (a)
222 free_func (a);
223 }
224
225
226 static void
out_of_core(void)227 out_of_core(void)
228 {
229 fputs ("\nfatal: out of memory\n", stderr );
230 exit (2);
231 }
232
233
234 /* Implementations of the common xfoo() memory allocation functions */
235 void *
_ksba_xmalloc(size_t n)236 _ksba_xmalloc (size_t n )
237 {
238 void *p = ksba_malloc (n);
239 if (!p)
240 out_of_core();
241 return p;
242 }
243
244 void *
_ksba_xcalloc(size_t n,size_t m)245 _ksba_xcalloc (size_t n, size_t m )
246 {
247 void *p = ksba_calloc (n,m);
248 if (!p)
249 out_of_core();
250 return p;
251 }
252
253 void *
_ksba_xrealloc(void * mem,size_t n)254 _ksba_xrealloc (void *mem, size_t n)
255 {
256 void *p = ksba_realloc (mem,n);
257 if (!p)
258 out_of_core();
259 return p;
260 }
261
262
263 char *
_ksba_xstrdup(const char * str)264 _ksba_xstrdup (const char *str)
265 {
266 char *p = ksba_strdup (str);
267 if (!p)
268 out_of_core();
269 return p;
270 }
271
272
273 #ifndef HAVE_STPCPY
274 char *
_ksba_stpcpy(char * a,const char * b)275 _ksba_stpcpy (char *a,const char *b)
276 {
277 while (*b)
278 *a++ = *b++;
279 *a = 0;
280
281 return a;
282 }
283 #endif
284
285
286 static inline int
ascii_toupper(int c)287 ascii_toupper (int c)
288 {
289 if (c >= 'a' && c <= 'z')
290 c &= ~0x20;
291 return c;
292 }
293
294
295 int
_ksba_ascii_memcasecmp(const void * a_arg,const void * b_arg,size_t n)296 _ksba_ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n)
297 {
298 const char *a = a_arg;
299 const char *b = b_arg;
300
301 if (a == b)
302 return 0;
303 for ( ; n; n--, a++, b++ )
304 {
305 if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b))
306 return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
307 }
308 return 0;
309 }
310