diff --git a/src/core/base16.c b/src/core/base16.c new file mode 100644 index 00000000..14de7957 --- /dev/null +++ b/src/core/base16.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010 Michael Brown . + * + * 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 2 of the + * License, or 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include + +/** @file + * + * Base16 encoding + * + */ + +/** + * Base16-encode data + * + * @v raw Raw data + * @v len Length of raw data + * @v encoded Buffer for encoded string + * + * The buffer must be the correct length for the encoded string. Use + * something like + * + * char buf[ base16_encoded_len ( len ) + 1 ]; + * + * (the +1 is for the terminating NUL) to provide a buffer of the + * correct size. + */ +void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) { + const uint8_t *raw_bytes = raw; + char *encoded_bytes = encoded; + size_t remaining = len; + + for ( ; remaining-- ; encoded_bytes += 2 ) { + sprintf ( encoded_bytes, "%02x", *(raw_bytes++) ); + } + + DBG ( "Base16-encoded to \"%s\":\n", encoded ); + DBG_HDA ( 0, raw, len ); + assert ( strlen ( encoded ) == base16_encoded_len ( len ) ); +} + +/** + * Base16-decode data + * + * @v encoded Encoded string + * @v raw Raw data + * @ret len Length of raw data, or negative error + * + * The buffer must be large enough to contain the decoded data. Use + * something like + * + * char buf[ base16_decoded_max_len ( encoded ) ]; + * + * to provide a buffer of the correct size. + */ +int base16_decode ( const char *encoded, uint8_t *raw ) { + const char *encoded_bytes = encoded; + uint8_t *raw_bytes = raw; + char buf[3]; + char *endp; + size_t len; + + while ( encoded_bytes[0] ) { + if ( ! encoded_bytes[1] ) { + DBG ( "Base16-encoded string \"%s\" has invalid " + "length\n", encoded ); + return -EINVAL; + } + memcpy ( buf, encoded_bytes, 2 ); + buf[2] = '\0'; + *(raw_bytes++) = strtoul ( buf, &endp, 16 ); + if ( *endp != '\0' ) { + DBG ( "Base16-encoded string \"%s\" has invalid " + "byte \"%s\"\n", encoded, buf ); + return -EINVAL; + } + encoded_bytes += 2; + } + len = ( raw_bytes - raw ); + + DBG ( "Base16-decoded \"%s\" to:\n", encoded ); + DBG_HDA ( 0, raw, len ); + assert ( len <= base16_decoded_max_len ( encoded ) ); + + return ( len ); +} diff --git a/src/include/ipxe/base16.h b/src/include/ipxe/base16.h new file mode 100644 index 00000000..f0c9842f --- /dev/null +++ b/src/include/ipxe/base16.h @@ -0,0 +1,38 @@ +#ifndef _IPXE_BASE16_H +#define _IPXE_BASE16_H + +/** @file + * + * Base16 encoding + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** + * Calculate length of base16-encoded data + * + * @v raw_len Raw data length + * @ret encoded_len Encoded string length (excluding NUL) + */ +static inline size_t base16_encoded_len ( size_t raw_len ) { + return ( 2 * raw_len ); +} + +/** + * Calculate maximum length of base16-decoded string + * + * @v encoded Encoded string + * @v max_raw_len Maximum length of raw data + */ +static inline size_t base16_decoded_max_len ( const char *encoded ) { + return ( ( strlen ( encoded ) + 1 ) / 2 ); +} + +extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded ); +extern int base16_decode ( const char *encoded, uint8_t *raw ); + +#endif /* _IPXE_BASE16_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index c62a5b7d..2bb655fd 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_xfer ( ERRFILE_CORE | 0x000e0000 ) #define ERRFILE_bitmap ( ERRFILE_CORE | 0x000f0000 ) #define ERRFILE_base64 ( ERRFILE_CORE | 0x00100000 ) +#define ERRFILE_base16 ( ERRFILE_CORE | 0x00110000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )