Annotation of embedaddon/ntp/lib/isc/base32.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008, 2009  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: base32.c,v 1.3.116.2 2009/01/18 23:47:41 tbox Exp $ */
        !            18: 
        !            19: /*! \file */
        !            20: 
        !            21: #include <config.h>
        !            22: 
        !            23: #include <isc/base32.h>
        !            24: #include <isc/buffer.h>
        !            25: #include <isc/lex.h>
        !            26: #include <isc/region.h>
        !            27: #include <isc/string.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: /*@{*/
        !            38: /*!
        !            39:  * These static functions are also present in lib/dns/rdata.c.  I'm not
        !            40:  * sure where they should go. -- bwelling
        !            41:  */
        !            42: static isc_result_t
        !            43: str_totext(const char *source, isc_buffer_t *target);
        !            44: 
        !            45: static isc_result_t
        !            46: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
        !            47: 
        !            48: /*@}*/
        !            49: 
        !            50: static const char base32[] =
        !            51:         "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
        !            52: static const char base32hex[] =
        !            53:        "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
        !            54: 
        !            55: static isc_result_t
        !            56: base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
        !            57:              isc_buffer_t *target, const char base[])
        !            58: {
        !            59:        char buf[9];
        !            60:        unsigned int loops = 0;
        !            61: 
        !            62:        if (wordlength >= 0 && wordlength < 8)
        !            63:                wordlength = 8;
        !            64: 
        !            65:        memset(buf, 0, sizeof(buf));
        !            66:        while (source->length > 0) {
        !            67:                buf[0] = base[((source->base[0]>>3)&0x1f)];     /* 5 + */
        !            68:                if (source->length == 1) {
        !            69:                        buf[1] = base[(source->base[0]<<2)&0x1c];
        !            70:                        buf[2] = buf[3] = buf[4] = '=';
        !            71:                        buf[5] = buf[6] = buf[7] = '=';
        !            72:                        RETERR(str_totext(buf, target));
        !            73:                        break;
        !            74:                }
        !            75:                buf[1] = base[((source->base[0]<<2)&0x1c)|      /* 3 = 8 */
        !            76:                              ((source->base[1]>>6)&0x03)];     /* 2 + */
        !            77:                buf[2] = base[((source->base[1]>>1)&0x1f)];     /* 5 + */
        !            78:                if (source->length == 2) {
        !            79:                        buf[3] = base[(source->base[1]<<4)&0x10];
        !            80:                        buf[4] = buf[5] = buf[6] = buf[7] = '=';
        !            81:                        RETERR(str_totext(buf, target));
        !            82:                        break;
        !            83:                }
        !            84:                buf[3] = base[((source->base[1]<<4)&0x10)|      /* 1 = 8 */
        !            85:                              ((source->base[2]>>4)&0x0f)];     /* 4 + */
        !            86:                if (source->length == 3) {
        !            87:                        buf[4] = base[(source->base[2]<<1)&0x1e];
        !            88:                        buf[5] = buf[6] = buf[7] = '=';
        !            89:                        RETERR(str_totext(buf, target));
        !            90:                        break;
        !            91:                }
        !            92:                buf[4] = base[((source->base[2]<<1)&0x1e)|      /* 4 = 8 */
        !            93:                              ((source->base[3]>>7)&0x01)];     /* 1 + */
        !            94:                buf[5] = base[((source->base[3]>>2)&0x1f)];     /* 5 + */
        !            95:                if (source->length == 4) {
        !            96:                        buf[6] = base[(source->base[3]<<3)&0x18];
        !            97:                        buf[7] = '=';
        !            98:                        RETERR(str_totext(buf, target));
        !            99:                        break;
        !           100:                }
        !           101:                buf[6] = base[((source->base[3]<<3)&0x18)|      /* 2 = 8 */
        !           102:                              ((source->base[4]>>5)&0x07)];     /* 3 + */
        !           103:                buf[7] = base[source->base[4]&0x1f];            /* 5 = 8 */
        !           104:                RETERR(str_totext(buf, target));
        !           105:                isc_region_consume(source, 5);
        !           106: 
        !           107:                loops++;
        !           108:                if (source->length != 0 && wordlength >= 0 &&
        !           109:                    (int)((loops + 1) * 8) >= wordlength)
        !           110:                {
        !           111:                        loops = 0;
        !           112:                        RETERR(str_totext(wordbreak, target));
        !           113:                }
        !           114:        }
        !           115:        return (ISC_R_SUCCESS);
        !           116: }
        !           117: 
        !           118: isc_result_t
        !           119: isc_base32_totext(isc_region_t *source, int wordlength,
        !           120:                  const char *wordbreak, isc_buffer_t *target)
        !           121: {
        !           122:        return (base32_totext(source, wordlength, wordbreak, target, base32));
        !           123: }
        !           124: 
        !           125: isc_result_t
        !           126: isc_base32hex_totext(isc_region_t *source, int wordlength,
        !           127:                     const char *wordbreak, isc_buffer_t *target)
        !           128: {
        !           129:        return (base32_totext(source, wordlength, wordbreak, target,
        !           130:                              base32hex));
        !           131: }
        !           132: 
        !           133: /*%
        !           134:  * State of a base32 decoding process in progress.
        !           135:  */
        !           136: typedef struct {
        !           137:        int length;             /*%< Desired length of binary data or -1 */
        !           138:        isc_buffer_t *target;   /*%< Buffer for resulting binary data */
        !           139:        int digits;             /*%< Number of buffered base32 digits */
        !           140:        isc_boolean_t seen_end; /*%< True if "=" end marker seen */
        !           141:        int val[8];
        !           142:        const char *base;       /*%< Which encoding we are using */
        !           143:        int seen_32;            /*%< Number of significant bytes if non zero */
        !           144: } base32_decode_ctx_t;
        !           145: 
        !           146: static inline void
        !           147: base32_decode_init(base32_decode_ctx_t *ctx, int length,
        !           148:                   const char base[], isc_buffer_t *target)
        !           149: {
        !           150:        ctx->digits = 0;
        !           151:        ctx->seen_end = ISC_FALSE;
        !           152:        ctx->seen_32 = 0;
        !           153:        ctx->length = length;
        !           154:        ctx->target = target;
        !           155:        ctx->base = base;
        !           156: }
        !           157: 
        !           158: static inline isc_result_t
        !           159: base32_decode_char(base32_decode_ctx_t *ctx, int c) {
        !           160:        char *s;
        !           161:        unsigned int last;
        !           162: 
        !           163:        if (ctx->seen_end)
        !           164:                return (ISC_R_BADBASE32);
        !           165:        if ((s = strchr(ctx->base, c)) == NULL)
        !           166:                return (ISC_R_BADBASE32);
        !           167:        last = s - ctx->base;
        !           168:        /*
        !           169:         * Handle lower case.
        !           170:         */
        !           171:        if (last > 32)
        !           172:                last -= 33;
        !           173:        /*
        !           174:         * Check that padding is contiguous.
        !           175:         */
        !           176:        if (last != 32 && ctx->seen_32 != 0)
        !           177:                return (ISC_R_BADBASE32);
        !           178:        /*
        !           179:         * Check that padding starts at the right place and that
        !           180:         * bits that should be zero are.
        !           181:         * Record how many significant bytes in answer (seen_32).
        !           182:         */
        !           183:        if (last == 32 && ctx->seen_32 == 0)
        !           184:                switch (ctx->digits) {
        !           185:                case 0:
        !           186:                case 1:
        !           187:                        return (ISC_R_BADBASE32);
        !           188:                case 2:
        !           189:                        if ((ctx->val[1]&0x03) != 0)
        !           190:                                return (ISC_R_BADBASE32);
        !           191:                        ctx->seen_32 = 1;
        !           192:                        break;
        !           193:                case 3:
        !           194:                        return (ISC_R_BADBASE32);
        !           195:                case 4:
        !           196:                        if ((ctx->val[3]&0x0f) != 0)
        !           197:                                return (ISC_R_BADBASE32);
        !           198:                        ctx->seen_32 = 3;
        !           199:                        break;
        !           200:                case 5:
        !           201:                        if ((ctx->val[4]&0x01) != 0)
        !           202:                                return (ISC_R_BADBASE32);
        !           203:                        ctx->seen_32 = 3;
        !           204:                        break;
        !           205:                case 6:
        !           206:                        return (ISC_R_BADBASE32);
        !           207:                case 7:
        !           208:                        if ((ctx->val[6]&0x07) != 0)
        !           209:                                return (ISC_R_BADBASE32);
        !           210:                        ctx->seen_32 = 4;
        !           211:                        break;
        !           212:                }
        !           213:        /*
        !           214:         * Zero fill pad values.
        !           215:         */
        !           216:        ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
        !           217: 
        !           218:        if (ctx->digits == 8) {
        !           219:                int n = 5;
        !           220:                unsigned char buf[5];
        !           221: 
        !           222:                if (ctx->seen_32 != 0) {
        !           223:                        ctx->seen_end = ISC_TRUE;
        !           224:                        n = ctx->seen_32;
        !           225:                }
        !           226:                buf[0] = (ctx->val[0]<<3)|(ctx->val[1]>>2);
        !           227:                buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
        !           228:                buf[2] = (ctx->val[3]<<4)|(ctx->val[4]>>1);
        !           229:                buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
        !           230:                buf[4] = (ctx->val[6]<<5)|(ctx->val[7]);
        !           231:                RETERR(mem_tobuffer(ctx->target, buf, n));
        !           232:                if (ctx->length >= 0) {
        !           233:                        if (n > ctx->length)
        !           234:                                return (ISC_R_BADBASE32);
        !           235:                        else
        !           236:                                ctx->length -= n;
        !           237:                }
        !           238:                ctx->digits = 0;
        !           239:        }
        !           240:        return (ISC_R_SUCCESS);
        !           241: }
        !           242: 
        !           243: static inline isc_result_t
        !           244: base32_decode_finish(base32_decode_ctx_t *ctx) {
        !           245:        if (ctx->length > 0)
        !           246:                return (ISC_R_UNEXPECTEDEND);
        !           247:        if (ctx->digits != 0)
        !           248:                return (ISC_R_BADBASE32);
        !           249:        return (ISC_R_SUCCESS);
        !           250: }
        !           251: 
        !           252: static isc_result_t
        !           253: base32_tobuffer(isc_lex_t *lexer, const char base[], isc_buffer_t *target,
        !           254:                int length)
        !           255: {
        !           256:        base32_decode_ctx_t ctx;
        !           257:        isc_textregion_t *tr;
        !           258:        isc_token_t token;
        !           259:        isc_boolean_t eol;
        !           260: 
        !           261:        base32_decode_init(&ctx, length, base, target);
        !           262: 
        !           263:        while (!ctx.seen_end && (ctx.length != 0)) {
        !           264:                unsigned int i;
        !           265: 
        !           266:                if (length > 0)
        !           267:                        eol = ISC_FALSE;
        !           268:                else
        !           269:                        eol = ISC_TRUE;
        !           270:                RETERR(isc_lex_getmastertoken(lexer, &token,
        !           271:                                              isc_tokentype_string, eol));
        !           272:                if (token.type != isc_tokentype_string)
        !           273:                        break;
        !           274:                tr = &token.value.as_textregion;
        !           275:                for (i = 0; i < tr->length; i++)
        !           276:                        RETERR(base32_decode_char(&ctx, tr->base[i]));
        !           277:        }
        !           278:        if (ctx.length < 0 && !ctx.seen_end)
        !           279:                isc_lex_ungettoken(lexer, &token);
        !           280:        RETERR(base32_decode_finish(&ctx));
        !           281:        return (ISC_R_SUCCESS);
        !           282: }
        !           283: 
        !           284: isc_result_t
        !           285: isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
        !           286:        return (base32_tobuffer(lexer, base32, target, length));
        !           287: }
        !           288: 
        !           289: isc_result_t
        !           290: isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
        !           291:        return (base32_tobuffer(lexer, base32hex, target, length));
        !           292: }
        !           293: 
        !           294: static isc_result_t
        !           295: base32_decodestring(const char *cstr, const char base[], isc_buffer_t *target) {
        !           296:        base32_decode_ctx_t ctx;
        !           297: 
        !           298:        base32_decode_init(&ctx, -1, base, target);
        !           299:        for (;;) {
        !           300:                int c = *cstr++;
        !           301:                if (c == '\0')
        !           302:                        break;
        !           303:                if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
        !           304:                        continue;
        !           305:                RETERR(base32_decode_char(&ctx, c));
        !           306:        }
        !           307:        RETERR(base32_decode_finish(&ctx));
        !           308:        return (ISC_R_SUCCESS);
        !           309: }
        !           310: 
        !           311: isc_result_t
        !           312: isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
        !           313:        return (base32_decodestring(cstr, base32, target));
        !           314: }
        !           315: 
        !           316: isc_result_t
        !           317: isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
        !           318:        return (base32_decodestring(cstr, base32hex, target));
        !           319: }
        !           320: 
        !           321: static isc_result_t
        !           322: base32_decoderegion(isc_region_t *source, const char base[], isc_buffer_t *target) {
        !           323:        base32_decode_ctx_t ctx;
        !           324: 
        !           325:        base32_decode_init(&ctx, -1, base, target);
        !           326:        while (source->length != 0) {
        !           327:                int c = *source->base;
        !           328:                RETERR(base32_decode_char(&ctx, c));
        !           329:                isc_region_consume(source, 1);
        !           330:        }
        !           331:        RETERR(base32_decode_finish(&ctx));
        !           332:        return (ISC_R_SUCCESS);
        !           333: }
        !           334: 
        !           335: isc_result_t
        !           336: isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
        !           337:        return (base32_decoderegion(source, base32, target));
        !           338: }
        !           339: 
        !           340: isc_result_t
        !           341: isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
        !           342:        return (base32_decoderegion(source, base32hex, target));
        !           343: }
        !           344: 
        !           345: static isc_result_t
        !           346: str_totext(const char *source, isc_buffer_t *target) {
        !           347:        unsigned int l;
        !           348:        isc_region_t region;
        !           349: 
        !           350:        isc_buffer_availableregion(target, &region);
        !           351:        l = strlen(source);
        !           352: 
        !           353:        if (l > region.length)
        !           354:                return (ISC_R_NOSPACE);
        !           355: 
        !           356:        memcpy(region.base, source, l);
        !           357:        isc_buffer_add(target, l);
        !           358:        return (ISC_R_SUCCESS);
        !           359: }
        !           360: 
        !           361: static isc_result_t
        !           362: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
        !           363:        isc_region_t tr;
        !           364: 
        !           365:        isc_buffer_availableregion(target, &tr);
        !           366:        if (length > tr.length)
        !           367:                return (ISC_R_NOSPACE);
        !           368:        memcpy(tr.base, base, length);
        !           369:        isc_buffer_add(target, length);
        !           370:        return (ISC_R_SUCCESS);
        !           371: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>