summaryrefslogtreecommitdiffstats
path: root/crypto/o_str.c
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-07-03 18:40:17 +0200
committerRichard Levitte <levitte@openssl.org>2019-08-12 12:50:41 +0200
commit82bd7c2cbd3a4b38321fb9053b8aa0f5d100cf54 (patch)
treeb3a77966489689c83d94dcd2be519186e4f08bd9 /crypto/o_str.c
parenta42cb4ba8aa74757b526af2cad2ac09b493df3fb (diff)
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)
Diffstat (limited to 'crypto/o_str.c')
-rw-r--r--crypto/o_str.c121
1 files changed, 85 insertions, 36 deletions
diff --git a/crypto/o_str.c b/crypto/o_str.c
index c24524f892..6780188cda 100644
--- a/crypto/o_str.c
+++ b/crypto/o_str.c
@@ -132,76 +132,125 @@ 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;
}
-/*
- * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
- * hex representation @@@ (Contents of buffer are always kept in ASCII, also
- * on EBCDIC machines)
- */
-char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
+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";
- char *tmp, *q;
const unsigned char *p;
- int i;
+ char *q;
+ size_t i;
- if (len == 0)
- return OPENSSL_zalloc(1);
+ if (strlen != NULL)
+ *strlen = buflen * 3;
+ if (str == NULL)
+ return 1;
- if ((tmp = OPENSSL_malloc(len * 3)) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
- return NULL;
+ if (str_n < (unsigned long)buflen * 3) {
+ CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR_EX, CRYPTO_R_TOO_SMALL_BUFFER);
+ return 0;
}
- q = tmp;
- for (i = 0, p = buffer; i < len; i++, p++) {
+
+ 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(tmp, tmp, q - tmp - 1);
+ ebcdic2ascii(str, str, q - str - 1);
#endif
+ return 1;
+}
+
+/*
+ * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation @@@ (Contents of buffer are always kept in ASCII, also
+ * on EBCDIC machines)
+ */
+char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen)
+{
+ char *tmp;
+ size_t tmp_n;
+
+ if (buflen == 0)
+ return OPENSSL_zalloc(1);
+
+ tmp_n = buflen * 3;
+ if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) {
+ CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
- 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)