base32.c revision 36e5ac00333d89001f0c518a7d381d16c38d0402
431a83fb29482c5170b3e4026e59bb14849a6707Tinderbox User * Copyright (C) 2008, 2009, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
f052a01ff268cdbbf3e6f600b06d02ed8573badfAutomatic Updater * Permission to use, copy, modify, and/or distribute this software for any
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * purpose with or without fee is hereby granted, provided that the above
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * copyright notice and this permission notice appear in all copies.
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews/* $Id: base32.c,v 1.6.698.1 2012/02/15 05:00:16 marka Exp $ */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews#define RETERR(x) do { \
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * These static functions are also present in lib/dns/rdata.c. I'm not
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * sure where they should go. -- bwelling
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsstr_totext(const char *source, isc_buffer_t *target);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsmem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsstatic const char base32[] =
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsstatic const char base32hex[] =
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsbase32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews isc_buffer_t *target, const char base[], char pad)
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews unsigned int loops = 0;
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[0] = base[((source->base[0]>>3)&0x1f)]; /* 5 + */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[1] = base[((source->base[0]<<2)&0x1c)| /* 3 = 8 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[2] = base[((source->base[1]>>1)&0x1f)]; /* 5 + */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[3] = base[((source->base[1]<<4)&0x10)| /* 1 = 8 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[4] = base[((source->base[2]<<1)&0x1e)| /* 4 = 8 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[5] = base[((source->base[3]>>2)&0x1f)]; /* 5 + */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[6] = base[((source->base[3]<<3)&0x18)| /* 2 = 8 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[7] = base[source->base[4]&0x1f]; /* 5 = 8 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32_totext(isc_region_t *source, int wordlength,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_totext(source, wordlength, wordbreak, target,
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32hex_totext(isc_region_t *source, int wordlength,
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews return (base32_totext(source, wordlength, wordbreak, target,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsisc_base32hexnp_totext(isc_region_t *source, int wordlength,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_totext(source, wordlength, wordbreak, target,
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * State of a base32 decoding process in progress.
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewstypedef struct {
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews int length; /*%< Desired length of binary data or -1 */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews isc_buffer_t *target; /*%< Buffer for resulting binary data */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews int digits; /*%< Number of buffered base32 digits */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews isc_boolean_t seen_end; /*%< True if "=" end marker seen */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews const char *base; /*%< Which encoding we are using */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews int seen_32; /*%< Number of significant bytes if non zero */
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsstatic inline void
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsbase32_decode_init(base32_decode_ctx_t *ctx, int length, const char base[],
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsbase32_decode_char(base32_decode_ctx_t *ctx, int c) {
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews unsigned int last;
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * Handle lower case.
1016f2638f8a34a802ce41043d5369553ac14246Francis Dupont * Check that padding is contiguous.
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews * If padding is not permitted flag padding as a error.
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * Check that padding starts at the right place and that
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * bits that should be zero are.
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * Record how many significant bytes in answer (seen_32).
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews * Zero fill pad values.
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsbase32_decode_finish(base32_decode_ctx_t *ctx) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews * Add missing padding if required.
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsbase32_tobuffer(isc_lex_t *lexer, const char base[], isc_boolean_t pad,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews base32_decode_init(&ctx, length, base, pad, target);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews unsigned int i;
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_tobuffer(lexer, base32, ISC_TRUE, target, length));
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_tobuffer(lexer, base32hex, ISC_TRUE, target, length));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsisc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_tobuffer(lexer, base32hex, ISC_FALSE, target, length));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsbase32_decodestring(const char *cstr, const char base[], isc_boolean_t pad,
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews base32_decode_init(&ctx, -1, base, pad, target);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews if (c == '\0')
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decodestring(cstr, base32, ISC_TRUE, target));
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decodestring(cstr, base32hex, ISC_TRUE, target));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsisc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decodestring(cstr, base32hex, ISC_FALSE, target));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsbase32_decoderegion(isc_region_t *source, const char base[],
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews base32_decode_init(&ctx, -1, base, pad, target);
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decoderegion(source, base32, ISC_TRUE, target));
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsisc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decoderegion(source, base32hex, ISC_TRUE, target));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrewsisc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target) {
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews return (base32_decoderegion(source, base32hex, ISC_FALSE, target));
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsstr_totext(const char *source, isc_buffer_t *target) {
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrews unsigned int l;
77abeb5330ed5f87eb406c64a738c9edb403a171Mark Andrewsmem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {