"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/crypto_backend/argon2/encoding.c" (13 Jan 2022, 16268 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


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 "encoding.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Argon2 reference source code package - reference C implementations
    3  *
    4  * Copyright 2015
    5  * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
    6  *
    7  * You may use this work under the terms of a Creative Commons CC0 1.0
    8  * License/Waiver or the Apache Public License 2.0, at your option. The terms of
    9  * these licenses can be found at:
   10  *
   11  * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
   12  * - Apache 2.0        : https://www.apache.org/licenses/LICENSE-2.0
   13  *
   14  * You should have received a copy of both of these licenses along with this
   15  * software. If not, they may be obtained at the above URLs.
   16  */
   17 
   18 #include <stdio.h>
   19 #include <stdlib.h>
   20 #include <string.h>
   21 #include <limits.h>
   22 #include "encoding.h"
   23 #include "core.h"
   24 
   25 /*
   26  * Example code for a decoder and encoder of "hash strings", with Argon2
   27  * parameters.
   28  *
   29  * This code comprises three sections:
   30  *
   31  *   -- The first section contains generic Base64 encoding and decoding
   32  *   functions. It is conceptually applicable to any hash function
   33  *   implementation that uses Base64 to encode and decode parameters,
   34  *   salts and outputs. It could be made into a library, provided that
   35  *   the relevant functions are made public (non-static) and be given
   36  *   reasonable names to avoid collisions with other functions.
   37  *
   38  *   -- The second section is specific to Argon2. It encodes and decodes
   39  *   the parameters, salts and outputs. It does not compute the hash
   40  *   itself.
   41  *
   42  * The code was originally written by Thomas Pornin <pornin@bolet.org>,
   43  * to whom comments and remarks may be sent. It is released under what
   44  * should amount to Public Domain or its closest equivalent; the
   45  * following mantra is supposed to incarnate that fact with all the
   46  * proper legal rituals:
   47  *
   48  * ---------------------------------------------------------------------
   49  * This file is provided under the terms of Creative Commons CC0 1.0
   50  * Public Domain Dedication. To the extent possible under law, the
   51  * author (Thomas Pornin) has waived all copyright and related or
   52  * neighboring rights to this file. This work is published from: Canada.
   53  * ---------------------------------------------------------------------
   54  *
   55  * Copyright (c) 2015 Thomas Pornin
   56  */
   57 
   58 /* ==================================================================== */
   59 /*
   60  * Common code; could be shared between different hash functions.
   61  *
   62  * Note: the Base64 functions below assume that uppercase letters (resp.
   63  * lowercase letters) have consecutive numerical codes, that fit on 8
   64  * bits. All modern systems use ASCII-compatible charsets, where these
   65  * properties are true. If you are stuck with a dinosaur of a system
   66  * that still defaults to EBCDIC then you already have much bigger
   67  * interoperability issues to deal with.
   68  */
   69 
   70 /*
   71  * Some macros for constant-time comparisons. These work over values in
   72  * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
   73  */
   74 #define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
   75 #define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
   76 #define GE(x, y) (GT(y, x) ^ 0xFF)
   77 #define LT(x, y) GT(y, x)
   78 #define LE(x, y) GE(y, x)
   79 
   80 /*
   81  * Convert value x (0..63) to corresponding Base64 character.
   82  */
   83 static int b64_byte_to_char(unsigned x) {
   84     return (LT(x, 26) & (x + 'A')) |
   85            (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
   86            (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
   87            (EQ(x, 63) & '/');
   88 }
   89 
   90 /*
   91  * Convert character c to the corresponding 6-bit value. If character c
   92  * is not a Base64 character, then 0xFF (255) is returned.
   93  */
   94 static unsigned b64_char_to_byte(int c) {
   95     unsigned x;
   96 
   97     x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
   98         (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
   99         (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
  100         (EQ(c, '/') & 63);
  101     return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
  102 }
  103 
  104 /*
  105  * Convert some bytes to Base64. 'dst_len' is the length (in characters)
  106  * of the output buffer 'dst'; if that buffer is not large enough to
  107  * receive the result (including the terminating 0), then (size_t)-1
  108  * is returned. Otherwise, the zero-terminated Base64 string is written
  109  * in the buffer, and the output length (counted WITHOUT the terminating
  110  * zero) is returned.
  111  */
  112 static size_t to_base64(char *dst, size_t dst_len, const void *src,
  113                         size_t src_len) {
  114     size_t olen;
  115     const unsigned char *buf;
  116     unsigned acc, acc_len;
  117 
  118     olen = (src_len / 3) << 2;
  119     switch (src_len % 3) {
  120     case 2:
  121         olen++;
  122     /* fall through */
  123     case 1:
  124         olen += 2;
  125         break;
  126     }
  127     if (dst_len <= olen) {
  128         return (size_t)-1;
  129     }
  130     acc = 0;
  131     acc_len = 0;
  132     buf = (const unsigned char *)src;
  133     while (src_len-- > 0) {
  134         acc = (acc << 8) + (*buf++);
  135         acc_len += 8;
  136         while (acc_len >= 6) {
  137             acc_len -= 6;
  138             *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
  139         }
  140     }
  141     if (acc_len > 0) {
  142         *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
  143     }
  144     *dst++ = 0;
  145     return olen;
  146 }
  147 
  148 /*
  149  * Decode Base64 chars into bytes. The '*dst_len' value must initially
  150  * contain the length of the output buffer '*dst'; when the decoding
  151  * ends, the actual number of decoded bytes is written back in
  152  * '*dst_len'.
  153  *
  154  * Decoding stops when a non-Base64 character is encountered, or when
  155  * the output buffer capacity is exceeded. If an error occurred (output
  156  * buffer is too small, invalid last characters leading to unprocessed
  157  * buffered bits), then NULL is returned; otherwise, the returned value
  158  * points to the first non-Base64 character in the source stream, which
  159  * may be the terminating zero.
  160  */
  161 static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
  162     size_t len;
  163     unsigned char *buf;
  164     unsigned acc, acc_len;
  165 
  166     buf = (unsigned char *)dst;
  167     len = 0;
  168     acc = 0;
  169     acc_len = 0;
  170     for (;;) {
  171         unsigned d;
  172 
  173         d = b64_char_to_byte(*src);
  174         if (d == 0xFF) {
  175             break;
  176         }
  177         src++;
  178         acc = (acc << 6) + d;
  179         acc_len += 6;
  180         if (acc_len >= 8) {
  181             acc_len -= 8;
  182             if ((len++) >= *dst_len) {
  183                 return NULL;
  184             }
  185             *buf++ = (acc >> acc_len) & 0xFF;
  186         }
  187     }
  188 
  189     /*
  190      * If the input length is equal to 1 modulo 4 (which is
  191      * invalid), then there will remain 6 unprocessed bits;
  192      * otherwise, only 0, 2 or 4 bits are buffered. The buffered
  193      * bits must also all be zero.
  194      */
  195     if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
  196         return NULL;
  197     }
  198     *dst_len = len;
  199     return src;
  200 }
  201 
  202 /*
  203  * Decode decimal integer from 'str'; the value is written in '*v'.
  204  * Returned value is a pointer to the next non-decimal character in the
  205  * string. If there is no digit at all, or the value encoding is not
  206  * minimal (extra leading zeros), or the value does not fit in an
  207  * 'unsigned long', then NULL is returned.
  208  */
  209 static const char *decode_decimal(const char *str, unsigned long *v) {
  210     const char *orig;
  211     unsigned long acc;
  212 
  213     acc = 0;
  214     for (orig = str;; str++) {
  215         int c;
  216 
  217         c = *str;
  218         if (c < '0' || c > '9') {
  219             break;
  220         }
  221         c -= '0';
  222         if (acc > (ULONG_MAX / 10)) {
  223             return NULL;
  224         }
  225         acc *= 10;
  226         if ((unsigned long)c > (ULONG_MAX - acc)) {
  227             return NULL;
  228         }
  229         acc += (unsigned long)c;
  230     }
  231     if (str == orig || (*orig == '0' && str != (orig + 1))) {
  232         return NULL;
  233     }
  234     *v = acc;
  235     return str;
  236 }
  237 
  238 /* ==================================================================== */
  239 /*
  240  * Code specific to Argon2.
  241  *
  242  * The code below applies the following format:
  243  *
  244  *  $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
  245  *
  246  * where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
  247  * fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
  248  * characters, no newline or whitespace).
  249  *
  250  * The last two binary chunks (encoded in Base64) are, in that order,
  251  * the salt and the output. Both are required. The binary salt length and the
  252  * output length must be in the allowed ranges defined in argon2.h.
  253  *
  254  * The ctx struct must contain buffers large enough to hold the salt and pwd
  255  * when it is fed into decode_string.
  256  */
  257 
  258 int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
  259 
  260 /* check for prefix */
  261 #define CC(prefix)                                                             \
  262     do {                                                                       \
  263         size_t cc_len = strlen(prefix);                                        \
  264         if (strncmp(str, prefix, cc_len) != 0) {                               \
  265             return ARGON2_DECODING_FAIL;                                       \
  266         }                                                                      \
  267         str += cc_len;                                                         \
  268     } while ((void)0, 0)
  269 
  270 /* optional prefix checking with supplied code */
  271 #define CC_opt(prefix, code)                                                   \
  272     do {                                                                       \
  273         size_t cc_len = strlen(prefix);                                        \
  274         if (strncmp(str, prefix, cc_len) == 0) {                               \
  275             str += cc_len;                                                     \
  276             { code; }                                                          \
  277         }                                                                      \
  278     } while ((void)0, 0)
  279 
  280 /* Decoding prefix into decimal */
  281 #define DECIMAL(x)                                                             \
  282     do {                                                                       \
  283         unsigned long dec_x;                                                   \
  284         str = decode_decimal(str, &dec_x);                                     \
  285         if (str == NULL) {                                                     \
  286             return ARGON2_DECODING_FAIL;                                       \
  287         }                                                                      \
  288         (x) = dec_x;                                                           \
  289     } while ((void)0, 0)
  290 
  291 
  292 /* Decoding prefix into uint32_t decimal */
  293 #define DECIMAL_U32(x)                                                         \
  294     do {                                                                       \
  295         unsigned long dec_x;                                                   \
  296         str = decode_decimal(str, &dec_x);                                     \
  297         if (str == NULL || dec_x > UINT32_MAX) {                               \
  298             return ARGON2_DECODING_FAIL;                                       \
  299         }                                                                      \
  300         (x) = (uint32_t)dec_x;                                                 \
  301     } while ((void)0, 0)
  302 
  303 
  304 /* Decoding base64 into a binary buffer */
  305 #define BIN(buf, max_len, len)                                                 \
  306     do {                                                                       \
  307         size_t bin_len = (max_len);                                            \
  308         str = from_base64(buf, &bin_len, str);                                 \
  309         if (str == NULL || bin_len > UINT32_MAX) {                             \
  310             return ARGON2_DECODING_FAIL;                                       \
  311         }                                                                      \
  312         (len) = (uint32_t)bin_len;                                             \
  313     } while ((void)0, 0)
  314 
  315     size_t maxsaltlen = ctx->saltlen;
  316     size_t maxoutlen = ctx->outlen;
  317     int validation_result;
  318     const char* type_string;
  319 
  320     /* We should start with the argon2_type we are using */
  321     type_string = argon2_type2string(type, 0);
  322     if (!type_string) {
  323         return ARGON2_INCORRECT_TYPE;
  324     }
  325 
  326     CC("$");
  327     CC(type_string);
  328 
  329     /* Reading the version number if the default is suppressed */
  330     ctx->version = ARGON2_VERSION_10;
  331     CC_opt("$v=", DECIMAL_U32(ctx->version));
  332 
  333     CC("$m=");
  334     DECIMAL_U32(ctx->m_cost);
  335     CC(",t=");
  336     DECIMAL_U32(ctx->t_cost);
  337     CC(",p=");
  338     DECIMAL_U32(ctx->lanes);
  339     ctx->threads = ctx->lanes;
  340 
  341     CC("$");
  342     BIN(ctx->salt, maxsaltlen, ctx->saltlen);
  343     CC("$");
  344     BIN(ctx->out, maxoutlen, ctx->outlen);
  345 
  346     /* The rest of the fields get the default values */
  347     ctx->secret = NULL;
  348     ctx->secretlen = 0;
  349     ctx->ad = NULL;
  350     ctx->adlen = 0;
  351     ctx->allocate_cbk = NULL;
  352     ctx->free_cbk = NULL;
  353     ctx->flags = ARGON2_DEFAULT_FLAGS;
  354 
  355     /* On return, must have valid context */
  356     validation_result = validate_inputs(ctx);
  357     if (validation_result != ARGON2_OK) {
  358         return validation_result;
  359     }
  360 
  361     /* Can't have any additional characters */
  362     if (*str == 0) {
  363         return ARGON2_OK;
  364     } else {
  365         return ARGON2_DECODING_FAIL;
  366     }
  367 #undef CC
  368 #undef CC_opt
  369 #undef DECIMAL
  370 #undef BIN
  371 }
  372 
  373 int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
  374                   argon2_type type) {
  375 #define SS(str)                                                                \
  376     do {                                                                       \
  377         size_t pp_len = strlen(str);                                           \
  378         if (pp_len >= dst_len) {                                               \
  379             return ARGON2_ENCODING_FAIL;                                       \
  380         }                                                                      \
  381         memcpy(dst, str, pp_len + 1);                                          \
  382         dst += pp_len;                                                         \
  383         dst_len -= pp_len;                                                     \
  384     } while ((void)0, 0)
  385 
  386 #define SX(x)                                                                  \
  387     do {                                                                       \
  388         char tmp[30];                                                          \
  389         sprintf(tmp, "%lu", (unsigned long)(x));                               \
  390         SS(tmp);                                                               \
  391     } while ((void)0, 0)
  392 
  393 #define SB(buf, len)                                                           \
  394     do {                                                                       \
  395         size_t sb_len = to_base64(dst, dst_len, buf, len);                     \
  396         if (sb_len == (size_t)-1) {                                            \
  397             return ARGON2_ENCODING_FAIL;                                       \
  398         }                                                                      \
  399         dst += sb_len;                                                         \
  400         dst_len -= sb_len;                                                     \
  401     } while ((void)0, 0)
  402 
  403     const char* type_string = argon2_type2string(type, 0);
  404     int validation_result = validate_inputs(ctx);
  405 
  406     if (!type_string) {
  407       return ARGON2_ENCODING_FAIL;
  408     }
  409 
  410     if (validation_result != ARGON2_OK) {
  411       return validation_result;
  412     }
  413 
  414 
  415     SS("$");
  416     SS(type_string);
  417 
  418     SS("$v=");
  419     SX(ctx->version);
  420 
  421     SS("$m=");
  422     SX(ctx->m_cost);
  423     SS(",t=");
  424     SX(ctx->t_cost);
  425     SS(",p=");
  426     SX(ctx->lanes);
  427 
  428     SS("$");
  429     SB(ctx->salt, ctx->saltlen);
  430 
  431     SS("$");
  432     SB(ctx->out, ctx->outlen);
  433     return ARGON2_OK;
  434 
  435 #undef SS
  436 #undef SX
  437 #undef SB
  438 }
  439 
  440 size_t b64len(uint32_t len) {
  441     size_t olen = ((size_t)len / 3) << 2;
  442 
  443     switch (len % 3) {
  444     case 2:
  445         olen++;
  446     /* fall through */
  447     case 1:
  448         olen += 2;
  449         break;
  450     }
  451 
  452     return olen;
  453 }
  454 
  455 size_t numlen(uint32_t num) {
  456     size_t len = 1;
  457     while (num >= 10) {
  458         ++len;
  459         num = num / 10;
  460     }
  461     return len;
  462 }