Commit 6f091db0 authored by Daniel Salzman's avatar Daniel Salzman

libdnssec: move hex to/from bin functions to contrib/string

parent 71bae255
......@@ -283,8 +283,6 @@ src/libdnssec/shared/bignum.h
src/libdnssec/shared/binary_wire.h
src/libdnssec/shared/dname.c
src/libdnssec/shared/dname.h
src/libdnssec/shared/hex.c
src/libdnssec/shared/hex.h
src/libdnssec/shared/keyid_gnutls.c
src/libdnssec/shared/keyid_gnutls.h
src/libdnssec/shared/pem.c
......
......@@ -14,6 +14,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -110,3 +111,75 @@ void *memzero(void *s, size_t n)
{
return volatile_memset(s, 0, n);
}
static const char BIN_TO_HEX[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
char *bin_to_hex(const uint8_t *bin, size_t bin_len)
{
if (bin == NULL) {
return NULL;
}
size_t hex_size = bin_len * 2;
char *hex = malloc(hex_size + 1);
if (hex == NULL) {
return NULL;
}
for (size_t i = 0; i < bin_len; i++) {
hex[2 * i] = BIN_TO_HEX[bin[i] >> 4];
hex[2 * i + 1] = BIN_TO_HEX[bin[i] & 0x0f];
}
hex[hex_size] = '\0';
return hex;
}
/*!
* Convert HEX character to numeric value (assumes valid input).
*/
static uint8_t hex_to_number(const char hex)
{
if (hex >= '0' && hex <= '9') {
return hex - '0';
} else if (hex >= 'a' && hex <= 'f') {
return hex - 'a' + 10;
} else {
assert(hex >= 'A' && hex <= 'F');
return hex - 'A' + 10;
}
}
uint8_t *hex_to_bin(const char *hex, size_t *out_len)
{
if (hex == NULL || out_len == NULL) {
return NULL;
}
size_t hex_len = strlen(hex);
if (hex_len % 2 != 0) {
return NULL;
}
size_t bin_len = hex_len / 2;
uint8_t *bin = malloc(bin_len + 1);
if (bin == NULL) {
return NULL;
}
for (size_t i = 0; i < bin_len; i++) {
if (!is_xdigit(hex[2 * i]) || !is_xdigit(hex[2 * i + 1])) {
free(bin);
return NULL;
}
uint8_t high = hex_to_number(hex[2 * i]);
uint8_t low = hex_to_number(hex[2 * i + 1]);
bin[i] = high << 4 | low;
}
*out_len = bin_len;
return bin;
}
......@@ -80,3 +80,13 @@ int const_time_memcmp(const void *s1, const void *s2, size_t n);
* \return Pointer to the memory.
*/
void *memzero(void *s, size_t n);
/*!
* \brief Convert binary data to hexadecimal string.
*/
char *bin_to_hex(const uint8_t *bin, size_t bin_len);
/*!
* \brief Convert hex encoded string to binary data.
*/
uint8_t *hex_to_bin(const char *hex, size_t *out_len);
......@@ -11,8 +11,6 @@ libshared_la_SOURCES = \
libdnssec/shared/binary_wire.h \
libdnssec/shared/dname.c \
libdnssec/shared/dname.h \
libdnssec/shared/hex.c \
libdnssec/shared/hex.h \
libdnssec/shared/keyid_gnutls.c \
libdnssec/shared/keyid_gnutls.h \
libdnssec/shared/pem.c \
......
......@@ -17,8 +17,8 @@
#include <gnutls/gnutls.h>
#include <pthread.h>
#include "contrib/string.h"
#include "libdnssec/error.h"
#include "libdnssec/shared/hex.h"
#include "libdnssec/keyid.h"
#include "libdnssec/shared/keyid_gnutls.h"
#include "libdnssec/keystore.h"
......@@ -213,9 +213,8 @@ static char *get_object_id(gnutls_pkcs11_obj_t object)
return NULL;
}
const dnssec_binary_t bin = { .data = buffer, .size = sizeof(buffer) };
char *id = NULL;
if (bin_to_hex(&bin, &id) != DNSSEC_EOK) {
char *id = bin_to_hex(buffer, sizeof(buffer));
if (id == NULL) {
return NULL;
}
......@@ -274,9 +273,8 @@ static int pkcs11_generate_key(void *_ctx, gnutls_pk_algorithm_t algorithm,
return DNSSEC_KEY_GENERATE_ERROR;
}
char *id = NULL;
r = bin_to_hex(&cka_id, &id);
if (r != DNSSEC_EOK) {
char *id = bin_to_hex(cka_id.data, cka_id.size);
if (id == NULL) {
return DNSSEC_ENOMEM;
}
......@@ -358,7 +356,12 @@ static int pkcs11_import_key(void *_ctx, const dnssec_binary_t *pem, char **id_p
return DNSSEC_KEY_IMPORT_ERROR;
}
return bin_to_hex(&id, id_ptr);
*id_ptr = bin_to_hex(id.data, id.size);
if (id_ptr == NULL) {
return DNSSEC_ENOMEM;
}
return DNSSEC_EOK;
}
static int pkcs11_remove_key(void *_ctx, const char *id)
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include "libdnssec/binary.h"
#include "libdnssec/error.h"
#include "contrib/ctype.h"
/* -- binary to hex -------------------------------------------------------- */
static const char BIN_TO_HEX[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
int bin_to_hex_static(const dnssec_binary_t *bin, dnssec_binary_t *hex)
{
if (!bin || !hex) {
return DNSSEC_EINVAL;
}
if (bin->size * 2 != hex->size) {
return DNSSEC_EINVAL;
}
for (size_t i = 0; i < bin->size; i++) {
hex->data[2*i] = BIN_TO_HEX[bin->data[i] >> 4];
hex->data[2*i+1] = BIN_TO_HEX[bin->data[i] & 0x0f];
}
return DNSSEC_EOK;
}
int bin_to_hex(const dnssec_binary_t *bin, char **hex_ptr)
{
if (!bin || !hex_ptr) {
return DNSSEC_EINVAL;
}
size_t hex_size = bin->size * 2;
char *hex = malloc(hex_size + 1);
if (!hex) {
return DNSSEC_ENOMEM;
}
dnssec_binary_t hex_bin = { .data = (uint8_t *)hex, .size = hex_size };
bin_to_hex_static(bin, &hex_bin);
hex[hex_size] = '\0';
*hex_ptr = hex;
return DNSSEC_EOK;
}
/* -- hex to binary -------------------------------------------------------- */
/*!
* Convert HEX character to numeric value (assumes valid and lowercase input).
*/
static uint8_t hex_to_number(const char hex)
{
if (hex >= '0' && hex <= '9') {
return hex - '0';
} else if (hex >= 'a' && hex <= 'f') {
return hex - 'a' + 10;
} else {
assert(hex >= 'A' && hex <= 'F');
return hex - 'A' + 10;
}
}
/*!
* Check if the input string has valid size and contains valid characters.
*/
static bool hex_valid_input(const dnssec_binary_t *hex)
{
assert(hex);
if (hex->size % 2 != 0) {
return false;
}
for (int i = 0; i < hex->size; i++) {
if (!is_xdigit(hex->data[i])) {
return false;
}
}
return true;
}
/*!
* Perform hex to bin conversion without checking the validity.
*/
static void hex_to_bin_convert(const dnssec_binary_t *hex, dnssec_binary_t *bin)
{
assert(hex);
assert(bin);
for (size_t i = 0; i < bin->size; i++) {
uint8_t high = hex_to_number(hex->data[2 * i]);
uint8_t low = hex_to_number(hex->data[2 * i + 1]);
bin->data[i] = high << 4 | low;
}
}
int hex_to_bin_static(const dnssec_binary_t *hex, dnssec_binary_t *bin)
{
if (!hex || !bin) {
return DNSSEC_EINVAL;
}
if (hex->size / 2 != bin->size) {
return DNSSEC_EINVAL;
}
if (!hex_valid_input(hex)) {
return DNSSEC_MALFORMED_DATA;
}
hex_to_bin_convert(hex, bin);
return DNSSEC_EOK;
}
int hex_to_bin(const char *hex_str, dnssec_binary_t *bin)
{
if (!hex_str || !bin) {
return DNSSEC_EINVAL;
}
dnssec_binary_t hex = { .data = (uint8_t *)hex_str, .size = strlen(hex_str) };
if (!hex_valid_input(&hex)) {
return DNSSEC_MALFORMED_DATA;
}
size_t bin_size = hex.size / 2;
if (bin_size == 0) {
bin->size = 0;
bin->data = NULL;
return DNSSEC_EOK;
}
int result = dnssec_binary_alloc(bin, bin_size);
if (result != DNSSEC_EOK) {
return result;
}
hex_to_bin_static(&hex, bin);
return DNSSEC_EOK;
}
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "libdnssec/binary.h"
/*!
* Convert binary data to preallocated hexadecimal string.
*/
int bin_to_hex_static(const dnssec_binary_t *bin, dnssec_binary_t *hex);
/**
* Convert binary data to hexadecimal string.
*/
int bin_to_hex(const dnssec_binary_t *bin, char **hex_ptr);
/*!
* Convert hex encoded string to preallocated binary data.
*/
int hex_to_bin_static(const dnssec_binary_t *hex, dnssec_binary_t *bin);
/*!
* Convert hex encoded string to binary data.
*/
int hex_to_bin(const char *hex, dnssec_binary_t *bin);
......@@ -20,12 +20,12 @@
#include <gnutls/x509.h>
#include <string.h>
#include "contrib/string.h"
#include "libdnssec/binary.h"
#include "libdnssec/error.h"
#include "libdnssec/keyid.h"
#include "libdnssec/shared/keyid_gnutls.h"
#include "libdnssec/shared/shared.h"
#include "libdnssec/shared/hex.h"
/*!
* Get binary key ID from a key (public or private).
......@@ -70,7 +70,12 @@ static int keyid_hex(gnutls_x509_privkey_t key, gnutls_pubkey_t pubkey, char **i
return r;
}
return bin_to_hex(&bin, id);
*id = bin_to_hex(bin.data, bin.size);
if (*id == NULL) {
return DNSSEC_ENOMEM;
}
return DNSSEC_EOK;
}
int keyid_x509(gnutls_x509_privkey_t key, dnssec_binary_t *id)
......
......@@ -66,7 +66,7 @@ kdig_LDADD = libknotus.la
khost_CPPFLAGS = $(AM_CPPFLAGS) $(gnutls_CFLAGS)
khost_LDADD = libknotus.la
knsec3hash_CPPFLAGS = $(AM_CPPFLAGS)
knsec3hash_LDADD = libcontrib.la libdnssec.la libknot.la libshared.la
knsec3hash_LDADD = libcontrib.la libdnssec.la libknot.la
knsupdate_CPPFLAGS = $(AM_CPPFLAGS) $(gnutls_CFLAGS)
knsupdate_LDADD = libknotus.la libzscanner.la
......
......@@ -22,10 +22,10 @@
#include <string.h>
#include "contrib/base32hex.h"
#include "contrib/string.h"
#include "contrib/strtonum.h"
#include "libdnssec/error.h"
#include "libdnssec/nsec.h"
#include "libdnssec/shared/hex.h"
#include "libknot/libknot.h"
#define PROGRAM_NAME "knsec3hash"
......@@ -57,7 +57,8 @@ static int str_to_salt(const char *str, dnssec_binary_t *salt)
salt->size = 0;
return DNSSEC_EOK;
} else {
return hex_to_bin(str, salt);
salt->data = hex_to_bin(str, &salt->size);
return (salt->data != NULL ? DNSSEC_EOK : DNSSEC_EINVAL);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment