├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── _example ├── custom_func │ └── main.go ├── hook │ └── hook.go ├── limit │ └── limit.go ├── mod_regexp │ ├── Makefile │ ├── extension.go │ └── sqlite3_mod_regexp.c ├── mod_vtable │ ├── Makefile │ ├── extension.go │ ├── picojson.h │ └── sqlite3_mod_vtable.cc ├── simple │ ├── build.sh │ └── simple.go ├── trace │ └── main.go └── vtable │ ├── main.go │ └── vtable.go ├── aes.c ├── aes_tab.c ├── backup.go ├── backup_test.go ├── callback.go ├── callback_test.go ├── cbc_decrypt.c ├── cbc_done.c ├── cbc_encrypt.c ├── cbc_getiv.c ├── cbc_setiv.c ├── cbc_start.c ├── compare_testvector.c ├── crypt.c ├── crypt_argchk.c ├── crypt_cipher_descriptor.c ├── crypt_cipher_is_valid.c ├── crypt_constants.c ├── crypt_find_cipher.c ├── crypt_find_cipher_any.c ├── crypt_find_cipher_id.c ├── crypt_find_hash.c ├── crypt_find_hash_any.c ├── crypt_find_hash_id.c ├── crypt_find_hash_oid.c ├── crypt_find_prng.c ├── crypt_fsa.c ├── crypt_hash_descriptor.c ├── crypt_hash_is_valid.c ├── crypt_inits.c ├── crypt_ltc_mp_descriptor.c ├── crypt_prng_descriptor.c ├── crypt_prng_is_valid.c ├── crypt_prng_rng_descriptor.c ├── crypt_register_cipher.c ├── crypt_register_hash.c ├── crypt_register_prng.c ├── crypt_sizes.c ├── crypt_unregister_cipher.c ├── crypt_unregister_hash.c ├── crypt_unregister_prng.c ├── crypto.h ├── doc.go ├── error.go ├── error_test.go ├── fortuna.c ├── hash_memory.c ├── hash_memory_multi.c ├── hmac_done.c ├── hmac_file.c ├── hmac_init.c ├── hmac_memory.c ├── hmac_memory_multi.c ├── hmac_process.c ├── hmac_test.c ├── pkcs_5_2.c ├── sha1.c ├── sha256.c ├── sqlcipher.h ├── sqlite3-binding.c ├── sqlite3-binding.c.diff ├── sqlite3-binding.h ├── sqlite3.go ├── sqlite3_context.go ├── sqlite3_func_crypt.go ├── sqlite3_func_crypt_test.go ├── sqlite3_go18.go ├── sqlite3_go18_test.go ├── sqlite3_libsqlite3.go ├── sqlite3_load_extension.go ├── sqlite3_load_extension_omit.go ├── sqlite3_opt_allow_uri_authority.go ├── sqlite3_opt_app_armor.go ├── sqlite3_opt_foreign_keys.go ├── sqlite3_opt_fts3_test.go ├── sqlite3_opt_fts5.go ├── sqlite3_opt_icu.go ├── sqlite3_opt_introspect.go ├── sqlite3_opt_json1.go ├── sqlite3_opt_secure_delete.go ├── sqlite3_opt_secure_delete_fast.go ├── sqlite3_opt_stat4.go ├── sqlite3_opt_unlock_notify.c ├── sqlite3_opt_unlock_notify.go ├── sqlite3_opt_unlock_notify_test.go ├── sqlite3_opt_userauth.go ├── sqlite3_opt_userauth_omit.go ├── sqlite3_opt_userauth_test.go ├── sqlite3_opt_vacuum_full.go ├── sqlite3_opt_vacuum_incr.go ├── sqlite3_opt_vtable.go ├── sqlite3_opt_vtable_test.go ├── sqlite3_other.go ├── sqlite3_solaris.go ├── sqlite3_test.go ├── sqlite3_trace.go ├── sqlite3_type.go ├── sqlite3_usleep_windows.go ├── sqlite3_windows.go ├── sqlite3ext.h ├── static_mock.go ├── tomcrypt.h ├── tomcrypt_argchk.h ├── tomcrypt_cfg.h ├── tomcrypt_cipher.h ├── tomcrypt_custom.h ├── tomcrypt_hash.h ├── tomcrypt_mac.h ├── tomcrypt_macros.h ├── tomcrypt_math.h ├── tomcrypt_misc.h ├── tomcrypt_pk.h ├── tomcrypt_pkcs.h ├── tomcrypt_private.h ├── tomcrypt_prng.h ├── upgrade ├── package.go └── upgrade.go └── zeromem.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: mattn # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | *.exe 3 | *.dll 4 | *.o 5 | 6 | .idea 7 | 8 | # VSCode 9 | .vscode 10 | 11 | # Exclude from upgrade 12 | upgrade/*.c 13 | upgrade/*.h 14 | 15 | # Exclude upgrade binary 16 | upgrade/upgrade 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | os: 4 | - linux 5 | - osx 6 | 7 | addons: 8 | apt: 9 | update: true 10 | 11 | go: 12 | - 1.9.x 13 | - 1.10.x 14 | - 1.11.x 15 | - master 16 | 17 | before_install: 18 | - | 19 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 20 | brew update 21 | fi 22 | - go get github.com/smartystreets/goconvey 23 | - go get github.com/mattn/goveralls 24 | - go get golang.org/x/tools/cmd/cover 25 | 26 | script: 27 | - $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx 28 | - go test -race -v . -tags "" 29 | - go test -race -v . -tags "libsqlite3" 30 | - go test -race -v . -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify" 31 | - go test -race -v . -tags "sqlite_vacuum_full" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_example/custom_func/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "math" 8 | "math/rand" 9 | 10 | sqlite "github.com/mattn/go-sqlite3" 11 | ) 12 | 13 | // Computes x^y 14 | func pow(x, y int64) int64 { 15 | return int64(math.Pow(float64(x), float64(y))) 16 | } 17 | 18 | // Computes the bitwise exclusive-or of all its arguments 19 | func xor(xs ...int64) int64 { 20 | var ret int64 21 | for _, x := range xs { 22 | ret ^= x 23 | } 24 | return ret 25 | } 26 | 27 | // Returns a random number. It's actually deterministic here because 28 | // we don't seed the RNG, but it's an example of a non-pure function 29 | // from SQLite's POV. 30 | func getrand() int64 { 31 | return rand.Int63() 32 | } 33 | 34 | // Computes the standard deviation of a GROUPed BY set of values 35 | type stddev struct { 36 | xs []int64 37 | // Running average calculation 38 | sum int64 39 | n int64 40 | } 41 | 42 | func newStddev() *stddev { return &stddev{} } 43 | 44 | func (s *stddev) Step(x int64) { 45 | s.xs = append(s.xs, x) 46 | s.sum += x 47 | s.n++ 48 | } 49 | 50 | func (s *stddev) Done() float64 { 51 | mean := float64(s.sum) / float64(s.n) 52 | var sqDiff []float64 53 | for _, x := range s.xs { 54 | sqDiff = append(sqDiff, math.Pow(float64(x)-mean, 2)) 55 | } 56 | var dev float64 57 | for _, x := range sqDiff { 58 | dev += x 59 | } 60 | dev /= float64(len(sqDiff)) 61 | return math.Sqrt(dev) 62 | } 63 | 64 | func main() { 65 | sql.Register("sqlite3_custom", &sqlite.SQLiteDriver{ 66 | ConnectHook: func(conn *sqlite.SQLiteConn) error { 67 | if err := conn.RegisterFunc("pow", pow, true); err != nil { 68 | return err 69 | } 70 | if err := conn.RegisterFunc("xor", xor, true); err != nil { 71 | return err 72 | } 73 | if err := conn.RegisterFunc("rand", getrand, false); err != nil { 74 | return err 75 | } 76 | if err := conn.RegisterAggregator("stddev", newStddev, true); err != nil { 77 | return err 78 | } 79 | return nil 80 | }, 81 | }) 82 | 83 | db, err := sql.Open("sqlite3_custom", ":memory:") 84 | if err != nil { 85 | log.Fatal("Failed to open database:", err) 86 | } 87 | defer db.Close() 88 | 89 | var i int64 90 | err = db.QueryRow("SELECT pow(2,3)").Scan(&i) 91 | if err != nil { 92 | log.Fatal("POW query error:", err) 93 | } 94 | fmt.Println("pow(2,3) =", i) // 8 95 | 96 | err = db.QueryRow("SELECT xor(1,2,3,4,5,6)").Scan(&i) 97 | if err != nil { 98 | log.Fatal("XOR query error:", err) 99 | } 100 | fmt.Println("xor(1,2,3,4,5) =", i) // 7 101 | 102 | err = db.QueryRow("SELECT rand()").Scan(&i) 103 | if err != nil { 104 | log.Fatal("RAND query error:", err) 105 | } 106 | fmt.Println("rand() =", i) // pseudorandom 107 | 108 | _, err = db.Exec("create table foo (department integer, profits integer)") 109 | if err != nil { 110 | log.Fatal("Failed to create table:", err) 111 | } 112 | _, err = db.Exec("insert into foo values (1, 10), (1, 20), (1, 45), (2, 42), (2, 115)") 113 | if err != nil { 114 | log.Fatal("Failed to insert records:", err) 115 | } 116 | 117 | rows, err := db.Query("select department, stddev(profits) from foo group by department") 118 | if err != nil { 119 | log.Fatal("STDDEV query error:", err) 120 | } 121 | defer rows.Close() 122 | for rows.Next() { 123 | var dept int64 124 | var dev float64 125 | if err := rows.Scan(&dept, &dev); err != nil { 126 | log.Fatal(err) 127 | } 128 | fmt.Printf("dept=%d stddev=%f\n", dept, dev) 129 | } 130 | if err := rows.Err(); err != nil { 131 | log.Fatal(err) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /_example/hook/hook.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "log" 6 | "os" 7 | 8 | "github.com/mattn/go-sqlite3" 9 | ) 10 | 11 | func main() { 12 | sqlite3conn := []*sqlite3.SQLiteConn{} 13 | sql.Register("sqlite3_with_hook_example", 14 | &sqlite3.SQLiteDriver{ 15 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 16 | sqlite3conn = append(sqlite3conn, conn) 17 | conn.RegisterUpdateHook(func(op int, db string, table string, rowid int64) { 18 | switch op { 19 | case sqlite3.SQLITE_INSERT: 20 | log.Println("Notified of insert on db", db, "table", table, "rowid", rowid) 21 | } 22 | }) 23 | return nil 24 | }, 25 | }) 26 | os.Remove("./foo.db") 27 | os.Remove("./bar.db") 28 | 29 | srcDb, err := sql.Open("sqlite3_with_hook_example", "./foo.db") 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | defer srcDb.Close() 34 | srcDb.Ping() 35 | 36 | _, err = srcDb.Exec("create table foo(id int, value text)") 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | _, err = srcDb.Exec("insert into foo values(1, 'foo')") 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | _, err = srcDb.Exec("insert into foo values(2, 'bar')") 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | _, err = srcDb.Query("select * from foo") 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | destDb, err := sql.Open("sqlite3_with_hook_example", "./bar.db") 53 | if err != nil { 54 | log.Fatal(err) 55 | } 56 | defer destDb.Close() 57 | destDb.Ping() 58 | 59 | bk, err := sqlite3conn[1].Backup("main", sqlite3conn[0], "main") 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | 64 | _, err = bk.Step(-1) 65 | if err != nil { 66 | log.Fatal(err) 67 | } 68 | _, err = destDb.Query("select * from foo") 69 | if err != nil { 70 | log.Fatal(err) 71 | } 72 | _, err = destDb.Exec("insert into foo values(3, 'bar')") 73 | if err != nil { 74 | log.Fatal(err) 75 | } 76 | 77 | bk.Finish() 78 | } 79 | -------------------------------------------------------------------------------- /_example/limit/limit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strings" 9 | 10 | "github.com/mattn/go-sqlite3" 11 | ) 12 | 13 | func createBulkInsertQuery(n int, start int) (query string, args []interface{}) { 14 | values := make([]string, n) 15 | args = make([]interface{}, n*2) 16 | pos := 0 17 | for i := 0; i < n; i++ { 18 | values[i] = "(?, ?)" 19 | args[pos] = start + i 20 | args[pos+1] = fmt.Sprintf("こんにちわ世界%03d", i) 21 | pos += 2 22 | } 23 | query = fmt.Sprintf( 24 | "insert into foo(id, name) values %s", 25 | strings.Join(values, ", "), 26 | ) 27 | return 28 | } 29 | 30 | func bukInsert(db *sql.DB, query string, args []interface{}) (err error) { 31 | stmt, err := db.Prepare(query) 32 | if err != nil { 33 | return 34 | } 35 | 36 | _, err = stmt.Exec(args...) 37 | if err != nil { 38 | return 39 | } 40 | 41 | return 42 | } 43 | 44 | func main() { 45 | var sqlite3conn *sqlite3.SQLiteConn 46 | sql.Register("sqlite3_with_limit", &sqlite3.SQLiteDriver{ 47 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 48 | sqlite3conn = conn 49 | return nil 50 | }, 51 | }) 52 | 53 | os.Remove("./foo.db") 54 | db, err := sql.Open("sqlite3_with_limit", "./foo.db") 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | defer db.Close() 59 | 60 | sqlStmt := ` 61 | create table foo (id integer not null primary key, name text); 62 | delete from foo; 63 | ` 64 | _, err = db.Exec(sqlStmt) 65 | if err != nil { 66 | log.Printf("%q: %s\n", err, sqlStmt) 67 | return 68 | } 69 | 70 | if sqlite3conn == nil { 71 | log.Fatal("not set sqlite3 connection") 72 | } 73 | 74 | limitVariableNumber := sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) 75 | log.Printf("default SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) 76 | 77 | num := 400 78 | query, args := createBulkInsertQuery(num, 0) 79 | err = bukInsert(db, query, args) 80 | if err != nil { 81 | log.Fatal(err) 82 | } 83 | 84 | smallLimitVariableNumber := 100 85 | sqlite3conn.SetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, smallLimitVariableNumber) 86 | 87 | limitVariableNumber = sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) 88 | log.Printf("updated SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) 89 | 90 | query, args = createBulkInsertQuery(num, num) 91 | err = bukInsert(db, query, args) 92 | if err != nil { 93 | if err != nil { 94 | log.Printf("expect failed since SQLITE_LIMIT_VARIABLE_NUMBER is too small: %v", err) 95 | } 96 | } 97 | 98 | bigLimitVariableNumber := 999999 99 | sqlite3conn.SetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, bigLimitVariableNumber) 100 | limitVariableNumber = sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) 101 | log.Printf("set SQLITE_LIMIT_VARIABLE_NUMBER: %d", bigLimitVariableNumber) 102 | log.Printf("updated SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) 103 | 104 | query, args = createBulkInsertQuery(500, num+num) 105 | err = bukInsert(db, query, args) 106 | if err != nil { 107 | if err != nil { 108 | log.Fatal(err) 109 | } 110 | } 111 | 112 | log.Println("no error if SQLITE_LIMIT_VARIABLE_NUMBER > 999") 113 | } 114 | -------------------------------------------------------------------------------- /_example/mod_regexp/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | EXE=extension.exe 3 | EXT=sqlite3_mod_regexp.dll 4 | RM=cmd /c del 5 | LDFLAG= 6 | else 7 | EXE=extension 8 | EXT=sqlite3_mod_regexp.so 9 | RM=rm 10 | LDFLAG=-fPIC 11 | endif 12 | 13 | all : $(EXE) $(EXT) 14 | 15 | $(EXE) : extension.go 16 | go build $< 17 | 18 | $(EXT) : sqlite3_mod_regexp.c 19 | gcc $(LDFLAG) -shared -o $@ $< -lsqlite3 -lpcre 20 | 21 | clean : 22 | @-$(RM) $(EXE) $(EXT) 23 | -------------------------------------------------------------------------------- /_example/mod_regexp/extension.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "github.com/mattn/go-sqlite3" 7 | "log" 8 | ) 9 | 10 | func main() { 11 | sql.Register("sqlite3_with_extensions", 12 | &sqlite3.SQLiteDriver{ 13 | Extensions: []string{ 14 | "sqlite3_mod_regexp", 15 | }, 16 | }) 17 | 18 | db, err := sql.Open("sqlite3_with_extensions", ":memory:") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | defer db.Close() 23 | 24 | // Force db to make a new connection in pool 25 | // by putting the original in a transaction 26 | tx, err := db.Begin() 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | defer tx.Commit() 31 | 32 | // New connection works (hopefully!) 33 | rows, err := db.Query("select 'hello world' where 'hello world' regexp '^hello.*d$'") 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | defer rows.Close() 38 | for rows.Next() { 39 | var helloworld string 40 | rows.Scan(&helloworld) 41 | fmt.Println(helloworld) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /_example/mod_regexp/sqlite3_mod_regexp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | SQLITE_EXTENSION_INIT1 7 | static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) { 8 | if (argc >= 2) { 9 | const char *target = (const char *)sqlite3_value_text(argv[1]); 10 | const char *pattern = (const char *)sqlite3_value_text(argv[0]); 11 | const char* errstr = NULL; 12 | int erroff = 0; 13 | int vec[500]; 14 | int n, rc; 15 | pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL); 16 | rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500); 17 | if (rc <= 0) { 18 | sqlite3_result_error(context, errstr, 0); 19 | return; 20 | } 21 | sqlite3_result_int(context, 1); 22 | } 23 | } 24 | 25 | #ifdef _WIN32 26 | __declspec(dllexport) 27 | #endif 28 | int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) { 29 | SQLITE_EXTENSION_INIT2(api); 30 | return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, (void*)db, regexp_func, NULL, NULL); 31 | } 32 | -------------------------------------------------------------------------------- /_example/mod_vtable/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | EXE=extension.exe 3 | EXT=sqlite3_mod_vtable.dll 4 | RM=cmd /c del 5 | LIBCURL=-lcurldll 6 | LDFLAG= 7 | else 8 | EXE=extension 9 | EXT=sqlite3_mod_vtable.so 10 | RM=rm 11 | LDFLAG=-fPIC 12 | LIBCURL=-lcurl 13 | endif 14 | 15 | all : $(EXE) $(EXT) 16 | 17 | $(EXE) : extension.go 18 | go build $< 19 | 20 | $(EXT) : sqlite3_mod_vtable.cc 21 | g++ $(LDFLAG) -shared -o $@ $< -lsqlite3 $(LIBCURL) 22 | 23 | clean : 24 | @-$(RM) $(EXE) $(EXT) 25 | -------------------------------------------------------------------------------- /_example/mod_vtable/extension.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/mattn/go-sqlite3" 9 | ) 10 | 11 | func main() { 12 | sql.Register("sqlite3_with_extensions", 13 | &sqlite3.SQLiteDriver{ 14 | Extensions: []string{ 15 | "sqlite3_mod_vtable", 16 | }, 17 | }) 18 | 19 | db, err := sql.Open("sqlite3_with_extensions", ":memory:") 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer db.Close() 24 | 25 | db.Exec("create virtual table repo using github(id, full_name, description, html_url)") 26 | 27 | rows, err := db.Query("select id, full_name, description, html_url from repo") 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | defer rows.Close() 32 | for rows.Next() { 33 | var id, fullName, description, htmlURL string 34 | rows.Scan(&id, &fullName, &description, &htmlURL) 35 | fmt.Printf("%s: %s\n\t%s\n\t%s\n\n", id, fullName, description, htmlURL) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /_example/mod_vtable/sqlite3_mod_vtable.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "picojson.h" 7 | 8 | #ifdef _WIN32 9 | # define EXPORT __declspec(dllexport) 10 | #else 11 | # define EXPORT 12 | #endif 13 | 14 | SQLITE_EXTENSION_INIT1; 15 | 16 | typedef struct { 17 | char* data; // response data from server 18 | size_t size; // response size of data 19 | } MEMFILE; 20 | 21 | MEMFILE* 22 | memfopen() { 23 | MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE)); 24 | if (mf) { 25 | mf->data = NULL; 26 | mf->size = 0; 27 | } 28 | return mf; 29 | } 30 | 31 | void 32 | memfclose(MEMFILE* mf) { 33 | if (mf->data) free(mf->data); 34 | free(mf); 35 | } 36 | 37 | size_t 38 | memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) { 39 | MEMFILE* mf = (MEMFILE*) stream; 40 | int block = size * nmemb; 41 | if (!mf) return block; // through 42 | if (!mf->data) 43 | mf->data = (char*) malloc(block); 44 | else 45 | mf->data = (char*) realloc(mf->data, mf->size + block); 46 | if (mf->data) { 47 | memcpy(mf->data + mf->size, ptr, block); 48 | mf->size += block; 49 | } 50 | return block; 51 | } 52 | 53 | char* 54 | memfstrdup(MEMFILE* mf) { 55 | char* buf; 56 | if (mf->size == 0) return NULL; 57 | buf = (char*) malloc(mf->size + 1); 58 | memcpy(buf, mf->data, mf->size); 59 | buf[mf->size] = 0; 60 | return buf; 61 | } 62 | 63 | static int 64 | my_connect(sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **c) { 65 | std::stringstream ss; 66 | ss << "CREATE TABLE " << argv[0] 67 | << "(id int, full_name text, description text, html_url text)"; 68 | int rc = sqlite3_declare_vtab(db, ss.str().c_str()); 69 | *ppVTab = (sqlite3_vtab *) sqlite3_malloc(sizeof(sqlite3_vtab)); 70 | memset(*ppVTab, 0, sizeof(sqlite3_vtab)); 71 | return rc; 72 | } 73 | 74 | static int 75 | my_create(sqlite3 *db, void *pAux, int argc, const char * const * argv, sqlite3_vtab **ppVTab, char **c) { 76 | return my_connect(db, pAux, argc, argv, ppVTab, c); 77 | } 78 | 79 | static int my_disconnect(sqlite3_vtab *pVTab) { 80 | sqlite3_free(pVTab); 81 | return SQLITE_OK; 82 | } 83 | 84 | static int 85 | my_destroy(sqlite3_vtab *pVTab) { 86 | sqlite3_free(pVTab); 87 | return SQLITE_OK; 88 | } 89 | 90 | typedef struct { 91 | sqlite3_vtab_cursor base; 92 | int index; 93 | picojson::value* rows; 94 | } cursor; 95 | 96 | static int 97 | my_open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) { 98 | MEMFILE* mf; 99 | CURL* curl; 100 | char* json; 101 | CURLcode res = CURLE_OK; 102 | char error[CURL_ERROR_SIZE] = {0}; 103 | char* cert_file = getenv("SSL_CERT_FILE"); 104 | 105 | mf = memfopen(); 106 | curl = curl_easy_init(); 107 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); 108 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2); 109 | curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.29.0"); 110 | curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repositories"); 111 | if (cert_file) 112 | curl_easy_setopt(curl, CURLOPT_CAINFO, cert_file); 113 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); 114 | curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error); 115 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); 116 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); 117 | res = curl_easy_perform(curl); 118 | curl_easy_cleanup(curl); 119 | if (res != CURLE_OK) { 120 | std::cerr << error << std::endl; 121 | return SQLITE_FAIL; 122 | } 123 | 124 | picojson::value* v = new picojson::value; 125 | std::string err; 126 | picojson::parse(*v, mf->data, mf->data + mf->size, &err); 127 | memfclose(mf); 128 | 129 | if (!err.empty()) { 130 | delete v; 131 | std::cerr << err << std::endl; 132 | return SQLITE_FAIL; 133 | } 134 | 135 | cursor *c = (cursor *)sqlite3_malloc(sizeof(cursor)); 136 | c->rows = v; 137 | c->index = 0; 138 | *ppCursor = &c->base; 139 | return SQLITE_OK; 140 | } 141 | 142 | static int 143 | my_close(cursor *c) { 144 | delete c->rows; 145 | sqlite3_free(c); 146 | return SQLITE_OK; 147 | } 148 | 149 | static int 150 | my_filter(cursor *c, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) { 151 | c->index = 0; 152 | return SQLITE_OK; 153 | } 154 | 155 | static int 156 | my_next(cursor *c) { 157 | c->index++; 158 | return SQLITE_OK; 159 | } 160 | 161 | static int 162 | my_eof(cursor *c) { 163 | return c->index >= c->rows->get().size() ? 1 : 0; 164 | } 165 | 166 | static int 167 | my_column(cursor *c, sqlite3_context *ctxt, int i) { 168 | picojson::value v = c->rows->get()[c->index]; 169 | picojson::object row = v.get(); 170 | const char* p = NULL; 171 | switch (i) { 172 | case 0: 173 | p = row["id"].to_str().c_str(); 174 | break; 175 | case 1: 176 | p = row["full_name"].to_str().c_str(); 177 | break; 178 | case 2: 179 | p = row["description"].to_str().c_str(); 180 | break; 181 | case 3: 182 | p = row["html_url"].to_str().c_str(); 183 | break; 184 | } 185 | sqlite3_result_text(ctxt, strdup(p), strlen(p), free); 186 | return SQLITE_OK; 187 | } 188 | 189 | static int 190 | my_rowid(cursor *c, sqlite3_int64 *pRowid) { 191 | *pRowid = c->index; 192 | return SQLITE_OK; 193 | } 194 | 195 | static int 196 | my_bestindex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo) { 197 | return SQLITE_OK; 198 | } 199 | 200 | static const sqlite3_module module = { 201 | 0, 202 | my_create, 203 | my_connect, 204 | my_bestindex, 205 | my_disconnect, 206 | my_destroy, 207 | my_open, 208 | (int (*)(sqlite3_vtab_cursor *)) my_close, 209 | (int (*)(sqlite3_vtab_cursor *, int, char const *, int, sqlite3_value **)) my_filter, 210 | (int (*)(sqlite3_vtab_cursor *)) my_next, 211 | (int (*)(sqlite3_vtab_cursor *)) my_eof, 212 | (int (*)(sqlite3_vtab_cursor *, sqlite3_context *, int)) my_column, 213 | (int (*)(sqlite3_vtab_cursor *, sqlite3_int64 *)) my_rowid, 214 | NULL, // my_update 215 | NULL, // my_begin 216 | NULL, // my_sync 217 | NULL, // my_commit 218 | NULL, // my_rollback 219 | NULL, // my_findfunction 220 | NULL, // my_rename 221 | }; 222 | 223 | static void 224 | destructor(void *arg) { 225 | return; 226 | } 227 | 228 | 229 | extern "C" { 230 | 231 | EXPORT int 232 | sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) { 233 | SQLITE_EXTENSION_INIT2(api); 234 | sqlite3_create_module_v2(db, "github", &module, NULL, destructor); 235 | return 0; 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /_example/simple/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$OSTYPE" == "linux-gnu" ]]; then 4 | CGO_ENABLED=1 go build -a -x -v --tags "linux sqlite_omit_load_extension sqlite_vtable sqlite_fts5 sqlite_icu sqlite_json" && ldd simple 5 | elif [[ "$OSTYPE" == "darwin"* ]]; then 6 | CGO_ENABLED=1 go build -a -x -v --tags "darwin sqlite_omit_load_extension sqlite_vtable sqlite_fts5 sqlite_icu sqlite_json" 7 | fi 8 | -------------------------------------------------------------------------------- /_example/simple/simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | _ "github.com/CovenantSQL/go-sqlite3-encrypt" 10 | ) 11 | 12 | func main() { 13 | os.Remove("./foo.db") 14 | 15 | db, err := sql.Open("sqlite3", "./foo.db") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | defer db.Close() 20 | 21 | sqlStmt := ` 22 | PRAGMA key = auxten; 23 | create table foo (id integer not null primary key, name text); 24 | delete from foo; 25 | ` 26 | _, err = db.Exec(sqlStmt) 27 | if err != nil { 28 | log.Printf("%q: %s\n", err, sqlStmt) 29 | return 30 | } 31 | 32 | tx, err := db.Begin() 33 | if err != nil { 34 | log.Fatal(err) 35 | } 36 | stmt, err := tx.Prepare("insert into foo(id, name) values(?, ?)") 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | defer stmt.Close() 41 | for i := 0; i < 100; i++ { 42 | _, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i)) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | } 47 | tx.Commit() 48 | 49 | rows, err := db.Query("select id, name from foo") 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | defer rows.Close() 54 | for rows.Next() { 55 | var id int 56 | var name string 57 | err = rows.Scan(&id, &name) 58 | if err != nil { 59 | log.Fatal(err) 60 | } 61 | fmt.Println(id, name) 62 | } 63 | err = rows.Err() 64 | if err != nil { 65 | log.Fatal(err) 66 | } 67 | 68 | stmt, err = db.Prepare("select name from foo where id = ?") 69 | if err != nil { 70 | log.Fatal(err) 71 | } 72 | defer stmt.Close() 73 | var name string 74 | err = stmt.QueryRow("3").Scan(&name) 75 | if err != nil { 76 | log.Fatal(err) 77 | } 78 | fmt.Println(name) 79 | 80 | _, err = db.Exec("delete from foo") 81 | if err != nil { 82 | log.Fatal(err) 83 | } 84 | 85 | _, err = db.Exec("insert into foo(id, name) values(1, 'foo'), (2, 'bar'), (3, 'baz')") 86 | if err != nil { 87 | log.Fatal(err) 88 | } 89 | 90 | rows, err = db.Query("select id, name from foo") 91 | if err != nil { 92 | log.Fatal(err) 93 | } 94 | defer rows.Close() 95 | for rows.Next() { 96 | var id int 97 | var name string 98 | err = rows.Scan(&id, &name) 99 | if err != nil { 100 | log.Fatal(err) 101 | } 102 | fmt.Println(id, name) 103 | } 104 | err = rows.Err() 105 | if err != nil { 106 | log.Fatal(err) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /_example/trace/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | sqlite3 "github.com/mattn/go-sqlite3" 10 | ) 11 | 12 | func traceCallback(info sqlite3.TraceInfo) int { 13 | // Not very readable but may be useful; uncomment next line in case of doubt: 14 | //fmt.Printf("Trace: %#v\n", info) 15 | 16 | var dbErrText string 17 | if info.DBError.Code != 0 || info.DBError.ExtendedCode != 0 { 18 | dbErrText = fmt.Sprintf("; DB error: %#v", info.DBError) 19 | } else { 20 | dbErrText = "." 21 | } 22 | 23 | // Show the Statement-or-Trigger text in curly braces ('{', '}') 24 | // since from the *paired* ASCII characters they are 25 | // the least used in SQL syntax, therefore better visual delimiters. 26 | // Maybe show 'ExpandedSQL' the same way as 'StmtOrTrigger'. 27 | // 28 | // A known use of curly braces (outside strings) is 29 | // for ODBC escape sequences. Not likely to appear here. 30 | // 31 | // Template languages, etc. don't matter, we should see their *result* 32 | // at *this* level. 33 | // Strange curly braces in SQL code that reached the database driver 34 | // suggest that there is a bug in the application. 35 | // The braces are likely to be either template syntax or 36 | // a programming language's string interpolation syntax. 37 | 38 | var expandedText string 39 | if info.ExpandedSQL != "" { 40 | if info.ExpandedSQL == info.StmtOrTrigger { 41 | expandedText = " = exp" 42 | } else { 43 | expandedText = fmt.Sprintf(" expanded {%q}", info.ExpandedSQL) 44 | } 45 | } else { 46 | expandedText = "" 47 | } 48 | 49 | // SQLite docs as of September 6, 2016: Tracing and Profiling Functions 50 | // https://www.sqlite.org/c3ref/profile.html 51 | // 52 | // The profile callback time is in units of nanoseconds, however 53 | // the current implementation is only capable of millisecond resolution 54 | // so the six least significant digits in the time are meaningless. 55 | // Future versions of SQLite might provide greater resolution on the profiler callback. 56 | 57 | var runTimeText string 58 | if info.RunTimeNanosec == 0 { 59 | if info.EventCode == sqlite3.TraceProfile { 60 | //runTimeText = "; no time" // seems confusing 61 | runTimeText = "; time 0" // no measurement unit 62 | } else { 63 | //runTimeText = "; no time" // seems useless and confusing 64 | } 65 | } else { 66 | const nanosPerMillisec = 1000000 67 | if info.RunTimeNanosec%nanosPerMillisec == 0 { 68 | runTimeText = fmt.Sprintf("; time %d ms", info.RunTimeNanosec/nanosPerMillisec) 69 | } else { 70 | // unexpected: better than millisecond resolution 71 | runTimeText = fmt.Sprintf("; time %d ns!!!", info.RunTimeNanosec) 72 | } 73 | } 74 | 75 | var modeText string 76 | if info.AutoCommit { 77 | modeText = "-AC-" 78 | } else { 79 | modeText = "+Tx+" 80 | } 81 | 82 | fmt.Printf("Trace: ev %d %s conn 0x%x, stmt 0x%x {%q}%s%s%s\n", 83 | info.EventCode, modeText, info.ConnHandle, info.StmtHandle, 84 | info.StmtOrTrigger, expandedText, 85 | runTimeText, 86 | dbErrText) 87 | return 0 88 | } 89 | 90 | func main() { 91 | eventMask := sqlite3.TraceStmt | sqlite3.TraceProfile | sqlite3.TraceRow | sqlite3.TraceClose 92 | 93 | sql.Register("sqlite3_tracing", 94 | &sqlite3.SQLiteDriver{ 95 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 96 | err := conn.SetTrace(&sqlite3.TraceConfig{ 97 | Callback: traceCallback, 98 | EventMask: eventMask, 99 | WantExpandedSQL: true, 100 | }) 101 | return err 102 | }, 103 | }) 104 | 105 | os.Exit(dbMain()) 106 | } 107 | 108 | // Harder to do DB work in main(). 109 | // It's better with a separate function because 110 | // 'defer' and 'os.Exit' don't go well together. 111 | // 112 | // DO NOT use 'log.Fatal...' below: remember that it's equivalent to 113 | // Print() followed by a call to os.Exit(1) --- and 114 | // we want to avoid Exit() so 'defer' can do cleanup. 115 | // Use 'log.Panic...' instead. 116 | 117 | func dbMain() int { 118 | db, err := sql.Open("sqlite3_tracing", ":memory:") 119 | if err != nil { 120 | fmt.Printf("Failed to open database: %#+v\n", err) 121 | return 1 122 | } 123 | defer db.Close() 124 | 125 | err = db.Ping() 126 | if err != nil { 127 | log.Panic(err) 128 | } 129 | 130 | dbSetup(db) 131 | 132 | dbDoInsert(db) 133 | dbDoInsertPrepared(db) 134 | dbDoSelect(db) 135 | dbDoSelectPrepared(db) 136 | 137 | return 0 138 | } 139 | 140 | // 'DDL' stands for "Data Definition Language": 141 | 142 | // Note: "INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT" causes the error 143 | // 'near "AUTOINCREMENT": syntax error'; without "NOT NULL" it works. 144 | const tableDDL = `CREATE TABLE t1 ( 145 | id INTEGER PRIMARY KEY AUTOINCREMENT, 146 | note VARCHAR NOT NULL 147 | )` 148 | 149 | // 'DML' stands for "Data Manipulation Language": 150 | 151 | const insertDML = "INSERT INTO t1 (note) VALUES (?)" 152 | const selectDML = "SELECT id, note FROM t1 WHERE note LIKE ?" 153 | 154 | const textPrefix = "bla-1234567890-" 155 | const noteTextPattern = "%Prep%" 156 | 157 | const nGenRows = 4 // Number of Rows to Generate (for *each* approach tested) 158 | 159 | func dbSetup(db *sql.DB) { 160 | var err error 161 | 162 | _, err = db.Exec("DROP TABLE IF EXISTS t1") 163 | if err != nil { 164 | log.Panic(err) 165 | } 166 | _, err = db.Exec(tableDDL) 167 | if err != nil { 168 | log.Panic(err) 169 | } 170 | } 171 | 172 | func dbDoInsert(db *sql.DB) { 173 | const Descr = "DB-Exec" 174 | for i := 0; i < nGenRows; i++ { 175 | result, err := db.Exec(insertDML, textPrefix+Descr) 176 | if err != nil { 177 | log.Panic(err) 178 | } 179 | 180 | resultDoCheck(result, Descr, i) 181 | } 182 | } 183 | 184 | func dbDoInsertPrepared(db *sql.DB) { 185 | const Descr = "DB-Prepare" 186 | 187 | stmt, err := db.Prepare(insertDML) 188 | if err != nil { 189 | log.Panic(err) 190 | } 191 | defer stmt.Close() 192 | 193 | for i := 0; i < nGenRows; i++ { 194 | result, err := stmt.Exec(textPrefix + Descr) 195 | if err != nil { 196 | log.Panic(err) 197 | } 198 | 199 | resultDoCheck(result, Descr, i) 200 | } 201 | } 202 | 203 | func resultDoCheck(result sql.Result, callerDescr string, callIndex int) { 204 | lastID, err := result.LastInsertId() 205 | if err != nil { 206 | log.Panic(err) 207 | } 208 | nAffected, err := result.RowsAffected() 209 | if err != nil { 210 | log.Panic(err) 211 | } 212 | 213 | log.Printf("Exec result for %s (%d): ID = %d, affected = %d\n", callerDescr, callIndex, lastID, nAffected) 214 | } 215 | 216 | func dbDoSelect(db *sql.DB) { 217 | const Descr = "DB-Query" 218 | 219 | rows, err := db.Query(selectDML, noteTextPattern) 220 | if err != nil { 221 | log.Panic(err) 222 | } 223 | defer rows.Close() 224 | 225 | rowsDoFetch(rows, Descr) 226 | } 227 | 228 | func dbDoSelectPrepared(db *sql.DB) { 229 | const Descr = "DB-Prepare" 230 | 231 | stmt, err := db.Prepare(selectDML) 232 | if err != nil { 233 | log.Panic(err) 234 | } 235 | defer stmt.Close() 236 | 237 | rows, err := stmt.Query(noteTextPattern) 238 | if err != nil { 239 | log.Panic(err) 240 | } 241 | defer rows.Close() 242 | 243 | rowsDoFetch(rows, Descr) 244 | } 245 | 246 | func rowsDoFetch(rows *sql.Rows, callerDescr string) { 247 | var nRows int 248 | var id int64 249 | var note string 250 | 251 | for rows.Next() { 252 | err := rows.Scan(&id, ¬e) 253 | if err != nil { 254 | log.Panic(err) 255 | } 256 | log.Printf("Row for %s (%d): id=%d, note=%q\n", 257 | callerDescr, nRows, id, note) 258 | nRows++ 259 | } 260 | if err := rows.Err(); err != nil { 261 | log.Panic(err) 262 | } 263 | log.Printf("Total %d rows for %s.\n", nRows, callerDescr) 264 | } 265 | -------------------------------------------------------------------------------- /_example/vtable/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/mattn/go-sqlite3" 9 | ) 10 | 11 | func main() { 12 | sql.Register("sqlite3_with_extensions", &sqlite3.SQLiteDriver{ 13 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 14 | return conn.CreateModule("github", &githubModule{}) 15 | }, 16 | }) 17 | db, err := sql.Open("sqlite3_with_extensions", ":memory:") 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | defer db.Close() 22 | 23 | _, err = db.Exec("create virtual table repo using github(id, full_name, description, html_url)") 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | 28 | rows, err := db.Query("select id, full_name, description, html_url from repo") 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | defer rows.Close() 33 | for rows.Next() { 34 | var id, fullName, description, htmlURL string 35 | rows.Scan(&id, &fullName, &description, &htmlURL) 36 | fmt.Printf("%s: %s\n\t%s\n\t%s\n\n", id, fullName, description, htmlURL) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /_example/vtable/vtable.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | "github.com/mattn/go-sqlite3" 10 | ) 11 | 12 | type githubRepo struct { 13 | ID int `json:"id"` 14 | FullName string `json:"full_name"` 15 | Description string `json:"description"` 16 | HTMLURL string `json:"html_url"` 17 | } 18 | 19 | type githubModule struct { 20 | } 21 | 22 | func (m *githubModule) Create(c *sqlite3.SQLiteConn, args []string) (sqlite3.VTab, error) { 23 | err := c.DeclareVTab(fmt.Sprintf(` 24 | CREATE TABLE %s ( 25 | id INT, 26 | full_name TEXT, 27 | description TEXT, 28 | html_url TEXT 29 | )`, args[0])) 30 | if err != nil { 31 | return nil, err 32 | } 33 | return &ghRepoTable{}, nil 34 | } 35 | 36 | func (m *githubModule) Connect(c *sqlite3.SQLiteConn, args []string) (sqlite3.VTab, error) { 37 | return m.Create(c, args) 38 | } 39 | 40 | func (m *githubModule) DestroyModule() {} 41 | 42 | type ghRepoTable struct { 43 | repos []githubRepo 44 | } 45 | 46 | func (v *ghRepoTable) Open() (sqlite3.VTabCursor, error) { 47 | resp, err := http.Get("https://api.github.com/repositories") 48 | if err != nil { 49 | return nil, err 50 | } 51 | defer resp.Body.Close() 52 | 53 | body, err := ioutil.ReadAll(resp.Body) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | var repos []githubRepo 59 | if err := json.Unmarshal(body, &repos); err != nil { 60 | return nil, err 61 | } 62 | return &ghRepoCursor{0, repos}, nil 63 | } 64 | 65 | func (v *ghRepoTable) BestIndex(cst []sqlite3.InfoConstraint, ob []sqlite3.InfoOrderBy) (*sqlite3.IndexResult, error) { 66 | return &sqlite3.IndexResult{}, nil 67 | } 68 | 69 | func (v *ghRepoTable) Disconnect() error { return nil } 70 | func (v *ghRepoTable) Destroy() error { return nil } 71 | 72 | type ghRepoCursor struct { 73 | index int 74 | repos []githubRepo 75 | } 76 | 77 | func (vc *ghRepoCursor) Column(c *sqlite3.SQLiteContext, col int) error { 78 | switch col { 79 | case 0: 80 | c.ResultInt(vc.repos[vc.index].ID) 81 | case 1: 82 | c.ResultText(vc.repos[vc.index].FullName) 83 | case 2: 84 | c.ResultText(vc.repos[vc.index].Description) 85 | case 3: 86 | c.ResultText(vc.repos[vc.index].HTMLURL) 87 | } 88 | return nil 89 | } 90 | 91 | func (vc *ghRepoCursor) Filter(idxNum int, idxStr string, vals []interface{}) error { 92 | vc.index = 0 93 | return nil 94 | } 95 | 96 | func (vc *ghRepoCursor) Next() error { 97 | vc.index++ 98 | return nil 99 | } 100 | 101 | func (vc *ghRepoCursor) EOF() bool { 102 | return vc.index >= len(vc.repos) 103 | } 104 | 105 | func (vc *ghRepoCursor) Rowid() (int64, error) { 106 | return int64(vc.index), nil 107 | } 108 | 109 | func (vc *ghRepoCursor) Close() error { 110 | return nil 111 | } 112 | -------------------------------------------------------------------------------- /backup.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | /* 9 | #ifndef USE_LIBSQLITE3 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include 15 | */ 16 | import "C" 17 | import ( 18 | "runtime" 19 | "unsafe" 20 | ) 21 | 22 | // SQLiteBackup implement interface of Backup. 23 | type SQLiteBackup struct { 24 | b *C.sqlite3_backup 25 | } 26 | 27 | // Backup make backup from src to dest. 28 | func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) { 29 | destptr := C.CString(dest) 30 | defer C.free(unsafe.Pointer(destptr)) 31 | srcptr := C.CString(src) 32 | defer C.free(unsafe.Pointer(srcptr)) 33 | 34 | if b := C.sqlite3_backup_init(c.db, destptr, conn.db, srcptr); b != nil { 35 | bb := &SQLiteBackup{b: b} 36 | runtime.SetFinalizer(bb, (*SQLiteBackup).Finish) 37 | return bb, nil 38 | } 39 | return nil, c.lastError() 40 | } 41 | 42 | // Step to backs up for one step. Calls the underlying `sqlite3_backup_step` 43 | // function. This function returns a boolean indicating if the backup is done 44 | // and an error signalling any other error. Done is returned if the underlying 45 | // C function returns SQLITE_DONE (Code 101) 46 | func (b *SQLiteBackup) Step(p int) (bool, error) { 47 | ret := C.sqlite3_backup_step(b.b, C.int(p)) 48 | if ret == C.SQLITE_DONE { 49 | return true, nil 50 | } else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY { 51 | return false, Error{Code: ErrNo(ret)} 52 | } 53 | return false, nil 54 | } 55 | 56 | // Remaining return whether have the rest for backup. 57 | func (b *SQLiteBackup) Remaining() int { 58 | return int(C.sqlite3_backup_remaining(b.b)) 59 | } 60 | 61 | // PageCount return count of pages. 62 | func (b *SQLiteBackup) PageCount() int { 63 | return int(C.sqlite3_backup_pagecount(b.b)) 64 | } 65 | 66 | // Finish close backup. 67 | func (b *SQLiteBackup) Finish() error { 68 | return b.Close() 69 | } 70 | 71 | // Close close backup. 72 | func (b *SQLiteBackup) Close() error { 73 | ret := C.sqlite3_backup_finish(b.b) 74 | 75 | // sqlite3_backup_finish() never fails, it just returns the 76 | // error code from previous operations, so clean up before 77 | // checking and returning an error 78 | b.b = nil 79 | runtime.SetFinalizer(b, nil) 80 | 81 | if ret != 0 { 82 | return Error{Code: ErrNo(ret)} 83 | } 84 | return nil 85 | } 86 | -------------------------------------------------------------------------------- /callback_test.go: -------------------------------------------------------------------------------- 1 | package sqlite3 2 | 3 | import ( 4 | "errors" 5 | "math" 6 | "reflect" 7 | "testing" 8 | ) 9 | 10 | func TestCallbackArgCast(t *testing.T) { 11 | intConv := callbackSyntheticForTests(reflect.ValueOf(int64(math.MaxInt64)), nil) 12 | floatConv := callbackSyntheticForTests(reflect.ValueOf(float64(math.MaxFloat64)), nil) 13 | errConv := callbackSyntheticForTests(reflect.Value{}, errors.New("test")) 14 | 15 | tests := []struct { 16 | f callbackArgConverter 17 | o reflect.Value 18 | }{ 19 | {intConv, reflect.ValueOf(int8(-1))}, 20 | {intConv, reflect.ValueOf(int16(-1))}, 21 | {intConv, reflect.ValueOf(int32(-1))}, 22 | {intConv, reflect.ValueOf(uint8(math.MaxUint8))}, 23 | {intConv, reflect.ValueOf(uint16(math.MaxUint16))}, 24 | {intConv, reflect.ValueOf(uint32(math.MaxUint32))}, 25 | // Special case, int64->uint64 is only 1<<63 - 1, not 1<<64 - 1 26 | {intConv, reflect.ValueOf(uint64(math.MaxInt64))}, 27 | {floatConv, reflect.ValueOf(float32(math.Inf(1)))}, 28 | } 29 | 30 | for _, test := range tests { 31 | conv := callbackArgCast{test.f, test.o.Type()} 32 | val, err := conv.Run(nil) 33 | if err != nil { 34 | t.Errorf("Couldn't convert to %s: %s", test.o.Type(), err) 35 | } else if !reflect.DeepEqual(val.Interface(), test.o.Interface()) { 36 | t.Errorf("Unexpected result from converting to %s: got %v, want %v", test.o.Type(), val.Interface(), test.o.Interface()) 37 | } 38 | } 39 | 40 | conv := callbackArgCast{errConv, reflect.TypeOf(int8(0))} 41 | _, err := conv.Run(nil) 42 | if err == nil { 43 | t.Errorf("Expected error during callbackArgCast, but got none") 44 | } 45 | } 46 | 47 | func TestCallbackConverters(t *testing.T) { 48 | tests := []struct { 49 | v interface{} 50 | err bool 51 | }{ 52 | // Unfortunately, we can't tell which converter was returned, 53 | // but we can at least check which types can be converted. 54 | {[]byte{0}, false}, 55 | {"text", false}, 56 | {true, false}, 57 | {int8(0), false}, 58 | {int16(0), false}, 59 | {int32(0), false}, 60 | {int64(0), false}, 61 | {uint8(0), false}, 62 | {uint16(0), false}, 63 | {uint32(0), false}, 64 | {uint64(0), false}, 65 | {int(0), false}, 66 | {uint(0), false}, 67 | {float64(0), false}, 68 | {float32(0), false}, 69 | 70 | {func() {}, true}, 71 | {complex64(complex(0, 0)), true}, 72 | {complex128(complex(0, 0)), true}, 73 | {struct{}{}, true}, 74 | {map[string]string{}, true}, 75 | {[]string{}, true}, 76 | {(*int8)(nil), true}, 77 | {make(chan int), true}, 78 | } 79 | 80 | for _, test := range tests { 81 | _, err := callbackArg(reflect.TypeOf(test.v)) 82 | if test.err && err == nil { 83 | t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) 84 | } else if !test.err && err != nil { 85 | t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) 86 | } 87 | } 88 | 89 | for _, test := range tests { 90 | _, err := callbackRet(reflect.TypeOf(test.v)) 91 | if test.err && err == nil { 92 | t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) 93 | } else if !test.err && err != nil { 94 | t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /cbc_decrypt.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_decrypt.c 13 | CBC implementation, encrypt block, Tom St Denis 14 | */ 15 | 16 | 17 | #ifdef LTC_CBC_MODE 18 | 19 | /** 20 | CBC decrypt 21 | @param ct Ciphertext 22 | @param pt [out] Plaintext 23 | @param len The number of bytes to process (must be multiple of block length) 24 | @param cbc CBC state 25 | @return CRYPT_OK if successful 26 | */ 27 | int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) 28 | { 29 | int x, err; 30 | unsigned char tmp[16]; 31 | #ifdef LTC_FAST 32 | LTC_FAST_TYPE tmpy; 33 | #else 34 | unsigned char tmpy; 35 | #endif 36 | 37 | LTC_ARGCHK(pt != NULL); 38 | LTC_ARGCHK(ct != NULL); 39 | LTC_ARGCHK(cbc != NULL); 40 | 41 | if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { 42 | return err; 43 | } 44 | 45 | /* is blocklen valid? */ 46 | if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) { 47 | return CRYPT_INVALID_ARG; 48 | } 49 | 50 | if (len % cbc->blocklen) { 51 | return CRYPT_INVALID_ARG; 52 | } 53 | #ifdef LTC_FAST 54 | if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { 55 | return CRYPT_INVALID_ARG; 56 | } 57 | #endif 58 | 59 | if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) { 60 | return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key); 61 | } 62 | while (len) { 63 | /* decrypt */ 64 | if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) { 65 | return err; 66 | } 67 | 68 | /* xor IV against plaintext */ 69 | #if defined(LTC_FAST) 70 | for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { 71 | tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x)); 72 | *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); 73 | *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy; 74 | } 75 | #else 76 | for (x = 0; x < cbc->blocklen; x++) { 77 | tmpy = tmp[x] ^ cbc->IV[x]; 78 | cbc->IV[x] = ct[x]; 79 | pt[x] = tmpy; 80 | } 81 | #endif 82 | 83 | ct += cbc->blocklen; 84 | pt += cbc->blocklen; 85 | len -= cbc->blocklen; 86 | } 87 | return CRYPT_OK; 88 | } 89 | 90 | #endif 91 | 92 | /* ref: $Format:%D$ */ 93 | /* git commit: $Format:%H$ */ 94 | /* commit time: $Format:%ai$ */ 95 | -------------------------------------------------------------------------------- /cbc_done.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_done.c 13 | CBC implementation, finish chain, Tom St Denis 14 | */ 15 | 16 | #ifdef LTC_CBC_MODE 17 | 18 | /** Terminate the chain 19 | @param cbc The CBC chain to terminate 20 | @return CRYPT_OK on success 21 | */ 22 | int cbc_done(symmetric_CBC *cbc) 23 | { 24 | int err; 25 | LTC_ARGCHK(cbc != NULL); 26 | 27 | if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { 28 | return err; 29 | } 30 | cipher_descriptor[cbc->cipher].done(&cbc->key); 31 | return CRYPT_OK; 32 | } 33 | 34 | 35 | 36 | #endif 37 | 38 | /* ref: $Format:%D$ */ 39 | /* git commit: $Format:%H$ */ 40 | /* commit time: $Format:%ai$ */ 41 | -------------------------------------------------------------------------------- /cbc_encrypt.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_encrypt.c 13 | CBC implementation, encrypt block, Tom St Denis 14 | */ 15 | 16 | 17 | #ifdef LTC_CBC_MODE 18 | 19 | /** 20 | CBC encrypt 21 | @param pt Plaintext 22 | @param ct [out] Ciphertext 23 | @param len The number of bytes to process (must be multiple of block length) 24 | @param cbc CBC state 25 | @return CRYPT_OK if successful 26 | */ 27 | int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc) 28 | { 29 | int x, err; 30 | 31 | LTC_ARGCHK(pt != NULL); 32 | LTC_ARGCHK(ct != NULL); 33 | LTC_ARGCHK(cbc != NULL); 34 | 35 | if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { 36 | return err; 37 | } 38 | 39 | /* is blocklen valid? */ 40 | if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) { 41 | return CRYPT_INVALID_ARG; 42 | } 43 | 44 | if (len % cbc->blocklen) { 45 | return CRYPT_INVALID_ARG; 46 | } 47 | #ifdef LTC_FAST 48 | if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { 49 | return CRYPT_INVALID_ARG; 50 | } 51 | #endif 52 | 53 | if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) { 54 | return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key); 55 | } 56 | while (len) { 57 | /* xor IV against plaintext */ 58 | #if defined(LTC_FAST) 59 | for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { 60 | *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)); 61 | } 62 | #else 63 | for (x = 0; x < cbc->blocklen; x++) { 64 | cbc->IV[x] ^= pt[x]; 65 | } 66 | #endif 67 | 68 | /* encrypt */ 69 | if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) { 70 | return err; 71 | } 72 | 73 | /* store IV [ciphertext] for a future block */ 74 | #if defined(LTC_FAST) 75 | for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { 76 | *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); 77 | } 78 | #else 79 | for (x = 0; x < cbc->blocklen; x++) { 80 | cbc->IV[x] = ct[x]; 81 | } 82 | #endif 83 | 84 | ct += cbc->blocklen; 85 | pt += cbc->blocklen; 86 | len -= cbc->blocklen; 87 | } 88 | return CRYPT_OK; 89 | } 90 | 91 | #endif 92 | 93 | /* ref: $Format:%D$ */ 94 | /* git commit: $Format:%H$ */ 95 | /* commit time: $Format:%ai$ */ 96 | -------------------------------------------------------------------------------- /cbc_getiv.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_getiv.c 13 | CBC implementation, get IV, Tom St Denis 14 | */ 15 | 16 | #ifdef LTC_CBC_MODE 17 | 18 | /** 19 | Get the current initialization vector 20 | @param IV [out] The destination of the initialization vector 21 | @param len [in/out] The max size and resulting size of the initialization vector 22 | @param cbc The CBC state 23 | @return CRYPT_OK if successful 24 | */ 25 | int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc) 26 | { 27 | LTC_ARGCHK(IV != NULL); 28 | LTC_ARGCHK(len != NULL); 29 | LTC_ARGCHK(cbc != NULL); 30 | if ((unsigned long)cbc->blocklen > *len) { 31 | *len = cbc->blocklen; 32 | return CRYPT_BUFFER_OVERFLOW; 33 | } 34 | XMEMCPY(IV, cbc->IV, cbc->blocklen); 35 | *len = cbc->blocklen; 36 | 37 | return CRYPT_OK; 38 | } 39 | 40 | #endif 41 | 42 | /* ref: $Format:%D$ */ 43 | /* git commit: $Format:%H$ */ 44 | /* commit time: $Format:%ai$ */ 45 | -------------------------------------------------------------------------------- /cbc_setiv.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_setiv.c 13 | CBC implementation, set IV, Tom St Denis 14 | */ 15 | 16 | 17 | #ifdef LTC_CBC_MODE 18 | 19 | /** 20 | Set an initialization vector 21 | @param IV The initialization vector 22 | @param len The length of the vector (in octets) 23 | @param cbc The CBC state 24 | @return CRYPT_OK if successful 25 | */ 26 | int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) 27 | { 28 | LTC_ARGCHK(IV != NULL); 29 | LTC_ARGCHK(cbc != NULL); 30 | if (len != (unsigned long)cbc->blocklen) { 31 | return CRYPT_INVALID_ARG; 32 | } 33 | XMEMCPY(cbc->IV, IV, len); 34 | return CRYPT_OK; 35 | } 36 | 37 | #endif 38 | 39 | 40 | /* ref: $Format:%D$ */ 41 | /* git commit: $Format:%H$ */ 42 | /* commit time: $Format:%ai$ */ 43 | -------------------------------------------------------------------------------- /cbc_start.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file cbc_start.c 13 | CBC implementation, start chain, Tom St Denis 14 | */ 15 | 16 | #ifdef LTC_CBC_MODE 17 | 18 | /** 19 | Initialize a CBC context 20 | @param cipher The index of the cipher desired 21 | @param IV The initialization vector 22 | @param key The secret key 23 | @param keylen The length of the secret key (octets) 24 | @param num_rounds Number of rounds in the cipher desired (0 for default) 25 | @param cbc The CBC state to initialize 26 | @return CRYPT_OK if successful 27 | */ 28 | int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, 29 | int keylen, int num_rounds, symmetric_CBC *cbc) 30 | { 31 | int x, err; 32 | 33 | LTC_ARGCHK(IV != NULL); 34 | LTC_ARGCHK(key != NULL); 35 | LTC_ARGCHK(cbc != NULL); 36 | 37 | /* bad param? */ 38 | if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { 39 | return err; 40 | } 41 | 42 | /* setup cipher */ 43 | if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { 44 | return err; 45 | } 46 | 47 | /* copy IV */ 48 | cbc->blocklen = cipher_descriptor[cipher].block_length; 49 | cbc->cipher = cipher; 50 | for (x = 0; x < cbc->blocklen; x++) { 51 | cbc->IV[x] = IV[x]; 52 | } 53 | return CRYPT_OK; 54 | } 55 | 56 | #endif 57 | 58 | /* ref: $Format:%D$ */ 59 | /* git commit: $Format:%H$ */ 60 | /* commit time: $Format:%ai$ */ 61 | -------------------------------------------------------------------------------- /compare_testvector.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | #include "tomcrypt_private.h" 11 | 12 | /** 13 | @file compare_testvector.c 14 | Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel 15 | */ 16 | 17 | #if defined(LTC_TEST) && defined(LTC_TEST_DBG) 18 | static void _print_hex(const char* what, const void* v, const unsigned long l) 19 | { 20 | const unsigned char* p = v; 21 | unsigned long x, y = 0, z; 22 | fprintf(stderr, "%s contents: \n", what); 23 | for (x = 0; x < l; ) { 24 | fprintf(stderr, "%02X ", p[x]); 25 | if (!(++x % 16) || x == l) { 26 | if((x % 16) != 0) { 27 | z = 16 - (x % 16); 28 | if(z >= 8) 29 | fprintf(stderr, " "); 30 | for (; z != 0; --z) { 31 | fprintf(stderr, " "); 32 | } 33 | } 34 | fprintf(stderr, " | "); 35 | for(; y < x; y++) { 36 | if((y % 8) == 0) 37 | fprintf(stderr, " "); 38 | if(isgraph(p[y])) 39 | fprintf(stderr, "%c", p[y]); 40 | else 41 | fprintf(stderr, "."); 42 | } 43 | fprintf(stderr, "\n"); 44 | } 45 | else if((x % 8) == 0) { 46 | fprintf(stderr, " "); 47 | } 48 | } 49 | } 50 | #endif 51 | 52 | /** 53 | Compare two test-vectors 54 | 55 | @param is The data as it is 56 | @param is_len The length of is 57 | @param should The data as it should 58 | @param should_len The length of should 59 | @param what The type of the data 60 | @param which The iteration count 61 | @return 0 on equality, -1 or 1 on difference 62 | */ 63 | int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) 64 | { 65 | int res = 0; 66 | if(is_len != should_len) { 67 | res = is_len > should_len ? -1 : 1; 68 | } else { 69 | res = XMEMCMP(is, should, is_len); 70 | } 71 | #if defined(LTC_TEST) && defined(LTC_TEST_DBG) 72 | if (res != 0) { 73 | fprintf(stderr, "Testvector #%i of %s failed:\n", which, what); 74 | _print_hex("SHOULD", should, should_len); 75 | _print_hex("IS ", is, is_len); 76 | #if LTC_TEST_DBG > 1 77 | } else { 78 | fprintf(stderr, "Testvector #%i of %s passed!\n", which, what); 79 | #endif 80 | } 81 | #else 82 | LTC_UNUSED_PARAM(which); 83 | LTC_UNUSED_PARAM(what); 84 | #endif 85 | 86 | return res; 87 | } 88 | 89 | /* ref: $Format:%D$ */ 90 | /* git commit: $Format:%H$ */ 91 | /* commit time: $Format:%ai$ */ 92 | -------------------------------------------------------------------------------- /crypt_argchk.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_argchk.c 13 | Perform argument checking, Tom St Denis 14 | */ 15 | 16 | #if (ARGTYPE == 0) 17 | void crypt_argchk(const char *v, const char *s, int d) 18 | { 19 | fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", 20 | v, d, s); 21 | abort(); 22 | } 23 | #endif 24 | 25 | /* ref: $Format:%D$ */ 26 | /* git commit: $Format:%H$ */ 27 | /* commit time: $Format:%ai$ */ 28 | -------------------------------------------------------------------------------- /crypt_cipher_descriptor.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_cipher_descriptor.c 13 | Stores the cipher descriptor table, Tom St Denis 14 | */ 15 | 16 | struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = { 17 | { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } 18 | }; 19 | 20 | LTC_MUTEX_GLOBAL(ltc_cipher_mutex) 21 | 22 | 23 | /* ref: $Format:%D$ */ 24 | /* git commit: $Format:%H$ */ 25 | /* commit time: $Format:%ai$ */ 26 | -------------------------------------------------------------------------------- /crypt_cipher_is_valid.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_cipher_is_valid.c 13 | Determine if cipher is valid, Tom St Denis 14 | */ 15 | 16 | /* 17 | Test if a cipher index is valid 18 | @param idx The index of the cipher to search for 19 | @return CRYPT_OK if valid 20 | */ 21 | int cipher_is_valid(int idx) 22 | { 23 | LTC_MUTEX_LOCK(<c_cipher_mutex); 24 | if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { 25 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 26 | return CRYPT_INVALID_CIPHER; 27 | } 28 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 29 | return CRYPT_OK; 30 | } 31 | 32 | /* ref: $Format:%D$ */ 33 | /* git commit: $Format:%H$ */ 34 | /* commit time: $Format:%ai$ */ 35 | -------------------------------------------------------------------------------- /crypt_find_cipher.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_cipher.c 13 | Find a cipher in the descriptor tables, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a registered cipher by name 18 | @param name The name of the cipher to look for 19 | @return >= 0 if found, -1 if not present 20 | */ 21 | int find_cipher(const char *name) 22 | { 23 | int x; 24 | LTC_ARGCHK(name != NULL); 25 | LTC_MUTEX_LOCK(<c_cipher_mutex); 26 | for (x = 0; x < TAB_SIZE; x++) { 27 | if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) { 28 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 29 | return x; 30 | } 31 | } 32 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 33 | return -1; 34 | } 35 | 36 | 37 | /* ref: $Format:%D$ */ 38 | /* git commit: $Format:%H$ */ 39 | /* commit time: $Format:%ai$ */ 40 | -------------------------------------------------------------------------------- /crypt_find_cipher_any.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_cipher_any.c 13 | Find a cipher in the descriptor tables, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a cipher flexibly. First by name then if not present by block and key size 18 | @param name The name of the cipher desired 19 | @param blocklen The minimum length of the block cipher desired (octets) 20 | @param keylen The minimum length of the key size desired (octets) 21 | @return >= 0 if found, -1 if not present 22 | */ 23 | int find_cipher_any(const char *name, int blocklen, int keylen) 24 | { 25 | int x; 26 | 27 | if(name != NULL) { 28 | x = find_cipher(name); 29 | if (x != -1) return x; 30 | } 31 | 32 | LTC_MUTEX_LOCK(<c_cipher_mutex); 33 | for (x = 0; x < TAB_SIZE; x++) { 34 | if (cipher_descriptor[x].name == NULL) { 35 | continue; 36 | } 37 | if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { 38 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 39 | return x; 40 | } 41 | } 42 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 43 | return -1; 44 | } 45 | 46 | /* ref: $Format:%D$ */ 47 | /* git commit: $Format:%H$ */ 48 | /* commit time: $Format:%ai$ */ 49 | -------------------------------------------------------------------------------- /crypt_find_cipher_id.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_cipher_id.c 13 | Find cipher by ID, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a cipher by ID number 18 | @param ID The ID (not same as index) of the cipher to find 19 | @return >= 0 if found, -1 if not present 20 | */ 21 | int find_cipher_id(unsigned char ID) 22 | { 23 | int x; 24 | LTC_MUTEX_LOCK(<c_cipher_mutex); 25 | for (x = 0; x < TAB_SIZE; x++) { 26 | if (cipher_descriptor[x].ID == ID) { 27 | x = (cipher_descriptor[x].name == NULL) ? -1 : x; 28 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 29 | return x; 30 | } 31 | } 32 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 33 | return -1; 34 | } 35 | 36 | /* ref: $Format:%D$ */ 37 | /* git commit: $Format:%H$ */ 38 | /* commit time: $Format:%ai$ */ 39 | -------------------------------------------------------------------------------- /crypt_find_hash.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_hash.c 13 | Find a hash, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a registered hash by name 18 | @param name The name of the hash to look for 19 | @return >= 0 if found, -1 if not present 20 | */ 21 | int find_hash(const char *name) 22 | { 23 | int x; 24 | LTC_ARGCHK(name != NULL); 25 | LTC_MUTEX_LOCK(<c_hash_mutex); 26 | for (x = 0; x < TAB_SIZE; x++) { 27 | if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) { 28 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 29 | return x; 30 | } 31 | } 32 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 33 | return -1; 34 | } 35 | 36 | /* ref: $Format:%D$ */ 37 | /* git commit: $Format:%H$ */ 38 | /* commit time: $Format:%ai$ */ 39 | -------------------------------------------------------------------------------- /crypt_find_hash_any.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_hash_any.c 13 | Find a hash, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a hash flexibly. First by name then if not present by digest size 18 | @param name The name of the hash desired 19 | @param digestlen The minimum length of the digest size (octets) 20 | @return >= 0 if found, -1 if not present 21 | */int find_hash_any(const char *name, int digestlen) 22 | { 23 | int x, y, z; 24 | LTC_ARGCHK(name != NULL); 25 | 26 | x = find_hash(name); 27 | if (x != -1) return x; 28 | 29 | LTC_MUTEX_LOCK(<c_hash_mutex); 30 | y = MAXBLOCKSIZE+1; 31 | z = -1; 32 | for (x = 0; x < TAB_SIZE; x++) { 33 | if (hash_descriptor[x].name == NULL) { 34 | continue; 35 | } 36 | if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { 37 | z = x; 38 | y = hash_descriptor[x].hashsize; 39 | } 40 | } 41 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 42 | return z; 43 | } 44 | 45 | /* ref: $Format:%D$ */ 46 | /* git commit: $Format:%H$ */ 47 | /* commit time: $Format:%ai$ */ 48 | -------------------------------------------------------------------------------- /crypt_find_hash_id.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_hash_id.c 13 | Find hash by ID, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a hash by ID number 18 | @param ID The ID (not same as index) of the hash to find 19 | @return >= 0 if found, -1 if not present 20 | */ 21 | int find_hash_id(unsigned char ID) 22 | { 23 | int x; 24 | LTC_MUTEX_LOCK(<c_hash_mutex); 25 | for (x = 0; x < TAB_SIZE; x++) { 26 | if (hash_descriptor[x].ID == ID) { 27 | x = (hash_descriptor[x].name == NULL) ? -1 : x; 28 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 29 | return x; 30 | } 31 | } 32 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 33 | return -1; 34 | } 35 | 36 | /* ref: $Format:%D$ */ 37 | /* git commit: $Format:%H$ */ 38 | /* commit time: $Format:%ai$ */ 39 | -------------------------------------------------------------------------------- /crypt_find_hash_oid.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_hash_oid.c 13 | Find a hash, Tom St Denis 14 | */ 15 | 16 | int find_hash_oid(const unsigned long *ID, unsigned long IDlen) 17 | { 18 | int x; 19 | LTC_ARGCHK(ID != NULL); 20 | LTC_MUTEX_LOCK(<c_hash_mutex); 21 | for (x = 0; x < TAB_SIZE; x++) { 22 | if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) { 23 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 24 | return x; 25 | } 26 | } 27 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 28 | return -1; 29 | } 30 | 31 | /* ref: $Format:%D$ */ 32 | /* git commit: $Format:%H$ */ 33 | /* commit time: $Format:%ai$ */ 34 | -------------------------------------------------------------------------------- /crypt_find_prng.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_find_prng.c 13 | Find a PRNG, Tom St Denis 14 | */ 15 | 16 | /** 17 | Find a registered PRNG by name 18 | @param name The name of the PRNG to look for 19 | @return >= 0 if found, -1 if not present 20 | */ 21 | int find_prng(const char *name) 22 | { 23 | int x; 24 | LTC_ARGCHK(name != NULL); 25 | LTC_MUTEX_LOCK(<c_prng_mutex); 26 | for (x = 0; x < TAB_SIZE; x++) { 27 | if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) { 28 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 29 | return x; 30 | } 31 | } 32 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 33 | return -1; 34 | } 35 | 36 | 37 | /* ref: $Format:%D$ */ 38 | /* git commit: $Format:%H$ */ 39 | /* commit time: $Format:%ai$ */ 40 | -------------------------------------------------------------------------------- /crypt_fsa.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | #include 11 | 12 | /** 13 | @file crypt_fsa.c 14 | LibTomCrypt FULL SPEED AHEAD!, Tom St Denis 15 | */ 16 | 17 | /* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */ 18 | int crypt_fsa(void *mp, ...) 19 | { 20 | va_list args; 21 | void *p; 22 | 23 | va_start(args, mp); 24 | if (mp != NULL) { 25 | XMEMCPY(<c_mp, mp, sizeof(ltc_mp)); 26 | } 27 | 28 | while ((p = va_arg(args, void*)) != NULL) { 29 | if (register_cipher(p) == -1) { 30 | va_end(args); 31 | return CRYPT_INVALID_CIPHER; 32 | } 33 | } 34 | 35 | while ((p = va_arg(args, void*)) != NULL) { 36 | if (register_hash(p) == -1) { 37 | va_end(args); 38 | return CRYPT_INVALID_HASH; 39 | } 40 | } 41 | 42 | while ((p = va_arg(args, void*)) != NULL) { 43 | if (register_prng(p) == -1) { 44 | va_end(args); 45 | return CRYPT_INVALID_PRNG; 46 | } 47 | } 48 | 49 | va_end(args); 50 | return CRYPT_OK; 51 | } 52 | 53 | 54 | /* ref: $Format:%D$ */ 55 | /* git commit: $Format:%H$ */ 56 | /* commit time: $Format:%ai$ */ 57 | -------------------------------------------------------------------------------- /crypt_hash_descriptor.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_hash_descriptor.c 13 | Stores the hash descriptor table, Tom St Denis 14 | */ 15 | 16 | struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = { 17 | { NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL } 18 | }; 19 | 20 | LTC_MUTEX_GLOBAL(ltc_hash_mutex) 21 | 22 | 23 | /* ref: $Format:%D$ */ 24 | /* git commit: $Format:%H$ */ 25 | /* commit time: $Format:%ai$ */ 26 | -------------------------------------------------------------------------------- /crypt_hash_is_valid.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_hash_is_valid.c 13 | Determine if hash is valid, Tom St Denis 14 | */ 15 | 16 | /* 17 | Test if a hash index is valid 18 | @param idx The index of the hash to search for 19 | @return CRYPT_OK if valid 20 | */ 21 | int hash_is_valid(int idx) 22 | { 23 | LTC_MUTEX_LOCK(<c_hash_mutex); 24 | if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { 25 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 26 | return CRYPT_INVALID_HASH; 27 | } 28 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 29 | return CRYPT_OK; 30 | } 31 | 32 | /* ref: $Format:%D$ */ 33 | /* git commit: $Format:%H$ */ 34 | /* commit time: $Format:%ai$ */ 35 | -------------------------------------------------------------------------------- /crypt_inits.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_inits.c 13 | 14 | Provide math library functions for dynamic languages 15 | like Python - Larry Bugbee, February 2013 16 | */ 17 | 18 | 19 | #ifdef LTM_DESC 20 | void init_LTM(void) 21 | { 22 | ltc_mp = ltm_desc; 23 | } 24 | #endif 25 | 26 | #ifdef TFM_DESC 27 | void init_TFM(void) 28 | { 29 | ltc_mp = tfm_desc; 30 | } 31 | #endif 32 | 33 | #ifdef GMP_DESC 34 | void init_GMP(void) 35 | { 36 | ltc_mp = gmp_desc; 37 | } 38 | #endif 39 | 40 | int crypt_mp_init(const char* mpi) 41 | { 42 | if (mpi == NULL) return CRYPT_ERROR; 43 | switch (mpi[0]) { 44 | #ifdef LTM_DESC 45 | case 'l': 46 | case 'L': 47 | ltc_mp = ltm_desc; 48 | return CRYPT_OK; 49 | #endif 50 | #ifdef TFM_DESC 51 | case 't': 52 | case 'T': 53 | ltc_mp = tfm_desc; 54 | return CRYPT_OK; 55 | #endif 56 | #ifdef GMP_DESC 57 | case 'g': 58 | case 'G': 59 | ltc_mp = gmp_desc; 60 | return CRYPT_OK; 61 | #endif 62 | #ifdef EXT_MATH_LIB 63 | case 'e': 64 | case 'E': 65 | { 66 | extern ltc_math_descriptor EXT_MATH_LIB; 67 | ltc_mp = EXT_MATH_LIB; 68 | } 69 | 70 | #if defined(LTC_TEST_DBG) 71 | #define NAME_VALUE(s) #s"="NAME(s) 72 | #define NAME(s) #s 73 | printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB)); 74 | #undef NAME_VALUE 75 | #undef NAME 76 | #endif 77 | 78 | return CRYPT_OK; 79 | #endif 80 | default: 81 | #if defined(LTC_TEST_DBG) 82 | printf("Unknown/Invalid MPI provider: %s\n", mpi); 83 | #endif 84 | return CRYPT_ERROR; 85 | } 86 | } 87 | 88 | 89 | /* ref: $Format:%D$ */ 90 | /* git commit: $Format:%H$ */ 91 | /* commit time: $Format:%ai$ */ 92 | -------------------------------------------------------------------------------- /crypt_ltc_mp_descriptor.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */ 12 | ltc_math_descriptor ltc_mp = { 0 }; 13 | 14 | /* ref: $Format:%D$ */ 15 | /* git commit: $Format:%H$ */ 16 | /* commit time: $Format:%ai$ */ 17 | -------------------------------------------------------------------------------- /crypt_prng_descriptor.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_prng_descriptor.c 13 | Stores the PRNG descriptors, Tom St Denis 14 | */ 15 | struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = { 16 | { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } 17 | }; 18 | 19 | LTC_MUTEX_GLOBAL(ltc_prng_mutex) 20 | 21 | 22 | /* ref: $Format:%D$ */ 23 | /* git commit: $Format:%H$ */ 24 | /* commit time: $Format:%ai$ */ 25 | -------------------------------------------------------------------------------- /crypt_prng_is_valid.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_prng_is_valid.c 13 | Determine if PRNG is valid, Tom St Denis 14 | */ 15 | 16 | /* 17 | Test if a PRNG index is valid 18 | @param idx The index of the PRNG to search for 19 | @return CRYPT_OK if valid 20 | */ 21 | int prng_is_valid(int idx) 22 | { 23 | LTC_MUTEX_LOCK(<c_prng_mutex); 24 | if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { 25 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 26 | return CRYPT_INVALID_PRNG; 27 | } 28 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 29 | return CRYPT_OK; 30 | } 31 | 32 | /* ref: $Format:%D$ */ 33 | /* git commit: $Format:%H$ */ 34 | /* commit time: $Format:%ai$ */ 35 | -------------------------------------------------------------------------------- /crypt_prng_rng_descriptor.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | #ifdef LTC_PRNG_ENABLE_LTC_RNG 12 | unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); 13 | #endif 14 | 15 | /* ref: $Format:%D$ */ 16 | /* git commit: $Format:%H$ */ 17 | /* commit time: $Format:%ai$ */ 18 | -------------------------------------------------------------------------------- /crypt_register_cipher.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_register_cipher.c 13 | Register a cipher, Tom St Denis 14 | */ 15 | 16 | /** 17 | Register a cipher with the descriptor table 18 | @param cipher The cipher you wish to register 19 | @return value >= 0 if successfully added (or already present), -1 if unsuccessful 20 | */ 21 | int register_cipher(const struct ltc_cipher_descriptor *cipher) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(cipher != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_cipher_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { 31 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 32 | return x; 33 | } 34 | } 35 | 36 | /* find a blank spot */ 37 | for (x = 0; x < TAB_SIZE; x++) { 38 | if (cipher_descriptor[x].name == NULL) { 39 | XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)); 40 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 41 | return x; 42 | } 43 | } 44 | 45 | /* no spot */ 46 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 47 | return -1; 48 | } 49 | 50 | /* ref: $Format:%D$ */ 51 | /* git commit: $Format:%H$ */ 52 | /* commit time: $Format:%ai$ */ 53 | -------------------------------------------------------------------------------- /crypt_register_hash.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_register_hash.c 13 | Register a HASH, Tom St Denis 14 | */ 15 | 16 | /** 17 | Register a hash with the descriptor table 18 | @param hash The hash you wish to register 19 | @return value >= 0 if successfully added (or already present), -1 if unsuccessful 20 | */ 21 | int register_hash(const struct ltc_hash_descriptor *hash) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(hash != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_hash_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { 31 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 32 | return x; 33 | } 34 | } 35 | 36 | /* find a blank spot */ 37 | for (x = 0; x < TAB_SIZE; x++) { 38 | if (hash_descriptor[x].name == NULL) { 39 | XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)); 40 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 41 | return x; 42 | } 43 | } 44 | 45 | /* no spot */ 46 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 47 | return -1; 48 | } 49 | 50 | /* ref: $Format:%D$ */ 51 | /* git commit: $Format:%H$ */ 52 | /* commit time: $Format:%ai$ */ 53 | -------------------------------------------------------------------------------- /crypt_register_prng.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_register_prng.c 13 | Register a PRNG, Tom St Denis 14 | */ 15 | 16 | /** 17 | Register a PRNG with the descriptor table 18 | @param prng The PRNG you wish to register 19 | @return value >= 0 if successfully added (or already present), -1 if unsuccessful 20 | */ 21 | int register_prng(const struct ltc_prng_descriptor *prng) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(prng != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_prng_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { 31 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 32 | return x; 33 | } 34 | } 35 | 36 | /* find a blank spot */ 37 | for (x = 0; x < TAB_SIZE; x++) { 38 | if (prng_descriptor[x].name == NULL) { 39 | XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)); 40 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 41 | return x; 42 | } 43 | } 44 | 45 | /* no spot */ 46 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 47 | return -1; 48 | } 49 | 50 | /* ref: $Format:%D$ */ 51 | /* git commit: $Format:%H$ */ 52 | /* commit time: $Format:%ai$ */ 53 | -------------------------------------------------------------------------------- /crypt_unregister_cipher.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_unregister_cipher.c 13 | Unregister a cipher, Tom St Denis 14 | */ 15 | 16 | /** 17 | Unregister a cipher from the descriptor table 18 | @param cipher The cipher descriptor to remove 19 | @return CRYPT_OK on success 20 | */ 21 | int unregister_cipher(const struct ltc_cipher_descriptor *cipher) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(cipher != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_cipher_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) { 31 | cipher_descriptor[x].name = NULL; 32 | cipher_descriptor[x].ID = 255; 33 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 34 | return CRYPT_OK; 35 | } 36 | } 37 | LTC_MUTEX_UNLOCK(<c_cipher_mutex); 38 | return CRYPT_ERROR; 39 | } 40 | 41 | /* ref: $Format:%D$ */ 42 | /* git commit: $Format:%H$ */ 43 | /* commit time: $Format:%ai$ */ 44 | -------------------------------------------------------------------------------- /crypt_unregister_hash.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_unregister_hash.c 13 | Unregister a hash, Tom St Denis 14 | */ 15 | 16 | /** 17 | Unregister a hash from the descriptor table 18 | @param hash The hash descriptor to remove 19 | @return CRYPT_OK on success 20 | */ 21 | int unregister_hash(const struct ltc_hash_descriptor *hash) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(hash != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_hash_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { 31 | hash_descriptor[x].name = NULL; 32 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 33 | return CRYPT_OK; 34 | } 35 | } 36 | LTC_MUTEX_UNLOCK(<c_hash_mutex); 37 | return CRYPT_ERROR; 38 | } 39 | 40 | /* ref: $Format:%D$ */ 41 | /* git commit: $Format:%H$ */ 42 | /* commit time: $Format:%ai$ */ 43 | -------------------------------------------------------------------------------- /crypt_unregister_prng.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file crypt_unregister_prng.c 13 | Unregister a PRNG, Tom St Denis 14 | */ 15 | 16 | /** 17 | Unregister a PRNG from the descriptor table 18 | @param prng The PRNG descriptor to remove 19 | @return CRYPT_OK on success 20 | */ 21 | int unregister_prng(const struct ltc_prng_descriptor *prng) 22 | { 23 | int x; 24 | 25 | LTC_ARGCHK(prng != NULL); 26 | 27 | /* is it already registered? */ 28 | LTC_MUTEX_LOCK(<c_prng_mutex); 29 | for (x = 0; x < TAB_SIZE; x++) { 30 | if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { 31 | prng_descriptor[x].name = NULL; 32 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 33 | return CRYPT_OK; 34 | } 35 | } 36 | LTC_MUTEX_UNLOCK(<c_prng_mutex); 37 | return CRYPT_ERROR; 38 | } 39 | 40 | /* ref: $Format:%D$ */ 41 | /* git commit: $Format:%H$ */ 42 | /* commit time: $Format:%ai$ */ 43 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package sqlite3 provides interface to SQLite3 databases. 3 | 4 | This works as a driver for database/sql. 5 | 6 | Installation 7 | 8 | go get github.com/mattn/go-sqlite3 9 | 10 | Supported Types 11 | 12 | Currently, go-sqlite3 supports the following data types. 13 | 14 | +------------------------------+ 15 | |go | sqlite3 | 16 | |----------|-------------------| 17 | |nil | null | 18 | |int | integer | 19 | |int64 | integer | 20 | |float64 | float | 21 | |bool | integer | 22 | |[]byte | blob | 23 | |string | text | 24 | |time.Time | timestamp/datetime| 25 | +------------------------------+ 26 | 27 | SQLite3 Extension 28 | 29 | You can write your own extension module for sqlite3. For example, below is an 30 | extension for a Regexp matcher operation. 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | SQLITE_EXTENSION_INIT1 38 | static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) { 39 | if (argc >= 2) { 40 | const char *target = (const char *)sqlite3_value_text(argv[1]); 41 | const char *pattern = (const char *)sqlite3_value_text(argv[0]); 42 | const char* errstr = NULL; 43 | int erroff = 0; 44 | int vec[500]; 45 | int n, rc; 46 | pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL); 47 | rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500); 48 | if (rc <= 0) { 49 | sqlite3_result_error(context, errstr, 0); 50 | return; 51 | } 52 | sqlite3_result_int(context, 1); 53 | } 54 | } 55 | 56 | #ifdef _WIN32 57 | __declspec(dllexport) 58 | #endif 59 | int sqlite3_extension_init(sqlite3 *db, char **errmsg, 60 | const sqlite3_api_routines *api) { 61 | SQLITE_EXTENSION_INIT2(api); 62 | return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 63 | (void*)db, regexp_func, NULL, NULL); 64 | } 65 | 66 | It needs to be built as a so/dll shared library. And you need to register 67 | the extension module like below. 68 | 69 | sql.Register("sqlite3_with_extensions", 70 | &sqlite3.SQLiteDriver{ 71 | Extensions: []string{ 72 | "sqlite3_mod_regexp", 73 | }, 74 | }) 75 | 76 | Then, you can use this extension. 77 | 78 | rows, err := db.Query("select text from mytable where name regexp '^golang'") 79 | 80 | Connection Hook 81 | 82 | You can hook and inject your code when the connection is established. database/sql 83 | doesn't provide a way to get native go-sqlite3 interfaces. So if you want, 84 | you need to set ConnectHook and get the SQLiteConn. 85 | 86 | sql.Register("sqlite3_with_hook_example", 87 | &sqlite3.SQLiteDriver{ 88 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 89 | sqlite3conn = append(sqlite3conn, conn) 90 | return nil 91 | }, 92 | }) 93 | 94 | Go SQlite3 Extensions 95 | 96 | If you want to register Go functions as SQLite extension functions, 97 | call RegisterFunction from ConnectHook. 98 | 99 | regex = func(re, s string) (bool, error) { 100 | return regexp.MatchString(re, s) 101 | } 102 | sql.Register("sqlite3_with_go_func", 103 | &sqlite3.SQLiteDriver{ 104 | ConnectHook: func(conn *sqlite3.SQLiteConn) error { 105 | return conn.RegisterFunc("regexp", regex, true) 106 | }, 107 | }) 108 | 109 | See the documentation of RegisterFunc for more details. 110 | 111 | */ 112 | package sqlite3 113 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import "C" 9 | 10 | // ErrNo inherit errno. 11 | type ErrNo int 12 | 13 | // ErrNoMask is mask code. 14 | const ErrNoMask C.int = 0xff 15 | 16 | // ErrNoExtended is extended errno. 17 | type ErrNoExtended int 18 | 19 | // Error implement sqlite error code. 20 | type Error struct { 21 | Code ErrNo /* The error code returned by SQLite */ 22 | ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */ 23 | err string /* The error string returned by sqlite3_errmsg(), 24 | this usually contains more specific details. */ 25 | } 26 | 27 | // result codes from http://www.sqlite.org/c3ref/c_abort.html 28 | var ( 29 | ErrError = ErrNo(1) /* SQL error or missing database */ 30 | ErrInternal = ErrNo(2) /* Internal logic error in SQLite */ 31 | ErrPerm = ErrNo(3) /* Access permission denied */ 32 | ErrAbort = ErrNo(4) /* Callback routine requested an abort */ 33 | ErrBusy = ErrNo(5) /* The database file is locked */ 34 | ErrLocked = ErrNo(6) /* A table in the database is locked */ 35 | ErrNomem = ErrNo(7) /* A malloc() failed */ 36 | ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */ 37 | ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */ 38 | ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */ 39 | ErrCorrupt = ErrNo(11) /* The database disk image is malformed */ 40 | ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */ 41 | ErrFull = ErrNo(13) /* Insertion failed because database is full */ 42 | ErrCantOpen = ErrNo(14) /* Unable to open the database file */ 43 | ErrProtocol = ErrNo(15) /* Database lock protocol error */ 44 | ErrEmpty = ErrNo(16) /* Database is empty */ 45 | ErrSchema = ErrNo(17) /* The database schema changed */ 46 | ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */ 47 | ErrConstraint = ErrNo(19) /* Abort due to constraint violation */ 48 | ErrMismatch = ErrNo(20) /* Data type mismatch */ 49 | ErrMisuse = ErrNo(21) /* Library used incorrectly */ 50 | ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */ 51 | ErrAuth = ErrNo(23) /* Authorization denied */ 52 | ErrFormat = ErrNo(24) /* Auxiliary database format error */ 53 | ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */ 54 | ErrNotADB = ErrNo(26) /* File opened that is not a database file */ 55 | ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */ 56 | ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */ 57 | ) 58 | 59 | // Error return error message from errno. 60 | func (err ErrNo) Error() string { 61 | return Error{Code: err}.Error() 62 | } 63 | 64 | // Extend return extended errno. 65 | func (err ErrNo) Extend(by int) ErrNoExtended { 66 | return ErrNoExtended(int(err) | (by << 8)) 67 | } 68 | 69 | // Error return error message that is extended code. 70 | func (err ErrNoExtended) Error() string { 71 | return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error() 72 | } 73 | 74 | func (err Error) Error() string { 75 | if err.err != "" { 76 | return err.err 77 | } 78 | return errorString(err) 79 | } 80 | 81 | // result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html 82 | var ( 83 | ErrIoErrRead = ErrIoErr.Extend(1) 84 | ErrIoErrShortRead = ErrIoErr.Extend(2) 85 | ErrIoErrWrite = ErrIoErr.Extend(3) 86 | ErrIoErrFsync = ErrIoErr.Extend(4) 87 | ErrIoErrDirFsync = ErrIoErr.Extend(5) 88 | ErrIoErrTruncate = ErrIoErr.Extend(6) 89 | ErrIoErrFstat = ErrIoErr.Extend(7) 90 | ErrIoErrUnlock = ErrIoErr.Extend(8) 91 | ErrIoErrRDlock = ErrIoErr.Extend(9) 92 | ErrIoErrDelete = ErrIoErr.Extend(10) 93 | ErrIoErrBlocked = ErrIoErr.Extend(11) 94 | ErrIoErrNoMem = ErrIoErr.Extend(12) 95 | ErrIoErrAccess = ErrIoErr.Extend(13) 96 | ErrIoErrCheckReservedLock = ErrIoErr.Extend(14) 97 | ErrIoErrLock = ErrIoErr.Extend(15) 98 | ErrIoErrClose = ErrIoErr.Extend(16) 99 | ErrIoErrDirClose = ErrIoErr.Extend(17) 100 | ErrIoErrSHMOpen = ErrIoErr.Extend(18) 101 | ErrIoErrSHMSize = ErrIoErr.Extend(19) 102 | ErrIoErrSHMLock = ErrIoErr.Extend(20) 103 | ErrIoErrSHMMap = ErrIoErr.Extend(21) 104 | ErrIoErrSeek = ErrIoErr.Extend(22) 105 | ErrIoErrDeleteNoent = ErrIoErr.Extend(23) 106 | ErrIoErrMMap = ErrIoErr.Extend(24) 107 | ErrIoErrGetTempPath = ErrIoErr.Extend(25) 108 | ErrIoErrConvPath = ErrIoErr.Extend(26) 109 | ErrLockedSharedCache = ErrLocked.Extend(1) 110 | ErrBusyRecovery = ErrBusy.Extend(1) 111 | ErrBusySnapshot = ErrBusy.Extend(2) 112 | ErrCantOpenNoTempDir = ErrCantOpen.Extend(1) 113 | ErrCantOpenIsDir = ErrCantOpen.Extend(2) 114 | ErrCantOpenFullPath = ErrCantOpen.Extend(3) 115 | ErrCantOpenConvPath = ErrCantOpen.Extend(4) 116 | ErrCorruptVTab = ErrCorrupt.Extend(1) 117 | ErrReadonlyRecovery = ErrReadonly.Extend(1) 118 | ErrReadonlyCantLock = ErrReadonly.Extend(2) 119 | ErrReadonlyRollback = ErrReadonly.Extend(3) 120 | ErrReadonlyDbMoved = ErrReadonly.Extend(4) 121 | ErrAbortRollback = ErrAbort.Extend(2) 122 | ErrConstraintCheck = ErrConstraint.Extend(1) 123 | ErrConstraintCommitHook = ErrConstraint.Extend(2) 124 | ErrConstraintForeignKey = ErrConstraint.Extend(3) 125 | ErrConstraintFunction = ErrConstraint.Extend(4) 126 | ErrConstraintNotNull = ErrConstraint.Extend(5) 127 | ErrConstraintPrimaryKey = ErrConstraint.Extend(6) 128 | ErrConstraintTrigger = ErrConstraint.Extend(7) 129 | ErrConstraintUnique = ErrConstraint.Extend(8) 130 | ErrConstraintVTab = ErrConstraint.Extend(9) 131 | ErrConstraintRowID = ErrConstraint.Extend(10) 132 | ErrNoticeRecoverWAL = ErrNotice.Extend(1) 133 | ErrNoticeRecoverRollback = ErrNotice.Extend(2) 134 | ErrWarningAutoIndex = ErrWarning.Extend(1) 135 | ) 136 | -------------------------------------------------------------------------------- /error_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "database/sql" 10 | "io/ioutil" 11 | "os" 12 | "path" 13 | "testing" 14 | ) 15 | 16 | func TestSimpleError(t *testing.T) { 17 | e := ErrError.Error() 18 | if e != "SQL logic error or missing database" && e != "SQL logic error" { 19 | t.Error("wrong error code: " + e) 20 | } 21 | } 22 | 23 | func TestCorruptDbErrors(t *testing.T) { 24 | dirName, err := ioutil.TempDir("", "sqlite3") 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | defer os.RemoveAll(dirName) 29 | 30 | dbFileName := path.Join(dirName, "test.db") 31 | f, err := os.Create(dbFileName) 32 | if err != nil { 33 | t.Error(err) 34 | } 35 | f.Write([]byte{1, 2, 3, 4, 5}) 36 | f.Close() 37 | 38 | db, err := sql.Open("sqlite3", dbFileName) 39 | if err == nil { 40 | _, err = db.Exec("drop table foo") 41 | } 42 | 43 | sqliteErr := err.(Error) 44 | if sqliteErr.Code != ErrNotADB { 45 | t.Error("wrong error code for corrupted DB") 46 | } 47 | if err.Error() == "" { 48 | t.Error("wrong error string for corrupted DB") 49 | } 50 | db.Close() 51 | } 52 | 53 | func TestSqlLogicErrors(t *testing.T) { 54 | dirName, err := ioutil.TempDir("", "sqlite3") 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | defer os.RemoveAll(dirName) 59 | 60 | dbFileName := path.Join(dirName, "test.db") 61 | db, err := sql.Open("sqlite3", dbFileName) 62 | if err != nil { 63 | t.Error(err) 64 | } 65 | defer db.Close() 66 | 67 | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") 68 | if err != nil { 69 | t.Error(err) 70 | } 71 | 72 | const expectedErr = "table Foo already exists" 73 | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") 74 | if err.Error() != expectedErr { 75 | t.Errorf("Unexpected error: %s, expected %s", err.Error(), expectedErr) 76 | } 77 | 78 | } 79 | 80 | func TestExtendedErrorCodes_ForeignKey(t *testing.T) { 81 | dirName, err := ioutil.TempDir("", "sqlite3-err") 82 | if err != nil { 83 | t.Fatal(err) 84 | } 85 | defer os.RemoveAll(dirName) 86 | 87 | dbFileName := path.Join(dirName, "test.db") 88 | db, err := sql.Open("sqlite3", dbFileName) 89 | if err != nil { 90 | t.Error(err) 91 | } 92 | defer db.Close() 93 | 94 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 95 | if err != nil { 96 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 97 | } 98 | 99 | _, err = db.Exec(`CREATE TABLE Foo ( 100 | id INTEGER PRIMARY KEY AUTOINCREMENT, 101 | value INTEGER NOT NULL, 102 | ref INTEGER NULL REFERENCES Foo (id), 103 | UNIQUE(value) 104 | );`) 105 | if err != nil { 106 | t.Error(err) 107 | } 108 | 109 | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (100, 100);") 110 | if err == nil { 111 | t.Error("No error!") 112 | } else { 113 | sqliteErr := err.(Error) 114 | if sqliteErr.Code != ErrConstraint { 115 | t.Errorf("Wrong basic error code: %d != %d", 116 | sqliteErr.Code, ErrConstraint) 117 | } 118 | if sqliteErr.ExtendedCode != ErrConstraintForeignKey { 119 | t.Errorf("Wrong extended error code: %d != %d", 120 | sqliteErr.ExtendedCode, ErrConstraintForeignKey) 121 | } 122 | } 123 | 124 | } 125 | 126 | func TestExtendedErrorCodes_NotNull(t *testing.T) { 127 | dirName, err := ioutil.TempDir("", "sqlite3-err") 128 | if err != nil { 129 | t.Fatal(err) 130 | } 131 | defer os.RemoveAll(dirName) 132 | 133 | dbFileName := path.Join(dirName, "test.db") 134 | db, err := sql.Open("sqlite3", dbFileName) 135 | if err != nil { 136 | t.Error(err) 137 | } 138 | defer db.Close() 139 | 140 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 141 | if err != nil { 142 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 143 | } 144 | 145 | _, err = db.Exec(`CREATE TABLE Foo ( 146 | id INTEGER PRIMARY KEY AUTOINCREMENT, 147 | value INTEGER NOT NULL, 148 | ref INTEGER NULL REFERENCES Foo (id), 149 | UNIQUE(value) 150 | );`) 151 | if err != nil { 152 | t.Error(err) 153 | } 154 | 155 | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") 156 | if err != nil { 157 | t.Fatalf("Creating first row: %v", err) 158 | } 159 | 160 | id, err := res.LastInsertId() 161 | if err != nil { 162 | t.Fatalf("Retrieving last insert id: %v", err) 163 | } 164 | 165 | _, err = db.Exec("INSERT INTO Foo (ref) VALUES (?);", id) 166 | if err == nil { 167 | t.Error("No error!") 168 | } else { 169 | sqliteErr := err.(Error) 170 | if sqliteErr.Code != ErrConstraint { 171 | t.Errorf("Wrong basic error code: %d != %d", 172 | sqliteErr.Code, ErrConstraint) 173 | } 174 | if sqliteErr.ExtendedCode != ErrConstraintNotNull { 175 | t.Errorf("Wrong extended error code: %d != %d", 176 | sqliteErr.ExtendedCode, ErrConstraintNotNull) 177 | } 178 | } 179 | 180 | } 181 | 182 | func TestExtendedErrorCodes_Unique(t *testing.T) { 183 | dirName, err := ioutil.TempDir("", "sqlite3-err") 184 | if err != nil { 185 | t.Fatal(err) 186 | } 187 | defer os.RemoveAll(dirName) 188 | 189 | dbFileName := path.Join(dirName, "test.db") 190 | db, err := sql.Open("sqlite3", dbFileName) 191 | if err != nil { 192 | t.Error(err) 193 | } 194 | defer db.Close() 195 | 196 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 197 | if err != nil { 198 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 199 | } 200 | 201 | _, err = db.Exec(`CREATE TABLE Foo ( 202 | id INTEGER PRIMARY KEY AUTOINCREMENT, 203 | value INTEGER NOT NULL, 204 | ref INTEGER NULL REFERENCES Foo (id), 205 | UNIQUE(value) 206 | );`) 207 | if err != nil { 208 | t.Error(err) 209 | } 210 | 211 | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") 212 | if err != nil { 213 | t.Fatalf("Creating first row: %v", err) 214 | } 215 | 216 | id, err := res.LastInsertId() 217 | if err != nil { 218 | t.Fatalf("Retrieving last insert id: %v", err) 219 | } 220 | 221 | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (?, 100);", id) 222 | if err == nil { 223 | t.Error("No error!") 224 | } else { 225 | sqliteErr := err.(Error) 226 | if sqliteErr.Code != ErrConstraint { 227 | t.Errorf("Wrong basic error code: %d != %d", 228 | sqliteErr.Code, ErrConstraint) 229 | } 230 | if sqliteErr.ExtendedCode != ErrConstraintUnique { 231 | t.Errorf("Wrong extended error code: %d != %d", 232 | sqliteErr.ExtendedCode, ErrConstraintUnique) 233 | } 234 | extended := sqliteErr.Code.Extend(3).Error() 235 | expected := "constraint failed" 236 | if extended != expected { 237 | t.Errorf("Wrong basic error code: %q != %q", 238 | extended, expected) 239 | } 240 | } 241 | 242 | } 243 | -------------------------------------------------------------------------------- /hash_memory.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | #ifdef LTC_HASH_HELPERS 12 | /** 13 | @file hash_memory.c 14 | Hash memory helper, Tom St Denis 15 | */ 16 | 17 | /** 18 | Hash a block of memory and store the digest. 19 | @param hash The index of the hash you wish to use 20 | @param in The data you wish to hash 21 | @param inlen The length of the data to hash (octets) 22 | @param out [out] Where to store the digest 23 | @param outlen [in/out] Max size and resulting size of the digest 24 | @return CRYPT_OK if successful 25 | */ 26 | int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) 27 | { 28 | hash_state *md; 29 | int err; 30 | 31 | LTC_ARGCHK(in != NULL); 32 | LTC_ARGCHK(out != NULL); 33 | LTC_ARGCHK(outlen != NULL); 34 | 35 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { 36 | return err; 37 | } 38 | 39 | if (*outlen < hash_descriptor[hash].hashsize) { 40 | *outlen = hash_descriptor[hash].hashsize; 41 | return CRYPT_BUFFER_OVERFLOW; 42 | } 43 | 44 | md = XMALLOC(sizeof(hash_state)); 45 | if (md == NULL) { 46 | return CRYPT_MEM; 47 | } 48 | 49 | if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { 50 | goto LBL_ERR; 51 | } 52 | if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) { 53 | goto LBL_ERR; 54 | } 55 | err = hash_descriptor[hash].done(md, out); 56 | *outlen = hash_descriptor[hash].hashsize; 57 | LBL_ERR: 58 | #ifdef LTC_CLEAN_STACK 59 | zeromem(md, sizeof(hash_state)); 60 | #endif 61 | XFREE(md); 62 | 63 | return err; 64 | } 65 | #endif /* #ifdef LTC_HASH_HELPERS */ 66 | 67 | /* ref: $Format:%D$ */ 68 | /* git commit: $Format:%H$ */ 69 | /* commit time: $Format:%ai$ */ 70 | -------------------------------------------------------------------------------- /hash_memory_multi.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | #include 11 | 12 | #ifdef LTC_HASH_HELPERS 13 | /** 14 | @file hash_memory_multi.c 15 | Hash (multiple buffers) memory helper, Tom St Denis 16 | */ 17 | 18 | /** 19 | Hash multiple (non-adjacent) blocks of memory at once. 20 | @param hash The index of the hash you wish to use 21 | @param out [out] Where to store the digest 22 | @param outlen [in/out] Max size and resulting size of the digest 23 | @param in The data you wish to hash 24 | @param inlen The length of the data to hash (octets) 25 | @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) 26 | @return CRYPT_OK if successful 27 | */ 28 | int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, 29 | const unsigned char *in, unsigned long inlen, ...) 30 | { 31 | hash_state *md; 32 | int err; 33 | va_list args; 34 | const unsigned char *curptr; 35 | unsigned long curlen; 36 | 37 | LTC_ARGCHK(in != NULL); 38 | LTC_ARGCHK(out != NULL); 39 | LTC_ARGCHK(outlen != NULL); 40 | 41 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { 42 | return err; 43 | } 44 | 45 | if (*outlen < hash_descriptor[hash].hashsize) { 46 | *outlen = hash_descriptor[hash].hashsize; 47 | return CRYPT_BUFFER_OVERFLOW; 48 | } 49 | 50 | md = XMALLOC(sizeof(hash_state)); 51 | if (md == NULL) { 52 | return CRYPT_MEM; 53 | } 54 | 55 | if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { 56 | goto LBL_ERR; 57 | } 58 | 59 | va_start(args, inlen); 60 | curptr = in; 61 | curlen = inlen; 62 | for (;;) { 63 | /* process buf */ 64 | if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) { 65 | goto LBL_ERR; 66 | } 67 | /* step to next */ 68 | curptr = va_arg(args, const unsigned char*); 69 | if (curptr == NULL) { 70 | break; 71 | } 72 | curlen = va_arg(args, unsigned long); 73 | } 74 | err = hash_descriptor[hash].done(md, out); 75 | *outlen = hash_descriptor[hash].hashsize; 76 | LBL_ERR: 77 | #ifdef LTC_CLEAN_STACK 78 | zeromem(md, sizeof(hash_state)); 79 | #endif 80 | XFREE(md); 81 | va_end(args); 82 | return err; 83 | } 84 | #endif /* #ifdef LTC_HASH_HELPERS */ 85 | 86 | /* ref: $Format:%D$ */ 87 | /* git commit: $Format:%H$ */ 88 | /* commit time: $Format:%ai$ */ 89 | -------------------------------------------------------------------------------- /hmac_done.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file hmac_done.c 13 | HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer 14 | */ 15 | 16 | #ifdef LTC_HMAC 17 | 18 | #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize 19 | 20 | /** 21 | Terminate an HMAC session 22 | @param hmac The HMAC state 23 | @param out [out] The destination of the HMAC authentication tag 24 | @param outlen [in/out] The max size and resulting size of the HMAC authentication tag 25 | @return CRYPT_OK if successful 26 | */ 27 | int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) 28 | { 29 | unsigned char *buf, *isha; 30 | unsigned long hashsize, i; 31 | int hash, err; 32 | 33 | LTC_ARGCHK(hmac != NULL); 34 | LTC_ARGCHK(out != NULL); 35 | 36 | /* test hash */ 37 | hash = hmac->hash; 38 | if((err = hash_is_valid(hash)) != CRYPT_OK) { 39 | return err; 40 | } 41 | 42 | /* get the hash message digest size */ 43 | hashsize = hash_descriptor[hash].hashsize; 44 | 45 | /* allocate buffers */ 46 | buf = XMALLOC(LTC_HMAC_BLOCKSIZE); 47 | isha = XMALLOC(hashsize); 48 | if (buf == NULL || isha == NULL) { 49 | if (buf != NULL) { 50 | XFREE(buf); 51 | } 52 | if (isha != NULL) { 53 | XFREE(isha); 54 | } 55 | return CRYPT_MEM; 56 | } 57 | 58 | /* Get the hash of the first HMAC vector plus the data */ 59 | if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { 60 | goto LBL_ERR; 61 | } 62 | 63 | /* Create the second HMAC vector vector for step (3) */ 64 | for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { 65 | buf[i] = hmac->key[i] ^ 0x5C; 66 | } 67 | 68 | /* Now calculate the "outer" hash for step (5), (6), and (7) */ 69 | if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { 70 | goto LBL_ERR; 71 | } 72 | if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { 73 | goto LBL_ERR; 74 | } 75 | if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { 76 | goto LBL_ERR; 77 | } 78 | if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { 79 | goto LBL_ERR; 80 | } 81 | 82 | /* copy to output */ 83 | for (i = 0; i < hashsize && i < *outlen; i++) { 84 | out[i] = buf[i]; 85 | } 86 | *outlen = i; 87 | 88 | err = CRYPT_OK; 89 | LBL_ERR: 90 | #ifdef LTC_CLEAN_STACK 91 | zeromem(isha, hashsize); 92 | zeromem(buf, hashsize); 93 | zeromem(hmac, sizeof(*hmac)); 94 | #endif 95 | 96 | XFREE(isha); 97 | XFREE(buf); 98 | 99 | return err; 100 | } 101 | 102 | #endif 103 | 104 | /* ref: $Format:%D$ */ 105 | /* git commit: $Format:%H$ */ 106 | /* commit time: $Format:%ai$ */ 107 | -------------------------------------------------------------------------------- /hmac_file.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file hmac_file.c 13 | HMAC support, process a file, Tom St Denis/Dobes Vandermeer 14 | */ 15 | 16 | #ifdef LTC_HMAC 17 | 18 | /** 19 | HMAC a file 20 | @param hash The index of the hash you wish to use 21 | @param fname The name of the file you wish to HMAC 22 | @param key The secret key 23 | @param keylen The length of the secret key 24 | @param out [out] The HMAC authentication tag 25 | @param outlen [in/out] The max size and resulting size of the authentication tag 26 | @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled 27 | */ 28 | int hmac_file(int hash, const char *fname, 29 | const unsigned char *key, unsigned long keylen, 30 | unsigned char *out, unsigned long *outlen) 31 | { 32 | #ifdef LTC_NO_FILE 33 | LTC_UNUSED_PARAM(hash); 34 | LTC_UNUSED_PARAM(fname); 35 | LTC_UNUSED_PARAM(key); 36 | LTC_UNUSED_PARAM(keylen); 37 | LTC_UNUSED_PARAM(out); 38 | LTC_UNUSED_PARAM(outlen); 39 | return CRYPT_NOP; 40 | #else 41 | hmac_state hmac; 42 | FILE *in; 43 | unsigned char *buf; 44 | size_t x; 45 | int err; 46 | 47 | LTC_ARGCHK(fname != NULL); 48 | LTC_ARGCHK(key != NULL); 49 | LTC_ARGCHK(out != NULL); 50 | LTC_ARGCHK(outlen != NULL); 51 | 52 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { 53 | return CRYPT_MEM; 54 | } 55 | 56 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { 57 | goto LBL_ERR; 58 | } 59 | 60 | if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { 61 | goto LBL_ERR; 62 | } 63 | 64 | in = fopen(fname, "rb"); 65 | if (in == NULL) { 66 | err = CRYPT_FILE_NOTFOUND; 67 | goto LBL_ERR; 68 | } 69 | 70 | do { 71 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); 72 | if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { 73 | fclose(in); /* we don't trap this error since we're already returning an error! */ 74 | goto LBL_CLEANBUF; 75 | } 76 | } while (x == LTC_FILE_READ_BUFSIZE); 77 | 78 | if (fclose(in) != 0) { 79 | err = CRYPT_ERROR; 80 | goto LBL_CLEANBUF; 81 | } 82 | 83 | err = hmac_done(&hmac, out, outlen); 84 | 85 | LBL_CLEANBUF: 86 | zeromem(buf, LTC_FILE_READ_BUFSIZE); 87 | LBL_ERR: 88 | #ifdef LTC_CLEAN_STACK 89 | zeromem(&hmac, sizeof(hmac_state)); 90 | #endif 91 | XFREE(buf); 92 | return err; 93 | #endif 94 | } 95 | 96 | #endif 97 | 98 | /* ref: $Format:%D$ */ 99 | /* git commit: $Format:%H$ */ 100 | /* commit time: $Format:%ai$ */ 101 | -------------------------------------------------------------------------------- /hmac_init.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file hmac_init.c 13 | HMAC support, initialize state, Tom St Denis/Dobes Vandermeer 14 | */ 15 | 16 | #ifdef LTC_HMAC 17 | 18 | #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize 19 | 20 | /** 21 | Initialize an HMAC context. 22 | @param hmac The HMAC state 23 | @param hash The index of the hash you want to use 24 | @param key The secret key 25 | @param keylen The length of the secret key (octets) 26 | @return CRYPT_OK if successful 27 | */ 28 | int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) 29 | { 30 | unsigned char *buf; 31 | unsigned long hashsize; 32 | unsigned long i, z; 33 | int err; 34 | 35 | LTC_ARGCHK(hmac != NULL); 36 | LTC_ARGCHK(key != NULL); 37 | 38 | /* valid hash? */ 39 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { 40 | return err; 41 | } 42 | hmac->hash = hash; 43 | hashsize = hash_descriptor[hash].hashsize; 44 | 45 | /* valid key length? */ 46 | if (keylen == 0) { 47 | return CRYPT_INVALID_KEYSIZE; 48 | } 49 | 50 | /* allocate ram for buf */ 51 | buf = XMALLOC(LTC_HMAC_BLOCKSIZE); 52 | if (buf == NULL) { 53 | return CRYPT_MEM; 54 | } 55 | 56 | /* check hash block fits */ 57 | if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) { 58 | err = CRYPT_BUFFER_OVERFLOW; 59 | goto LBL_ERR; 60 | } 61 | 62 | /* (1) make sure we have a large enough key */ 63 | if(keylen > LTC_HMAC_BLOCKSIZE) { 64 | z = LTC_HMAC_BLOCKSIZE; 65 | if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { 66 | goto LBL_ERR; 67 | } 68 | keylen = hashsize; 69 | } else { 70 | XMEMCPY(hmac->key, key, (size_t)keylen); 71 | } 72 | 73 | if(keylen < LTC_HMAC_BLOCKSIZE) { 74 | zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); 75 | } 76 | 77 | /* Create the initialization vector for step (3) */ 78 | for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { 79 | buf[i] = hmac->key[i] ^ 0x36; 80 | } 81 | 82 | /* Pre-pend that to the hash data */ 83 | if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { 84 | goto LBL_ERR; 85 | } 86 | 87 | if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { 88 | goto LBL_ERR; 89 | } 90 | 91 | LBL_ERR: 92 | #ifdef LTC_CLEAN_STACK 93 | zeromem(buf, LTC_HMAC_BLOCKSIZE); 94 | #endif 95 | 96 | XFREE(buf); 97 | return err; 98 | } 99 | 100 | #endif 101 | 102 | /* ref: $Format:%D$ */ 103 | /* git commit: $Format:%H$ */ 104 | /* commit time: $Format:%ai$ */ 105 | -------------------------------------------------------------------------------- /hmac_memory.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file hmac_memory.c 13 | HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer 14 | */ 15 | 16 | #ifdef LTC_HMAC 17 | 18 | /** 19 | HMAC a block of memory to produce the authentication tag 20 | @param hash The index of the hash to use 21 | @param key The secret key 22 | @param keylen The length of the secret key (octets) 23 | @param in The data to HMAC 24 | @param inlen The length of the data to HMAC (octets) 25 | @param out [out] Destination of the authentication tag 26 | @param outlen [in/out] Max size and resulting size of authentication tag 27 | @return CRYPT_OK if successful 28 | */ 29 | int hmac_memory(int hash, 30 | const unsigned char *key, unsigned long keylen, 31 | const unsigned char *in, unsigned long inlen, 32 | unsigned char *out, unsigned long *outlen) 33 | { 34 | hmac_state *hmac; 35 | int err; 36 | 37 | LTC_ARGCHK(key != NULL); 38 | LTC_ARGCHK(in != NULL); 39 | LTC_ARGCHK(out != NULL); 40 | LTC_ARGCHK(outlen != NULL); 41 | 42 | /* make sure hash descriptor is valid */ 43 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { 44 | return err; 45 | } 46 | 47 | /* is there a descriptor? */ 48 | if (hash_descriptor[hash].hmac_block != NULL) { 49 | return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); 50 | } 51 | 52 | /* nope, so call the hmac functions */ 53 | /* allocate ram for hmac state */ 54 | hmac = XMALLOC(sizeof(hmac_state)); 55 | if (hmac == NULL) { 56 | return CRYPT_MEM; 57 | } 58 | 59 | if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { 60 | goto LBL_ERR; 61 | } 62 | 63 | if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { 64 | goto LBL_ERR; 65 | } 66 | 67 | if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { 68 | goto LBL_ERR; 69 | } 70 | 71 | err = CRYPT_OK; 72 | LBL_ERR: 73 | #ifdef LTC_CLEAN_STACK 74 | zeromem(hmac, sizeof(hmac_state)); 75 | #endif 76 | 77 | XFREE(hmac); 78 | return err; 79 | } 80 | 81 | #endif 82 | 83 | 84 | /* ref: $Format:%D$ */ 85 | /* git commit: $Format:%H$ */ 86 | /* commit time: $Format:%ai$ */ 87 | -------------------------------------------------------------------------------- /hmac_memory_multi.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | #include 11 | 12 | /** 13 | @file hmac_memory_multi.c 14 | HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer 15 | */ 16 | 17 | #ifdef LTC_HMAC 18 | 19 | /** 20 | HMAC multiple blocks of memory to produce the authentication tag 21 | @param hash The index of the hash to use 22 | @param key The secret key 23 | @param keylen The length of the secret key (octets) 24 | @param out [out] Destination of the authentication tag 25 | @param outlen [in/out] Max size and resulting size of authentication tag 26 | @param in The data to HMAC 27 | @param inlen The length of the data to HMAC (octets) 28 | @param ... tuples of (data,len) pairs to HMAC, terminated with a (NULL,x) (x=don't care) 29 | @return CRYPT_OK if successful 30 | */ 31 | int hmac_memory_multi(int hash, 32 | const unsigned char *key, unsigned long keylen, 33 | unsigned char *out, unsigned long *outlen, 34 | const unsigned char *in, unsigned long inlen, ...) 35 | 36 | { 37 | hmac_state *hmac; 38 | int err; 39 | va_list args; 40 | const unsigned char *curptr; 41 | unsigned long curlen; 42 | 43 | LTC_ARGCHK(key != NULL); 44 | LTC_ARGCHK(in != NULL); 45 | LTC_ARGCHK(out != NULL); 46 | LTC_ARGCHK(outlen != NULL); 47 | 48 | /* allocate ram for hmac state */ 49 | hmac = XMALLOC(sizeof(hmac_state)); 50 | if (hmac == NULL) { 51 | return CRYPT_MEM; 52 | } 53 | 54 | if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { 55 | goto LBL_ERR; 56 | } 57 | 58 | va_start(args, inlen); 59 | curptr = in; 60 | curlen = inlen; 61 | for (;;) { 62 | /* process buf */ 63 | if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { 64 | goto LBL_ERR; 65 | } 66 | /* step to next */ 67 | curptr = va_arg(args, const unsigned char*); 68 | if (curptr == NULL) { 69 | break; 70 | } 71 | curlen = va_arg(args, unsigned long); 72 | } 73 | if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { 74 | goto LBL_ERR; 75 | } 76 | LBL_ERR: 77 | #ifdef LTC_CLEAN_STACK 78 | zeromem(hmac, sizeof(hmac_state)); 79 | #endif 80 | XFREE(hmac); 81 | va_end(args); 82 | return err; 83 | } 84 | 85 | #endif 86 | 87 | 88 | /* ref: $Format:%D$ */ 89 | /* git commit: $Format:%H$ */ 90 | /* commit time: $Format:%ai$ */ 91 | -------------------------------------------------------------------------------- /hmac_process.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file hmac_process.c 13 | HMAC support, process data, Tom St Denis/Dobes Vandermeer 14 | */ 15 | 16 | #ifdef LTC_HMAC 17 | 18 | /** 19 | Process data through HMAC 20 | @param hmac The hmac state 21 | @param in The data to send through HMAC 22 | @param inlen The length of the data to HMAC (octets) 23 | @return CRYPT_OK if successful 24 | */ 25 | int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) 26 | { 27 | int err; 28 | LTC_ARGCHK(hmac != NULL); 29 | LTC_ARGCHK(in != NULL); 30 | if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { 31 | return err; 32 | } 33 | return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); 34 | } 35 | 36 | #endif 37 | 38 | 39 | /* ref: $Format:%D$ */ 40 | /* git commit: $Format:%H$ */ 41 | /* commit time: $Format:%ai$ */ 42 | -------------------------------------------------------------------------------- /pkcs_5_2.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file pkcs_5_2.c 13 | PKCS #5, Algorithm #2, Tom St Denis 14 | */ 15 | #ifdef LTC_PKCS_5 16 | 17 | /** 18 | Execute PKCS #5 v2 19 | @param password The input password (or key) 20 | @param password_len The length of the password (octets) 21 | @param salt The salt (or nonce) 22 | @param salt_len The length of the salt (octets) 23 | @param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more] 24 | @param hash_idx The index of the hash desired 25 | @param out [out] The destination for this algorithm 26 | @param outlen [in/out] The max size and resulting size of the algorithm output 27 | @return CRYPT_OK if successful 28 | */ 29 | int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 30 | const unsigned char *salt, unsigned long salt_len, 31 | int iteration_count, int hash_idx, 32 | unsigned char *out, unsigned long *outlen) 33 | { 34 | int err, itts; 35 | ulong32 blkno; 36 | unsigned long stored, left, x, y; 37 | unsigned char *buf[2]; 38 | hmac_state *hmac; 39 | 40 | LTC_ARGCHK(password != NULL); 41 | LTC_ARGCHK(salt != NULL); 42 | LTC_ARGCHK(out != NULL); 43 | LTC_ARGCHK(outlen != NULL); 44 | 45 | /* test hash IDX */ 46 | if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 47 | return err; 48 | } 49 | 50 | buf[0] = XMALLOC(MAXBLOCKSIZE * 2); 51 | hmac = XMALLOC(sizeof(hmac_state)); 52 | if (hmac == NULL || buf[0] == NULL) { 53 | if (hmac != NULL) { 54 | XFREE(hmac); 55 | } 56 | if (buf[0] != NULL) { 57 | XFREE(buf[0]); 58 | } 59 | return CRYPT_MEM; 60 | } 61 | /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ 62 | buf[1] = buf[0] + MAXBLOCKSIZE; 63 | 64 | left = *outlen; 65 | blkno = 1; 66 | stored = 0; 67 | while (left != 0) { 68 | /* process block number blkno */ 69 | zeromem(buf[0], MAXBLOCKSIZE*2); 70 | 71 | /* store current block number and increment for next pass */ 72 | STORE32H(blkno, buf[1]); 73 | ++blkno; 74 | 75 | /* get PRF(P, S||int(blkno)) */ 76 | if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { 77 | goto LBL_ERR; 78 | } 79 | if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { 80 | goto LBL_ERR; 81 | } 82 | if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { 83 | goto LBL_ERR; 84 | } 85 | x = MAXBLOCKSIZE; 86 | if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { 87 | goto LBL_ERR; 88 | } 89 | 90 | /* now compute repeated and XOR it in buf[1] */ 91 | XMEMCPY(buf[1], buf[0], x); 92 | for (itts = 1; itts < iteration_count; ++itts) { 93 | if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { 94 | goto LBL_ERR; 95 | } 96 | for (y = 0; y < x; y++) { 97 | buf[1][y] ^= buf[0][y]; 98 | } 99 | } 100 | 101 | /* now emit upto x bytes of buf[1] to output */ 102 | for (y = 0; y < x && left != 0; ++y) { 103 | out[stored++] = buf[1][y]; 104 | --left; 105 | } 106 | } 107 | *outlen = stored; 108 | 109 | err = CRYPT_OK; 110 | LBL_ERR: 111 | #ifdef LTC_CLEAN_STACK 112 | zeromem(buf[0], MAXBLOCKSIZE*2); 113 | zeromem(hmac, sizeof(hmac_state)); 114 | #endif 115 | 116 | XFREE(hmac); 117 | XFREE(buf[0]); 118 | 119 | return err; 120 | } 121 | 122 | #endif 123 | 124 | 125 | /* ref: $Format:%D$ */ 126 | /* git commit: $Format:%H$ */ 127 | /* commit time: $Format:%ai$ */ 128 | -------------------------------------------------------------------------------- /sha1.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file sha1.c 13 | LTC_SHA1 code by Tom St Denis 14 | */ 15 | 16 | 17 | #ifdef LTC_SHA1 18 | 19 | const struct ltc_hash_descriptor sha1_desc = 20 | { 21 | "sha1", 22 | 2, 23 | 20, 24 | 64, 25 | 26 | /* OID */ 27 | { 1, 3, 14, 3, 2, 26, }, 28 | 6, 29 | 30 | &sha1_init, 31 | &sha1_process, 32 | &sha1_done, 33 | &sha1_test, 34 | NULL 35 | }; 36 | 37 | #define F0(x,y,z) (z ^ (x & (y ^ z))) 38 | #define F1(x,y,z) (x ^ y ^ z) 39 | #define F2(x,y,z) ((x & y) | (z & (x | y))) 40 | #define F3(x,y,z) (x ^ y ^ z) 41 | 42 | #ifdef LTC_CLEAN_STACK 43 | static int _sha1_compress(hash_state *md, const unsigned char *buf) 44 | #else 45 | static int sha1_compress(hash_state *md, const unsigned char *buf) 46 | #endif 47 | { 48 | ulong32 a,b,c,d,e,W[80],i; 49 | #ifdef LTC_SMALL_CODE 50 | ulong32 t; 51 | #endif 52 | 53 | /* copy the state into 512-bits into W[0..15] */ 54 | for (i = 0; i < 16; i++) { 55 | LOAD32H(W[i], buf + (4*i)); 56 | } 57 | 58 | /* copy state */ 59 | a = md->sha1.state[0]; 60 | b = md->sha1.state[1]; 61 | c = md->sha1.state[2]; 62 | d = md->sha1.state[3]; 63 | e = md->sha1.state[4]; 64 | 65 | /* expand it */ 66 | for (i = 16; i < 80; i++) { 67 | W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); 68 | } 69 | 70 | /* compress */ 71 | /* round one */ 72 | #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); 73 | #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); 74 | #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); 75 | #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); 76 | 77 | #ifdef LTC_SMALL_CODE 78 | 79 | for (i = 0; i < 20; ) { 80 | FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 81 | } 82 | 83 | for (; i < 40; ) { 84 | FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 85 | } 86 | 87 | for (; i < 60; ) { 88 | FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 89 | } 90 | 91 | for (; i < 80; ) { 92 | FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 93 | } 94 | 95 | #else 96 | 97 | for (i = 0; i < 20; ) { 98 | FF0(a,b,c,d,e,i++); 99 | FF0(e,a,b,c,d,i++); 100 | FF0(d,e,a,b,c,i++); 101 | FF0(c,d,e,a,b,i++); 102 | FF0(b,c,d,e,a,i++); 103 | } 104 | 105 | /* round two */ 106 | for (; i < 40; ) { 107 | FF1(a,b,c,d,e,i++); 108 | FF1(e,a,b,c,d,i++); 109 | FF1(d,e,a,b,c,i++); 110 | FF1(c,d,e,a,b,i++); 111 | FF1(b,c,d,e,a,i++); 112 | } 113 | 114 | /* round three */ 115 | for (; i < 60; ) { 116 | FF2(a,b,c,d,e,i++); 117 | FF2(e,a,b,c,d,i++); 118 | FF2(d,e,a,b,c,i++); 119 | FF2(c,d,e,a,b,i++); 120 | FF2(b,c,d,e,a,i++); 121 | } 122 | 123 | /* round four */ 124 | for (; i < 80; ) { 125 | FF3(a,b,c,d,e,i++); 126 | FF3(e,a,b,c,d,i++); 127 | FF3(d,e,a,b,c,i++); 128 | FF3(c,d,e,a,b,i++); 129 | FF3(b,c,d,e,a,i++); 130 | } 131 | #endif 132 | 133 | #undef FF0 134 | #undef FF1 135 | #undef FF2 136 | #undef FF3 137 | 138 | /* store */ 139 | md->sha1.state[0] = md->sha1.state[0] + a; 140 | md->sha1.state[1] = md->sha1.state[1] + b; 141 | md->sha1.state[2] = md->sha1.state[2] + c; 142 | md->sha1.state[3] = md->sha1.state[3] + d; 143 | md->sha1.state[4] = md->sha1.state[4] + e; 144 | 145 | return CRYPT_OK; 146 | } 147 | 148 | #ifdef LTC_CLEAN_STACK 149 | static int sha1_compress(hash_state *md, const unsigned char *buf) 150 | { 151 | int err; 152 | err = _sha1_compress(md, buf); 153 | burn_stack(sizeof(ulong32) * 87); 154 | return err; 155 | } 156 | #endif 157 | 158 | /** 159 | Initialize the hash state 160 | @param md The hash state you wish to initialize 161 | @return CRYPT_OK if successful 162 | */ 163 | int sha1_init(hash_state * md) 164 | { 165 | LTC_ARGCHK(md != NULL); 166 | md->sha1.state[0] = 0x67452301UL; 167 | md->sha1.state[1] = 0xefcdab89UL; 168 | md->sha1.state[2] = 0x98badcfeUL; 169 | md->sha1.state[3] = 0x10325476UL; 170 | md->sha1.state[4] = 0xc3d2e1f0UL; 171 | md->sha1.curlen = 0; 172 | md->sha1.length = 0; 173 | return CRYPT_OK; 174 | } 175 | 176 | /** 177 | Process a block of memory though the hash 178 | @param md The hash state 179 | @param in The data to hash 180 | @param inlen The length of the data (octets) 181 | @return CRYPT_OK if successful 182 | */ 183 | HASH_PROCESS(sha1_process, sha1_compress, sha1, 64) 184 | 185 | /** 186 | Terminate the hash to get the digest 187 | @param md The hash state 188 | @param out [out] The destination of the hash (20 bytes) 189 | @return CRYPT_OK if successful 190 | */ 191 | int sha1_done(hash_state * md, unsigned char *out) 192 | { 193 | int i; 194 | 195 | LTC_ARGCHK(md != NULL); 196 | LTC_ARGCHK(out != NULL); 197 | 198 | if (md->sha1.curlen >= sizeof(md->sha1.buf)) { 199 | return CRYPT_INVALID_ARG; 200 | } 201 | 202 | /* increase the length of the message */ 203 | md->sha1.length += md->sha1.curlen * 8; 204 | 205 | /* append the '1' bit */ 206 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; 207 | 208 | /* if the length is currently above 56 bytes we append zeros 209 | * then compress. Then we can fall back to padding zeros and length 210 | * encoding like normal. 211 | */ 212 | if (md->sha1.curlen > 56) { 213 | while (md->sha1.curlen < 64) { 214 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; 215 | } 216 | sha1_compress(md, md->sha1.buf); 217 | md->sha1.curlen = 0; 218 | } 219 | 220 | /* pad upto 56 bytes of zeroes */ 221 | while (md->sha1.curlen < 56) { 222 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; 223 | } 224 | 225 | /* store length */ 226 | STORE64H(md->sha1.length, md->sha1.buf+56); 227 | sha1_compress(md, md->sha1.buf); 228 | 229 | /* copy output */ 230 | for (i = 0; i < 5; i++) { 231 | STORE32H(md->sha1.state[i], out+(4*i)); 232 | } 233 | #ifdef LTC_CLEAN_STACK 234 | zeromem(md, sizeof(hash_state)); 235 | #endif 236 | return CRYPT_OK; 237 | } 238 | 239 | /** 240 | Self-test the hash 241 | @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 242 | */ 243 | int sha1_test(void) 244 | { 245 | #ifndef LTC_TEST 246 | return CRYPT_NOP; 247 | #else 248 | static const struct { 249 | const char *msg; 250 | unsigned char hash[20]; 251 | } tests[] = { 252 | { "abc", 253 | { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 254 | 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 255 | 0x9c, 0xd0, 0xd8, 0x9d } 256 | }, 257 | { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 258 | { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 259 | 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 260 | 0xE5, 0x46, 0x70, 0xF1 } 261 | } 262 | }; 263 | 264 | int i; 265 | unsigned char tmp[20]; 266 | hash_state md; 267 | 268 | for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { 269 | sha1_init(&md); 270 | sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 271 | sha1_done(&md, tmp); 272 | if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) { 273 | return CRYPT_FAIL_TESTVECTOR; 274 | } 275 | } 276 | return CRYPT_OK; 277 | #endif 278 | } 279 | 280 | #endif 281 | 282 | 283 | 284 | /* ref: $Format:%D$ */ 285 | /* git commit: $Format:%H$ */ 286 | /* commit time: $Format:%ai$ */ 287 | -------------------------------------------------------------------------------- /sqlcipher.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** SQLCipher 3 | ** sqlcipher.h developed by Stephen Lombardo (Zetetic LLC) 4 | ** sjlombardo at zetetic dot net 5 | ** http://zetetic.net 6 | ** 7 | ** Copyright (c) 2008, ZETETIC LLC 8 | ** All rights reserved. 9 | ** 10 | ** Redistribution and use in source and binary forms, with or without 11 | ** modification, are permitted provided that the following conditions are met: 12 | ** * Redistributions of source code must retain the above copyright 13 | ** notice, this list of conditions and the following disclaimer. 14 | ** * Redistributions in binary form must reproduce the above copyright 15 | ** notice, this list of conditions and the following disclaimer in the 16 | ** documentation and/or other materials provided with the distribution. 17 | ** * Neither the name of the ZETETIC LLC nor the 18 | ** names of its contributors may be used to endorse or promote products 19 | ** derived from this software without specific prior written permission. 20 | ** 21 | ** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY 22 | ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | ** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY 25 | ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 | ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ** 32 | */ 33 | /* BEGIN SQLCIPHER */ 34 | #ifdef SQLITE_HAS_CODEC 35 | #ifndef SQLCIPHER_H 36 | #define SQLCIPHER_H 37 | 38 | 39 | typedef struct { 40 | int (*activate)(void *ctx); 41 | int (*deactivate)(void *ctx); 42 | const char* (*get_provider_name)(void *ctx); 43 | int (*add_random)(void *ctx, void *buffer, int length); 44 | int (*random)(void *ctx, void *buffer, int length); 45 | int (*hmac)(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out); 46 | int (*kdf)(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key); 47 | int (*cipher)(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out); 48 | int (*set_cipher)(void *ctx, const char *cipher_name); 49 | const char* (*get_cipher)(void *ctx); 50 | int (*get_key_sz)(void *ctx); 51 | int (*get_iv_sz)(void *ctx); 52 | int (*get_block_sz)(void *ctx); 53 | int (*get_hmac_sz)(void *ctx); 54 | int (*ctx_copy)(void *target_ctx, void *source_ctx); 55 | int (*ctx_cmp)(void *c1, void *c2); 56 | int (*ctx_init)(void **ctx); 57 | int (*ctx_free)(void **ctx); 58 | int (*fips_status)(void *ctx); 59 | const char* (*get_provider_version)(void *ctx); 60 | } sqlcipher_provider; 61 | 62 | /* utility functions */ 63 | void sqlcipher_free(void *ptr, int sz); 64 | void* sqlcipher_malloc(int sz); 65 | void* sqlcipher_memset(void *v, unsigned char value, int len); 66 | int sqlcipher_ismemset(const void *v, unsigned char value, int len); 67 | int sqlcipher_memcmp(const void *v0, const void *v1, int len); 68 | void sqlcipher_free(void *, int); 69 | 70 | /* provider interfaces */ 71 | int sqlcipher_register_provider(sqlcipher_provider *p); 72 | sqlcipher_provider* sqlcipher_get_provider(); 73 | 74 | #endif 75 | #endif 76 | /* END SQLCIPHER */ 77 | 78 | -------------------------------------------------------------------------------- /sqlite3_context.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | /* 9 | 10 | #ifndef USE_LIBSQLITE3 11 | #include 12 | #else 13 | #include 14 | #endif 15 | #include 16 | // These wrappers are necessary because SQLITE_TRANSIENT 17 | // is a pointer constant, and cgo doesn't translate them correctly. 18 | 19 | static inline void my_result_text(sqlite3_context *ctx, char *p, int np) { 20 | sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT); 21 | } 22 | 23 | static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) { 24 | sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT); 25 | } 26 | */ 27 | import "C" 28 | 29 | import ( 30 | "math" 31 | "reflect" 32 | "unsafe" 33 | ) 34 | 35 | const i64 = unsafe.Sizeof(int(0)) > 4 36 | 37 | // SQLiteContext behave sqlite3_context 38 | type SQLiteContext C.sqlite3_context 39 | 40 | // ResultBool sets the result of an SQL function. 41 | func (c *SQLiteContext) ResultBool(b bool) { 42 | if b { 43 | c.ResultInt(1) 44 | } else { 45 | c.ResultInt(0) 46 | } 47 | } 48 | 49 | // ResultBlob sets the result of an SQL function. 50 | // See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html 51 | func (c *SQLiteContext) ResultBlob(b []byte) { 52 | if i64 && len(b) > math.MaxInt32 { 53 | C.sqlite3_result_error_toobig((*C.sqlite3_context)(c)) 54 | return 55 | } 56 | var p *byte 57 | if len(b) > 0 { 58 | p = &b[0] 59 | } 60 | C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b))) 61 | } 62 | 63 | // ResultDouble sets the result of an SQL function. 64 | // See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html 65 | func (c *SQLiteContext) ResultDouble(d float64) { 66 | C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d)) 67 | } 68 | 69 | // ResultInt sets the result of an SQL function. 70 | // See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html 71 | func (c *SQLiteContext) ResultInt(i int) { 72 | if i64 && (i > math.MaxInt32 || i < math.MinInt32) { 73 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) 74 | } else { 75 | C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i)) 76 | } 77 | } 78 | 79 | // ResultInt64 sets the result of an SQL function. 80 | // See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html 81 | func (c *SQLiteContext) ResultInt64(i int64) { 82 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) 83 | } 84 | 85 | // ResultNull sets the result of an SQL function. 86 | // See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html 87 | func (c *SQLiteContext) ResultNull() { 88 | C.sqlite3_result_null((*C.sqlite3_context)(c)) 89 | } 90 | 91 | // ResultText sets the result of an SQL function. 92 | // See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html 93 | func (c *SQLiteContext) ResultText(s string) { 94 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 95 | cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len) 96 | C.my_result_text((*C.sqlite3_context)(c), cs, l) 97 | } 98 | 99 | // ResultZeroblob sets the result of an SQL function. 100 | // See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html 101 | func (c *SQLiteContext) ResultZeroblob(n int) { 102 | C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n)) 103 | } 104 | -------------------------------------------------------------------------------- /sqlite3_func_crypt.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "crypto/sha1" 10 | "crypto/sha256" 11 | "crypto/sha512" 12 | ) 13 | 14 | // This file provides several different implementations for the 15 | // default embedded sqlite_crypt function. 16 | // This function is uses a caesar-cypher by default 17 | // and is used within the UserAuthentication module to encode 18 | // the password. 19 | // 20 | // The provided functions can be used as an overload to the sqlite_crypt 21 | // function through the use of the RegisterFunc on the connection. 22 | // 23 | // Because the functions can serv a purpose to an end-user 24 | // without using the UserAuthentication module 25 | // the functions are default compiled in. 26 | // 27 | // From SQLITE3 - user-auth.txt 28 | // The sqlite_user.pw field is encoded by a built-in SQL function 29 | // "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument 30 | // is the plaintext password supplied to the sqlite3_user_authenticate() 31 | // interface. The second argument is the sqlite_user.pw value and is supplied 32 | // so that the function can extract the "salt" used by the password encoder. 33 | // The result of sqlite_crypt(X,Y) is another blob which is the value that 34 | // ends up being stored in sqlite_user.pw. To verify credentials X supplied 35 | // by the sqlite3_user_authenticate() routine, SQLite runs: 36 | // 37 | // sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw) 38 | // 39 | // To compute an appropriate sqlite_user.pw value from a new or modified 40 | // password X, sqlite_crypt(X,NULL) is run. A new random salt is selected 41 | // when the second argument is NULL. 42 | // 43 | // The built-in version of of sqlite_crypt() uses a simple Caesar-cypher 44 | // which prevents passwords from being revealed by searching the raw database 45 | // for ASCII text, but is otherwise trivally broken. For better password 46 | // security, the database should be encrypted using the SQLite Encryption 47 | // Extension or similar technology. Or, the application can use the 48 | // sqlite3_create_function() interface to provide an alternative 49 | // implementation of sqlite_crypt() that computes a stronger password hash, 50 | // perhaps using a cryptographic hash function like SHA1. 51 | 52 | // CryptEncoderSHA1 encodes a password with SHA1 53 | func CryptEncoderSHA1(pass []byte, hash interface{}) []byte { 54 | h := sha1.Sum(pass) 55 | return h[:] 56 | } 57 | 58 | // CryptEncoderSSHA1 encodes a password with SHA1 with the 59 | // configured salt. 60 | func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte { 61 | return func(pass []byte, hash interface{}) []byte { 62 | s := []byte(salt) 63 | p := append(pass, s...) 64 | h := sha1.Sum(p) 65 | return h[:] 66 | } 67 | } 68 | 69 | // CryptEncoderSHA256 encodes a password with SHA256 70 | func CryptEncoderSHA256(pass []byte, hash interface{}) []byte { 71 | h := sha256.Sum256(pass) 72 | return h[:] 73 | } 74 | 75 | // CryptEncoderSSHA256 encodes a password with SHA256 76 | // with the configured salt 77 | func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte { 78 | return func(pass []byte, hash interface{}) []byte { 79 | s := []byte(salt) 80 | p := append(pass, s...) 81 | h := sha256.Sum256(p) 82 | return h[:] 83 | } 84 | } 85 | 86 | // CryptEncoderSHA384 encodes a password with SHA384 87 | func CryptEncoderSHA384(pass []byte, hash interface{}) []byte { 88 | h := sha512.Sum384(pass) 89 | return h[:] 90 | } 91 | 92 | // CryptEncoderSSHA384 encodes a password with SHA384 93 | // with the configured salt 94 | func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte { 95 | return func(pass []byte, hash interface{}) []byte { 96 | s := []byte(salt) 97 | p := append(pass, s...) 98 | h := sha512.Sum384(p) 99 | return h[:] 100 | } 101 | } 102 | 103 | // CryptEncoderSHA512 encodes a password with SHA512 104 | func CryptEncoderSHA512(pass []byte, hash interface{}) []byte { 105 | h := sha512.Sum512(pass) 106 | return h[:] 107 | } 108 | 109 | // CryptEncoderSSHA512 encodes a password with SHA512 110 | // with the configured salt 111 | func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte { 112 | return func(pass []byte, hash interface{}) []byte { 113 | s := []byte(salt) 114 | p := append(pass, s...) 115 | h := sha512.Sum512(p) 116 | return h[:] 117 | } 118 | } 119 | 120 | // EOF 121 | -------------------------------------------------------------------------------- /sqlite3_func_crypt_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "fmt" 10 | "strings" 11 | "testing" 12 | ) 13 | 14 | // TestCryptEncoders to increase coverage 15 | func TestCryptEncoders(t *testing.T) { 16 | tests := []struct { 17 | enc string 18 | salt string 19 | expected string 20 | }{ 21 | {"sha1", "", "d033e22ae348aeb5660fc2140aec35850c4da997"}, 22 | {"sha256", "", "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"}, 23 | {"sha384", "", "9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782"}, 24 | {"sha512", "", "c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec"}, 25 | {"ssha1", "salt", "9bc7aa55f08fdad935c3f8362d3f48bcf70eb280"}, 26 | {"ssha256", "salt", "f9a81477552594c79f2abc3fc099daa896a6e3a3590a55ffa392b6000412e80b"}, 27 | {"ssha384", "salt", "9ed776b477fcfc1b5e584989e8d770f5e17d98a7643546a63c2b07d4ab00f1348f6b8e73103d3a23554f727136e8c215"}, 28 | {"ssha512", "salt", "3c4a79782143337be4492be072abcfe979dd703c00541a8c39a0f3df4bab2029c050cf46fddc47090b5b04ac537b3e78189e3de16e601e859f95c51ac9f6dafb"}, 29 | } 30 | 31 | for _, e := range tests { 32 | var fn func(pass []byte, hash interface{}) []byte 33 | switch e.enc { 34 | case "sha1": 35 | fn = CryptEncoderSHA1 36 | case "ssha1": 37 | fn = CryptEncoderSSHA1(e.salt) 38 | case "sha256": 39 | fn = CryptEncoderSHA256 40 | case "ssha256": 41 | fn = CryptEncoderSSHA256(e.salt) 42 | case "sha384": 43 | fn = CryptEncoderSHA384 44 | case "ssha384": 45 | fn = CryptEncoderSSHA384(e.salt) 46 | case "sha512": 47 | fn = CryptEncoderSHA512 48 | case "ssha512": 49 | fn = CryptEncoderSSHA512(e.salt) 50 | } 51 | 52 | h := fn([]byte("admin"), nil) 53 | if strings.Compare(fmt.Sprintf("%x", h), e.expected) != 0 { 54 | t.Fatalf("Invalid %s hash: expected: %s; got: %x", strings.ToUpper(e.enc), e.expected, h) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /sqlite3_go18.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | // +build go1.8 8 | 9 | package sqlite3 10 | 11 | import ( 12 | "database/sql/driver" 13 | "errors" 14 | 15 | "context" 16 | ) 17 | 18 | // Ping implement Pinger. 19 | func (c *SQLiteConn) Ping(ctx context.Context) error { 20 | if c.db == nil { 21 | return errors.New("Connection was closed") 22 | } 23 | return nil 24 | } 25 | 26 | // QueryContext implement QueryerContext. 27 | func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 28 | list := make([]namedValue, len(args)) 29 | for i, nv := range args { 30 | list[i] = namedValue(nv) 31 | } 32 | return c.query(ctx, query, list) 33 | } 34 | 35 | // ExecContext implement ExecerContext. 36 | func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 37 | list := make([]namedValue, len(args)) 38 | for i, nv := range args { 39 | list[i] = namedValue(nv) 40 | } 41 | return c.exec(ctx, query, list) 42 | } 43 | 44 | // PrepareContext implement ConnPrepareContext. 45 | func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { 46 | return c.prepare(ctx, query) 47 | } 48 | 49 | // BeginTx implement ConnBeginTx. 50 | func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 51 | return c.begin(ctx) 52 | } 53 | 54 | // QueryContext implement QueryerContext. 55 | func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { 56 | list := make([]namedValue, len(args)) 57 | for i, nv := range args { 58 | list[i] = namedValue(nv) 59 | } 60 | return s.query(ctx, list) 61 | } 62 | 63 | // ExecContext implement ExecerContext. 64 | func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { 65 | list := make([]namedValue, len(args)) 66 | for i, nv := range args { 67 | list[i] = namedValue(nv) 68 | } 69 | return s.exec(ctx, list) 70 | } 71 | -------------------------------------------------------------------------------- /sqlite3_go18_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build go1.8 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "context" 12 | "database/sql" 13 | "fmt" 14 | "math/rand" 15 | "os" 16 | "testing" 17 | "time" 18 | ) 19 | 20 | func TestNamedParams(t *testing.T) { 21 | tempFilename := TempFilename(t) 22 | defer os.Remove(tempFilename) 23 | db, err := sql.Open("sqlite3", tempFilename) 24 | if err != nil { 25 | t.Fatal("Failed to open database:", err) 26 | } 27 | defer db.Close() 28 | 29 | _, err = db.Exec(` 30 | create table foo (id integer, name text, extra text); 31 | `) 32 | if err != nil { 33 | t.Error("Failed to call db.Query:", err) 34 | } 35 | 36 | _, err = db.Exec(`insert into foo(id, name, extra) values(:id, :name, :name)`, sql.Named("name", "foo"), sql.Named("id", 1)) 37 | if err != nil { 38 | t.Error("Failed to call db.Exec:", err) 39 | } 40 | 41 | row := db.QueryRow(`select id, extra from foo where id = :id and extra = :extra`, sql.Named("id", 1), sql.Named("extra", "foo")) 42 | if row == nil { 43 | t.Error("Failed to call db.QueryRow") 44 | } 45 | var id int 46 | var extra string 47 | err = row.Scan(&id, &extra) 48 | if err != nil { 49 | t.Error("Failed to db.Scan:", err) 50 | } 51 | if id != 1 || extra != "foo" { 52 | t.Error("Failed to db.QueryRow: not matched results") 53 | } 54 | } 55 | 56 | var ( 57 | testTableStatements = []string{ 58 | `DROP TABLE IF EXISTS test_table`, 59 | ` 60 | CREATE TABLE IF NOT EXISTS test_table ( 61 | key1 VARCHAR(64) PRIMARY KEY, 62 | key_id VARCHAR(64) NOT NULL, 63 | key2 VARCHAR(64) NOT NULL, 64 | key3 VARCHAR(64) NOT NULL, 65 | key4 VARCHAR(64) NOT NULL, 66 | key5 VARCHAR(64) NOT NULL, 67 | key6 VARCHAR(64) NOT NULL, 68 | data BLOB NOT NULL 69 | );`, 70 | } 71 | letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 72 | ) 73 | 74 | func randStringBytes(n int) string { 75 | b := make([]byte, n) 76 | for i := range b { 77 | b[i] = letterBytes[rand.Intn(len(letterBytes))] 78 | } 79 | return string(b) 80 | } 81 | 82 | func initDatabase(t *testing.T, db *sql.DB, rowCount int64) { 83 | for _, query := range testTableStatements { 84 | _, err := db.Exec(query) 85 | if err != nil { 86 | t.Fatal(err) 87 | } 88 | } 89 | for i := int64(0); i < rowCount; i++ { 90 | query := `INSERT INTO test_table 91 | (key1, key_id, key2, key3, key4, key5, key6, data) 92 | VALUES 93 | (?, ?, ?, ?, ?, ?, ?, ?);` 94 | args := []interface{}{ 95 | randStringBytes(50), 96 | fmt.Sprint(i), 97 | randStringBytes(50), 98 | randStringBytes(50), 99 | randStringBytes(50), 100 | randStringBytes(50), 101 | randStringBytes(50), 102 | randStringBytes(50), 103 | randStringBytes(2048), 104 | } 105 | _, err := db.Exec(query, args...) 106 | if err != nil { 107 | t.Fatal(err) 108 | } 109 | } 110 | } 111 | 112 | func TestShortTimeout(t *testing.T) { 113 | srcTempFilename := TempFilename(t) 114 | defer os.Remove(srcTempFilename) 115 | 116 | db, err := sql.Open("sqlite3", srcTempFilename) 117 | if err != nil { 118 | t.Fatal(err) 119 | } 120 | defer db.Close() 121 | initDatabase(t, db, 100) 122 | 123 | ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond) 124 | defer cancel() 125 | query := `SELECT key1, key_id, key2, key3, key4, key5, key6, data 126 | FROM test_table 127 | ORDER BY key2 ASC` 128 | _, err = db.QueryContext(ctx, query) 129 | if err != nil && err != context.DeadlineExceeded { 130 | t.Fatal(err) 131 | } 132 | if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { 133 | t.Fatal(ctx.Err()) 134 | } 135 | } 136 | 137 | func TestExecCancel(t *testing.T) { 138 | db, err := sql.Open("sqlite3", ":memory:") 139 | if err != nil { 140 | t.Fatal(err) 141 | } 142 | defer db.Close() 143 | 144 | if _, err = db.Exec("create table foo (id integer primary key)"); err != nil { 145 | t.Fatal(err) 146 | } 147 | 148 | for n := 0; n < 100; n++ { 149 | ctx, cancel := context.WithCancel(context.Background()) 150 | _, err = db.ExecContext(ctx, "insert into foo (id) values (?)", n) 151 | cancel() 152 | if err != nil { 153 | t.Fatal(err) 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /sqlite3_libsqlite3.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build libsqlite3 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DUSE_LIBSQLITE3 12 | #cgo linux LDFLAGS: -lsqlite3 13 | #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 14 | #cgo openbsd LDFLAGS: -lsqlite3 15 | #cgo solaris LDFLAGS: -lsqlite3 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /sqlite3_load_extension.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !sqlite_omit_load_extension 7 | 8 | package sqlite3 9 | 10 | /* 11 | #ifndef USE_LIBSQLITE3 12 | #include 13 | #else 14 | #include 15 | #endif 16 | #include 17 | */ 18 | import "C" 19 | import ( 20 | "errors" 21 | "unsafe" 22 | ) 23 | 24 | func (c *SQLiteConn) loadExtensions(extensions []string) error { 25 | rv := C.sqlite3_enable_load_extension(c.db, 1) 26 | if rv != C.SQLITE_OK { 27 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 28 | } 29 | 30 | for _, extension := range extensions { 31 | cext := C.CString(extension) 32 | defer C.free(unsafe.Pointer(cext)) 33 | rv = C.sqlite3_load_extension(c.db, cext, nil, nil) 34 | if rv != C.SQLITE_OK { 35 | C.sqlite3_enable_load_extension(c.db, 0) 36 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 37 | } 38 | } 39 | 40 | rv = C.sqlite3_enable_load_extension(c.db, 0) 41 | if rv != C.SQLITE_OK { 42 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 43 | } 44 | return nil 45 | } 46 | 47 | // LoadExtension load the sqlite3 extension. 48 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error { 49 | rv := C.sqlite3_enable_load_extension(c.db, 1) 50 | if rv != C.SQLITE_OK { 51 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 52 | } 53 | 54 | clib := C.CString(lib) 55 | defer C.free(unsafe.Pointer(clib)) 56 | centry := C.CString(entry) 57 | defer C.free(unsafe.Pointer(centry)) 58 | 59 | rv = C.sqlite3_load_extension(c.db, clib, centry, nil) 60 | if rv != C.SQLITE_OK { 61 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 62 | } 63 | 64 | rv = C.sqlite3_enable_load_extension(c.db, 0) 65 | if rv != C.SQLITE_OK { 66 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 67 | } 68 | 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /sqlite3_load_extension_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_omit_load_extension 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION 12 | */ 13 | import "C" 14 | import ( 15 | "errors" 16 | ) 17 | 18 | func (c *SQLiteConn) loadExtensions(extensions []string) error { 19 | return errors.New("Extensions have been disabled for static builds") 20 | } 21 | 22 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error { 23 | return errors.New("Extensions have been disabled for static builds") 24 | } 25 | -------------------------------------------------------------------------------- /sqlite3_opt_allow_uri_authority.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_allow_uri_authority 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_app_armor.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build !windows 8 | // +build sqlite_app_armor 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /sqlite3_opt_foreign_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_foreign_keys 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_fts3_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "database/sql" 10 | "os" 11 | "testing" 12 | ) 13 | 14 | func TestFTS3(t *testing.T) { 15 | tempFilename := TempFilename(t) 16 | defer os.Remove(tempFilename) 17 | db, err := sql.Open("sqlite3", tempFilename) 18 | if err != nil { 19 | t.Fatal("Failed to open database:", err) 20 | } 21 | defer db.Close() 22 | 23 | _, err = db.Exec("DROP TABLE foo") 24 | _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts3(id INTEGER PRIMARY KEY, value TEXT)") 25 | if err != nil { 26 | t.Fatal("Failed to create table:", err) 27 | } 28 | 29 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `今日の 晩御飯は 天麩羅よ`) 30 | if err != nil { 31 | t.Fatal("Failed to insert value:", err) 32 | } 33 | 34 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 2, `今日は いい 天気だ`) 35 | if err != nil { 36 | t.Fatal("Failed to insert value:", err) 37 | } 38 | 39 | rows, err := db.Query("SELECT id, value FROM foo WHERE value MATCH '今日* 天*'") 40 | if err != nil { 41 | t.Fatal("Unable to query foo table:", err) 42 | } 43 | defer rows.Close() 44 | 45 | for rows.Next() { 46 | var id int 47 | var value string 48 | 49 | if err := rows.Scan(&id, &value); err != nil { 50 | t.Error("Unable to scan results:", err) 51 | continue 52 | } 53 | 54 | if id == 1 && value != `今日の 晩御飯は 天麩羅よ` { 55 | t.Error("Value for id 1 should be `今日の 晩御飯は 天麩羅よ`, but:", value) 56 | } else if id == 2 && value != `今日は いい 天気だ` { 57 | t.Error("Value for id 2 should be `今日は いい 天気だ`, but:", value) 58 | } 59 | } 60 | 61 | rows, err = db.Query("SELECT value FROM foo WHERE value MATCH '今日* 天麩羅*'") 62 | if err != nil { 63 | t.Fatal("Unable to query foo table:", err) 64 | } 65 | defer rows.Close() 66 | 67 | var value string 68 | if !rows.Next() { 69 | t.Fatal("Result should be only one") 70 | } 71 | 72 | if err := rows.Scan(&value); err != nil { 73 | t.Fatal("Unable to scan results:", err) 74 | } 75 | 76 | if value != `今日の 晩御飯は 天麩羅よ` { 77 | t.Fatal("Value should be `今日の 晩御飯は 天麩羅よ`, but:", value) 78 | } 79 | 80 | if rows.Next() { 81 | t.Fatal("Result should be only one") 82 | } 83 | } 84 | 85 | func TestFTS4(t *testing.T) { 86 | tempFilename := TempFilename(t) 87 | defer os.Remove(tempFilename) 88 | db, err := sql.Open("sqlite3", tempFilename) 89 | if err != nil { 90 | t.Fatal("Failed to open database:", err) 91 | } 92 | defer db.Close() 93 | 94 | _, err = db.Exec("DROP TABLE foo") 95 | _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts4(tokenize=unicode61, id INTEGER PRIMARY KEY, value TEXT)") 96 | switch { 97 | case err != nil && err.Error() == "unknown tokenizer: unicode61": 98 | t.Skip("FTS4 not supported") 99 | case err != nil: 100 | t.Fatal("Failed to create table:", err) 101 | } 102 | 103 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `février`) 104 | if err != nil { 105 | t.Fatal("Failed to insert value:", err) 106 | } 107 | 108 | rows, err := db.Query("SELECT value FROM foo WHERE value MATCH 'fevrier'") 109 | if err != nil { 110 | t.Fatal("Unable to query foo table:", err) 111 | } 112 | defer rows.Close() 113 | 114 | var value string 115 | if !rows.Next() { 116 | t.Fatal("Result should be only one") 117 | } 118 | 119 | if err := rows.Scan(&value); err != nil { 120 | t.Fatal("Unable to scan results:", err) 121 | } 122 | 123 | if value != `février` { 124 | t.Fatal("Value should be `février`, but:", value) 125 | } 126 | 127 | if rows.Next() { 128 | t.Fatal("Result should be only one") 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /sqlite3_opt_fts5.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_fts5 fts5 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS5 12 | #cgo LDFLAGS: -lm 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /sqlite3_opt_icu.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_icu icu 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo LDFLAGS: -licui18n -licuuc -licudata -lm -lpthread -lstdc++ 12 | #cgo CFLAGS: -DSQLITE_ENABLE_ICU -DU_STATIC_IMPLEMENTATION 13 | #cgo darwin CFLAGS: -I/usr/local/opt/icu4c/include 14 | #cgo darwin LDFLAGS: -L/usr/local/opt/icu4c/lib 15 | #cgo openbsd LDFLAGS: -lsqlite3 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /sqlite3_opt_introspect.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_introspect 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_json1.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_json sqlite_json1 json1 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_ENABLE_JSON1 12 | */ 13 | import "C" 14 | -------------------------------------------------------------------------------- /sqlite3_opt_secure_delete.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_secure_delete 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_secure_delete_fast.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_secure_delete_fast 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_stat4.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_stat4 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_STAT4 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 7 | #include 8 | #include 9 | 10 | extern int unlock_notify_wait(sqlite3 *db); 11 | 12 | int 13 | _sqlite3_step_blocking(sqlite3_stmt *stmt) 14 | { 15 | int rv; 16 | sqlite3* db; 17 | 18 | db = sqlite3_db_handle(stmt); 19 | for (;;) { 20 | rv = sqlite3_step(stmt); 21 | if (rv != SQLITE_LOCKED) { 22 | break; 23 | } 24 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 25 | break; 26 | } 27 | rv = unlock_notify_wait(db); 28 | if (rv != SQLITE_OK) { 29 | break; 30 | } 31 | sqlite3_reset(stmt); 32 | } 33 | 34 | return rv; 35 | } 36 | 37 | int 38 | _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes) 39 | { 40 | int rv; 41 | sqlite3* db; 42 | 43 | db = sqlite3_db_handle(stmt); 44 | for (;;) { 45 | rv = sqlite3_step(stmt); 46 | if (rv!=SQLITE_LOCKED) { 47 | break; 48 | } 49 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 50 | break; 51 | } 52 | rv = unlock_notify_wait(db); 53 | if (rv != SQLITE_OK) { 54 | break; 55 | } 56 | sqlite3_reset(stmt); 57 | } 58 | 59 | *rowid = (long long) sqlite3_last_insert_rowid(db); 60 | *changes = (long long) sqlite3_changes(db); 61 | return rv; 62 | } 63 | 64 | int 65 | _sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail) 66 | { 67 | int rv; 68 | 69 | for (;;) { 70 | rv = sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail); 71 | if (rv!=SQLITE_LOCKED) { 72 | break; 73 | } 74 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 75 | break; 76 | } 77 | rv = unlock_notify_wait(db); 78 | if (rv != SQLITE_OK) { 79 | break; 80 | } 81 | } 82 | 83 | return rv; 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | // +build sqlite_unlock_notify 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY 13 | 14 | #include 15 | #include 16 | 17 | extern void unlock_notify_callback(void *arg, int argc); 18 | */ 19 | import "C" 20 | import ( 21 | "fmt" 22 | "math" 23 | "sync" 24 | "unsafe" 25 | ) 26 | 27 | type unlock_notify_table struct { 28 | sync.Mutex 29 | seqnum uint 30 | table map[uint]chan struct{} 31 | } 32 | 33 | var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})} 34 | 35 | func (t *unlock_notify_table) add(c chan struct{}) uint { 36 | t.Lock() 37 | defer t.Unlock() 38 | h := t.seqnum 39 | t.table[h] = c 40 | t.seqnum++ 41 | return h 42 | } 43 | 44 | func (t *unlock_notify_table) remove(h uint) { 45 | t.Lock() 46 | defer t.Unlock() 47 | delete(t.table, h) 48 | } 49 | 50 | func (t *unlock_notify_table) get(h uint) chan struct{} { 51 | t.Lock() 52 | defer t.Unlock() 53 | c, ok := t.table[h] 54 | if !ok { 55 | panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h)) 56 | } 57 | return c 58 | } 59 | 60 | //export unlock_notify_callback 61 | func unlock_notify_callback(argv unsafe.Pointer, argc C.int) { 62 | for i := 0; i < int(argc); i++ { 63 | parg := ((*(*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.uint)(nil))]*[1]uint)(argv))[i]) 64 | arg := *parg 65 | h := arg[0] 66 | c := unt.get(h) 67 | c <- struct{}{} 68 | } 69 | } 70 | 71 | //export unlock_notify_wait 72 | func unlock_notify_wait(db *C.sqlite3) C.int { 73 | // It has to be a bufferred channel to not block in sqlite_unlock_notify 74 | // as sqlite_unlock_notify could invoke the callback before it returns. 75 | c := make(chan struct{}, 1) 76 | defer close(c) 77 | 78 | h := unt.add(c) 79 | defer unt.remove(h) 80 | 81 | pargv := C.malloc(C.sizeof_uint) 82 | defer C.free(pargv) 83 | 84 | argv := (*[1]uint)(pargv) 85 | argv[0] = h 86 | if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK { 87 | return rv 88 | } 89 | 90 | <-c 91 | 92 | return C.SQLITE_OK 93 | } 94 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_unlock_notify 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "fmt" 13 | "os" 14 | "sync" 15 | "testing" 16 | "time" 17 | ) 18 | 19 | func TestUnlockNotify(t *testing.T) { 20 | tempFilename := TempFilename(t) 21 | defer os.Remove(tempFilename) 22 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 23 | db, err := sql.Open("sqlite3", dsn) 24 | if err != nil { 25 | t.Fatal("Failed to open database:", err) 26 | } 27 | defer db.Close() 28 | 29 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 30 | if err != nil { 31 | t.Fatal("Failed to create table:", err) 32 | } 33 | 34 | tx, err := db.Begin() 35 | if err != nil { 36 | t.Fatal("Failed to begin transaction:", err) 37 | } 38 | 39 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 40 | if err != nil { 41 | t.Fatal("Failed to insert null:", err) 42 | } 43 | 44 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 45 | if err != nil { 46 | t.Fatal("Failed to update table:", err) 47 | } 48 | 49 | wg := sync.WaitGroup{} 50 | wg.Add(1) 51 | timer := time.NewTimer(500 * time.Millisecond) 52 | go func() { 53 | <-timer.C 54 | err := tx.Commit() 55 | if err != nil { 56 | t.Fatal("Failed to commit transaction:", err) 57 | } 58 | wg.Done() 59 | }() 60 | 61 | rows, err := db.Query("SELECT count(*) from foo") 62 | if err != nil { 63 | t.Fatal("Unable to query foo table:", err) 64 | } 65 | 66 | if rows.Next() { 67 | var count int 68 | if err := rows.Scan(&count); err != nil { 69 | t.Fatal("Failed to Scan rows", err) 70 | } 71 | } 72 | if err := rows.Err(); err != nil { 73 | t.Fatal("Failed at the call to Next:", err) 74 | } 75 | wg.Wait() 76 | 77 | } 78 | 79 | func TestUnlockNotifyMany(t *testing.T) { 80 | tempFilename := TempFilename(t) 81 | defer os.Remove(tempFilename) 82 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 83 | db, err := sql.Open("sqlite3", dsn) 84 | if err != nil { 85 | t.Fatal("Failed to open database:", err) 86 | } 87 | defer db.Close() 88 | 89 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 90 | if err != nil { 91 | t.Fatal("Failed to create table:", err) 92 | } 93 | 94 | tx, err := db.Begin() 95 | if err != nil { 96 | t.Fatal("Failed to begin transaction:", err) 97 | } 98 | 99 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 100 | if err != nil { 101 | t.Fatal("Failed to insert null:", err) 102 | } 103 | 104 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 105 | if err != nil { 106 | t.Fatal("Failed to update table:", err) 107 | } 108 | 109 | wg := sync.WaitGroup{} 110 | wg.Add(1) 111 | timer := time.NewTimer(500 * time.Millisecond) 112 | go func() { 113 | <-timer.C 114 | err := tx.Commit() 115 | if err != nil { 116 | t.Fatal("Failed to commit transaction:", err) 117 | } 118 | wg.Done() 119 | }() 120 | 121 | const concurrentQueries = 1000 122 | wg.Add(concurrentQueries) 123 | for i := 0; i < concurrentQueries; i++ { 124 | go func() { 125 | rows, err := db.Query("SELECT count(*) from foo") 126 | if err != nil { 127 | t.Fatal("Unable to query foo table:", err) 128 | } 129 | 130 | if rows.Next() { 131 | var count int 132 | if err := rows.Scan(&count); err != nil { 133 | t.Fatal("Failed to Scan rows", err) 134 | } 135 | } 136 | if err := rows.Err(); err != nil { 137 | t.Fatal("Failed at the call to Next:", err) 138 | } 139 | wg.Done() 140 | }() 141 | } 142 | wg.Wait() 143 | } 144 | 145 | func TestUnlockNotifyDeadlock(t *testing.T) { 146 | tempFilename := TempFilename(t) 147 | defer os.Remove(tempFilename) 148 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 149 | db, err := sql.Open("sqlite3", dsn) 150 | if err != nil { 151 | t.Fatal("Failed to open database:", err) 152 | } 153 | defer db.Close() 154 | 155 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 156 | if err != nil { 157 | t.Fatal("Failed to create table:", err) 158 | } 159 | 160 | tx, err := db.Begin() 161 | if err != nil { 162 | t.Fatal("Failed to begin transaction:", err) 163 | } 164 | 165 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 166 | if err != nil { 167 | t.Fatal("Failed to insert null:", err) 168 | } 169 | 170 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 171 | if err != nil { 172 | t.Fatal("Failed to update table:", err) 173 | } 174 | 175 | wg := sync.WaitGroup{} 176 | wg.Add(1) 177 | timer := time.NewTimer(500 * time.Millisecond) 178 | go func() { 179 | <-timer.C 180 | err := tx.Commit() 181 | if err != nil { 182 | t.Fatal("Failed to commit transaction:", err) 183 | } 184 | wg.Done() 185 | }() 186 | 187 | wg.Add(1) 188 | go func() { 189 | tx2, err := db.Begin() 190 | if err != nil { 191 | t.Fatal("Failed to begin transaction:", err) 192 | } 193 | defer tx2.Rollback() 194 | 195 | _, err = tx2.Exec("DELETE FROM foo") 196 | if err != nil { 197 | t.Fatal("Failed to delete table:", err) 198 | } 199 | err = tx2.Commit() 200 | if err != nil { 201 | t.Fatal("Failed to commit transaction:", err) 202 | } 203 | wg.Done() 204 | }() 205 | 206 | rows, err := tx.Query("SELECT count(*) from foo") 207 | if err != nil { 208 | t.Fatal("Unable to query foo table:", err) 209 | } 210 | 211 | if rows.Next() { 212 | var count int 213 | if err := rows.Scan(&count); err != nil { 214 | t.Fatal("Failed to Scan rows", err) 215 | } 216 | } 217 | if err := rows.Err(); err != nil { 218 | t.Fatal("Failed at the call to Next:", err) 219 | } 220 | 221 | wg.Wait() 222 | } 223 | -------------------------------------------------------------------------------- /sqlite3_opt_userauth.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_userauth 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION 12 | #cgo LDFLAGS: -lm 13 | #ifndef USE_LIBSQLITE3 14 | #include 15 | #else 16 | #include 17 | #endif 18 | #include 19 | 20 | static int 21 | _sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW) 22 | { 23 | return sqlite3_user_authenticate(db, zUsername, aPW, nPW); 24 | } 25 | 26 | static int 27 | _sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) 28 | { 29 | return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin); 30 | } 31 | 32 | static int 33 | _sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) 34 | { 35 | return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin); 36 | } 37 | 38 | static int 39 | _sqlite3_user_delete(sqlite3* db, const char* zUsername) 40 | { 41 | return sqlite3_user_delete(db, zUsername); 42 | } 43 | 44 | static int 45 | _sqlite3_auth_enabled(sqlite3* db) 46 | { 47 | int exists = -1; 48 | 49 | sqlite3_stmt *stmt; 50 | sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL); 51 | 52 | while ( sqlite3_step(stmt) == SQLITE_ROW) { 53 | exists = sqlite3_column_int(stmt, 0); 54 | } 55 | 56 | sqlite3_finalize(stmt); 57 | 58 | return exists; 59 | } 60 | */ 61 | import "C" 62 | import ( 63 | "errors" 64 | "unsafe" 65 | ) 66 | 67 | const ( 68 | SQLITE_AUTH = C.SQLITE_AUTH 69 | ) 70 | 71 | var ( 72 | ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized") 73 | ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required") 74 | ) 75 | 76 | // Authenticate will perform an authentication of the provided username 77 | // and password against the database. 78 | // 79 | // If a database contains the SQLITE_USER table, then the 80 | // call to Authenticate must be invoked with an 81 | // appropriate username and password prior to enable read and write 82 | //access to the database. 83 | // 84 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password 85 | // combination is incorrect or unknown. 86 | // 87 | // If the SQLITE_USER table is not present in the database file, then 88 | // this interface is a harmless no-op returnning SQLITE_OK. 89 | func (c *SQLiteConn) Authenticate(username, password string) error { 90 | rv := c.authenticate(username, password) 91 | switch rv { 92 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 93 | return ErrUnauthorized 94 | case C.SQLITE_OK: 95 | return nil 96 | default: 97 | return c.lastError() 98 | } 99 | } 100 | 101 | // authenticate provides the actual authentication to SQLite. 102 | // This is not exported for usage in Go. 103 | // It is however exported for usage within SQL by the user. 104 | // 105 | // Returns: 106 | // C.SQLITE_OK (0) 107 | // C.SQLITE_ERROR (1) 108 | // C.SQLITE_AUTH (23) 109 | func (c *SQLiteConn) authenticate(username, password string) int { 110 | // Allocate C Variables 111 | cuser := C.CString(username) 112 | cpass := C.CString(password) 113 | 114 | // Free C Variables 115 | defer func() { 116 | C.free(unsafe.Pointer(cuser)) 117 | C.free(unsafe.Pointer(cpass)) 118 | }() 119 | 120 | return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))) 121 | } 122 | 123 | // AuthUserAdd can be used (by an admin user only) 124 | // to create a new user. When called on a no-authentication-required 125 | // database, this routine converts the database into an authentication- 126 | // required database, automatically makes the added user an 127 | // administrator, and logs in the current connection as that user. 128 | // The AuthUserAdd only works for the "main" database, not 129 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a 130 | // non-admin user results in an error. 131 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { 132 | isAdmin := 0 133 | if admin { 134 | isAdmin = 1 135 | } 136 | 137 | rv := c.authUserAdd(username, password, isAdmin) 138 | switch rv { 139 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 140 | return ErrAdminRequired 141 | case C.SQLITE_OK: 142 | return nil 143 | default: 144 | return c.lastError() 145 | } 146 | } 147 | 148 | // authUserAdd enables the User Authentication if not enabled. 149 | // Otherwise it will add a user. 150 | // 151 | // When user authentication is already enabled then this function 152 | // can only be called by an admin. 153 | // 154 | // This is not exported for usage in Go. 155 | // It is however exported for usage within SQL by the user. 156 | // 157 | // Returns: 158 | // C.SQLITE_OK (0) 159 | // C.SQLITE_ERROR (1) 160 | // C.SQLITE_AUTH (23) 161 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { 162 | // Allocate C Variables 163 | cuser := C.CString(username) 164 | cpass := C.CString(password) 165 | 166 | // Free C Variables 167 | defer func() { 168 | C.free(unsafe.Pointer(cuser)) 169 | C.free(unsafe.Pointer(cpass)) 170 | }() 171 | 172 | return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) 173 | } 174 | 175 | // AuthUserChange can be used to change a users 176 | // login credentials or admin privilege. Any user can change their own 177 | // login credentials. Only an admin user can change another users login 178 | // credentials or admin privilege setting. No user may change their own 179 | // admin privilege setting. 180 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { 181 | isAdmin := 0 182 | if admin { 183 | isAdmin = 1 184 | } 185 | 186 | rv := c.authUserChange(username, password, isAdmin) 187 | switch rv { 188 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 189 | return ErrAdminRequired 190 | case C.SQLITE_OK: 191 | return nil 192 | default: 193 | return c.lastError() 194 | } 195 | } 196 | 197 | // authUserChange allows to modify a user. 198 | // Users can change their own password. 199 | // 200 | // Only admins can change passwords for other users 201 | // and modify the admin flag. 202 | // 203 | // The admin flag of the current logged in user cannot be changed. 204 | // THis ensures that their is always an admin. 205 | // 206 | // This is not exported for usage in Go. 207 | // It is however exported for usage within SQL by the user. 208 | // 209 | // Returns: 210 | // C.SQLITE_OK (0) 211 | // C.SQLITE_ERROR (1) 212 | // C.SQLITE_AUTH (23) 213 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int { 214 | // Allocate C Variables 215 | cuser := C.CString(username) 216 | cpass := C.CString(password) 217 | 218 | // Free C Variables 219 | defer func() { 220 | C.free(unsafe.Pointer(cuser)) 221 | C.free(unsafe.Pointer(cpass)) 222 | }() 223 | 224 | return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) 225 | } 226 | 227 | // AuthUserDelete can be used (by an admin user only) 228 | // to delete a user. The currently logged-in user cannot be deleted, 229 | // which guarantees that there is always an admin user and hence that 230 | // the database cannot be converted into a no-authentication-required 231 | // database. 232 | func (c *SQLiteConn) AuthUserDelete(username string) error { 233 | rv := c.authUserDelete(username) 234 | switch rv { 235 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 236 | return ErrAdminRequired 237 | case C.SQLITE_OK: 238 | return nil 239 | default: 240 | return c.lastError() 241 | } 242 | } 243 | 244 | // authUserDelete can be used to delete a user. 245 | // 246 | // This function can only be executed by an admin. 247 | // 248 | // This is not exported for usage in Go. 249 | // It is however exported for usage within SQL by the user. 250 | // 251 | // Returns: 252 | // C.SQLITE_OK (0) 253 | // C.SQLITE_ERROR (1) 254 | // C.SQLITE_AUTH (23) 255 | func (c *SQLiteConn) authUserDelete(username string) int { 256 | // Allocate C Variables 257 | cuser := C.CString(username) 258 | 259 | // Free C Variables 260 | defer func() { 261 | C.free(unsafe.Pointer(cuser)) 262 | }() 263 | 264 | return int(C._sqlite3_user_delete(c.db, cuser)) 265 | } 266 | 267 | // AuthEnabled checks if the database is protected by user authentication 268 | func (c *SQLiteConn) AuthEnabled() (exists bool) { 269 | rv := c.authEnabled() 270 | if rv == 1 { 271 | exists = true 272 | } 273 | 274 | return 275 | } 276 | 277 | // authEnabled perform the actual check for user authentication. 278 | // 279 | // This is not exported for usage in Go. 280 | // It is however exported for usage within SQL by the user. 281 | // 282 | // Returns: 283 | // 0 - Disabled 284 | // 1 - Enabled 285 | func (c *SQLiteConn) authEnabled() int { 286 | return int(C._sqlite3_auth_enabled(c.db)) 287 | } 288 | 289 | // EOF 290 | -------------------------------------------------------------------------------- /sqlite3_opt_userauth_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !sqlite_userauth 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "C" 12 | ) 13 | 14 | // Authenticate will perform an authentication of the provided username 15 | // and password against the database. 16 | // 17 | // If a database contains the SQLITE_USER table, then the 18 | // call to Authenticate must be invoked with an 19 | // appropriate username and password prior to enable read and write 20 | //access to the database. 21 | // 22 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password 23 | // combination is incorrect or unknown. 24 | // 25 | // If the SQLITE_USER table is not present in the database file, then 26 | // this interface is a harmless no-op returnning SQLITE_OK. 27 | func (c *SQLiteConn) Authenticate(username, password string) error { 28 | // NOOP 29 | return nil 30 | } 31 | 32 | // authenticate provides the actual authentication to SQLite. 33 | // This is not exported for usage in Go. 34 | // It is however exported for usage within SQL by the user. 35 | // 36 | // Returns: 37 | // C.SQLITE_OK (0) 38 | // C.SQLITE_ERROR (1) 39 | // C.SQLITE_AUTH (23) 40 | func (c *SQLiteConn) authenticate(username, password string) int { 41 | // NOOP 42 | return 0 43 | } 44 | 45 | // AuthUserAdd can be used (by an admin user only) 46 | // to create a new user. When called on a no-authentication-required 47 | // database, this routine converts the database into an authentication- 48 | // required database, automatically makes the added user an 49 | // administrator, and logs in the current connection as that user. 50 | // The AuthUserAdd only works for the "main" database, not 51 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a 52 | // non-admin user results in an error. 53 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { 54 | // NOOP 55 | return nil 56 | } 57 | 58 | // authUserAdd enables the User Authentication if not enabled. 59 | // Otherwise it will add a user. 60 | // 61 | // When user authentication is already enabled then this function 62 | // can only be called by an admin. 63 | // 64 | // This is not exported for usage in Go. 65 | // It is however exported for usage within SQL by the user. 66 | // 67 | // Returns: 68 | // C.SQLITE_OK (0) 69 | // C.SQLITE_ERROR (1) 70 | // C.SQLITE_AUTH (23) 71 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { 72 | // NOOP 73 | return 0 74 | } 75 | 76 | // AuthUserChange can be used to change a users 77 | // login credentials or admin privilege. Any user can change their own 78 | // login credentials. Only an admin user can change another users login 79 | // credentials or admin privilege setting. No user may change their own 80 | // admin privilege setting. 81 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { 82 | // NOOP 83 | return nil 84 | } 85 | 86 | // authUserChange allows to modify a user. 87 | // Users can change their own password. 88 | // 89 | // Only admins can change passwords for other users 90 | // and modify the admin flag. 91 | // 92 | // The admin flag of the current logged in user cannot be changed. 93 | // THis ensures that their is always an admin. 94 | // 95 | // This is not exported for usage in Go. 96 | // It is however exported for usage within SQL by the user. 97 | // 98 | // Returns: 99 | // C.SQLITE_OK (0) 100 | // C.SQLITE_ERROR (1) 101 | // C.SQLITE_AUTH (23) 102 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int { 103 | // NOOP 104 | return 0 105 | } 106 | 107 | // AuthUserDelete can be used (by an admin user only) 108 | // to delete a user. The currently logged-in user cannot be deleted, 109 | // which guarantees that there is always an admin user and hence that 110 | // the database cannot be converted into a no-authentication-required 111 | // database. 112 | func (c *SQLiteConn) AuthUserDelete(username string) error { 113 | // NOOP 114 | return nil 115 | } 116 | 117 | // authUserDelete can be used to delete a user. 118 | // 119 | // This function can only be executed by an admin. 120 | // 121 | // This is not exported for usage in Go. 122 | // It is however exported for usage within SQL by the user. 123 | // 124 | // Returns: 125 | // C.SQLITE_OK (0) 126 | // C.SQLITE_ERROR (1) 127 | // C.SQLITE_AUTH (23) 128 | func (c *SQLiteConn) authUserDelete(username string) int { 129 | // NOOP 130 | return 0 131 | } 132 | 133 | // AuthEnabled checks if the database is protected by user authentication 134 | func (c *SQLiteConn) AuthEnabled() (exists bool) { 135 | // NOOP 136 | return false 137 | } 138 | 139 | // authEnabled perform the actual check for user authentication. 140 | // 141 | // This is not exported for usage in Go. 142 | // It is however exported for usage within SQL by the user. 143 | // 144 | // Returns: 145 | // 0 - Disabled 146 | // 1 - Enabled 147 | func (c *SQLiteConn) authEnabled() int { 148 | // NOOP 149 | return 0 150 | } 151 | 152 | // EOF 153 | -------------------------------------------------------------------------------- /sqlite3_opt_vacuum_full.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_vacuum_full 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_vacuum_incr.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_vacuum_incr 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_other.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !windows 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -I. 12 | #cgo linux LDFLAGS: -ldl 13 | #cgo linux,ppc LDFLAGS: -lpthread 14 | #cgo linux,ppc64 LDFLAGS: -lpthread 15 | #cgo linux,ppc64le LDFLAGS: -lpthread 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /sqlite3_solaris.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build solaris 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -D__EXTENSIONS__=1 12 | #cgo LDFLAGS: -lc 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /sqlite3_type.go: -------------------------------------------------------------------------------- 1 | package sqlite3 2 | 3 | /* 4 | #ifndef USE_LIBSQLITE3 5 | #include 6 | #else 7 | #include 8 | #endif 9 | */ 10 | import "C" 11 | import ( 12 | "reflect" 13 | "time" 14 | ) 15 | 16 | // ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName. 17 | func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string { 18 | return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))) 19 | } 20 | 21 | /* 22 | func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) { 23 | return 0, false 24 | } 25 | 26 | func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) { 27 | return 0, 0, false 28 | } 29 | */ 30 | 31 | // ColumnTypeNullable implement RowsColumnTypeNullable. 32 | func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) { 33 | return true, true 34 | } 35 | 36 | // ColumnTypeScanType implement RowsColumnTypeScanType. 37 | func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type { 38 | switch C.sqlite3_column_type(rc.s.s, C.int(i)) { 39 | case C.SQLITE_INTEGER: 40 | switch C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))) { 41 | case "timestamp", "datetime", "date": 42 | return reflect.TypeOf(time.Time{}) 43 | case "boolean": 44 | return reflect.TypeOf(false) 45 | } 46 | return reflect.TypeOf(int64(0)) 47 | case C.SQLITE_FLOAT: 48 | return reflect.TypeOf(float64(0)) 49 | case C.SQLITE_BLOB: 50 | return reflect.SliceOf(reflect.TypeOf(byte(0))) 51 | case C.SQLITE_NULL: 52 | return reflect.TypeOf(nil) 53 | case C.SQLITE_TEXT: 54 | return reflect.TypeOf("") 55 | } 56 | return reflect.SliceOf(reflect.TypeOf(byte(0))) 57 | } 58 | -------------------------------------------------------------------------------- /sqlite3_usleep_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | 8 | package sqlite3 9 | 10 | // usleep is a function available on *nix based systems. 11 | // This function is not present in Windows. 12 | // Windows has a sleep function but this works with seconds 13 | // and not with microseconds as usleep. 14 | // 15 | // This code should improve performance on windows because 16 | // without the presence of usleep SQLite waits 1 second. 17 | // 18 | // Source: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa 19 | 20 | /* 21 | #include 22 | 23 | void usleep(__int64 usec) 24 | { 25 | HANDLE timer; 26 | LARGE_INTEGER ft; 27 | 28 | // Convert to 100 nanosecond interval, negative value indicates relative time 29 | ft.QuadPart = -(10*usec); 30 | 31 | timer = CreateWaitableTimer(NULL, TRUE, NULL); 32 | SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); 33 | WaitForSingleObject(timer, INFINITE); 34 | CloseHandle(timer); 35 | } 36 | */ 37 | import "C" 38 | 39 | // EOF 40 | -------------------------------------------------------------------------------- /sqlite3_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -I. 12 | #cgo CFLAGS: -fno-stack-check 13 | #cgo CFLAGS: -fno-stack-protector 14 | #cgo CFLAGS: -mno-stack-arg-probe 15 | #cgo LDFLAGS: -lmingwex -lmingw32 16 | #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T 17 | */ 18 | import "C" 19 | -------------------------------------------------------------------------------- /static_mock.go: -------------------------------------------------------------------------------- 1 | // +build !cgo 2 | 3 | package sqlite3 4 | 5 | import ( 6 | "database/sql" 7 | "database/sql/driver" 8 | "errors" 9 | ) 10 | 11 | func init() { 12 | sql.Register("sqlite3", &SQLiteDriverMock{}) 13 | } 14 | 15 | type SQLiteDriverMock struct{} 16 | 17 | var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub") 18 | 19 | func (SQLiteDriverMock) Open(s string) (driver.Conn, error) { 20 | return nil, errorMsg 21 | } 22 | -------------------------------------------------------------------------------- /tomcrypt.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | #ifndef TOMCRYPT_H_ 11 | #define TOMCRYPT_H_ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* use configuration data */ 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* version */ 29 | #define CRYPT 0x0118 30 | #define SCRYPT "1.18.2-develop" 31 | 32 | /* max size of either a cipher/hash block or symmetric key [largest of the two] */ 33 | #define MAXBLOCKSIZE 144 34 | 35 | #ifndef TAB_SIZE 36 | /* descriptor table size */ 37 | #define TAB_SIZE 34 38 | #endif 39 | 40 | /* error codes [will be expanded in future releases] */ 41 | enum { 42 | CRYPT_OK=0, /* Result OK */ 43 | CRYPT_ERROR, /* Generic Error */ 44 | CRYPT_NOP, /* Not a failure but no operation was performed */ 45 | 46 | CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ 47 | CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ 48 | CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ 49 | 50 | CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ 51 | CRYPT_INVALID_PACKET, /* Invalid input packet given */ 52 | 53 | CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ 54 | CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ 55 | 56 | CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ 57 | CRYPT_INVALID_HASH, /* Invalid hash specified */ 58 | CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ 59 | 60 | CRYPT_MEM, /* Out of memory */ 61 | 62 | CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ 63 | CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ 64 | 65 | CRYPT_INVALID_ARG, /* Generic invalid argument */ 66 | CRYPT_FILE_NOTFOUND, /* File Not Found */ 67 | 68 | CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ 69 | 70 | CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ 71 | 72 | CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ 73 | 74 | CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ 75 | 76 | CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ 77 | 78 | CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ 79 | CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ 80 | 81 | CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ 82 | }; 83 | 84 | #include 85 | #include 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif /* TOMCRYPT_H_ */ 101 | 102 | 103 | /* ref: $Format:%D$ */ 104 | /* git commit: $Format:%H$ */ 105 | /* commit time: $Format:%ai$ */ 106 | -------------------------------------------------------------------------------- /tomcrypt_argchk.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* Defines the LTC_ARGCHK macro used within the library */ 11 | /* ARGTYPE is defined in tomcrypt_cfg.h */ 12 | #if ARGTYPE == 0 13 | 14 | #include 15 | 16 | /* this is the default LibTomCrypt macro */ 17 | #if defined(__clang__) || defined(__GNUC_MINOR__) 18 | #define NORETURN __attribute__ ((noreturn)) 19 | #else 20 | #define NORETURN 21 | #endif 22 | 23 | void crypt_argchk(const char *v, const char *s, int d) NORETURN; 24 | #define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) 25 | #define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) 26 | 27 | #elif ARGTYPE == 1 28 | 29 | /* fatal type of error */ 30 | #define LTC_ARGCHK(x) assert((x)) 31 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 32 | 33 | #elif ARGTYPE == 2 34 | 35 | #define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } 36 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 37 | 38 | #elif ARGTYPE == 3 39 | 40 | #define LTC_ARGCHK(x) 41 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 42 | 43 | #elif ARGTYPE == 4 44 | 45 | #define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; 46 | #define LTC_ARGCHKVD(x) if (!(x)) return; 47 | 48 | #endif 49 | 50 | 51 | /* ref: $Format:%D$ */ 52 | /* git commit: $Format:%H$ */ 53 | /* commit time: $Format:%ai$ */ 54 | -------------------------------------------------------------------------------- /tomcrypt_misc.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* ---- LTC_BASE64 Routines ---- */ 11 | #ifdef LTC_BASE64 12 | int base64_encode(const unsigned char *in, unsigned long inlen, 13 | char *out, unsigned long *outlen); 14 | 15 | int base64_decode(const char *in, unsigned long inlen, 16 | unsigned char *out, unsigned long *outlen); 17 | int base64_strict_decode(const char *in, unsigned long inlen, 18 | unsigned char *out, unsigned long *outlen); 19 | int base64_sane_decode(const char *in, unsigned long inlen, 20 | unsigned char *out, unsigned long *outlen); 21 | #endif 22 | 23 | #ifdef LTC_BASE64_URL 24 | int base64url_encode(const unsigned char *in, unsigned long inlen, 25 | char *out, unsigned long *outlen); 26 | int base64url_strict_encode(const unsigned char *in, unsigned long inlen, 27 | char *out, unsigned long *outlen); 28 | 29 | int base64url_decode(const char *in, unsigned long inlen, 30 | unsigned char *out, unsigned long *outlen); 31 | int base64url_strict_decode(const char *in, unsigned long inlen, 32 | unsigned char *out, unsigned long *outlen); 33 | int base64url_sane_decode(const char *in, unsigned long inlen, 34 | unsigned char *out, unsigned long *outlen); 35 | #endif 36 | 37 | /* ---- BASE32 Routines ---- */ 38 | #ifdef LTC_BASE32 39 | typedef enum { 40 | BASE32_RFC4648 = 0, 41 | BASE32_BASE32HEX = 1, 42 | BASE32_ZBASE32 = 2, 43 | BASE32_CROCKFORD = 3 44 | } base32_alphabet; 45 | int base32_encode(const unsigned char *in, unsigned long inlen, 46 | char *out, unsigned long *outlen, 47 | base32_alphabet id); 48 | int base32_decode(const char *in, unsigned long inlen, 49 | unsigned char *out, unsigned long *outlen, 50 | base32_alphabet id); 51 | #endif 52 | 53 | /* ---- BASE16 Routines ---- */ 54 | #ifdef LTC_BASE16 55 | int base16_encode(const unsigned char *in, unsigned long inlen, 56 | char *out, unsigned long *outlen, 57 | unsigned int options); 58 | int base16_decode(const char *in, unsigned long inlen, 59 | unsigned char *out, unsigned long *outlen); 60 | #endif 61 | 62 | /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ 63 | #ifdef LTC_HKDF 64 | 65 | int hkdf_test(void); 66 | 67 | int hkdf_extract(int hash_idx, 68 | const unsigned char *salt, unsigned long saltlen, 69 | const unsigned char *in, unsigned long inlen, 70 | unsigned char *out, unsigned long *outlen); 71 | 72 | int hkdf_expand(int hash_idx, 73 | const unsigned char *info, unsigned long infolen, 74 | const unsigned char *in, unsigned long inlen, 75 | unsigned char *out, unsigned long outlen); 76 | 77 | int hkdf(int hash_idx, 78 | const unsigned char *salt, unsigned long saltlen, 79 | const unsigned char *info, unsigned long infolen, 80 | const unsigned char *in, unsigned long inlen, 81 | unsigned char *out, unsigned long outlen); 82 | 83 | #endif /* LTC_HKDF */ 84 | 85 | /* ---- MEM routines ---- */ 86 | int mem_neq(const void *a, const void *b, size_t len); 87 | void zeromem(volatile void *out, size_t outlen); 88 | void burn_stack(unsigned long len); 89 | 90 | const char *error_to_string(int err); 91 | 92 | extern const char *crypt_build_settings; 93 | 94 | /* ---- HMM ---- */ 95 | int crypt_fsa(void *mp, ...); 96 | 97 | /* ---- Dynamic language support ---- */ 98 | int crypt_get_constant(const char* namein, int *valueout); 99 | int crypt_list_all_constants(char *names_list, unsigned int *names_list_size); 100 | 101 | int crypt_get_size(const char* namein, unsigned int *sizeout); 102 | int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size); 103 | 104 | #ifdef LTM_DESC 105 | LTC_DEPRECATED void init_LTM(void); 106 | #endif 107 | #ifdef TFM_DESC 108 | LTC_DEPRECATED void init_TFM(void); 109 | #endif 110 | #ifdef GMP_DESC 111 | LTC_DEPRECATED void init_GMP(void); 112 | #endif 113 | int crypt_mp_init(const char* mpi); 114 | 115 | #ifdef LTC_ADLER32 116 | typedef struct adler32_state_s 117 | { 118 | unsigned short s[2]; 119 | } adler32_state; 120 | 121 | void adler32_init(adler32_state *ctx); 122 | void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); 123 | void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size); 124 | int adler32_test(void); 125 | #endif 126 | 127 | #ifdef LTC_CRC32 128 | typedef struct crc32_state_s 129 | { 130 | ulong32 crc; 131 | } crc32_state; 132 | 133 | void crc32_init(crc32_state *ctx); 134 | void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length); 135 | void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size); 136 | int crc32_test(void); 137 | #endif 138 | 139 | 140 | #ifdef LTC_PADDING 141 | 142 | enum padding_type { 143 | LTC_PAD_PKCS7 = 0x0000U, 144 | #ifdef LTC_RNG_GET_BYTES 145 | LTC_PAD_ISO_10126 = 0x1000U, 146 | #endif 147 | LTC_PAD_ANSI_X923 = 0x2000U, 148 | LTC_PAD_ONE_AND_ZERO = 0x8000U, 149 | LTC_PAD_ZERO = 0x9000U, 150 | LTC_PAD_ZERO_ALWAYS = 0xA000U, 151 | }; 152 | 153 | int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode); 154 | int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode); 155 | #endif /* LTC_PADDING */ 156 | 157 | int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); 158 | 159 | /* ref: $Format:%D$ */ 160 | /* git commit: $Format:%H$ */ 161 | /* commit time: $Format:%ai$ */ 162 | -------------------------------------------------------------------------------- /tomcrypt_pkcs.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* PKCS Header Info */ 11 | 12 | /* ===> PKCS #1 -- RSA Cryptography <=== */ 13 | #ifdef LTC_PKCS_1 14 | 15 | enum ltc_pkcs_1_v1_5_blocks 16 | { 17 | LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ 18 | LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ 19 | }; 20 | 21 | enum ltc_pkcs_1_paddings 22 | { 23 | LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ 24 | LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ 25 | LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */ 26 | LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ 27 | }; 28 | 29 | int pkcs_1_mgf1( int hash_idx, 30 | const unsigned char *seed, unsigned long seedlen, 31 | unsigned char *mask, unsigned long masklen); 32 | 33 | int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); 34 | int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); 35 | 36 | /* *** v1.5 padding */ 37 | int pkcs_1_v1_5_encode(const unsigned char *msg, 38 | unsigned long msglen, 39 | int block_type, 40 | unsigned long modulus_bitlen, 41 | prng_state *prng, 42 | int prng_idx, 43 | unsigned char *out, 44 | unsigned long *outlen); 45 | 46 | int pkcs_1_v1_5_decode(const unsigned char *msg, 47 | unsigned long msglen, 48 | int block_type, 49 | unsigned long modulus_bitlen, 50 | unsigned char *out, 51 | unsigned long *outlen, 52 | int *is_valid); 53 | 54 | /* *** v2.1 padding */ 55 | int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, 56 | const unsigned char *lparam, unsigned long lparamlen, 57 | unsigned long modulus_bitlen, prng_state *prng, 58 | int prng_idx, int hash_idx, 59 | unsigned char *out, unsigned long *outlen); 60 | 61 | int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, 62 | const unsigned char *lparam, unsigned long lparamlen, 63 | unsigned long modulus_bitlen, int hash_idx, 64 | unsigned char *out, unsigned long *outlen, 65 | int *res); 66 | 67 | int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, 68 | unsigned long saltlen, prng_state *prng, 69 | int prng_idx, int hash_idx, 70 | unsigned long modulus_bitlen, 71 | unsigned char *out, unsigned long *outlen); 72 | 73 | int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, 74 | const unsigned char *sig, unsigned long siglen, 75 | unsigned long saltlen, int hash_idx, 76 | unsigned long modulus_bitlen, int *res); 77 | 78 | #endif /* LTC_PKCS_1 */ 79 | 80 | /* ===> PKCS #5 -- Password Based Cryptography <=== */ 81 | #ifdef LTC_PKCS_5 82 | 83 | /* Algorithm #1 (PBKDF1) */ 84 | int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 85 | const unsigned char *salt, 86 | int iteration_count, int hash_idx, 87 | unsigned char *out, unsigned long *outlen); 88 | 89 | /* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys. 90 | Compatible with EVP_BytesToKey() */ 91 | int pkcs_5_alg1_openssl(const unsigned char *password, 92 | unsigned long password_len, 93 | const unsigned char *salt, 94 | int iteration_count, int hash_idx, 95 | unsigned char *out, unsigned long *outlen); 96 | 97 | /* Algorithm #2 (PBKDF2) */ 98 | int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 99 | const unsigned char *salt, unsigned long salt_len, 100 | int iteration_count, int hash_idx, 101 | unsigned char *out, unsigned long *outlen); 102 | 103 | int pkcs_5_test (void); 104 | #endif /* LTC_PKCS_5 */ 105 | 106 | 107 | /* ref: $Format:%D$ */ 108 | /* git commit: $Format:%H$ */ 109 | /* commit time: $Format:%ai$ */ 110 | -------------------------------------------------------------------------------- /upgrade/package.go: -------------------------------------------------------------------------------- 1 | // Package upgrade is a dummy package to ensure package can be loaded 2 | // 3 | // This file is to avoid the following error: 4 | // can't load package: package go-sqlite3/upgrade: build constraints exclude all Go files in go-sqlite3\upgrade 5 | package upgrade 6 | -------------------------------------------------------------------------------- /upgrade/upgrade.go: -------------------------------------------------------------------------------- 1 | // +build !cgo 2 | // +build upgrade 3 | 4 | package main 5 | 6 | import ( 7 | "archive/zip" 8 | "bufio" 9 | "bytes" 10 | "fmt" 11 | "io" 12 | "io/ioutil" 13 | "log" 14 | "net/http" 15 | "os" 16 | "path" 17 | "path/filepath" 18 | "strings" 19 | "time" 20 | 21 | "github.com/PuerkitoBio/goquery" 22 | ) 23 | 24 | func download(prefix string) (url string, content []byte, err error) { 25 | year := time.Now().Year() 26 | 27 | site := "https://www.sqlite.org/download.html" 28 | //fmt.Printf("scraping %v\n", site) 29 | doc, err := goquery.NewDocument(site) 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | 34 | doc.Find("a").Each(func(_ int, s *goquery.Selection) { 35 | if strings.HasPrefix(s.Text(), prefix) { 36 | url = fmt.Sprintf("https://www.sqlite.org/%d/", year) + s.Text() 37 | } 38 | }) 39 | 40 | if url == "" { 41 | return "", nil, fmt.Errorf("Unable to find prefix '%s' on sqlite.org", prefix) 42 | } 43 | 44 | fmt.Printf("Downloading %v\n", url) 45 | resp, err := http.Get(url) 46 | if err != nil { 47 | log.Fatal(err) 48 | } 49 | 50 | // Ready Body Content 51 | content, err = ioutil.ReadAll(resp.Body) 52 | defer resp.Body.Close() 53 | if err != nil { 54 | return "", nil, err 55 | } 56 | 57 | return url, content, nil 58 | } 59 | 60 | func mergeFile(src string, dst string) error { 61 | defer func() error { 62 | fmt.Printf("Removing: %s\n", src) 63 | err := os.Remove(src) 64 | 65 | if err != nil { 66 | return err 67 | } 68 | 69 | return nil 70 | }() 71 | 72 | // Open destination 73 | fdst, err := os.OpenFile(dst, os.O_APPEND|os.O_WRONLY, 0666) 74 | if err != nil { 75 | return err 76 | } 77 | defer fdst.Close() 78 | 79 | // Read source content 80 | content, err := ioutil.ReadFile(src) 81 | if err != nil { 82 | return err 83 | } 84 | 85 | // Add Additional newline 86 | if _, err := fdst.WriteString("\n"); err != nil { 87 | return err 88 | } 89 | 90 | fmt.Printf("Merging: %s into %s\n", src, dst) 91 | if _, err = fdst.Write(content); err != nil { 92 | return err 93 | } 94 | 95 | return nil 96 | } 97 | 98 | func main() { 99 | fmt.Println("Go-SQLite3 Upgrade Tool") 100 | 101 | // Download Amalgamation 102 | _, amalgamation, err := download("sqlite-amalgamation-") 103 | if err != nil { 104 | fmt.Println("Failed to download: sqlite-amalgamation; %s", err) 105 | } 106 | 107 | // Download Source 108 | _, source, err := download("sqlite-src-") 109 | if err != nil { 110 | fmt.Println("Failed to download: sqlite-src; %s", err) 111 | } 112 | 113 | // Create Amalgamation Zip Reader 114 | rAmalgamation, err := zip.NewReader(bytes.NewReader(amalgamation), int64(len(amalgamation))) 115 | if err != nil { 116 | log.Fatal(err) 117 | } 118 | 119 | // Create Source Zip Reader 120 | rSource, err := zip.NewReader(bytes.NewReader(source), int64(len(source))) 121 | if err != nil { 122 | log.Fatal(err) 123 | } 124 | 125 | // Extract Amalgamation 126 | for _, zf := range rAmalgamation.File { 127 | var f *os.File 128 | switch path.Base(zf.Name) { 129 | case "sqlite3.c": 130 | f, err = os.Create("sqlite3-binding.c") 131 | case "sqlite3.h": 132 | f, err = os.Create("sqlite3-binding.h") 133 | case "sqlite3ext.h": 134 | f, err = os.Create("sqlite3ext.h") 135 | default: 136 | continue 137 | } 138 | if err != nil { 139 | log.Fatal(err) 140 | } 141 | zr, err := zf.Open() 142 | if err != nil { 143 | log.Fatal(err) 144 | } 145 | 146 | _, err = io.WriteString(f, "#ifndef USE_LIBSQLITE3\n") 147 | if err != nil { 148 | zr.Close() 149 | f.Close() 150 | log.Fatal(err) 151 | } 152 | scanner := bufio.NewScanner(zr) 153 | for scanner.Scan() { 154 | text := scanner.Text() 155 | if text == `#include "sqlite3.h"` { 156 | text = `#include "sqlite3-binding.h"` 157 | } 158 | _, err = fmt.Fprintln(f, text) 159 | if err != nil { 160 | break 161 | } 162 | } 163 | err = scanner.Err() 164 | if err != nil { 165 | zr.Close() 166 | f.Close() 167 | log.Fatal(err) 168 | } 169 | _, err = io.WriteString(f, "#else // USE_LIBSQLITE3\n // If users really want to link against the system sqlite3 we\n// need to make this file a noop.\n #endif") 170 | if err != nil { 171 | zr.Close() 172 | f.Close() 173 | log.Fatal(err) 174 | } 175 | zr.Close() 176 | f.Close() 177 | fmt.Printf("Extracted: %v\n", filepath.Base(f.Name())) 178 | } 179 | 180 | //Extract Source 181 | for _, zf := range rSource.File { 182 | var f *os.File 183 | switch path.Base(zf.Name) { 184 | case "userauth.c": 185 | f, err = os.Create("userauth.c") 186 | case "sqlite3userauth.h": 187 | f, err = os.Create("userauth.h") 188 | default: 189 | continue 190 | } 191 | if err != nil { 192 | log.Fatal(err) 193 | } 194 | zr, err := zf.Open() 195 | if err != nil { 196 | log.Fatal(err) 197 | } 198 | 199 | _, err = io.Copy(f, zr) 200 | if err != nil { 201 | log.Fatal(err) 202 | } 203 | 204 | zr.Close() 205 | f.Close() 206 | fmt.Printf("extracted %v\n", filepath.Base(f.Name())) 207 | } 208 | 209 | // Merge SQLite User Authentication into amalgamation 210 | if err := mergeFile("userauth.c", "sqlite3-binding.c"); err != nil { 211 | log.Fatal(err) 212 | } 213 | if err := mergeFile("userauth.h", "sqlite3-binding.h"); err != nil { 214 | log.Fatal(err) 215 | } 216 | 217 | os.Exit(0) 218 | } 219 | -------------------------------------------------------------------------------- /zeromem.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt_private.h" 10 | 11 | /** 12 | @file zeromem.c 13 | Zero a block of memory, Tom St Denis 14 | */ 15 | 16 | /** 17 | Zero a block of memory 18 | @param out The destination of the area to zero 19 | @param outlen The length of the area to zero (octets) 20 | */ 21 | void zeromem(volatile void *out, size_t outlen) 22 | { 23 | volatile char *mem = out; 24 | LTC_ARGCHKVD(out != NULL); 25 | while (outlen-- > 0) { 26 | *mem++ = '\0'; 27 | } 28 | } 29 | 30 | /* ref: $Format:%D$ */ 31 | /* git commit: $Format:%H$ */ 32 | /* commit time: $Format:%ai$ */ 33 | --------------------------------------------------------------------------------