💾 Archived View for gmi.noulin.net › gitRepositories › liveserver › file › utilities.c.gmi captured on 2023-01-29 at 13:16:56. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

liveserver

Log

Files

Refs

README

LICENSE

utilities.c (13003B)

     1 /*
     2   utilities.c
     3 
     4     Jonathan D. Hall - jhall@futuresouth.us
     5     Copyright 2015 Future South Technologies
     6 
     7     This file is part of libwebsock2.
     8 
     9     libwebsock2 is free software: you can redistribute it and/or modify
    10     it under the terms of the GNU General Public License as published by
    11     the Free Software Foundation, either version 3 of the License, or
    12     (at your option) any later version.
    13 
    14     libwebsock2 is distributed in the hope that it will be useful,
    15     but WITHOUT ANY WARRANTY; without even the implied warranty of
    16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17     GNU General Public License for more details.
    18 
    19     You should have received a copy of the GNU General Public License
    20     along with libwebsock2.  If not, see <http://www.gnu.org/licenses/>.
    21 
    22 */
    23 
    24 #include "utilities.h"
    25 
    26 #define UTF8_ACCEPT 0
    27 #define UTF8_REJECT 1
    28 
    29 #define SHA1CircularShift(bits,word) \
    30 ((((word) << (bits)) & 0xFFFFFFFF) | \
    31 ((word) >> (32-(bits))))
    32 
    33 uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte);
    34 
    35 //these functions assume little endian machine as they're only used on windows
    36 uint16_t lws_htobe16(uint16_t x)
    37 {
    38     return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
    39 }
    40 
    41 uint16_t lws_be16toh(uint16_t x)
    42 {
    43     return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
    44 }
    45 
    46 uint64_t lws_htobe64(uint64_t x)
    47 {
    48     return (x >> 56) |
    49     ((x << 40) & 0x00ff000000000000LL) |
    50     ((x << 24) & 0x0000ff0000000000LL) |
    51     ((x << 8) & 0x000000ff00000000LL) |
    52     ((x >> 8) & 0x00000000ff000000LL) |
    53     ((x >> 24) & 0x0000000000ff0000LL) |
    54     ((x >> 40) & 0x000000000000ff00LL) |
    55     (x << 56);
    56 }
    57 
    58 uint64_t lws_be64toh(uint64_t x)
    59 {
    60     return (x >> 56) |
    61     ((x << 40) & 0x00ff000000000000LL) |
    62     ((x << 24) & 0x0000ff0000000000LL) |
    63     ((x << 8) & 0x000000ff00000000LL) |
    64     ((x >> 8) & 0x00000000ff000000LL) |
    65     ((x >> 24) & 0x0000000000ff0000LL) |
    66     ((x >> 40) & 0x000000000000ff00LL) |
    67     (x << 56);
    68 }
    69 
    70 int validate_utf8_sequence(uint8_t *s)
    71 {
    72     uint32_t codepoint;
    73     uint32_t state = 0;
    74 
    75     for(; *s; ++s) {
    76         decode(&state, &codepoint, *s);
    77     }
    78 
    79     return state == UTF8_ACCEPT;
    80 }
    81 
    82 const uint8_t utf8d[] = {
    83     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
    84     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
    85     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
    86     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
    87     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
    88     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
    89     8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
    90     0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
    91     0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
    92     0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
    93     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
    94     1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
    95     1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
    96     1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
    97 };
    98 
    99 uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte)
   100 {
   101     uint32_t type = utf8d[byte];
   102 
   103     *codep = (*state != UTF8_ACCEPT) ?
   104     (byte & 0x3fu) | (*codep << 6) :
   105     (0xff >> type) & (byte);
   106 
   107     *state = utf8d[256 + *state*16 + type];
   108     return *state;
   109 }
   110 
   111 const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
   112 
   113 void _base64_encode_triple(unsigned char triple[3], char result[4])
   114 {
   115     int tripleValue, i;
   116 
   117     tripleValue = triple[0];
   118     tripleValue *= 256;
   119     tripleValue += triple[1];
   120     tripleValue *= 256;
   121     tripleValue += triple[2];
   122 
   123     for (i=0; i<4; i++)
   124     {
   125         result[3-i] = BASE64_CHARS[tripleValue%64];
   126         tripleValue /= 64;
   127     }
   128 }
   129 
   130 int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen)
   131 {
   132     if ((sourcelen+2)/3*4 > targetlen-1)
   133         return 0;
   134 
   135     while (sourcelen >= 3)
   136     {
   137         _base64_encode_triple(source, target);
   138         sourcelen -= 3;
   139         source += 3;
   140         target += 4;
   141     }
   142 
   143     if (sourcelen > 0)
   144     {
   145         unsigned char temp[3];
   146         memset(temp, 0, sizeof(temp));
   147         memcpy(temp, source, sourcelen);
   148         _base64_encode_triple(temp, target);
   149         target[3] = '=';
   150         if (sourcelen == 1)
   151             target[2] = '=';
   152 
   153         target += 4;
   154     }
   155 
   156     target[0] = 0;
   157 
   158     return 1;
   159 }
   160 
   161 int _base64_char_value(char base64char)
   162 {
   163     if (base64char >= 'A' && base64char <= 'Z')
   164         return base64char-'A';
   165     if (base64char >= 'a' && base64char <= 'z')
   166         return base64char-'a'+26;
   167     if (base64char >= '0' && base64char <= '9')
   168         return base64char-'0'+2*26;
   169     if (base64char == '+')
   170         return 2*26+10;
   171     if (base64char == '/')
   172         return 2*26+11;
   173     return -1;
   174 }
   175 
   176 int _base64_decode_triple(char quadruple[4], unsigned char *result)
   177 {
   178     int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
   179     int char_value[4];
   180 
   181     for (i=0; i<4; i++)
   182         char_value[i] = _base64_char_value(quadruple[i]);
   183 
   184     for (i=3; i>=0; i--)
   185     {
   186         if (char_value[i]<0)
   187         {
   188             if (only_equals_yet && quadruple[i]=='=')
   189             {
   190                 char_value[i]=0;
   191                 bytes_to_decode--;
   192                 continue;
   193             }
   194             return 0;
   195         }
   196         only_equals_yet = 0;
   197     }
   198 
   199     if (bytes_to_decode < 0)
   200         bytes_to_decode = 0;
   201 
   202     triple_value = char_value[0];
   203     triple_value *= 64;
   204     triple_value += char_value[1];
   205     triple_value *= 64;
   206     triple_value += char_value[2];
   207     triple_value *= 64;
   208     triple_value += char_value[3];
   209 
   210     for (i=bytes_to_decode; i<3; i++)
   211         triple_value /= 256;
   212     for (i=bytes_to_decode-1; i>=0; i--)
   213     {
   214         result[i] = triple_value%256;
   215         triple_value /= 256;
   216     }
   217 
   218     return bytes_to_decode;
   219 }
   220 
   221 size_t base64_decode(char *source, unsigned char *target, size_t targetlen)
   222 {
   223     char *src, *tmpptr;
   224     char quadruple[4];
   225     unsigned char tmpresult[3];
   226     int i, tmplen = 3;
   227     size_t converted = 0;
   228 
   229     src = (char *)malloc(strlen(source)+5);
   230     if (src == NULL)
   231         return -1;
   232     strcpy(src, source);
   233     strcat(src, "====");
   234     tmpptr = src;
   235 
   236     while (tmplen == 3)
   237     {
   238         for (i=0; i<4; i++)
   239         {
   240             while (*tmpptr != '=' && _base64_char_value(*tmpptr)<0)
   241                 tmpptr++;
   242 
   243             quadruple[i] = *(tmpptr++);
   244         }
   245 
   246         tmplen = _base64_decode_triple(quadruple, tmpresult);
   247 
   248         if (targetlen < tmplen)
   249         {
   250             free(src);
   251             return -1;
   252         }
   253 
   254         memcpy(target, tmpresult, tmplen);
   255         target += tmplen;
   256         targetlen -= tmplen;
   257         converted += tmplen;
   258     }
   259 
   260     free(src);
   261     return converted;
   262 }
   263 
   264 void SHA1Reset(SHA1Context *context)
   265 {
   266     context->Length_Low             = 0;
   267     context->Length_High            = 0;
   268     context->Message_Block_Index    = 0;
   269 
   270     context->Message_Digest[0]      = 0x67452301;
   271     context->Message_Digest[1]      = 0xEFCDAB89;
   272     context->Message_Digest[2]      = 0x98BADCFE;
   273     context->Message_Digest[3]      = 0x10325476;
   274     context->Message_Digest[4]      = 0xC3D2E1F0;
   275 
   276     context->Computed   = 0;
   277     context->Corrupted  = 0;
   278 }
   279 
   280 int SHA1Result(SHA1Context *context)
   281 {
   282 
   283     if (context->Corrupted)
   284     {
   285         return 0;
   286     }
   287 
   288     if (!context->Computed)
   289     {
   290         SHA1PadMessage(context);
   291         context->Computed = 1;
   292     }
   293 
   294     return 1;
   295 }
   296 
   297 void SHA1Input(     SHA1Context         *context,
   298                const unsigned char *message_array,
   299                unsigned            length)
   300 {
   301     if (!length)
   302     {
   303         return;
   304     }
   305 
   306     if (context->Computed || context->Corrupted)
   307     {
   308         context->Corrupted = 1;
   309         return;
   310     }
   311 
   312     while(length-- && !context->Corrupted)
   313     {
   314         context->Message_Block[context->Message_Block_Index++] =
   315         (*message_array & 0xFF);
   316 
   317         context->Length_Low += 8;
   318         /* Force it to 32 bits */
   319         context->Length_Low &= 0xFFFFFFFF;
   320         if (context->Length_Low == 0)
   321         {
   322             context->Length_High++;
   323             /* Force it to 32 bits */
   324             context->Length_High &= 0xFFFFFFFF;
   325             if (context->Length_High == 0)
   326             {
   327                 /* Message is too long */
   328                 context->Corrupted = 1;
   329             }
   330         }
   331 
   332         if (context->Message_Block_Index == 64)
   333         {
   334             SHA1ProcessMessageBlock(context);
   335         }
   336 
   337         message_array++;
   338     }
   339 }
   340 
   341 void SHA1ProcessMessageBlock(SHA1Context *context)
   342 {
   343     const unsigned K[] =            /* Constants defined in SHA-1   */
   344     {
   345         0x5A827999,
   346         0x6ED9EBA1,
   347         0x8F1BBCDC,
   348         0xCA62C1D6
   349     };
   350     int         t;                  /* Loop counter                 */
   351     unsigned    temp;               /* Temporary word value         */
   352     unsigned    W[80];              /* Word sequence                */
   353     unsigned    A, B, C, D, E;      /* Word buffers                 */
   354 
   355     /*
   356      *  Initialize the first 16 words in the array W
   357      */
   358     for(t = 0; t < 16; t++)
   359     {
   360         W[t]  = ((unsigned) context->Message_Block[t * 4]) << 24;
   361         W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
   362         W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
   363         W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
   364     }
   365 
   366     for(t = 16; t < 80; t++)
   367     {
   368         W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
   369     }
   370 
   371     A = context->Message_Digest[0];
   372     B = context->Message_Digest[1];
   373     C = context->Message_Digest[2];
   374     D = context->Message_Digest[3];
   375     E = context->Message_Digest[4];
   376 
   377     for(t = 0; t < 20; t++)
   378     {
   379         temp =  SHA1CircularShift(5,A) +
   380         ((B & C) | ((~B) & D)) + E + W[t] + K[0];
   381         temp &= 0xFFFFFFFF;
   382         E = D;
   383         D = C;
   384         C = SHA1CircularShift(30,B);
   385         B = A;
   386         A = temp;
   387     }
   388 
   389     for(t = 20; t < 40; t++)
   390     {
   391         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
   392         temp &= 0xFFFFFFFF;
   393         E = D;
   394         D = C;
   395         C = SHA1CircularShift(30,B);
   396         B = A;
   397         A = temp;
   398     }
   399 
   400     for(t = 40; t < 60; t++)
   401     {
   402         temp = SHA1CircularShift(5,A) +
   403         ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
   404         temp &= 0xFFFFFFFF;
   405         E = D;
   406         D = C;
   407         C = SHA1CircularShift(30,B);
   408         B = A;
   409         A = temp;
   410     }
   411 
   412     for(t = 60; t < 80; t++)
   413     {
   414         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
   415         temp &= 0xFFFFFFFF;
   416         E = D;
   417         D = C;
   418         C = SHA1CircularShift(30,B);
   419         B = A;
   420         A = temp;
   421     }
   422 
   423     context->Message_Digest[0] =
   424     (context->Message_Digest[0] + A) & 0xFFFFFFFF;
   425     context->Message_Digest[1] =
   426     (context->Message_Digest[1] + B) & 0xFFFFFFFF;
   427     context->Message_Digest[2] =
   428     (context->Message_Digest[2] + C) & 0xFFFFFFFF;
   429     context->Message_Digest[3] =
   430     (context->Message_Digest[3] + D) & 0xFFFFFFFF;
   431     context->Message_Digest[4] =
   432     (context->Message_Digest[4] + E) & 0xFFFFFFFF;
   433 
   434     context->Message_Block_Index = 0;
   435 }
   436 
   437 void SHA1PadMessage(SHA1Context *context)
   438 {
   439     /*
   440      *  Check to see if the current message block is too small to hold
   441      *  the initial padding bits and length.  If so, we will pad the
   442      *  block, process it, and then continue padding into a second
   443      *  block.
   444      */
   445     if (context->Message_Block_Index > 55)
   446     {
   447         context->Message_Block[context->Message_Block_Index++] = 0x80;
   448         while(context->Message_Block_Index < 64)
   449         {
   450             context->Message_Block[context->Message_Block_Index++] = 0;
   451         }
   452 
   453         SHA1ProcessMessageBlock(context);
   454 
   455         while(context->Message_Block_Index < 56)
   456         {
   457             context->Message_Block[context->Message_Block_Index++] = 0;
   458         }
   459     }
   460     else
   461     {
   462         context->Message_Block[context->Message_Block_Index++] = 0x80;
   463         while(context->Message_Block_Index < 56)
   464         {
   465             context->Message_Block[context->Message_Block_Index++] = 0;
   466         }
   467     }
   468 
   469     /*
   470      *  Store the message length as the last 8 octets
   471      */
   472     context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
   473     context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
   474     context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
   475     context->Message_Block[59] = (context->Length_High) & 0xFF;
   476     context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
   477     context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
   478     context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
   479     context->Message_Block[63] = (context->Length_Low) & 0xFF;
   480 
   481     SHA1ProcessMessageBlock(context);
   482 }