├── .gitmodules ├── ldid2 ├── .gitignore ├── version.sh ├── control.sh ├── control ├── ios.sh ├── make_ldid.sh ├── make_ldid2.sh ├── README.md ├── arid.cpp ├── sha-private.h ├── sha1.h ├── minimal ├── string.h ├── mapping.h ├── hexdump.h ├── sqlite3.h └── stdlib.h ├── sha1.c ├── lookup2.c ├── sha.h ├── sha224-256.c ├── COPYING ├── ldid.cpp └── ldid2.cpp /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ldid2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GaryniL/ldid/HEAD/ldid2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ldid 2 | ldid.arm 3 | ldid.o 4 | ldid.deb 5 | debs 6 | _ 7 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "$(git describe --tags --dirty="+" --match="v*" | sed -e 's@-\([^-]*\)-\([^-]*\)$@+\1.\2@;s@^v@1:@')" 3 | -------------------------------------------------------------------------------- /control.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dir=$1 3 | dir=${dir:=_} 4 | sed -e "s@^\(Version:.*\)@\1$(./version.sh)@" control 5 | echo "Installed-Size: $(du -s "${dir}" | cut -f 1)" 6 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: ldid 2 | Priority: optional 3 | Section: Development 4 | Maintainer: Jay Freeman (saurik) 5 | Architecture: iphoneos-arm 6 | Version: 7 | Description: pseudo-codesign Mach-O files 8 | Name: Link Identity Editor 9 | Author: Jay Freeman (saurik) 10 | Depiction: http://cydia.saurik.com/info/ldid/ 11 | Tag: purpose::console, role::developer 12 | -------------------------------------------------------------------------------- /ios.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e -x 4 | 5 | sudo xcode-select --switch /Applications/Xcode-4.6.3.app 6 | cycc -i2.0 -oldid.arm -- -c -std=c++11 ldid.cpp -I. 7 | cycc -i2.0 -oldid.arm -- ldid.arm -x c sha1.c lookup2.c -I . 8 | 9 | rm -rf _ 10 | mkdir -p _/usr/bin 11 | cp -a ldid.arm _/usr/bin/ldid 12 | mkdir -p _/DEBIAN 13 | ./control.sh _ >_/DEBIAN/control 14 | mkdir -p debs 15 | ln -sf debs/ldid_$(./version.sh)_iphoneos-arm.deb ldid.deb 16 | dpkg-deb -b _ ldid.deb 17 | readlink ldid.deb 18 | -------------------------------------------------------------------------------- /make_ldid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | sudo xcode-select --switch /Applications/Xcode.app 6 | 7 | if which xcrun &>/dev/null; then 8 | flags=(xcrun -sdk macosx g++) 9 | flags+=(-mmacosx-version-min=10.4) 10 | 11 | for arch in i386 x86_64; do 12 | flags+=(-arch "${arch}") 13 | done 14 | else 15 | flags=(g++) 16 | fi 17 | 18 | flags+=(-I.) 19 | 20 | set -x 21 | "${flags[@]}" -c -std=c++11 -o ldid.o ldid.cpp 22 | "${flags[@]}" -o ldid ldid.o -x c lookup2.c -x c sha1.c 23 | -------------------------------------------------------------------------------- /make_ldid2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | sudo xcode-select --switch /Applications/Xcode.app 6 | 7 | if which xcrun &>/dev/null; then 8 | flags=(xcrun -sdk macosx g++) 9 | flags+=(-mmacosx-version-min=10.9) 10 | 11 | for arch in i386 x86_64; do 12 | flags+=(-arch "${arch}") 13 | done 14 | else 15 | flags=(g++) 16 | fi 17 | 18 | flags+=(-I.) 19 | 20 | set -x 21 | "${flags[@]}" -c -std=c++11 -o ldid.o ldid2.cpp 22 | "${flags[@]}" -o ldid2 ldid.o -x c lookup2.c -x c sha1.c sha224-256.c 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ldid 2 | ldid is a tool made by saurik for modifying a binary's entitlements easily. 3 | This repo is a fork of ldid / ldid2 (with SHA256 supported from [xerub](https://github.com/xerub/ldid)) from saurik git repository git://git.saurik.com/ldid.git 4 | 5 | # Compile 6 | ```./make_ldid.sh``` 7 | or 8 | ```./make_ldid2.sh``` 9 | # Usage 10 | You ca download build version of ldid in [release page](https://github.com/GaryniL/ldid/releases). 11 | Put [ldid](https://github.com/GaryniL/ldid/releases/tag/0.1-1) or [ldid2](https://github.com/GaryniL/ldid/releases/tag/0.1-2) to /usr/bin/, then it works! 12 | For futher usage, find it on [iPhoneDevWiki](http://iphonedevwiki.net/index.php/Ldid) 13 | -------------------------------------------------------------------------------- /arid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "minimal/mapping.h" 4 | 5 | struct ar_hdr { 6 | char ar_name[16]; 7 | char ar_date[12]; 8 | char ar_uid[6]; 9 | char ar_gid[6]; 10 | char ar_mode[8]; 11 | char ar_size[10]; 12 | #define ARFMAG "`\n" 13 | char ar_fmag[2]; 14 | }; 15 | 16 | int main(int argc, char *argv[]) { 17 | size_t size; 18 | _assert(argc == 2); 19 | uint8_t *data = reinterpret_cast(map(argv[1], 0, _not(size_t), &size, false)); 20 | data += 8; 21 | uint8_t *end = data + size; 22 | while (end - data >= sizeof(struct ar_hdr)) { 23 | struct ar_hdr *head = reinterpret_cast(data); 24 | memset(head->ar_date + 1, ' ', sizeof(head->ar_date) - 1); 25 | head->ar_date[0] = '0'; 26 | size_t length = strtoul(head->ar_size, NULL, 10); 27 | data += length + sizeof(struct ar_hdr); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /sha-private.h: -------------------------------------------------------------------------------- 1 | /************************ sha-private.h ************************/ 2 | /***************** See RFC 6234 for details. *******************/ 3 | #ifndef _SHA_PRIVATE__H 4 | #define _SHA_PRIVATE__H 5 | /* 6 | * These definitions are defined in FIPS 180-3, section 4.1. 7 | * Ch() and Maj() are defined identically in sections 4.1.1, 8 | * 4.1.2, and 4.1.3. 9 | * 10 | * The definitions used in FIPS 180-3 are as follows: 11 | */ 12 | 13 | #ifndef USE_MODIFIED_MACROS 14 | #define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 15 | #define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 16 | #else /* USE_MODIFIED_MACROS */ 17 | /* 18 | * The following definitions are equivalent and potentially faster. 19 | */ 20 | 21 | #define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z)) 22 | #define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) 23 | 24 | #endif /* USE_MODIFIED_MACROS */ 25 | 26 | #define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z)) 27 | 28 | #endif /* _SHA_PRIVATE__H */ 29 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sha1.h 3 | * 4 | * Description: 5 | * This is the header file for code which implements the Secure 6 | * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published 7 | * April 17, 1995. 8 | * 9 | * Many of the variable names in this code, especially the 10 | * single character names, were used because those were the names 11 | * used in the publication. 12 | * 13 | * Please read the file sha1.c for more information. 14 | * 15 | */ 16 | 17 | #ifndef _SHA1_H_ 18 | #define _SHA1_H_ 19 | 20 | #include 21 | 22 | #ifndef _SHA_enum_ 23 | #define _SHA_enum_ 24 | enum 25 | { 26 | shaSuccess = 0, 27 | shaNull, /* Null pointer parameter */ 28 | shaInputTooLong, /* input data too long */ 29 | shaStateError /* called Input after Result */ 30 | }; 31 | #endif 32 | #define SHA1HashSize 20 33 | 34 | /* 35 | * This structure will hold context information for the SHA-1 36 | * hashing operation 37 | */ 38 | typedef struct SHA1Context 39 | { 40 | uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ 41 | 42 | uint32_t Length_Low; /* Message length in bits */ 43 | uint32_t Length_High; /* Message length in bits */ 44 | 45 | /* Index into message block array */ 46 | int_least16_t Message_Block_Index; 47 | uint8_t Message_Block[64]; /* 512-bit message blocks */ 48 | 49 | int Computed; /* Is the digest computed? */ 50 | int Corrupted; /* Is the message digest corrupted? */ 51 | } SHA1Context; 52 | 53 | /* 54 | * Function Prototypes 55 | */ 56 | 57 | int SHA1Reset( SHA1Context *); 58 | int SHA1Input( SHA1Context *, 59 | const uint8_t *, 60 | unsigned int); 61 | int SHA1Result( SHA1Context *, 62 | uint8_t Message_Digest[SHA1HashSize]); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /minimal/string.h: -------------------------------------------------------------------------------- 1 | /* Minimal - the simplest thing that could possibly work 2 | * Copyright (C) 2007 Jay Freeman (saurik) 3 | */ 4 | 5 | /* 6 | * Redistribution and use in source and binary 7 | * forms, with or without modification, are permitted 8 | * provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the 11 | * above copyright notice, this list of conditions 12 | * and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the 14 | * above copyright notice, this list of conditions 15 | * and the following disclaimer in the documentation 16 | * and/or other materials provided with the 17 | * distribution. 18 | * 3. The name of the author may not be used to endorse 19 | * or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef MINIMAL_STRING_H 39 | #define MINIMAL_STRING_H 40 | 41 | #include 42 | 43 | _disused static char *strndup_(const char *src, int len) { 44 | char *dst = (char *) malloc(len + 1); 45 | _assert(dst != NULL); 46 | strncpy(dst, src, len); 47 | dst[len] = '\0'; 48 | return dst; 49 | } 50 | 51 | #endif/*MINIMAL_STRING_H*/ 52 | -------------------------------------------------------------------------------- /minimal/mapping.h: -------------------------------------------------------------------------------- 1 | /* Minimal - the simplest thing that could possibly work 2 | * Copyright (C) 2007 Jay Freeman (saurik) 3 | */ 4 | 5 | /* 6 | * Redistribution and use in source and binary 7 | * forms, with or without modification, are permitted 8 | * provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the 11 | * above copyright notice, this list of conditions 12 | * and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the 14 | * above copyright notice, this list of conditions 15 | * and the following disclaimer in the documentation 16 | * and/or other materials provided with the 17 | * distribution. 18 | * 3. The name of the author may not be used to endorse 19 | * or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef MINIMAL_MAPPING_H 39 | #define MINIMAL_MAPPING_H 40 | 41 | #include 42 | 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | 50 | #include "minimal/stdlib.h" 51 | 52 | void *map(const char *path, size_t offset, size_t size, size_t *psize, bool ro) { 53 | int fd; 54 | _syscall(fd = open(path, ro ? O_RDONLY : O_RDWR)); 55 | 56 | if (size == _not(size_t)) { 57 | struct stat stat; 58 | _syscall(fstat(fd, &stat)); 59 | size = stat.st_size; 60 | } 61 | 62 | if (psize != NULL) 63 | *psize = size; 64 | 65 | void *base; 66 | _syscall(base = mmap(NULL, size, ro ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)); 67 | 68 | _syscall(close(fd)); 69 | return base; 70 | } 71 | 72 | #endif/*MINIMAL_MAPPING_H*/ 73 | -------------------------------------------------------------------------------- /minimal/hexdump.h: -------------------------------------------------------------------------------- 1 | /* Minimal - the simplest thing that could possibly work 2 | * Copyright (C) 2007 Jay Freeman (saurik) 3 | */ 4 | 5 | /* 6 | * Redistribution and use in source and binary 7 | * forms, with or without modification, are permitted 8 | * provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the 11 | * above copyright notice, this list of conditions 12 | * and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the 14 | * above copyright notice, this list of conditions 15 | * and the following disclaimer in the documentation 16 | * and/or other materials provided with the 17 | * distribution. 18 | * 3. The name of the author may not be used to endorse 19 | * or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef MINIMAL_HEXDUMP_H 39 | #define MINIMAL_HEXDUMP_H 40 | 41 | #include "minimal/stdlib.h" 42 | 43 | _disused static char hexchar(uint8_t value) { 44 | return value < 0x20 || value >= 0x80 ? '.' : value; 45 | } 46 | 47 | #define HexWidth_ 12 48 | 49 | _disused static void hexdump(const char *mark, const uint8_t *data, size_t size) { 50 | size_t i = 0, j; 51 | 52 | while (i != size) { 53 | if (i % HexWidth_ == 0) 54 | printf("[%s] 0x%.3zx:", mark, i); 55 | 56 | printf(" %.2x", data[i]); 57 | 58 | if (++i % HexWidth_ == 0) { 59 | printf(" "); 60 | for (j = i - HexWidth_; j != i; ++j) 61 | printf("%c", hexchar(data[j])); 62 | printf("\n"); 63 | } 64 | } 65 | 66 | if (i % HexWidth_ != 0) { 67 | for (j = i % HexWidth_; j != HexWidth_; ++j) 68 | printf(" "); 69 | printf(" "); 70 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j) 71 | printf("%c", hexchar(data[j])); 72 | printf("\n"); 73 | } 74 | } 75 | 76 | #endif/*MINIMAL_HEXDUMP_H*/ -------------------------------------------------------------------------------- /minimal/sqlite3.h: -------------------------------------------------------------------------------- 1 | /* Minimal - the simplest thing that could possibly work 2 | * Copyright (C) 2007 Jay Freeman (saurik) 3 | */ 4 | 5 | /* 6 | * Redistribution and use in source and binary 7 | * forms, with or without modification, are permitted 8 | * provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the 11 | * above copyright notice, this list of conditions 12 | * and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the 14 | * above copyright notice, this list of conditions 15 | * and the following disclaimer in the documentation 16 | * and/or other materials provided with the 17 | * distribution. 18 | * 3. The name of the author may not be used to endorse 19 | * or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef MINIMAL_SQLITE3_H 39 | #define MINIMAL_SQLITE3_H 40 | 41 | #include 42 | #include 43 | 44 | #define _sqlcall(expr) ({ \ 45 | __typeof__(expr) _value = (expr); \ 46 | if (_value != 0 && (_value < 100 || _value >= 200)) \ 47 | _assert(false, "_sqlcall(%u:%s): %s\n", _value, #expr, sqlite3_errmsg(database_)); \ 48 | _value; \ 49 | }) 50 | 51 | int sqlite3_bind_string(sqlite3_stmt *stmt, int n, const char *value) { 52 | if (value == NULL) 53 | return sqlite3_bind_null(stmt, n); 54 | else 55 | return sqlite3_bind_text(stmt, n, strdup(value), -1, &free); 56 | } 57 | 58 | int sqlite3_bind_boolean(sqlite3_stmt *stmt, int n, bool value) { 59 | return sqlite3_bind_int(stmt, n, value ? 1 : 0); 60 | } 61 | 62 | char *sqlite3_column_string(sqlite3_stmt *stmt, int n) { 63 | const unsigned char *value = sqlite3_column_text(stmt, n); 64 | return value == NULL ? NULL : strdup((const char *) value); 65 | } 66 | 67 | bool sqlite3_column_boolean(sqlite3_stmt *stmt, int n) { 68 | return sqlite3_column_int(stmt, n) != 0; 69 | } 70 | 71 | #endif/*MINIMAL_SQLITE3_H*/ 72 | -------------------------------------------------------------------------------- /minimal/stdlib.h: -------------------------------------------------------------------------------- 1 | /* Minimal - the simplest thing that could possibly work 2 | * Copyright (C) 2007 Jay Freeman (saurik) 3 | */ 4 | 5 | /* 6 | * Redistribution and use in source and binary 7 | * forms, with or without modification, are permitted 8 | * provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the 11 | * above copyright notice, this list of conditions 12 | * and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the 14 | * above copyright notice, this list of conditions 15 | * and the following disclaimer in the documentation 16 | * and/or other materials provided with the 17 | * distribution. 18 | * 3. The name of the author may not be used to endorse 19 | * or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef MINIMAL_STDLIB_H 39 | #define MINIMAL_STDLIB_H 40 | 41 | #ifdef __i386__ 42 | #define _breakpoint() \ 43 | __asm__ ("int $0x03") 44 | #else 45 | #define _breakpoint() 46 | #endif 47 | 48 | #ifdef __cplusplus 49 | #define _assert___(line) \ 50 | #line 51 | #define _assert__(line) \ 52 | _assert___(line) 53 | #define _assert_(e) \ 54 | throw __FILE__ "(" _assert__(__LINE__) "): _assert(" e ")" 55 | #else 56 | #define _assert_(e) \ 57 | exit(1) 58 | #endif 59 | 60 | #define _assert(expr) \ 61 | do if (!(expr)) { \ 62 | fprintf(stderr, "%s(%u): _assert(%s); errno=%u\n", __FILE__, __LINE__, #expr, errno); \ 63 | _breakpoint(); \ 64 | _assert_(#expr); \ 65 | } while (false) 66 | 67 | #define _syscall(expr) ({ \ 68 | __typeof__(expr) _value; \ 69 | do if ((long) (_value = (expr)) != -1) \ 70 | break; \ 71 | else switch (errno) { \ 72 | case EINTR: \ 73 | continue; \ 74 | default: \ 75 | _assert(false); \ 76 | } while (true); \ 77 | _value; \ 78 | }) 79 | 80 | #define _aprcall(expr) \ 81 | do { \ 82 | apr_status_t _aprstatus((expr)); \ 83 | _assert(_aprstatus == APR_SUCCESS); \ 84 | } while (false) 85 | 86 | #define _forever \ 87 | for (;;) 88 | 89 | #define _trace() \ 90 | fprintf(stderr, "_trace(%s:%u): %s\n", __FILE__, __LINE__, __FUNCTION__) 91 | 92 | #define _not(type) \ 93 | ((type) ~ (type) 0) 94 | 95 | #define _finline \ 96 | inline __attribute__((always_inline)) 97 | #define _disused \ 98 | __attribute__((unused)) 99 | 100 | #define _label__(x) _label ## x 101 | #define _label_(y) _label__(y) 102 | #define _label _label_(__LINE__) 103 | 104 | #define _packed \ 105 | __attribute__((packed)) 106 | 107 | #ifdef __cplusplus 108 | 109 | template 110 | struct Iterator_ { 111 | typedef typename Type_::const_iterator Result; 112 | }; 113 | 114 | #define _foreach(item, list) \ 115 | for (bool _stop(true); _stop; ) \ 116 | for (const __typeof__(list) &_list = (list); _stop; _stop = false) \ 117 | for (Iterator_<__typeof__(list)>::Result _item = _list.begin(); _item != _list.end(); ++_item) \ 118 | for (bool _suck(true); _suck; _suck = false) \ 119 | for (const __typeof__(*_item) &item = *_item; _suck; _suck = false) 120 | 121 | #endif 122 | 123 | #include 124 | #include 125 | #include 126 | #include 127 | #include 128 | 129 | #endif/*MINIMAL_STDLIB_H*/ 130 | -------------------------------------------------------------------------------- /sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sha1.c 3 | * 4 | * Description: 5 | * This file implements the Secure Hashing Algorithm 1 as 6 | * defined in FIPS PUB 180-1 published April 17, 1995. 7 | * 8 | * The SHA-1, produces a 160-bit message digest for a given 9 | * data stream. It should take about 2**n steps to find a 10 | * message with the same digest as a given message and 11 | * 2**(n/2) to find any two messages with the same digest, 12 | * when n is the digest size in bits. Therefore, this 13 | * algorithm can serve as a means of providing a 14 | * "fingerprint" for a message. 15 | * 16 | * Portability Issues: 17 | * SHA-1 is defined in terms of 32-bit "words". This code 18 | * uses (included via "sha1.h" to define 32 and 8 19 | * bit unsigned integer types. If your C compiler does not 20 | * support 32 bit unsigned integers, this code is not 21 | * appropriate. 22 | * 23 | * Caveats: 24 | * SHA-1 is designed to work with messages less than 2^64 bits 25 | * long. Although SHA-1 allows a message digest to be generated 26 | * for messages of any number of bits less than 2^64, this 27 | * implementation only works with messages with a length that is 28 | * a multiple of the size of an 8-bit character. 29 | * 30 | */ 31 | 32 | #include "sha1.h" 33 | 34 | /* 35 | * Define the SHA1 circular left shift macro 36 | */ 37 | #define SHA1CircularShift(bits,word) \ 38 | (((word) << (bits)) | ((word) >> (32-(bits)))) 39 | 40 | /* Local Function Prototyptes */ 41 | void SHA1PadMessage(SHA1Context *); 42 | void SHA1ProcessMessageBlock(SHA1Context *); 43 | 44 | /* 45 | * SHA1Reset 46 | * 47 | * Description: 48 | * This function will initialize the SHA1Context in preparation 49 | * for computing a new SHA1 message digest. 50 | * 51 | * Parameters: 52 | * context: [in/out] 53 | * The context to reset. 54 | * 55 | * Returns: 56 | * sha Error Code. 57 | * 58 | */ 59 | int SHA1Reset(SHA1Context *context) 60 | { 61 | if (!context) 62 | { 63 | return shaNull; 64 | } 65 | 66 | context->Length_Low = 0; 67 | context->Length_High = 0; 68 | context->Message_Block_Index = 0; 69 | 70 | context->Intermediate_Hash[0] = 0x67452301; 71 | context->Intermediate_Hash[1] = 0xEFCDAB89; 72 | context->Intermediate_Hash[2] = 0x98BADCFE; 73 | context->Intermediate_Hash[3] = 0x10325476; 74 | context->Intermediate_Hash[4] = 0xC3D2E1F0; 75 | 76 | context->Computed = 0; 77 | context->Corrupted = 0; 78 | 79 | return shaSuccess; 80 | } 81 | 82 | /* 83 | * SHA1Result 84 | * 85 | * Description: 86 | * This function will return the 160-bit message digest into the 87 | * Message_Digest array provided by the caller. 88 | * NOTE: The first octet of hash is stored in the 0th element, 89 | * the last octet of hash in the 19th element. 90 | * 91 | * Parameters: 92 | * context: [in/out] 93 | * The context to use to calculate the SHA-1 hash. 94 | * Message_Digest: [out] 95 | * Where the digest is returned. 96 | * 97 | * Returns: 98 | * sha Error Code. 99 | * 100 | */ 101 | int SHA1Result( SHA1Context *context, 102 | uint8_t Message_Digest[SHA1HashSize]) 103 | { 104 | int i; 105 | 106 | if (!context || !Message_Digest) 107 | { 108 | return shaNull; 109 | } 110 | 111 | if (context->Corrupted) 112 | { 113 | return context->Corrupted; 114 | } 115 | 116 | if (!context->Computed) 117 | { 118 | SHA1PadMessage(context); 119 | for(i=0; i<64; ++i) 120 | { 121 | /* message may be sensitive, clear it out */ 122 | context->Message_Block[i] = 0; 123 | } 124 | context->Length_Low = 0; /* and clear length */ 125 | context->Length_High = 0; 126 | context->Computed = 1; 127 | 128 | } 129 | 130 | for(i = 0; i < SHA1HashSize; ++i) 131 | { 132 | Message_Digest[i] = context->Intermediate_Hash[i>>2] 133 | >> 8 * ( 3 - ( i & 0x03 ) ); 134 | } 135 | 136 | return shaSuccess; 137 | } 138 | 139 | /* 140 | * SHA1Input 141 | * 142 | * Description: 143 | * This function accepts an array of octets as the next portion 144 | * of the message. 145 | * 146 | * Parameters: 147 | * context: [in/out] 148 | * The SHA context to update 149 | * message_array: [in] 150 | * An array of characters representing the next portion of 151 | * the message. 152 | * length: [in] 153 | * The length of the message in message_array 154 | * 155 | * Returns: 156 | * sha Error Code. 157 | * 158 | */ 159 | int SHA1Input( SHA1Context *context, 160 | const uint8_t *message_array, 161 | unsigned length) 162 | { 163 | if (!length) 164 | { 165 | return shaSuccess; 166 | } 167 | 168 | if (!context || !message_array) 169 | { 170 | return shaNull; 171 | } 172 | 173 | if (context->Computed) 174 | { 175 | context->Corrupted = shaStateError; 176 | 177 | return shaStateError; 178 | } 179 | 180 | if (context->Corrupted) 181 | { 182 | return context->Corrupted; 183 | } 184 | while(length-- && !context->Corrupted) 185 | { 186 | context->Message_Block[context->Message_Block_Index++] = 187 | (*message_array & 0xFF); 188 | 189 | context->Length_Low += 8; 190 | if (context->Length_Low == 0) 191 | { 192 | context->Length_High++; 193 | if (context->Length_High == 0) 194 | { 195 | /* Message is too long */ 196 | context->Corrupted = 1; 197 | } 198 | } 199 | 200 | if (context->Message_Block_Index == 64) 201 | { 202 | SHA1ProcessMessageBlock(context); 203 | } 204 | 205 | message_array++; 206 | } 207 | 208 | return shaSuccess; 209 | } 210 | 211 | /* 212 | * SHA1ProcessMessageBlock 213 | * 214 | * Description: 215 | * This function will process the next 512 bits of the message 216 | * stored in the Message_Block array. 217 | * 218 | * Parameters: 219 | * None. 220 | * 221 | * Returns: 222 | * Nothing. 223 | * 224 | * Comments: 225 | 226 | * Many of the variable names in this code, especially the 227 | * single character names, were used because those were the 228 | * names used in the publication. 229 | * 230 | * 231 | */ 232 | void SHA1ProcessMessageBlock(SHA1Context *context) 233 | { 234 | const uint32_t K[] = { /* Constants defined in SHA-1 */ 235 | 0x5A827999, 236 | 0x6ED9EBA1, 237 | 0x8F1BBCDC, 238 | 0xCA62C1D6 239 | }; 240 | int t; /* Loop counter */ 241 | uint32_t temp; /* Temporary word value */ 242 | uint32_t W[80]; /* Word sequence */ 243 | uint32_t A, B, C, D, E; /* Word buffers */ 244 | 245 | /* 246 | * Initialize the first 16 words in the array W 247 | */ 248 | for(t = 0; t < 16; t++) 249 | { 250 | W[t] = context->Message_Block[t * 4] << 24; 251 | W[t] |= context->Message_Block[t * 4 + 1] << 16; 252 | W[t] |= context->Message_Block[t * 4 + 2] << 8; 253 | W[t] |= context->Message_Block[t * 4 + 3]; 254 | } 255 | 256 | for(t = 16; t < 80; t++) 257 | { 258 | W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 259 | } 260 | 261 | A = context->Intermediate_Hash[0]; 262 | B = context->Intermediate_Hash[1]; 263 | C = context->Intermediate_Hash[2]; 264 | D = context->Intermediate_Hash[3]; 265 | E = context->Intermediate_Hash[4]; 266 | 267 | for(t = 0; t < 20; t++) 268 | { 269 | temp = SHA1CircularShift(5,A) + 270 | ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 271 | E = D; 272 | D = C; 273 | C = SHA1CircularShift(30,B); 274 | 275 | B = A; 276 | A = temp; 277 | } 278 | 279 | for(t = 20; t < 40; t++) 280 | { 281 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 282 | E = D; 283 | D = C; 284 | C = SHA1CircularShift(30,B); 285 | B = A; 286 | A = temp; 287 | } 288 | 289 | for(t = 40; t < 60; t++) 290 | { 291 | temp = SHA1CircularShift(5,A) + 292 | ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 293 | E = D; 294 | D = C; 295 | C = SHA1CircularShift(30,B); 296 | B = A; 297 | A = temp; 298 | } 299 | 300 | for(t = 60; t < 80; t++) 301 | { 302 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 303 | E = D; 304 | D = C; 305 | C = SHA1CircularShift(30,B); 306 | B = A; 307 | A = temp; 308 | } 309 | 310 | context->Intermediate_Hash[0] += A; 311 | context->Intermediate_Hash[1] += B; 312 | context->Intermediate_Hash[2] += C; 313 | context->Intermediate_Hash[3] += D; 314 | context->Intermediate_Hash[4] += E; 315 | 316 | context->Message_Block_Index = 0; 317 | } 318 | 319 | /* 320 | * SHA1PadMessage 321 | * 322 | 323 | * Description: 324 | * According to the standard, the message must be padded to an even 325 | * 512 bits. The first padding bit must be a '1'. The last 64 326 | * bits represent the length of the original message. All bits in 327 | * between should be 0. This function will pad the message 328 | * according to those rules by filling the Message_Block array 329 | * accordingly. It will also call the ProcessMessageBlock function 330 | * provided appropriately. When it returns, it can be assumed that 331 | * the message digest has been computed. 332 | * 333 | * Parameters: 334 | * context: [in/out] 335 | * The context to pad 336 | * ProcessMessageBlock: [in] 337 | * The appropriate SHA*ProcessMessageBlock function 338 | * Returns: 339 | * Nothing. 340 | * 341 | */ 342 | 343 | void SHA1PadMessage(SHA1Context *context) 344 | { 345 | /* 346 | * Check to see if the current message block is too small to hold 347 | * the initial padding bits and length. If so, we will pad the 348 | * block, process it, and then continue padding into a second 349 | * block. 350 | */ 351 | if (context->Message_Block_Index > 55) 352 | { 353 | context->Message_Block[context->Message_Block_Index++] = 0x80; 354 | while(context->Message_Block_Index < 64) 355 | { 356 | context->Message_Block[context->Message_Block_Index++] = 0; 357 | } 358 | 359 | SHA1ProcessMessageBlock(context); 360 | 361 | while(context->Message_Block_Index < 56) 362 | { 363 | context->Message_Block[context->Message_Block_Index++] = 0; 364 | } 365 | } 366 | else 367 | { 368 | context->Message_Block[context->Message_Block_Index++] = 0x80; 369 | while(context->Message_Block_Index < 56) 370 | { 371 | 372 | context->Message_Block[context->Message_Block_Index++] = 0; 373 | } 374 | } 375 | 376 | /* 377 | * Store the message length as the last 8 octets 378 | */ 379 | context->Message_Block[56] = context->Length_High >> 24; 380 | context->Message_Block[57] = context->Length_High >> 16; 381 | context->Message_Block[58] = context->Length_High >> 8; 382 | context->Message_Block[59] = context->Length_High; 383 | context->Message_Block[60] = context->Length_Low >> 24; 384 | context->Message_Block[61] = context->Length_Low >> 16; 385 | context->Message_Block[62] = context->Length_Low >> 8; 386 | context->Message_Block[63] = context->Length_Low; 387 | 388 | SHA1ProcessMessageBlock(context); 389 | } 390 | -------------------------------------------------------------------------------- /lookup2.c: -------------------------------------------------------------------------------- 1 | /* 2 | -------------------------------------------------------------------- 3 | lookup2.c, by Bob Jenkins, December 1996, Public Domain. 4 | hash(), hash2(), hash3, and mix() are externally useful functions. 5 | Routines to test the hash are included if SELF_TEST is defined. 6 | You can use this free for any purpose. It has no warranty. 7 | -------------------------------------------------------------------- 8 | */ 9 | #include 10 | #include 11 | #include 12 | typedef unsigned long int ub4; /* unsigned 4-byte quantities */ 13 | typedef unsigned char ub1; 14 | 15 | #define hashsize(n) ((ub4)1<<(n)) 16 | #define hashmask(n) (hashsize(n)-1) 17 | 18 | /* 19 | -------------------------------------------------------------------- 20 | mix -- mix 3 32-bit values reversibly. 21 | For every delta with one or two bit set, and the deltas of all three 22 | high bits or all three low bits, whether the original value of a,b,c 23 | is almost all zero or is uniformly distributed, 24 | * If mix() is run forward or backward, at least 32 bits in a,b,c 25 | have at least 1/4 probability of changing. 26 | * If mix() is run forward, every bit of c will change between 1/3 and 27 | 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.) 28 | mix() was built out of 36 single-cycle latency instructions in a 29 | structure that could supported 2x parallelism, like so: 30 | a -= b; 31 | a -= c; x = (c>>13); 32 | b -= c; a ^= x; 33 | b -= a; x = (a<<8); 34 | c -= a; b ^= x; 35 | c -= b; x = (b>>13); 36 | ... 37 | Unfortunately, superscalar Pentiums and Sparcs can't take advantage 38 | of that parallelism. They've also turned some of those single-cycle 39 | latency instructions into multi-cycle latency instructions. Still, 40 | this is the fastest good hash I could find. There were about 2^^68 41 | to choose from. I only looked at a billion or so. 42 | -------------------------------------------------------------------- 43 | */ 44 | #define mix(a,b,c) \ 45 | { \ 46 | a -= b; a -= c; a ^= (c>>13); \ 47 | b -= c; b -= a; b ^= (a<<8); \ 48 | c -= a; c -= b; c ^= (b>>13); \ 49 | a -= b; a -= c; a ^= (c>>12); \ 50 | b -= c; b -= a; b ^= (a<<16); \ 51 | c -= a; c -= b; c ^= (b>>5); \ 52 | a -= b; a -= c; a ^= (c>>3); \ 53 | b -= c; b -= a; b ^= (a<<10); \ 54 | c -= a; c -= b; c ^= (b>>15); \ 55 | } 56 | 57 | /* same, but slower, works on systems that might have 8 byte ub4's */ 58 | #define mix2(a,b,c) \ 59 | { \ 60 | a -= b; a -= c; a ^= (c>>13); \ 61 | b -= c; b -= a; b ^= (a<< 8); \ 62 | c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ 63 | a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ 64 | b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ 65 | c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ 66 | a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ 67 | b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ 68 | c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ 69 | } 70 | 71 | /* 72 | -------------------------------------------------------------------- 73 | hash() -- hash a variable-length key into a 32-bit value 74 | k : the key (the unaligned variable-length array of bytes) 75 | len : the length of the key, counting by bytes 76 | level : can be any 4-byte value 77 | Returns a 32-bit value. Every bit of the key affects every bit of 78 | the return value. Every 1-bit and 2-bit delta achieves avalanche. 79 | About 36+6len instructions. 80 | 81 | The best hash table sizes are powers of 2. There is no need to do 82 | mod a prime (mod is sooo slow!). If you need less than 32 bits, 83 | use a bitmask. For example, if you need only 10 bits, do 84 | h = (h & hashmask(10)); 85 | In which case, the hash table should have hashsize(10) elements. 86 | 87 | If you are hashing n strings (ub1 **)k, do it like this: 88 | for (i=0, h=0; i= 12) 113 | { 114 | a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24)); 115 | b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24)); 116 | c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24)); 117 | mix(a,b,c); 118 | k += 12; len -= 12; 119 | } 120 | 121 | /*------------------------------------- handle the last 11 bytes */ 122 | c += length; 123 | switch(len) /* all the case statements fall through */ 124 | { 125 | case 11: c+=((ub4)k[10]<<24); 126 | case 10: c+=((ub4)k[9]<<16); 127 | case 9 : c+=((ub4)k[8]<<8); 128 | /* the first byte of c is reserved for the length */ 129 | case 8 : b+=((ub4)k[7]<<24); 130 | case 7 : b+=((ub4)k[6]<<16); 131 | case 6 : b+=((ub4)k[5]<<8); 132 | case 5 : b+=k[4]; 133 | case 4 : a+=((ub4)k[3]<<24); 134 | case 3 : a+=((ub4)k[2]<<16); 135 | case 2 : a+=((ub4)k[1]<<8); 136 | case 1 : a+=k[0]; 137 | /* case 0: nothing left to add */ 138 | } 139 | mix(a,b,c); 140 | /*-------------------------------------------- report the result */ 141 | return c; 142 | } 143 | 144 | 145 | /* 146 | -------------------------------------------------------------------- 147 | This works on all machines. hash2() is identical to hash() on 148 | little-endian machines, except that the length has to be measured 149 | in ub4s instead of bytes. It is much faster than hash(). It 150 | requires 151 | -- that the key be an array of ub4's, and 152 | -- that all your machines have the same endianness, and 153 | -- that the length be the number of ub4's in the key 154 | -------------------------------------------------------------------- 155 | */ 156 | ub4 hash2( k, length, initval) 157 | register ub4 *k; /* the key */ 158 | register ub4 length; /* the length of the key, in ub4s */ 159 | register ub4 initval; /* the previous hash, or an arbitrary value */ 160 | { 161 | register ub4 a,b,c,len; 162 | 163 | /* Set up the internal state */ 164 | len = length; 165 | a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ 166 | c = initval; /* the previous hash value */ 167 | 168 | /*---------------------------------------- handle most of the key */ 169 | while (len >= 3) 170 | { 171 | a += k[0]; 172 | b += k[1]; 173 | c += k[2]; 174 | mix(a,b,c); 175 | k += 3; len -= 3; 176 | } 177 | 178 | /*-------------------------------------- handle the last 2 ub4's */ 179 | c += length; 180 | switch(len) /* all the case statements fall through */ 181 | { 182 | /* c is reserved for the length */ 183 | case 2 : b+=k[1]; 184 | case 1 : a+=k[0]; 185 | /* case 0: nothing left to add */ 186 | } 187 | mix(a,b,c); 188 | /*-------------------------------------------- report the result */ 189 | return c; 190 | } 191 | 192 | /* 193 | -------------------------------------------------------------------- 194 | This is identical to hash() on little-endian machines (like Intel 195 | x86s or VAXen). It gives nondeterministic results on big-endian 196 | machines. It is faster than hash(), but a little slower than 197 | hash2(), and it requires 198 | -- that all your machines be little-endian 199 | -------------------------------------------------------------------- 200 | */ 201 | 202 | ub4 hash3( k, length, initval) 203 | register ub1 *k; /* the key */ 204 | register ub4 length; /* the length of the key */ 205 | register ub4 initval; /* the previous hash, or an arbitrary value */ 206 | { 207 | register ub4 a,b,c,len; 208 | 209 | /* Set up the internal state */ 210 | len = length; 211 | a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ 212 | c = initval; /* the previous hash value */ 213 | 214 | /*---------------------------------------- handle most of the key */ 215 | if (((ub4)k)&3) 216 | { 217 | while (len >= 12) /* unaligned */ 218 | { 219 | a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24)); 220 | b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24)); 221 | c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24)); 222 | mix(a,b,c); 223 | k += 12; len -= 12; 224 | } 225 | } 226 | else 227 | { 228 | while (len >= 12) /* aligned */ 229 | { 230 | a += *(ub4 *)(k+0); 231 | b += *(ub4 *)(k+4); 232 | c += *(ub4 *)(k+8); 233 | mix(a,b,c); 234 | k += 12; len -= 12; 235 | } 236 | } 237 | 238 | /*------------------------------------- handle the last 11 bytes */ 239 | c += length; 240 | switch(len) /* all the case statements fall through */ 241 | { 242 | case 11: c+=((ub4)k[10]<<24); 243 | case 10: c+=((ub4)k[9]<<16); 244 | case 9 : c+=((ub4)k[8]<<8); 245 | /* the first byte of c is reserved for the length */ 246 | case 8 : b+=((ub4)k[7]<<24); 247 | case 7 : b+=((ub4)k[6]<<16); 248 | case 6 : b+=((ub4)k[5]<<8); 249 | case 5 : b+=k[4]; 250 | case 4 : a+=((ub4)k[3]<<24); 251 | case 3 : a+=((ub4)k[2]<<16); 252 | case 2 : a+=((ub4)k[1]<<8); 253 | case 1 : a+=k[0]; 254 | /* case 0: nothing left to add */ 255 | } 256 | mix(a,b,c); 257 | /*-------------------------------------------- report the result */ 258 | return c; 259 | } 260 | 261 | 262 | 263 | #ifdef SELF_TEST 264 | 265 | /* used for timings */ 266 | void driver1() 267 | { 268 | ub4 buf[256]; 269 | ub4 i; 270 | ub4 h=0; 271 | 272 | for (i=0; i<256; ++i) 273 | { 274 | h = hash(buf,i,h); 275 | } 276 | } 277 | 278 | /* check that every input bit changes every output bit half the time */ 279 | #define HASHSTATE 1 280 | #define HASHLEN 1 281 | #define MAXPAIR 80 282 | #define MAXLEN 70 283 | void driver2() 284 | { 285 | ub1 qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; 286 | ub4 c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m, z; 287 | ub4 e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; 288 | ub4 x[HASHSTATE],y[HASHSTATE]; 289 | ub4 hlen; 290 | 291 | printf("No more than %d trials should ever be needed \n",MAXPAIR/2); 292 | for (hlen=0; hlen < MAXLEN; ++hlen) 293 | { 294 | z=0; 295 | for (i=0; i>(8-j)); 312 | c[0] = hash(a, hlen, m); 313 | b[i] ^= ((k+1)<>(8-j)); 315 | d[0] = hash(b, hlen, m); 316 | /* check every bit is 1, 0, set, and not set at least once */ 317 | for (l=0; lz) z=k; 330 | if (k==MAXPAIR) 331 | { 332 | printf("Some bit didn't change: "); 333 | printf("%.8lx %.8lx %.8lx %.8lx %.8lx %.8lx ", 334 | e[0],f[0],g[0],h[0],x[0],y[0]); 335 | printf("i %ld j %ld m %ld len %ld\n",i,j,m,hlen); 336 | } 337 | if (z==MAXPAIR) goto done; 338 | } 339 | } 340 | } 341 | done: 342 | if (z < MAXPAIR) 343 | { 344 | printf("Mix success %2ld bytes %2ld initvals ",i,m); 345 | printf("required %ld trials\n",z/2); 346 | } 347 | } 348 | printf("\n"); 349 | } 350 | 351 | /* Check for reading beyond the end of the buffer and alignment problems */ 352 | void driver3() 353 | { 354 | ub1 buf[MAXLEN+20], *b; 355 | ub4 len; 356 | ub1 q[] = "This is the time for all good men to come to the aid of their country"; 357 | ub1 qq[] = "xThis is the time for all good men to come to the aid of their country"; 358 | ub1 qqq[] = "xxThis is the time for all good men to come to the aid of their country"; 359 | ub1 qqqq[] = "xxxThis is the time for all good men to come to the aid of their country"; 360 | ub4 h,i,j,ref,x,y; 361 | 362 | printf("Endianness. These should all be the same:\n"); 363 | printf("%.8lx\n", hash(q, sizeof(q)-1, (ub4)0)); 364 | printf("%.8lx\n", hash(qq+1, sizeof(q)-1, (ub4)0)); 365 | printf("%.8lx\n", hash(qqq+2, sizeof(q)-1, (ub4)0)); 366 | printf("%.8lx\n", hash(qqqq+3, sizeof(q)-1, (ub4)0)); 367 | printf("\n"); 368 | for (h=0, b=buf+1; h<8; ++h, ++b) 369 | { 370 | for (i=0; i 74 | /* 75 | * If you do not have the ISO standard stdint.h header file, then you 76 | * must typedef the following: 77 | * name meaning 78 | * uint64_t unsigned 64-bit integer 79 | * uint32_t unsigned 32-bit integer 80 | * uint8_t unsigned 8-bit integer (i.e., unsigned char) 81 | * int_least16_t integer of >= 16 bits 82 | * 83 | * See stdint-example.h 84 | */ 85 | 86 | #ifndef _SHA_enum_ 87 | #define _SHA_enum_ 88 | /* 89 | * All SHA functions return one of these values. 90 | */ 91 | enum { 92 | shaSuccess = 0, 93 | shaNull, /* Null pointer parameter */ 94 | shaInputTooLong, /* input data too long */ 95 | shaStateError, /* called Input after FinalBits or Result */ 96 | shaBadParam /* passed a bad parameter */ 97 | }; 98 | #endif /* _SHA_enum_ */ 99 | 100 | /* 101 | * These constants hold size information for each of the SHA 102 | * hashing operations 103 | */ 104 | enum { 105 | SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64, 106 | SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128, 107 | SHA512_Message_Block_Size = 128, 108 | USHA_Max_Message_Block_Size = SHA512_Message_Block_Size, 109 | 110 | SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32, 111 | SHA384HashSize = 48, SHA512HashSize = 64, 112 | USHAMaxHashSize = SHA512HashSize, 113 | 114 | SHA1HashSizeBits = 160, SHA224HashSizeBits = 224, 115 | SHA256HashSizeBits = 256, SHA384HashSizeBits = 384, 116 | SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits 117 | }; 118 | 119 | /* 120 | * These constants are used in the USHA (Unified SHA) functions. 121 | */ 122 | typedef enum SHAversion { 123 | SHA1, SHA224, SHA256, SHA384, SHA512 124 | } SHAversion; 125 | 126 | /* 127 | * This structure will hold context information for the SHA-1 128 | * hashing operation. 129 | */ 130 | typedef struct SHA1Context { 131 | uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ 132 | 133 | uint32_t Length_High; /* Message length in bits */ 134 | uint32_t Length_Low; /* Message length in bits */ 135 | 136 | int_least16_t Message_Block_Index; /* Message_Block array index */ 137 | /* 512-bit message blocks */ 138 | uint8_t Message_Block[SHA1_Message_Block_Size]; 139 | 140 | int Computed; /* Is the hash computed? */ 141 | int Corrupted; /* Cumulative corruption code */ 142 | } SHA1Context; 143 | 144 | /* 145 | * This structure will hold context information for the SHA-256 146 | * hashing operation. 147 | */ 148 | typedef struct SHA256Context { 149 | uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */ 150 | 151 | uint32_t Length_High; /* Message length in bits */ 152 | uint32_t Length_Low; /* Message length in bits */ 153 | 154 | int_least16_t Message_Block_Index; /* Message_Block array index */ 155 | /* 512-bit message blocks */ 156 | uint8_t Message_Block[SHA256_Message_Block_Size]; 157 | 158 | int Computed; /* Is the hash computed? */ 159 | int Corrupted; /* Cumulative corruption code */ 160 | } SHA256Context; 161 | 162 | /* 163 | * This structure will hold context information for the SHA-512 164 | * hashing operation. 165 | */ 166 | typedef struct SHA512Context { 167 | #ifdef USE_32BIT_ONLY 168 | uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */ 169 | uint32_t Length[4]; /* Message length in bits */ 170 | #else /* !USE_32BIT_ONLY */ 171 | uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */ 172 | uint64_t Length_High, Length_Low; /* Message length in bits */ 173 | #endif /* USE_32BIT_ONLY */ 174 | 175 | int_least16_t Message_Block_Index; /* Message_Block array index */ 176 | /* 1024-bit message blocks */ 177 | uint8_t Message_Block[SHA512_Message_Block_Size]; 178 | 179 | int Computed; /* Is the hash computed?*/ 180 | int Corrupted; /* Cumulative corruption code */ 181 | } SHA512Context; 182 | 183 | /* 184 | * This structure will hold context information for the SHA-224 185 | * hashing operation. It uses the SHA-256 structure for computation. 186 | */ 187 | typedef struct SHA256Context SHA224Context; 188 | 189 | /* 190 | * This structure will hold context information for the SHA-384 191 | * hashing operation. It uses the SHA-512 structure for computation. 192 | */ 193 | typedef struct SHA512Context SHA384Context; 194 | 195 | /* 196 | * This structure holds context information for all SHA 197 | * hashing operations. 198 | */ 199 | typedef struct USHAContext { 200 | int whichSha; /* which SHA is being used */ 201 | union { 202 | SHA1Context sha1Context; 203 | SHA224Context sha224Context; SHA256Context sha256Context; 204 | SHA384Context sha384Context; SHA512Context sha512Context; 205 | } ctx; 206 | } USHAContext; 207 | 208 | /* 209 | * This structure will hold context information for the HMAC 210 | * keyed-hashing operation. 211 | */ 212 | typedef struct HMACContext { 213 | int whichSha; /* which SHA is being used */ 214 | int hashSize; /* hash size of SHA being used */ 215 | int blockSize; /* block size of SHA being used */ 216 | USHAContext shaContext; /* SHA context */ 217 | unsigned char k_opad[USHA_Max_Message_Block_Size]; 218 | /* outer padding - key XORd with opad */ 219 | int Computed; /* Is the MAC computed? */ 220 | int Corrupted; /* Cumulative corruption code */ 221 | 222 | } HMACContext; 223 | 224 | /* 225 | * This structure will hold context information for the HKDF 226 | * extract-and-expand Key Derivation Functions. 227 | */ 228 | typedef struct HKDFContext { 229 | int whichSha; /* which SHA is being used */ 230 | HMACContext hmacContext; 231 | int hashSize; /* hash size of SHA being used */ 232 | unsigned char prk[USHAMaxHashSize]; 233 | /* pseudo-random key - output of hkdfInput */ 234 | int Computed; /* Is the key material computed? */ 235 | int Corrupted; /* Cumulative corruption code */ 236 | } HKDFContext; 237 | 238 | /* 239 | * Function Prototypes 240 | */ 241 | 242 | /* SHA-1 */ 243 | extern int SHA1Reset(SHA1Context *); 244 | extern int SHA1Input(SHA1Context *, const uint8_t *bytes, 245 | unsigned int bytecount); 246 | extern int SHA1FinalBits(SHA1Context *, uint8_t bits, 247 | unsigned int bit_count); 248 | extern int SHA1Result(SHA1Context *, 249 | uint8_t Message_Digest[SHA1HashSize]); 250 | 251 | /* SHA-224 */ 252 | extern int SHA224Reset(SHA224Context *); 253 | extern int SHA224Input(SHA224Context *, const uint8_t *bytes, 254 | unsigned int bytecount); 255 | extern int SHA224FinalBits(SHA224Context *, uint8_t bits, 256 | unsigned int bit_count); 257 | extern int SHA224Result(SHA224Context *, 258 | uint8_t Message_Digest[SHA224HashSize]); 259 | 260 | /* SHA-256 */ 261 | extern int SHA256Reset(SHA256Context *); 262 | extern int SHA256Input(SHA256Context *, const uint8_t *bytes, 263 | unsigned int bytecount); 264 | extern int SHA256FinalBits(SHA256Context *, uint8_t bits, 265 | unsigned int bit_count); 266 | extern int SHA256Result(SHA256Context *, 267 | uint8_t Message_Digest[SHA256HashSize]); 268 | 269 | /* SHA-384 */ 270 | extern int SHA384Reset(SHA384Context *); 271 | extern int SHA384Input(SHA384Context *, const uint8_t *bytes, 272 | unsigned int bytecount); 273 | extern int SHA384FinalBits(SHA384Context *, uint8_t bits, 274 | unsigned int bit_count); 275 | extern int SHA384Result(SHA384Context *, 276 | uint8_t Message_Digest[SHA384HashSize]); 277 | 278 | /* SHA-512 */ 279 | extern int SHA512Reset(SHA512Context *); 280 | extern int SHA512Input(SHA512Context *, const uint8_t *bytes, 281 | unsigned int bytecount); 282 | extern int SHA512FinalBits(SHA512Context *, uint8_t bits, 283 | unsigned int bit_count); 284 | extern int SHA512Result(SHA512Context *, 285 | uint8_t Message_Digest[SHA512HashSize]); 286 | 287 | /* Unified SHA functions, chosen by whichSha */ 288 | extern int USHAReset(USHAContext *context, SHAversion whichSha); 289 | extern int USHAInput(USHAContext *context, 290 | const uint8_t *bytes, unsigned int bytecount); 291 | extern int USHAFinalBits(USHAContext *context, 292 | uint8_t bits, unsigned int bit_count); 293 | extern int USHAResult(USHAContext *context, 294 | uint8_t Message_Digest[USHAMaxHashSize]); 295 | extern int USHABlockSize(enum SHAversion whichSha); 296 | extern int USHAHashSize(enum SHAversion whichSha); 297 | extern int USHAHashSizeBits(enum SHAversion whichSha); 298 | extern const char *USHAHashName(enum SHAversion whichSha); 299 | 300 | /* 301 | * HMAC Keyed-Hashing for Message Authentication, RFC 2104, 302 | * for all SHAs. 303 | * This interface allows a fixed-length text input to be used. 304 | */ 305 | extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */ 306 | const unsigned char *text, /* pointer to data stream */ 307 | int text_len, /* length of data stream */ 308 | const unsigned char *key, /* pointer to authentication key */ 309 | int key_len, /* length of authentication key */ 310 | uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */ 311 | 312 | /* 313 | * HMAC Keyed-Hashing for Message Authentication, RFC 2104, 314 | * for all SHAs. 315 | * This interface allows any length of text input to be used. 316 | */ 317 | extern int hmacReset(HMACContext *context, enum SHAversion whichSha, 318 | const unsigned char *key, int key_len); 319 | extern int hmacInput(HMACContext *context, const unsigned char *text, 320 | int text_len); 321 | extern int hmacFinalBits(HMACContext *context, uint8_t bits, 322 | unsigned int bit_count); 323 | extern int hmacResult(HMACContext *context, 324 | uint8_t digest[USHAMaxHashSize]); 325 | 326 | /* 327 | * HKDF HMAC-based Extract-and-Expand Key Derivation Function, 328 | * RFC 5869, for all SHAs. 329 | */ 330 | extern int hkdf(SHAversion whichSha, const unsigned char *salt, 331 | int salt_len, const unsigned char *ikm, int ikm_len, 332 | const unsigned char *info, int info_len, 333 | uint8_t okm[ ], int okm_len); 334 | extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt, 335 | int salt_len, const unsigned char *ikm, 336 | int ikm_len, uint8_t prk[USHAMaxHashSize]); 337 | extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], 338 | int prk_len, const unsigned char *info, 339 | int info_len, uint8_t okm[ ], int okm_len); 340 | 341 | /* 342 | * HKDF HMAC-based Extract-and-Expand Key Derivation Function, 343 | * RFC 5869, for all SHAs. 344 | * This interface allows any length of text input to be used. 345 | */ 346 | extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha, 347 | const unsigned char *salt, int salt_len); 348 | extern int hkdfInput(HKDFContext *context, const unsigned char *ikm, 349 | int ikm_len); 350 | extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, 351 | unsigned int ikm_bit_count); 352 | extern int hkdfResult(HKDFContext *context, 353 | uint8_t prk[USHAMaxHashSize], 354 | const unsigned char *info, int info_len, 355 | uint8_t okm[USHAMaxHashSize], int okm_len); 356 | #endif /* _SHA_H_ */ 357 | -------------------------------------------------------------------------------- /sha224-256.c: -------------------------------------------------------------------------------- 1 | /************************* sha224-256.c ************************/ 2 | /***************** See RFC 6234 for details. *******************/ 3 | /* Copyright (c) 2011 IETF Trust and the persons identified as */ 4 | /* authors of the code. All rights reserved. */ 5 | /* See sha.h for terms of use and redistribution. */ 6 | 7 | /* 8 | * Description: 9 | * This file implements the Secure Hash Algorithms SHA-224 and 10 | * SHA-256 as defined in the U.S. National Institute of Standards 11 | * and Technology Federal Information Processing Standards 12 | * Publication (FIPS PUB) 180-3 published in October 2008 13 | * and formerly defined in its predecessors, FIPS PUB 180-1 14 | * and FIP PUB 180-2. 15 | * 16 | * A combined document showing all algorithms is available at 17 | * http://csrc.nist.gov/publications/fips/ 18 | * fips180-3/fips180-3_final.pdf 19 | * 20 | * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit 21 | * message digests for a given data stream. It should take about 22 | * 2**n steps to find a message with the same digest as a given 23 | * message and 2**(n/2) to find any two messages with the same 24 | * digest, when n is the digest size in bits. Therefore, this 25 | * algorithm can serve as a means of providing a 26 | * "fingerprint" for a message. 27 | * 28 | * Portability Issues: 29 | * SHA-224 and SHA-256 are defined in terms of 32-bit "words". 30 | * This code uses (included via "sha.h") to define 32- 31 | * and 8-bit unsigned integer types. If your C compiler does not 32 | * support 32-bit unsigned integers, this code is not 33 | * appropriate. 34 | * 35 | * Caveats: 36 | * SHA-224 and SHA-256 are designed to work with messages less 37 | * than 2^64 bits long. This implementation uses SHA224/256Input() 38 | * to hash the bits that are a multiple of the size of an 8-bit 39 | * octet, and then optionally uses SHA224/256FinalBits() 40 | * to hash the final few bits of the input. 41 | */ 42 | 43 | #include "sha.h" 44 | #include "sha-private.h" 45 | 46 | /* Define the SHA shift, rotate left, and rotate right macros */ 47 | #define SHA256_SHR(bits,word) ((word) >> (bits)) 48 | #define SHA256_ROTL(bits,word) \ 49 | (((word) << (bits)) | ((word) >> (32-(bits)))) 50 | #define SHA256_ROTR(bits,word) \ 51 | (((word) >> (bits)) | ((word) << (32-(bits)))) 52 | 53 | /* Define the SHA SIGMA and sigma macros */ 54 | #define SHA256_SIGMA0(word) \ 55 | (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word)) 56 | #define SHA256_SIGMA1(word) \ 57 | (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word)) 58 | #define SHA256_sigma0(word) \ 59 | (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word)) 60 | #define SHA256_sigma1(word) \ 61 | (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word)) 62 | 63 | /* 64 | * Add "length" to the length. 65 | * Set Corrupted when overflow has occurred. 66 | */ 67 | static uint32_t addTemp; 68 | #define SHA224_256AddLength(context, length) \ 69 | (addTemp = (context)->Length_Low, (context)->Corrupted = \ 70 | (((context)->Length_Low += (length)) < addTemp) && \ 71 | (++(context)->Length_High == 0) ? shaInputTooLong : \ 72 | (context)->Corrupted ) 73 | 74 | /* Local Function Prototypes */ 75 | static int SHA224_256Reset(SHA256Context *context, uint32_t *H0); 76 | static void SHA224_256ProcessMessageBlock(SHA256Context *context); 77 | static void SHA224_256Finalize(SHA256Context *context, 78 | uint8_t Pad_Byte); 79 | static void SHA224_256PadMessage(SHA256Context *context, 80 | uint8_t Pad_Byte); 81 | static int SHA224_256ResultN(SHA256Context *context, 82 | uint8_t Message_Digest[ ], int HashSize); 83 | 84 | /* Initial Hash Values: FIPS 180-3 section 5.3.2 */ 85 | static uint32_t SHA224_H0[SHA256HashSize/4] = { 86 | 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, 87 | 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 88 | }; 89 | 90 | /* Initial Hash Values: FIPS 180-3 section 5.3.3 */ 91 | static uint32_t SHA256_H0[SHA256HashSize/4] = { 92 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 93 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 94 | }; 95 | 96 | /* 97 | * SHA224Reset 98 | * 99 | * Description: 100 | * This function will initialize the SHA224Context in preparation 101 | * for computing a new SHA224 message digest. 102 | * 103 | * Parameters: 104 | * context: [in/out] 105 | * The context to reset. 106 | * 107 | * Returns: 108 | * sha Error Code. 109 | */ 110 | int SHA224Reset(SHA224Context *context) 111 | { 112 | return SHA224_256Reset(context, SHA224_H0); 113 | } 114 | 115 | /* 116 | * SHA224Input 117 | * 118 | * Description: 119 | * This function accepts an array of octets as the next portion 120 | * of the message. 121 | * 122 | * Parameters: 123 | * context: [in/out] 124 | * The SHA context to update. 125 | * message_array[ ]: [in] 126 | * An array of octets representing the next portion of 127 | * the message. 128 | * length: [in] 129 | * The length of the message in message_array. 130 | * 131 | * Returns: 132 | * sha Error Code. 133 | * 134 | */ 135 | int SHA224Input(SHA224Context *context, const uint8_t *message_array, 136 | unsigned int length) 137 | { 138 | return SHA256Input(context, message_array, length); 139 | } 140 | 141 | /* 142 | * SHA224FinalBits 143 | * 144 | * Description: 145 | * This function will add in any final bits of the message. 146 | * 147 | * Parameters: 148 | * context: [in/out] 149 | * The SHA context to update. 150 | * message_bits: [in] 151 | * The final bits of the message, in the upper portion of the 152 | * byte. (Use 0b###00000 instead of 0b00000### to input the 153 | * three bits ###.) 154 | * length: [in] 155 | * The number of bits in message_bits, between 1 and 7. 156 | * 157 | * Returns: 158 | * sha Error Code. 159 | */ 160 | int SHA224FinalBits(SHA224Context *context, 161 | uint8_t message_bits, unsigned int length) 162 | { 163 | return SHA256FinalBits(context, message_bits, length); 164 | } 165 | 166 | /* 167 | * SHA224Result 168 | * 169 | * Description: 170 | * This function will return the 224-bit message digest 171 | * into the Message_Digest array provided by the caller. 172 | * NOTE: 173 | * The first octet of hash is stored in the element with index 0, 174 | * the last octet of hash in the element with index 27. 175 | * 176 | * Parameters: 177 | * context: [in/out] 178 | * The context to use to calculate the SHA hash. 179 | * Message_Digest[ ]: [out] 180 | * Where the digest is returned. 181 | * 182 | * Returns: 183 | * sha Error Code. 184 | */ 185 | int SHA224Result(SHA224Context *context, 186 | uint8_t Message_Digest[SHA224HashSize]) 187 | { 188 | return SHA224_256ResultN(context, Message_Digest, SHA224HashSize); 189 | } 190 | 191 | /* 192 | * SHA256Reset 193 | * 194 | * Description: 195 | * This function will initialize the SHA256Context in preparation 196 | * for computing a new SHA256 message digest. 197 | * 198 | * Parameters: 199 | * context: [in/out] 200 | * The context to reset. 201 | * 202 | * Returns: 203 | * sha Error Code. 204 | */ 205 | int SHA256Reset(SHA256Context *context) 206 | { 207 | return SHA224_256Reset(context, SHA256_H0); 208 | } 209 | 210 | /* 211 | * SHA256Input 212 | * 213 | * Description: 214 | * This function accepts an array of octets as the next portion 215 | * of the message. 216 | * 217 | * Parameters: 218 | * context: [in/out] 219 | * The SHA context to update. 220 | * message_array[ ]: [in] 221 | * An array of octets representing the next portion of 222 | * the message. 223 | * length: [in] 224 | * The length of the message in message_array. 225 | * 226 | * Returns: 227 | * sha Error Code. 228 | */ 229 | int SHA256Input(SHA256Context *context, const uint8_t *message_array, 230 | unsigned int length) 231 | { 232 | if (!context) return shaNull; 233 | if (!length) return shaSuccess; 234 | if (!message_array) return shaNull; 235 | if (context->Computed) return context->Corrupted = shaStateError; 236 | if (context->Corrupted) return context->Corrupted; 237 | 238 | while (length--) { 239 | context->Message_Block[context->Message_Block_Index++] = 240 | *message_array; 241 | 242 | if ((SHA224_256AddLength(context, 8) == shaSuccess) && 243 | (context->Message_Block_Index == SHA256_Message_Block_Size)) 244 | SHA224_256ProcessMessageBlock(context); 245 | 246 | message_array++; 247 | } 248 | 249 | return context->Corrupted; 250 | 251 | } 252 | 253 | /* 254 | * SHA256FinalBits 255 | * 256 | * Description: 257 | * This function will add in any final bits of the message. 258 | * 259 | * Parameters: 260 | * context: [in/out] 261 | * The SHA context to update. 262 | * message_bits: [in] 263 | * The final bits of the message, in the upper portion of the 264 | * byte. (Use 0b###00000 instead of 0b00000### to input the 265 | * three bits ###.) 266 | * length: [in] 267 | * The number of bits in message_bits, between 1 and 7. 268 | * 269 | * Returns: 270 | * sha Error Code. 271 | */ 272 | int SHA256FinalBits(SHA256Context *context, 273 | uint8_t message_bits, unsigned int length) 274 | { 275 | static uint8_t masks[8] = { 276 | /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, 277 | /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, 278 | /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, 279 | /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE 280 | }; 281 | static uint8_t markbit[8] = { 282 | /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, 283 | /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, 284 | /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, 285 | /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 286 | }; 287 | 288 | if (!context) return shaNull; 289 | if (!length) return shaSuccess; 290 | if (context->Corrupted) return context->Corrupted; 291 | if (context->Computed) return context->Corrupted = shaStateError; 292 | if (length >= 8) return context->Corrupted = shaBadParam; 293 | 294 | SHA224_256AddLength(context, length); 295 | SHA224_256Finalize(context, (uint8_t) 296 | ((message_bits & masks[length]) | markbit[length])); 297 | 298 | return context->Corrupted; 299 | } 300 | 301 | /* 302 | * SHA256Result 303 | * 304 | * Description: 305 | * This function will return the 256-bit message digest 306 | * into the Message_Digest array provided by the caller. 307 | * NOTE: 308 | * The first octet of hash is stored in the element with index 0, 309 | * the last octet of hash in the element with index 31. 310 | * 311 | * Parameters: 312 | * context: [in/out] 313 | * The context to use to calculate the SHA hash. 314 | * Message_Digest[ ]: [out] 315 | * Where the digest is returned. 316 | * 317 | * Returns: 318 | * sha Error Code. 319 | */ 320 | int SHA256Result(SHA256Context *context, 321 | uint8_t Message_Digest[SHA256HashSize]) 322 | { 323 | return SHA224_256ResultN(context, Message_Digest, SHA256HashSize); 324 | } 325 | 326 | /* 327 | * SHA224_256Reset 328 | * 329 | * Description: 330 | * This helper function will initialize the SHA256Context in 331 | * preparation for computing a new SHA-224 or SHA-256 message digest. 332 | * 333 | * Parameters: 334 | * context: [in/out] 335 | * The context to reset. 336 | * H0[ ]: [in] 337 | * The initial hash value array to use. 338 | * 339 | * Returns: 340 | * sha Error Code. 341 | */ 342 | static int SHA224_256Reset(SHA256Context *context, uint32_t *H0) 343 | { 344 | if (!context) return shaNull; 345 | 346 | context->Length_High = context->Length_Low = 0; 347 | context->Message_Block_Index = 0; 348 | 349 | context->Intermediate_Hash[0] = H0[0]; 350 | context->Intermediate_Hash[1] = H0[1]; 351 | context->Intermediate_Hash[2] = H0[2]; 352 | context->Intermediate_Hash[3] = H0[3]; 353 | context->Intermediate_Hash[4] = H0[4]; 354 | context->Intermediate_Hash[5] = H0[5]; 355 | context->Intermediate_Hash[6] = H0[6]; 356 | context->Intermediate_Hash[7] = H0[7]; 357 | 358 | context->Computed = 0; 359 | context->Corrupted = shaSuccess; 360 | 361 | return shaSuccess; 362 | } 363 | 364 | /* 365 | * SHA224_256ProcessMessageBlock 366 | * 367 | * Description: 368 | * This helper function will process the next 512 bits of the 369 | * message stored in the Message_Block array. 370 | * 371 | * Parameters: 372 | * context: [in/out] 373 | * The SHA context to update. 374 | * 375 | * Returns: 376 | * Nothing. 377 | * 378 | * Comments: 379 | * Many of the variable names in this code, especially the 380 | * single character names, were used because those were the 381 | * names used in the Secure Hash Standard. 382 | */ 383 | static void SHA224_256ProcessMessageBlock(SHA256Context *context) 384 | { 385 | /* Constants defined in FIPS 180-3, section 4.2.2 */ 386 | static const uint32_t K[64] = { 387 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 388 | 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 389 | 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 390 | 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 391 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 392 | 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 393 | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 394 | 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 395 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 396 | 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 397 | 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 398 | 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 399 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 400 | }; 401 | int t, t4; /* Loop counter */ 402 | uint32_t temp1, temp2; /* Temporary word value */ 403 | uint32_t W[64]; /* Word sequence */ 404 | uint32_t A, B, C, D, E, F, G, H; /* Word buffers */ 405 | 406 | /* 407 | * Initialize the first 16 words in the array W 408 | */ 409 | for (t = t4 = 0; t < 16; t++, t4 += 4) 410 | W[t] = (((uint32_t)context->Message_Block[t4]) << 24) | 411 | (((uint32_t)context->Message_Block[t4 + 1]) << 16) | 412 | (((uint32_t)context->Message_Block[t4 + 2]) << 8) | 413 | (((uint32_t)context->Message_Block[t4 + 3])); 414 | 415 | for (t = 16; t < 64; t++) 416 | W[t] = SHA256_sigma1(W[t-2]) + W[t-7] + 417 | SHA256_sigma0(W[t-15]) + W[t-16]; 418 | 419 | A = context->Intermediate_Hash[0]; 420 | B = context->Intermediate_Hash[1]; 421 | C = context->Intermediate_Hash[2]; 422 | D = context->Intermediate_Hash[3]; 423 | E = context->Intermediate_Hash[4]; 424 | F = context->Intermediate_Hash[5]; 425 | G = context->Intermediate_Hash[6]; 426 | H = context->Intermediate_Hash[7]; 427 | 428 | for (t = 0; t < 64; t++) { 429 | temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; 430 | temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C); 431 | H = G; 432 | G = F; 433 | F = E; 434 | E = D + temp1; 435 | D = C; 436 | C = B; 437 | B = A; 438 | A = temp1 + temp2; 439 | } 440 | 441 | context->Intermediate_Hash[0] += A; 442 | context->Intermediate_Hash[1] += B; 443 | context->Intermediate_Hash[2] += C; 444 | context->Intermediate_Hash[3] += D; 445 | context->Intermediate_Hash[4] += E; 446 | context->Intermediate_Hash[5] += F; 447 | context->Intermediate_Hash[6] += G; 448 | context->Intermediate_Hash[7] += H; 449 | 450 | context->Message_Block_Index = 0; 451 | } 452 | 453 | /* 454 | * SHA224_256Finalize 455 | * 456 | * Description: 457 | * This helper function finishes off the digest calculations. 458 | * 459 | * Parameters: 460 | * context: [in/out] 461 | * The SHA context to update. 462 | * Pad_Byte: [in] 463 | * The last byte to add to the message block before the 0-padding 464 | * and length. This will contain the last bits of the message 465 | * followed by another single bit. If the message was an 466 | * exact multiple of 8-bits long, Pad_Byte will be 0x80. 467 | * 468 | * Returns: 469 | * sha Error Code. 470 | */ 471 | static void SHA224_256Finalize(SHA256Context *context, 472 | uint8_t Pad_Byte) 473 | { 474 | int i; 475 | SHA224_256PadMessage(context, Pad_Byte); 476 | /* message may be sensitive, so clear it out */ 477 | for (i = 0; i < SHA256_Message_Block_Size; ++i) 478 | context->Message_Block[i] = 0; 479 | context->Length_High = 0; /* and clear length */ 480 | context->Length_Low = 0; 481 | context->Computed = 1; 482 | } 483 | 484 | /* 485 | * SHA224_256PadMessage 486 | * 487 | * Description: 488 | * According to the standard, the message must be padded to the next 489 | * even multiple of 512 bits. The first padding bit must be a '1'. 490 | * The last 64 bits represent the length of the original message. 491 | * All bits in between should be 0. This helper function will pad 492 | * the message according to those rules by filling the 493 | * Message_Block array accordingly. When it returns, it can be 494 | * assumed that the message digest has been computed. 495 | * 496 | * Parameters: 497 | * context: [in/out] 498 | * The context to pad. 499 | * Pad_Byte: [in] 500 | * The last byte to add to the message block before the 0-padding 501 | * and length. This will contain the last bits of the message 502 | * followed by another single bit. If the message was an 503 | * exact multiple of 8-bits long, Pad_Byte will be 0x80. 504 | * 505 | * Returns: 506 | * Nothing. 507 | */ 508 | static void SHA224_256PadMessage(SHA256Context *context, 509 | uint8_t Pad_Byte) 510 | { 511 | /* 512 | * Check to see if the current message block is too small to hold 513 | * the initial padding bits and length. If so, we will pad the 514 | * block, process it, and then continue padding into a second 515 | * block. 516 | */ 517 | if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) { 518 | context->Message_Block[context->Message_Block_Index++] = Pad_Byte; 519 | while (context->Message_Block_Index < SHA256_Message_Block_Size) 520 | context->Message_Block[context->Message_Block_Index++] = 0; 521 | SHA224_256ProcessMessageBlock(context); 522 | } else 523 | context->Message_Block[context->Message_Block_Index++] = Pad_Byte; 524 | 525 | while (context->Message_Block_Index < (SHA256_Message_Block_Size-8)) 526 | context->Message_Block[context->Message_Block_Index++] = 0; 527 | 528 | /* 529 | * Store the message length as the last 8 octets 530 | */ 531 | context->Message_Block[56] = (uint8_t)(context->Length_High >> 24); 532 | context->Message_Block[57] = (uint8_t)(context->Length_High >> 16); 533 | context->Message_Block[58] = (uint8_t)(context->Length_High >> 8); 534 | context->Message_Block[59] = (uint8_t)(context->Length_High); 535 | context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24); 536 | context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16); 537 | context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8); 538 | context->Message_Block[63] = (uint8_t)(context->Length_Low); 539 | 540 | SHA224_256ProcessMessageBlock(context); 541 | } 542 | 543 | /* 544 | * SHA224_256ResultN 545 | * 546 | * Description: 547 | * This helper function will return the 224-bit or 256-bit message 548 | * digest into the Message_Digest array provided by the caller. 549 | * NOTE: 550 | * The first octet of hash is stored in the element with index 0, 551 | * the last octet of hash in the element with index 27/31. 552 | * 553 | * Parameters: 554 | * context: [in/out] 555 | * The context to use to calculate the SHA hash. 556 | * Message_Digest[ ]: [out] 557 | * Where the digest is returned. 558 | * HashSize: [in] 559 | * The size of the hash, either 28 or 32. 560 | * 561 | * Returns: 562 | * sha Error Code. 563 | */ 564 | static int SHA224_256ResultN(SHA256Context *context, 565 | uint8_t Message_Digest[ ], int HashSize) 566 | { 567 | int i; 568 | 569 | if (!context) return shaNull; 570 | if (!Message_Digest) return shaNull; 571 | if (context->Corrupted) return context->Corrupted; 572 | 573 | if (!context->Computed) 574 | SHA224_256Finalize(context, 0x80); 575 | 576 | for (i = 0; i < HashSize; ++i) 577 | Message_Digest[i] = (uint8_t) 578 | (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) )); 579 | 580 | return shaSuccess; 581 | } 582 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /ldid.cpp: -------------------------------------------------------------------------------- 1 | /* ldid - (Mach-O) Link-Loader Identity Editor 2 | * Copyright (C) 2007-2012 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Affero General Public License, Version 3 {{{ */ 6 | /* 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "minimal/stdlib.h" 23 | #include "minimal/string.h" 24 | #include "minimal/mapping.h" 25 | 26 | extern "C" { 27 | #include "sha1.h" 28 | } 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | struct fat_header { 35 | uint32_t magic; 36 | uint32_t nfat_arch; 37 | } _packed; 38 | 39 | #define FAT_MAGIC 0xcafebabe 40 | #define FAT_CIGAM 0xbebafeca 41 | 42 | struct fat_arch { 43 | uint32_t cputype; 44 | uint32_t cpusubtype; 45 | uint32_t offset; 46 | uint32_t size; 47 | uint32_t align; 48 | } _packed; 49 | 50 | struct mach_header { 51 | uint32_t magic; 52 | uint32_t cputype; 53 | uint32_t cpusubtype; 54 | uint32_t filetype; 55 | uint32_t ncmds; 56 | uint32_t sizeofcmds; 57 | uint32_t flags; 58 | } _packed; 59 | 60 | #define MH_MAGIC 0xfeedface 61 | #define MH_CIGAM 0xcefaedfe 62 | 63 | #define MH_MAGIC_64 0xfeedfacf 64 | #define MH_CIGAM_64 0xcffaedfe 65 | 66 | #define MH_DYLDLINK 0x4 67 | 68 | #define MH_OBJECT 0x1 69 | #define MH_EXECUTE 0x2 70 | #define MH_DYLIB 0x6 71 | #define MH_BUNDLE 0x8 72 | #define MH_DYLIB_STUB 0x9 73 | 74 | struct load_command { 75 | uint32_t cmd; 76 | uint32_t cmdsize; 77 | } _packed; 78 | 79 | #define LC_REQ_DYLD uint32_t(0x80000000) 80 | 81 | #define LC_SEGMENT uint32_t(0x01) 82 | #define LC_SYMTAB uint32_t(0x02) 83 | #define LC_DYSYMTAB uint32_t(0x0b) 84 | #define LC_LOAD_DYLIB uint32_t(0x0c) 85 | #define LC_ID_DYLIB uint32_t(0x0d) 86 | #define LC_SEGMENT_64 uint32_t(0x19) 87 | #define LC_UUID uint32_t(0x1b) 88 | #define LC_CODE_SIGNATURE uint32_t(0x1d) 89 | #define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e) 90 | #define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD) 91 | #define LC_ENCRYPTION_INFO uint32_t(0x21) 92 | #define LC_DYLD_INFO uint32_t(0x22) 93 | #define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD) 94 | 95 | struct dylib { 96 | uint32_t name; 97 | uint32_t timestamp; 98 | uint32_t current_version; 99 | uint32_t compatibility_version; 100 | } _packed; 101 | 102 | struct dylib_command { 103 | uint32_t cmd; 104 | uint32_t cmdsize; 105 | struct dylib dylib; 106 | } _packed; 107 | 108 | struct uuid_command { 109 | uint32_t cmd; 110 | uint32_t cmdsize; 111 | uint8_t uuid[16]; 112 | } _packed; 113 | 114 | struct symtab_command { 115 | uint32_t cmd; 116 | uint32_t cmdsize; 117 | uint32_t symoff; 118 | uint32_t nsyms; 119 | uint32_t stroff; 120 | uint32_t strsize; 121 | } _packed; 122 | 123 | struct dyld_info_command { 124 | uint32_t cmd; 125 | uint32_t cmdsize; 126 | uint32_t rebase_off; 127 | uint32_t rebase_size; 128 | uint32_t bind_off; 129 | uint32_t bind_size; 130 | uint32_t weak_bind_off; 131 | uint32_t weak_bind_size; 132 | uint32_t lazy_bind_off; 133 | uint32_t lazy_bind_size; 134 | uint32_t export_off; 135 | uint32_t export_size; 136 | } _packed; 137 | 138 | struct dysymtab_command { 139 | uint32_t cmd; 140 | uint32_t cmdsize; 141 | uint32_t ilocalsym; 142 | uint32_t nlocalsym; 143 | uint32_t iextdefsym; 144 | uint32_t nextdefsym; 145 | uint32_t iundefsym; 146 | uint32_t nundefsym; 147 | uint32_t tocoff; 148 | uint32_t ntoc; 149 | uint32_t modtaboff; 150 | uint32_t nmodtab; 151 | uint32_t extrefsymoff; 152 | uint32_t nextrefsyms; 153 | uint32_t indirectsymoff; 154 | uint32_t nindirectsyms; 155 | uint32_t extreloff; 156 | uint32_t nextrel; 157 | uint32_t locreloff; 158 | uint32_t nlocrel; 159 | } _packed; 160 | 161 | struct dylib_table_of_contents { 162 | uint32_t symbol_index; 163 | uint32_t module_index; 164 | } _packed; 165 | 166 | struct dylib_module { 167 | uint32_t module_name; 168 | uint32_t iextdefsym; 169 | uint32_t nextdefsym; 170 | uint32_t irefsym; 171 | uint32_t nrefsym; 172 | uint32_t ilocalsym; 173 | uint32_t nlocalsym; 174 | uint32_t iextrel; 175 | uint32_t nextrel; 176 | uint32_t iinit_iterm; 177 | uint32_t ninit_nterm; 178 | uint32_t objc_module_info_addr; 179 | uint32_t objc_module_info_size; 180 | } _packed; 181 | 182 | struct dylib_reference { 183 | uint32_t isym:24; 184 | uint32_t flags:8; 185 | } _packed; 186 | 187 | struct relocation_info { 188 | int32_t r_address; 189 | uint32_t r_symbolnum:24; 190 | uint32_t r_pcrel:1; 191 | uint32_t r_length:2; 192 | uint32_t r_extern:1; 193 | uint32_t r_type:4; 194 | } _packed; 195 | 196 | struct nlist { 197 | union { 198 | char *n_name; 199 | int32_t n_strx; 200 | } n_un; 201 | 202 | uint8_t n_type; 203 | uint8_t n_sect; 204 | uint8_t n_desc; 205 | uint32_t n_value; 206 | } _packed; 207 | 208 | struct segment_command { 209 | uint32_t cmd; 210 | uint32_t cmdsize; 211 | char segname[16]; 212 | uint32_t vmaddr; 213 | uint32_t vmsize; 214 | uint32_t fileoff; 215 | uint32_t filesize; 216 | uint32_t maxprot; 217 | uint32_t initprot; 218 | uint32_t nsects; 219 | uint32_t flags; 220 | } _packed; 221 | 222 | struct segment_command_64 { 223 | uint32_t cmd; 224 | uint32_t cmdsize; 225 | char segname[16]; 226 | uint64_t vmaddr; 227 | uint64_t vmsize; 228 | uint64_t fileoff; 229 | uint64_t filesize; 230 | uint32_t maxprot; 231 | uint32_t initprot; 232 | uint32_t nsects; 233 | uint32_t flags; 234 | } _packed; 235 | 236 | struct section { 237 | char sectname[16]; 238 | char segname[16]; 239 | uint32_t addr; 240 | uint32_t size; 241 | uint32_t offset; 242 | uint32_t align; 243 | uint32_t reloff; 244 | uint32_t nreloc; 245 | uint32_t flags; 246 | uint32_t reserved1; 247 | uint32_t reserved2; 248 | } _packed; 249 | 250 | struct section_64 { 251 | char sectname[16]; 252 | char segname[16]; 253 | uint64_t addr; 254 | uint64_t size; 255 | uint32_t offset; 256 | uint32_t align; 257 | uint32_t reloff; 258 | uint32_t nreloc; 259 | uint32_t flags; 260 | uint32_t reserved1; 261 | uint32_t reserved2; 262 | } _packed; 263 | 264 | struct linkedit_data_command { 265 | uint32_t cmd; 266 | uint32_t cmdsize; 267 | uint32_t dataoff; 268 | uint32_t datasize; 269 | } _packed; 270 | 271 | struct encryption_info_command { 272 | uint32_t cmd; 273 | uint32_t cmdsize; 274 | uint32_t cryptoff; 275 | uint32_t cryptsize; 276 | uint32_t cryptid; 277 | } _packed; 278 | 279 | #define BIND_OPCODE_MASK 0xf0 280 | #define BIND_IMMEDIATE_MASK 0x0f 281 | #define BIND_OPCODE_DONE 0x00 282 | #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10 283 | #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20 284 | #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 285 | #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 286 | #define BIND_OPCODE_SET_TYPE_IMM 0x50 287 | #define BIND_OPCODE_SET_ADDEND_SLEB 0x60 288 | #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 289 | #define BIND_OPCODE_ADD_ADDR_ULEB 0x80 290 | #define BIND_OPCODE_DO_BIND 0x90 291 | #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xa0 292 | #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0 293 | #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0 294 | 295 | template 296 | Type_ Align(Type_ value, size_t align) { 297 | value += align - 1; 298 | value /= align; 299 | value *= align; 300 | return value; 301 | } 302 | 303 | uint16_t Swap_(uint16_t value) { 304 | return 305 | ((value >> 8) & 0x00ff) | 306 | ((value << 8) & 0xff00); 307 | } 308 | 309 | uint32_t Swap_(uint32_t value) { 310 | value = ((value >> 8) & 0x00ff00ff) | 311 | ((value << 8) & 0xff00ff00); 312 | value = ((value >> 16) & 0x0000ffff) | 313 | ((value << 16) & 0xffff0000); 314 | return value; 315 | } 316 | 317 | uint64_t Swap_(uint64_t value) { 318 | value = (value & 0x00000000ffffffffULL) << 32 | (value & 0xffffffff00000000ULL) >> 32; 319 | value = (value & 0x0000ffff0000ffffULL) << 16 | (value & 0xffff0000ffff0000ULL) >> 16; 320 | value = (value & 0x00ff00ff00ff00ffULL) << 8 | (value & 0xff00ff00ff00ff00ULL) >> 8; 321 | return value; 322 | } 323 | 324 | int16_t Swap_(int16_t value) { 325 | return Swap_(static_cast(value)); 326 | } 327 | 328 | int32_t Swap_(int32_t value) { 329 | return Swap_(static_cast(value)); 330 | } 331 | 332 | int64_t Swap_(int64_t value) { 333 | return Swap_(static_cast(value)); 334 | } 335 | 336 | bool little_(true); 337 | 338 | uint16_t Swap(uint16_t value) { 339 | return little_ ? Swap_(value) : value; 340 | } 341 | 342 | uint32_t Swap(uint32_t value) { 343 | return little_ ? Swap_(value) : value; 344 | } 345 | 346 | uint64_t Swap(uint64_t value) { 347 | return little_ ? Swap_(value) : value; 348 | } 349 | 350 | int16_t Swap(int16_t value) { 351 | return Swap(static_cast(value)); 352 | } 353 | 354 | int32_t Swap(int32_t value) { 355 | return Swap(static_cast(value)); 356 | } 357 | 358 | int64_t Swap(int64_t value) { 359 | return Swap(static_cast(value)); 360 | } 361 | 362 | template 363 | class Pointer; 364 | 365 | class Data { 366 | private: 367 | void *base_; 368 | size_t size_; 369 | 370 | protected: 371 | bool swapped_; 372 | 373 | public: 374 | Data(void *base, size_t size) : 375 | base_(base), 376 | size_(size), 377 | swapped_(false) 378 | { 379 | } 380 | 381 | uint16_t Swap(uint16_t value) const { 382 | return swapped_ ? Swap_(value) : value; 383 | } 384 | 385 | uint32_t Swap(uint32_t value) const { 386 | return swapped_ ? Swap_(value) : value; 387 | } 388 | 389 | uint64_t Swap(uint64_t value) const { 390 | return swapped_ ? Swap_(value) : value; 391 | } 392 | 393 | int16_t Swap(int16_t value) const { 394 | return Swap(static_cast(value)); 395 | } 396 | 397 | int32_t Swap(int32_t value) const { 398 | return Swap(static_cast(value)); 399 | } 400 | 401 | int64_t Swap(int64_t value) const { 402 | return Swap(static_cast(value)); 403 | } 404 | 405 | void *GetBase() const { 406 | return base_; 407 | } 408 | 409 | size_t GetSize() const { 410 | return size_; 411 | } 412 | }; 413 | 414 | class MachHeader : 415 | public Data 416 | { 417 | private: 418 | bool bits64_; 419 | 420 | struct mach_header *mach_header_; 421 | struct load_command *load_command_; 422 | 423 | public: 424 | MachHeader(void *base, size_t size) : 425 | Data(base, size) 426 | { 427 | mach_header_ = (mach_header *) base; 428 | 429 | switch (Swap(mach_header_->magic)) { 430 | case MH_CIGAM: 431 | swapped_ = !swapped_; 432 | case MH_MAGIC: 433 | bits64_ = false; 434 | break; 435 | 436 | case MH_CIGAM_64: 437 | swapped_ = !swapped_; 438 | case MH_MAGIC_64: 439 | bits64_ = true; 440 | break; 441 | 442 | default: 443 | _assert(false); 444 | } 445 | 446 | void *post = mach_header_ + 1; 447 | if (bits64_) 448 | post = (uint32_t *) post + 1; 449 | load_command_ = (struct load_command *) post; 450 | 451 | _assert( 452 | Swap(mach_header_->filetype) == MH_EXECUTE || 453 | Swap(mach_header_->filetype) == MH_DYLIB || 454 | Swap(mach_header_->filetype) == MH_BUNDLE 455 | ); 456 | } 457 | 458 | struct mach_header *operator ->() const { 459 | return mach_header_; 460 | } 461 | 462 | operator struct mach_header *() const { 463 | return mach_header_; 464 | } 465 | 466 | uint32_t GetCPUType() const { 467 | return Swap(mach_header_->cputype); 468 | } 469 | 470 | uint32_t GetCPUSubtype() const { 471 | return Swap(mach_header_->cpusubtype) & 0xff; 472 | } 473 | 474 | struct load_command *GetLoadCommand() const { 475 | return load_command_; 476 | } 477 | 478 | std::vector GetLoadCommands() const { 479 | std::vector load_commands; 480 | 481 | struct load_command *load_command = load_command_; 482 | for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { 483 | load_commands.push_back(load_command); 484 | load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize)); 485 | } 486 | 487 | return load_commands; 488 | } 489 | 490 | std::vector GetSegments(const char *segment_name) const { 491 | std::vector segment_commands; 492 | 493 | _foreach (load_command, GetLoadCommands()) { 494 | if (Swap(load_command->cmd) == LC_SEGMENT) { 495 | segment_command *segment_command = reinterpret_cast(load_command); 496 | if (strncmp(segment_command->segname, segment_name, 16) == 0) 497 | segment_commands.push_back(segment_command); 498 | } 499 | } 500 | 501 | return segment_commands; 502 | } 503 | 504 | std::vector GetSegments64(const char *segment_name) const { 505 | std::vector segment_commands; 506 | 507 | _foreach (load_command, GetLoadCommands()) { 508 | if (Swap(load_command->cmd) == LC_SEGMENT_64) { 509 | segment_command_64 *segment_command = reinterpret_cast(load_command); 510 | if (strncmp(segment_command->segname, segment_name, 16) == 0) 511 | segment_commands.push_back(segment_command); 512 | } 513 | } 514 | 515 | return segment_commands; 516 | } 517 | 518 | std::vector
GetSections(const char *segment_name, const char *section_name) const { 519 | std::vector
sections; 520 | 521 | _foreach (segment, GetSegments(segment_name)) { 522 | section *section = (struct section *) (segment + 1); 523 | 524 | uint32_t sect; 525 | for (sect = 0; sect != Swap(segment->nsects); ++sect) { 526 | if (strncmp(section->sectname, section_name, 16) == 0) 527 | sections.push_back(section); 528 | ++section; 529 | } 530 | } 531 | 532 | return sections; 533 | } 534 | 535 | template 536 | Pointer GetPointer(uint32_t address, const char *segment_name = NULL) const { 537 | load_command *load_command = (struct load_command *) (mach_header_ + 1); 538 | uint32_t cmd; 539 | 540 | for (cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { 541 | if (Swap(load_command->cmd) == LC_SEGMENT) { 542 | segment_command *segment_command = (struct segment_command *) load_command; 543 | if (segment_name != NULL && strncmp(segment_command->segname, segment_name, 16) != 0) 544 | goto next_command; 545 | 546 | section *sections = (struct section *) (segment_command + 1); 547 | 548 | uint32_t sect; 549 | for (sect = 0; sect != Swap(segment_command->nsects); ++sect) { 550 | section *section = §ions[sect]; 551 | //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); 552 | if (address >= Swap(section->addr) && address < Swap(section->addr) + Swap(section->size)) { 553 | //printf("0x%.8x %s\n", address, segment_command->segname); 554 | return Pointer(this, reinterpret_cast(address - Swap(section->addr) + Swap(section->offset) + (char *) mach_header_)); 555 | } 556 | } 557 | } 558 | 559 | next_command: 560 | load_command = (struct load_command *) ((char *) load_command + Swap(load_command->cmdsize)); 561 | } 562 | 563 | return Pointer(this); 564 | } 565 | 566 | template 567 | Pointer GetOffset(uint32_t offset) { 568 | return Pointer(this, reinterpret_cast(offset + (uint8_t *) mach_header_)); 569 | } 570 | }; 571 | 572 | class FatMachHeader : 573 | public MachHeader 574 | { 575 | private: 576 | fat_arch *fat_arch_; 577 | 578 | public: 579 | FatMachHeader(void *base, size_t size, fat_arch *fat_arch) : 580 | MachHeader(base, size), 581 | fat_arch_(fat_arch) 582 | { 583 | } 584 | 585 | fat_arch *GetFatArch() const { 586 | return fat_arch_; 587 | } 588 | }; 589 | 590 | class FatHeader : 591 | public Data 592 | { 593 | private: 594 | fat_header *fat_header_; 595 | std::vector mach_headers_; 596 | 597 | public: 598 | FatHeader(void *base, size_t size) : 599 | Data(base, size) 600 | { 601 | fat_header_ = reinterpret_cast(base); 602 | 603 | if (Swap(fat_header_->magic) == FAT_CIGAM) { 604 | swapped_ = !swapped_; 605 | goto fat; 606 | } else if (Swap(fat_header_->magic) != FAT_MAGIC) { 607 | fat_header_ = NULL; 608 | mach_headers_.push_back(FatMachHeader(base, size, NULL)); 609 | } else fat: { 610 | size_t fat_narch = Swap(fat_header_->nfat_arch); 611 | fat_arch *fat_arch = reinterpret_cast(fat_header_ + 1); 612 | size_t arch; 613 | for (arch = 0; arch != fat_narch; ++arch) { 614 | uint32_t arch_offset = Swap(fat_arch->offset); 615 | uint32_t arch_size = Swap(fat_arch->size); 616 | mach_headers_.push_back(FatMachHeader((uint8_t *) base + arch_offset, arch_size, fat_arch)); 617 | ++fat_arch; 618 | } 619 | } 620 | } 621 | 622 | std::vector &GetMachHeaders() { 623 | return mach_headers_; 624 | } 625 | 626 | bool IsFat() const { 627 | return fat_header_ != NULL; 628 | } 629 | 630 | struct fat_header *operator ->() const { 631 | return fat_header_; 632 | } 633 | 634 | operator struct fat_header *() const { 635 | return fat_header_; 636 | } 637 | }; 638 | 639 | FatHeader Map(const char *path, bool ro = false) { 640 | size_t size; 641 | void *base(map(path, 0, _not(size_t), &size, ro)); 642 | return FatHeader(base, size); 643 | } 644 | 645 | template 646 | class Pointer { 647 | private: 648 | const MachHeader *framework_; 649 | const Target_ *pointer_; 650 | 651 | public: 652 | Pointer(const MachHeader *framework = NULL, const Target_ *pointer = NULL) : 653 | framework_(framework), 654 | pointer_(pointer) 655 | { 656 | } 657 | 658 | operator const Target_ *() const { 659 | return pointer_; 660 | } 661 | 662 | const Target_ *operator ->() const { 663 | return pointer_; 664 | } 665 | 666 | Pointer &operator ++() { 667 | ++pointer_; 668 | return *this; 669 | } 670 | 671 | template 672 | Value_ Swap(Value_ value) { 673 | return framework_->Swap(value); 674 | } 675 | }; 676 | 677 | #define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02) 678 | #define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0) 679 | #define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171) 680 | 681 | #define CSSLOT_CODEDIRECTORY uint32_t(0) 682 | #define CSSLOT_REQUIREMENTS uint32_t(2) 683 | #define CSSLOT_ENTITLEMENTS uint32_t(5) 684 | 685 | struct BlobIndex { 686 | uint32_t type; 687 | uint32_t offset; 688 | } _packed; 689 | 690 | struct Blob { 691 | uint32_t magic; 692 | uint32_t length; 693 | } _packed; 694 | 695 | struct SuperBlob { 696 | struct Blob blob; 697 | uint32_t count; 698 | struct BlobIndex index[]; 699 | } _packed; 700 | 701 | struct CodeDirectory { 702 | struct Blob blob; 703 | uint32_t version; 704 | uint32_t flags; 705 | uint32_t hashOffset; 706 | uint32_t identOffset; 707 | uint32_t nSpecialSlots; 708 | uint32_t nCodeSlots; 709 | uint32_t codeLimit; 710 | uint8_t hashSize; 711 | uint8_t hashType; 712 | uint8_t spare1; 713 | uint8_t pageSize; 714 | uint32_t spare2; 715 | } _packed; 716 | 717 | extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); 718 | 719 | void sha1(uint8_t *hash, uint8_t *data, size_t size) { 720 | SHA1Context context; 721 | SHA1Reset(&context); 722 | SHA1Input(&context, data, size); 723 | SHA1Result(&context, hash); 724 | } 725 | 726 | struct CodesignAllocation { 727 | FatMachHeader mach_header_; 728 | uint32_t offset_; 729 | uint32_t size_; 730 | uint32_t alloc_; 731 | uint32_t align_; 732 | 733 | CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc, size_t align) : 734 | mach_header_(mach_header), 735 | offset_(offset), 736 | size_(size), 737 | alloc_(alloc), 738 | align_(align) 739 | { 740 | } 741 | }; 742 | 743 | int main(int argc, const char *argv[]) { 744 | union { 745 | uint16_t word; 746 | uint8_t byte[2]; 747 | } endian = {1}; 748 | 749 | little_ = endian.byte[0]; 750 | 751 | bool flag_R(false); 752 | bool flag_r(false); 753 | 754 | bool flag_t(false); 755 | bool flag_p(false); 756 | bool flag_u(false); 757 | bool flag_e(false); 758 | 759 | bool flag_T(false); 760 | 761 | bool flag_S(false); 762 | bool flag_s(false); 763 | 764 | bool flag_O(false); 765 | 766 | bool flag_D(false); 767 | bool flag_d(false); 768 | 769 | bool flag_A(false); 770 | bool flag_a(false); 771 | 772 | uint32_t flag_CPUType(_not(uint32_t)); 773 | uint32_t flag_CPUSubtype(_not(uint32_t)); 774 | 775 | const char *flag_I(NULL); 776 | 777 | bool timeh(false); 778 | uint32_t timev(0); 779 | 780 | const void *xmld(NULL); 781 | size_t xmls(0); 782 | 783 | uintptr_t noffset(_not(uintptr_t)); 784 | uintptr_t woffset(_not(uintptr_t)); 785 | 786 | std::vector files; 787 | 788 | if (argc == 1) { 789 | fprintf(stderr, "usage: %s -S[entitlements.xml] \n", argv[0]); 790 | fprintf(stderr, " %s -e MobileSafari\n", argv[0]); 791 | fprintf(stderr, " %s -S cat\n", argv[0]); 792 | fprintf(stderr, " %s -Stfp.xml gdb\n", argv[0]); 793 | exit(0); 794 | } 795 | 796 | for (int argi(1); argi != argc; ++argi) 797 | if (argv[argi][0] != '-') 798 | files.push_back(argv[argi]); 799 | else switch (argv[argi][1]) { 800 | case 'R': flag_R = true; break; 801 | case 'r': flag_r = true; break; 802 | 803 | case 't': flag_t = true; break; 804 | case 'u': flag_u = true; break; 805 | case 'p': flag_p = true; break; 806 | case 'e': flag_e = true; break; 807 | case 'O': flag_O = true; break; 808 | 809 | case 'D': flag_D = true; break; 810 | case 'd': flag_d = true; break; 811 | 812 | case 'a': flag_a = true; break; 813 | 814 | case 'A': 815 | flag_A = true; 816 | if (argv[argi][2] != '\0') { 817 | const char *cpu = argv[argi] + 2; 818 | const char *colon = strchr(cpu, ':'); 819 | _assert(colon != NULL); 820 | char *arge; 821 | flag_CPUType = strtoul(cpu, &arge, 0); 822 | _assert(arge == colon); 823 | flag_CPUSubtype = strtoul(colon + 1, &arge, 0); 824 | _assert(arge == argv[argi] + strlen(argv[argi])); 825 | } 826 | break; 827 | 828 | case 's': 829 | _assert(!flag_S); 830 | flag_s = true; 831 | break; 832 | 833 | case 'S': 834 | _assert(!flag_s); 835 | flag_S = true; 836 | if (argv[argi][2] != '\0') { 837 | const char *xml = argv[argi] + 2; 838 | xmld = map(xml, 0, _not(size_t), &xmls, true); 839 | } 840 | break; 841 | 842 | case 'T': { 843 | flag_T = true; 844 | if (argv[argi][2] == '-') 845 | timeh = true; 846 | else { 847 | char *arge; 848 | timev = strtoul(argv[argi] + 2, &arge, 0); 849 | _assert(arge == argv[argi] + strlen(argv[argi])); 850 | } 851 | } break; 852 | 853 | case 'I': { 854 | flag_I = argv[argi] + 2; 855 | } break; 856 | 857 | case 'n': { 858 | char *arge; 859 | noffset = strtoul(argv[argi] + 2, &arge, 0); 860 | _assert(arge == argv[argi] + strlen(argv[argi])); 861 | } break; 862 | 863 | case 'w': { 864 | char *arge; 865 | woffset = strtoul(argv[argi] + 2, &arge, 0); 866 | _assert(arge == argv[argi] + strlen(argv[argi])); 867 | } break; 868 | 869 | default: 870 | goto usage; 871 | break; 872 | } 873 | 874 | if (files.empty()) usage: { 875 | exit(0); 876 | } 877 | 878 | size_t filei(0), filee(0); 879 | _foreach (file, files) try { 880 | const char *path(file.c_str()); 881 | const char *base = strrchr(path, '/'); 882 | char *temp(NULL), *dir; 883 | 884 | if (base != NULL) 885 | dir = strndup_(path, base++ - path + 1); 886 | else { 887 | dir = strdup(""); 888 | base = path; 889 | } 890 | 891 | const char *name(flag_I ?: base); 892 | 893 | if (flag_r) { 894 | uint32_t clip(0); { 895 | FatHeader fat_header(Map(path)); 896 | _foreach (mach_header, fat_header.GetMachHeaders()) { 897 | if (flag_A) { 898 | if (mach_header.GetCPUType() != flag_CPUType) 899 | continue; 900 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 901 | continue; 902 | } 903 | 904 | mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK); 905 | 906 | uint32_t size(_not(uint32_t)); { 907 | _foreach (load_command, mach_header.GetLoadCommands()) { 908 | switch (mach_header.Swap(load_command->cmd)) { 909 | case LC_CODE_SIGNATURE: { 910 | struct linkedit_data_command *signature = reinterpret_cast(load_command); 911 | memset(reinterpret_cast(mach_header.GetBase()) + mach_header.Swap(signature->dataoff), 0, mach_header.Swap(signature->datasize)); 912 | memset(signature, 0, sizeof(struct linkedit_data_command)); 913 | 914 | mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) - 1); 915 | mach_header->sizeofcmds = mach_header.Swap(uint32_t(mach_header.Swap(mach_header->sizeofcmds) - sizeof(struct linkedit_data_command))); 916 | } break; 917 | 918 | case LC_SYMTAB: { 919 | struct symtab_command *symtab = reinterpret_cast(load_command); 920 | size = mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize); 921 | } break; 922 | } 923 | } 924 | } 925 | 926 | _assert(size != _not(uint32_t)); 927 | 928 | _foreach (segment, mach_header.GetSegments("__LINKEDIT")) { 929 | segment->filesize -= mach_header.GetSize() - size; 930 | 931 | if (fat_arch *fat_arch = mach_header.GetFatArch()) { 932 | fat_arch->size = fat_header.Swap(size); 933 | clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size); 934 | } else 935 | clip = std::max(clip, size); 936 | } 937 | 938 | _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) { 939 | segment->filesize -= mach_header.GetSize() - size; 940 | 941 | if (fat_arch *fat_arch = mach_header.GetFatArch()) { 942 | fat_arch->size = fat_header.Swap(size); 943 | clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size); 944 | } else 945 | clip = std::max(clip, size); 946 | } 947 | } 948 | } 949 | 950 | if (clip != 0) 951 | _syscall(truncate(path, clip)); 952 | } 953 | 954 | if (flag_S) { 955 | FatHeader source(Map(path)); 956 | 957 | size_t offset(0); 958 | 959 | if (source.IsFat()) 960 | offset += sizeof(fat_header) + sizeof(fat_arch) * source.Swap(source->nfat_arch); 961 | 962 | std::vector allocations; { 963 | _foreach (mach_header, source.GetMachHeaders()) { 964 | if (flag_A) { 965 | if (mach_header.GetCPUType() != flag_CPUType) 966 | continue; 967 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 968 | continue; 969 | } 970 | 971 | mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK); 972 | 973 | size_t size(_not(size_t)); { 974 | _foreach (load_command, mach_header.GetLoadCommands()) { 975 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 976 | if (cmd == LC_CODE_SIGNATURE) { 977 | struct linkedit_data_command *signature = reinterpret_cast(load_command); 978 | size = mach_header.Swap(signature->dataoff); 979 | _assert(size < mach_header.GetSize()); 980 | break; 981 | } 982 | } 983 | 984 | if (size == _not(size_t)) 985 | size = mach_header.GetSize(); 986 | } 987 | 988 | size_t alloc(0); 989 | alloc += sizeof(struct SuperBlob); 990 | uint32_t special(0); 991 | 992 | special = std::max(special, CSSLOT_CODEDIRECTORY); 993 | alloc += sizeof(struct BlobIndex); 994 | alloc += sizeof(struct CodeDirectory); 995 | alloc += strlen(name) + 1; 996 | 997 | special = std::max(special, CSSLOT_REQUIREMENTS); 998 | alloc += sizeof(struct BlobIndex); 999 | alloc += 0xc; 1000 | 1001 | if (xmld != NULL) { 1002 | special = std::max(special, CSSLOT_ENTITLEMENTS); 1003 | alloc += sizeof(struct BlobIndex); 1004 | alloc += sizeof(struct Blob); 1005 | alloc += xmls; 1006 | } 1007 | 1008 | size_t normal((size + 0x1000 - 1) / 0x1000); 1009 | alloc = Align(alloc + (special + normal) * 0x14, 16); 1010 | 1011 | fat_arch *fat_arch(mach_header.GetFatArch()); 1012 | uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align)); 1013 | offset = Align(offset, 1 << align); 1014 | 1015 | allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc, align)); 1016 | offset += size + alloc; 1017 | offset = Align(offset, 16); 1018 | } 1019 | } 1020 | 1021 | asprintf(&temp, "%s.%s.cs", dir, base); 1022 | fclose(fopen(temp, "w+")); 1023 | _syscall(truncate(temp, offset)); 1024 | 1025 | void *file(map(temp, 0, offset, NULL, false)); 1026 | memset(file, 0, offset); 1027 | 1028 | fat_arch *fat_arch; 1029 | if (!source.IsFat()) 1030 | fat_arch = NULL; 1031 | else { 1032 | fat_header *fat_header(reinterpret_cast(file)); 1033 | fat_header->magic = Swap(FAT_MAGIC); 1034 | fat_header->nfat_arch = Swap(source.Swap(source->nfat_arch)); 1035 | fat_arch = reinterpret_cast(fat_header + 1); 1036 | } 1037 | 1038 | _foreach (allocation, allocations) { 1039 | const FatMachHeader &source(allocation.mach_header_); 1040 | 1041 | uint32_t align(allocation.size_); 1042 | align = Align(align, 0x10); 1043 | 1044 | if (fat_arch != NULL) { 1045 | fat_arch->cputype = Swap(source->cputype); 1046 | fat_arch->cpusubtype = Swap(source->cpusubtype); 1047 | fat_arch->offset = Swap(allocation.offset_); 1048 | fat_arch->size = Swap(align + allocation.alloc_); 1049 | fat_arch->align = Swap(allocation.align_); 1050 | ++fat_arch; 1051 | } 1052 | 1053 | void *target(reinterpret_cast(file) + allocation.offset_); 1054 | memcpy(target, source, allocation.size_); 1055 | MachHeader mach_header(target, align + allocation.alloc_); 1056 | 1057 | struct linkedit_data_command *signature(NULL); 1058 | _foreach (load_command, mach_header.GetLoadCommands()) { 1059 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 1060 | if (cmd != LC_CODE_SIGNATURE) 1061 | continue; 1062 | signature = reinterpret_cast(load_command); 1063 | break; 1064 | } 1065 | 1066 | if (signature == NULL) { 1067 | mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) + 1); 1068 | signature = reinterpret_cast(reinterpret_cast(mach_header.GetLoadCommand()) + mach_header.Swap(mach_header->sizeofcmds)); 1069 | mach_header->sizeofcmds = mach_header.Swap(mach_header.Swap(mach_header->sizeofcmds) + uint32_t(sizeof(*signature))); 1070 | signature->cmd = mach_header.Swap(LC_CODE_SIGNATURE); 1071 | signature->cmdsize = mach_header.Swap(uint32_t(sizeof(*signature))); 1072 | } 1073 | 1074 | signature->dataoff = mach_header.Swap(align); 1075 | signature->datasize = mach_header.Swap(allocation.alloc_); 1076 | 1077 | _foreach (segment, mach_header.GetSegments("__LINKEDIT")) { 1078 | size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); 1079 | segment->filesize = size; 1080 | segment->vmsize = Align(size, 0x1000); 1081 | } 1082 | 1083 | _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) { 1084 | size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); 1085 | segment->filesize = size; 1086 | segment->vmsize = Align(size, 0x1000); 1087 | } 1088 | } 1089 | } 1090 | 1091 | if (flag_p) 1092 | printf("path%zu='%s'\n", filei, file.c_str()); 1093 | 1094 | FatHeader fat_header(Map(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D))); 1095 | struct linkedit_data_command *signature(NULL); 1096 | 1097 | _foreach (mach_header, fat_header.GetMachHeaders()) { 1098 | if (flag_A) { 1099 | if (mach_header.GetCPUType() != flag_CPUType) 1100 | continue; 1101 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 1102 | continue; 1103 | } 1104 | 1105 | if (flag_a) 1106 | printf("cpu=0x%x:0x%x\n", mach_header.GetCPUType(), mach_header.GetCPUSubtype()); 1107 | 1108 | if (flag_d) { 1109 | if (struct fat_arch *fat_arch = mach_header.GetFatArch()) 1110 | printf("offset=0x%x\n", Swap(fat_arch->offset)); 1111 | else 1112 | printf("offset=0x0\n"); 1113 | } 1114 | 1115 | if (woffset != _not(uintptr_t)) { 1116 | Pointer wvalue(mach_header.GetPointer(woffset)); 1117 | if (wvalue == NULL) 1118 | printf("(null) %p\n", reinterpret_cast(woffset)); 1119 | else 1120 | printf("0x%.08x\n", *wvalue); 1121 | } 1122 | 1123 | if (noffset != _not(uintptr_t)) 1124 | printf("%s\n", &*mach_header.GetPointer(noffset)); 1125 | 1126 | if (flag_d) 1127 | _foreach(segment, mach_header.GetSegments("__TEXT")) { 1128 | printf("vmaddr=0x%x\n", mach_header.Swap(segment->vmaddr)); 1129 | printf("fileoff=0x%x\n", mach_header.Swap(segment->fileoff)); 1130 | } 1131 | 1132 | if (flag_O) { 1133 | _foreach(section, mach_header.GetSections("__TEXT", "__text")) 1134 | section->addr = mach_header.Swap(0); 1135 | } 1136 | 1137 | _foreach (load_command, mach_header.GetLoadCommands()) { 1138 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 1139 | 1140 | if (flag_R && cmd == LC_REEXPORT_DYLIB) 1141 | load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB); 1142 | else if (cmd == LC_CODE_SIGNATURE) 1143 | signature = reinterpret_cast(load_command); 1144 | else if (cmd == LC_UUID) { 1145 | volatile struct uuid_command *uuid_command(reinterpret_cast(load_command)); 1146 | 1147 | if (flag_u) { 1148 | printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei, 1149 | uuid_command->uuid[ 0], uuid_command->uuid[ 1], uuid_command->uuid[ 2], uuid_command->uuid[ 3], 1150 | uuid_command->uuid[ 4], uuid_command->uuid[ 5], uuid_command->uuid[ 6], uuid_command->uuid[ 7], 1151 | uuid_command->uuid[ 8], uuid_command->uuid[ 9], uuid_command->uuid[10], uuid_command->uuid[11], 1152 | uuid_command->uuid[12], uuid_command->uuid[13], uuid_command->uuid[14], uuid_command->uuid[15] 1153 | ); 1154 | } 1155 | } else if (cmd == LC_ID_DYLIB) { 1156 | volatile struct dylib_command *dylib_command(reinterpret_cast(load_command)); 1157 | 1158 | if (flag_t) 1159 | printf("time%zu=0x%.8x\n", filei, mach_header.Swap(dylib_command->dylib.timestamp)); 1160 | 1161 | if (flag_T) { 1162 | uint32_t timed; 1163 | 1164 | if (!timeh) 1165 | timed = timev; 1166 | else { 1167 | dylib_command->dylib.timestamp = 0; 1168 | timed = hash(reinterpret_cast(mach_header.GetBase()), mach_header.GetSize(), timev); 1169 | } 1170 | 1171 | dylib_command->dylib.timestamp = mach_header.Swap(timed); 1172 | } 1173 | } else if (cmd == LC_ENCRYPTION_INFO) { 1174 | volatile struct encryption_info_command *encryption_info_command(reinterpret_cast(load_command)); 1175 | 1176 | if (flag_D) 1177 | encryption_info_command->cryptid = mach_header.Swap(0); 1178 | 1179 | if (flag_d) { 1180 | printf("cryptoff=0x%x\n", mach_header.Swap(encryption_info_command->cryptoff)); 1181 | printf("cryptsize=0x%x\n", mach_header.Swap(encryption_info_command->cryptsize)); 1182 | printf("cryptid=0x%x\n", mach_header.Swap(encryption_info_command->cryptid)); 1183 | } 1184 | } 1185 | } 1186 | 1187 | if (flag_e) { 1188 | _assert(signature != NULL); 1189 | 1190 | uint32_t data = mach_header.Swap(signature->dataoff); 1191 | 1192 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1193 | uint8_t *blob = top + data; 1194 | struct SuperBlob *super = reinterpret_cast(blob); 1195 | 1196 | for (size_t index(0); index != Swap(super->count); ++index) 1197 | if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) { 1198 | uint32_t begin = Swap(super->index[index].offset); 1199 | struct Blob *entitlements = reinterpret_cast(blob + begin); 1200 | fwrite(entitlements + 1, 1, Swap(entitlements->length) - sizeof(struct Blob), stdout); 1201 | } 1202 | } 1203 | 1204 | if (flag_s) { 1205 | _assert(signature != NULL); 1206 | 1207 | uint32_t data = mach_header.Swap(signature->dataoff); 1208 | 1209 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1210 | uint8_t *blob = top + data; 1211 | struct SuperBlob *super = reinterpret_cast(blob); 1212 | 1213 | for (size_t index(0); index != Swap(super->count); ++index) 1214 | if (Swap(super->index[index].type) == CSSLOT_CODEDIRECTORY) { 1215 | uint32_t begin = Swap(super->index[index].offset); 1216 | struct CodeDirectory *directory = reinterpret_cast(blob + begin); 1217 | 1218 | uint8_t (*hashes)[20] = reinterpret_cast(blob + begin + Swap(directory->hashOffset)); 1219 | uint32_t pages = Swap(directory->nCodeSlots); 1220 | 1221 | if (pages != 1) 1222 | for (size_t i = 0; i != pages - 1; ++i) 1223 | sha1(hashes[i], top + 0x1000 * i, 0x1000); 1224 | if (pages != 0) 1225 | sha1(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1); 1226 | } 1227 | } 1228 | 1229 | if (flag_S) { 1230 | _assert(signature != NULL); 1231 | 1232 | uint32_t data = mach_header.Swap(signature->dataoff); 1233 | uint32_t size = mach_header.Swap(signature->datasize); 1234 | 1235 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1236 | uint8_t *blob = top + data; 1237 | struct SuperBlob *super = reinterpret_cast(blob); 1238 | super->blob.magic = Swap(CSMAGIC_EMBEDDED_SIGNATURE); 1239 | 1240 | uint32_t count = xmld == NULL ? 2 : 3; 1241 | uint32_t offset = sizeof(struct SuperBlob) + count * sizeof(struct BlobIndex); 1242 | 1243 | super->index[0].type = Swap(CSSLOT_CODEDIRECTORY); 1244 | super->index[0].offset = Swap(offset); 1245 | 1246 | uint32_t begin = offset; 1247 | struct CodeDirectory *directory = reinterpret_cast(blob + begin); 1248 | offset += sizeof(struct CodeDirectory); 1249 | 1250 | directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY); 1251 | directory->version = Swap(uint32_t(0x00020001)); 1252 | directory->flags = Swap(uint32_t(0)); 1253 | directory->codeLimit = Swap(data); 1254 | directory->hashSize = 0x14; 1255 | directory->hashType = 0x01; 1256 | directory->spare1 = 0x00; 1257 | directory->pageSize = 0x0c; 1258 | directory->spare2 = Swap(uint32_t(0)); 1259 | 1260 | directory->identOffset = Swap(offset - begin); 1261 | strcpy(reinterpret_cast(blob + offset), name); 1262 | offset += strlen(name) + 1; 1263 | 1264 | uint32_t special = xmld == NULL ? CSSLOT_REQUIREMENTS : CSSLOT_ENTITLEMENTS; 1265 | directory->nSpecialSlots = Swap(special); 1266 | 1267 | uint8_t (*hashes)[20] = reinterpret_cast(blob + offset); 1268 | memset(hashes, 0, sizeof(*hashes) * special); 1269 | 1270 | offset += sizeof(*hashes) * special; 1271 | hashes += special; 1272 | 1273 | uint32_t pages = (data + 0x1000 - 1) / 0x1000; 1274 | directory->nCodeSlots = Swap(pages); 1275 | 1276 | if (pages != 1) 1277 | for (size_t i = 0; i != pages - 1; ++i) 1278 | sha1(hashes[i], top + 0x1000 * i, 0x1000); 1279 | if (pages != 0) 1280 | sha1(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1); 1281 | 1282 | directory->hashOffset = Swap(offset - begin); 1283 | offset += sizeof(*hashes) * pages; 1284 | directory->blob.length = Swap(offset - begin); 1285 | 1286 | super->index[1].type = Swap(CSSLOT_REQUIREMENTS); 1287 | super->index[1].offset = Swap(offset); 1288 | 1289 | memcpy(blob + offset, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc); 1290 | offset += 0xc; 1291 | 1292 | if (xmld != NULL) { 1293 | super->index[2].type = Swap(CSSLOT_ENTITLEMENTS); 1294 | super->index[2].offset = Swap(offset); 1295 | 1296 | uint32_t begin = offset; 1297 | struct Blob *entitlements = reinterpret_cast(blob + begin); 1298 | offset += sizeof(struct Blob); 1299 | 1300 | memcpy(blob + offset, xmld, xmls); 1301 | offset += xmls; 1302 | 1303 | entitlements->magic = Swap(CSMAGIC_ENTITLEMENTS); 1304 | entitlements->length = Swap(offset - begin); 1305 | } 1306 | 1307 | for (size_t index(0); index != count; ++index) { 1308 | uint32_t type = Swap(super->index[index].type); 1309 | if (type != 0 && type <= special) { 1310 | uint32_t offset = Swap(super->index[index].offset); 1311 | struct Blob *local = (struct Blob *) (blob + offset); 1312 | sha1((uint8_t *) (hashes - type), (uint8_t *) local, Swap(local->length)); 1313 | } 1314 | } 1315 | 1316 | super->count = Swap(count); 1317 | super->blob.length = Swap(offset); 1318 | 1319 | if (offset > size) { 1320 | fprintf(stderr, "offset (%u) > size (%u)\n", offset, size); 1321 | _assert(false); 1322 | } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size); 1323 | 1324 | memset(blob + offset, 0, size - offset); 1325 | } 1326 | } 1327 | 1328 | if (flag_S) { 1329 | uint8_t *top = reinterpret_cast(fat_header.GetBase()); 1330 | size_t size = fat_header.GetSize(); 1331 | 1332 | char *copy; 1333 | asprintf(©, "%s.%s.cp", dir, base); 1334 | FILE *file = fopen(copy, "w+"); 1335 | size_t writ = fwrite(top, 1, size, file); 1336 | _assert(writ == size); 1337 | fclose(file); 1338 | 1339 | _syscall(unlink(temp)); 1340 | free(temp); 1341 | temp = copy; 1342 | } 1343 | 1344 | if (temp != NULL) { 1345 | struct stat info; 1346 | _syscall(stat(path, &info)); 1347 | _syscall(chown(temp, info.st_uid, info.st_gid)); 1348 | _syscall(chmod(temp, info.st_mode)); 1349 | _syscall(unlink(path)); 1350 | _syscall(rename(temp, path)); 1351 | free(temp); 1352 | } 1353 | 1354 | free(dir); 1355 | ++filei; 1356 | } catch (const char *) { 1357 | ++filee; 1358 | ++filei; 1359 | } 1360 | 1361 | return filee; 1362 | } 1363 | -------------------------------------------------------------------------------- /ldid2.cpp: -------------------------------------------------------------------------------- 1 | /* ldid - (Mach-O) Link-Loader Identity Editor 2 | * Copyright (C) 2007-2012 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Affero General Public License, Version 3 {{{ */ 6 | /* 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "minimal/stdlib.h" 23 | #include "minimal/string.h" 24 | #include "minimal/mapping.h" 25 | 26 | extern "C" { 27 | #include "sha.h" 28 | } 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | struct fat_header { 35 | uint32_t magic; 36 | uint32_t nfat_arch; 37 | } _packed; 38 | 39 | #define FAT_MAGIC 0xcafebabe 40 | #define FAT_CIGAM 0xbebafeca 41 | 42 | struct fat_arch { 43 | uint32_t cputype; 44 | uint32_t cpusubtype; 45 | uint32_t offset; 46 | uint32_t size; 47 | uint32_t align; 48 | } _packed; 49 | 50 | struct mach_header { 51 | uint32_t magic; 52 | uint32_t cputype; 53 | uint32_t cpusubtype; 54 | uint32_t filetype; 55 | uint32_t ncmds; 56 | uint32_t sizeofcmds; 57 | uint32_t flags; 58 | } _packed; 59 | 60 | #define MH_MAGIC 0xfeedface 61 | #define MH_CIGAM 0xcefaedfe 62 | 63 | #define MH_MAGIC_64 0xfeedfacf 64 | #define MH_CIGAM_64 0xcffaedfe 65 | 66 | #define MH_DYLDLINK 0x4 67 | 68 | #define MH_OBJECT 0x1 69 | #define MH_EXECUTE 0x2 70 | #define MH_DYLIB 0x6 71 | #define MH_BUNDLE 0x8 72 | #define MH_DYLIB_STUB 0x9 73 | 74 | struct load_command { 75 | uint32_t cmd; 76 | uint32_t cmdsize; 77 | } _packed; 78 | 79 | #define LC_REQ_DYLD uint32_t(0x80000000) 80 | 81 | #define LC_SEGMENT uint32_t(0x01) 82 | #define LC_SYMTAB uint32_t(0x02) 83 | #define LC_DYSYMTAB uint32_t(0x0b) 84 | #define LC_LOAD_DYLIB uint32_t(0x0c) 85 | #define LC_ID_DYLIB uint32_t(0x0d) 86 | #define LC_SEGMENT_64 uint32_t(0x19) 87 | #define LC_UUID uint32_t(0x1b) 88 | #define LC_CODE_SIGNATURE uint32_t(0x1d) 89 | #define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e) 90 | #define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD) 91 | #define LC_ENCRYPTION_INFO uint32_t(0x21) 92 | #define LC_DYLD_INFO uint32_t(0x22) 93 | #define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD) 94 | 95 | struct dylib { 96 | uint32_t name; 97 | uint32_t timestamp; 98 | uint32_t current_version; 99 | uint32_t compatibility_version; 100 | } _packed; 101 | 102 | struct dylib_command { 103 | uint32_t cmd; 104 | uint32_t cmdsize; 105 | struct dylib dylib; 106 | } _packed; 107 | 108 | struct uuid_command { 109 | uint32_t cmd; 110 | uint32_t cmdsize; 111 | uint8_t uuid[16]; 112 | } _packed; 113 | 114 | struct symtab_command { 115 | uint32_t cmd; 116 | uint32_t cmdsize; 117 | uint32_t symoff; 118 | uint32_t nsyms; 119 | uint32_t stroff; 120 | uint32_t strsize; 121 | } _packed; 122 | 123 | struct dyld_info_command { 124 | uint32_t cmd; 125 | uint32_t cmdsize; 126 | uint32_t rebase_off; 127 | uint32_t rebase_size; 128 | uint32_t bind_off; 129 | uint32_t bind_size; 130 | uint32_t weak_bind_off; 131 | uint32_t weak_bind_size; 132 | uint32_t lazy_bind_off; 133 | uint32_t lazy_bind_size; 134 | uint32_t export_off; 135 | uint32_t export_size; 136 | } _packed; 137 | 138 | struct dysymtab_command { 139 | uint32_t cmd; 140 | uint32_t cmdsize; 141 | uint32_t ilocalsym; 142 | uint32_t nlocalsym; 143 | uint32_t iextdefsym; 144 | uint32_t nextdefsym; 145 | uint32_t iundefsym; 146 | uint32_t nundefsym; 147 | uint32_t tocoff; 148 | uint32_t ntoc; 149 | uint32_t modtaboff; 150 | uint32_t nmodtab; 151 | uint32_t extrefsymoff; 152 | uint32_t nextrefsyms; 153 | uint32_t indirectsymoff; 154 | uint32_t nindirectsyms; 155 | uint32_t extreloff; 156 | uint32_t nextrel; 157 | uint32_t locreloff; 158 | uint32_t nlocrel; 159 | } _packed; 160 | 161 | struct dylib_table_of_contents { 162 | uint32_t symbol_index; 163 | uint32_t module_index; 164 | } _packed; 165 | 166 | struct dylib_module { 167 | uint32_t module_name; 168 | uint32_t iextdefsym; 169 | uint32_t nextdefsym; 170 | uint32_t irefsym; 171 | uint32_t nrefsym; 172 | uint32_t ilocalsym; 173 | uint32_t nlocalsym; 174 | uint32_t iextrel; 175 | uint32_t nextrel; 176 | uint32_t iinit_iterm; 177 | uint32_t ninit_nterm; 178 | uint32_t objc_module_info_addr; 179 | uint32_t objc_module_info_size; 180 | } _packed; 181 | 182 | struct dylib_reference { 183 | uint32_t isym:24; 184 | uint32_t flags:8; 185 | } _packed; 186 | 187 | struct relocation_info { 188 | int32_t r_address; 189 | uint32_t r_symbolnum:24; 190 | uint32_t r_pcrel:1; 191 | uint32_t r_length:2; 192 | uint32_t r_extern:1; 193 | uint32_t r_type:4; 194 | } _packed; 195 | 196 | struct nlist { 197 | union { 198 | char *n_name; 199 | int32_t n_strx; 200 | } n_un; 201 | 202 | uint8_t n_type; 203 | uint8_t n_sect; 204 | uint8_t n_desc; 205 | uint32_t n_value; 206 | } _packed; 207 | 208 | struct segment_command { 209 | uint32_t cmd; 210 | uint32_t cmdsize; 211 | char segname[16]; 212 | uint32_t vmaddr; 213 | uint32_t vmsize; 214 | uint32_t fileoff; 215 | uint32_t filesize; 216 | uint32_t maxprot; 217 | uint32_t initprot; 218 | uint32_t nsects; 219 | uint32_t flags; 220 | } _packed; 221 | 222 | struct segment_command_64 { 223 | uint32_t cmd; 224 | uint32_t cmdsize; 225 | char segname[16]; 226 | uint64_t vmaddr; 227 | uint64_t vmsize; 228 | uint64_t fileoff; 229 | uint64_t filesize; 230 | uint32_t maxprot; 231 | uint32_t initprot; 232 | uint32_t nsects; 233 | uint32_t flags; 234 | } _packed; 235 | 236 | struct section { 237 | char sectname[16]; 238 | char segname[16]; 239 | uint32_t addr; 240 | uint32_t size; 241 | uint32_t offset; 242 | uint32_t align; 243 | uint32_t reloff; 244 | uint32_t nreloc; 245 | uint32_t flags; 246 | uint32_t reserved1; 247 | uint32_t reserved2; 248 | } _packed; 249 | 250 | struct section_64 { 251 | char sectname[16]; 252 | char segname[16]; 253 | uint64_t addr; 254 | uint64_t size; 255 | uint32_t offset; 256 | uint32_t align; 257 | uint32_t reloff; 258 | uint32_t nreloc; 259 | uint32_t flags; 260 | uint32_t reserved1; 261 | uint32_t reserved2; 262 | } _packed; 263 | 264 | struct linkedit_data_command { 265 | uint32_t cmd; 266 | uint32_t cmdsize; 267 | uint32_t dataoff; 268 | uint32_t datasize; 269 | } _packed; 270 | 271 | struct encryption_info_command { 272 | uint32_t cmd; 273 | uint32_t cmdsize; 274 | uint32_t cryptoff; 275 | uint32_t cryptsize; 276 | uint32_t cryptid; 277 | } _packed; 278 | 279 | #define BIND_OPCODE_MASK 0xf0 280 | #define BIND_IMMEDIATE_MASK 0x0f 281 | #define BIND_OPCODE_DONE 0x00 282 | #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10 283 | #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20 284 | #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 285 | #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 286 | #define BIND_OPCODE_SET_TYPE_IMM 0x50 287 | #define BIND_OPCODE_SET_ADDEND_SLEB 0x60 288 | #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 289 | #define BIND_OPCODE_ADD_ADDR_ULEB 0x80 290 | #define BIND_OPCODE_DO_BIND 0x90 291 | #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xa0 292 | #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0 293 | #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0 294 | 295 | template 296 | Type_ Align(Type_ value, size_t align) { 297 | value += align - 1; 298 | value /= align; 299 | value *= align; 300 | return value; 301 | } 302 | 303 | uint16_t Swap_(uint16_t value) { 304 | return 305 | ((value >> 8) & 0x00ff) | 306 | ((value << 8) & 0xff00); 307 | } 308 | 309 | uint32_t Swap_(uint32_t value) { 310 | value = ((value >> 8) & 0x00ff00ff) | 311 | ((value << 8) & 0xff00ff00); 312 | value = ((value >> 16) & 0x0000ffff) | 313 | ((value << 16) & 0xffff0000); 314 | return value; 315 | } 316 | 317 | uint64_t Swap_(uint64_t value) { 318 | value = (value & 0x00000000ffffffffULL) << 32 | (value & 0xffffffff00000000ULL) >> 32; 319 | value = (value & 0x0000ffff0000ffffULL) << 16 | (value & 0xffff0000ffff0000ULL) >> 16; 320 | value = (value & 0x00ff00ff00ff00ffULL) << 8 | (value & 0xff00ff00ff00ff00ULL) >> 8; 321 | return value; 322 | } 323 | 324 | int16_t Swap_(int16_t value) { 325 | return Swap_(static_cast(value)); 326 | } 327 | 328 | int32_t Swap_(int32_t value) { 329 | return Swap_(static_cast(value)); 330 | } 331 | 332 | int64_t Swap_(int64_t value) { 333 | return Swap_(static_cast(value)); 334 | } 335 | 336 | bool little_(true); 337 | 338 | uint16_t Swap(uint16_t value) { 339 | return little_ ? Swap_(value) : value; 340 | } 341 | 342 | uint32_t Swap(uint32_t value) { 343 | return little_ ? Swap_(value) : value; 344 | } 345 | 346 | uint64_t Swap(uint64_t value) { 347 | return little_ ? Swap_(value) : value; 348 | } 349 | 350 | int16_t Swap(int16_t value) { 351 | return Swap(static_cast(value)); 352 | } 353 | 354 | int32_t Swap(int32_t value) { 355 | return Swap(static_cast(value)); 356 | } 357 | 358 | int64_t Swap(int64_t value) { 359 | return Swap(static_cast(value)); 360 | } 361 | 362 | template 363 | class Pointer; 364 | 365 | class Data { 366 | private: 367 | void *base_; 368 | size_t size_; 369 | 370 | protected: 371 | bool swapped_; 372 | 373 | public: 374 | Data(void *base, size_t size) : 375 | base_(base), 376 | size_(size), 377 | swapped_(false) 378 | { 379 | } 380 | 381 | uint16_t Swap(uint16_t value) const { 382 | return swapped_ ? Swap_(value) : value; 383 | } 384 | 385 | uint32_t Swap(uint32_t value) const { 386 | return swapped_ ? Swap_(value) : value; 387 | } 388 | 389 | uint64_t Swap(uint64_t value) const { 390 | return swapped_ ? Swap_(value) : value; 391 | } 392 | 393 | int16_t Swap(int16_t value) const { 394 | return Swap(static_cast(value)); 395 | } 396 | 397 | int32_t Swap(int32_t value) const { 398 | return Swap(static_cast(value)); 399 | } 400 | 401 | int64_t Swap(int64_t value) const { 402 | return Swap(static_cast(value)); 403 | } 404 | 405 | void *GetBase() const { 406 | return base_; 407 | } 408 | 409 | size_t GetSize() const { 410 | return size_; 411 | } 412 | }; 413 | 414 | class MachHeader : 415 | public Data 416 | { 417 | private: 418 | bool bits64_; 419 | 420 | struct mach_header *mach_header_; 421 | struct load_command *load_command_; 422 | 423 | public: 424 | MachHeader(void *base, size_t size) : 425 | Data(base, size) 426 | { 427 | mach_header_ = (mach_header *) base; 428 | 429 | switch (Swap(mach_header_->magic)) { 430 | case MH_CIGAM: 431 | swapped_ = !swapped_; 432 | case MH_MAGIC: 433 | bits64_ = false; 434 | break; 435 | 436 | case MH_CIGAM_64: 437 | swapped_ = !swapped_; 438 | case MH_MAGIC_64: 439 | bits64_ = true; 440 | break; 441 | 442 | default: 443 | _assert(false); 444 | } 445 | 446 | void *post = mach_header_ + 1; 447 | if (bits64_) 448 | post = (uint32_t *) post + 1; 449 | load_command_ = (struct load_command *) post; 450 | 451 | _assert( 452 | Swap(mach_header_->filetype) == MH_EXECUTE || 453 | Swap(mach_header_->filetype) == MH_DYLIB || 454 | Swap(mach_header_->filetype) == MH_BUNDLE 455 | ); 456 | } 457 | 458 | struct mach_header *operator ->() const { 459 | return mach_header_; 460 | } 461 | 462 | operator struct mach_header *() const { 463 | return mach_header_; 464 | } 465 | 466 | uint32_t GetCPUType() const { 467 | return Swap(mach_header_->cputype); 468 | } 469 | 470 | uint32_t GetCPUSubtype() const { 471 | return Swap(mach_header_->cpusubtype) & 0xff; 472 | } 473 | 474 | struct load_command *GetLoadCommand() const { 475 | return load_command_; 476 | } 477 | 478 | std::vector GetLoadCommands() const { 479 | std::vector load_commands; 480 | 481 | struct load_command *load_command = load_command_; 482 | for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { 483 | load_commands.push_back(load_command); 484 | load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize)); 485 | } 486 | 487 | return load_commands; 488 | } 489 | 490 | std::vector GetSegments(const char *segment_name) const { 491 | std::vector segment_commands; 492 | 493 | _foreach (load_command, GetLoadCommands()) { 494 | if (Swap(load_command->cmd) == LC_SEGMENT) { 495 | segment_command *segment_command = reinterpret_cast(load_command); 496 | if (strncmp(segment_command->segname, segment_name, 16) == 0) 497 | segment_commands.push_back(segment_command); 498 | } 499 | } 500 | 501 | return segment_commands; 502 | } 503 | 504 | std::vector GetSegments64(const char *segment_name) const { 505 | std::vector segment_commands; 506 | 507 | _foreach (load_command, GetLoadCommands()) { 508 | if (Swap(load_command->cmd) == LC_SEGMENT_64) { 509 | segment_command_64 *segment_command = reinterpret_cast(load_command); 510 | if (strncmp(segment_command->segname, segment_name, 16) == 0) 511 | segment_commands.push_back(segment_command); 512 | } 513 | } 514 | 515 | return segment_commands; 516 | } 517 | 518 | std::vector
GetSections(const char *segment_name, const char *section_name) const { 519 | std::vector
sections; 520 | 521 | _foreach (segment, GetSegments(segment_name)) { 522 | section *section = (struct section *) (segment + 1); 523 | 524 | uint32_t sect; 525 | for (sect = 0; sect != Swap(segment->nsects); ++sect) { 526 | if (strncmp(section->sectname, section_name, 16) == 0) 527 | sections.push_back(section); 528 | ++section; 529 | } 530 | } 531 | 532 | return sections; 533 | } 534 | 535 | template 536 | Pointer GetPointer(uint32_t address, const char *segment_name = NULL) const { 537 | load_command *load_command = (struct load_command *) (mach_header_ + 1); 538 | uint32_t cmd; 539 | 540 | for (cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { 541 | if (Swap(load_command->cmd) == LC_SEGMENT) { 542 | segment_command *segment_command = (struct segment_command *) load_command; 543 | if (segment_name != NULL && strncmp(segment_command->segname, segment_name, 16) != 0) 544 | goto next_command; 545 | 546 | section *sections = (struct section *) (segment_command + 1); 547 | 548 | uint32_t sect; 549 | for (sect = 0; sect != Swap(segment_command->nsects); ++sect) { 550 | section *section = §ions[sect]; 551 | //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); 552 | if (address >= Swap(section->addr) && address < Swap(section->addr) + Swap(section->size)) { 553 | //printf("0x%.8x %s\n", address, segment_command->segname); 554 | return Pointer(this, reinterpret_cast(address - Swap(section->addr) + Swap(section->offset) + (char *) mach_header_)); 555 | } 556 | } 557 | } 558 | 559 | next_command: 560 | load_command = (struct load_command *) ((char *) load_command + Swap(load_command->cmdsize)); 561 | } 562 | 563 | return Pointer(this); 564 | } 565 | 566 | template 567 | Pointer GetOffset(uint32_t offset) { 568 | return Pointer(this, reinterpret_cast(offset + (uint8_t *) mach_header_)); 569 | } 570 | }; 571 | 572 | class FatMachHeader : 573 | public MachHeader 574 | { 575 | private: 576 | fat_arch *fat_arch_; 577 | 578 | public: 579 | FatMachHeader(void *base, size_t size, fat_arch *fat_arch) : 580 | MachHeader(base, size), 581 | fat_arch_(fat_arch) 582 | { 583 | } 584 | 585 | fat_arch *GetFatArch() const { 586 | return fat_arch_; 587 | } 588 | }; 589 | 590 | class FatHeader : 591 | public Data 592 | { 593 | private: 594 | fat_header *fat_header_; 595 | std::vector mach_headers_; 596 | 597 | public: 598 | FatHeader(void *base, size_t size) : 599 | Data(base, size) 600 | { 601 | fat_header_ = reinterpret_cast(base); 602 | 603 | if (Swap(fat_header_->magic) == FAT_CIGAM) { 604 | swapped_ = !swapped_; 605 | goto fat; 606 | } else if (Swap(fat_header_->magic) != FAT_MAGIC) { 607 | fat_header_ = NULL; 608 | mach_headers_.push_back(FatMachHeader(base, size, NULL)); 609 | } else fat: { 610 | size_t fat_narch = Swap(fat_header_->nfat_arch); 611 | fat_arch *fat_arch = reinterpret_cast(fat_header_ + 1); 612 | size_t arch; 613 | for (arch = 0; arch != fat_narch; ++arch) { 614 | uint32_t arch_offset = Swap(fat_arch->offset); 615 | uint32_t arch_size = Swap(fat_arch->size); 616 | mach_headers_.push_back(FatMachHeader((uint8_t *) base + arch_offset, arch_size, fat_arch)); 617 | ++fat_arch; 618 | } 619 | } 620 | } 621 | 622 | std::vector &GetMachHeaders() { 623 | return mach_headers_; 624 | } 625 | 626 | bool IsFat() const { 627 | return fat_header_ != NULL; 628 | } 629 | 630 | struct fat_header *operator ->() const { 631 | return fat_header_; 632 | } 633 | 634 | operator struct fat_header *() const { 635 | return fat_header_; 636 | } 637 | }; 638 | 639 | FatHeader Map(const char *path, bool ro = false) { 640 | size_t size; 641 | void *base(map(path, 0, _not(size_t), &size, ro)); 642 | return FatHeader(base, size); 643 | } 644 | 645 | template 646 | class Pointer { 647 | private: 648 | const MachHeader *framework_; 649 | const Target_ *pointer_; 650 | 651 | public: 652 | Pointer(const MachHeader *framework = NULL, const Target_ *pointer = NULL) : 653 | framework_(framework), 654 | pointer_(pointer) 655 | { 656 | } 657 | 658 | operator const Target_ *() const { 659 | return pointer_; 660 | } 661 | 662 | const Target_ *operator ->() const { 663 | return pointer_; 664 | } 665 | 666 | Pointer &operator ++() { 667 | ++pointer_; 668 | return *this; 669 | } 670 | 671 | template 672 | Value_ Swap(Value_ value) { 673 | return framework_->Swap(value); 674 | } 675 | }; 676 | 677 | #define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02) 678 | #define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0) 679 | #define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171) 680 | 681 | #define CSSLOT_CODEDIRECTORY uint32_t(0) 682 | #define CSSLOT_REQUIREMENTS uint32_t(2) 683 | #define CSSLOT_ENTITLEMENTS uint32_t(5) 684 | 685 | struct BlobIndex { 686 | uint32_t type; 687 | uint32_t offset; 688 | } _packed; 689 | 690 | struct Blob { 691 | uint32_t magic; 692 | uint32_t length; 693 | } _packed; 694 | 695 | struct SuperBlob { 696 | struct Blob blob; 697 | uint32_t count; 698 | struct BlobIndex index[]; 699 | } _packed; 700 | 701 | struct CodeDirectory { 702 | struct Blob blob; 703 | uint32_t version; 704 | uint32_t flags; 705 | uint32_t hashOffset; 706 | uint32_t identOffset; 707 | uint32_t nSpecialSlots; 708 | uint32_t nCodeSlots; 709 | uint32_t codeLimit; 710 | uint8_t hashSize; 711 | uint8_t hashType; 712 | uint8_t spare1; 713 | uint8_t pageSize; 714 | uint32_t spare2; 715 | } _packed; 716 | 717 | extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); 718 | 719 | void sha2(uint8_t *hash, uint8_t *data, size_t size) { 720 | SHA256Context context; 721 | SHA256Reset(&context); 722 | SHA256Input(&context, data, size); 723 | SHA256Result(&context, hash); 724 | } 725 | 726 | struct CodesignAllocation { 727 | FatMachHeader mach_header_; 728 | uint32_t offset_; 729 | uint32_t size_; 730 | uint32_t alloc_; 731 | uint32_t align_; 732 | 733 | CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc, size_t align) : 734 | mach_header_(mach_header), 735 | offset_(offset), 736 | size_(size), 737 | alloc_(alloc), 738 | align_(align) 739 | { 740 | } 741 | }; 742 | 743 | int main(int argc, const char *argv[]) { 744 | union { 745 | uint16_t word; 746 | uint8_t byte[2]; 747 | } endian = {1}; 748 | 749 | little_ = endian.byte[0]; 750 | 751 | bool flag_R(false); 752 | bool flag_r(false); 753 | 754 | bool flag_t(false); 755 | bool flag_p(false); 756 | bool flag_u(false); 757 | bool flag_e(false); 758 | 759 | bool flag_T(false); 760 | 761 | bool flag_S(false); 762 | bool flag_s(false); 763 | 764 | bool flag_O(false); 765 | 766 | bool flag_D(false); 767 | bool flag_d(false); 768 | 769 | bool flag_A(false); 770 | bool flag_a(false); 771 | 772 | uint32_t flag_CPUType(_not(uint32_t)); 773 | uint32_t flag_CPUSubtype(_not(uint32_t)); 774 | 775 | const char *flag_I(NULL); 776 | 777 | bool timeh(false); 778 | uint32_t timev(0); 779 | 780 | const void *xmld(NULL); 781 | size_t xmls(0); 782 | 783 | uintptr_t noffset(_not(uintptr_t)); 784 | uintptr_t woffset(_not(uintptr_t)); 785 | 786 | std::vector files; 787 | 788 | if (argc == 1) { 789 | fprintf(stderr, "usage: %s -S[entitlements.xml] \n", argv[0]); 790 | fprintf(stderr, " %s -e MobileSafari\n", argv[0]); 791 | fprintf(stderr, " %s -S cat\n", argv[0]); 792 | fprintf(stderr, " %s -Stfp.xml gdb\n", argv[0]); 793 | exit(0); 794 | } 795 | 796 | for (int argi(1); argi != argc; ++argi) 797 | if (argv[argi][0] != '-') 798 | files.push_back(argv[argi]); 799 | else switch (argv[argi][1]) { 800 | case 'R': flag_R = true; break; 801 | case 'r': flag_r = true; break; 802 | 803 | case 't': flag_t = true; break; 804 | case 'u': flag_u = true; break; 805 | case 'p': flag_p = true; break; 806 | case 'e': flag_e = true; break; 807 | case 'O': flag_O = true; break; 808 | 809 | case 'D': flag_D = true; break; 810 | case 'd': flag_d = true; break; 811 | 812 | case 'a': flag_a = true; break; 813 | 814 | case 'A': 815 | flag_A = true; 816 | if (argv[argi][2] != '\0') { 817 | const char *cpu = argv[argi] + 2; 818 | const char *colon = strchr(cpu, ':'); 819 | _assert(colon != NULL); 820 | char *arge; 821 | flag_CPUType = strtoul(cpu, &arge, 0); 822 | _assert(arge == colon); 823 | flag_CPUSubtype = strtoul(colon + 1, &arge, 0); 824 | _assert(arge == argv[argi] + strlen(argv[argi])); 825 | } 826 | break; 827 | 828 | case 's': 829 | _assert(!flag_S); 830 | flag_s = true; 831 | break; 832 | 833 | case 'S': 834 | _assert(!flag_s); 835 | flag_S = true; 836 | if (argv[argi][2] != '\0') { 837 | const char *xml = argv[argi] + 2; 838 | xmld = map(xml, 0, _not(size_t), &xmls, true); 839 | } 840 | break; 841 | 842 | case 'T': { 843 | flag_T = true; 844 | if (argv[argi][2] == '-') 845 | timeh = true; 846 | else { 847 | char *arge; 848 | timev = strtoul(argv[argi] + 2, &arge, 0); 849 | _assert(arge == argv[argi] + strlen(argv[argi])); 850 | } 851 | } break; 852 | 853 | case 'I': { 854 | flag_I = argv[argi] + 2; 855 | } break; 856 | 857 | case 'n': { 858 | char *arge; 859 | noffset = strtoul(argv[argi] + 2, &arge, 0); 860 | _assert(arge == argv[argi] + strlen(argv[argi])); 861 | } break; 862 | 863 | case 'w': { 864 | char *arge; 865 | woffset = strtoul(argv[argi] + 2, &arge, 0); 866 | _assert(arge == argv[argi] + strlen(argv[argi])); 867 | } break; 868 | 869 | default: 870 | goto usage; 871 | break; 872 | } 873 | 874 | if (files.empty()) usage: { 875 | exit(0); 876 | } 877 | 878 | size_t filei(0), filee(0); 879 | _foreach (file, files) try { 880 | const char *path(file.c_str()); 881 | const char *base = strrchr(path, '/'); 882 | char *temp(NULL), *dir; 883 | 884 | if (base != NULL) 885 | dir = strndup_(path, base++ - path + 1); 886 | else { 887 | dir = strdup(""); 888 | base = path; 889 | } 890 | 891 | const char *name(flag_I ?: base); 892 | 893 | if (flag_r) { 894 | uint32_t clip(0); { 895 | FatHeader fat_header(Map(path)); 896 | _foreach (mach_header, fat_header.GetMachHeaders()) { 897 | if (flag_A) { 898 | if (mach_header.GetCPUType() != flag_CPUType) 899 | continue; 900 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 901 | continue; 902 | } 903 | 904 | mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK); 905 | 906 | uint32_t size(_not(uint32_t)); { 907 | _foreach (load_command, mach_header.GetLoadCommands()) { 908 | switch (mach_header.Swap(load_command->cmd)) { 909 | case LC_CODE_SIGNATURE: { 910 | struct linkedit_data_command *signature = reinterpret_cast(load_command); 911 | memset(reinterpret_cast(mach_header.GetBase()) + mach_header.Swap(signature->dataoff), 0, mach_header.Swap(signature->datasize)); 912 | memset(signature, 0, sizeof(struct linkedit_data_command)); 913 | 914 | mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) - 1); 915 | mach_header->sizeofcmds = mach_header.Swap(uint32_t(mach_header.Swap(mach_header->sizeofcmds) - sizeof(struct linkedit_data_command))); 916 | } break; 917 | 918 | case LC_SYMTAB: { 919 | struct symtab_command *symtab = reinterpret_cast(load_command); 920 | size = mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize); 921 | } break; 922 | } 923 | } 924 | } 925 | 926 | _assert(size != _not(uint32_t)); 927 | 928 | _foreach (segment, mach_header.GetSegments("__LINKEDIT")) { 929 | segment->filesize -= mach_header.GetSize() - size; 930 | 931 | if (fat_arch *fat_arch = mach_header.GetFatArch()) { 932 | fat_arch->size = fat_header.Swap(size); 933 | clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size); 934 | } else 935 | clip = std::max(clip, size); 936 | } 937 | 938 | _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) { 939 | segment->filesize -= mach_header.GetSize() - size; 940 | 941 | if (fat_arch *fat_arch = mach_header.GetFatArch()) { 942 | fat_arch->size = fat_header.Swap(size); 943 | clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size); 944 | } else 945 | clip = std::max(clip, size); 946 | } 947 | } 948 | } 949 | 950 | if (clip != 0) 951 | _syscall(truncate(path, clip)); 952 | } 953 | 954 | if (flag_S) { 955 | FatHeader source(Map(path)); 956 | 957 | size_t offset(0); 958 | 959 | if (source.IsFat()) 960 | offset += sizeof(fat_header) + sizeof(fat_arch) * source.Swap(source->nfat_arch); 961 | 962 | std::vector allocations; { 963 | _foreach (mach_header, source.GetMachHeaders()) { 964 | if (flag_A) { 965 | if (mach_header.GetCPUType() != flag_CPUType) 966 | continue; 967 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 968 | continue; 969 | } 970 | 971 | mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK); 972 | 973 | size_t size(_not(size_t)); { 974 | _foreach (load_command, mach_header.GetLoadCommands()) { 975 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 976 | if (cmd == LC_CODE_SIGNATURE) { 977 | struct linkedit_data_command *signature = reinterpret_cast(load_command); 978 | size = mach_header.Swap(signature->dataoff); 979 | _assert(size < mach_header.GetSize()); 980 | break; 981 | } 982 | } 983 | 984 | if (size == _not(size_t)) 985 | size = mach_header.GetSize(); 986 | } 987 | 988 | size_t alloc(0); 989 | alloc += sizeof(struct SuperBlob); 990 | uint32_t special(0); 991 | 992 | special = std::max(special, CSSLOT_CODEDIRECTORY); 993 | alloc += sizeof(struct BlobIndex); 994 | alloc += sizeof(struct CodeDirectory); 995 | alloc += strlen(name) + 1; 996 | 997 | special = std::max(special, CSSLOT_REQUIREMENTS); 998 | alloc += sizeof(struct BlobIndex); 999 | alloc += 0xc; 1000 | 1001 | if (xmld != NULL) { 1002 | special = std::max(special, CSSLOT_ENTITLEMENTS); 1003 | alloc += sizeof(struct BlobIndex); 1004 | alloc += sizeof(struct Blob); 1005 | alloc += xmls; 1006 | } 1007 | 1008 | size_t normal((size + 0x1000 - 1) / 0x1000); 1009 | alloc = Align(alloc + (special + normal) * 0x20, 16); 1010 | 1011 | fat_arch *fat_arch(mach_header.GetFatArch()); 1012 | uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align)); 1013 | offset = Align(offset, 1 << align); 1014 | 1015 | allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc, align)); 1016 | offset += size + alloc; 1017 | offset = Align(offset, 16); 1018 | } 1019 | } 1020 | 1021 | asprintf(&temp, "%s.%s.cs", dir, base); 1022 | fclose(fopen(temp, "w+")); 1023 | _syscall(truncate(temp, offset)); 1024 | 1025 | void *file(map(temp, 0, offset, NULL, false)); 1026 | memset(file, 0, offset); 1027 | 1028 | fat_arch *fat_arch; 1029 | if (!source.IsFat()) 1030 | fat_arch = NULL; 1031 | else { 1032 | fat_header *fat_header(reinterpret_cast(file)); 1033 | fat_header->magic = Swap(FAT_MAGIC); 1034 | fat_header->nfat_arch = Swap(source.Swap(source->nfat_arch)); 1035 | fat_arch = reinterpret_cast(fat_header + 1); 1036 | } 1037 | 1038 | _foreach (allocation, allocations) { 1039 | const FatMachHeader &source(allocation.mach_header_); 1040 | 1041 | uint32_t align(allocation.size_); 1042 | align = Align(align, 0x10); 1043 | 1044 | if (fat_arch != NULL) { 1045 | fat_arch->cputype = Swap(source->cputype); 1046 | fat_arch->cpusubtype = Swap(source->cpusubtype); 1047 | fat_arch->offset = Swap(allocation.offset_); 1048 | fat_arch->size = Swap(align + allocation.alloc_); 1049 | fat_arch->align = Swap(allocation.align_); 1050 | ++fat_arch; 1051 | } 1052 | 1053 | void *target(reinterpret_cast(file) + allocation.offset_); 1054 | memcpy(target, source, allocation.size_); 1055 | MachHeader mach_header(target, align + allocation.alloc_); 1056 | 1057 | struct linkedit_data_command *signature(NULL); 1058 | _foreach (load_command, mach_header.GetLoadCommands()) { 1059 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 1060 | if (cmd != LC_CODE_SIGNATURE) 1061 | continue; 1062 | signature = reinterpret_cast(load_command); 1063 | break; 1064 | } 1065 | 1066 | if (signature == NULL) { 1067 | mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) + 1); 1068 | signature = reinterpret_cast(reinterpret_cast(mach_header.GetLoadCommand()) + mach_header.Swap(mach_header->sizeofcmds)); 1069 | mach_header->sizeofcmds = mach_header.Swap(mach_header.Swap(mach_header->sizeofcmds) + uint32_t(sizeof(*signature))); 1070 | signature->cmd = mach_header.Swap(LC_CODE_SIGNATURE); 1071 | signature->cmdsize = mach_header.Swap(uint32_t(sizeof(*signature))); 1072 | } 1073 | 1074 | signature->dataoff = mach_header.Swap(align); 1075 | signature->datasize = mach_header.Swap(allocation.alloc_); 1076 | 1077 | _foreach (segment, mach_header.GetSegments("__LINKEDIT")) { 1078 | size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); 1079 | segment->filesize = size; 1080 | segment->vmsize = Align(size, 0x1000); 1081 | } 1082 | 1083 | _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) { 1084 | size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); 1085 | segment->filesize = size; 1086 | segment->vmsize = Align(size, 0x1000); 1087 | } 1088 | } 1089 | } 1090 | 1091 | if (flag_p) 1092 | printf("path%zu='%s'\n", filei, file.c_str()); 1093 | 1094 | FatHeader fat_header(Map(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D))); 1095 | struct linkedit_data_command *signature(NULL); 1096 | 1097 | _foreach (mach_header, fat_header.GetMachHeaders()) { 1098 | if (flag_A) { 1099 | if (mach_header.GetCPUType() != flag_CPUType) 1100 | continue; 1101 | if (mach_header.GetCPUSubtype() != flag_CPUSubtype) 1102 | continue; 1103 | } 1104 | 1105 | if (flag_a) 1106 | printf("cpu=0x%x:0x%x\n", mach_header.GetCPUType(), mach_header.GetCPUSubtype()); 1107 | 1108 | if (flag_d) { 1109 | if (struct fat_arch *fat_arch = mach_header.GetFatArch()) 1110 | printf("offset=0x%x\n", Swap(fat_arch->offset)); 1111 | else 1112 | printf("offset=0x0\n"); 1113 | } 1114 | 1115 | if (woffset != _not(uintptr_t)) { 1116 | Pointer wvalue(mach_header.GetPointer(woffset)); 1117 | if (wvalue == NULL) 1118 | printf("(null) %p\n", reinterpret_cast(woffset)); 1119 | else 1120 | printf("0x%.08x\n", *wvalue); 1121 | } 1122 | 1123 | if (noffset != _not(uintptr_t)) 1124 | printf("%s\n", &*mach_header.GetPointer(noffset)); 1125 | 1126 | if (flag_d) 1127 | _foreach(segment, mach_header.GetSegments("__TEXT")) { 1128 | printf("vmaddr=0x%x\n", mach_header.Swap(segment->vmaddr)); 1129 | printf("fileoff=0x%x\n", mach_header.Swap(segment->fileoff)); 1130 | } 1131 | 1132 | if (flag_O) { 1133 | _foreach(section, mach_header.GetSections("__TEXT", "__text")) 1134 | section->addr = mach_header.Swap(0); 1135 | } 1136 | 1137 | _foreach (load_command, mach_header.GetLoadCommands()) { 1138 | uint32_t cmd(mach_header.Swap(load_command->cmd)); 1139 | 1140 | if (flag_R && cmd == LC_REEXPORT_DYLIB) 1141 | load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB); 1142 | else if (cmd == LC_CODE_SIGNATURE) 1143 | signature = reinterpret_cast(load_command); 1144 | else if (cmd == LC_UUID) { 1145 | volatile struct uuid_command *uuid_command(reinterpret_cast(load_command)); 1146 | 1147 | if (flag_u) { 1148 | printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei, 1149 | uuid_command->uuid[ 0], uuid_command->uuid[ 1], uuid_command->uuid[ 2], uuid_command->uuid[ 3], 1150 | uuid_command->uuid[ 4], uuid_command->uuid[ 5], uuid_command->uuid[ 6], uuid_command->uuid[ 7], 1151 | uuid_command->uuid[ 8], uuid_command->uuid[ 9], uuid_command->uuid[10], uuid_command->uuid[11], 1152 | uuid_command->uuid[12], uuid_command->uuid[13], uuid_command->uuid[14], uuid_command->uuid[15] 1153 | ); 1154 | } 1155 | } else if (cmd == LC_ID_DYLIB) { 1156 | volatile struct dylib_command *dylib_command(reinterpret_cast(load_command)); 1157 | 1158 | if (flag_t) 1159 | printf("time%zu=0x%.8x\n", filei, mach_header.Swap(dylib_command->dylib.timestamp)); 1160 | 1161 | if (flag_T) { 1162 | uint32_t timed; 1163 | 1164 | if (!timeh) 1165 | timed = timev; 1166 | else { 1167 | dylib_command->dylib.timestamp = 0; 1168 | timed = hash(reinterpret_cast(mach_header.GetBase()), mach_header.GetSize(), timev); 1169 | } 1170 | 1171 | dylib_command->dylib.timestamp = mach_header.Swap(timed); 1172 | } 1173 | } else if (cmd == LC_ENCRYPTION_INFO) { 1174 | volatile struct encryption_info_command *encryption_info_command(reinterpret_cast(load_command)); 1175 | 1176 | if (flag_D) 1177 | encryption_info_command->cryptid = mach_header.Swap(0); 1178 | 1179 | if (flag_d) { 1180 | printf("cryptoff=0x%x\n", mach_header.Swap(encryption_info_command->cryptoff)); 1181 | printf("cryptsize=0x%x\n", mach_header.Swap(encryption_info_command->cryptsize)); 1182 | printf("cryptid=0x%x\n", mach_header.Swap(encryption_info_command->cryptid)); 1183 | } 1184 | } 1185 | } 1186 | 1187 | if (flag_e) { 1188 | _assert(signature != NULL); 1189 | 1190 | uint32_t data = mach_header.Swap(signature->dataoff); 1191 | 1192 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1193 | uint8_t *blob = top + data; 1194 | struct SuperBlob *super = reinterpret_cast(blob); 1195 | 1196 | for (size_t index(0); index != Swap(super->count); ++index) 1197 | if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) { 1198 | uint32_t begin = Swap(super->index[index].offset); 1199 | struct Blob *entitlements = reinterpret_cast(blob + begin); 1200 | fwrite(entitlements + 1, 1, Swap(entitlements->length) - sizeof(struct Blob), stdout); 1201 | } 1202 | } 1203 | 1204 | if (flag_s) { 1205 | _assert(signature != NULL); 1206 | 1207 | uint32_t data = mach_header.Swap(signature->dataoff); 1208 | 1209 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1210 | uint8_t *blob = top + data; 1211 | struct SuperBlob *super = reinterpret_cast(blob); 1212 | 1213 | for (size_t index(0); index != Swap(super->count); ++index) 1214 | if (Swap(super->index[index].type) == CSSLOT_CODEDIRECTORY) { 1215 | uint32_t begin = Swap(super->index[index].offset); 1216 | struct CodeDirectory *directory = reinterpret_cast(blob + begin); 1217 | 1218 | uint8_t (*hashes)[32] = reinterpret_cast(blob + begin + Swap(directory->hashOffset)); 1219 | uint32_t pages = Swap(directory->nCodeSlots); 1220 | 1221 | if (pages != 1) 1222 | for (size_t i = 0; i != pages - 1; ++i) 1223 | sha2(hashes[i], top + 0x1000 * i, 0x1000); 1224 | if (pages != 0) 1225 | sha2(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1); 1226 | } 1227 | } 1228 | 1229 | if (flag_S) { 1230 | _assert(signature != NULL); 1231 | 1232 | uint32_t data = mach_header.Swap(signature->dataoff); 1233 | uint32_t size = mach_header.Swap(signature->datasize); 1234 | 1235 | uint8_t *top = reinterpret_cast(mach_header.GetBase()); 1236 | uint8_t *blob = top + data; 1237 | struct SuperBlob *super = reinterpret_cast(blob); 1238 | super->blob.magic = Swap(CSMAGIC_EMBEDDED_SIGNATURE); 1239 | 1240 | uint32_t count = xmld == NULL ? 2 : 3; 1241 | uint32_t offset = sizeof(struct SuperBlob) + count * sizeof(struct BlobIndex); 1242 | 1243 | super->index[0].type = Swap(CSSLOT_CODEDIRECTORY); 1244 | super->index[0].offset = Swap(offset); 1245 | 1246 | uint32_t begin = offset; 1247 | struct CodeDirectory *directory = reinterpret_cast(blob + begin); 1248 | offset += sizeof(struct CodeDirectory); 1249 | 1250 | directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY); 1251 | directory->version = Swap(uint32_t(0x00020001)); 1252 | directory->flags = Swap(uint32_t(0)); 1253 | directory->codeLimit = Swap(data); 1254 | directory->hashSize = 0x20; 1255 | directory->hashType = 0x02; 1256 | directory->spare1 = 0x00; 1257 | directory->pageSize = 0x0c; 1258 | directory->spare2 = Swap(uint32_t(0)); 1259 | 1260 | directory->identOffset = Swap(offset - begin); 1261 | strcpy(reinterpret_cast(blob + offset), name); 1262 | offset += strlen(name) + 1; 1263 | 1264 | uint32_t special = xmld == NULL ? CSSLOT_REQUIREMENTS : CSSLOT_ENTITLEMENTS; 1265 | directory->nSpecialSlots = Swap(special); 1266 | 1267 | uint8_t (*hashes)[32] = reinterpret_cast(blob + offset); 1268 | memset(hashes, 0, sizeof(*hashes) * special); 1269 | 1270 | offset += sizeof(*hashes) * special; 1271 | hashes += special; 1272 | 1273 | uint32_t pages = (data + 0x1000 - 1) / 0x1000; 1274 | directory->nCodeSlots = Swap(pages); 1275 | 1276 | if (pages != 1) 1277 | for (size_t i = 0; i != pages - 1; ++i) 1278 | sha2(hashes[i], top + 0x1000 * i, 0x1000); 1279 | if (pages != 0) 1280 | sha2(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1); 1281 | 1282 | directory->hashOffset = Swap(offset - begin); 1283 | offset += sizeof(*hashes) * pages; 1284 | directory->blob.length = Swap(offset - begin); 1285 | 1286 | super->index[1].type = Swap(CSSLOT_REQUIREMENTS); 1287 | super->index[1].offset = Swap(offset); 1288 | 1289 | memcpy(blob + offset, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc); 1290 | offset += 0xc; 1291 | 1292 | if (xmld != NULL) { 1293 | super->index[2].type = Swap(CSSLOT_ENTITLEMENTS); 1294 | super->index[2].offset = Swap(offset); 1295 | 1296 | uint32_t begin = offset; 1297 | struct Blob *entitlements = reinterpret_cast(blob + begin); 1298 | offset += sizeof(struct Blob); 1299 | 1300 | memcpy(blob + offset, xmld, xmls); 1301 | offset += xmls; 1302 | 1303 | entitlements->magic = Swap(CSMAGIC_ENTITLEMENTS); 1304 | entitlements->length = Swap(offset - begin); 1305 | } 1306 | 1307 | for (size_t index(0); index != count; ++index) { 1308 | uint32_t type = Swap(super->index[index].type); 1309 | if (type != 0 && type <= special) { 1310 | uint32_t offset = Swap(super->index[index].offset); 1311 | struct Blob *local = (struct Blob *) (blob + offset); 1312 | sha2((uint8_t *) (hashes - type), (uint8_t *) local, Swap(local->length)); 1313 | } 1314 | } 1315 | 1316 | super->count = Swap(count); 1317 | super->blob.length = Swap(offset); 1318 | 1319 | if (offset > size) { 1320 | fprintf(stderr, "offset (%u) > size (%u)\n", offset, size); 1321 | _assert(false); 1322 | } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size); 1323 | 1324 | memset(blob + offset, 0, size - offset); 1325 | } 1326 | } 1327 | 1328 | if (flag_S) { 1329 | uint8_t *top = reinterpret_cast(fat_header.GetBase()); 1330 | size_t size = fat_header.GetSize(); 1331 | 1332 | char *copy; 1333 | asprintf(©, "%s.%s.cp", dir, base); 1334 | FILE *file = fopen(copy, "w+"); 1335 | size_t writ = fwrite(top, 1, size, file); 1336 | _assert(writ == size); 1337 | fclose(file); 1338 | 1339 | _syscall(unlink(temp)); 1340 | free(temp); 1341 | temp = copy; 1342 | } 1343 | 1344 | if (temp != NULL) { 1345 | struct stat info; 1346 | _syscall(stat(path, &info)); 1347 | _syscall(chown(temp, info.st_uid, info.st_gid)); 1348 | _syscall(chmod(temp, info.st_mode)); 1349 | _syscall(unlink(path)); 1350 | _syscall(rename(temp, path)); 1351 | free(temp); 1352 | } 1353 | 1354 | free(dir); 1355 | ++filei; 1356 | } catch (const char *) { 1357 | ++filee; 1358 | ++filei; 1359 | } 1360 | 1361 | return filee; 1362 | } 1363 | --------------------------------------------------------------------------------