00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <isc/base32.h>
00024 #include <isc/buffer.h>
00025 #include <isc/lex.h>
00026 #include <isc/region.h>
00027 #include <isc/string.h>
00028 #include <isc/util.h>
00029
00030 #define RETERR(x) do { \
00031 isc_result_t _r = (x); \
00032 if (_r != ISC_R_SUCCESS) \
00033 return (_r); \
00034 } while (0)
00035
00036
00037
00038
00039
00040
00041
00042 static isc_result_t
00043 str_totext(const char *source, isc_buffer_t *target);
00044
00045 static isc_result_t
00046 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
00047
00048
00049
00050 static const char base32[] =
00051 "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
00052 static const char base32hex[] =
00053 "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
00054
00055 static isc_result_t
00056 base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
00057 isc_buffer_t *target, const char base[], char pad)
00058 {
00059 char buf[9];
00060 unsigned int loops = 0;
00061
00062 if (wordlength >= 0 && wordlength < 8)
00063 wordlength = 8;
00064
00065 memset(buf, 0, sizeof(buf));
00066 while (source->length > 0) {
00067 buf[0] = base[((source->base[0]>>3)&0x1f)];
00068 if (source->length == 1) {
00069 buf[1] = base[(source->base[0]<<2)&0x1c];
00070 buf[2] = buf[3] = buf[4] = pad;
00071 buf[5] = buf[6] = buf[7] = pad;
00072 RETERR(str_totext(buf, target));
00073 break;
00074 }
00075 buf[1] = base[((source->base[0]<<2)&0x1c)|
00076 ((source->base[1]>>6)&0x03)];
00077 buf[2] = base[((source->base[1]>>1)&0x1f)];
00078 if (source->length == 2) {
00079 buf[3] = base[(source->base[1]<<4)&0x10];
00080 buf[4] = buf[5] = buf[6] = buf[7] = pad;
00081 RETERR(str_totext(buf, target));
00082 break;
00083 }
00084 buf[3] = base[((source->base[1]<<4)&0x10)|
00085 ((source->base[2]>>4)&0x0f)];
00086 if (source->length == 3) {
00087 buf[4] = base[(source->base[2]<<1)&0x1e];
00088 buf[5] = buf[6] = buf[7] = pad;
00089 RETERR(str_totext(buf, target));
00090 break;
00091 }
00092 buf[4] = base[((source->base[2]<<1)&0x1e)|
00093 ((source->base[3]>>7)&0x01)];
00094 buf[5] = base[((source->base[3]>>2)&0x1f)];
00095 if (source->length == 4) {
00096 buf[6] = base[(source->base[3]<<3)&0x18];
00097 buf[7] = pad;
00098 RETERR(str_totext(buf, target));
00099 break;
00100 }
00101 buf[6] = base[((source->base[3]<<3)&0x18)|
00102 ((source->base[4]>>5)&0x07)];
00103 buf[7] = base[source->base[4]&0x1f];
00104 RETERR(str_totext(buf, target));
00105 isc_region_consume(source, 5);
00106
00107 loops++;
00108 if (source->length != 0 && wordlength >= 0 &&
00109 (int)((loops + 1) * 8) >= wordlength)
00110 {
00111 loops = 0;
00112 RETERR(str_totext(wordbreak, target));
00113 }
00114 }
00115 if (source->length > 0)
00116 isc_region_consume(source, source->length);
00117 return (ISC_R_SUCCESS);
00118 }
00119
00120 isc_result_t
00121 isc_base32_totext(isc_region_t *source, int wordlength,
00122 const char *wordbreak, isc_buffer_t *target)
00123 {
00124 return (base32_totext(source, wordlength, wordbreak, target,
00125 base32, '='));
00126 }
00127
00128 isc_result_t
00129 isc_base32hex_totext(isc_region_t *source, int wordlength,
00130 const char *wordbreak, isc_buffer_t *target)
00131 {
00132 return (base32_totext(source, wordlength, wordbreak, target,
00133 base32hex, '='));
00134 }
00135
00136 isc_result_t
00137 isc_base32hexnp_totext(isc_region_t *source, int wordlength,
00138 const char *wordbreak, isc_buffer_t *target)
00139 {
00140 return (base32_totext(source, wordlength, wordbreak, target,
00141 base32hex, 0));
00142 }
00143
00144
00145
00146
00147 typedef struct {
00148 int length;
00149 isc_buffer_t *target;
00150 int digits;
00151 isc_boolean_t seen_end;
00152 int val[8];
00153 const char *base;
00154 int seen_32;
00155 isc_boolean_t pad;
00156 } base32_decode_ctx_t;
00157
00158 static inline void
00159 base32_decode_init(base32_decode_ctx_t *ctx, int length, const char base[],
00160 isc_boolean_t pad, isc_buffer_t *target)
00161 {
00162 ctx->digits = 0;
00163 ctx->seen_end = ISC_FALSE;
00164 ctx->seen_32 = 0;
00165 ctx->length = length;
00166 ctx->target = target;
00167 ctx->base = base;
00168 ctx->pad = pad;
00169 }
00170
00171 static inline isc_result_t
00172 base32_decode_char(base32_decode_ctx_t *ctx, int c) {
00173 char *s;
00174 unsigned int last;
00175
00176 if (ctx->seen_end)
00177 return (ISC_R_BADBASE32);
00178 if ((s = strchr(ctx->base, c)) == NULL)
00179 return (ISC_R_BADBASE32);
00180 last = (unsigned int)(s - ctx->base);
00181
00182
00183
00184
00185 if (last > 32)
00186 last -= 33;
00187
00188
00189
00190
00191 if (last != 32 && ctx->seen_32 != 0)
00192 return (ISC_R_BADBASE32);
00193
00194
00195
00196
00197 if (last == 32 && !ctx->pad)
00198 return (ISC_R_BADBASE32);
00199
00200
00201
00202
00203
00204
00205 if (last == 32 && ctx->seen_32 == 0)
00206 switch (ctx->digits) {
00207 case 0:
00208 case 1:
00209 return (ISC_R_BADBASE32);
00210 case 2:
00211 if ((ctx->val[1]&0x03) != 0)
00212 return (ISC_R_BADBASE32);
00213 ctx->seen_32 = 1;
00214 break;
00215 case 3:
00216 return (ISC_R_BADBASE32);
00217 case 4:
00218 if ((ctx->val[3]&0x0f) != 0)
00219 return (ISC_R_BADBASE32);
00220 ctx->seen_32 = 3;
00221 break;
00222 case 5:
00223 if ((ctx->val[4]&0x01) != 0)
00224 return (ISC_R_BADBASE32);
00225 ctx->seen_32 = 3;
00226 break;
00227 case 6:
00228 return (ISC_R_BADBASE32);
00229 case 7:
00230 if ((ctx->val[6]&0x07) != 0)
00231 return (ISC_R_BADBASE32);
00232 ctx->seen_32 = 4;
00233 break;
00234 }
00235
00236
00237
00238
00239 ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
00240
00241 if (ctx->digits == 8) {
00242 int n = 5;
00243 unsigned char buf[5];
00244
00245 if (ctx->seen_32 != 0) {
00246 ctx->seen_end = ISC_TRUE;
00247 n = ctx->seen_32;
00248 }
00249 buf[0] = (ctx->val[0]<<3)|(ctx->val[1]>>2);
00250 buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
00251 buf[2] = (ctx->val[3]<<4)|(ctx->val[4]>>1);
00252 buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
00253 buf[4] = (ctx->val[6]<<5)|(ctx->val[7]);
00254 RETERR(mem_tobuffer(ctx->target, buf, n));
00255 if (ctx->length >= 0) {
00256 if (n > ctx->length)
00257 return (ISC_R_BADBASE32);
00258 else
00259 ctx->length -= n;
00260 }
00261 ctx->digits = 0;
00262 }
00263 return (ISC_R_SUCCESS);
00264 }
00265
00266 static inline isc_result_t
00267 base32_decode_finish(base32_decode_ctx_t *ctx) {
00268
00269 if (ctx->length > 0)
00270 return (ISC_R_UNEXPECTEDEND);
00271
00272
00273
00274 if (!ctx->pad && ctx->digits != 0) {
00275 ctx->pad = ISC_TRUE;
00276 do {
00277 RETERR(base32_decode_char(ctx, '='));
00278 } while (ctx->digits != 0);
00279 }
00280 if (ctx->digits != 0)
00281 return (ISC_R_BADBASE32);
00282 return (ISC_R_SUCCESS);
00283 }
00284
00285 static isc_result_t
00286 base32_tobuffer(isc_lex_t *lexer, const char base[], isc_boolean_t pad,
00287 isc_buffer_t *target, int length)
00288 {
00289 base32_decode_ctx_t ctx;
00290 isc_textregion_t *tr;
00291 isc_token_t token;
00292 isc_boolean_t eol;
00293
00294 base32_decode_init(&ctx, length, base, pad, target);
00295
00296 while (!ctx.seen_end && (ctx.length != 0)) {
00297 unsigned int i;
00298
00299 if (length > 0)
00300 eol = ISC_FALSE;
00301 else
00302 eol = ISC_TRUE;
00303 RETERR(isc_lex_getmastertoken(lexer, &token,
00304 isc_tokentype_string, eol));
00305 if (token.type != isc_tokentype_string)
00306 break;
00307 tr = &token.value.as_textregion;
00308 for (i = 0; i < tr->length; i++)
00309 RETERR(base32_decode_char(&ctx, tr->base[i]));
00310 }
00311 if (ctx.length < 0 && !ctx.seen_end)
00312 isc_lex_ungettoken(lexer, &token);
00313 RETERR(base32_decode_finish(&ctx));
00314 return (ISC_R_SUCCESS);
00315 }
00316
00317 isc_result_t
00318 isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
00319 return (base32_tobuffer(lexer, base32, ISC_TRUE, target, length));
00320 }
00321
00322 isc_result_t
00323 isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
00324 return (base32_tobuffer(lexer, base32hex, ISC_TRUE, target, length));
00325 }
00326
00327 isc_result_t
00328 isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
00329 return (base32_tobuffer(lexer, base32hex, ISC_FALSE, target, length));
00330 }
00331
00332 static isc_result_t
00333 base32_decodestring(const char *cstr, const char base[], isc_boolean_t pad,
00334 isc_buffer_t *target)
00335 {
00336 base32_decode_ctx_t ctx;
00337
00338 base32_decode_init(&ctx, -1, base, pad, target);
00339 for (;;) {
00340 int c = *cstr++;
00341 if (c == '\0')
00342 break;
00343 if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
00344 continue;
00345 RETERR(base32_decode_char(&ctx, c));
00346 }
00347 RETERR(base32_decode_finish(&ctx));
00348 return (ISC_R_SUCCESS);
00349 }
00350
00351 isc_result_t
00352 isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
00353 return (base32_decodestring(cstr, base32, ISC_TRUE, target));
00354 }
00355
00356 isc_result_t
00357 isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
00358 return (base32_decodestring(cstr, base32hex, ISC_TRUE, target));
00359 }
00360
00361 isc_result_t
00362 isc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target) {
00363 return (base32_decodestring(cstr, base32hex, ISC_FALSE, target));
00364 }
00365
00366 static isc_result_t
00367 base32_decoderegion(isc_region_t *source, const char base[],
00368 isc_boolean_t pad, isc_buffer_t *target)
00369 {
00370 base32_decode_ctx_t ctx;
00371
00372 base32_decode_init(&ctx, -1, base, pad, target);
00373 while (source->length != 0) {
00374 int c = *source->base;
00375 RETERR(base32_decode_char(&ctx, c));
00376 isc_region_consume(source, 1);
00377 }
00378 RETERR(base32_decode_finish(&ctx));
00379 return (ISC_R_SUCCESS);
00380 }
00381
00382 isc_result_t
00383 isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
00384 return (base32_decoderegion(source, base32, ISC_TRUE, target));
00385 }
00386
00387 isc_result_t
00388 isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
00389 return (base32_decoderegion(source, base32hex, ISC_TRUE, target));
00390 }
00391
00392 isc_result_t
00393 isc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target) {
00394 return (base32_decoderegion(source, base32hex, ISC_FALSE, target));
00395 }
00396
00397 static isc_result_t
00398 str_totext(const char *source, isc_buffer_t *target) {
00399 unsigned int l;
00400 isc_region_t region;
00401
00402 isc_buffer_availableregion(target, ®ion);
00403 l = strlen(source);
00404
00405 if (l > region.length)
00406 return (ISC_R_NOSPACE);
00407
00408 memmove(region.base, source, l);
00409 isc_buffer_add(target, l);
00410 return (ISC_R_SUCCESS);
00411 }
00412
00413 static isc_result_t
00414 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
00415 isc_region_t tr;
00416
00417 isc_buffer_availableregion(target, &tr);
00418 if (length > tr.length)
00419 return (ISC_R_NOSPACE);
00420 memmove(tr.base, base, length);
00421 isc_buffer_add(target, length);
00422 return (ISC_R_SUCCESS);
00423 }