💾 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
-=-=-=-=-=-=-
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 }