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