hex.c revision 1.4
1/* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id: hex.c,v 1.4 2020/02/26 18:47:25 florian Exp $ */ 18 19/*! \file */ 20 21#include <ctype.h> 22#include <string.h> 23 24#include <isc/buffer.h> 25#include <isc/hex.h> 26#include <isc/region.h> 27#include <isc/types.h> 28#include <isc/util.h> 29 30#define RETERR(x) do { \ 31 isc_result_t _r = (x); \ 32 if (_r != ISC_R_SUCCESS) \ 33 return (_r); \ 34 } while (0) 35 36/* 37 * BEW: These static functions are copied from lib/dns/rdata.c. 38 */ 39static isc_result_t 40str_totext(const char *source, isc_buffer_t *target); 41 42static const char hex[] = "0123456789ABCDEF"; 43 44isc_result_t 45isc_hex_totext(isc_region_t *source, int wordlength, 46 const char *wordbreak, isc_buffer_t *target) 47{ 48 char buf[3]; 49 unsigned int loops = 0; 50 51 if (wordlength < 2) 52 wordlength = 2; 53 54 memset(buf, 0, sizeof(buf)); 55 while (source->length > 0) { 56 buf[0] = hex[(source->base[0] >> 4) & 0xf]; 57 buf[1] = hex[(source->base[0]) & 0xf]; 58 RETERR(str_totext(buf, target)); 59 isc_region_consume(source, 1); 60 61 loops++; 62 if (source->length != 0 && 63 (int)((loops + 1) * 2) >= wordlength) 64 { 65 loops = 0; 66 RETERR(str_totext(wordbreak, target)); 67 } 68 } 69 return (ISC_R_SUCCESS); 70} 71 72/*% 73 * State of a hex decoding process in progress. 74 */ 75typedef struct { 76 int length; /*%< Desired length of binary data or -1 */ 77 isc_buffer_t *target; /*%< Buffer for resulting binary data */ 78 int digits; /*%< Number of buffered hex digits */ 79 int val[2]; 80} hex_decode_ctx_t; 81 82static inline void 83hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target) 84{ 85 ctx->digits = 0; 86 ctx->length = length; 87 ctx->target = target; 88} 89 90static inline isc_result_t 91hex_decode_char(hex_decode_ctx_t *ctx, int c) { 92 const char *s; 93 94 if ((s = strchr(hex, toupper(c))) == NULL) 95 return (ISC_R_BADHEX); 96 ctx->val[ctx->digits++] = (int)(s - hex); 97 if (ctx->digits == 2) { 98 unsigned char num; 99 100 num = (ctx->val[0] << 4) + (ctx->val[1]); 101 RETERR(isc_mem_tobuffer(ctx->target, &num, 1)); 102 if (ctx->length >= 0) { 103 if (ctx->length == 0) 104 return (ISC_R_BADHEX); 105 else 106 ctx->length -= 1; 107 } 108 ctx->digits = 0; 109 } 110 return (ISC_R_SUCCESS); 111} 112 113static inline isc_result_t 114hex_decode_finish(hex_decode_ctx_t *ctx) { 115 if (ctx->length > 0) 116 return (ISC_R_UNEXPECTEDEND); 117 if (ctx->digits != 0) 118 return (ISC_R_BADHEX); 119 return (ISC_R_SUCCESS); 120} 121 122isc_result_t 123isc_hex_decodestring(const char *cstr, isc_buffer_t *target) { 124 hex_decode_ctx_t ctx; 125 126 hex_decode_init(&ctx, -1, target); 127 for (;;) { 128 int c = *cstr++; 129 if (c == '\0') 130 break; 131 if (c == ' ' || c == '\t' || c == '\n' || c== '\r') 132 continue; 133 RETERR(hex_decode_char(&ctx, c)); 134 } 135 RETERR(hex_decode_finish(&ctx)); 136 return (ISC_R_SUCCESS); 137} 138 139static isc_result_t 140str_totext(const char *source, isc_buffer_t *target) { 141 unsigned int l; 142 isc_region_t region; 143 144 isc_buffer_availableregion(target, ®ion); 145 l = strlen(source); 146 147 if (l > region.length) 148 return (ISC_R_NOSPACE); 149 150 memmove(region.base, source, l); 151 isc_buffer_add(target, l); 152 return (ISC_R_SUCCESS); 153} 154