xref: /openssl/crypto/o_str.c (revision ca3c6f38)
1 /*
2  * Copyright 2003-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include "internal/e_os.h"
11 #include <string.h>
12 #include <limits.h>
13 #include <openssl/crypto.h>
14 #include "crypto/ctype.h"
15 #include "internal/cryptlib.h"
16 #include "internal/thread_once.h"
17 #include "internal/to_hex.h"
18 
19 #define DEFAULT_SEPARATOR ':'
20 #define CH_ZERO '\0'
21 
CRYPTO_strdup(const char * str,const char * file,int line)22 char *CRYPTO_strdup(const char *str, const char* file, int line)
23 {
24     char *ret;
25 
26     if (str == NULL)
27         return NULL;
28     ret = CRYPTO_malloc(strlen(str) + 1, file, line);
29     if (ret != NULL)
30         strcpy(ret, str);
31     return ret;
32 }
33 
CRYPTO_strndup(const char * str,size_t s,const char * file,int line)34 char *CRYPTO_strndup(const char *str, size_t s, const char* file, int line)
35 {
36     size_t maxlen;
37     char *ret;
38 
39     if (str == NULL)
40         return NULL;
41 
42     maxlen = OPENSSL_strnlen(str, s);
43 
44     ret = CRYPTO_malloc(maxlen + 1, file, line);
45     if (ret) {
46         memcpy(ret, str, maxlen);
47         ret[maxlen] = CH_ZERO;
48     }
49     return ret;
50 }
51 
CRYPTO_memdup(const void * data,size_t siz,const char * file,int line)52 void *CRYPTO_memdup(const void *data, size_t siz, const char* file, int line)
53 {
54     void *ret;
55 
56     if (data == NULL || siz >= INT_MAX)
57         return NULL;
58 
59     ret = CRYPTO_malloc(siz, file, line);
60     if (ret == NULL)
61         return NULL;
62     return memcpy(ret, data, siz);
63 }
64 
OPENSSL_strnlen(const char * str,size_t maxlen)65 size_t OPENSSL_strnlen(const char *str, size_t maxlen)
66 {
67     const char *p;
68 
69     for (p = str; maxlen-- != 0 && *p != CH_ZERO; ++p) ;
70 
71     return p - str;
72 }
73 
OPENSSL_strlcpy(char * dst,const char * src,size_t size)74 size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size)
75 {
76     size_t l = 0;
77     for (; size > 1 && *src; size--) {
78         *dst++ = *src++;
79         l++;
80     }
81     if (size)
82         *dst = CH_ZERO;
83     return l + strlen(src);
84 }
85 
OPENSSL_strlcat(char * dst,const char * src,size_t size)86 size_t OPENSSL_strlcat(char *dst, const char *src, size_t size)
87 {
88     size_t l = 0;
89     for (; size > 0 && *dst; size--, dst++)
90         l++;
91     return l + OPENSSL_strlcpy(dst, src, size);
92 }
93 
94 /**
95  * @brief Converts a string to an unsigned long integer.
96  *
97  * This function attempts to convert a string representation of a number
98  * to an unsigned long integer, given a specified base. It also provides
99  * error checking and reports whether the conversion was successful.
100  * This function is just a wrapper around the POSIX strtoul function with
101  * additional error checking.  This implies that errno for the caller is set
102  * on calls to this function.
103  *
104  * @param str The string containing the representation of the number.
105  * @param endptr A pointer to a pointer to character. If not NULL, it is set
106  *               to the character immediately following the number in the
107  *               string.
108  * @param base The base to use for the conversion, which must be between 2,
109  *             and 36 inclusive, or be the special value 0. If the base is 0,
110  *             the actual base is determined by the format of the initial
111  *             characters of the string.
112  * @param num A pointer to an unsigned long where the result of the
113  *            conversion is stored.
114  *
115  * @return 1 if the conversion was successful, 0 otherwise. Conversion is
116  *         considered unsuccessful if no digits were consumed or if an error
117  *         occurred during conversion.
118  *
119  * @note It is the caller's responsibility to check if the conversion is
120  *       correct based on the expected consumption of the string as reported
121  *       by endptr.
122  */
OPENSSL_strtoul(const char * str,char ** endptr,int base,unsigned long * num)123 int OPENSSL_strtoul(const char *str, char **endptr, int base,
124                     unsigned long *num)
125 {
126     char *tmp_endptr;
127     char **internal_endptr = endptr == NULL ? &tmp_endptr : endptr;
128 
129     errno = 0;
130 
131     *internal_endptr = (char *)str;
132 
133     if (num == NULL)
134         return 0;
135 
136     if (str == NULL)
137         return 0;
138 
139     /* Fail on negative input */
140     if (*str == '-')
141         return 0;
142 
143     *num = strtoul(str, internal_endptr, base);
144     /*
145      * We return error from this function under the following conditions
146      * 1) If strtoul itself returned an error in translation
147      * 2) If the caller didn't pass in an endptr value, and **internal_endptr
148      *    doesn't point to '\0'.  The implication here is that if the caller
149      *    doesn't care how much of a string is consumed, they expect the entire
150      *    string to be consumed.  As such, no pointing to the NULL terminator
151      *    means there was some part of the string left over after translation
152      * 3) If no bytes of the string were consumed
153      */
154     if (errno != 0 ||
155         (endptr == NULL && **internal_endptr != '\0') ||
156         (str == *internal_endptr))
157         return 0;
158 
159     return 1;
160 }
161 
OPENSSL_hexchar2int(unsigned char c)162 int OPENSSL_hexchar2int(unsigned char c)
163 {
164 #ifdef CHARSET_EBCDIC
165     c = os_toebcdic[c];
166 #endif
167 
168     switch (c) {
169     case '0':
170         return 0;
171     case '1':
172         return 1;
173     case '2':
174         return 2;
175     case '3':
176         return 3;
177     case '4':
178           return 4;
179     case '5':
180           return 5;
181     case '6':
182           return 6;
183     case '7':
184           return 7;
185     case '8':
186           return 8;
187     case '9':
188           return 9;
189     case 'a': case 'A':
190           return 0x0A;
191     case 'b': case 'B':
192           return 0x0B;
193     case 'c': case 'C':
194           return 0x0C;
195     case 'd': case 'D':
196           return 0x0D;
197     case 'e': case 'E':
198           return 0x0E;
199     case 'f': case 'F':
200           return 0x0F;
201     }
202     return -1;
203 }
204 
hexstr2buf_sep(unsigned char * buf,size_t buf_n,size_t * buflen,const char * str,const char sep)205 static int hexstr2buf_sep(unsigned char *buf, size_t buf_n, size_t *buflen,
206                           const char *str, const char sep)
207 {
208     unsigned char *q;
209     unsigned char ch, cl;
210     int chi, cli;
211     const unsigned char *p;
212     size_t cnt;
213 
214     for (p = (const unsigned char *)str, q = buf, cnt = 0; *p; ) {
215         ch = *p++;
216         /* A separator of CH_ZERO means there is no separator */
217         if (ch == sep && sep != CH_ZERO)
218             continue;
219         cl = *p++;
220         if (!cl) {
221             ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ODD_NUMBER_OF_DIGITS);
222             return 0;
223         }
224         cli = OPENSSL_hexchar2int(cl);
225         chi = OPENSSL_hexchar2int(ch);
226         if (cli < 0 || chi < 0) {
227             ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ILLEGAL_HEX_DIGIT);
228             return 0;
229         }
230         cnt++;
231         if (q != NULL) {
232             if (cnt > buf_n) {
233                 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
234                 return 0;
235             }
236             *q++ = (unsigned char)((chi << 4) | cli);
237         }
238     }
239 
240     if (buflen != NULL)
241         *buflen = cnt;
242     return 1;
243 }
244 
245 /*
246  * Given a string of hex digits convert to a buffer
247  */
OPENSSL_hexstr2buf_ex(unsigned char * buf,size_t buf_n,size_t * buflen,const char * str,const char sep)248 int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
249                           const char *str, const char sep)
250 {
251     return hexstr2buf_sep(buf, buf_n, buflen, str, sep);
252 }
253 
ossl_hexstr2buf_sep(const char * str,long * buflen,const char sep)254 unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
255                                    const char sep)
256 {
257     unsigned char *buf;
258     size_t buf_n, tmp_buflen;
259 
260     buf_n = strlen(str);
261     if (buf_n <= 1) {
262         ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_HEX_STRING_TOO_SHORT);
263         return NULL;
264     }
265     buf_n /= 2;
266     if ((buf = OPENSSL_malloc(buf_n)) == NULL)
267         return NULL;
268 
269     if (buflen != NULL)
270         *buflen = 0;
271     tmp_buflen = 0;
272     if (hexstr2buf_sep(buf, buf_n, &tmp_buflen, str, sep)) {
273         if (buflen != NULL)
274             *buflen = (long)tmp_buflen;
275         return buf;
276     }
277     OPENSSL_free(buf);
278     return NULL;
279 }
280 
OPENSSL_hexstr2buf(const char * str,long * buflen)281 unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen)
282 {
283     return ossl_hexstr2buf_sep(str, buflen, DEFAULT_SEPARATOR);
284 }
285 
buf2hexstr_sep(char * str,size_t str_n,size_t * strlength,const unsigned char * buf,size_t buflen,const char sep)286 static int buf2hexstr_sep(char *str, size_t str_n, size_t *strlength,
287                           const unsigned char *buf, size_t buflen,
288                           const char sep)
289 {
290     char *q;
291     int has_sep = (sep != CH_ZERO);
292     size_t i, len = has_sep ? buflen * 3 : 1 + buflen * 2;
293 
294     if (len == 0)
295         ++len;
296     if (strlength != NULL)
297         *strlength = len;
298     if (str == NULL)
299         return 1;
300 
301     if (str_n < len) {
302         ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
303         return 0;
304     }
305 
306     q = str;
307     for (i = 0; i < buflen; i++) {
308         q += ossl_to_hex(q, buf[i]);
309         if (has_sep)
310             *q++ = sep;
311     }
312     if (has_sep && buflen > 0)
313         --q;
314     *q = CH_ZERO;
315 
316 #ifdef CHARSET_EBCDIC
317     ebcdic2ascii(str, str, q - str);
318 #endif
319     return 1;
320 }
321 
OPENSSL_buf2hexstr_ex(char * str,size_t str_n,size_t * strlength,const unsigned char * buf,size_t buflen,const char sep)322 int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlength,
323                           const unsigned char *buf, size_t buflen,
324                           const char sep)
325 {
326     return buf2hexstr_sep(str, str_n, strlength, buf, buflen, sep);
327 }
328 
ossl_buf2hexstr_sep(const unsigned char * buf,long buflen,char sep)329 char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep)
330 {
331     char *tmp;
332     size_t tmp_n;
333 
334     if (buflen == 0)
335         return OPENSSL_zalloc(1);
336 
337     tmp_n = (sep != CH_ZERO) ? buflen * 3 : 1 + buflen * 2;
338     if ((tmp = OPENSSL_malloc(tmp_n)) == NULL)
339         return NULL;
340 
341     if (buf2hexstr_sep(tmp, tmp_n, NULL, buf, buflen, sep))
342         return tmp;
343     OPENSSL_free(tmp);
344     return NULL;
345 }
346 
347 
348 /*
349  * Given a buffer of length 'buflen' return a OPENSSL_malloc'ed string with
350  * its hex representation @@@ (Contents of buffer are always kept in ASCII,
351  * also on EBCDIC machines)
352  */
OPENSSL_buf2hexstr(const unsigned char * buf,long buflen)353 char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen)
354 {
355     return ossl_buf2hexstr_sep(buf, buflen, DEFAULT_SEPARATOR);
356 }
357 
openssl_strerror_r(int errnum,char * buf,size_t buflen)358 int openssl_strerror_r(int errnum, char *buf, size_t buflen)
359 {
360 #if defined(_MSC_VER) && _MSC_VER>=1400 && !defined(_WIN32_WCE)
361     return !strerror_s(buf, buflen, errnum);
362 #elif defined(_GNU_SOURCE)
363     char *err;
364 
365     /*
366      * GNU strerror_r may not actually set buf.
367      * It can return a pointer to some (immutable) static string in which case
368      * buf is left unused.
369      */
370     err = strerror_r(errnum, buf, buflen);
371     if (err == NULL || buflen == 0)
372         return 0;
373     /*
374      * If err is statically allocated, err != buf and we need to copy the data.
375      * If err points somewhere inside buf, OPENSSL_strlcpy can handle this,
376      * since src and dest are not annotated with __restrict and the function
377      * reads src byte for byte and writes to dest.
378      * If err == buf we do not have to copy anything.
379      */
380     if (err != buf)
381         OPENSSL_strlcpy(buf, err, buflen);
382     return 1;
383 #elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
384       (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
385     /*
386      * We can use "real" strerror_r. The OpenSSL version differs in that it
387      * gives 1 on success and 0 on failure for consistency with other OpenSSL
388      * functions. Real strerror_r does it the other way around
389      */
390     return !strerror_r(errnum, buf, buflen);
391 #else
392     char *err;
393 
394     /* Fall back to non-thread safe strerror()...its all we can do */
395     if (buflen < 2)
396         return 0;
397     err = strerror(errnum);
398     /* Can this ever happen? */
399     if (err == NULL)
400         return 0;
401     OPENSSL_strlcpy(buf, err, buflen);
402     return 1;
403 #endif
404 }
405 
OPENSSL_strcasecmp(const char * s1,const char * s2)406 int OPENSSL_strcasecmp(const char *s1, const char *s2)
407 {
408     int t;
409 
410     while ((t = ossl_tolower(*s1) - ossl_tolower(*s2++)) == 0)
411         if (*s1++ == '\0')
412             return 0;
413     return t;
414 }
415 
OPENSSL_strncasecmp(const char * s1,const char * s2,size_t n)416 int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
417 {
418     int t;
419     size_t i;
420 
421     for (i = 0; i < n; i++)
422         if ((t = ossl_tolower(*s1) - ossl_tolower(*s2++)) != 0)
423             return t;
424         else if (*s1++ == '\0')
425             return 0;
426     return 0;
427 }
428 
ossl_to_hex(char * buf,uint8_t n)429 size_t ossl_to_hex(char *buf, uint8_t n)
430 {
431     static const char hexdig[] = "0123456789ABCDEF";
432 
433     return to_hex(buf, n, hexdig);
434 }
435