├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── TODO.md ├── cov.sh ├── include ├── common │ └── utils.h ├── crypto │ ├── md5.h │ ├── rijndael.h │ ├── sha1.h │ └── sha2.h └── struct │ ├── htable.h │ ├── ilist.h │ └── rbtree.h ├── src ├── CMakeLists.txt ├── common │ └── utils.c ├── crypto │ ├── md5.c │ ├── rijndael.c │ ├── rijndael.tbl │ ├── sha1.c │ └── sha2.c └── struct │ ├── htable.c │ ├── ilist.c │ └── rbtree.c └── test ├── CMakeLists.txt ├── crypto ├── CMakeLists.txt ├── test_md5.c ├── test_rijndael.c ├── test_sha1.c ├── test_sha256.c ├── test_sha384.c └── test_sha512.c └── struct ├── CMakeLists.txt ├── test_dlist.c ├── test_htable.c ├── test_rbtree.c └── test_slist.c /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.o 3 | tags 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(c-algorithms-root) 4 | 5 | enable_testing() 6 | 7 | include_directories(include) 8 | 9 | add_subdirectory(src) 10 | add_subdirectory(test) 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Aleksander Alekseev 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-algorithms 2 | 3 | Collection of BSD/MIT-licensed algorithms implementations in pure C. High test coverage. 4 | 5 | ## Usage 6 | 7 | How to build: 8 | 9 | ``` 10 | mkdir build 11 | cd build 12 | cmake .. 13 | make -j4 14 | make test 15 | ``` 16 | 17 | How to make a coverage report: 18 | 19 | ``` 20 | sudo apt-get install lcov 21 | 22 | mkdir build 23 | cd build 24 | ../cov.sh 25 | ``` 26 | 27 | ## Index 28 | 29 | * Data Structures (src/struct/) 30 | * Single- and double-linked lists (ilist.c) 31 | * Red-black trees (rbtree.c) 32 | * Hash tables (htable.c) 33 | * Crytography (src/crypto/) 34 | * MD5 hashing (md5.c) 35 | * SHA1/SHA2 hashing (sha1.c, sha2.c) 36 | * AES (Rijndael) encryption (rijndael.c) 37 | 38 | # See also 39 | 40 | Related articles: 41 | 42 | * https://eax.me/c-lists-rbtree/ 43 | * https://eax.me/c-cryptography/ 44 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | * Implement AES CTR mode 4 | * Add algorithms: crypto: RSA, EC (see https://github.com/afiskon/c-elliptic-curves-crypto ), DH, Random/Entropy (see pgcrypto) + utils: crc32, adler32, crc64 5 | * Add BSD/MIT-licensed compression algoritms, including pglz 6 | * Refactor rbtree 7 | * Never override existing RB-tree nodes (see rbtree.c:593) 8 | * Write a test: make sure that changing walk direction from left-right to right-left works well 9 | * Implement search by part of the key: find\_by\_partial\_key\_march(rb, rb\_comparator, void\* arg) 10 | * Add AVL trees 11 | * Add skip lists, see: 12 | * https://github.com/begeekmyfriend/skiplist/blob/master/skiplist.h 13 | * https://github.com/antirez/redis/blob/unstable/src/t\_zset.c 14 | * Add LRU/LFU cache examples, see http://antirez.com/news/109 15 | * Add array-bases queue implementation (fifo) 16 | * Add in-memory B-tree implementation (See tarantool?) 17 | * Add scapegoat tree implementation https://github.com/delamonpansie/octopus/blob/master/third\_party/sptree.h#L331 18 | * From time to time recheck code using Clang Static Analyzer, PVS-Studio, CppCheck, MemorySanitizer 19 | -------------------------------------------------------------------------------- /cov.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | cmake -DCMAKE_C_COMPILER=`which gcc` \ 6 | -DCMAKE_CXX_COMPILER=`which g++` \ 7 | -DCMAKE_C_FLAGS="-O0 -g -fprofile-arcs -ftest-coverage" \ 8 | -DCMAKE_EXE_LINKER_FLAGS="-lgcov" .. 9 | make -j4 10 | make test 11 | lcov --directory . --capture --output-file cov.info 12 | mkdir cov-report 13 | genhtml -o ./cov-report/ cov.info 14 | x-www-browser cov-report/index.html 15 | -------------------------------------------------------------------------------- /include/common/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_UTILS_H_ 2 | #define _COMMON_UTILS_H_ 3 | 4 | #include 5 | 6 | int 7 | hexToBytes(char* s, uint8_t* b, int blen); 8 | 9 | void 10 | bytesToHex(uint8_t* b, int blen, char *s); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/crypto/md5.h: -------------------------------------------------------------------------------- 1 | /* contrib/pgcrypto/md5.h */ 2 | /* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ 3 | 4 | /* 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the project nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef _NETINET6_MD5_H_ 34 | #define _NETINET6_MD5_H_ 35 | 36 | #include 37 | 38 | #define MD5_DIGEST_LENGTH 16 39 | #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) 40 | 41 | #define MD5_BUFLEN 64 42 | 43 | typedef struct 44 | { 45 | union 46 | { 47 | uint32_t md5_state32[4]; 48 | uint8_t md5_state8[16]; 49 | } md5_st; 50 | 51 | #define md5_sta md5_st.md5_state32[0] 52 | #define md5_stb md5_st.md5_state32[1] 53 | #define md5_stc md5_st.md5_state32[2] 54 | #define md5_std md5_st.md5_state32[3] 55 | #define md5_st8 md5_st.md5_state8 56 | 57 | union 58 | { 59 | uint64_t md5_count64; 60 | uint8_t md5_count8[8]; 61 | } md5_count; 62 | #define md5_n md5_count.md5_count64 63 | #define md5_n8 md5_count.md5_count8 64 | 65 | unsigned int md5_i; 66 | uint8_t md5_buf[MD5_BUFLEN]; 67 | } md5_ctxt; 68 | 69 | extern void md5_init(md5_ctxt *); 70 | extern void md5_loop(md5_ctxt *, const uint8_t *, unsigned int); 71 | extern void md5_pad(md5_ctxt *); 72 | extern void md5_result(uint8_t *, md5_ctxt *); 73 | 74 | /* compatibility */ 75 | #define MD5_CTX md5_ctxt 76 | #define MD5_Init(x) md5_init((x)) 77 | #define MD5_Update(x, y, z) md5_loop((x), (y), (z)) 78 | #define MD5_Final(x, y) \ 79 | do { \ 80 | md5_pad((y)); \ 81 | md5_result((x), (y)); \ 82 | } while (0) 83 | 84 | #endif /* ! _NETINET6_MD5_H_ */ 85 | -------------------------------------------------------------------------------- /include/crypto/rijndael.h: -------------------------------------------------------------------------------- 1 | /* 2 | * contrib/pgcrypto/rijndael.h 3 | * 4 | * $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */ 5 | 6 | /* This is an independent implementation of the encryption algorithm: */ 7 | /* */ 8 | /* RIJNDAEL by Joan Daemen and Vincent Rijmen */ 9 | /* */ 10 | /* which is a candidate algorithm in the Advanced Encryption Standard */ 11 | /* programme of the US National Institute of Standards and Technology. */ 12 | /* */ 13 | /* Copyright in this implementation is held by Dr B R Gladman but I */ 14 | /* hereby give permission for its free direct or derivative use subject */ 15 | /* to acknowledgment of its origin and compliance with any conditions */ 16 | /* that the originators of the algorithm place on its exploitation. */ 17 | /* */ 18 | /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ 19 | 20 | #ifndef _RIJNDAEL_H_ 21 | #define _RIJNDAEL_H_ 22 | 23 | #include 24 | 25 | /* 1. Standard types for AES cryptography source code */ 26 | 27 | typedef uint8_t u1byte; /* an 8 bit unsigned character type */ 28 | typedef uint16_t u2byte; /* a 16 bit unsigned integer type */ 29 | typedef uint32_t u4byte; /* a 32 bit unsigned integer type */ 30 | 31 | typedef int8_t s1byte; /* an 8 bit signed character type */ 32 | typedef int16_t s2byte; /* a 16 bit signed integer type */ 33 | typedef int32_t s4byte; /* a 32 bit signed integer type */ 34 | 35 | typedef struct _rijndael_ctx 36 | { 37 | u4byte k_len; 38 | int decrypt; 39 | u4byte e_key[64]; 40 | u4byte d_key[64]; 41 | } rijndael_ctx; 42 | 43 | 44 | /* 2. Standard interface for AES cryptographic routines */ 45 | 46 | /* These are all based on 32 bit unsigned values and will therefore */ 47 | /* require endian conversions for big-endian architectures */ 48 | 49 | rijndael_ctx * 50 | rijndael_set_key(rijndael_ctx *, const u4byte *, const u4byte, int); 51 | void rijndael_encrypt(rijndael_ctx *, const u4byte *, u4byte *); 52 | void rijndael_decrypt(rijndael_ctx *, const u4byte *, u4byte *); 53 | 54 | /* conventional interface */ 55 | 56 | void aes_set_key(rijndael_ctx *ctx, const uint8_t *key, unsigned keybits, int enc); 57 | void aes_ecb_encrypt(rijndael_ctx *ctx, uint8_t *data, unsigned len); 58 | void aes_ecb_decrypt(rijndael_ctx *ctx, uint8_t *data, unsigned len); 59 | void aes_cbc_encrypt(rijndael_ctx *ctx, uint8_t *iva, uint8_t *data, unsigned len); 60 | void aes_cbc_decrypt(rijndael_ctx *ctx, uint8_t *iva, uint8_t *data, unsigned len); 61 | 62 | #endif /* _RIJNDAEL_H_ */ 63 | -------------------------------------------------------------------------------- /include/crypto/sha1.h: -------------------------------------------------------------------------------- 1 | /* contrib/pgcrypto/sha1.h */ 2 | /* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */ 3 | 4 | /* 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the project nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | */ 32 | /* 33 | * FIPS pub 180-1: Secure Hash Algorithm (SHA-1) 34 | * based on: http://www.itl.nist.gov/fipspubs/fip180-1.htm 35 | * implemented by Jun-ichiro itojun Itoh 36 | */ 37 | 38 | #ifndef _NETINET6_SHA1_H_ 39 | #define _NETINET6_SHA1_H_ 40 | 41 | #include 42 | 43 | #define SHA1_DIGEST_LENGTH 20 44 | #define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) 45 | 46 | struct sha1_ctxt 47 | { 48 | union 49 | { 50 | uint8_t b8[20]; 51 | uint32_t b32[5]; 52 | } h; 53 | union 54 | { 55 | uint8_t b8[8]; 56 | uint64_t b64[1]; 57 | } c; 58 | union 59 | { 60 | uint8_t b8[64]; 61 | uint32_t b32[16]; 62 | } m; 63 | uint8_t count; 64 | }; 65 | 66 | extern void sha1_init(struct sha1_ctxt *); 67 | extern void sha1_pad(struct sha1_ctxt *); 68 | extern void sha1_loop(struct sha1_ctxt *, const uint8_t *, size_t); 69 | extern void sha1_result(struct sha1_ctxt *, uint8_t *); 70 | 71 | /* compatibility with other SHA1 source codes */ 72 | typedef struct sha1_ctxt SHA1_CTX; 73 | 74 | #define SHA1_Init(x) sha1_init((x)) 75 | #define SHA1_Update(x, y, z) sha1_loop((x), (y), (z)) 76 | #define SHA1_Final(x, y) sha1_result((y), (x)) 77 | 78 | #endif /* _NETINET6_SHA1_H_ */ 79 | -------------------------------------------------------------------------------- /include/crypto/sha2.h: -------------------------------------------------------------------------------- 1 | /* contrib/pgcrypto/sha2.h */ 2 | /* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */ 3 | 4 | /* 5 | * FILE: sha2.h 6 | * AUTHOR: Aaron D. Gifford 7 | * 8 | * Copyright (c) 2000-2001, Aaron D. Gifford 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions 13 | * are met: 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the copyright holder nor the names of contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 | * SUCH DAMAGE. 34 | * 35 | * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ 36 | */ 37 | 38 | #ifndef _SHA2_H 39 | #define _SHA2_H 40 | 41 | #include 42 | 43 | /* avoid conflict with OpenSSL */ 44 | #define SHA256_Init pg_SHA256_Init 45 | #define SHA256_Update pg_SHA256_Update 46 | #define SHA256_Final pg_SHA256_Final 47 | #define SHA384_Init pg_SHA384_Init 48 | #define SHA384_Update pg_SHA384_Update 49 | #define SHA384_Final pg_SHA384_Final 50 | #define SHA512_Init pg_SHA512_Init 51 | #define SHA512_Update pg_SHA512_Update 52 | #define SHA512_Final pg_SHA512_Final 53 | 54 | /*** SHA-224/256/384/512 Various Length Definitions ***********************/ 55 | #define SHA224_BLOCK_LENGTH 64 56 | #define SHA224_DIGEST_LENGTH 28 57 | #define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1) 58 | #define SHA256_BLOCK_LENGTH 64 59 | #define SHA256_DIGEST_LENGTH 32 60 | #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) 61 | #define SHA384_BLOCK_LENGTH 128 62 | #define SHA384_DIGEST_LENGTH 48 63 | #define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) 64 | #define SHA512_BLOCK_LENGTH 128 65 | #define SHA512_DIGEST_LENGTH 64 66 | #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) 67 | 68 | 69 | /*** SHA-256/384/512 Context Structures *******************************/ 70 | typedef struct _SHA256_CTX 71 | { 72 | uint32_t state[8]; 73 | uint64_t bitcount; 74 | uint8_t buffer[SHA256_BLOCK_LENGTH]; 75 | } SHA256_CTX; 76 | typedef struct _SHA512_CTX 77 | { 78 | uint64_t state[8]; 79 | uint64_t bitcount[2]; 80 | uint8_t buffer[SHA512_BLOCK_LENGTH]; 81 | } SHA512_CTX; 82 | 83 | typedef SHA256_CTX SHA224_CTX; 84 | typedef SHA512_CTX SHA384_CTX; 85 | 86 | void SHA224_Init(SHA224_CTX *); 87 | void SHA224_Update(SHA224_CTX *, const uint8_t *, size_t); 88 | void SHA224_Final(uint8_t[SHA224_DIGEST_LENGTH], SHA224_CTX *); 89 | 90 | void SHA256_Init(SHA256_CTX *); 91 | void SHA256_Update(SHA256_CTX *, const uint8_t *, size_t); 92 | void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX *); 93 | 94 | void SHA384_Init(SHA384_CTX *); 95 | void SHA384_Update(SHA384_CTX *, const uint8_t *, size_t); 96 | void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX *); 97 | 98 | void SHA512_Init(SHA512_CTX *); 99 | void SHA512_Update(SHA512_CTX *, const uint8_t *, size_t); 100 | void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX *); 101 | 102 | #endif /* _SHA2_H */ 103 | -------------------------------------------------------------------------------- /include/struct/htable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * htable.h 3 | * (c) Alexandr A Alexeev 2011-2016 | http://eax.me/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct HTableNode 11 | { 12 | struct HTableNode* next; /* next node in a chain, if any */ 13 | uint32_t hash; /* hash function value */ 14 | } HTableNode; 15 | 16 | typedef uint32_t (*htable_hash_func) (const HTableNode* a, void *arg); 17 | typedef bool (*htable_keyeq_func) (const HTableNode* a, const HTableNode* b, void *arg); 18 | typedef void* (*htable_alloc_func) (size_t size, void *arg); 19 | typedef void (*htable_free_func) (void* mem, void *arg); 20 | typedef void (*htable_before_node_free_func) (HTableNode* node, void *arg); 21 | 22 | /* Hash table representation */ 23 | typedef struct { 24 | HTableNode** items; /* table items */ 25 | size_t nitems; /* how many items are stored in hash table */ 26 | uint32_t mask; /* mask, aplied to hash function */ 27 | size_t size; /* current hash table size */ 28 | 29 | /* user-specified arguments */ 30 | 31 | size_t node_size; 32 | htable_hash_func hfunc; 33 | htable_keyeq_func eqfunc; 34 | htable_alloc_func allocfunc; 35 | htable_free_func freefunc; 36 | htable_before_node_free_func bnffunc; 37 | void* arg; 38 | } HTable; 39 | 40 | extern uint32_t htable_default_hash(const char *key, const size_t key_len); 41 | extern void htable_create( 42 | HTable* tbl, 43 | size_t node_size, 44 | htable_hash_func hfunc, 45 | htable_keyeq_func eqfunc, 46 | htable_alloc_func allocfunc, 47 | htable_free_func freefunc, 48 | htable_before_node_free_func bnffunc, 49 | void* arg 50 | ); 51 | extern void htable_free_items(HTable* tbl); 52 | extern HTableNode* htable_find(HTable* tbl, HTableNode* query); 53 | extern void htable_insert(HTable* tbl, HTableNode* node, bool* isNewNode); 54 | extern bool htable_delete(HTable* tbl, HTableNode* query); 55 | 56 | #define htable_nitems(tbl) ((tbl)->nitems) 57 | -------------------------------------------------------------------------------- /include/struct/ilist.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | * 3 | * ilist.h 4 | * integrated/inline doubly- and singly-linked lists 5 | * 6 | * These list types are useful when there are only a predetermined set of 7 | * lists that an object could be in. List links are embedded directly into 8 | * the objects, and thus no extra memory management overhead is required. 9 | * (Of course, if only a small proportion of existing objects are in a list, 10 | * the link fields in the remainder would be wasted space. But usually, 11 | * it saves space to not have separately-allocated list nodes.) 12 | * 13 | * None of the functions here allocate any memory; they just manipulate 14 | * externally managed memory. The APIs for singly and doubly linked lists 15 | * are identical as far as capabilities of both allow. 16 | * 17 | * Each list has a list header, which exists even when the list is empty. 18 | * An empty singly-linked list has a NULL pointer in its header. 19 | * There are two kinds of empty doubly linked lists: those that have been 20 | * initialized to NULL, and those that have been initialized to circularity. 21 | * (If a dlist is modified and then all its elements are deleted, it will be 22 | * in the circular state.) We prefer circular dlists because there are some 23 | * operations that can be done without branches (and thus faster) on lists 24 | * that use circular representation. However, it is often convenient to 25 | * initialize list headers to zeroes rather than setting them up with an 26 | * explicit initialization function, so we also allow the other case. 27 | * 28 | * EXAMPLES 29 | * 30 | * Here's a simple example demonstrating how this can be used. Let's assume 31 | * we want to store information about the tables contained in a database. 32 | * 33 | * #include "lib/ilist.h" 34 | * 35 | * // Define struct for the databases including a list header that will be 36 | * // used to access the nodes in the table list later on. 37 | * typedef struct my_database 38 | * { 39 | * char *datname; 40 | * dlist_head tables; 41 | * // ... 42 | * } my_database; 43 | * 44 | * // Define struct for the tables. Note the list_node element which stores 45 | * // prev/next list links. The list_node element need not be first. 46 | * typedef struct my_table 47 | * { 48 | * char *tablename; 49 | * dlist_node list_node; 50 | * perm_t permissions; 51 | * // ... 52 | * } my_table; 53 | * 54 | * // create a database 55 | * my_database *db = create_database(); 56 | * 57 | * // and add a few tables to its table list 58 | * dlist_push_head(&db->tables, &create_table(db, "a")->list_node); 59 | * ... 60 | * dlist_push_head(&db->tables, &create_table(db, "b")->list_node); 61 | * 62 | * 63 | * To iterate over the table list, we allocate an iterator variable and use 64 | * a specialized looping construct. Inside a dlist_foreach, the iterator's 65 | * 'cur' field can be used to access the current element. iter.cur points to 66 | * a 'dlist_node', but most of the time what we want is the actual table 67 | * information; dlist_container() gives us that, like so: 68 | * 69 | * dlist_iter iter; 70 | * dlist_foreach(iter, &db->tables) 71 | * { 72 | * my_table *tbl = dlist_container(my_table, list_node, iter.cur); 73 | * printf("we have a table: %s in database %s\n", 74 | * tbl->tablename, db->datname); 75 | * } 76 | * 77 | * 78 | * While a simple iteration is useful, we sometimes also want to manipulate 79 | * the list while iterating. There is a different iterator element and looping 80 | * construct for that. Suppose we want to delete tables that meet a certain 81 | * criterion: 82 | * 83 | * dlist_mutable_iter miter; 84 | * dlist_foreach_modify(miter, &db->tables) 85 | * { 86 | * my_table *tbl = dlist_container(my_table, list_node, miter.cur); 87 | * 88 | * if (!tbl->to_be_deleted) 89 | * continue; // don't touch this one 90 | * 91 | * // unlink the current table from the linked list 92 | * dlist_delete(miter.cur); 93 | * // as these lists never manage memory, we can still access the table 94 | * // after it's been unlinked 95 | * drop_table(db, tbl); 96 | * } 97 | * 98 | * 99 | * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group 100 | * Portions Copyright (c) 1994, Regents of the University of California 101 | * 102 | * IDENTIFICATION 103 | * src/include/lib/ilist.h 104 | *------------------------------------------------------------------------- 105 | */ 106 | #ifndef ILIST_H 107 | #define ILIST_H 108 | 109 | #include 110 | #include 111 | #include 112 | #include 113 | #include 114 | 115 | /* 116 | * CppAsString 117 | * Convert the argument to a string, using the C preprocessor. 118 | * CppConcat 119 | * Concatenate two arguments together, using the C preprocessor. 120 | * 121 | * Note: There used to be support here for pre-ANSI C compilers that didn't 122 | * support # and ##. Nowadays, these macros are just for clarity and/or 123 | * backward compatibility with existing PostgreSQL code. 124 | */ 125 | #define CppAsString(identifier) #identifier 126 | #define CppConcat(x, y) x##y 127 | 128 | /* 129 | * Macros to support compile-time assertion checks. 130 | * 131 | * If the "condition" (a compile-time-constant expression) evaluates to false, 132 | * throw a compile error using the "errmessage" (a string literal). 133 | * 134 | * gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic 135 | * placement restrictions. These macros make it safe to use as a statement 136 | * or in an expression, respectively. 137 | * 138 | * Otherwise we fall back on a kluge that assumes the compiler will complain 139 | * about a negative width for a struct bit-field. This will not include a 140 | * helpful error message, but it beats not getting an error at all. 141 | */ 142 | #ifdef HAVE__STATIC_ASSERT 143 | #define StaticAssertStmt(condition, errmessage) \ 144 | do { _Static_assert(condition, errmessage); } while(0) 145 | #define StaticAssertExpr(condition, errmessage) \ 146 | ({ StaticAssertStmt(condition, errmessage); true; }) 147 | #else /* !HAVE__STATIC_ASSERT */ 148 | #define StaticAssertStmt(condition, errmessage) \ 149 | ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) 150 | #define StaticAssertExpr(condition, errmessage) \ 151 | StaticAssertStmt(condition, errmessage) 152 | #endif /* HAVE__STATIC_ASSERT */ 153 | 154 | 155 | /* 156 | * Compile-time checks that a variable (or expression) has the specified type. 157 | * 158 | * AssertVariableIsOfType() can be used as a statement. 159 | * AssertVariableIsOfTypeMacro() is intended for use in macros, eg 160 | * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x)) 161 | * 162 | * If we don't have __builtin_types_compatible_p, we can still assert that 163 | * the types have the same size. This is far from ideal (especially on 32-bit 164 | * platforms) but it provides at least some coverage. 165 | */ 166 | #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P 167 | #define AssertVariableIsOfType(varname, typename) \ 168 | StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \ 169 | CppAsString(varname) " does not have type " CppAsString(typename)) 170 | #define AssertVariableIsOfTypeMacro(varname, typename) \ 171 | ((void) StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \ 172 | CppAsString(varname) " does not have type " CppAsString(typename))) 173 | #else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ 174 | #define AssertVariableIsOfType(varname, typename) \ 175 | StaticAssertStmt(sizeof(varname) == sizeof(typename), \ 176 | CppAsString(varname) " does not have type " CppAsString(typename)) 177 | #define AssertVariableIsOfTypeMacro(varname, typename) \ 178 | ((void) StaticAssertExpr(sizeof(varname) == sizeof(typename), \ 179 | CppAsString(varname) " does not have type " CppAsString(typename))) 180 | #endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ 181 | 182 | /* 183 | * Enable for extra debugging. This is rather expensive, so it's not enabled by 184 | * default even when USE_ASSERT_CHECKING. 185 | */ 186 | /* #define ILIST_DEBUG */ 187 | 188 | /* 189 | * Node of a doubly linked list. 190 | * 191 | * Embed this in structs that need to be part of a doubly linked list. 192 | */ 193 | typedef struct dlist_node dlist_node; 194 | struct dlist_node 195 | { 196 | dlist_node *prev; 197 | dlist_node *next; 198 | }; 199 | 200 | /* 201 | * Head of a doubly linked list. 202 | * 203 | * Non-empty lists are internally circularly linked. Circular lists have the 204 | * advantage of not needing any branches in the most common list manipulations. 205 | * An empty list can also be represented as a pair of NULL pointers, making 206 | * initialization easier. 207 | */ 208 | typedef struct dlist_head 209 | { 210 | /* 211 | * head.next either points to the first element of the list; to &head if 212 | * it's a circular empty list; or to NULL if empty and not circular. 213 | * 214 | * head.prev either points to the last element of the list; to &head if 215 | * it's a circular empty list; or to NULL if empty and not circular. 216 | */ 217 | dlist_node head; 218 | } dlist_head; 219 | 220 | 221 | /* 222 | * Doubly linked list iterator. 223 | * 224 | * Used as state in dlist_foreach() and dlist_reverse_foreach(). To get the 225 | * current element of the iteration use the 'cur' member. 226 | * 227 | * Iterations using this are *not* allowed to change the list while iterating! 228 | * 229 | * NB: We use an extra "end" field here to avoid multiple evaluations of 230 | * arguments in the dlist_foreach() macro. 231 | */ 232 | typedef struct dlist_iter 233 | { 234 | dlist_node *cur; /* current element */ 235 | dlist_node *end; /* last node we'll iterate to */ 236 | } dlist_iter; 237 | 238 | /* 239 | * Doubly linked list iterator allowing some modifications while iterating. 240 | * 241 | * Used as state in dlist_foreach_modify(). To get the current element of the 242 | * iteration use the 'cur' member. 243 | * 244 | * Iterations using this are only allowed to change the list at the current 245 | * point of iteration. It is fine to delete the current node, but it is *not* 246 | * fine to insert or delete adjacent nodes. 247 | * 248 | * NB: We need a separate type for mutable iterations so that we can store 249 | * the 'next' node of the current node in case it gets deleted or modified. 250 | */ 251 | typedef struct dlist_mutable_iter 252 | { 253 | dlist_node *cur; /* current element */ 254 | dlist_node *next; /* next node we'll iterate to */ 255 | dlist_node *end; /* last node we'll iterate to */ 256 | } dlist_mutable_iter; 257 | 258 | /* 259 | * Node of a singly linked list. 260 | * 261 | * Embed this in structs that need to be part of a singly linked list. 262 | */ 263 | typedef struct slist_node slist_node; 264 | struct slist_node 265 | { 266 | slist_node *next; 267 | }; 268 | 269 | /* 270 | * Head of a singly linked list. 271 | * 272 | * Singly linked lists are not circularly linked, in contrast to doubly linked 273 | * lists; we just set head.next to NULL if empty. This doesn't incur any 274 | * additional branches in the usual manipulations. 275 | */ 276 | typedef struct slist_head 277 | { 278 | slist_node head; 279 | } slist_head; 280 | 281 | /* 282 | * Singly linked list iterator. 283 | * 284 | * Used as state in slist_foreach(). To get the current element of the 285 | * iteration use the 'cur' member. 286 | * 287 | * It's allowed to modify the list while iterating, with the exception of 288 | * deleting the iterator's current node; deletion of that node requires 289 | * care if the iteration is to be continued afterward. (Doing so and also 290 | * deleting or inserting adjacent list elements might misbehave; also, if 291 | * the user frees the current node's storage, continuing the iteration is 292 | * not safe.) 293 | * 294 | * NB: this wouldn't really need to be an extra struct, we could use an 295 | * slist_node * directly. We prefer a separate type for consistency. 296 | */ 297 | typedef struct slist_iter 298 | { 299 | slist_node *cur; 300 | } slist_iter; 301 | 302 | /* 303 | * Singly linked list iterator allowing some modifications while iterating. 304 | * 305 | * Used as state in slist_foreach_modify(). To get the current element of the 306 | * iteration use the 'cur' member. 307 | * 308 | * The only list modification allowed while iterating is to remove the current 309 | * node via slist_delete_current() (*not* slist_delete()). Insertion or 310 | * deletion of nodes adjacent to the current node would misbehave. 311 | */ 312 | typedef struct slist_mutable_iter 313 | { 314 | slist_node *cur; /* current element */ 315 | slist_node *next; /* next node we'll iterate to */ 316 | slist_node *prev; /* prev node, for deletions */ 317 | } slist_mutable_iter; 318 | 319 | 320 | /* Static initializers */ 321 | #define DLIST_STATIC_INIT(name) {{&(name).head, &(name).head}} 322 | #define SLIST_STATIC_INIT(name) {{NULL}} 323 | 324 | 325 | /* Prototypes for functions too big to be inline */ 326 | 327 | /* Caution: this is O(n); consider using slist_delete_current() instead */ 328 | extern void slist_delete(slist_head *head, slist_node *node); 329 | 330 | #ifdef ILIST_DEBUG 331 | extern void dlist_check(dlist_head *head); 332 | extern void slist_check(slist_head *head); 333 | #else 334 | /* 335 | * These seemingly useless casts to void are here to keep the compiler quiet 336 | * about the argument being unused in many functions in a non-debug compile, 337 | * in which functions the only point of passing the list head pointer is to be 338 | * able to run these checks. 339 | */ 340 | #define dlist_check(head) ((void) (head)) 341 | #define slist_check(head) ((void) (head)) 342 | #endif /* ILIST_DEBUG */ 343 | 344 | /* doubly linked list implementation */ 345 | 346 | /* 347 | * Initialize a doubly linked list. 348 | * Previous state will be thrown away without any cleanup. 349 | */ 350 | static inline void 351 | dlist_init(dlist_head *head) 352 | { 353 | head->head.next = head->head.prev = &head->head; 354 | } 355 | 356 | /* 357 | * Is the list empty? 358 | * 359 | * An empty list has either its first 'next' pointer set to NULL, or to itself. 360 | */ 361 | static inline bool 362 | dlist_is_empty(dlist_head *head) 363 | { 364 | dlist_check(head); 365 | 366 | return head->head.next == NULL || head->head.next == &(head->head); 367 | } 368 | 369 | /* 370 | * Insert a node at the beginning of the list. 371 | */ 372 | static inline void 373 | dlist_push_head(dlist_head *head, dlist_node *node) 374 | { 375 | if (head->head.next == NULL) /* convert NULL header to circular */ 376 | dlist_init(head); 377 | 378 | node->next = head->head.next; 379 | node->prev = &head->head; 380 | node->next->prev = node; 381 | head->head.next = node; 382 | 383 | dlist_check(head); 384 | } 385 | 386 | /* 387 | * Insert a node at the end of the list. 388 | */ 389 | static inline void 390 | dlist_push_tail(dlist_head *head, dlist_node *node) 391 | { 392 | if (head->head.next == NULL) /* convert NULL header to circular */ 393 | dlist_init(head); 394 | 395 | node->next = &head->head; 396 | node->prev = head->head.prev; 397 | node->prev->next = node; 398 | head->head.prev = node; 399 | 400 | dlist_check(head); 401 | } 402 | 403 | /* 404 | * Insert a node after another *in the same list* 405 | */ 406 | static inline void 407 | dlist_insert_after(dlist_node *after, dlist_node *node) 408 | { 409 | node->prev = after; 410 | node->next = after->next; 411 | after->next = node; 412 | node->next->prev = node; 413 | } 414 | 415 | /* 416 | * Insert a node before another *in the same list* 417 | */ 418 | static inline void 419 | dlist_insert_before(dlist_node *before, dlist_node *node) 420 | { 421 | node->prev = before->prev; 422 | node->next = before; 423 | before->prev = node; 424 | node->prev->next = node; 425 | } 426 | 427 | /* 428 | * Delete 'node' from its list (it must be in one). 429 | */ 430 | static inline void 431 | dlist_delete(dlist_node *node) 432 | { 433 | node->prev->next = node->next; 434 | node->next->prev = node->prev; 435 | } 436 | 437 | /* 438 | * Remove and return the first node from a list (there must be one). 439 | */ 440 | static inline dlist_node * 441 | dlist_pop_head_node(dlist_head *head) 442 | { 443 | dlist_node *node; 444 | 445 | assert(!dlist_is_empty(head)); 446 | node = head->head.next; 447 | dlist_delete(node); 448 | return node; 449 | } 450 | 451 | /* 452 | * Remove and return the last node from a list (there must be one). 453 | */ 454 | static inline dlist_node * 455 | dlist_pop_tail_node(dlist_head *head) 456 | { 457 | dlist_node *node; 458 | 459 | assert(!dlist_is_empty(head)); 460 | node = head->head.prev; 461 | dlist_delete(node); 462 | return node; 463 | } 464 | 465 | 466 | /* 467 | * Move element from its current position in the list to the head position in 468 | * the same list. 469 | * 470 | * Undefined behaviour if 'node' is not already part of the list. 471 | */ 472 | static inline void 473 | dlist_move_head(dlist_head *head, dlist_node *node) 474 | { 475 | /* fast path if it's already at the head */ 476 | if (head->head.next == node) 477 | return; 478 | 479 | dlist_delete(node); 480 | dlist_push_head(head, node); 481 | 482 | dlist_check(head); 483 | } 484 | 485 | /* 486 | * Check whether 'node' has a following node. 487 | * Caution: unreliable if 'node' is not in the list. 488 | */ 489 | static inline bool 490 | dlist_has_next(dlist_head *head, dlist_node *node) 491 | { 492 | return node->next != &head->head; 493 | } 494 | 495 | /* 496 | * Check whether 'node' has a preceding node. 497 | * Caution: unreliable if 'node' is not in the list. 498 | */ 499 | static inline bool 500 | dlist_has_prev(dlist_head *head, dlist_node *node) 501 | { 502 | return node->prev != &head->head; 503 | } 504 | 505 | /* 506 | * Return the next node in the list (there must be one). 507 | */ 508 | static inline dlist_node * 509 | dlist_next_node(dlist_head *head, dlist_node *node) 510 | { 511 | assert(dlist_has_next(head, node)); 512 | return node->next; 513 | } 514 | 515 | /* 516 | * Return previous node in the list (there must be one). 517 | */ 518 | static inline dlist_node * 519 | dlist_prev_node(dlist_head *head, dlist_node *node) 520 | { 521 | assert(dlist_has_prev(head, node)); 522 | return node->prev; 523 | } 524 | 525 | /* internal support function to get address of head element's struct */ 526 | static inline void * 527 | dlist_head_element_off(dlist_head *head, size_t off) 528 | { 529 | assert(!dlist_is_empty(head)); 530 | return (char *) head->head.next - off; 531 | } 532 | 533 | /* 534 | * Return the first node in the list (there must be one). 535 | */ 536 | static inline dlist_node * 537 | dlist_head_node(dlist_head *head) 538 | { 539 | return (dlist_node *) dlist_head_element_off(head, 0); 540 | } 541 | 542 | /* internal support function to get address of tail element's struct */ 543 | static inline void * 544 | dlist_tail_element_off(dlist_head *head, size_t off) 545 | { 546 | assert(!dlist_is_empty(head)); 547 | return (char *) head->head.prev - off; 548 | } 549 | 550 | /* 551 | * Return the last node in the list (there must be one). 552 | */ 553 | static inline dlist_node * 554 | dlist_tail_node(dlist_head *head) 555 | { 556 | return (dlist_node *) dlist_tail_element_off(head, 0); 557 | } 558 | 559 | /* 560 | * Return the containing struct of 'type' where 'membername' is the dlist_node 561 | * pointed at by 'ptr'. 562 | * 563 | * This is used to convert a dlist_node * back to its containing struct. 564 | */ 565 | #define dlist_container(type, membername, ptr) \ 566 | (AssertVariableIsOfTypeMacro(ptr, dlist_node *), \ 567 | AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ 568 | ((type *) ((char *) (ptr) - offsetof(type, membername)))) 569 | 570 | /* 571 | * Return the address of the first element in the list. 572 | * 573 | * The list must not be empty. 574 | */ 575 | #define dlist_head_element(type, membername, lhead) \ 576 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ 577 | (type *) dlist_head_element_off(lhead, offsetof(type, membername))) 578 | 579 | /* 580 | * Return the address of the last element in the list. 581 | * 582 | * The list must not be empty. 583 | */ 584 | #define dlist_tail_element(type, membername, lhead) \ 585 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ 586 | ((type *) dlist_tail_element_off(lhead, offsetof(type, membername)))) 587 | 588 | /* 589 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. 590 | * 591 | * Access the current element with iter.cur. 592 | * 593 | * It is *not* allowed to manipulate the list during iteration. 594 | */ 595 | #define dlist_foreach(iter, lhead) \ 596 | for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \ 597 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ 598 | (iter).end = &(lhead)->head, \ 599 | (iter).cur = (iter).end->next ? (iter).end->next : (iter).end; \ 600 | (iter).cur != (iter).end; \ 601 | (iter).cur = (iter).cur->next) 602 | 603 | /* 604 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. 605 | * 606 | * Access the current element with iter.cur. 607 | * 608 | * Iterations using this are only allowed to change the list at the current 609 | * point of iteration. It is fine to delete the current node, but it is *not* 610 | * fine to insert or delete adjacent nodes. 611 | */ 612 | #define dlist_foreach_modify(iter, lhead) \ 613 | for (AssertVariableIsOfTypeMacro(iter, dlist_mutable_iter), \ 614 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ 615 | (iter).end = &(lhead)->head, \ 616 | (iter).cur = (iter).end->next ? (iter).end->next : (iter).end, \ 617 | (iter).next = (iter).cur->next; \ 618 | (iter).cur != (iter).end; \ 619 | (iter).cur = (iter).next, (iter).next = (iter).cur->next) 620 | 621 | /* 622 | * Iterate through the list in reverse order. 623 | * 624 | * It is *not* allowed to manipulate the list during iteration. 625 | */ 626 | #define dlist_reverse_foreach(iter, lhead) \ 627 | for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \ 628 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ 629 | (iter).end = &(lhead)->head, \ 630 | (iter).cur = (iter).end->prev ? (iter).end->prev : (iter).end; \ 631 | (iter).cur != (iter).end; \ 632 | (iter).cur = (iter).cur->prev) 633 | 634 | 635 | /* singly linked list implementation */ 636 | 637 | /* 638 | * Initialize a singly linked list. 639 | * Previous state will be thrown away without any cleanup. 640 | */ 641 | static inline void 642 | slist_init(slist_head *head) 643 | { 644 | head->head.next = NULL; 645 | } 646 | 647 | /* 648 | * Is the list empty? 649 | */ 650 | static inline bool 651 | slist_is_empty(slist_head *head) 652 | { 653 | slist_check(head); 654 | 655 | return head->head.next == NULL; 656 | } 657 | 658 | /* 659 | * Insert a node at the beginning of the list. 660 | */ 661 | static inline void 662 | slist_push_head(slist_head *head, slist_node *node) 663 | { 664 | node->next = head->head.next; 665 | head->head.next = node; 666 | 667 | slist_check(head); 668 | } 669 | 670 | /* 671 | * Insert a node after another *in the same list* 672 | */ 673 | static inline void 674 | slist_insert_after(slist_node *after, slist_node *node) 675 | { 676 | node->next = after->next; 677 | after->next = node; 678 | } 679 | 680 | /* 681 | * Remove and return the first node from a list (there must be one). 682 | */ 683 | static inline slist_node * 684 | slist_pop_head_node(slist_head *head) 685 | { 686 | slist_node *node; 687 | 688 | assert(!slist_is_empty(head)); 689 | node = head->head.next; 690 | head->head.next = node->next; 691 | slist_check(head); 692 | return node; 693 | } 694 | 695 | /* 696 | * Check whether 'node' has a following node. 697 | */ 698 | static inline bool 699 | slist_has_next(slist_head *head, slist_node *node) 700 | { 701 | slist_check(head); 702 | 703 | return node->next != NULL; 704 | } 705 | 706 | /* 707 | * Return the next node in the list (there must be one). 708 | */ 709 | static inline slist_node * 710 | slist_next_node(slist_head *head, slist_node *node) 711 | { 712 | assert(slist_has_next(head, node)); 713 | return node->next; 714 | } 715 | 716 | /* internal support function to get address of head element's struct */ 717 | static inline void * 718 | slist_head_element_off(slist_head *head, size_t off) 719 | { 720 | assert(!slist_is_empty(head)); 721 | return (char *) head->head.next - off; 722 | } 723 | 724 | /* 725 | * Return the first node in the list (there must be one). 726 | */ 727 | static inline slist_node * 728 | slist_head_node(slist_head *head) 729 | { 730 | return (slist_node *) slist_head_element_off(head, 0); 731 | } 732 | 733 | /* 734 | * Delete the list element the iterator currently points to. 735 | * 736 | * Caution: this modifies iter->cur, so don't use that again in the current 737 | * loop iteration. 738 | */ 739 | static inline void 740 | slist_delete_current(slist_mutable_iter *iter) 741 | { 742 | /* 743 | * Update previous element's forward link. If the iteration is at the 744 | * first list element, iter->prev will point to the list header's "head" 745 | * field, so we don't need a special case for that. 746 | */ 747 | iter->prev->next = iter->next; 748 | 749 | /* 750 | * Reset cur to prev, so that prev will continue to point to the prior 751 | * valid list element after slist_foreach_modify() advances to the next. 752 | */ 753 | iter->cur = iter->prev; 754 | } 755 | 756 | /* 757 | * Return the containing struct of 'type' where 'membername' is the slist_node 758 | * pointed at by 'ptr'. 759 | * 760 | * This is used to convert a slist_node * back to its containing struct. 761 | */ 762 | #define slist_container(type, membername, ptr) \ 763 | (AssertVariableIsOfTypeMacro(ptr, slist_node *), \ 764 | AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \ 765 | ((type *) ((char *) (ptr) - offsetof(type, membername)))) 766 | 767 | /* 768 | * Return the address of the first element in the list. 769 | * 770 | * The list must not be empty. 771 | */ 772 | #define slist_head_element(type, membername, lhead) \ 773 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \ 774 | (type *) slist_head_element_off(lhead, offsetof(type, membername))) 775 | 776 | /* 777 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. 778 | * 779 | * Access the current element with iter.cur. 780 | * 781 | * It's allowed to modify the list while iterating, with the exception of 782 | * deleting the iterator's current node; deletion of that node requires 783 | * care if the iteration is to be continued afterward. (Doing so and also 784 | * deleting or inserting adjacent list elements might misbehave; also, if 785 | * the user frees the current node's storage, continuing the iteration is 786 | * not safe.) 787 | */ 788 | #define slist_foreach(iter, lhead) \ 789 | for (AssertVariableIsOfTypeMacro(iter, slist_iter), \ 790 | AssertVariableIsOfTypeMacro(lhead, slist_head *), \ 791 | (iter).cur = (lhead)->head.next; \ 792 | (iter).cur != NULL; \ 793 | (iter).cur = (iter).cur->next) 794 | 795 | /* 796 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. 797 | * 798 | * Access the current element with iter.cur. 799 | * 800 | * The only list modification allowed while iterating is to remove the current 801 | * node via slist_delete_current() (*not* slist_delete()). Insertion or 802 | * deletion of nodes adjacent to the current node would misbehave. 803 | */ 804 | #define slist_foreach_modify(iter, lhead) \ 805 | for (AssertVariableIsOfTypeMacro(iter, slist_mutable_iter), \ 806 | AssertVariableIsOfTypeMacro(lhead, slist_head *), \ 807 | (iter).prev = &(lhead)->head, \ 808 | (iter).cur = (iter).prev->next, \ 809 | (iter).next = (iter).cur ? (iter).cur->next : NULL; \ 810 | (iter).cur != NULL; \ 811 | (iter).prev = (iter).cur, \ 812 | (iter).cur = (iter).next, \ 813 | (iter).next = (iter).next ? (iter).next->next : NULL) 814 | 815 | #endif /* ILIST_H */ 816 | -------------------------------------------------------------------------------- /include/struct/rbtree.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | * 3 | * rbtree.h 4 | * interface for PostgreSQL generic Red-Black binary tree package 5 | * 6 | * Copyright (c) 2009-2016, PostgreSQL Global Development Group 7 | * 8 | * IDENTIFICATION 9 | * src/include/lib/rbtree.h 10 | * 11 | *------------------------------------------------------------------------- 12 | */ 13 | #ifndef RBTREE_H 14 | #define RBTREE_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* 22 | * RBNode is intended to be used as the first field of a larger struct, 23 | * whose additional fields carry whatever payload data the caller needs 24 | * for a tree entry. (The total size of that larger struct is passed to 25 | * rb_create.) RBNode is declared here to support this usage, but 26 | * callers must treat it as an opaque struct. 27 | */ 28 | typedef struct RBNode 29 | { 30 | char color; /* node's current color, red or black */ 31 | struct RBNode *left; /* left child, or RBNIL if none */ 32 | struct RBNode *right; /* right child, or RBNIL if none */ 33 | struct RBNode *parent; /* parent, or NULL (not RBNIL!) if none */ 34 | } RBNode; 35 | 36 | /* Support functions to be provided by caller */ 37 | typedef int (*rb_comparator) (const RBNode *a, const RBNode *b, void *arg); 38 | typedef void (*rb_combiner) (RBNode *existing, const RBNode *newdata, void *arg); 39 | typedef RBNode *(*rb_allocfunc) (void *arg); 40 | typedef void (*rb_freefunc) (RBNode *x, void *arg); 41 | typedef void (*rb_sprintfunc) (RBNode *x, char* buff); 42 | 43 | typedef struct RBTree RBTree; 44 | 45 | /* 46 | * RBTree control structure 47 | */ 48 | struct RBTree 49 | { 50 | RBNode *root; /* root node, or RBNIL if tree is empty */ 51 | 52 | /* Remaining fields are constant after rb_create */ 53 | 54 | size_t node_size; /* actual size of tree nodes */ 55 | /* The caller-supplied manipulation functions */ 56 | rb_comparator comparator; 57 | rb_combiner combiner; 58 | rb_allocfunc allocfunc; 59 | rb_freefunc freefunc; 60 | /* Passthrough arg passed to all manipulation functions */ 61 | void *arg; 62 | }; 63 | 64 | extern void rb_create(RBTree* tree, 65 | size_t node_size, 66 | rb_comparator comparator, 67 | rb_combiner combiner, 68 | rb_allocfunc allocfunc, 69 | rb_freefunc freefunc, 70 | void *arg); 71 | 72 | extern RBNode *rb_find(RBTree *rb, const RBNode *data); 73 | extern RBNode *rb_leftmost(RBTree *rb); 74 | extern RBNode *rb_rightmost(RBTree *rb); 75 | 76 | extern RBNode *rb_insert(RBTree *rb, const RBNode *data, bool *isNew); 77 | extern void rb_delete(RBTree *rb, RBNode *node); 78 | 79 | extern void rb_tree_debug_print(RBTree* rb, rb_sprintfunc sprintfunc); 80 | 81 | typedef enum RBTreeNextStep 82 | { 83 | NextStepNone, 84 | NextStepUp, 85 | NextStepLeft, 86 | NextStepRight 87 | } RBTreeNextStep; 88 | 89 | typedef struct 90 | { 91 | RBTree* rb; 92 | RBNode* last_visited; 93 | bool is_over; 94 | } RBTreeLeftRightWalk; 95 | 96 | extern void rb_begin_left_right_walk(RBTree *rb, RBTreeLeftRightWalk* lrw); 97 | extern RBNode* rb_left_right_walk(RBTreeLeftRightWalk* lrw); 98 | 99 | typedef struct 100 | { 101 | RBTree* rb; 102 | RBNode* last_visited; 103 | bool is_over; 104 | } RBTreeRightLeftWalk; 105 | 106 | extern void rb_begin_right_left_walk(RBTree *rb, RBTreeRightLeftWalk* rlw); 107 | extern RBNode* rb_right_left_walk(RBTreeRightLeftWalk* rlw); 108 | 109 | typedef struct 110 | { 111 | RBTree* rb; 112 | RBNode* last_visited; 113 | bool is_over; 114 | } RBTreeDirectWalk; 115 | 116 | extern void rb_begin_direct_walk(RBTree *rb, RBTreeDirectWalk* dw); 117 | extern RBNode* rb_direct_walk(RBTreeDirectWalk* dw); 118 | 119 | typedef struct 120 | { 121 | RBTree* rb; 122 | RBNode* last_visited; 123 | RBTreeNextStep next_step; 124 | bool is_over; 125 | } RBTreeInvertedWalk; 126 | 127 | extern void rb_begin_inverted_walk(RBTree *rb, RBTreeInvertedWalk* dw); 128 | extern RBNode* rb_inverted_walk(RBTreeInvertedWalk* dw); 129 | 130 | #endif /* RBTREE_H */ 131 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(c-algorithms) 4 | 5 | add_library(CAlgorithms STATIC 6 | struct/ilist.c 7 | struct/rbtree.c 8 | struct/htable.c 9 | 10 | crypto/md5.c 11 | crypto/sha1.c 12 | crypto/sha2.c 13 | crypto/rijndael.c 14 | 15 | common/utils.c 16 | ) 17 | -------------------------------------------------------------------------------- /src/common/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | inline static int 6 | hexToInt(char c) 7 | { 8 | if(c >= '0' && c <= '9') 9 | return (c - '0'); 10 | 11 | if(c >= 'A' && c <= 'F') 12 | return (10 + c - 'A'); 13 | 14 | if(c >= 'a' && c <= 'f') 15 | return (10 + c - 'a'); 16 | 17 | return -1; 18 | } 19 | 20 | int 21 | hexToBytes(char* s, uint8_t* b, int blen) 22 | { 23 | int i, th, tl, slen = strlen(s); 24 | if(slen % 2 != 0) 25 | return -1; 26 | if(slen / 2 != blen) 27 | return -2; 28 | 29 | for(i = 0; i < blen; i++) 30 | { 31 | th = hexToInt(s[i*2]); 32 | tl = hexToInt(s[i*2+1]); 33 | if(th < 0 || tl < 0) 34 | return -1; 35 | 36 | b[i] = ((uint8_t)th << 4) | (uint8_t)tl; 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | void 43 | bytesToHex(uint8_t* b, int blen, char *s) 44 | { 45 | static const char *hex = "0123456789ABCDEF"; 46 | int q, w; 47 | 48 | for (q = 0, w = 0; q < blen; q++) 49 | { 50 | s[w++] = hex[(b[q] >> 4) & 0x0F]; 51 | s[w++] = hex[b[q] & 0x0F]; 52 | } 53 | s[w] = '\0'; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/crypto/md5.c: -------------------------------------------------------------------------------- 1 | /* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ 2 | 3 | /* 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the project nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * contrib/pgcrypto/md5.c 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "crypto/md5.h" 39 | 40 | #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s)))) 41 | 42 | #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) 43 | #define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z))) 44 | #define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) 45 | #define I(X, Y, Z) ((Y) ^ ((X) | (~Z))) 46 | 47 | #define ROUND1(a, b, c, d, k, s, i) \ 48 | do { \ 49 | (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ 50 | (a) = SHIFT((a), (s)); \ 51 | (a) = (b) + (a); \ 52 | } while (0) 53 | 54 | #define ROUND2(a, b, c, d, k, s, i) \ 55 | do { \ 56 | (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ 57 | (a) = SHIFT((a), (s)); \ 58 | (a) = (b) + (a); \ 59 | } while (0) 60 | 61 | #define ROUND3(a, b, c, d, k, s, i) \ 62 | do { \ 63 | (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ 64 | (a) = SHIFT((a), (s)); \ 65 | (a) = (b) + (a); \ 66 | } while (0) 67 | 68 | #define ROUND4(a, b, c, d, k, s, i) \ 69 | do { \ 70 | (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ 71 | (a) = SHIFT((a), (s)); \ 72 | (a) = (b) + (a); \ 73 | } while (0) 74 | 75 | #define Sa 7 76 | #define Sb 12 77 | #define Sc 17 78 | #define Sd 22 79 | 80 | #define Se 5 81 | #define Sf 9 82 | #define Sg 14 83 | #define Sh 20 84 | 85 | #define Si 4 86 | #define Sj 11 87 | #define Sk 16 88 | #define Sl 23 89 | 90 | #define Sm 6 91 | #define Sn 10 92 | #define So 15 93 | #define Sp 21 94 | 95 | #define MD5_A0 0x67452301 96 | #define MD5_B0 0xefcdab89 97 | #define MD5_C0 0x98badcfe 98 | #define MD5_D0 0x10325476 99 | 100 | /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */ 101 | static const uint32_t T[65] = { 102 | 0, 103 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 104 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 105 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 106 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 107 | 108 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 109 | 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 110 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 111 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 112 | 113 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 114 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 115 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 116 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 117 | 118 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 119 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 120 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 121 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, 122 | }; 123 | 124 | static const uint8_t md5_paddat[MD5_BUFLEN] = { 125 | 0x80, 0, 0, 0, 0, 0, 0, 0, 126 | 0, 0, 0, 0, 0, 0, 0, 0, 127 | 0, 0, 0, 0, 0, 0, 0, 0, 128 | 0, 0, 0, 0, 0, 0, 0, 0, 129 | 0, 0, 0, 0, 0, 0, 0, 0, 130 | 0, 0, 0, 0, 0, 0, 0, 0, 131 | 0, 0, 0, 0, 0, 0, 0, 0, 132 | 0, 0, 0, 0, 0, 0, 0, 0, 133 | }; 134 | 135 | static void md5_calc(uint8_t *, md5_ctxt *); 136 | 137 | void 138 | md5_init(md5_ctxt *ctxt) 139 | { 140 | ctxt->md5_n = 0; 141 | ctxt->md5_i = 0; 142 | ctxt->md5_sta = MD5_A0; 143 | ctxt->md5_stb = MD5_B0; 144 | ctxt->md5_stc = MD5_C0; 145 | ctxt->md5_std = MD5_D0; 146 | memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); 147 | } 148 | 149 | void 150 | md5_loop(md5_ctxt *ctxt, const uint8_t *input, unsigned len) 151 | { 152 | unsigned int gap, 153 | i; 154 | 155 | ctxt->md5_n += len * 8; /* byte to bit */ 156 | gap = MD5_BUFLEN - ctxt->md5_i; 157 | 158 | if (len >= gap) 159 | { 160 | memmove(ctxt->md5_buf + ctxt->md5_i, input, gap); 161 | md5_calc(ctxt->md5_buf, ctxt); 162 | 163 | for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) 164 | md5_calc((uint8_t *) (input + i), ctxt); 165 | 166 | ctxt->md5_i = len - i; 167 | memmove(ctxt->md5_buf, input + i, ctxt->md5_i); 168 | } 169 | else 170 | { 171 | memmove(ctxt->md5_buf + ctxt->md5_i, input, len); 172 | ctxt->md5_i += len; 173 | } 174 | } 175 | 176 | void 177 | md5_pad(md5_ctxt *ctxt) 178 | { 179 | unsigned int gap; 180 | 181 | /* Don't count up padding. Keep md5_n. */ 182 | gap = MD5_BUFLEN - ctxt->md5_i; 183 | if (gap > 8) 184 | { 185 | memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, 186 | gap - sizeof(ctxt->md5_n)); 187 | } 188 | else 189 | { 190 | /* including gap == 8 */ 191 | memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); 192 | md5_calc(ctxt->md5_buf, ctxt); 193 | memmove(ctxt->md5_buf, md5_paddat + gap, 194 | MD5_BUFLEN - sizeof(ctxt->md5_n)); 195 | } 196 | 197 | /* 8 byte word */ 198 | #ifndef WORDS_BIGENDIAN 199 | memmove(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); 200 | #else 201 | ctxt->md5_buf[56] = ctxt->md5_n8[7]; 202 | ctxt->md5_buf[57] = ctxt->md5_n8[6]; 203 | ctxt->md5_buf[58] = ctxt->md5_n8[5]; 204 | ctxt->md5_buf[59] = ctxt->md5_n8[4]; 205 | ctxt->md5_buf[60] = ctxt->md5_n8[3]; 206 | ctxt->md5_buf[61] = ctxt->md5_n8[2]; 207 | ctxt->md5_buf[62] = ctxt->md5_n8[1]; 208 | ctxt->md5_buf[63] = ctxt->md5_n8[0]; 209 | #endif 210 | 211 | md5_calc(ctxt->md5_buf, ctxt); 212 | } 213 | 214 | void 215 | md5_result(uint8_t *digest, md5_ctxt *ctxt) 216 | { 217 | /* 4 byte words */ 218 | #ifndef WORDS_BIGENDIAN 219 | memmove(digest, &ctxt->md5_st8[0], 16); 220 | #else 221 | digest[0] = ctxt->md5_st8[3]; 222 | digest[1] = ctxt->md5_st8[2]; 223 | digest[2] = ctxt->md5_st8[1]; 224 | digest[3] = ctxt->md5_st8[0]; 225 | digest[4] = ctxt->md5_st8[7]; 226 | digest[5] = ctxt->md5_st8[6]; 227 | digest[6] = ctxt->md5_st8[5]; 228 | digest[7] = ctxt->md5_st8[4]; 229 | digest[8] = ctxt->md5_st8[11]; 230 | digest[9] = ctxt->md5_st8[10]; 231 | digest[10] = ctxt->md5_st8[9]; 232 | digest[11] = ctxt->md5_st8[8]; 233 | digest[12] = ctxt->md5_st8[15]; 234 | digest[13] = ctxt->md5_st8[14]; 235 | digest[14] = ctxt->md5_st8[13]; 236 | digest[15] = ctxt->md5_st8[12]; 237 | #endif 238 | } 239 | 240 | #ifdef WORDS_BIGENDIAN 241 | static uint32_t X[16]; 242 | #endif 243 | 244 | static void 245 | md5_calc(uint8_t *b64, md5_ctxt *ctxt) 246 | { 247 | uint32_t A = ctxt->md5_sta; 248 | uint32_t B = ctxt->md5_stb; 249 | uint32_t C = ctxt->md5_stc; 250 | uint32_t D = ctxt->md5_std; 251 | 252 | #ifndef WORDS_BIGENDIAN 253 | uint32_t *X = (uint32_t *) b64; 254 | #else 255 | /* 4 byte words */ 256 | /* what a brute force but fast! */ 257 | uint8_t *y = (uint8_t *) X; 258 | 259 | y[0] = b64[3]; 260 | y[1] = b64[2]; 261 | y[2] = b64[1]; 262 | y[3] = b64[0]; 263 | y[4] = b64[7]; 264 | y[5] = b64[6]; 265 | y[6] = b64[5]; 266 | y[7] = b64[4]; 267 | y[8] = b64[11]; 268 | y[9] = b64[10]; 269 | y[10] = b64[9]; 270 | y[11] = b64[8]; 271 | y[12] = b64[15]; 272 | y[13] = b64[14]; 273 | y[14] = b64[13]; 274 | y[15] = b64[12]; 275 | y[16] = b64[19]; 276 | y[17] = b64[18]; 277 | y[18] = b64[17]; 278 | y[19] = b64[16]; 279 | y[20] = b64[23]; 280 | y[21] = b64[22]; 281 | y[22] = b64[21]; 282 | y[23] = b64[20]; 283 | y[24] = b64[27]; 284 | y[25] = b64[26]; 285 | y[26] = b64[25]; 286 | y[27] = b64[24]; 287 | y[28] = b64[31]; 288 | y[29] = b64[30]; 289 | y[30] = b64[29]; 290 | y[31] = b64[28]; 291 | y[32] = b64[35]; 292 | y[33] = b64[34]; 293 | y[34] = b64[33]; 294 | y[35] = b64[32]; 295 | y[36] = b64[39]; 296 | y[37] = b64[38]; 297 | y[38] = b64[37]; 298 | y[39] = b64[36]; 299 | y[40] = b64[43]; 300 | y[41] = b64[42]; 301 | y[42] = b64[41]; 302 | y[43] = b64[40]; 303 | y[44] = b64[47]; 304 | y[45] = b64[46]; 305 | y[46] = b64[45]; 306 | y[47] = b64[44]; 307 | y[48] = b64[51]; 308 | y[49] = b64[50]; 309 | y[50] = b64[49]; 310 | y[51] = b64[48]; 311 | y[52] = b64[55]; 312 | y[53] = b64[54]; 313 | y[54] = b64[53]; 314 | y[55] = b64[52]; 315 | y[56] = b64[59]; 316 | y[57] = b64[58]; 317 | y[58] = b64[57]; 318 | y[59] = b64[56]; 319 | y[60] = b64[63]; 320 | y[61] = b64[62]; 321 | y[62] = b64[61]; 322 | y[63] = b64[60]; 323 | #endif 324 | 325 | ROUND1(A, B, C, D, 0, Sa, 1); 326 | ROUND1(D, A, B, C, 1, Sb, 2); 327 | ROUND1(C, D, A, B, 2, Sc, 3); 328 | ROUND1(B, C, D, A, 3, Sd, 4); 329 | ROUND1(A, B, C, D, 4, Sa, 5); 330 | ROUND1(D, A, B, C, 5, Sb, 6); 331 | ROUND1(C, D, A, B, 6, Sc, 7); 332 | ROUND1(B, C, D, A, 7, Sd, 8); 333 | ROUND1(A, B, C, D, 8, Sa, 9); 334 | ROUND1(D, A, B, C, 9, Sb, 10); 335 | ROUND1(C, D, A, B, 10, Sc, 11); 336 | ROUND1(B, C, D, A, 11, Sd, 12); 337 | ROUND1(A, B, C, D, 12, Sa, 13); 338 | ROUND1(D, A, B, C, 13, Sb, 14); 339 | ROUND1(C, D, A, B, 14, Sc, 15); 340 | ROUND1(B, C, D, A, 15, Sd, 16); 341 | 342 | ROUND2(A, B, C, D, 1, Se, 17); 343 | ROUND2(D, A, B, C, 6, Sf, 18); 344 | ROUND2(C, D, A, B, 11, Sg, 19); 345 | ROUND2(B, C, D, A, 0, Sh, 20); 346 | ROUND2(A, B, C, D, 5, Se, 21); 347 | ROUND2(D, A, B, C, 10, Sf, 22); 348 | ROUND2(C, D, A, B, 15, Sg, 23); 349 | ROUND2(B, C, D, A, 4, Sh, 24); 350 | ROUND2(A, B, C, D, 9, Se, 25); 351 | ROUND2(D, A, B, C, 14, Sf, 26); 352 | ROUND2(C, D, A, B, 3, Sg, 27); 353 | ROUND2(B, C, D, A, 8, Sh, 28); 354 | ROUND2(A, B, C, D, 13, Se, 29); 355 | ROUND2(D, A, B, C, 2, Sf, 30); 356 | ROUND2(C, D, A, B, 7, Sg, 31); 357 | ROUND2(B, C, D, A, 12, Sh, 32); 358 | 359 | ROUND3(A, B, C, D, 5, Si, 33); 360 | ROUND3(D, A, B, C, 8, Sj, 34); 361 | ROUND3(C, D, A, B, 11, Sk, 35); 362 | ROUND3(B, C, D, A, 14, Sl, 36); 363 | ROUND3(A, B, C, D, 1, Si, 37); 364 | ROUND3(D, A, B, C, 4, Sj, 38); 365 | ROUND3(C, D, A, B, 7, Sk, 39); 366 | ROUND3(B, C, D, A, 10, Sl, 40); 367 | ROUND3(A, B, C, D, 13, Si, 41); 368 | ROUND3(D, A, B, C, 0, Sj, 42); 369 | ROUND3(C, D, A, B, 3, Sk, 43); 370 | ROUND3(B, C, D, A, 6, Sl, 44); 371 | ROUND3(A, B, C, D, 9, Si, 45); 372 | ROUND3(D, A, B, C, 12, Sj, 46); 373 | ROUND3(C, D, A, B, 15, Sk, 47); 374 | ROUND3(B, C, D, A, 2, Sl, 48); 375 | 376 | ROUND4(A, B, C, D, 0, Sm, 49); 377 | ROUND4(D, A, B, C, 7, Sn, 50); 378 | ROUND4(C, D, A, B, 14, So, 51); 379 | ROUND4(B, C, D, A, 5, Sp, 52); 380 | ROUND4(A, B, C, D, 12, Sm, 53); 381 | ROUND4(D, A, B, C, 3, Sn, 54); 382 | ROUND4(C, D, A, B, 10, So, 55); 383 | ROUND4(B, C, D, A, 1, Sp, 56); 384 | ROUND4(A, B, C, D, 8, Sm, 57); 385 | ROUND4(D, A, B, C, 15, Sn, 58); 386 | ROUND4(C, D, A, B, 6, So, 59); 387 | ROUND4(B, C, D, A, 13, Sp, 60); 388 | ROUND4(A, B, C, D, 4, Sm, 61); 389 | ROUND4(D, A, B, C, 11, Sn, 62); 390 | ROUND4(C, D, A, B, 2, So, 63); 391 | ROUND4(B, C, D, A, 9, Sp, 64); 392 | 393 | ctxt->md5_sta += A; 394 | ctxt->md5_stb += B; 395 | ctxt->md5_stc += C; 396 | ctxt->md5_std += D; 397 | } 398 | -------------------------------------------------------------------------------- /src/crypto/rijndael.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */ 2 | 3 | /* contrib/pgcrypto/rijndael.c */ 4 | 5 | /* This is an independent implementation of the encryption algorithm: */ 6 | /* */ 7 | /* RIJNDAEL by Joan Daemen and Vincent Rijmen */ 8 | /* */ 9 | /* which is a candidate algorithm in the Advanced Encryption Standard */ 10 | /* programme of the US National Institute of Standards and Technology. */ 11 | /* */ 12 | /* Copyright in this implementation is held by Dr B R Gladman but I */ 13 | /* hereby give permission for its free direct or derivative use subject */ 14 | /* to acknowledgment of its origin and compliance with any conditions */ 15 | /* that the originators of the algorithm place on its exploitation. */ 16 | /* */ 17 | /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ 18 | 19 | /* Timing data for Rijndael (rijndael.c) 20 | 21 | Algorithm: rijndael (rijndael.c) 22 | 23 | 128 bit key: 24 | Key Setup: 305/1389 cycles (encrypt/decrypt) 25 | Encrypt: 374 cycles = 68.4 mbits/sec 26 | Decrypt: 352 cycles = 72.7 mbits/sec 27 | Mean: 363 cycles = 70.5 mbits/sec 28 | 29 | 192 bit key: 30 | Key Setup: 277/1595 cycles (encrypt/decrypt) 31 | Encrypt: 439 cycles = 58.3 mbits/sec 32 | Decrypt: 425 cycles = 60.2 mbits/sec 33 | Mean: 432 cycles = 59.3 mbits/sec 34 | 35 | 256 bit key: 36 | Key Setup: 374/1960 cycles (encrypt/decrypt) 37 | Encrypt: 502 cycles = 51.0 mbits/sec 38 | Decrypt: 498 cycles = 51.4 mbits/sec 39 | Mean: 500 cycles = 51.2 mbits/sec 40 | 41 | */ 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #include "crypto/rijndael.h" 48 | 49 | #define PRE_CALC_TABLES 50 | #define LARGE_TABLES 51 | 52 | static void gen_tabs(void); 53 | 54 | /* 3. Basic macros for speeding up generic operations */ 55 | 56 | /* Circular rotate of 32 bit values */ 57 | 58 | #define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) 59 | #define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) 60 | 61 | /* Invert byte order in a 32 bit variable */ 62 | 63 | #define bswap(x) ((rotl((x), 8) & 0x00ff00ff) | (rotr((x), 8) & 0xff00ff00)) 64 | 65 | /* Extract byte from a 32 bit quantity (little endian notation) */ 66 | 67 | #define byte(x,n) ((u1byte)((x) >> (8 * (n)))) 68 | 69 | #ifdef WORDS_BIGENDIAN 70 | #define io_swap(x) bswap(x) 71 | #else 72 | #define io_swap(x) (x) 73 | #endif 74 | 75 | #ifdef PRINT_TABS 76 | #undef PRE_CALC_TABLES 77 | #endif 78 | 79 | #ifdef PRE_CALC_TABLES 80 | 81 | #include "rijndael.tbl" 82 | #define tab_gen 1 83 | #else /* !PRE_CALC_TABLES */ 84 | 85 | static u1byte pow_tab[256]; 86 | static u1byte log_tab[256]; 87 | static u1byte sbx_tab[256]; 88 | static u1byte isb_tab[256]; 89 | static u4byte rco_tab[10]; 90 | static u4byte ft_tab[4][256]; 91 | static u4byte it_tab[4][256]; 92 | 93 | #ifdef LARGE_TABLES 94 | static u4byte fl_tab[4][256]; 95 | static u4byte il_tab[4][256]; 96 | #endif 97 | 98 | static u4byte tab_gen = 0; 99 | #endif /* !PRE_CALC_TABLES */ 100 | 101 | #define ff_mult(a,b) ((a) && (b) ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0) 102 | 103 | #define f_rn(bo, bi, n, k) \ 104 | (bo)[n] = ft_tab[0][byte((bi)[n],0)] ^ \ 105 | ft_tab[1][byte((bi)[((n) + 1) & 3],1)] ^ \ 106 | ft_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \ 107 | ft_tab[3][byte((bi)[((n) + 3) & 3],3)] ^ *((k) + (n)) 108 | 109 | #define i_rn(bo, bi, n, k) \ 110 | (bo)[n] = it_tab[0][byte((bi)[n],0)] ^ \ 111 | it_tab[1][byte((bi)[((n) + 3) & 3],1)] ^ \ 112 | it_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \ 113 | it_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n)) 114 | 115 | #ifdef LARGE_TABLES 116 | 117 | #define ls_box(x) \ 118 | ( fl_tab[0][byte(x, 0)] ^ \ 119 | fl_tab[1][byte(x, 1)] ^ \ 120 | fl_tab[2][byte(x, 2)] ^ \ 121 | fl_tab[3][byte(x, 3)] ) 122 | 123 | #define f_rl(bo, bi, n, k) \ 124 | (bo)[n] = fl_tab[0][byte((bi)[n],0)] ^ \ 125 | fl_tab[1][byte((bi)[((n) + 1) & 3],1)] ^ \ 126 | fl_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \ 127 | fl_tab[3][byte((bi)[((n) + 3) & 3],3)] ^ *((k) + (n)) 128 | 129 | #define i_rl(bo, bi, n, k) \ 130 | (bo)[n] = il_tab[0][byte((bi)[n],0)] ^ \ 131 | il_tab[1][byte((bi)[((n) + 3) & 3],1)] ^ \ 132 | il_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \ 133 | il_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n)) 134 | #else 135 | 136 | #define ls_box(x) \ 137 | ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \ 138 | ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \ 139 | ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \ 140 | ((u4byte)sbx_tab[byte(x, 3)] << 24) 141 | 142 | #define f_rl(bo, bi, n, k) \ 143 | (bo)[n] = (u4byte)sbx_tab[byte((bi)[n],0)] ^ \ 144 | rotl(((u4byte)sbx_tab[byte((bi)[((n) + 1) & 3],1)]), 8) ^ \ 145 | rotl(((u4byte)sbx_tab[byte((bi)[((n) + 2) & 3],2)]), 16) ^ \ 146 | rotl(((u4byte)sbx_tab[byte((bi)[((n) + 3) & 3],3)]), 24) ^ *((k) + (n)) 147 | 148 | #define i_rl(bo, bi, n, k) \ 149 | (bo)[n] = (u4byte)isb_tab[byte((bi)[n],0)] ^ \ 150 | rotl(((u4byte)isb_tab[byte((bi)[((n) + 3) & 3],1)]), 8) ^ \ 151 | rotl(((u4byte)isb_tab[byte((bi)[((n) + 2) & 3],2)]), 16) ^ \ 152 | rotl(((u4byte)isb_tab[byte((bi)[((n) + 1) & 3],3)]), 24) ^ *((k) + (n)) 153 | #endif 154 | 155 | static void 156 | gen_tabs(void) 157 | { 158 | #ifndef PRE_CALC_TABLES 159 | u4byte i, 160 | t; 161 | u1byte p, 162 | q; 163 | 164 | /* log and power tables for GF(2**8) finite field with */ 165 | /* 0x11b as modular polynomial - the simplest prmitive */ 166 | /* root is 0x11, used here to generate the tables */ 167 | 168 | for (i = 0, p = 1; i < 256; ++i) 169 | { 170 | pow_tab[i] = (u1byte) p; 171 | log_tab[p] = (u1byte) i; 172 | 173 | p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0); 174 | } 175 | 176 | log_tab[1] = 0; 177 | p = 1; 178 | 179 | for (i = 0; i < 10; ++i) 180 | { 181 | rco_tab[i] = p; 182 | 183 | p = (p << 1) ^ (p & 0x80 ? 0x1b : 0); 184 | } 185 | 186 | /* note that the affine byte transformation matrix in */ 187 | /* rijndael specification is in big endian format with */ 188 | /* bit 0 as the most significant bit. In the remainder */ 189 | /* of the specification the bits are numbered from the */ 190 | /* least significant end of a byte. */ 191 | 192 | for (i = 0; i < 256; ++i) 193 | { 194 | p = (i ? pow_tab[255 - log_tab[i]] : 0); 195 | q = p; 196 | q = (q >> 7) | (q << 1); 197 | p ^= q; 198 | q = (q >> 7) | (q << 1); 199 | p ^= q; 200 | q = (q >> 7) | (q << 1); 201 | p ^= q; 202 | q = (q >> 7) | (q << 1); 203 | p ^= q ^ 0x63; 204 | sbx_tab[i] = (u1byte) p; 205 | isb_tab[p] = (u1byte) i; 206 | } 207 | 208 | for (i = 0; i < 256; ++i) 209 | { 210 | p = sbx_tab[i]; 211 | 212 | #ifdef LARGE_TABLES 213 | 214 | t = p; 215 | fl_tab[0][i] = t; 216 | fl_tab[1][i] = rotl(t, 8); 217 | fl_tab[2][i] = rotl(t, 16); 218 | fl_tab[3][i] = rotl(t, 24); 219 | #endif 220 | t = ((u4byte) ff_mult(2, p)) | 221 | ((u4byte) p << 8) | 222 | ((u4byte) p << 16) | 223 | ((u4byte) ff_mult(3, p) << 24); 224 | 225 | ft_tab[0][i] = t; 226 | ft_tab[1][i] = rotl(t, 8); 227 | ft_tab[2][i] = rotl(t, 16); 228 | ft_tab[3][i] = rotl(t, 24); 229 | 230 | p = isb_tab[i]; 231 | 232 | #ifdef LARGE_TABLES 233 | 234 | t = p; 235 | il_tab[0][i] = t; 236 | il_tab[1][i] = rotl(t, 8); 237 | il_tab[2][i] = rotl(t, 16); 238 | il_tab[3][i] = rotl(t, 24); 239 | #endif 240 | t = ((u4byte) ff_mult(14, p)) | 241 | ((u4byte) ff_mult(9, p) << 8) | 242 | ((u4byte) ff_mult(13, p) << 16) | 243 | ((u4byte) ff_mult(11, p) << 24); 244 | 245 | it_tab[0][i] = t; 246 | it_tab[1][i] = rotl(t, 8); 247 | it_tab[2][i] = rotl(t, 16); 248 | it_tab[3][i] = rotl(t, 24); 249 | } 250 | 251 | tab_gen = 1; 252 | #endif /* !PRE_CALC_TABLES */ 253 | } 254 | 255 | 256 | #define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) 257 | 258 | #define imix_col(y,x) \ 259 | do { \ 260 | u = star_x(x); \ 261 | v = star_x(u); \ 262 | w = star_x(v); \ 263 | t = w ^ (x); \ 264 | (y) = u ^ v ^ w; \ 265 | (y) ^= rotr(u ^ t, 8) ^ \ 266 | rotr(v ^ t, 16) ^ \ 267 | rotr(t,24); \ 268 | } while (0) 269 | 270 | /* initialise the key schedule from the user supplied key */ 271 | 272 | #define loop4(i) \ 273 | do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ 274 | t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \ 275 | t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \ 276 | t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \ 277 | t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \ 278 | } while (0) 279 | 280 | #define loop6(i) \ 281 | do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ 282 | t ^= e_key[6 * (i)]; e_key[6 * (i) + 6] = t; \ 283 | t ^= e_key[6 * (i) + 1]; e_key[6 * (i) + 7] = t; \ 284 | t ^= e_key[6 * (i) + 2]; e_key[6 * (i) + 8] = t; \ 285 | t ^= e_key[6 * (i) + 3]; e_key[6 * (i) + 9] = t; \ 286 | t ^= e_key[6 * (i) + 4]; e_key[6 * (i) + 10] = t; \ 287 | t ^= e_key[6 * (i) + 5]; e_key[6 * (i) + 11] = t; \ 288 | } while (0) 289 | 290 | #define loop8(i) \ 291 | do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ 292 | t ^= e_key[8 * (i)]; e_key[8 * (i) + 8] = t; \ 293 | t ^= e_key[8 * (i) + 1]; e_key[8 * (i) + 9] = t; \ 294 | t ^= e_key[8 * (i) + 2]; e_key[8 * (i) + 10] = t; \ 295 | t ^= e_key[8 * (i) + 3]; e_key[8 * (i) + 11] = t; \ 296 | t = e_key[8 * (i) + 4] ^ ls_box(t); \ 297 | e_key[8 * (i) + 12] = t; \ 298 | t ^= e_key[8 * (i) + 5]; e_key[8 * (i) + 13] = t; \ 299 | t ^= e_key[8 * (i) + 6]; e_key[8 * (i) + 14] = t; \ 300 | t ^= e_key[8 * (i) + 7]; e_key[8 * (i) + 15] = t; \ 301 | } while (0) 302 | 303 | rijndael_ctx * 304 | rijndael_set_key(rijndael_ctx *ctx, const u4byte *in_key, const u4byte key_len, 305 | int encrypt) 306 | { 307 | u4byte i, 308 | t, 309 | u, 310 | v, 311 | w; 312 | u4byte *e_key = ctx->e_key; 313 | u4byte *d_key = ctx->d_key; 314 | 315 | ctx->decrypt = !encrypt; 316 | 317 | if (!tab_gen) 318 | gen_tabs(); 319 | 320 | ctx->k_len = (key_len + 31) / 32; 321 | 322 | e_key[0] = io_swap(in_key[0]); 323 | e_key[1] = io_swap(in_key[1]); 324 | e_key[2] = io_swap(in_key[2]); 325 | e_key[3] = io_swap(in_key[3]); 326 | 327 | switch (ctx->k_len) 328 | { 329 | case 4: 330 | t = e_key[3]; 331 | for (i = 0; i < 10; ++i) 332 | loop4(i); 333 | break; 334 | 335 | case 6: 336 | e_key[4] = io_swap(in_key[4]); 337 | t = e_key[5] = io_swap(in_key[5]); 338 | for (i = 0; i < 8; ++i) 339 | loop6(i); 340 | break; 341 | 342 | case 8: 343 | e_key[4] = io_swap(in_key[4]); 344 | e_key[5] = io_swap(in_key[5]); 345 | e_key[6] = io_swap(in_key[6]); 346 | t = e_key[7] = io_swap(in_key[7]); 347 | for (i = 0; i < 7; ++i) 348 | loop8(i); 349 | break; 350 | } 351 | 352 | if (!encrypt) 353 | { 354 | d_key[0] = e_key[0]; 355 | d_key[1] = e_key[1]; 356 | d_key[2] = e_key[2]; 357 | d_key[3] = e_key[3]; 358 | 359 | for (i = 4; i < 4 * ctx->k_len + 24; ++i) 360 | imix_col(d_key[i], e_key[i]); 361 | } 362 | 363 | return ctx; 364 | } 365 | 366 | /* encrypt a block of text */ 367 | 368 | #define f_nround(bo, bi, k) \ 369 | do { \ 370 | f_rn(bo, bi, 0, k); \ 371 | f_rn(bo, bi, 1, k); \ 372 | f_rn(bo, bi, 2, k); \ 373 | f_rn(bo, bi, 3, k); \ 374 | k += 4; \ 375 | } while (0) 376 | 377 | #define f_lround(bo, bi, k) \ 378 | do { \ 379 | f_rl(bo, bi, 0, k); \ 380 | f_rl(bo, bi, 1, k); \ 381 | f_rl(bo, bi, 2, k); \ 382 | f_rl(bo, bi, 3, k); \ 383 | } while (0) 384 | 385 | void 386 | rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) 387 | { 388 | u4byte k_len = ctx->k_len; 389 | u4byte *e_key = ctx->e_key; 390 | u4byte b0[4], 391 | b1[4], 392 | *kp; 393 | 394 | b0[0] = io_swap(in_blk[0]) ^ e_key[0]; 395 | b0[1] = io_swap(in_blk[1]) ^ e_key[1]; 396 | b0[2] = io_swap(in_blk[2]) ^ e_key[2]; 397 | b0[3] = io_swap(in_blk[3]) ^ e_key[3]; 398 | 399 | kp = e_key + 4; 400 | 401 | if (k_len > 6) 402 | { 403 | f_nround(b1, b0, kp); 404 | f_nround(b0, b1, kp); 405 | } 406 | 407 | if (k_len > 4) 408 | { 409 | f_nround(b1, b0, kp); 410 | f_nround(b0, b1, kp); 411 | } 412 | 413 | f_nround(b1, b0, kp); 414 | f_nround(b0, b1, kp); 415 | f_nround(b1, b0, kp); 416 | f_nround(b0, b1, kp); 417 | f_nround(b1, b0, kp); 418 | f_nround(b0, b1, kp); 419 | f_nround(b1, b0, kp); 420 | f_nround(b0, b1, kp); 421 | f_nround(b1, b0, kp); 422 | f_lround(b0, b1, kp); 423 | 424 | out_blk[0] = io_swap(b0[0]); 425 | out_blk[1] = io_swap(b0[1]); 426 | out_blk[2] = io_swap(b0[2]); 427 | out_blk[3] = io_swap(b0[3]); 428 | } 429 | 430 | /* decrypt a block of text */ 431 | 432 | #define i_nround(bo, bi, k) \ 433 | do { \ 434 | i_rn(bo, bi, 0, k); \ 435 | i_rn(bo, bi, 1, k); \ 436 | i_rn(bo, bi, 2, k); \ 437 | i_rn(bo, bi, 3, k); \ 438 | k -= 4; \ 439 | } while (0) 440 | 441 | #define i_lround(bo, bi, k) \ 442 | do { \ 443 | i_rl(bo, bi, 0, k); \ 444 | i_rl(bo, bi, 1, k); \ 445 | i_rl(bo, bi, 2, k); \ 446 | i_rl(bo, bi, 3, k); \ 447 | } while (0) 448 | 449 | void 450 | rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) 451 | { 452 | u4byte b0[4], 453 | b1[4], 454 | *kp; 455 | u4byte k_len = ctx->k_len; 456 | u4byte *e_key = ctx->e_key; 457 | u4byte *d_key = ctx->d_key; 458 | 459 | b0[0] = io_swap(in_blk[0]) ^ e_key[4 * k_len + 24]; 460 | b0[1] = io_swap(in_blk[1]) ^ e_key[4 * k_len + 25]; 461 | b0[2] = io_swap(in_blk[2]) ^ e_key[4 * k_len + 26]; 462 | b0[3] = io_swap(in_blk[3]) ^ e_key[4 * k_len + 27]; 463 | 464 | kp = d_key + 4 * (k_len + 5); 465 | 466 | if (k_len > 6) 467 | { 468 | i_nround(b1, b0, kp); 469 | i_nround(b0, b1, kp); 470 | } 471 | 472 | if (k_len > 4) 473 | { 474 | i_nround(b1, b0, kp); 475 | i_nround(b0, b1, kp); 476 | } 477 | 478 | i_nround(b1, b0, kp); 479 | i_nround(b0, b1, kp); 480 | i_nround(b1, b0, kp); 481 | i_nround(b0, b1, kp); 482 | i_nround(b1, b0, kp); 483 | i_nround(b0, b1, kp); 484 | i_nround(b1, b0, kp); 485 | i_nround(b0, b1, kp); 486 | i_nround(b1, b0, kp); 487 | i_lround(b0, b1, kp); 488 | 489 | out_blk[0] = io_swap(b0[0]); 490 | out_blk[1] = io_swap(b0[1]); 491 | out_blk[2] = io_swap(b0[2]); 492 | out_blk[3] = io_swap(b0[3]); 493 | } 494 | 495 | /* 496 | * conventional interface 497 | * 498 | * ATM it hopes all data is 4-byte aligned - which 499 | * should be true for PX. -marko 500 | */ 501 | 502 | void 503 | aes_set_key(rijndael_ctx *ctx, const uint8_t *key, unsigned keybits, int enc) 504 | { 505 | uint32_t *k; 506 | 507 | k = (uint32_t *) key; 508 | rijndael_set_key(ctx, k, keybits, enc); 509 | } 510 | 511 | void 512 | aes_ecb_encrypt(rijndael_ctx *ctx, uint8_t *data, unsigned len) 513 | { 514 | unsigned bs = 16; 515 | uint32_t *d; 516 | 517 | while (len >= bs) 518 | { 519 | d = (uint32_t *) data; 520 | rijndael_encrypt(ctx, d, d); 521 | 522 | len -= bs; 523 | data += bs; 524 | } 525 | } 526 | 527 | void 528 | aes_ecb_decrypt(rijndael_ctx *ctx, uint8_t *data, unsigned len) 529 | { 530 | unsigned bs = 16; 531 | uint32_t *d; 532 | 533 | while (len >= bs) 534 | { 535 | d = (uint32_t *) data; 536 | rijndael_decrypt(ctx, d, d); 537 | 538 | len -= bs; 539 | data += bs; 540 | } 541 | } 542 | 543 | void 544 | aes_cbc_encrypt(rijndael_ctx *ctx, uint8_t *iva, uint8_t *data, unsigned len) 545 | { 546 | uint32_t *iv = (uint32_t *) iva; 547 | uint32_t *d = (uint32_t *) data; 548 | unsigned bs = 16; 549 | 550 | while (len >= bs) 551 | { 552 | d[0] ^= iv[0]; 553 | d[1] ^= iv[1]; 554 | d[2] ^= iv[2]; 555 | d[3] ^= iv[3]; 556 | 557 | rijndael_encrypt(ctx, d, d); 558 | 559 | iv = d; 560 | d += bs / 4; 561 | len -= bs; 562 | } 563 | } 564 | 565 | void 566 | aes_cbc_decrypt(rijndael_ctx *ctx, uint8_t *iva, uint8_t *data, unsigned len) 567 | { 568 | uint32_t *d = (uint32_t *) data; 569 | unsigned bs = 16; 570 | uint32_t buf[4], 571 | iv[4]; 572 | 573 | memcpy(iv, iva, bs); 574 | while (len >= bs) 575 | { 576 | buf[0] = d[0]; 577 | buf[1] = d[1]; 578 | buf[2] = d[2]; 579 | buf[3] = d[3]; 580 | 581 | rijndael_decrypt(ctx, buf, d); 582 | 583 | d[0] ^= iv[0]; 584 | d[1] ^= iv[1]; 585 | d[2] ^= iv[2]; 586 | d[3] ^= iv[3]; 587 | 588 | iv[0] = buf[0]; 589 | iv[1] = buf[1]; 590 | iv[2] = buf[2]; 591 | iv[3] = buf[3]; 592 | d += 4; 593 | len -= bs; 594 | } 595 | } 596 | 597 | /* 598 | * pre-calculate tables. 599 | * 600 | * On i386 lifts 17k from .bss to .rodata 601 | * and avoids 1k code and setup time. 602 | * -marko 603 | */ 604 | #ifdef PRINT_TABS 605 | 606 | static void 607 | show256u8(char *name, uint8_t *data) 608 | { 609 | int i; 610 | 611 | printf("static const u1byte %s[256] = {\n ", name); 612 | for (i = 0; i < 256;) 613 | { 614 | printf("%u", pow_tab[i++]); 615 | if (i < 256) 616 | printf(i % 16 ? ", " : ",\n "); 617 | } 618 | printf("\n};\n\n"); 619 | } 620 | 621 | 622 | static void 623 | show4x256u32(char *name, uint32_t data[4][256]) 624 | { 625 | int i, 626 | j; 627 | 628 | printf("static const u4byte %s[4][256] = {\n{\n ", name); 629 | for (i = 0; i < 4; i++) 630 | { 631 | for (j = 0; j < 256;) 632 | { 633 | printf("0x%08x", data[i][j]); 634 | j++; 635 | if (j < 256) 636 | printf(j % 4 ? ", " : ",\n "); 637 | } 638 | printf(i < 3 ? "\n}, {\n " : "\n}\n"); 639 | } 640 | printf("};\n\n"); 641 | } 642 | 643 | int 644 | main() 645 | { 646 | int i; 647 | char *hdr = "/* Generated by rijndael.c */\n\n"; 648 | 649 | gen_tabs(); 650 | 651 | printf(hdr); 652 | show256u8("pow_tab", pow_tab); 653 | show256u8("log_tab", log_tab); 654 | show256u8("sbx_tab", sbx_tab); 655 | show256u8("isb_tab", isb_tab); 656 | 657 | show4x256u32("ft_tab", ft_tab); 658 | show4x256u32("it_tab", it_tab); 659 | #ifdef LARGE_TABLES 660 | show4x256u32("fl_tab", fl_tab); 661 | show4x256u32("il_tab", il_tab); 662 | #endif 663 | printf("static const u4byte rco_tab[10] = {\n "); 664 | for (i = 0; i < 10; i++) 665 | { 666 | printf("0x%08x", rco_tab[i]); 667 | if (i < 9) 668 | printf(", "); 669 | if (i == 4) 670 | printf("\n "); 671 | } 672 | printf("\n};\n\n"); 673 | return 0; 674 | } 675 | 676 | #endif 677 | -------------------------------------------------------------------------------- /src/crypto/sha1.c: -------------------------------------------------------------------------------- 1 | /* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ 2 | 3 | /* 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the project nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * contrib/pgcrypto/sha1.c 32 | */ 33 | /* 34 | * FIPS pub 180-1: Secure Hash Algorithm (SHA-1) 35 | * based on: http://www.itl.nist.gov/fipspubs/fip180-1.htm 36 | * implemented by Jun-ichiro itojun Itoh 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include "crypto/sha1.h" 43 | 44 | /* constant table */ 45 | static uint32_t _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; 46 | 47 | #define K(t) _K[(t) / 20] 48 | 49 | #define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) 50 | #define F1(b, c, d) (((b) ^ (c)) ^ (d)) 51 | #define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) 52 | #define F3(b, c, d) (((b) ^ (c)) ^ (d)) 53 | 54 | #define S(n, x) (((x) << (n)) | ((x) >> (32 - (n)))) 55 | 56 | #define H(n) (ctxt->h.b32[(n)]) 57 | #define COUNT (ctxt->count) 58 | #define BCOUNT (ctxt->c.b64[0] / 8) 59 | #define W(n) (ctxt->m.b32[(n)]) 60 | 61 | #define PUTBYTE(x) \ 62 | do { \ 63 | ctxt->m.b8[(COUNT % 64)] = (x); \ 64 | COUNT++; \ 65 | COUNT %= 64; \ 66 | ctxt->c.b64[0] += 8; \ 67 | if (COUNT % 64 == 0) \ 68 | sha1_step(ctxt); \ 69 | } while (0) 70 | 71 | #define PUTPAD(x) \ 72 | do { \ 73 | ctxt->m.b8[(COUNT % 64)] = (x); \ 74 | COUNT++; \ 75 | COUNT %= 64; \ 76 | if (COUNT % 64 == 0) \ 77 | sha1_step(ctxt); \ 78 | } while (0) 79 | 80 | static void sha1_step(struct sha1_ctxt *); 81 | 82 | static void 83 | sha1_step(struct sha1_ctxt * ctxt) 84 | { 85 | uint32_t a, 86 | b, 87 | c, 88 | d, 89 | e; 90 | size_t t, 91 | s; 92 | uint32_t tmp; 93 | 94 | #ifndef WORDS_BIGENDIAN 95 | struct sha1_ctxt tctxt; 96 | 97 | memmove(&tctxt.m.b8[0], &ctxt->m.b8[0], 64); 98 | ctxt->m.b8[0] = tctxt.m.b8[3]; 99 | ctxt->m.b8[1] = tctxt.m.b8[2]; 100 | ctxt->m.b8[2] = tctxt.m.b8[1]; 101 | ctxt->m.b8[3] = tctxt.m.b8[0]; 102 | ctxt->m.b8[4] = tctxt.m.b8[7]; 103 | ctxt->m.b8[5] = tctxt.m.b8[6]; 104 | ctxt->m.b8[6] = tctxt.m.b8[5]; 105 | ctxt->m.b8[7] = tctxt.m.b8[4]; 106 | ctxt->m.b8[8] = tctxt.m.b8[11]; 107 | ctxt->m.b8[9] = tctxt.m.b8[10]; 108 | ctxt->m.b8[10] = tctxt.m.b8[9]; 109 | ctxt->m.b8[11] = tctxt.m.b8[8]; 110 | ctxt->m.b8[12] = tctxt.m.b8[15]; 111 | ctxt->m.b8[13] = tctxt.m.b8[14]; 112 | ctxt->m.b8[14] = tctxt.m.b8[13]; 113 | ctxt->m.b8[15] = tctxt.m.b8[12]; 114 | ctxt->m.b8[16] = tctxt.m.b8[19]; 115 | ctxt->m.b8[17] = tctxt.m.b8[18]; 116 | ctxt->m.b8[18] = tctxt.m.b8[17]; 117 | ctxt->m.b8[19] = tctxt.m.b8[16]; 118 | ctxt->m.b8[20] = tctxt.m.b8[23]; 119 | ctxt->m.b8[21] = tctxt.m.b8[22]; 120 | ctxt->m.b8[22] = tctxt.m.b8[21]; 121 | ctxt->m.b8[23] = tctxt.m.b8[20]; 122 | ctxt->m.b8[24] = tctxt.m.b8[27]; 123 | ctxt->m.b8[25] = tctxt.m.b8[26]; 124 | ctxt->m.b8[26] = tctxt.m.b8[25]; 125 | ctxt->m.b8[27] = tctxt.m.b8[24]; 126 | ctxt->m.b8[28] = tctxt.m.b8[31]; 127 | ctxt->m.b8[29] = tctxt.m.b8[30]; 128 | ctxt->m.b8[30] = tctxt.m.b8[29]; 129 | ctxt->m.b8[31] = tctxt.m.b8[28]; 130 | ctxt->m.b8[32] = tctxt.m.b8[35]; 131 | ctxt->m.b8[33] = tctxt.m.b8[34]; 132 | ctxt->m.b8[34] = tctxt.m.b8[33]; 133 | ctxt->m.b8[35] = tctxt.m.b8[32]; 134 | ctxt->m.b8[36] = tctxt.m.b8[39]; 135 | ctxt->m.b8[37] = tctxt.m.b8[38]; 136 | ctxt->m.b8[38] = tctxt.m.b8[37]; 137 | ctxt->m.b8[39] = tctxt.m.b8[36]; 138 | ctxt->m.b8[40] = tctxt.m.b8[43]; 139 | ctxt->m.b8[41] = tctxt.m.b8[42]; 140 | ctxt->m.b8[42] = tctxt.m.b8[41]; 141 | ctxt->m.b8[43] = tctxt.m.b8[40]; 142 | ctxt->m.b8[44] = tctxt.m.b8[47]; 143 | ctxt->m.b8[45] = tctxt.m.b8[46]; 144 | ctxt->m.b8[46] = tctxt.m.b8[45]; 145 | ctxt->m.b8[47] = tctxt.m.b8[44]; 146 | ctxt->m.b8[48] = tctxt.m.b8[51]; 147 | ctxt->m.b8[49] = tctxt.m.b8[50]; 148 | ctxt->m.b8[50] = tctxt.m.b8[49]; 149 | ctxt->m.b8[51] = tctxt.m.b8[48]; 150 | ctxt->m.b8[52] = tctxt.m.b8[55]; 151 | ctxt->m.b8[53] = tctxt.m.b8[54]; 152 | ctxt->m.b8[54] = tctxt.m.b8[53]; 153 | ctxt->m.b8[55] = tctxt.m.b8[52]; 154 | ctxt->m.b8[56] = tctxt.m.b8[59]; 155 | ctxt->m.b8[57] = tctxt.m.b8[58]; 156 | ctxt->m.b8[58] = tctxt.m.b8[57]; 157 | ctxt->m.b8[59] = tctxt.m.b8[56]; 158 | ctxt->m.b8[60] = tctxt.m.b8[63]; 159 | ctxt->m.b8[61] = tctxt.m.b8[62]; 160 | ctxt->m.b8[62] = tctxt.m.b8[61]; 161 | ctxt->m.b8[63] = tctxt.m.b8[60]; 162 | #endif 163 | 164 | a = H(0); 165 | b = H(1); 166 | c = H(2); 167 | d = H(3); 168 | e = H(4); 169 | 170 | for (t = 0; t < 20; t++) 171 | { 172 | s = t & 0x0f; 173 | if (t >= 16) 174 | W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); 175 | tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); 176 | e = d; 177 | d = c; 178 | c = S(30, b); 179 | b = a; 180 | a = tmp; 181 | } 182 | for (t = 20; t < 40; t++) 183 | { 184 | s = t & 0x0f; 185 | W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); 186 | tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); 187 | e = d; 188 | d = c; 189 | c = S(30, b); 190 | b = a; 191 | a = tmp; 192 | } 193 | for (t = 40; t < 60; t++) 194 | { 195 | s = t & 0x0f; 196 | W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); 197 | tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); 198 | e = d; 199 | d = c; 200 | c = S(30, b); 201 | b = a; 202 | a = tmp; 203 | } 204 | for (t = 60; t < 80; t++) 205 | { 206 | s = t & 0x0f; 207 | W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); 208 | tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); 209 | e = d; 210 | d = c; 211 | c = S(30, b); 212 | b = a; 213 | a = tmp; 214 | } 215 | 216 | H(0) = H(0) + a; 217 | H(1) = H(1) + b; 218 | H(2) = H(2) + c; 219 | H(3) = H(3) + d; 220 | H(4) = H(4) + e; 221 | 222 | memset(&ctxt->m.b8[0], 0, 64); 223 | } 224 | 225 | /*------------------------------------------------------------*/ 226 | 227 | void 228 | sha1_init(struct sha1_ctxt * ctxt) 229 | { 230 | memset(ctxt, 0, sizeof(struct sha1_ctxt)); 231 | H(0) = 0x67452301; 232 | H(1) = 0xefcdab89; 233 | H(2) = 0x98badcfe; 234 | H(3) = 0x10325476; 235 | H(4) = 0xc3d2e1f0; 236 | } 237 | 238 | void 239 | sha1_pad(struct sha1_ctxt * ctxt) 240 | { 241 | size_t padlen; /* pad length in bytes */ 242 | size_t padstart; 243 | 244 | PUTPAD(0x80); 245 | 246 | padstart = COUNT % 64; 247 | padlen = 64 - padstart; 248 | if (padlen < 8) 249 | { 250 | memset(&ctxt->m.b8[padstart], 0, padlen); 251 | COUNT += padlen; 252 | COUNT %= 64; 253 | sha1_step(ctxt); 254 | padstart = COUNT % 64; /* should be 0 */ 255 | padlen = 64 - padstart; /* should be 64 */ 256 | } 257 | memset(&ctxt->m.b8[padstart], 0, padlen - 8); 258 | COUNT += (padlen - 8); 259 | COUNT %= 64; 260 | #ifdef WORDS_BIGENDIAN 261 | PUTPAD(ctxt->c.b8[0]); 262 | PUTPAD(ctxt->c.b8[1]); 263 | PUTPAD(ctxt->c.b8[2]); 264 | PUTPAD(ctxt->c.b8[3]); 265 | PUTPAD(ctxt->c.b8[4]); 266 | PUTPAD(ctxt->c.b8[5]); 267 | PUTPAD(ctxt->c.b8[6]); 268 | PUTPAD(ctxt->c.b8[7]); 269 | #else 270 | PUTPAD(ctxt->c.b8[7]); 271 | PUTPAD(ctxt->c.b8[6]); 272 | PUTPAD(ctxt->c.b8[5]); 273 | PUTPAD(ctxt->c.b8[4]); 274 | PUTPAD(ctxt->c.b8[3]); 275 | PUTPAD(ctxt->c.b8[2]); 276 | PUTPAD(ctxt->c.b8[1]); 277 | PUTPAD(ctxt->c.b8[0]); 278 | #endif 279 | } 280 | 281 | void 282 | sha1_loop(struct sha1_ctxt * ctxt, const uint8_t *input0, size_t len) 283 | { 284 | const uint8_t *input; 285 | size_t gaplen; 286 | size_t gapstart; 287 | size_t off; 288 | size_t copysiz; 289 | 290 | input = (const uint8_t *) input0; 291 | off = 0; 292 | 293 | while (off < len) 294 | { 295 | gapstart = COUNT % 64; 296 | gaplen = 64 - gapstart; 297 | 298 | copysiz = (gaplen < len - off) ? gaplen : len - off; 299 | memmove(&ctxt->m.b8[gapstart], &input[off], copysiz); 300 | COUNT += copysiz; 301 | COUNT %= 64; 302 | ctxt->c.b64[0] += copysiz * 8; 303 | if (COUNT % 64 == 0) 304 | sha1_step(ctxt); 305 | off += copysiz; 306 | } 307 | } 308 | 309 | void 310 | sha1_result(struct sha1_ctxt * ctxt, uint8_t *digest0) 311 | { 312 | uint8_t *digest; 313 | 314 | digest = (uint8_t *) digest0; 315 | sha1_pad(ctxt); 316 | #ifdef WORDS_BIGENDIAN 317 | memmove(digest, &ctxt->h.b8[0], 20); 318 | #else 319 | digest[0] = ctxt->h.b8[3]; 320 | digest[1] = ctxt->h.b8[2]; 321 | digest[2] = ctxt->h.b8[1]; 322 | digest[3] = ctxt->h.b8[0]; 323 | digest[4] = ctxt->h.b8[7]; 324 | digest[5] = ctxt->h.b8[6]; 325 | digest[6] = ctxt->h.b8[5]; 326 | digest[7] = ctxt->h.b8[4]; 327 | digest[8] = ctxt->h.b8[11]; 328 | digest[9] = ctxt->h.b8[10]; 329 | digest[10] = ctxt->h.b8[9]; 330 | digest[11] = ctxt->h.b8[8]; 331 | digest[12] = ctxt->h.b8[15]; 332 | digest[13] = ctxt->h.b8[14]; 333 | digest[14] = ctxt->h.b8[13]; 334 | digest[15] = ctxt->h.b8[12]; 335 | digest[16] = ctxt->h.b8[19]; 336 | digest[17] = ctxt->h.b8[18]; 337 | digest[18] = ctxt->h.b8[17]; 338 | digest[19] = ctxt->h.b8[16]; 339 | #endif 340 | } 341 | -------------------------------------------------------------------------------- /src/crypto/sha2.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:36 millert Exp $ */ 2 | 3 | /* 4 | * FILE: sha2.c 5 | * AUTHOR: Aaron D. Gifford 6 | * 7 | * Copyright (c) 2000-2001, Aaron D. Gifford 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ 35 | * 36 | * contrib/pgcrypto/sha2.c 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include "crypto/sha2.h" 43 | 44 | /* 45 | * UNROLLED TRANSFORM LOOP NOTE: 46 | * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform 47 | * loop version for the hash transform rounds (defined using macros 48 | * later in this file). Either define on the command line, for example: 49 | * 50 | * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c 51 | * 52 | * or define below: 53 | * 54 | * #define SHA2_UNROLL_TRANSFORM 55 | * 56 | */ 57 | 58 | /*** SHA-256/384/512 Various Length Definitions ***********************/ 59 | /* NOTE: Most of these are in sha2.h */ 60 | #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) 61 | #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) 62 | #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) 63 | 64 | 65 | /*** ENDIAN REVERSAL MACROS *******************************************/ 66 | #ifndef WORDS_BIGENDIAN 67 | #define REVERSE32(w,x) { \ 68 | uint32_t tmp = (w); \ 69 | tmp = (tmp >> 16) | (tmp << 16); \ 70 | (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ 71 | } 72 | #define REVERSE64(w,x) { \ 73 | uint64_t tmp = (w); \ 74 | tmp = (tmp >> 32) | (tmp << 32); \ 75 | tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ 76 | ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ 77 | (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ 78 | ((tmp & 0x0000ffff0000ffffULL) << 16); \ 79 | } 80 | #endif /* not bigendian */ 81 | 82 | /* 83 | * Macro for incrementally adding the unsigned 64-bit integer n to the 84 | * unsigned 128-bit integer (represented using a two-element array of 85 | * 64-bit words): 86 | */ 87 | #define ADDINC128(w,n) { \ 88 | (w)[0] += (uint64_t)(n); \ 89 | if ((w)[0] < (n)) { \ 90 | (w)[1]++; \ 91 | } \ 92 | } 93 | 94 | /*** THE SIX LOGICAL FUNCTIONS ****************************************/ 95 | /* 96 | * Bit shifting and rotation (used by the six SHA-XYZ logical functions: 97 | * 98 | * NOTE: The naming of R and S appears backwards here (R is a SHIFT and 99 | * S is a ROTATION) because the SHA-256/384/512 description document 100 | * (see http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf) 101 | * uses this same "backwards" definition. 102 | */ 103 | /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ 104 | #define R(b,x) ((x) >> (b)) 105 | /* 32-bit Rotate-right (used in SHA-256): */ 106 | #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) 107 | /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ 108 | #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) 109 | 110 | /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ 111 | #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 112 | #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 113 | 114 | /* Four of six logical functions used in SHA-256: */ 115 | #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) 116 | #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) 117 | #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) 118 | #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) 119 | 120 | /* Four of six logical functions used in SHA-384 and SHA-512: */ 121 | #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) 122 | #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) 123 | #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) 124 | #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) 125 | 126 | /*** INTERNAL FUNCTION PROTOTYPES *************************************/ 127 | /* NOTE: These should not be accessed directly from outside this 128 | * library -- they are intended for private internal visibility/use 129 | * only. 130 | */ 131 | static void SHA512_Last(SHA512_CTX *); 132 | static void SHA256_Transform(SHA256_CTX *, const uint8_t *); 133 | static void SHA512_Transform(SHA512_CTX *, const uint8_t *); 134 | 135 | 136 | /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ 137 | /* Hash constant words K for SHA-256: */ 138 | static const uint32_t K256[64] = { 139 | 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 140 | 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 141 | 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 142 | 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 143 | 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 144 | 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 145 | 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 146 | 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 147 | 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 148 | 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 149 | 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 150 | 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 151 | 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 152 | 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 153 | 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 154 | 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 155 | }; 156 | 157 | /* Initial hash value H for SHA-224: */ 158 | static const uint32_t sha224_initial_hash_value[8] = { 159 | 0xc1059ed8UL, 160 | 0x367cd507UL, 161 | 0x3070dd17UL, 162 | 0xf70e5939UL, 163 | 0xffc00b31UL, 164 | 0x68581511UL, 165 | 0x64f98fa7UL, 166 | 0xbefa4fa4UL 167 | }; 168 | 169 | /* Initial hash value H for SHA-256: */ 170 | static const uint32_t sha256_initial_hash_value[8] = { 171 | 0x6a09e667UL, 172 | 0xbb67ae85UL, 173 | 0x3c6ef372UL, 174 | 0xa54ff53aUL, 175 | 0x510e527fUL, 176 | 0x9b05688cUL, 177 | 0x1f83d9abUL, 178 | 0x5be0cd19UL 179 | }; 180 | 181 | /* Hash constant words K for SHA-384 and SHA-512: */ 182 | static const uint64_t K512[80] = { 183 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 184 | 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 185 | 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 186 | 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 187 | 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 188 | 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 189 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 190 | 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 191 | 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 192 | 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 193 | 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 194 | 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 195 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 196 | 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 197 | 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 198 | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 199 | 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 200 | 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 201 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 202 | 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 203 | 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 204 | 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 205 | 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 206 | 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 207 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 208 | 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 209 | 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 210 | 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 211 | 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 212 | 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 213 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 214 | 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 215 | 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 216 | 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 217 | 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 218 | 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 219 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 220 | 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 221 | 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 222 | 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 223 | }; 224 | 225 | /* Initial hash value H for SHA-384 */ 226 | static const uint64_t sha384_initial_hash_value[8] = { 227 | 0xcbbb9d5dc1059ed8ULL, 228 | 0x629a292a367cd507ULL, 229 | 0x9159015a3070dd17ULL, 230 | 0x152fecd8f70e5939ULL, 231 | 0x67332667ffc00b31ULL, 232 | 0x8eb44a8768581511ULL, 233 | 0xdb0c2e0d64f98fa7ULL, 234 | 0x47b5481dbefa4fa4ULL 235 | }; 236 | 237 | /* Initial hash value H for SHA-512 */ 238 | static const uint64_t sha512_initial_hash_value[8] = { 239 | 0x6a09e667f3bcc908ULL, 240 | 0xbb67ae8584caa73bULL, 241 | 0x3c6ef372fe94f82bULL, 242 | 0xa54ff53a5f1d36f1ULL, 243 | 0x510e527fade682d1ULL, 244 | 0x9b05688c2b3e6c1fULL, 245 | 0x1f83d9abfb41bd6bULL, 246 | 0x5be0cd19137e2179ULL 247 | }; 248 | 249 | 250 | /*** SHA-256: *********************************************************/ 251 | void 252 | SHA256_Init(SHA256_CTX *context) 253 | { 254 | if (context == NULL) 255 | return; 256 | memcpy(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); 257 | memset(context->buffer, 0, SHA256_BLOCK_LENGTH); 258 | context->bitcount = 0; 259 | } 260 | 261 | #ifdef SHA2_UNROLL_TRANSFORM 262 | 263 | /* Unrolled SHA-256 round macros: */ 264 | 265 | #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \ 266 | W256[j] = (uint32_t)data[3] | ((uint32_t)data[2] << 8) | \ 267 | ((uint32_t)data[1] << 16) | ((uint32_t)data[0] << 24); \ 268 | data += 4; \ 269 | T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ 270 | (d) += T1; \ 271 | (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ 272 | j++; \ 273 | } while(0) 274 | 275 | #define ROUND256(a,b,c,d,e,f,g,h) do { \ 276 | s0 = W256[(j+1)&0x0f]; \ 277 | s0 = sigma0_256(s0); \ 278 | s1 = W256[(j+14)&0x0f]; \ 279 | s1 = sigma1_256(s1); \ 280 | T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \ 281 | (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ 282 | (d) += T1; \ 283 | (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ 284 | j++; \ 285 | } while(0) 286 | 287 | static void 288 | SHA256_Transform(SHA256_CTX *context, const uint8_t *data) 289 | { 290 | uint32_t a, 291 | b, 292 | c, 293 | d, 294 | e, 295 | f, 296 | g, 297 | h, 298 | s0, 299 | s1; 300 | uint32_t T1, 301 | *W256; 302 | int j; 303 | 304 | W256 = (uint32_t *) context->buffer; 305 | 306 | /* Initialize registers with the prev. intermediate value */ 307 | a = context->state[0]; 308 | b = context->state[1]; 309 | c = context->state[2]; 310 | d = context->state[3]; 311 | e = context->state[4]; 312 | f = context->state[5]; 313 | g = context->state[6]; 314 | h = context->state[7]; 315 | 316 | j = 0; 317 | do 318 | { 319 | /* Rounds 0 to 15 (unrolled): */ 320 | ROUND256_0_TO_15(a, b, c, d, e, f, g, h); 321 | ROUND256_0_TO_15(h, a, b, c, d, e, f, g); 322 | ROUND256_0_TO_15(g, h, a, b, c, d, e, f); 323 | ROUND256_0_TO_15(f, g, h, a, b, c, d, e); 324 | ROUND256_0_TO_15(e, f, g, h, a, b, c, d); 325 | ROUND256_0_TO_15(d, e, f, g, h, a, b, c); 326 | ROUND256_0_TO_15(c, d, e, f, g, h, a, b); 327 | ROUND256_0_TO_15(b, c, d, e, f, g, h, a); 328 | } while (j < 16); 329 | 330 | /* Now for the remaining rounds to 64: */ 331 | do 332 | { 333 | ROUND256(a, b, c, d, e, f, g, h); 334 | ROUND256(h, a, b, c, d, e, f, g); 335 | ROUND256(g, h, a, b, c, d, e, f); 336 | ROUND256(f, g, h, a, b, c, d, e); 337 | ROUND256(e, f, g, h, a, b, c, d); 338 | ROUND256(d, e, f, g, h, a, b, c); 339 | ROUND256(c, d, e, f, g, h, a, b); 340 | ROUND256(b, c, d, e, f, g, h, a); 341 | } while (j < 64); 342 | 343 | /* Compute the current intermediate hash value */ 344 | context->state[0] += a; 345 | context->state[1] += b; 346 | context->state[2] += c; 347 | context->state[3] += d; 348 | context->state[4] += e; 349 | context->state[5] += f; 350 | context->state[6] += g; 351 | context->state[7] += h; 352 | 353 | /* Clean up */ 354 | a = b = c = d = e = f = g = h = T1 = 0; 355 | } 356 | #else /* SHA2_UNROLL_TRANSFORM */ 357 | 358 | static void 359 | SHA256_Transform(SHA256_CTX *context, const uint8_t *data) 360 | { 361 | uint32_t a, 362 | b, 363 | c, 364 | d, 365 | e, 366 | f, 367 | g, 368 | h, 369 | s0, 370 | s1; 371 | uint32_t T1, 372 | T2, 373 | *W256; 374 | int j; 375 | 376 | W256 = (uint32_t *) context->buffer; 377 | 378 | /* Initialize registers with the prev. intermediate value */ 379 | a = context->state[0]; 380 | b = context->state[1]; 381 | c = context->state[2]; 382 | d = context->state[3]; 383 | e = context->state[4]; 384 | f = context->state[5]; 385 | g = context->state[6]; 386 | h = context->state[7]; 387 | 388 | j = 0; 389 | do 390 | { 391 | W256[j] = (uint32_t) data[3] | ((uint32_t) data[2] << 8) | 392 | ((uint32_t) data[1] << 16) | ((uint32_t) data[0] << 24); 393 | data += 4; 394 | /* Apply the SHA-256 compression function to update a..h */ 395 | T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; 396 | T2 = Sigma0_256(a) + Maj(a, b, c); 397 | h = g; 398 | g = f; 399 | f = e; 400 | e = d + T1; 401 | d = c; 402 | c = b; 403 | b = a; 404 | a = T1 + T2; 405 | 406 | j++; 407 | } while (j < 16); 408 | 409 | do 410 | { 411 | /* Part of the message block expansion: */ 412 | s0 = W256[(j + 1) & 0x0f]; 413 | s0 = sigma0_256(s0); 414 | s1 = W256[(j + 14) & 0x0f]; 415 | s1 = sigma1_256(s1); 416 | 417 | /* Apply the SHA-256 compression function to update a..h */ 418 | T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 419 | (W256[j & 0x0f] += s1 + W256[(j + 9) & 0x0f] + s0); 420 | T2 = Sigma0_256(a) + Maj(a, b, c); 421 | h = g; 422 | g = f; 423 | f = e; 424 | e = d + T1; 425 | d = c; 426 | c = b; 427 | b = a; 428 | a = T1 + T2; 429 | 430 | j++; 431 | } while (j < 64); 432 | 433 | /* Compute the current intermediate hash value */ 434 | context->state[0] += a; 435 | context->state[1] += b; 436 | context->state[2] += c; 437 | context->state[3] += d; 438 | context->state[4] += e; 439 | context->state[5] += f; 440 | context->state[6] += g; 441 | context->state[7] += h; 442 | 443 | /* Clean up */ 444 | a = b = c = d = e = f = g = h = T1 = T2 = 0; 445 | } 446 | #endif /* SHA2_UNROLL_TRANSFORM */ 447 | 448 | void 449 | SHA256_Update(SHA256_CTX *context, const uint8_t *data, size_t len) 450 | { 451 | size_t freespace, 452 | usedspace; 453 | 454 | /* Calling with no data is valid (we do nothing) */ 455 | if (len == 0) 456 | return; 457 | 458 | usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; 459 | if (usedspace > 0) 460 | { 461 | /* Calculate how much free space is available in the buffer */ 462 | freespace = SHA256_BLOCK_LENGTH - usedspace; 463 | 464 | if (len >= freespace) 465 | { 466 | /* Fill the buffer completely and process it */ 467 | memcpy(&context->buffer[usedspace], data, freespace); 468 | context->bitcount += freespace << 3; 469 | len -= freespace; 470 | data += freespace; 471 | SHA256_Transform(context, context->buffer); 472 | } 473 | else 474 | { 475 | /* The buffer is not yet full */ 476 | memcpy(&context->buffer[usedspace], data, len); 477 | context->bitcount += len << 3; 478 | /* Clean up: */ 479 | usedspace = freespace = 0; 480 | return; 481 | } 482 | } 483 | while (len >= SHA256_BLOCK_LENGTH) 484 | { 485 | /* Process as many complete blocks as we can */ 486 | SHA256_Transform(context, data); 487 | context->bitcount += SHA256_BLOCK_LENGTH << 3; 488 | len -= SHA256_BLOCK_LENGTH; 489 | data += SHA256_BLOCK_LENGTH; 490 | } 491 | if (len > 0) 492 | { 493 | /* There's left-overs, so save 'em */ 494 | memcpy(context->buffer, data, len); 495 | context->bitcount += len << 3; 496 | } 497 | /* Clean up: */ 498 | usedspace = freespace = 0; 499 | } 500 | 501 | static void 502 | SHA256_Last(SHA256_CTX *context) 503 | { 504 | unsigned int usedspace; 505 | 506 | usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; 507 | #ifndef WORDS_BIGENDIAN 508 | /* Convert FROM host byte order */ 509 | REVERSE64(context->bitcount, context->bitcount); 510 | #endif 511 | if (usedspace > 0) 512 | { 513 | /* Begin padding with a 1 bit: */ 514 | context->buffer[usedspace++] = 0x80; 515 | 516 | if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) 517 | { 518 | /* Set-up for the last transform: */ 519 | memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); 520 | } 521 | else 522 | { 523 | if (usedspace < SHA256_BLOCK_LENGTH) 524 | { 525 | memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); 526 | } 527 | /* Do second-to-last transform: */ 528 | SHA256_Transform(context, context->buffer); 529 | 530 | /* And set-up for the last transform: */ 531 | memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); 532 | } 533 | } 534 | else 535 | { 536 | /* Set-up for the last transform: */ 537 | memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); 538 | 539 | /* Begin padding with a 1 bit: */ 540 | *context->buffer = 0x80; 541 | } 542 | /* Set the bit count: */ 543 | *(uint64_t *) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; 544 | 545 | /* Final transform: */ 546 | SHA256_Transform(context, context->buffer); 547 | } 548 | 549 | void 550 | SHA256_Final(uint8_t digest[], SHA256_CTX *context) 551 | { 552 | /* If no digest buffer is passed, we don't bother doing this: */ 553 | if (digest != NULL) 554 | { 555 | SHA256_Last(context); 556 | 557 | #ifndef WORDS_BIGENDIAN 558 | { 559 | /* Convert TO host byte order */ 560 | int j; 561 | 562 | for (j = 0; j < 8; j++) 563 | { 564 | REVERSE32(context->state[j], context->state[j]); 565 | } 566 | } 567 | #endif 568 | memcpy(digest, context->state, SHA256_DIGEST_LENGTH); 569 | } 570 | 571 | /* Clean up state data: */ 572 | memset(context, 0, sizeof(*context)); 573 | } 574 | 575 | 576 | /*** SHA-512: *********************************************************/ 577 | void 578 | SHA512_Init(SHA512_CTX *context) 579 | { 580 | if (context == NULL) 581 | return; 582 | memcpy(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); 583 | memset(context->buffer, 0, SHA512_BLOCK_LENGTH); 584 | context->bitcount[0] = context->bitcount[1] = 0; 585 | } 586 | 587 | #ifdef SHA2_UNROLL_TRANSFORM 588 | 589 | /* Unrolled SHA-512 round macros: */ 590 | 591 | #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \ 592 | W512[j] = (uint64_t)data[7] | ((uint64_t)data[6] << 8) | \ 593 | ((uint64_t)data[5] << 16) | ((uint64_t)data[4] << 24) | \ 594 | ((uint64_t)data[3] << 32) | ((uint64_t)data[2] << 40) | \ 595 | ((uint64_t)data[1] << 48) | ((uint64_t)data[0] << 56); \ 596 | data += 8; \ 597 | T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ 598 | (d) += T1; \ 599 | (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ 600 | j++; \ 601 | } while(0) 602 | 603 | 604 | #define ROUND512(a,b,c,d,e,f,g,h) do { \ 605 | s0 = W512[(j+1)&0x0f]; \ 606 | s0 = sigma0_512(s0); \ 607 | s1 = W512[(j+14)&0x0f]; \ 608 | s1 = sigma1_512(s1); \ 609 | T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \ 610 | (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ 611 | (d) += T1; \ 612 | (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ 613 | j++; \ 614 | } while(0) 615 | 616 | static void 617 | SHA512_Transform(SHA512_CTX *context, const uint8_t *data) 618 | { 619 | uint64_t a, 620 | b, 621 | c, 622 | d, 623 | e, 624 | f, 625 | g, 626 | h, 627 | s0, 628 | s1; 629 | uint64_t T1, 630 | *W512 = (uint64_t *) context->buffer; 631 | int j; 632 | 633 | /* Initialize registers with the prev. intermediate value */ 634 | a = context->state[0]; 635 | b = context->state[1]; 636 | c = context->state[2]; 637 | d = context->state[3]; 638 | e = context->state[4]; 639 | f = context->state[5]; 640 | g = context->state[6]; 641 | h = context->state[7]; 642 | 643 | j = 0; 644 | do 645 | { 646 | ROUND512_0_TO_15(a, b, c, d, e, f, g, h); 647 | ROUND512_0_TO_15(h, a, b, c, d, e, f, g); 648 | ROUND512_0_TO_15(g, h, a, b, c, d, e, f); 649 | ROUND512_0_TO_15(f, g, h, a, b, c, d, e); 650 | ROUND512_0_TO_15(e, f, g, h, a, b, c, d); 651 | ROUND512_0_TO_15(d, e, f, g, h, a, b, c); 652 | ROUND512_0_TO_15(c, d, e, f, g, h, a, b); 653 | ROUND512_0_TO_15(b, c, d, e, f, g, h, a); 654 | } while (j < 16); 655 | 656 | /* Now for the remaining rounds up to 79: */ 657 | do 658 | { 659 | ROUND512(a, b, c, d, e, f, g, h); 660 | ROUND512(h, a, b, c, d, e, f, g); 661 | ROUND512(g, h, a, b, c, d, e, f); 662 | ROUND512(f, g, h, a, b, c, d, e); 663 | ROUND512(e, f, g, h, a, b, c, d); 664 | ROUND512(d, e, f, g, h, a, b, c); 665 | ROUND512(c, d, e, f, g, h, a, b); 666 | ROUND512(b, c, d, e, f, g, h, a); 667 | } while (j < 80); 668 | 669 | /* Compute the current intermediate hash value */ 670 | context->state[0] += a; 671 | context->state[1] += b; 672 | context->state[2] += c; 673 | context->state[3] += d; 674 | context->state[4] += e; 675 | context->state[5] += f; 676 | context->state[6] += g; 677 | context->state[7] += h; 678 | 679 | /* Clean up */ 680 | a = b = c = d = e = f = g = h = T1 = 0; 681 | } 682 | #else /* SHA2_UNROLL_TRANSFORM */ 683 | 684 | static void 685 | SHA512_Transform(SHA512_CTX *context, const uint8_t *data) 686 | { 687 | uint64_t a, 688 | b, 689 | c, 690 | d, 691 | e, 692 | f, 693 | g, 694 | h, 695 | s0, 696 | s1; 697 | uint64_t T1, 698 | T2, 699 | *W512 = (uint64_t *) context->buffer; 700 | int j; 701 | 702 | /* Initialize registers with the prev. intermediate value */ 703 | a = context->state[0]; 704 | b = context->state[1]; 705 | c = context->state[2]; 706 | d = context->state[3]; 707 | e = context->state[4]; 708 | f = context->state[5]; 709 | g = context->state[6]; 710 | h = context->state[7]; 711 | 712 | j = 0; 713 | do 714 | { 715 | W512[j] = (uint64_t) data[7] | ((uint64_t) data[6] << 8) | 716 | ((uint64_t) data[5] << 16) | ((uint64_t) data[4] << 24) | 717 | ((uint64_t) data[3] << 32) | ((uint64_t) data[2] << 40) | 718 | ((uint64_t) data[1] << 48) | ((uint64_t) data[0] << 56); 719 | data += 8; 720 | /* Apply the SHA-512 compression function to update a..h */ 721 | T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; 722 | T2 = Sigma0_512(a) + Maj(a, b, c); 723 | h = g; 724 | g = f; 725 | f = e; 726 | e = d + T1; 727 | d = c; 728 | c = b; 729 | b = a; 730 | a = T1 + T2; 731 | 732 | j++; 733 | } while (j < 16); 734 | 735 | do 736 | { 737 | /* Part of the message block expansion: */ 738 | s0 = W512[(j + 1) & 0x0f]; 739 | s0 = sigma0_512(s0); 740 | s1 = W512[(j + 14) & 0x0f]; 741 | s1 = sigma1_512(s1); 742 | 743 | /* Apply the SHA-512 compression function to update a..h */ 744 | T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + 745 | (W512[j & 0x0f] += s1 + W512[(j + 9) & 0x0f] + s0); 746 | T2 = Sigma0_512(a) + Maj(a, b, c); 747 | h = g; 748 | g = f; 749 | f = e; 750 | e = d + T1; 751 | d = c; 752 | c = b; 753 | b = a; 754 | a = T1 + T2; 755 | 756 | j++; 757 | } while (j < 80); 758 | 759 | /* Compute the current intermediate hash value */ 760 | context->state[0] += a; 761 | context->state[1] += b; 762 | context->state[2] += c; 763 | context->state[3] += d; 764 | context->state[4] += e; 765 | context->state[5] += f; 766 | context->state[6] += g; 767 | context->state[7] += h; 768 | 769 | /* Clean up */ 770 | a = b = c = d = e = f = g = h = T1 = T2 = 0; 771 | } 772 | #endif /* SHA2_UNROLL_TRANSFORM */ 773 | 774 | void 775 | SHA512_Update(SHA512_CTX *context, const uint8_t *data, size_t len) 776 | { 777 | size_t freespace, 778 | usedspace; 779 | 780 | /* Calling with no data is valid (we do nothing) */ 781 | if (len == 0) 782 | return; 783 | 784 | usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; 785 | if (usedspace > 0) 786 | { 787 | /* Calculate how much free space is available in the buffer */ 788 | freespace = SHA512_BLOCK_LENGTH - usedspace; 789 | 790 | if (len >= freespace) 791 | { 792 | /* Fill the buffer completely and process it */ 793 | memcpy(&context->buffer[usedspace], data, freespace); 794 | ADDINC128(context->bitcount, freespace << 3); 795 | len -= freespace; 796 | data += freespace; 797 | SHA512_Transform(context, context->buffer); 798 | } 799 | else 800 | { 801 | /* The buffer is not yet full */ 802 | memcpy(&context->buffer[usedspace], data, len); 803 | ADDINC128(context->bitcount, len << 3); 804 | /* Clean up: */ 805 | usedspace = freespace = 0; 806 | return; 807 | } 808 | } 809 | while (len >= SHA512_BLOCK_LENGTH) 810 | { 811 | /* Process as many complete blocks as we can */ 812 | SHA512_Transform(context, data); 813 | ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); 814 | len -= SHA512_BLOCK_LENGTH; 815 | data += SHA512_BLOCK_LENGTH; 816 | } 817 | if (len > 0) 818 | { 819 | /* There's left-overs, so save 'em */ 820 | memcpy(context->buffer, data, len); 821 | ADDINC128(context->bitcount, len << 3); 822 | } 823 | /* Clean up: */ 824 | usedspace = freespace = 0; 825 | } 826 | 827 | static void 828 | SHA512_Last(SHA512_CTX *context) 829 | { 830 | unsigned int usedspace; 831 | 832 | usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; 833 | #ifndef WORDS_BIGENDIAN 834 | /* Convert FROM host byte order */ 835 | REVERSE64(context->bitcount[0], context->bitcount[0]); 836 | REVERSE64(context->bitcount[1], context->bitcount[1]); 837 | #endif 838 | if (usedspace > 0) 839 | { 840 | /* Begin padding with a 1 bit: */ 841 | context->buffer[usedspace++] = 0x80; 842 | 843 | if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) 844 | { 845 | /* Set-up for the last transform: */ 846 | memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace); 847 | } 848 | else 849 | { 850 | if (usedspace < SHA512_BLOCK_LENGTH) 851 | { 852 | memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace); 853 | } 854 | /* Do second-to-last transform: */ 855 | SHA512_Transform(context, context->buffer); 856 | 857 | /* And set-up for the last transform: */ 858 | memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2); 859 | } 860 | } 861 | else 862 | { 863 | /* Prepare for final transform: */ 864 | memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH); 865 | 866 | /* Begin padding with a 1 bit: */ 867 | *context->buffer = 0x80; 868 | } 869 | /* Store the length of input data (in bits): */ 870 | *(uint64_t *) &context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; 871 | *(uint64_t *) &context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8] = context->bitcount[0]; 872 | 873 | /* Final transform: */ 874 | SHA512_Transform(context, context->buffer); 875 | } 876 | 877 | void 878 | SHA512_Final(uint8_t digest[], SHA512_CTX *context) 879 | { 880 | /* If no digest buffer is passed, we don't bother doing this: */ 881 | if (digest != NULL) 882 | { 883 | SHA512_Last(context); 884 | 885 | /* Save the hash data for output: */ 886 | #ifndef WORDS_BIGENDIAN 887 | { 888 | /* Convert TO host byte order */ 889 | int j; 890 | 891 | for (j = 0; j < 8; j++) 892 | { 893 | REVERSE64(context->state[j], context->state[j]); 894 | } 895 | } 896 | #endif 897 | memcpy(digest, context->state, SHA512_DIGEST_LENGTH); 898 | } 899 | 900 | /* Zero out state data */ 901 | memset(context, 0, sizeof(*context)); 902 | } 903 | 904 | 905 | /*** SHA-384: *********************************************************/ 906 | void 907 | SHA384_Init(SHA384_CTX *context) 908 | { 909 | if (context == NULL) 910 | return; 911 | memcpy(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); 912 | memset(context->buffer, 0, SHA384_BLOCK_LENGTH); 913 | context->bitcount[0] = context->bitcount[1] = 0; 914 | } 915 | 916 | void 917 | SHA384_Update(SHA384_CTX *context, const uint8_t *data, size_t len) 918 | { 919 | SHA512_Update((SHA512_CTX *) context, data, len); 920 | } 921 | 922 | void 923 | SHA384_Final(uint8_t digest[], SHA384_CTX *context) 924 | { 925 | /* If no digest buffer is passed, we don't bother doing this: */ 926 | if (digest != NULL) 927 | { 928 | SHA512_Last((SHA512_CTX *) context); 929 | 930 | /* Save the hash data for output: */ 931 | #ifndef WORDS_BIGENDIAN 932 | { 933 | /* Convert TO host byte order */ 934 | int j; 935 | 936 | for (j = 0; j < 6; j++) 937 | { 938 | REVERSE64(context->state[j], context->state[j]); 939 | } 940 | } 941 | #endif 942 | memcpy(digest, context->state, SHA384_DIGEST_LENGTH); 943 | } 944 | 945 | /* Zero out state data */ 946 | memset(context, 0, sizeof(*context)); 947 | } 948 | 949 | /*** SHA-224: *********************************************************/ 950 | void 951 | SHA224_Init(SHA224_CTX *context) 952 | { 953 | if (context == NULL) 954 | return; 955 | memcpy(context->state, sha224_initial_hash_value, SHA256_DIGEST_LENGTH); 956 | memset(context->buffer, 0, SHA256_BLOCK_LENGTH); 957 | context->bitcount = 0; 958 | } 959 | 960 | void 961 | SHA224_Update(SHA224_CTX *context, const uint8_t *data, size_t len) 962 | { 963 | SHA256_Update((SHA256_CTX *) context, data, len); 964 | } 965 | 966 | void 967 | SHA224_Final(uint8_t digest[], SHA224_CTX *context) 968 | { 969 | /* If no digest buffer is passed, we don't bother doing this: */ 970 | if (digest != NULL) 971 | { 972 | SHA256_Last(context); 973 | 974 | #ifndef WORDS_BIGENDIAN 975 | { 976 | /* Convert TO host byte order */ 977 | int j; 978 | 979 | for (j = 0; j < 8; j++) 980 | { 981 | REVERSE32(context->state[j], context->state[j]); 982 | } 983 | } 984 | #endif 985 | memcpy(digest, context->state, SHA224_DIGEST_LENGTH); 986 | } 987 | 988 | /* Clean up state data: */ 989 | memset(context, 0, sizeof(*context)); 990 | } 991 | -------------------------------------------------------------------------------- /src/struct/htable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * htable.c 3 | * (c) Alexandr A Alexeev 2011-2016 | http://eax.me/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "struct/htable.h" 12 | 13 | #define MIN_HTABLE_SIZE (1 << 3) 14 | 15 | static void 16 | _htable_resize(HTable* tbl) 17 | { 18 | HTableNode **new_items; 19 | HTableNode *curr_item, *prev_item, *temp_item; 20 | size_t item_idx, new_size = tbl->size; 21 | uint32_t new_mask; 22 | 23 | if(tbl->nitems < MIN_HTABLE_SIZE) 24 | return; 25 | 26 | if(tbl->nitems > tbl->size) 27 | { 28 | new_size = tbl->size * 2; 29 | new_mask = new_size - 1; 30 | new_items = tbl->allocfunc(sizeof(HTableNode*) * new_size, tbl->arg); 31 | if(new_items == NULL) 32 | return; 33 | 34 | /* just copy first part of the `items` table */ 35 | memcpy(new_items, tbl->items, tbl->size * sizeof(HTableNode*)); 36 | /* second part fill with zeros for now */ 37 | memset(&new_items[tbl->size], 0, tbl->size * sizeof(HTableNode*)); 38 | 39 | for(item_idx = 0; item_idx < tbl->size; item_idx++) 40 | { 41 | prev_item = NULL; 42 | curr_item = new_items[item_idx]; 43 | while(curr_item != NULL) 44 | { 45 | if((curr_item->hash & tbl->mask) != (curr_item->hash & new_mask)) 46 | { 47 | if(prev_item == NULL) 48 | new_items[item_idx] = curr_item->next; 49 | else 50 | prev_item->next = curr_item->next; 51 | 52 | temp_item = curr_item->next; 53 | curr_item->next = new_items[curr_item->hash & new_mask]; 54 | new_items[curr_item->hash & new_mask] = curr_item; 55 | curr_item = temp_item; 56 | } 57 | else 58 | { 59 | prev_item = curr_item; 60 | curr_item = curr_item->next; 61 | } 62 | } /* while */ 63 | } /* for */ 64 | } 65 | else if(tbl->nitems <= (tbl->size / 2)) 66 | { 67 | new_size = tbl->size / 2; 68 | new_mask = new_size - 1; 69 | new_items = tbl->allocfunc(sizeof(HTableNode*) * new_size, tbl->arg); 70 | if(new_items == NULL) 71 | return; 72 | 73 | memcpy(new_items, tbl->items, new_size * sizeof(HTableNode*)); 74 | for(item_idx = new_size; item_idx < tbl->size; item_idx++) 75 | { 76 | if(tbl->items[item_idx] == NULL) 77 | continue; 78 | 79 | if(new_items[item_idx - new_size] == NULL) 80 | new_items[item_idx - new_size] = tbl->items[item_idx]; 81 | else 82 | { 83 | curr_item = new_items[item_idx - new_size]; 84 | while(curr_item->next != NULL) 85 | curr_item = curr_item->next; 86 | curr_item->next = tbl->items[item_idx]; 87 | } 88 | } 89 | } 90 | 91 | if(new_size != tbl->size) 92 | { 93 | tbl->freefunc(tbl->items, tbl->arg); 94 | tbl->items = new_items; 95 | tbl->size = new_size; 96 | tbl->mask = new_mask; 97 | } 98 | } 99 | 100 | /* http://en.wikipedia.org/wiki/Jenkins_hash_function */ 101 | uint32_t 102 | htable_default_hash(const char *key, const size_t key_len) 103 | { 104 | uint32_t hash, i; 105 | 106 | for(hash = i = 0; i < key_len; i++) 107 | { 108 | hash += key[i]; 109 | hash += (hash << 10); 110 | hash ^= (hash >> 6); 111 | } 112 | 113 | hash += (hash << 3); 114 | hash ^= (hash >> 11); 115 | hash += (hash << 15); 116 | return hash; 117 | } 118 | 119 | void 120 | htable_create( 121 | HTable* tbl, 122 | size_t node_size, 123 | htable_hash_func hfunc, 124 | htable_keyeq_func eqfunc, 125 | htable_alloc_func allocfunc, 126 | htable_free_func freefunc, 127 | htable_before_node_free_func bnffunc, 128 | void* arg) 129 | { 130 | tbl->nitems = 0; 131 | tbl->size = MIN_HTABLE_SIZE; 132 | tbl->mask = tbl->size - 1; 133 | tbl->node_size = node_size; 134 | tbl->hfunc = hfunc; 135 | tbl->eqfunc = eqfunc; 136 | tbl->allocfunc = allocfunc; 137 | tbl->freefunc = freefunc; 138 | tbl->bnffunc = bnffunc; 139 | tbl->arg = arg; 140 | 141 | tbl->items = (HTableNode**)tbl->allocfunc(sizeof(HTableNode*) * tbl->size, tbl->arg); 142 | if(tbl->items == NULL) 143 | return; 144 | memset(tbl->items, 0, sizeof(void*) * tbl->size); 145 | } 146 | 147 | void 148 | htable_free_items(HTable* tbl) 149 | { 150 | size_t item_idx; 151 | HTableNode *curr_item, *next_item; 152 | 153 | for(item_idx = 0; item_idx < tbl->size; item_idx++) 154 | { 155 | curr_item = tbl->items[item_idx]; 156 | while(curr_item) 157 | { 158 | next_item = curr_item->next; 159 | if(tbl->bnffunc) 160 | tbl->bnffunc(curr_item, tbl->arg); 161 | tbl->freefunc(curr_item, tbl->arg); 162 | curr_item = next_item; 163 | } 164 | } 165 | 166 | tbl->freefunc(tbl->items, tbl->arg); 167 | } 168 | 169 | HTableNode* 170 | htable_find(HTable* tbl, HTableNode* query) 171 | { 172 | uint32_t hash = tbl->hfunc(query, tbl->arg); 173 | HTableNode* curr_item = tbl->items[hash & tbl->mask]; 174 | 175 | while(curr_item) 176 | { 177 | if(tbl->eqfunc(curr_item, query, tbl->arg)) 178 | return curr_item; 179 | curr_item = curr_item->next; 180 | } 181 | 182 | return NULL; 183 | } 184 | 185 | void 186 | htable_insert(HTable* tbl, HTableNode* node, bool* isNewNode) 187 | { 188 | uint32_t hash = tbl->hfunc(node, tbl->arg); 189 | HTableNode* item = tbl->items[hash & tbl->mask]; 190 | 191 | /* if such a key is already used, update node */ 192 | while(item) 193 | { 194 | if(tbl->eqfunc(item, node, tbl->arg)) 195 | { 196 | HTableNode* savedNext = item->next; 197 | if(tbl->bnffunc) 198 | tbl->bnffunc(item, tbl->arg); 199 | memcpy(item, node, tbl->node_size); 200 | item->next = savedNext; 201 | item->hash = hash; 202 | *isNewNode = false; 203 | return; 204 | } 205 | item = item->next; 206 | } 207 | 208 | /* key is not used yet, add new node */ 209 | item = tbl->allocfunc(tbl->node_size, tbl->arg); 210 | if(item == NULL) 211 | return; 212 | 213 | memcpy(item, node, tbl->node_size); 214 | 215 | item->hash = hash; 216 | item->next = tbl->items[hash & tbl->mask]; 217 | tbl->items[hash & tbl->mask] = item; 218 | tbl->nitems++; 219 | 220 | _htable_resize(tbl); 221 | *isNewNode = true; 222 | } 223 | 224 | bool 225 | htable_delete(HTable* tbl, HTableNode* query) 226 | { 227 | uint32_t hash = tbl->hfunc(query, tbl->arg); 228 | HTableNode* item = tbl->items[hash & tbl->mask]; 229 | HTableNode* prev = NULL; 230 | 231 | while(item) 232 | { 233 | if(tbl->eqfunc(item, query, tbl->arg)) 234 | { 235 | if(prev) 236 | prev->next = item->next; 237 | else 238 | tbl->items[hash & tbl->mask] = item->next; 239 | 240 | if(tbl->bnffunc) 241 | tbl->bnffunc(item, tbl->arg); 242 | tbl->freefunc(item, tbl->arg); 243 | tbl->nitems--; 244 | _htable_resize(tbl); 245 | return true; 246 | } 247 | prev = item; 248 | item = item->next; 249 | } 250 | 251 | return false; 252 | } 253 | 254 | -------------------------------------------------------------------------------- /src/struct/ilist.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | * 3 | * ilist.c 4 | * support for integrated/inline doubly- and singly- linked lists 5 | * 6 | * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group 7 | * Portions Copyright (c) 1994, Regents of the University of California 8 | * 9 | * 10 | * IDENTIFICATION 11 | * src/backend/lib/ilist.c 12 | * 13 | * NOTES 14 | * This file only contains functions that are too big to be considered 15 | * for inlining. See ilist.h for most of the goodies. 16 | * 17 | *------------------------------------------------------------------------- 18 | */ 19 | 20 | #include "struct/ilist.h" 21 | 22 | /* 23 | * Delete 'node' from list. 24 | * 25 | * It is not allowed to delete a 'node' which is not in the list 'head' 26 | * 27 | * Caution: this is O(n); consider using slist_delete_current() instead. 28 | */ 29 | void 30 | slist_delete(slist_head *head, slist_node *node) 31 | { 32 | slist_node *last = &head->head; 33 | slist_node *cur; 34 | bool found = false; 35 | 36 | while ((cur = last->next) != NULL) 37 | { 38 | if (cur == node) 39 | { 40 | last->next = cur->next; 41 | found = true; 42 | break; 43 | } 44 | last = cur; 45 | } 46 | assert(found); 47 | 48 | slist_check(head); 49 | } 50 | 51 | #ifdef ILIST_DEBUG 52 | /* 53 | * Verify integrity of a doubly linked list 54 | */ 55 | void 56 | dlist_check(dlist_head *head) 57 | { 58 | dlist_node *cur; 59 | 60 | if (head == NULL) 61 | { 62 | fprintf(stderr, "doubly linked list head address is NULL\n"); 63 | exit(1); 64 | } 65 | 66 | if (head->head.next == NULL && head->head.prev == NULL) 67 | return; /* OK, initialized as zeroes */ 68 | 69 | /* iterate in forward direction */ 70 | for (cur = head->head.next; cur != &head->head; cur = cur->next) 71 | { 72 | if (cur == NULL || 73 | cur->next == NULL || 74 | cur->prev == NULL || 75 | cur->prev->next != cur || 76 | cur->next->prev != cur) 77 | { 78 | fprintf(stderr, "doubly linked list is corrupted\n"); 79 | exit(1); 80 | } 81 | } 82 | 83 | /* iterate in backward direction */ 84 | for (cur = head->head.prev; cur != &head->head; cur = cur->prev) 85 | { 86 | if (cur == NULL || 87 | cur->next == NULL || 88 | cur->prev == NULL || 89 | cur->prev->next != cur || 90 | cur->next->prev != cur) 91 | { 92 | fprintf(stderr, "doubly linked list is corrupted\n"); 93 | exit(1); 94 | } 95 | } 96 | } 97 | 98 | /* 99 | * Verify integrity of a singly linked list 100 | */ 101 | void 102 | slist_check(slist_head *head) 103 | { 104 | slist_node *cur; 105 | 106 | if (head == NULL) 107 | { 108 | fprintf(stderr, "singly linked list head address is NULL\n"); 109 | exit(1); 110 | } 111 | 112 | /* 113 | * there isn't much we can test in a singly linked list except that it 114 | * actually ends sometime, i.e. hasn't introduced a cycle or similar 115 | */ 116 | for (cur = head->head.next; cur != NULL; cur = cur->next) 117 | ; 118 | } 119 | 120 | #endif /* ILIST_DEBUG */ 121 | -------------------------------------------------------------------------------- /src/struct/rbtree.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | * 3 | * rbtree.c 4 | * implementation for PostgreSQL generic Red-Black binary tree package 5 | * Adopted from http://algolist.manual.ru/ds/rbtree.php 6 | * 7 | * This code comes from Thomas Niemann's "Sorting and Searching Algorithms: 8 | * a Cookbook". 9 | * 10 | * See http://www.cs.auckland.ac.nz/software/AlgAnim/niemann/s_man.htm for 11 | * license terms: "Source code, when part of a software project, may be used 12 | * freely without reference to the author." 13 | * 14 | * Red-black trees are a type of balanced binary tree wherein (1) any child of 15 | * a red node is always black, and (2) every path from root to leaf traverses 16 | * an equal number of black nodes. From these properties, it follows that the 17 | * longest path from root to leaf is only about twice as long as the shortest, 18 | * so lookups are guaranteed to run in O(lg n) time. 19 | * 20 | * Copyright (c) 2009-2016, PostgreSQL Global Development Group 21 | * 22 | * IDENTIFICATION 23 | * src/backend/lib/rbtree.c 24 | * 25 | *------------------------------------------------------------------------- 26 | */ 27 | 28 | #include "struct/rbtree.h" 29 | #include 30 | 31 | /* 32 | * Colors of nodes (values of RBNode.color) 33 | */ 34 | #define RBBLACK (0) 35 | #define RBRED (1) 36 | 37 | /* 38 | * all leafs are sentinels, use customized NIL name to prevent 39 | * collision with system-wide constant NIL which is actually NULL 40 | */ 41 | #define RBNIL (&sentinel) 42 | 43 | static RBNode sentinel = {RBBLACK, RBNIL, RBNIL, NULL}; 44 | 45 | 46 | /* 47 | * rb_create: create an empty RBTree 48 | * 49 | * Arguments are: 50 | * tree: buffer for storing RBTree structure 51 | * node_size: actual size of tree nodes (> sizeof(RBNode)) 52 | * The manipulation functions: 53 | * comparator: compare two RBNodes for less/equal/greater 54 | * combiner: merge an existing tree entry with a new one 55 | * allocfunc: allocate a new RBNode 56 | * freefunc: free an old RBNode 57 | * arg: passthrough pointer that will be passed to the manipulation functions 58 | * 59 | * Note that the combiner's righthand argument will be a "proposed" tree node, 60 | * ie the input to rb_insert, in which the RBNode fields themselves aren't 61 | * valid. Similarly, either input to the comparator may be a "proposed" node. 62 | * This shouldn't matter since the functions aren't supposed to look at the 63 | * RBNode fields, only the extra fields of the struct the RBNode is embedded 64 | * in. 65 | * 66 | * The freefunc should just be pfree or equivalent; it should NOT attempt 67 | * to free any subsidiary data, because the node passed to it may not contain 68 | * valid data! freefunc can be NULL if caller doesn't require retail 69 | * space reclamation. 70 | * 71 | * Since tree contents are managed by the caller, there is currently not 72 | * an explicit "destroy" operation; typically a tree would be freed by 73 | * resetting or deleting the memory context it's stored in. You can pfree 74 | * the RBTree node if you feel the urge. 75 | */ 76 | void 77 | rb_create(RBTree *tree, 78 | size_t node_size, 79 | rb_comparator comparator, 80 | rb_combiner combiner, 81 | rb_allocfunc allocfunc, 82 | rb_freefunc freefunc, 83 | void *arg) 84 | { 85 | assert(node_size > sizeof(RBNode)); 86 | 87 | tree->root = RBNIL; 88 | tree->node_size = node_size; 89 | tree->comparator = comparator; 90 | tree->combiner = combiner; 91 | tree->allocfunc = allocfunc; 92 | tree->freefunc = freefunc; 93 | 94 | tree->arg = arg; 95 | } 96 | 97 | /* Copy the additional data fields from one RBNode to another */ 98 | static inline void 99 | rb_copy_data(RBTree *rb, RBNode *dest, const RBNode *src) 100 | { 101 | memcpy(dest + 1, src + 1, rb->node_size - sizeof(RBNode)); 102 | } 103 | 104 | /********************************************************************** 105 | * Search * 106 | **********************************************************************/ 107 | 108 | /* 109 | * rb_find: search for a value in an RBTree 110 | * 111 | * data represents the value to try to find. Its RBNode fields need not 112 | * be valid, it's the extra data in the larger struct that is of interest. 113 | * 114 | * Returns the matching tree entry, or NULL if no match is found. 115 | */ 116 | RBNode * 117 | rb_find(RBTree *rb, const RBNode *data) 118 | { 119 | RBNode *node = rb->root; 120 | 121 | while (node != RBNIL) 122 | { 123 | int cmp = rb->comparator(data, node, rb->arg); 124 | 125 | if (cmp == 0) 126 | return node; 127 | else if (cmp < 0) 128 | node = node->left; 129 | else 130 | node = node->right; 131 | } 132 | 133 | return NULL; 134 | } 135 | 136 | /* 137 | * rb_leftmost: fetch the leftmost (smallest-valued) tree node. 138 | * Returns NULL if tree is empty. 139 | * 140 | * Note: in the original implementation this included an unlink step, but 141 | * that's a bit awkward. Just call rb_delete on the result if that's what 142 | * you want. 143 | */ 144 | RBNode * 145 | rb_leftmost(RBTree *rb) 146 | { 147 | RBNode *node = rb->root; 148 | RBNode *leftmost = rb->root; 149 | 150 | while (node != RBNIL) 151 | { 152 | leftmost = node; 153 | node = node->left; 154 | } 155 | 156 | if (leftmost != RBNIL) 157 | return leftmost; 158 | 159 | return NULL; 160 | } 161 | 162 | /* 163 | * rb_rightmost: fetch the rightmost (highest-valued) tree node. 164 | * Returns NULL if tree is empty. 165 | */ 166 | RBNode * 167 | rb_rightmost(RBTree *rb) 168 | { 169 | RBNode *node = rb->root; 170 | RBNode *rightmost = rb->root; 171 | 172 | while (node != RBNIL) 173 | { 174 | rightmost = node; 175 | node = node->right; 176 | } 177 | 178 | if (rightmost != RBNIL) 179 | return rightmost; 180 | 181 | return NULL; 182 | } 183 | 184 | /********************************************************************** 185 | * Insertion * 186 | **********************************************************************/ 187 | 188 | /* 189 | * Rotate node x to left. 190 | * 191 | * x's right child takes its place in the tree, and x becomes the left 192 | * child of that node. 193 | */ 194 | static void 195 | rb_rotate_left(RBTree *rb, RBNode *x) 196 | { 197 | RBNode *y = x->right; 198 | 199 | /* establish x->right link */ 200 | x->right = y->left; 201 | if (y->left != RBNIL) 202 | y->left->parent = x; 203 | 204 | /* establish y->parent link */ 205 | if (y != RBNIL) 206 | y->parent = x->parent; 207 | if (x->parent) 208 | { 209 | if (x == x->parent->left) 210 | x->parent->left = y; 211 | else 212 | x->parent->right = y; 213 | } 214 | else 215 | { 216 | rb->root = y; 217 | } 218 | 219 | /* link x and y */ 220 | y->left = x; 221 | if (x != RBNIL) 222 | x->parent = y; 223 | } 224 | 225 | /* 226 | * Rotate node x to right. 227 | * 228 | * x's left right child takes its place in the tree, and x becomes the right 229 | * child of that node. 230 | */ 231 | static void 232 | rb_rotate_right(RBTree *rb, RBNode *x) 233 | { 234 | RBNode *y = x->left; 235 | 236 | /* establish x->left link */ 237 | x->left = y->right; 238 | if (y->right != RBNIL) 239 | y->right->parent = x; 240 | 241 | /* establish y->parent link */ 242 | if (y != RBNIL) 243 | y->parent = x->parent; 244 | if (x->parent) 245 | { 246 | if (x == x->parent->right) 247 | x->parent->right = y; 248 | else 249 | x->parent->left = y; 250 | } 251 | else 252 | { 253 | rb->root = y; 254 | } 255 | 256 | /* link x and y */ 257 | y->right = x; 258 | if (x != RBNIL) 259 | x->parent = y; 260 | } 261 | 262 | /* 263 | * Maintain Red-Black tree balance after inserting node x. 264 | * 265 | * The newly inserted node is always initially marked red. That may lead to 266 | * a situation where a red node has a red child, which is prohibited. We can 267 | * always fix the problem by a series of color changes and/or "rotations", 268 | * which move the problem progressively higher up in the tree. If one of the 269 | * two red nodes is the root, we can always fix the problem by changing the 270 | * root from red to black. 271 | * 272 | * (This does not work lower down in the tree because we must also maintain 273 | * the invariant that every leaf has equal black-height.) 274 | */ 275 | static void 276 | rb_insert_fixup(RBTree *rb, RBNode *x) 277 | { 278 | /* 279 | * x is always a red node. Initially, it is the newly inserted node. Each 280 | * iteration of this loop moves it higher up in the tree. 281 | */ 282 | while (x != rb->root && x->parent->color == RBRED) 283 | { 284 | /* 285 | * x and x->parent are both red. Fix depends on whether x->parent is 286 | * a left or right child. In either case, we define y to be the 287 | * "uncle" of x, that is, the other child of x's grandparent. 288 | * 289 | * If the uncle is red, we flip the grandparent to red and its two 290 | * children to black. Then we loop around again to check whether the 291 | * grandparent still has a problem. 292 | * 293 | * If the uncle is black, we will perform one or two "rotations" to 294 | * balance the tree. Either x or x->parent will take the 295 | * grandparent's position in the tree and recolored black, and the 296 | * original grandparent will be recolored red and become a child of 297 | * that node. This always leaves us with a valid red-black tree, so 298 | * the loop will terminate. 299 | */ 300 | if (x->parent == x->parent->parent->left) 301 | { 302 | RBNode *y = x->parent->parent->right; 303 | 304 | if (y->color == RBRED) 305 | { 306 | /* uncle is RBRED */ 307 | x->parent->color = RBBLACK; 308 | y->color = RBBLACK; 309 | x->parent->parent->color = RBRED; 310 | 311 | x = x->parent->parent; 312 | } 313 | else 314 | { 315 | /* uncle is RBBLACK */ 316 | if (x == x->parent->right) 317 | { 318 | /* make x a left child */ 319 | x = x->parent; 320 | rb_rotate_left(rb, x); 321 | } 322 | 323 | /* recolor and rotate */ 324 | x->parent->color = RBBLACK; 325 | x->parent->parent->color = RBRED; 326 | 327 | rb_rotate_right(rb, x->parent->parent); 328 | } 329 | } 330 | else 331 | { 332 | /* mirror image of above code */ 333 | RBNode *y = x->parent->parent->left; 334 | 335 | if (y->color == RBRED) 336 | { 337 | /* uncle is RBRED */ 338 | x->parent->color = RBBLACK; 339 | y->color = RBBLACK; 340 | x->parent->parent->color = RBRED; 341 | 342 | x = x->parent->parent; 343 | } 344 | else 345 | { 346 | /* uncle is RBBLACK */ 347 | if (x == x->parent->left) 348 | { 349 | x = x->parent; 350 | rb_rotate_right(rb, x); 351 | } 352 | x->parent->color = RBBLACK; 353 | x->parent->parent->color = RBRED; 354 | 355 | rb_rotate_left(rb, x->parent->parent); 356 | } 357 | } 358 | } 359 | 360 | /* 361 | * The root may already have been black; if not, the black-height of every 362 | * node in the tree increases by one. 363 | */ 364 | rb->root->color = RBBLACK; 365 | } 366 | 367 | /* 368 | * rb_insert: insert a new value into the tree. 369 | * 370 | * data represents the value to insert. Its RBNode fields need not 371 | * be valid, it's the extra data in the larger struct that is of interest. 372 | * 373 | * If the value represented by "data" is not present in the tree, then 374 | * we copy "data" into a new tree entry and return that node, setting *isNew 375 | * to true. 376 | * 377 | * If the value represented by "data" is already present, then we call the 378 | * combiner function to merge data into the existing node, and return the 379 | * existing node, setting *isNew to false. 380 | * 381 | * "data" is unmodified in either case; it's typically just a local 382 | * variable in the caller. 383 | */ 384 | RBNode * 385 | rb_insert(RBTree *rb, const RBNode *data, bool *isNew) 386 | { 387 | RBNode *current, 388 | *parent, 389 | *x; 390 | int cmp; 391 | 392 | /* find where node belongs */ 393 | current = rb->root; 394 | parent = NULL; 395 | cmp = 0; /* just to prevent compiler warning */ 396 | 397 | while (current != RBNIL) 398 | { 399 | cmp = rb->comparator(data, current, rb->arg); 400 | if (cmp == 0) 401 | { 402 | /* 403 | * Found node with given key. Apply combiner. 404 | */ 405 | rb->combiner(current, data, rb->arg); 406 | *isNew = false; 407 | return current; 408 | } 409 | parent = current; 410 | current = (cmp < 0) ? current->left : current->right; 411 | } 412 | 413 | /* 414 | * Value is not present, so create a new node containing data. 415 | */ 416 | *isNew = true; 417 | 418 | x = rb->allocfunc (rb->arg); 419 | if(x == NULL) 420 | return NULL; 421 | 422 | x->color = RBRED; 423 | 424 | x->left = RBNIL; 425 | x->right = RBNIL; 426 | x->parent = parent; 427 | rb_copy_data(rb, x, data); 428 | 429 | /* insert node in tree */ 430 | if (parent) 431 | { 432 | if (cmp < 0) 433 | parent->left = x; 434 | else 435 | parent->right = x; 436 | } 437 | else 438 | { 439 | rb->root = x; 440 | } 441 | 442 | rb_insert_fixup(rb, x); 443 | 444 | return x; 445 | } 446 | 447 | /********************************************************************** 448 | * Deletion * 449 | **********************************************************************/ 450 | 451 | /* 452 | * Maintain Red-Black tree balance after deleting a black node. 453 | */ 454 | static void 455 | rb_delete_fixup(RBTree *rb, RBNode *x) 456 | { 457 | /* 458 | * x is always a black node. Initially, it is the former child of the 459 | * deleted node. Each iteration of this loop moves it higher up in the 460 | * tree. 461 | */ 462 | while (x != rb->root && x->color == RBBLACK) 463 | { 464 | /* 465 | * Left and right cases are symmetric. Any nodes that are children of 466 | * x have a black-height one less than the remainder of the nodes in 467 | * the tree. We rotate and recolor nodes to move the problem up the 468 | * tree: at some stage we'll either fix the problem, or reach the root 469 | * (where the black-height is allowed to decrease). 470 | */ 471 | if (x == x->parent->left) 472 | { 473 | RBNode *w = x->parent->right; 474 | 475 | if (w->color == RBRED) 476 | { 477 | w->color = RBBLACK; 478 | x->parent->color = RBRED; 479 | 480 | rb_rotate_left(rb, x->parent); 481 | w = x->parent->right; 482 | } 483 | 484 | if (w->left->color == RBBLACK && w->right->color == RBBLACK) 485 | { 486 | w->color = RBRED; 487 | 488 | x = x->parent; 489 | } 490 | else 491 | { 492 | if (w->right->color == RBBLACK) 493 | { 494 | w->left->color = RBBLACK; 495 | w->color = RBRED; 496 | 497 | rb_rotate_right(rb, w); 498 | w = x->parent->right; 499 | } 500 | w->color = x->parent->color; 501 | x->parent->color = RBBLACK; 502 | w->right->color = RBBLACK; 503 | 504 | rb_rotate_left(rb, x->parent); 505 | x = rb->root; /* Arrange for loop to terminate. */ 506 | } 507 | } 508 | else 509 | { 510 | RBNode *w = x->parent->left; 511 | 512 | if (w->color == RBRED) 513 | { 514 | w->color = RBBLACK; 515 | x->parent->color = RBRED; 516 | 517 | rb_rotate_right(rb, x->parent); 518 | w = x->parent->left; 519 | } 520 | 521 | if (w->right->color == RBBLACK && w->left->color == RBBLACK) 522 | { 523 | w->color = RBRED; 524 | 525 | x = x->parent; 526 | } 527 | else 528 | { 529 | if (w->left->color == RBBLACK) 530 | { 531 | w->right->color = RBBLACK; 532 | w->color = RBRED; 533 | 534 | rb_rotate_left(rb, w); 535 | w = x->parent->left; 536 | } 537 | w->color = x->parent->color; 538 | x->parent->color = RBBLACK; 539 | w->left->color = RBBLACK; 540 | 541 | rb_rotate_right(rb, x->parent); 542 | x = rb->root; /* Arrange for loop to terminate. */ 543 | } 544 | } 545 | } 546 | x->color = RBBLACK; 547 | } 548 | 549 | /* 550 | * Delete node z from tree. 551 | */ 552 | static void 553 | rb_delete_node(RBTree *rb, RBNode *z) 554 | { 555 | RBNode *x, 556 | *y; 557 | 558 | if (!z || z == RBNIL) 559 | return; 560 | 561 | /* 562 | * y is the node that will actually be removed from the tree. This will 563 | * be z if z has fewer than two children, or the tree successor of z 564 | * otherwise. 565 | */ 566 | if (z->left == RBNIL || z->right == RBNIL) 567 | { 568 | /* y has a RBNIL node as a child */ 569 | y = z; 570 | } 571 | else 572 | { 573 | /* find tree successor */ 574 | y = z->right; 575 | while (y->left != RBNIL) 576 | y = y->left; 577 | } 578 | 579 | /* x is y's only child */ 580 | if (y->left != RBNIL) 581 | x = y->left; 582 | else 583 | x = y->right; 584 | 585 | /* Remove y from the tree. */ 586 | x->parent = y->parent; 587 | if (y->parent) 588 | { 589 | if (y == y->parent->left) 590 | y->parent->left = x; 591 | else 592 | y->parent->right = x; 593 | } 594 | else 595 | { 596 | rb->root = x; 597 | } 598 | 599 | /* 600 | * If we removed the tree successor of z rather than z itself, then move 601 | * the data for the removed node to the one we were supposed to remove. 602 | */ 603 | if (y != z) 604 | rb_copy_data(rb, z, y); 605 | 606 | /* 607 | * Removing a black node might make some paths from root to leaf contain 608 | * fewer black nodes than others, or it might make two red nodes adjacent. 609 | */ 610 | if (y->color == RBBLACK) 611 | rb_delete_fixup(rb, x); 612 | 613 | /* Now we can recycle the y node */ 614 | if (rb->freefunc) 615 | rb->freefunc (y, rb->arg); 616 | } 617 | 618 | /* 619 | * rb_delete: remove the given tree entry 620 | * 621 | * "node" must have previously been found via rb_find or rb_leftmost. 622 | * It is caller's responsibility to free any subsidiary data attached 623 | * to the node before calling rb_delete. (Do *not* try to push that 624 | * responsibility off to the freefunc, as some other physical node 625 | * may be the one actually freed!) 626 | */ 627 | void 628 | rb_delete(RBTree *rb, RBNode *node) 629 | { 630 | rb_delete_node(rb, node); 631 | } 632 | 633 | /********************************************************************** 634 | * Traverse * 635 | **********************************************************************/ 636 | 637 | /* 638 | * Begin left right walk. 639 | */ 640 | void 641 | rb_begin_left_right_walk(RBTree *rb, RBTreeLeftRightWalk* lrw) 642 | { 643 | lrw->rb = rb; 644 | lrw->last_visited = NULL; 645 | lrw->is_over = (lrw->rb->root == RBNIL); 646 | } 647 | 648 | /* 649 | * Left right walk: get next node. Returns NULL if there is none. 650 | */ 651 | RBNode* 652 | rb_left_right_walk(RBTreeLeftRightWalk* lrw) 653 | { 654 | if(lrw->is_over) 655 | return NULL; 656 | 657 | if(lrw->last_visited == NULL) 658 | { 659 | lrw->last_visited = lrw->rb->root; 660 | while(lrw->last_visited->left != RBNIL) 661 | lrw->last_visited = lrw->last_visited->left; 662 | 663 | return lrw->last_visited; 664 | } 665 | 666 | if(lrw->last_visited->right != RBNIL) 667 | { 668 | lrw->last_visited = lrw->last_visited->right; 669 | while(lrw->last_visited->left != RBNIL) 670 | lrw->last_visited = lrw->last_visited->left; 671 | 672 | return lrw->last_visited; 673 | } 674 | 675 | for(;;) 676 | { 677 | RBNode* came_from = lrw->last_visited; 678 | lrw->last_visited = lrw->last_visited->parent; 679 | if(lrw->last_visited == NULL) 680 | { 681 | lrw->is_over = true; 682 | break; 683 | } 684 | 685 | if(lrw->last_visited->left == came_from) 686 | break; /* came from left sub-tree, return current node */ 687 | 688 | /* else - came from right sub-tree, continue to move up */ 689 | } 690 | 691 | return lrw->last_visited; 692 | } 693 | 694 | /* 695 | * Begin right left walk. 696 | */ 697 | void 698 | rb_begin_right_left_walk(RBTree *rb, RBTreeRightLeftWalk* rlw) 699 | { 700 | rlw->rb = rb; 701 | rlw->last_visited = NULL; 702 | rlw->is_over = (rlw->rb->root == RBNIL); 703 | } 704 | 705 | /* 706 | * Right left walk: get next node. Returns NULL if there is none. 707 | */ 708 | RBNode* 709 | rb_right_left_walk(RBTreeRightLeftWalk* rlw) 710 | { 711 | if(rlw->is_over) 712 | return NULL; 713 | 714 | if(rlw->last_visited == NULL) 715 | { 716 | rlw->last_visited = rlw->rb->root; 717 | while(rlw->last_visited->right != RBNIL) 718 | rlw->last_visited = rlw->last_visited->right; 719 | 720 | return rlw->last_visited; 721 | } 722 | 723 | if(rlw->last_visited->left != RBNIL) 724 | { 725 | rlw->last_visited = rlw->last_visited->left; 726 | while(rlw->last_visited->right != RBNIL) 727 | rlw->last_visited = rlw->last_visited->right; 728 | 729 | return rlw->last_visited; 730 | } 731 | 732 | for(;;) 733 | { 734 | RBNode* came_from = rlw->last_visited; 735 | rlw->last_visited = rlw->last_visited->parent; 736 | if(rlw->last_visited == NULL) 737 | { 738 | rlw->is_over = true; 739 | break; 740 | } 741 | 742 | if(rlw->last_visited->right == came_from) 743 | break; /* came from right sub-tree, return current node */ 744 | 745 | /* else - came from left sub-tree, continue to move up */ 746 | } 747 | 748 | return rlw->last_visited; 749 | } 750 | 751 | /* 752 | * Begin direct walk (a.k.a pre-order traversal). 753 | * 754 | * Pre-order traversal while duplicating nodes and edges can make a complete 755 | * duplicate of a binary tree. It can also be used to make a prefix expression 756 | * (Polish notation) from expression trees: traverse the expression tree 757 | * pre-orderly. 758 | * 759 | * https://en.wikipedia.org/wiki/Tree_traversal#Applications 760 | */ 761 | void 762 | rb_begin_direct_walk(RBTree *rb, RBTreeDirectWalk* dw) 763 | { 764 | dw->rb = rb; 765 | dw->last_visited = NULL; 766 | dw->is_over = (dw->rb->root == RBNIL); 767 | } 768 | 769 | /* 770 | * Direct walk: get next node. Returns NULL if there is none. 771 | */ 772 | RBNode* 773 | rb_direct_walk(RBTreeDirectWalk* dw) 774 | { 775 | if(dw->is_over) 776 | return NULL; 777 | 778 | if(dw->last_visited == NULL) 779 | { 780 | dw->last_visited = dw->rb->root; 781 | return dw->last_visited; 782 | } 783 | 784 | if(dw->last_visited->left != RBNIL) 785 | { 786 | dw->last_visited = dw->last_visited->left; 787 | return dw->last_visited; 788 | } 789 | 790 | do 791 | { 792 | if(dw->last_visited->right != RBNIL) 793 | { 794 | dw->last_visited = dw->last_visited->right; 795 | break; 796 | } 797 | 798 | /* go up and one step right */ 799 | for(;;) 800 | { 801 | RBNode* came_from = dw->last_visited; 802 | dw->last_visited = dw->last_visited->parent; 803 | if(dw->last_visited == NULL) 804 | { 805 | dw->is_over = true; 806 | break; 807 | } 808 | 809 | if((dw->last_visited->right != came_from) && (dw->last_visited->right != RBNIL)) 810 | { 811 | dw->last_visited = dw->last_visited->right; 812 | return dw->last_visited; 813 | } 814 | } 815 | } 816 | while(dw->last_visited != NULL); 817 | 818 | return dw->last_visited; 819 | } 820 | 821 | /* 822 | * Begin inverted walk (a.k.a post-order traversal). 823 | */ 824 | void 825 | rb_begin_inverted_walk(RBTree *rb, RBTreeInvertedWalk* iw) 826 | { 827 | iw->rb = rb; 828 | iw->last_visited = NULL; 829 | iw->next_step = NextStepNone; 830 | iw->is_over = (iw->rb->root == RBNIL); 831 | } 832 | 833 | /* 834 | * Inverted walk: get next node. Returns NULL if there is none. 835 | * 836 | * Post-order traversal while deleting or freeing nodes and values can delete 837 | * or free an entire binary tree. It can also generate a postfix 838 | * representation of a binary tree. 839 | * 840 | * https://en.wikipedia.org/wiki/Tree_traversal#Applications 841 | */ 842 | RBNode* 843 | rb_inverted_walk(RBTreeInvertedWalk* iw) 844 | { 845 | RBNode* came_from; 846 | 847 | if(iw->is_over) 848 | return NULL; 849 | 850 | if(iw->last_visited == NULL) 851 | { 852 | iw->last_visited = iw->rb->root; 853 | iw->next_step = NextStepLeft; 854 | } 855 | 856 | loop: 857 | switch(iw->next_step) 858 | { 859 | case NextStepLeft: 860 | came_from = iw->last_visited; 861 | while(iw->last_visited->left != RBNIL) 862 | iw->last_visited = iw->last_visited->left; 863 | 864 | iw->next_step = NextStepRight; 865 | goto loop; 866 | 867 | case NextStepRight: 868 | if(iw->last_visited->right != RBNIL) 869 | { 870 | iw->last_visited = iw->last_visited->right; 871 | iw->next_step = NextStepLeft; 872 | goto loop; 873 | } 874 | else /* not moved - return current, then go up */ 875 | iw->next_step = NextStepUp; 876 | break; 877 | case NextStepUp: 878 | for(;;) 879 | { 880 | came_from = iw->last_visited; 881 | iw->last_visited = iw->last_visited->parent; 882 | if(iw->last_visited == NULL) 883 | { 884 | iw->is_over = true; 885 | break; /* end of iteration */ 886 | } 887 | 888 | if(came_from == iw->last_visited->right) 889 | { 890 | /* return current, then continue to go up */ 891 | break; 892 | } 893 | 894 | /* otherwise we came from the left */ 895 | iw->next_step = NextStepRight; 896 | goto loop; 897 | } 898 | break; 899 | default: 900 | fprintf(stderr, "Unexpected next step value during inverted walk: %d\n", iw->next_step); 901 | exit(1); 902 | } 903 | 904 | return iw->last_visited; 905 | } 906 | 907 | /* 908 | * Print tree to stdout. 909 | */ 910 | void 911 | rb_tree_debug_print(RBTree* rb, rb_sprintfunc sprintfunc) 912 | { 913 | RBTreeDirectWalk dw; 914 | RBNode* node; 915 | char buff[1024]; 916 | 917 | rb_begin_direct_walk(rb, &dw); 918 | printf("nodes = {}\n"); 919 | for(;;) 920 | { 921 | node = rb_direct_walk(&dw); 922 | if(!node) 923 | break; 924 | sprintfunc(node, buff); 925 | printf("nodes['%p'] = {'parent':'%p','left':'%p','right':'%p','color':'%s','data':'%s'}\n", 926 | (void*)node, (void*)node->parent, (void*)(node->left == RBNIL ? NULL : node->left), (void*)(node->right == RBNIL ? NULL : node->right), 927 | node->color == RBBLACK ? "black" : "red", buff); 928 | } 929 | } 930 | 931 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(c-algorithms-tests) 4 | 5 | add_subdirectory(struct) 6 | add_subdirectory(crypto) 7 | -------------------------------------------------------------------------------- /test/crypto/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(c-algorithms-crypto-tests) 4 | 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g") 6 | 7 | add_executable(test_md5 test_md5.c) 8 | target_link_libraries(test_md5 CAlgorithms) 9 | add_test(test_md5 "./test_md5") 10 | 11 | add_executable(test_sha1 test_sha1.c) 12 | target_link_libraries(test_sha1 CAlgorithms) 13 | add_test(test_sha1 "./test_sha1") 14 | 15 | add_executable(test_sha256 test_sha256.c) 16 | target_link_libraries(test_sha256 CAlgorithms) 17 | add_test(test_sha256 "./test_sha256") 18 | 19 | add_executable(test_sha384 test_sha384.c) 20 | target_link_libraries(test_sha384 CAlgorithms) 21 | add_test(test_sha384 "./test_sha384") 22 | 23 | add_executable(test_sha512 test_sha512.c) 24 | target_link_libraries(test_sha512 CAlgorithms) 25 | add_test(test_sha512 "./test_sha512") 26 | 27 | add_executable(test_rijndael test_rijndael.c) 28 | target_link_libraries(test_rijndael CAlgorithms) 29 | add_test(test_rijndael "./test_rijndael") 30 | 31 | -------------------------------------------------------------------------------- /test/crypto/test_md5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "crypto/md5.h" 7 | #include "common/utils.h" 8 | 9 | /* 10 | See https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors 11 | */ 12 | int main() 13 | { 14 | MD5_CTX ctx; 15 | uint8_t res[MD5_DIGEST_LENGTH]; 16 | char strres[MD5_DIGEST_STRING_LENGTH]; 17 | char* vectors[] = { 18 | "D41D8CD98F00B204E9800998ECF8427E", "", 19 | "0CC175B9C0F1B6A831C399E269772661", "a", 20 | "900150983CD24FB0D6963F7D28E17F72", "abc", 21 | "F96B697D7CB7938D525A2F31AAF161D0", "message digest", 22 | "C3FCD3D76192E4007DFB496CCA67E13B", "abcdefghijklmnopqrstuvwxyz", 23 | "8215EF0796A20BCAAAE116D3876C664A", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 24 | "D174AB98D277D9F5A5611C2C9F419D9F", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 25 | "57EDF4A22BE3C955AC49DA2E2107B67A", "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 26 | "7707D6AE4E027C70EEA2A935C2296F21", NULL 27 | }; 28 | char a10[] = "aaaaaaaaaa"; 29 | int j, i = 0; 30 | 31 | while(vectors[i+1] != NULL) 32 | { 33 | MD5_Init(&ctx); 34 | MD5_Update(&ctx, (uint8_t*)vectors[i+1], strlen(vectors[i+1])); 35 | MD5_Final(res, &ctx); 36 | bytesToHex(res, MD5_DIGEST_LENGTH, strres); 37 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 38 | assert(strcmp(strres, vectors[i]) == 0); 39 | i += 2; 40 | } 41 | 42 | // Vector 8, 1 million times "a" 43 | MD5_Init(&ctx); 44 | for(j = 0; j < 1000000 / (sizeof(a10)-1); j++) 45 | { 46 | MD5_Update(&ctx, (uint8_t*)a10, sizeof(a10)-1); 47 | } 48 | MD5_Final(res, &ctx); 49 | bytesToHex(res, MD5_DIGEST_LENGTH, strres); 50 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 51 | assert(strcmp(strres, vectors[i]) == 0); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /test/crypto/test_rijndael.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "crypto/rijndael.h" 8 | #include "common/utils.h" 9 | 10 | /* 11 | See: 12 | 13 | https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/rijndael/Rijndael-128-128.unverified.test-vectors 14 | https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/rijndael/Rijndael-192-128.unverified.test-vectors 15 | https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/rijndael/Rijndael-256-128.unverified.test-vectors 16 | */ 17 | static void 18 | test_basics() 19 | { 20 | rijndael_ctx ctx; 21 | char* vectors[] = { 22 | // key, plain, encrypted 23 | "000102030405060708090A0B0C0D0E0F", 24 | "762A5AB50929189CEFDB99434790AAD8", 25 | "00112233445566778899AABBCCDDEEFF", 26 | 27 | "2BD6459F82C5B300952C49104881FF48", 28 | "E99388EED41AD8058D6162B0CF4667E6", 29 | "EA024714AD5C4D84EA024714AD5C4D84", 30 | 31 | "000102030405060708090A0B0C0D0E0F1011121314151617", 32 | "3369EB82973635E9C2E96D687724C790", 33 | "00112233445566778899AABBCCDDEEFF", 34 | 35 | "2BD6459F82C5B300952C49104881FF482BD6459F82C5B300", 36 | "A4C5C1F3858A5A596189E928B4469EA2", 37 | "EA024714AD5C4D84EA024714AD5C4D84", 38 | 39 | "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", 40 | "EAB487E68EC92DB4AC288A24757B0262", 41 | "00112233445566778899AABBCCDDEEFF", 42 | 43 | "2BD6459F82C5B300952C49104881FF482BD6459F82C5B300952C49104881FF48", 44 | "DFC295E9D04A30DB25940E4FCC64516F", 45 | "EA024714AD5C4D84EA024714AD5C4D84", 46 | }; 47 | int t, ntests = sizeof(vectors) / sizeof(vectors[0]) / 3; 48 | 49 | for(t = 0; t < ntests; t++) 50 | { 51 | uint8_t bkey[32]; // at most 256 bits 52 | uint8_t bplain[16]; 53 | uint8_t bencrypted[16]; 54 | char encrypted_hex[33]; 55 | char plain_hex[33]; 56 | char* skey = vectors[t*3]; 57 | char* splain = vectors[t*3 + 1]; 58 | char* sencrypted = vectors[t*3 + 2]; 59 | int bkeylen = strlen(skey) / 2; 60 | int tmp; 61 | 62 | tmp = hexToBytes(skey, bkey, bkeylen); 63 | assert(tmp == 0); 64 | 65 | tmp = hexToBytes(splain, bplain, sizeof(bplain)); 66 | assert(tmp == 0); 67 | 68 | rijndael_set_key(&ctx, (u4byte*)&bkey, bkeylen*8, 0); 69 | 70 | // test encryption 71 | 72 | rijndael_encrypt(&ctx, (u4byte*)&bplain, (u4byte*)&bencrypted); 73 | bytesToHex(bencrypted, sizeof(bencrypted), encrypted_hex); 74 | 75 | // test decryption 76 | 77 | memset(bplain, 0, sizeof(bplain)); 78 | rijndael_decrypt(&ctx, (u4byte*)&bencrypted, (u4byte*)&bplain); 79 | bytesToHex(bplain, sizeof(bplain), plain_hex); 80 | 81 | printf("Test vector %d, skey = %s, splain = %s, sencrypted = %s, encrypted_hex = %s, plain_hex = %s\n", 82 | t, skey, splain, sencrypted, encrypted_hex, plain_hex); 83 | 84 | assert(strcmp(sencrypted, encrypted_hex) == 0); 85 | assert(strcmp(splain, plain_hex) == 0); 86 | } 87 | } 88 | 89 | static void 90 | test_ecb() 91 | { 92 | rijndael_ctx ctx; 93 | bool equal; 94 | uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 95 | uint8_t data[16*3]; 96 | 97 | assert(sizeof(key) == 16); 98 | assert((sizeof(data) % 16) == 0); 99 | 100 | for(uint8_t i = 0; i < sizeof(data); i++) 101 | data[i] = i; 102 | 103 | aes_set_key(&ctx, key, sizeof(key)*8, 0); 104 | aes_ecb_encrypt(&ctx, data, sizeof(data)); 105 | 106 | equal = true; 107 | for(uint8_t i = 0; i < sizeof(data); i++) 108 | equal &= (data[i] == i); 109 | 110 | assert(!equal); 111 | 112 | aes_ecb_decrypt(&ctx, data, sizeof(data)); 113 | 114 | for(uint8_t i = 0; i < sizeof(data); i++) 115 | assert(data[i] == i); 116 | 117 | printf("ECB test passed!\n"); 118 | } 119 | 120 | static void 121 | test_cbc() 122 | { 123 | rijndael_ctx ctx; 124 | bool equal; 125 | uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 126 | uint8_t iv[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 127 | uint8_t data[16*3]; 128 | 129 | assert(sizeof(key) == 16); 130 | assert(sizeof(iv) == 16); 131 | assert((sizeof(data) % 16) == 0); 132 | 133 | for(uint8_t i = 0; i < sizeof(data); i++) 134 | data[i] = i; 135 | 136 | aes_set_key(&ctx, key, sizeof(key)*8, 0); 137 | aes_cbc_encrypt(&ctx, iv, data, sizeof(data)); 138 | 139 | equal = true; 140 | for(uint8_t i = 0; i < sizeof(data); i++) 141 | equal &= (data[i] == i); 142 | 143 | assert(!equal); 144 | 145 | aes_cbc_decrypt(&ctx, iv, data, sizeof(data)); 146 | 147 | for(uint8_t i = 0; i < sizeof(data); i++) 148 | assert(data[i] == i); 149 | 150 | printf("CBC test passed!\n"); 151 | } 152 | 153 | int main() 154 | { 155 | test_basics(); 156 | test_ecb(); 157 | test_cbc(); 158 | return 0; 159 | } 160 | -------------------------------------------------------------------------------- /test/crypto/test_sha1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "crypto/sha1.h" 7 | #include "common/utils.h" 8 | 9 | /* 10 | See http://www.di-mgt.com.au/sha_testvectors.html 11 | */ 12 | int main() 13 | { 14 | SHA1_CTX ctx; 15 | uint8_t res[SHA1_DIGEST_LENGTH]; 16 | char strres[SHA1_DIGEST_STRING_LENGTH]; 17 | char* vectors[] = { 18 | "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", "", 19 | "86F7E437FAA5A7FCE15D1DDCB9EAEAEA377667B8", "a", 20 | "A9993E364706816ABA3E25717850C26C9CD0D89D", "abc", 21 | "C12252CEDA8BE8994D5FA0290A47231C1D16AAE3", "message digest", 22 | "32D10C7B8CF96570CA04CE37F2A19D84240D3A89", "abcdefghijklmnopqrstuvwxyz", 23 | "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 24 | "761C457BF73B14D27E9E9265C46F4B4DDA11F940", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 25 | "50ABF5706A150990A08B2C5EA40FA0E585554732", "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 26 | "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F", NULL 27 | }; 28 | char a10[] = "aaaaaaaaaa"; 29 | int j, i = 0; 30 | 31 | while(vectors[i+1] != NULL) 32 | { 33 | SHA1_Init(&ctx); 34 | SHA1_Update(&ctx, (uint8_t*)vectors[i+1], strlen(vectors[i+1])); 35 | SHA1_Final(res, &ctx); 36 | bytesToHex(res, SHA1_DIGEST_LENGTH, strres); 37 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 38 | assert(strcmp(strres, vectors[i]) == 0); 39 | i += 2; 40 | } 41 | 42 | // Vector 8, 1 million times "a" 43 | SHA1_Init(&ctx); 44 | for(j = 0; j < 1000000 / (sizeof(a10)-1); j++) 45 | { 46 | SHA1_Update(&ctx, (uint8_t*)a10, sizeof(a10)-1); 47 | } 48 | SHA1_Final(res, &ctx); 49 | bytesToHex(res, SHA1_DIGEST_LENGTH, strres); 50 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 51 | assert(strcmp(strres, vectors[i]) == 0); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /test/crypto/test_sha256.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "crypto/sha2.h" 7 | #include "common/utils.h" 8 | 9 | /* 10 | See http://www.di-mgt.com.au/sha_testvectors.html 11 | */ 12 | int main() 13 | { 14 | SHA256_CTX ctx; 15 | uint8_t res[SHA256_DIGEST_LENGTH]; 16 | char strres[SHA256_DIGEST_STRING_LENGTH]; 17 | char* vectors[] = { 18 | "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "", 19 | "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB", "a", 20 | "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD", "abc", 21 | "F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650", "message digest", 22 | "71C480DF93D6AE2F1EFAD1447C66C9525E316218CF51FC8D9ED832F2DAF18B73", "abcdefghijklmnopqrstuvwxyz", 23 | "248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 24 | "DB4BFCBD4DA0CD85A60C3C37D3FBD8805C77F15FC6B1FDFE614EE0A7C8FDB4C0", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 25 | "F371BC4A311F2B009EEF952DD83CA80E2B60026C8E935592D0F9C308453C813E", "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 26 | "CDC76E5C9914FB9281A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0", NULL 27 | }; 28 | char a10[] = "aaaaaaaaaa"; 29 | int j, i = 0; 30 | 31 | while(vectors[i+1] != NULL) 32 | { 33 | SHA256_Init(&ctx); 34 | SHA256_Update(&ctx, (uint8_t*)vectors[i+1], strlen(vectors[i+1])); 35 | SHA256_Final(res, &ctx); 36 | bytesToHex(res, SHA256_DIGEST_LENGTH, strres); 37 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 38 | assert(strcmp(strres, vectors[i]) == 0); 39 | i += 2; 40 | } 41 | 42 | // Vector 8, 1 million times "a" 43 | SHA256_Init(&ctx); 44 | for(j = 0; j < 1000000 / (sizeof(a10)-1); j++) 45 | { 46 | SHA256_Update(&ctx, (uint8_t*)a10, sizeof(a10)-1); 47 | } 48 | SHA256_Final(res, &ctx); 49 | bytesToHex(res, SHA256_DIGEST_LENGTH, strres); 50 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 51 | assert(strcmp(strres, vectors[i]) == 0); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /test/crypto/test_sha384.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "crypto/sha2.h" 7 | #include "common/utils.h" 8 | 9 | /* 10 | See http://www.di-mgt.com.au/sha_testvectors.html 11 | */ 12 | int main() 13 | { 14 | SHA384_CTX ctx; 15 | uint8_t res[SHA384_DIGEST_LENGTH]; 16 | char strres[SHA384_DIGEST_STRING_LENGTH]; 17 | char* vectors[] = { 18 | "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B", 19 | "", 20 | 21 | "54A59B9F22B0B80880D8427E548B7C23ABD873486E1F035DCE9CD697E85175033CAA88E6D57BC35EFAE0B5AFD3145F31", 22 | "a", 23 | 24 | "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7", 25 | "abc", 26 | 27 | "473ED35167EC1F5D8E550368A3DB39BE54639F828868E9454C239FC8B52E3C61DBD0D8B4DE1390C256DCBB5D5FD99CD5", 28 | "message digest", 29 | 30 | "FEB67349DF3DB6F5924815D6C3DC133F091809213731FE5C7B5F4999E463479FF2877F5F2936FA63BB43784B12F3EBB4", 31 | "abcdefghijklmnopqrstuvwxyz", 32 | 33 | "3391FDDDFC8DC7393707A65B1B4709397CF8B1D162AF05ABFE8F450DE5F36BC6B0455A8520BC4E6F5FE95B1FE3C8452B", 34 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 35 | 36 | "1761336E3F7CBFE51DEB137F026F89E01A448E3B1FAFA64039C1464EE8732F11A5341A6F41E0C202294736ED64DB1A84", 37 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 38 | 39 | "B12932B0627D1C060942F5447764155655BD4DA0C9AFA6DD9B9EF53129AF1B8FB0195996D2DE9CA0DF9D821FFEE67026", 40 | "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 41 | 42 | "9D0E1809716474CB086E834E310A4A1CED149E9C00F248527972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985", 43 | NULL 44 | }; 45 | char a10[] = "aaaaaaaaaa"; 46 | int j, i = 0; 47 | 48 | while(vectors[i+1] != NULL) 49 | { 50 | SHA384_Init(&ctx); 51 | SHA384_Update(&ctx, (uint8_t*)vectors[i+1], strlen(vectors[i+1])); 52 | SHA384_Final(res, &ctx); 53 | bytesToHex(res, SHA384_DIGEST_LENGTH, strres); 54 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 55 | assert(strcmp(strres, vectors[i]) == 0); 56 | i += 2; 57 | } 58 | 59 | // Vector 8, 1 million times "a" 60 | SHA384_Init(&ctx); 61 | for(j = 0; j < 1000000 / (sizeof(a10)-1); j++) 62 | { 63 | SHA384_Update(&ctx, (uint8_t*)a10, sizeof(a10)-1); 64 | } 65 | SHA384_Final(res, &ctx); 66 | bytesToHex(res, SHA384_DIGEST_LENGTH, strres); 67 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 68 | assert(strcmp(strres, vectors[i]) == 0); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /test/crypto/test_sha512.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "crypto/sha2.h" 7 | #include "common/utils.h" 8 | 9 | /* 10 | See http://www.di-mgt.com.au/sha_testvectors.html 11 | */ 12 | int main() 13 | { 14 | SHA512_CTX ctx; 15 | uint8_t res[SHA512_DIGEST_LENGTH]; 16 | char strres[SHA512_DIGEST_STRING_LENGTH]; 17 | char* vectors[] = { 18 | "CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E", 19 | "", 20 | 21 | "1F40FC92DA241694750979EE6CF582F2D5D7D28E18335DE05ABC54D0560E0F5302860C652BF08D560252AA5E74210546F369FBBBCE8C12CFC7957B2652FE9A75", 22 | "a", 23 | 24 | "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F", 25 | "abc", 26 | 27 | "107DBF389D9E9F71A3A95F6C055B9251BC5268C2BE16D6C13492EA45B0199F3309E16455AB1E96118E8A905D5597B72038DDB372A89826046DE66687BB420E7C", 28 | "message digest", 29 | 30 | "4DBFF86CC2CA1BAE1E16468A05CB9881C97F1753BCE3619034898FAA1AABE429955A1BF8EC483D7421FE3C1646613A59ED5441FB0F321389F77F48A879C7B1F1", 31 | "abcdefghijklmnopqrstuvwxyz", 32 | 33 | "204A8FC6DDA82F0A0CED7BEB8E08A41657C16EF468B228A8279BE331A703C33596FD15C13B1B07F9AA1D3BEA57789CA031AD85C7A71DD70354EC631238CA3445", 34 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 35 | 36 | "1E07BE23C26A86EA37EA810C8EC7809352515A970E9253C26F536CFC7A9996C45C8370583E0A78FA4A90041D71A4CEAB7423F19C71B9D5A3E01249F0BEBD5894", 37 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 38 | 39 | "72EC1EF1124A45B047E8B7C75A932195135BB61DE24EC0D1914042246E0AEC3A2354E093D76F3048B456764346900CB130D2A4FD5DD16ABB5E30BCB850DEE843", 40 | "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 41 | 42 | "E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044285632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B", 43 | NULL 44 | }; 45 | char a10[] = "aaaaaaaaaa"; 46 | int j, i = 0; 47 | 48 | while(vectors[i+1] != NULL) 49 | { 50 | SHA512_Init(&ctx); 51 | SHA512_Update(&ctx, (uint8_t*)vectors[i+1], strlen(vectors[i+1])); 52 | SHA512_Final(res, &ctx); 53 | bytesToHex(res, SHA512_DIGEST_LENGTH, strres); 54 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 55 | assert(strcmp(strres, vectors[i]) == 0); 56 | i += 2; 57 | } 58 | 59 | // Vector 8, 1 million times "a" 60 | SHA512_Init(&ctx); 61 | for(j = 0; j < 1000000 / (sizeof(a10)-1); j++) 62 | { 63 | SHA512_Update(&ctx, (uint8_t*)a10, sizeof(a10)-1); 64 | } 65 | SHA512_Final(res, &ctx); 66 | bytesToHex(res, SHA512_DIGEST_LENGTH, strres); 67 | printf("Vector %i, result = %s, expected = %s\n", i / 2, strres, vectors[i]); 68 | assert(strcmp(strres, vectors[i]) == 0); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /test/struct/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(c-algorithms-struct-tests) 4 | 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g") 6 | 7 | add_executable(test_slist test_slist.c) 8 | target_link_libraries(test_slist CAlgorithms) 9 | 10 | add_executable(test_dlist test_dlist.c) 11 | target_link_libraries(test_dlist CAlgorithms) 12 | 13 | add_executable(test_htable test_htable.c) 14 | target_link_libraries(test_htable CAlgorithms) 15 | 16 | add_executable(test_rbtree test_rbtree.c) 17 | target_link_libraries(test_rbtree CAlgorithms) 18 | 19 | add_test(test_slist "./test_slist") 20 | add_test(test_dlist "./test_dlist") 21 | add_test(test_htable "./test_htable") 22 | add_test(test_rbtree "./test_rbtree") 23 | -------------------------------------------------------------------------------- /test/struct/test_dlist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "struct/ilist.h" 6 | 7 | typedef struct 8 | { 9 | dlist_node node; 10 | char data[128]; 11 | } ListItemData; 12 | 13 | typedef ListItemData *ListItem; 14 | 15 | int main() 16 | { 17 | dlist_iter iter; 18 | ListItemData item1, item2, item3; 19 | ListItem tmp; 20 | char temp_buff[512]; 21 | 22 | dlist_head head; 23 | dlist_init(&head); 24 | assert(dlist_is_empty(&head)); 25 | 26 | strcpy(item1.data, "first item"); 27 | strcpy(item2.data, "second item"); 28 | strcpy(item3.data, "third item"); 29 | 30 | dlist_push_tail(&head, (dlist_node*) &item1); 31 | assert(!dlist_is_empty(&head)); 32 | 33 | dlist_push_tail(&head, (dlist_node*) &item2); 34 | dlist_push_tail(&head, (dlist_node*) &item3); 35 | 36 | temp_buff[0] = 0; 37 | dlist_foreach(iter, &head) 38 | { 39 | tmp = (ListItem) iter.cur; 40 | strcat(temp_buff, tmp->data); 41 | strcat(temp_buff, ","); 42 | } 43 | assert(strcmp(temp_buff, "first item,second item,third item,") == 0); 44 | 45 | tmp = (ListItem) dlist_pop_tail_node(&head); 46 | assert(strcmp(tmp->data, "third item") == 0); 47 | 48 | temp_buff[0] = 0; 49 | dlist_foreach(iter, &head) 50 | { 51 | tmp = (ListItem) iter.cur; 52 | strcat(temp_buff, tmp->data); 53 | strcat(temp_buff, ","); 54 | } 55 | assert(strcmp(temp_buff, "first item,second item,") == 0); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /test/struct/test_htable.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "struct/htable.h" 7 | 8 | #define N 100 9 | 10 | typedef struct 11 | { 12 | HTableNode node; 13 | char expression[128]; 14 | int value; 15 | } ExpressionTableNodeData; 16 | 17 | typedef ExpressionTableNodeData *ExpressionTableNode; 18 | 19 | static bool 20 | keyeq_func(const HTableNode* a_, const HTableNode* b_, void *arg) 21 | { 22 | ExpressionTableNode a = (ExpressionTableNode)a_; 23 | ExpressionTableNode b = (ExpressionTableNode)b_; 24 | return (strcmp(a->expression, b->expression) == 0); 25 | } 26 | 27 | static uint32_t 28 | hash_func(const HTableNode* a_, void *arg) 29 | { 30 | ExpressionTableNode a = (ExpressionTableNode)a_; 31 | return htable_default_hash(a->expression, strlen(a->expression)); 32 | } 33 | 34 | static void* 35 | alloc_func(size_t size, void *arg) 36 | { 37 | return malloc(size); 38 | } 39 | 40 | static void 41 | free_func(void* mem, void *arg) 42 | { 43 | free(mem); 44 | } 45 | 46 | static void 47 | run_test(HTable* htable) 48 | { 49 | int i, j; 50 | 51 | /* fill table */ 52 | for(i = 1; i <= N; i++) 53 | { 54 | for(j = 1; j <= N; j++) 55 | { 56 | bool isNewNode; 57 | ExpressionTableNodeData new_node_data; 58 | sprintf(new_node_data.expression, "%d + %d", i, j); 59 | new_node_data.value = (i + j); 60 | htable_insert(htable, (HTableNode*)&new_node_data, &isNewNode); 61 | assert(isNewNode); 62 | } 63 | } 64 | 65 | assert(htable_nitems(htable) == (N*N)); 66 | 67 | /* check hash table is filled right */ 68 | for(i = 1; i <= N; i++) 69 | { 70 | for(j = 1; j <= N; j++) 71 | { 72 | ExpressionTableNode found_node; 73 | ExpressionTableNodeData query; 74 | sprintf(query.expression, "%d + %d", i, j); 75 | found_node = (ExpressionTableNode)htable_find(htable, (HTableNode*)&query); 76 | assert(found_node != NULL); 77 | assert(found_node->value == (i + j)); 78 | } 79 | } 80 | 81 | /* try to delete a non-existing node */ 82 | { 83 | bool result; 84 | ExpressionTableNodeData query; 85 | sprintf(query.expression, "ololo trololo"); 86 | result = htable_delete(htable, (HTableNode*)&query); 87 | assert(result == false); 88 | } 89 | 90 | /* clean table */ 91 | for(i = 1; i <= N; i++) 92 | { 93 | for(j = 1; j <= N; j++) 94 | { 95 | bool result; 96 | ExpressionTableNodeData query; 97 | sprintf(query.expression, "%d + %d", i, j); 98 | result = htable_delete(htable, (HTableNode*)&query); 99 | assert(result == true); 100 | } 101 | } 102 | 103 | assert(htable_nitems(htable) == 0); 104 | } 105 | 106 | int main() 107 | { 108 | int i; 109 | HTable htable_data; 110 | 111 | htable_create( 112 | &htable_data, 113 | sizeof(ExpressionTableNodeData), 114 | hash_func, 115 | keyeq_func, 116 | alloc_func, 117 | free_func, 118 | NULL, 119 | NULL 120 | ); 121 | 122 | run_test(&htable_data); 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /test/struct/test_rbtree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "struct/rbtree.h" 9 | 10 | /* #define INIFNITE_TEST */ 11 | #define UNIQUE_NUMBERS_ARRAY_SIZE 7777 12 | 13 | typedef struct 14 | { 15 | RBNode node; 16 | char data[128]; 17 | } TreeItemData; 18 | 19 | typedef TreeItemData *TreeItem; 20 | 21 | static int 22 | tree_comparator(const RBNode* a, const RBNode* b, void* arg) 23 | { 24 | return strcmp(((const TreeItem)a)->data, ((const TreeItem)b)->data); 25 | } 26 | 27 | static void 28 | tree_combiner(RBNode* existing, const RBNode* newdata, void* arg) 29 | { 30 | /* do nothing */ 31 | } 32 | 33 | static RBNode* 34 | tree_allocfunc(void* arg) 35 | { 36 | return malloc(sizeof(TreeItemData)); 37 | } 38 | 39 | static void 40 | tree_freefunc(RBNode* node, void* arg) 41 | { 42 | free(node); 43 | } 44 | 45 | static void 46 | tree_sprintfunc(RBNode* node, char* buff) 47 | { 48 | strcpy(buff, ((TreeItemData*)node)->data); 49 | } 50 | 51 | static void 52 | general_test() 53 | { 54 | RBTree tree; 55 | bool isNew; 56 | TreeItemData item; 57 | TreeItem tmp; 58 | RBTreeLeftRightWalk lrw; 59 | char temp_buff[512]; 60 | 61 | rb_create(&tree, sizeof(TreeItemData), tree_comparator, tree_combiner, tree_allocfunc, tree_freefunc, NULL); 62 | 63 | assert(rb_leftmost(&tree) == NULL); 64 | 65 | strcpy(item.data, "Item A"); 66 | rb_insert(&tree, (RBNode*)&item, &isNew); 67 | assert(isNew); 68 | assert(rb_leftmost(&tree) != NULL); 69 | 70 | strcpy(item.data, "Item B"); 71 | rb_insert(&tree, (RBNode*)&item, &isNew); 72 | assert(isNew); 73 | 74 | strcpy(item.data, "Item C"); 75 | rb_insert(&tree, (RBNode*)&item, &isNew); 76 | assert(isNew); 77 | 78 | temp_buff[0] = 0; 79 | rb_begin_left_right_walk(&tree, &lrw); 80 | while( (tmp = (TreeItem)rb_left_right_walk(&lrw)) ) 81 | { 82 | strcat(temp_buff, tmp->data); 83 | strcat(temp_buff, ","); 84 | } 85 | assert(strcmp(temp_buff, "Item A,Item B,Item C,") == 0); 86 | 87 | strcpy(item.data, "No Such Item"); 88 | tmp = (TreeItem)rb_find(&tree, (RBNode*)&item); 89 | assert(tmp == NULL); 90 | 91 | strcpy(item.data, "Item A"); 92 | tmp = (TreeItem)rb_find(&tree, (RBNode*)&item); 93 | assert(tmp != NULL); 94 | 95 | strcpy(item.data, "Item C"); 96 | tmp = (TreeItem)rb_find(&tree, (RBNode*)&item); 97 | assert(tmp != NULL); 98 | 99 | strcpy(item.data, "Item B"); 100 | tmp = (TreeItem)rb_find(&tree, (RBNode*)&item); 101 | assert(tmp != NULL); 102 | 103 | rb_delete(&tree, (RBNode*)tmp); 104 | 105 | /* rb_begin_iterate + rb_iterate doesn't work here! */ 106 | temp_buff[0] = 0; 107 | while( (tmp = (TreeItem)rb_leftmost(&tree)) ) 108 | { 109 | strcat(temp_buff, tmp->data); 110 | strcat(temp_buff, ","); 111 | rb_delete(&tree, (RBNode*)tmp); 112 | } 113 | 114 | assert(strcmp(temp_buff, "Item A,Item C,") == 0); 115 | assert(rb_leftmost(&tree) == NULL); 116 | } 117 | 118 | /* 119 | * Make sure left right walk enumirates all items, and any item is returned 120 | * only once. Also make sure left right walk returns item in sorted order. 121 | */ 122 | static void 123 | left_right_walk_test() 124 | { 125 | RBTree tree; 126 | bool isNew; 127 | TreeItemData item; 128 | TreeItem tmp; 129 | RBTreeLeftRightWalk lrw; 130 | bool number_returned[UNIQUE_NUMBERS_ARRAY_SIZE]; 131 | int unique_numbers[UNIQUE_NUMBERS_ARRAY_SIZE]; 132 | int i, j, temp, nitems, last_item; 133 | int array_size = UNIQUE_NUMBERS_ARRAY_SIZE; 134 | 135 | #ifdef INIFNITE_TEST 136 | array_size = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 137 | #endif 138 | 139 | for(i = 0; i < array_size; i++) 140 | { 141 | unique_numbers[i] = i; 142 | number_returned[i] = false; 143 | } 144 | 145 | /* shuffle numbers */ 146 | for(i = 0; i < array_size; i++) 147 | { 148 | j = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 149 | assert((j >= 0) && (j < array_size)); 150 | temp = unique_numbers[i]; 151 | unique_numbers[i] = unique_numbers[j]; 152 | unique_numbers[j] = temp; 153 | } 154 | 155 | /* create an empty tree */ 156 | rb_create(&tree, sizeof(TreeItemData), tree_comparator, tree_combiner, tree_allocfunc, tree_freefunc, NULL); 157 | 158 | rb_begin_left_right_walk(&tree, &lrw); 159 | assert(rb_left_right_walk(&lrw) == NULL); 160 | 161 | /* fill a tree */ 162 | for(i = 0; i < array_size; i++) 163 | { 164 | sprintf(item.data, "Item %08x", unique_numbers[i]); 165 | rb_insert(&tree, (RBNode*)&item, &isNew); 166 | assert(isNew); 167 | } 168 | 169 | /* check enumiration */ 170 | nitems = 0; 171 | last_item = -1; 172 | rb_begin_left_right_walk(&tree, &lrw); 173 | while( (tmp = (TreeItem)rb_left_right_walk(&lrw)) ) 174 | { 175 | sscanf(tmp->data, "Item %08x", &i); 176 | 177 | assert(number_returned[i] == false); 178 | number_returned[i] = true; 179 | 180 | assert(last_item < i); 181 | last_item = i; 182 | 183 | nitems++; 184 | } 185 | assert(nitems == array_size); 186 | assert(last_item == (array_size-1)); 187 | 188 | /* free memory */ 189 | nitems = 0; 190 | while( (tmp = (TreeItem)rb_leftmost(&tree)) ) 191 | { 192 | rb_delete(&tree, (RBNode*)tmp); 193 | nitems++; 194 | } 195 | assert(nitems == array_size); 196 | } 197 | 198 | /* 199 | * Make sure right left walk enumirates all items, and any item is returned 200 | * only once. Also make sure right left walk returns item in revere sorted 201 | * order. 202 | */ 203 | static void 204 | right_left_walk_test() 205 | { 206 | RBTree tree; 207 | bool isNew; 208 | TreeItemData item; 209 | TreeItem tmp; 210 | RBTreeRightLeftWalk rlw; 211 | bool number_returned[UNIQUE_NUMBERS_ARRAY_SIZE]; 212 | int unique_numbers[UNIQUE_NUMBERS_ARRAY_SIZE]; 213 | int i, j, temp, nitems, last_item; 214 | int array_size = UNIQUE_NUMBERS_ARRAY_SIZE; 215 | 216 | #ifdef INIFNITE_TEST 217 | array_size = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 218 | #endif 219 | 220 | for(i = 0; i < array_size; i++) 221 | { 222 | unique_numbers[i] = i; 223 | number_returned[i] = false; 224 | } 225 | 226 | /* shuffle numbers */ 227 | for(i = 0; i < array_size; i++) 228 | { 229 | j = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 230 | assert((j >= 0) && (j < array_size)); 231 | temp = unique_numbers[i]; 232 | unique_numbers[i] = unique_numbers[j]; 233 | unique_numbers[j] = temp; 234 | } 235 | 236 | /* create an empty tree */ 237 | rb_create(&tree, sizeof(TreeItemData), tree_comparator, tree_combiner, tree_allocfunc, tree_freefunc, NULL); 238 | 239 | rb_begin_right_left_walk(&tree, &rlw); 240 | assert(rb_right_left_walk(&rlw) == NULL); 241 | 242 | /* fill a tree */ 243 | for(i = 0; i < array_size; i++) 244 | { 245 | sprintf(item.data, "Item %08x", unique_numbers[i]); 246 | rb_insert(&tree, (RBNode*)&item, &isNew); 247 | assert(isNew); 248 | } 249 | 250 | /* check enumiration */ 251 | nitems = 0; 252 | last_item = array_size; 253 | rb_begin_right_left_walk(&tree, &rlw); 254 | while( (tmp = (TreeItem)rb_right_left_walk(&rlw)) ) 255 | { 256 | sscanf(tmp->data, "Item %08x", &i); 257 | 258 | assert(number_returned[i] == false); 259 | number_returned[i] = true; 260 | 261 | assert(last_item > i); 262 | last_item = i; 263 | 264 | nitems++; 265 | } 266 | assert(nitems == array_size); 267 | assert(last_item == 0); 268 | 269 | /* free memory */ 270 | nitems = 0; 271 | while( (tmp = (TreeItem)rb_rightmost(&tree)) ) 272 | { 273 | rb_delete(&tree, (RBNode*)tmp); 274 | nitems++; 275 | } 276 | assert(nitems == array_size); 277 | } 278 | 279 | /* 280 | * Make sure direct walk enumirates all items, and any item is returned only 281 | * once 282 | */ 283 | static void 284 | direct_walk_test() 285 | { 286 | RBTree tree; 287 | bool isNew; 288 | TreeItemData item; 289 | TreeItem tmp; 290 | RBTreeDirectWalk dw; 291 | bool number_returned[UNIQUE_NUMBERS_ARRAY_SIZE]; 292 | int unique_numbers[UNIQUE_NUMBERS_ARRAY_SIZE]; 293 | int i, j, temp, nitems; 294 | int array_size = UNIQUE_NUMBERS_ARRAY_SIZE; 295 | 296 | #ifdef INIFNITE_TEST 297 | array_size = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 298 | #endif 299 | 300 | for(i = 0; i < array_size; i++) 301 | { 302 | unique_numbers[i] = i; 303 | number_returned[i] = false; 304 | } 305 | 306 | /* shuffle numbers */ 307 | for(i = 0; i < array_size; i++) 308 | { 309 | j = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 310 | assert((j >= 0) && (j < array_size)); 311 | temp = unique_numbers[i]; 312 | unique_numbers[i] = unique_numbers[j]; 313 | unique_numbers[j] = temp; 314 | } 315 | 316 | /* create an empty tree */ 317 | rb_create(&tree, sizeof(TreeItemData), tree_comparator, tree_combiner, tree_allocfunc, tree_freefunc, NULL); 318 | 319 | rb_begin_direct_walk(&tree, &dw); 320 | assert(rb_direct_walk(&dw) == NULL); 321 | 322 | /* fill a tree */ 323 | for(i = 0; i < array_size; i++) 324 | { 325 | sprintf(item.data, "Item %08x", unique_numbers[i]); 326 | rb_insert(&tree, (RBNode*)&item, &isNew); 327 | assert(isNew); 328 | } 329 | 330 | /* check enumiration */ 331 | nitems = 0; 332 | rb_begin_direct_walk(&tree, &dw); 333 | while( (tmp = (TreeItem)rb_direct_walk(&dw)) ) 334 | { 335 | sscanf(tmp->data, "Item %08x", &i); 336 | assert(number_returned[i] == false); 337 | number_returned[i] = true; 338 | nitems++; 339 | } 340 | assert(nitems == array_size); 341 | 342 | /* free memory */ 343 | nitems = 0; 344 | while( (tmp = (TreeItem)rb_leftmost(&tree)) ) 345 | { 346 | rb_delete(&tree, (RBNode*)tmp); 347 | nitems++; 348 | } 349 | assert(nitems == array_size); 350 | } 351 | 352 | /* 353 | * Make sure inverted walk enumirates all items, and any item is returned only 354 | * once 355 | */ 356 | static void 357 | inverted_walk_test() 358 | { 359 | RBTree tree; 360 | bool isNew; 361 | TreeItemData item; 362 | TreeItem tmp; 363 | RBTreeInvertedWalk iw; 364 | bool number_returned[UNIQUE_NUMBERS_ARRAY_SIZE]; 365 | int unique_numbers[UNIQUE_NUMBERS_ARRAY_SIZE]; 366 | int i, j, temp, nitems; 367 | int array_size = UNIQUE_NUMBERS_ARRAY_SIZE; 368 | 369 | #ifdef INIFNITE_TEST 370 | array_size = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 371 | #endif 372 | 373 | for(i = 0; i < array_size; i++) 374 | { 375 | unique_numbers[i] = i; 376 | number_returned[i] = false; 377 | } 378 | 379 | /* shuffle numbers */ 380 | for(i = 0; i < array_size; i++) 381 | { 382 | j = (int)((((double)rand()) / ((double)RAND_MAX+1.0)) * array_size); 383 | assert((j >= 0) && (j < array_size)); 384 | temp = unique_numbers[i]; 385 | unique_numbers[i] = unique_numbers[j]; 386 | unique_numbers[j] = temp; 387 | } 388 | 389 | /* create an empty tree */ 390 | rb_create(&tree, sizeof(TreeItemData), tree_comparator, tree_combiner, tree_allocfunc, tree_freefunc, NULL); 391 | 392 | rb_begin_inverted_walk(&tree, &iw); 393 | assert(rb_inverted_walk(&iw) == NULL); 394 | 395 | /* fill a tree */ 396 | for(i = 0; i < array_size; i++) 397 | { 398 | sprintf(item.data, "Item %08x", unique_numbers[i]); 399 | rb_insert(&tree, (RBNode*)&item, &isNew); 400 | assert(isNew); 401 | } 402 | 403 | /* check enumiration */ 404 | nitems = 0; 405 | rb_begin_inverted_walk(&tree, &iw); 406 | while( (tmp = (TreeItem)rb_inverted_walk(&iw)) ) 407 | { 408 | sscanf(tmp->data, "Item %08x", &i); 409 | assert(number_returned[i] == false); 410 | number_returned[i] = true; 411 | nitems++; 412 | } 413 | assert(nitems == array_size); 414 | 415 | /* free memory */ 416 | nitems = 0; 417 | while( (tmp = (TreeItem)rb_rightmost(&tree)) ) 418 | { 419 | rb_delete(&tree, (RBNode*)tmp); 420 | nitems++; 421 | } 422 | assert(nitems == array_size); 423 | } 424 | 425 | static void 426 | run_tests() 427 | { 428 | general_test(); 429 | left_right_walk_test(); 430 | right_left_walk_test(); 431 | direct_walk_test(); 432 | inverted_walk_test(); 433 | } 434 | 435 | int main() 436 | { 437 | /* 438 | struct timeval tv; 439 | gettimeofday(&tv, NULL); 440 | srand(tv.tv_sec ^ tv.tv_usec); 441 | */ 442 | 443 | srand(0); 444 | 445 | #ifdef INIFNITE_TEST 446 | { 447 | int i = 0; 448 | for(;;) { 449 | run_tests(); 450 | i++; 451 | printf("Tests passed: %d\n", i); 452 | } 453 | } 454 | #else 455 | run_tests(); 456 | #endif 457 | 458 | return 0; 459 | } 460 | 461 | 462 | -------------------------------------------------------------------------------- /test/struct/test_slist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "struct/ilist.h" 6 | 7 | typedef struct 8 | { 9 | slist_node node; 10 | char data[128]; 11 | } ListItemData; 12 | 13 | typedef ListItemData *ListItem; 14 | 15 | int main() 16 | { 17 | slist_iter iter; 18 | ListItemData item1, item2, item3; 19 | ListItem tmp; 20 | char temp_buff[512]; 21 | 22 | slist_head head; 23 | slist_init(&head); 24 | assert(slist_is_empty(&head)); 25 | 26 | strcpy(item1.data, "first item"); 27 | strcpy(item2.data, "second item"); 28 | strcpy(item3.data, "third item"); 29 | 30 | slist_push_head(&head, (slist_node*)&item1); 31 | assert(!slist_is_empty(&head)); 32 | 33 | slist_push_head(&head, (slist_node*)&item2); 34 | slist_push_head(&head, (slist_node*)&item3); 35 | 36 | temp_buff[0] = 0; 37 | slist_foreach(iter, &head) 38 | { 39 | tmp = (ListItem) iter.cur; 40 | strcat(temp_buff, tmp->data); 41 | strcat(temp_buff, ","); 42 | } 43 | assert(strcmp(temp_buff, "third item,second item,first item,") == 0); 44 | 45 | tmp = (ListItem) slist_pop_head_node(&head); 46 | assert(strcmp(tmp->data, "third item") == 0); 47 | 48 | temp_buff[0] = 0; 49 | slist_foreach(iter, &head) 50 | { 51 | tmp = (ListItem) iter.cur; 52 | strcat(temp_buff, tmp->data); 53 | strcat(temp_buff, ","); 54 | } 55 | assert(strcmp(temp_buff, "second item,first item,") == 0); 56 | 57 | return 0; 58 | } 59 | --------------------------------------------------------------------------------