0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2008, 2009, 2013-2016 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews/* $Id: base32.c,v 1.6.698.1 2012/02/15 05:00:16 marka Exp $ */
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 Andrews "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
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 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) {
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews const char *s;
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) {