Add OPENSSL_hexstr2buf_ex() and OPENSSL_buf2hexstr_ex()

They do the same thing as OPENSSL_hexstr2buf() and OPENSSL_buf2hexstr(),
except they take a result buffer from the caller.

We take the opportunity to break out the documentation of the hex to /
from buffer conversion routines from the OPENSSL_malloc() file to its
own file.  These routines aren't memory allocation routines per se.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9303)
This commit is contained in:
Richard Levitte 2019-07-03 18:40:17 +02:00
parent a42cb4ba8a
commit 82bd7c2cbd
8 changed files with 176 additions and 59 deletions

View file

@ -40,6 +40,8 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = {
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_BYTES), "too many bytes"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_RECORDS),
"too many records"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_SMALL_BUFFER),
"too small buffer"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ZERO_LENGTH_NUMBER),
"zero length number"},
{0, NULL}

View file

@ -391,8 +391,10 @@ CRYPTO_F_GET_AND_LOCK:113:get_and_lock
CRYPTO_F_GET_PROVIDER_STORE:133:get_provider_store
CRYPTO_F_OPENSSL_ATEXIT:114:OPENSSL_atexit
CRYPTO_F_OPENSSL_BUF2HEXSTR:117:OPENSSL_buf2hexstr
CRYPTO_F_OPENSSL_BUF2HEXSTR_EX:153:
CRYPTO_F_OPENSSL_FOPEN:119:openssl_fopen
CRYPTO_F_OPENSSL_HEXSTR2BUF:118:OPENSSL_hexstr2buf
CRYPTO_F_OPENSSL_HEXSTR2BUF_EX:154:
CRYPTO_F_OPENSSL_INIT_CRYPTO:116:OPENSSL_init_crypto
CRYPTO_F_OPENSSL_LH_NEW:126:OPENSSL_LH_new
CRYPTO_F_OPENSSL_SK_DEEP_COPY:127:OPENSSL_sk_deep_copy
@ -2243,6 +2245,7 @@ CRYPTO_R_SECURE_MALLOC_FAILURE:111:secure malloc failure
CRYPTO_R_STRING_TOO_LONG:112:string too long
CRYPTO_R_TOO_MANY_BYTES:113:too many bytes
CRYPTO_R_TOO_MANY_RECORDS:114:too many records
CRYPTO_R_TOO_SMALL_BUFFER:116:too small buffer
CRYPTO_R_ZERO_LENGTH_NUMBER:115:zero length number
CT_R_BASE64_DECODE_ERROR:108:base64 decode error
CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length

View file

@ -132,43 +132,100 @@ int OPENSSL_hexchar2int(unsigned char c)
/*
* Give a string of hex digits convert to a buffer
*/
unsigned char *OPENSSL_hexstr2buf(const char *str, long *len)
int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
const char *str)
{
unsigned char *hexbuf, *q;
unsigned char *q;
unsigned char ch, cl;
int chi, cli;
const unsigned char *p;
size_t s;
size_t cnt;
s = strlen(str);
if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
for (p = (const unsigned char *)str, q = buf, cnt = 0; *p; ) {
ch = *p++;
if (ch == ':')
continue;
cl = *p++;
if (!cl) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF,
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX,
CRYPTO_R_ODD_NUMBER_OF_DIGITS);
OPENSSL_free(hexbuf);
return NULL;
return 0;
}
cli = OPENSSL_hexchar2int(cl);
chi = OPENSSL_hexchar2int(ch);
if (cli < 0 || chi < 0) {
OPENSSL_free(hexbuf);
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
return NULL;
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX,
CRYPTO_R_ILLEGAL_HEX_DIGIT);
return 0;
}
cnt++;
if (q != NULL) {
if (cnt > buf_n) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX,
CRYPTO_R_TOO_SMALL_BUFFER);
return 0;
}
*q++ = (unsigned char)((chi << 4) | cli);
}
*q++ = (unsigned char)((chi << 4) | cli);
}
if (len)
*len = q - hexbuf;
return hexbuf;
if (buflen != NULL)
*buflen = cnt;
return 1;
}
unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen)
{
unsigned char *buf;
size_t buf_n, tmp_buflen;
buf_n = strlen(str) >> 1;
if ((buf = OPENSSL_malloc(buf_n)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (buflen != NULL)
*buflen = 0;
tmp_buflen = 0;
if (OPENSSL_hexstr2buf_ex(buf, buf_n, &tmp_buflen, str)) {
if (buflen != NULL)
*buflen = (long)tmp_buflen;
return buf;
}
OPENSSL_free(buf);
return NULL;
}
int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlen,
const unsigned char *buf, size_t buflen)
{
static const char hexdig[] = "0123456789ABCDEF";
const unsigned char *p;
char *q;
size_t i;
if (strlen != NULL)
*strlen = buflen * 3;
if (str == NULL)
return 1;
if (str_n < (unsigned long)buflen * 3) {
CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR_EX, CRYPTO_R_TOO_SMALL_BUFFER);
return 0;
}
q = str;
for (i = 0, p = buf; i < buflen; i++, p++) {
*q++ = hexdig[(*p >> 4) & 0xf];
*q++ = hexdig[*p & 0xf];
*q++ = ':';
}
q[-1] = 0;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(str, str, q - str - 1);
#endif
return 1;
}
/*
@ -176,32 +233,24 @@ unsigned char *OPENSSL_hexstr2buf(const char *str, long *len)
* hex representation @@@ (Contents of buffer are always kept in ASCII, also
* on EBCDIC machines)
*/
char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen)
{
static const char hexdig[] = "0123456789ABCDEF";
char *tmp, *q;
const unsigned char *p;
int i;
char *tmp;
size_t tmp_n;
if (len == 0)
if (buflen == 0)
return OPENSSL_zalloc(1);
if ((tmp = OPENSSL_malloc(len * 3)) == NULL) {
tmp_n = buflen * 3;
if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
return NULL;
}
q = tmp;
for (i = 0, p = buffer; i < len; i++, p++) {
*q++ = hexdig[(*p >> 4) & 0xf];
*q++ = hexdig[*p & 0xf];
*q++ = ':';
}
q[-1] = 0;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(tmp, tmp, q - tmp - 1);
#endif
return tmp;
if (OPENSSL_buf2hexstr_ex(tmp, tmp_n, NULL, buf, buflen))
return tmp;
OPENSSL_free(tmp);
return NULL;
}
int openssl_strerror_r(int errnum, char *buf, size_t buflen)

View file

@ -0,0 +1,74 @@
=pod
=head1 NAME
OPENSSL_hexchar2int,
OPENSSL_hexstr2buf_ex, OPENSSL_hexstr2buf,
OPENSSL_buf2hexstr_ex, OPENSSL_buf2hexstr
- Hex encoding and decoding functions
=head1 SYNOPSIS
#include <openssl/crypto.h>
int OPENSSL_hexchar2int(unsigned char c);
int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, long *buflen,
const char *str);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlen,
const unsigned char *buf, long buflen);
char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen);
=head1 DESCRIPTION
OPENSSL_hexchar2int() converts a hexadecimal character to its numeric
equivalent.
OPENSSL_hexstr2buf_ex() decodes the hex string B<str> and places the
resulting string of bytes in the given I<buf>.
I<buf_n> gives the size of the buffer.
If I<buflen> is not NULL, it is filled in with the result length.
To find out how large the result will be, call this function with NULL
for I<buf>.
Colons between two-character hex "bytes" are accepted and ignored.
An odd number of hex digits is an error.
OPENSSL_hexstr2buf() does the same thing as OPENSSL_hexstr2buf_ex(),
but allocates the space for the result, and returns the result.
The memory is allocated by calling OPENSSL_malloc() and should be
released by calling OPENSSL_free().
OPENSSL_buf2hexstr_ex() encodes the contents of the given I<buf> with
length I<buflen> and places the resulting hexadecimal character string
in the given I<str>.
I<str_n> gives the size of the of the string buffer.
If I<strlen> is not NULL, it is filled in with the result length.
To find out how large the result will be, call this function with NULL
for I<str>.
OPENSSL_buf2hexstr() does the same thing as OPENSSL_buf2hexstr_ex(),
but allocates the space for the result, and returns the result.
The memory is allocated by calling OPENSSL_malloc() and should be
released by calling OPENSSL_free().
=head1 RETURN VALUES
OPENSSL_hexchar2int returns the value of a decoded hex character,
or -1 on error.
OPENSSL_buf2hexstr() and OPENSSL_hexstr2buf()
return a pointer to allocated memory, or NULL on error.
OPENSSL_buf2hexstr_ex() and OPENSSL_hexstr2buf_ex() return 1 on
success, or 0 on error.
=head1 COPYRIGHT
Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -8,7 +8,6 @@ OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse,
CRYPTO_malloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free,
OPENSSL_strdup, OPENSSL_strndup,
OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat,
OPENSSL_hexstr2buf, OPENSSL_buf2hexstr, OPENSSL_hexchar2int,
CRYPTO_strdup, CRYPTO_strndup,
OPENSSL_mem_debug_push, OPENSSL_mem_debug_pop,
CRYPTO_mem_debug_push, CRYPTO_mem_debug_pop,
@ -40,10 +39,6 @@ OPENSSL_MALLOC_FD
void OPENSSL_clear_free(void *str, size_t num)
void OPENSSL_cleanse(void *ptr, size_t len);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len);
int OPENSSL_hexchar2int(unsigned char c);
void *CRYPTO_malloc(size_t num, const char *file, int line)
void *CRYPTO_zalloc(size_t num, const char *file, int line)
void *CRYPTO_realloc(void *p, size_t num, const char *file, int line)
@ -119,20 +114,6 @@ OPENSSL_strlcpy(),
OPENSSL_strlcat() and OPENSSL_strnlen() are equivalents of the common C
library functions and are provided for portability.
OPENSSL_hexstr2buf() parses B<str> as a hex string and returns a
pointer to the parsed value. The memory is allocated by calling
OPENSSL_malloc() and should be released by calling OPENSSL_free().
If B<len> is not NULL, it is filled in with the output length.
Colons between two-character hex "bytes" are ignored.
An odd number of hex digits is an error.
OPENSSL_buf2hexstr() takes the specified buffer and length, and returns
a hex string for value, or NULL on error.
B<Buffer> cannot be NULL; if B<len> is 0 an empty string is returned.
OPENSSL_hexchar2int() converts a character to the hexadecimal equivalent,
or returns -1 on error.
If no allocations have been done, it is possible to "swap out" the default
implementations for OPENSSL_malloc(), OPENSSL_realloc and OPENSSL_free()
and replace them with alternate versions (hooks).
@ -216,7 +197,6 @@ OPENSSL_malloc(), OPENSSL_zalloc(), OPENSSL_realloc(),
OPENSSL_clear_realloc(),
CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_realloc(),
CRYPTO_clear_realloc(),
OPENSSL_buf2hexstr(), OPENSSL_hexstr2buf(),
OPENSSL_strdup(), and OPENSSL_strndup()
return a pointer to allocated memory or NULL on error.

View file

@ -148,8 +148,12 @@ int CRYPTO_mem_ctrl(int mode);
size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz);
size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz);
size_t OPENSSL_strnlen(const char *str, size_t maxlen);
char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlen,
const unsigned char *buf, size_t buflen);
char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen);
int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
const char *str);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
int OPENSSL_hexchar2int(unsigned char c);
# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type))

View file

@ -40,8 +40,10 @@ int ERR_load_CRYPTO_strings(void);
# define CRYPTO_F_GET_PROVIDER_STORE 0
# define CRYPTO_F_OPENSSL_ATEXIT 0
# define CRYPTO_F_OPENSSL_BUF2HEXSTR 0
# define CRYPTO_F_OPENSSL_BUF2HEXSTR_EX 0
# define CRYPTO_F_OPENSSL_FOPEN 0
# define CRYPTO_F_OPENSSL_HEXSTR2BUF 0
# define CRYPTO_F_OPENSSL_HEXSTR2BUF_EX 0
# define CRYPTO_F_OPENSSL_INIT_CRYPTO 0
# define CRYPTO_F_OPENSSL_LH_NEW 0
# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 0
@ -89,6 +91,7 @@ int ERR_load_CRYPTO_strings(void);
# define CRYPTO_R_STRING_TOO_LONG 112
# define CRYPTO_R_TOO_MANY_BYTES 113
# define CRYPTO_R_TOO_MANY_RECORDS 114
# define CRYPTO_R_TOO_SMALL_BUFFER 116
# define CRYPTO_R_ZERO_LENGTH_NUMBER 115
#endif

View file

@ -4706,3 +4706,5 @@ EC_GROUP_new_ex 4815 3_0_0 EXIST::FUNCTION:EC
EC_GROUP_new_by_curve_name_ex 4816 3_0_0 EXIST::FUNCTION:EC
EC_KEY_new_ex 4817 3_0_0 EXIST::FUNCTION:EC
EC_KEY_new_by_curve_name_ex 4818 3_0_0 EXIST::FUNCTION:EC
OPENSSL_hexstr2buf_ex 4819 3_0_0 EXIST::FUNCTION:
OPENSSL_buf2hexstr_ex 4820 3_0_0 EXIST::FUNCTION: