"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/isc/base32.c" (7 Sep 2020, 10912 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "base32.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.11.22_vs_9.11.23.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 
   13 /*! \file */
   14 
   15 #include <config.h>
   16 
   17 #include <stdbool.h>
   18 
   19 #include <isc/base32.h>
   20 #include <isc/buffer.h>
   21 #include <isc/lex.h>
   22 #include <isc/region.h>
   23 #include <isc/string.h>
   24 #include <isc/util.h>
   25 
   26 #define RETERR(x) do { \
   27     isc_result_t _r = (x); \
   28     if (_r != ISC_R_SUCCESS) \
   29         return (_r); \
   30     } while (0)
   31 
   32 
   33 /*@{*/
   34 /*!
   35  * These static functions are also present in lib/dns/rdata.c.  I'm not
   36  * sure where they should go. -- bwelling
   37  */
   38 static isc_result_t
   39 str_totext(const char *source, isc_buffer_t *target);
   40 
   41 static isc_result_t
   42 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
   43 
   44 /*@}*/
   45 
   46 static const char base32[] =
   47      "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
   48 static const char base32hex[] =
   49     "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
   50 
   51 static isc_result_t
   52 base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
   53           isc_buffer_t *target, const char base[], char pad)
   54 {
   55     char buf[9];
   56     unsigned int loops = 0;
   57 
   58     if (wordlength >= 0 && wordlength < 8)
   59         wordlength = 8;
   60 
   61     memset(buf, 0, sizeof(buf));
   62     while (source->length > 0) {
   63         buf[0] = base[((source->base[0]>>3)&0x1f)]; /* 5 + */
   64         if (source->length == 1) {
   65             buf[1] = base[(source->base[0]<<2)&0x1c];
   66             buf[2] = buf[3] = buf[4] = pad;
   67             buf[5] = buf[6] = buf[7] = pad;
   68             RETERR(str_totext(buf, target));
   69             break;
   70         }
   71         buf[1] = base[((source->base[0]<<2)&0x1c)|  /* 3 = 8 */
   72                   ((source->base[1]>>6)&0x03)]; /* 2 + */
   73         buf[2] = base[((source->base[1]>>1)&0x1f)]; /* 5 + */
   74         if (source->length == 2) {
   75             buf[3] = base[(source->base[1]<<4)&0x10];
   76             buf[4] = buf[5] = buf[6] = buf[7] = pad;
   77             RETERR(str_totext(buf, target));
   78             break;
   79         }
   80         buf[3] = base[((source->base[1]<<4)&0x10)|  /* 1 = 8 */
   81                   ((source->base[2]>>4)&0x0f)]; /* 4 + */
   82         if (source->length == 3) {
   83             buf[4] = base[(source->base[2]<<1)&0x1e];
   84             buf[5] = buf[6] = buf[7] = pad;
   85             RETERR(str_totext(buf, target));
   86             break;
   87         }
   88         buf[4] = base[((source->base[2]<<1)&0x1e)|  /* 4 = 8 */
   89                   ((source->base[3]>>7)&0x01)]; /* 1 + */
   90         buf[5] = base[((source->base[3]>>2)&0x1f)]; /* 5 + */
   91         if (source->length == 4) {
   92             buf[6] = base[(source->base[3]<<3)&0x18];
   93             buf[7] = pad;
   94             RETERR(str_totext(buf, target));
   95             break;
   96         }
   97         buf[6] = base[((source->base[3]<<3)&0x18)|  /* 2 = 8 */
   98                   ((source->base[4]>>5)&0x07)]; /* 3 + */
   99         buf[7] = base[source->base[4]&0x1f];        /* 5 = 8 */
  100         RETERR(str_totext(buf, target));
  101         isc_region_consume(source, 5);
  102 
  103         loops++;
  104         if (source->length != 0 && wordlength >= 0 &&
  105             (int)((loops + 1) * 8) >= wordlength)
  106         {
  107             loops = 0;
  108             RETERR(str_totext(wordbreak, target));
  109         }
  110     }
  111     if (source->length > 0)
  112         isc_region_consume(source, source->length);
  113     return (ISC_R_SUCCESS);
  114 }
  115 
  116 isc_result_t
  117 isc_base32_totext(isc_region_t *source, int wordlength,
  118           const char *wordbreak, isc_buffer_t *target)
  119 {
  120     return (base32_totext(source, wordlength, wordbreak, target,
  121                   base32, '='));
  122 }
  123 
  124 isc_result_t
  125 isc_base32hex_totext(isc_region_t *source, int wordlength,
  126              const char *wordbreak, isc_buffer_t *target)
  127 {
  128     return (base32_totext(source, wordlength, wordbreak, target,
  129                   base32hex, '='));
  130 }
  131 
  132 isc_result_t
  133 isc_base32hexnp_totext(isc_region_t *source, int wordlength,
  134              const char *wordbreak, isc_buffer_t *target)
  135 {
  136     return (base32_totext(source, wordlength, wordbreak, target,
  137                   base32hex, 0));
  138 }
  139 
  140 /*%
  141  * State of a base32 decoding process in progress.
  142  */
  143 typedef struct {
  144     int length;     /*%< Desired length of binary data or -1 */
  145     isc_buffer_t *target;   /*%< Buffer for resulting binary data */
  146     int digits;     /*%< Number of buffered base32 digits */
  147     bool seen_end;  /*%< True if "=" end marker seen */
  148     int val[8];
  149     const char *base;   /*%< Which encoding we are using */
  150     int seen_32;        /*%< Number of significant bytes if non zero */
  151     bool pad;   /*%< Expect padding */
  152 } base32_decode_ctx_t;
  153 
  154 static inline void
  155 base32_decode_init(base32_decode_ctx_t *ctx, int length, const char base[],
  156            bool pad, isc_buffer_t *target)
  157 {
  158     ctx->digits = 0;
  159     ctx->seen_end = false;
  160     ctx->seen_32 = 0;
  161     ctx->length = length;
  162     ctx->target = target;
  163     ctx->base = base;
  164     ctx->pad = pad;
  165 }
  166 
  167 static inline isc_result_t
  168 base32_decode_char(base32_decode_ctx_t *ctx, int c) {
  169     const char *s;
  170     unsigned int last;
  171 
  172     if (ctx->seen_end) {
  173         return (ISC_R_BADBASE32);
  174     }
  175     if ((s = strchr(ctx->base, c)) == NULL) {
  176         return (ISC_R_BADBASE32);
  177     }
  178     last = (unsigned int)(s - ctx->base);
  179 
  180     /*
  181      * Handle lower case.
  182      */
  183     if (last > 32) {
  184         last -= 33;
  185     }
  186 
  187     /*
  188      * Check that padding is contiguous.
  189      */
  190     if (last != 32 && ctx->seen_32 != 0) {
  191         return (ISC_R_BADBASE32);
  192     }
  193 
  194     /*
  195      * If padding is not permitted flag padding as a error.
  196      */
  197     if (last == 32 && !ctx->pad) {
  198         return (ISC_R_BADBASE32);
  199     }
  200 
  201     /*
  202      * Check that padding starts at the right place and that
  203      * bits that should be zero are.
  204      * Record how many significant bytes in answer (seen_32).
  205      */
  206     if (last == 32 && ctx->seen_32 == 0) {
  207         switch (ctx->digits) {
  208         case 0:
  209         case 1:
  210             return (ISC_R_BADBASE32);
  211         case 2:
  212             if ((ctx->val[1]&0x03) != 0) {
  213                 return (ISC_R_BADBASE32);
  214             }
  215             ctx->seen_32 = 1;
  216             break;
  217         case 3:
  218             return (ISC_R_BADBASE32);
  219         case 4:
  220             if ((ctx->val[3]&0x0f) != 0) {
  221                 return (ISC_R_BADBASE32);
  222             }
  223             ctx->seen_32 = 2;
  224             break;
  225         case 5:
  226             if ((ctx->val[4]&0x01) != 0) {
  227                 return (ISC_R_BADBASE32);
  228             }
  229             ctx->seen_32 = 3;
  230             break;
  231         case 6:
  232             return (ISC_R_BADBASE32);
  233         case 7:
  234             if ((ctx->val[6]&0x07) != 0) {
  235                 return (ISC_R_BADBASE32);
  236             }
  237             ctx->seen_32 = 4;
  238             break;
  239         }
  240     }
  241 
  242     /*
  243      * Zero fill pad values.
  244      */
  245     ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
  246 
  247     if (ctx->digits == 8) {
  248         int n = 5;
  249         unsigned char buf[5];
  250 
  251         if (ctx->seen_32 != 0) {
  252             ctx->seen_end = true;
  253             n = ctx->seen_32;
  254         }
  255         buf[0] = (ctx->val[0]<<3)|(ctx->val[1]>>2);
  256         buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
  257         buf[2] = (ctx->val[3]<<4)|(ctx->val[4]>>1);
  258         buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
  259         buf[4] = (ctx->val[6]<<5)|(ctx->val[7]);
  260         RETERR(mem_tobuffer(ctx->target, buf, n));
  261         if (ctx->length >= 0) {
  262             if (n > ctx->length) {
  263                 return (ISC_R_BADBASE32);
  264             } else {
  265                 ctx->length -= n;
  266             }
  267         }
  268         ctx->digits = 0;
  269     }
  270     return (ISC_R_SUCCESS);
  271 }
  272 
  273 static inline isc_result_t
  274 base32_decode_finish(base32_decode_ctx_t *ctx) {
  275 
  276     if (ctx->length > 0)
  277         return (ISC_R_UNEXPECTEDEND);
  278     /*
  279      * Add missing padding if required.
  280      */
  281     if (!ctx->pad && ctx->digits != 0) {
  282         ctx->pad = true;
  283         do {
  284             RETERR(base32_decode_char(ctx, '='));
  285         } while (ctx->digits != 0);
  286     }
  287     if (ctx->digits != 0)
  288         return (ISC_R_BADBASE32);
  289     return (ISC_R_SUCCESS);
  290 }
  291 
  292 static isc_result_t
  293 base32_tobuffer(isc_lex_t *lexer, const char base[], bool pad,
  294         isc_buffer_t *target, int length)
  295 {
  296     unsigned int before, after;
  297     base32_decode_ctx_t ctx;
  298     isc_textregion_t *tr;
  299     isc_token_t token;
  300     bool eol;
  301 
  302     REQUIRE(length >= -2);
  303 
  304     base32_decode_init(&ctx, length, base, pad, target);
  305 
  306     before = isc_buffer_usedlength(target);
  307     while (!ctx.seen_end && (ctx.length != 0)) {
  308         unsigned int i;
  309 
  310         if (length > 0) {
  311             eol = false;
  312         } else {
  313             eol = true;
  314         }
  315         RETERR(isc_lex_getmastertoken(lexer, &token,
  316                           isc_tokentype_string, eol));
  317         if (token.type != isc_tokentype_string) {
  318             break;
  319         }
  320         tr = &token.value.as_textregion;
  321         for (i = 0; i < tr->length; i++) {
  322             RETERR(base32_decode_char(&ctx, tr->base[i]));
  323         }
  324     }
  325     after = isc_buffer_usedlength(target);
  326     if (ctx.length < 0 && !ctx.seen_end) {
  327         isc_lex_ungettoken(lexer, &token);
  328     }
  329     RETERR(base32_decode_finish(&ctx));
  330     if (length == -2 && before == after) {
  331         return (ISC_R_UNEXPECTEDEND);
  332     }
  333     return (ISC_R_SUCCESS);
  334 }
  335 
  336 isc_result_t
  337 isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
  338     return (base32_tobuffer(lexer, base32, true, target, length));
  339 }
  340 
  341 isc_result_t
  342 isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
  343     return (base32_tobuffer(lexer, base32hex, true, target, length));
  344 }
  345 
  346 isc_result_t
  347 isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
  348     return (base32_tobuffer(lexer, base32hex, false, target, length));
  349 }
  350 
  351 static isc_result_t
  352 base32_decodestring(const char *cstr, const char base[], bool pad,
  353             isc_buffer_t *target)
  354 {
  355     base32_decode_ctx_t ctx;
  356 
  357     base32_decode_init(&ctx, -1, base, pad, target);
  358     for (;;) {
  359         int c = *cstr++;
  360         if (c == '\0')
  361             break;
  362         if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
  363             continue;
  364         RETERR(base32_decode_char(&ctx, c));
  365     }
  366     RETERR(base32_decode_finish(&ctx));
  367     return (ISC_R_SUCCESS);
  368 }
  369 
  370 isc_result_t
  371 isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
  372     return (base32_decodestring(cstr, base32, true, target));
  373 }
  374 
  375 isc_result_t
  376 isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
  377     return (base32_decodestring(cstr, base32hex, true, target));
  378 }
  379 
  380 isc_result_t
  381 isc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target) {
  382     return (base32_decodestring(cstr, base32hex, false, target));
  383 }
  384 
  385 static isc_result_t
  386 base32_decoderegion(isc_region_t *source, const char base[],
  387             bool pad, isc_buffer_t *target)
  388 {
  389     base32_decode_ctx_t ctx;
  390 
  391     base32_decode_init(&ctx, -1, base, pad, target);
  392     while (source->length != 0) {
  393         int c = *source->base;
  394         RETERR(base32_decode_char(&ctx, c));
  395         isc_region_consume(source, 1);
  396     }
  397     RETERR(base32_decode_finish(&ctx));
  398     return (ISC_R_SUCCESS);
  399 }
  400 
  401 isc_result_t
  402 isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
  403     return (base32_decoderegion(source, base32, true, target));
  404 }
  405 
  406 isc_result_t
  407 isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
  408     return (base32_decoderegion(source, base32hex, true, target));
  409 }
  410 
  411 isc_result_t
  412 isc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target) {
  413     return (base32_decoderegion(source, base32hex, false, target));
  414 }
  415 
  416 static isc_result_t
  417 str_totext(const char *source, isc_buffer_t *target) {
  418     unsigned int l;
  419     isc_region_t region;
  420 
  421     isc_buffer_availableregion(target, &region);
  422     l = strlen(source);
  423 
  424     if (l > region.length)
  425         return (ISC_R_NOSPACE);
  426 
  427     memmove(region.base, source, l);
  428     isc_buffer_add(target, l);
  429     return (ISC_R_SUCCESS);
  430 }
  431 
  432 static isc_result_t
  433 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
  434     isc_region_t tr;
  435 
  436     isc_buffer_availableregion(target, &tr);
  437     if (length > tr.length)
  438         return (ISC_R_NOSPACE);
  439     memmove(tr.base, base, length);
  440     isc_buffer_add(target, length);
  441     return (ISC_R_SUCCESS);
  442 }