├── .clang-format
├── .gitignore
├── Makefile
├── README.md
├── benchmark
├── README.md
├── bin
│ ├── oltp.jar
│ └── tpch.jar
├── config
│ ├── config.xml
│ ├── plugin.xml
│ ├── tpcc_config.xml
│ └── tpch_postgres.xml
├── db_schemas
│ ├── tpcc-schema.sql
│ ├── tpcc-schema_encrypted.sql
│ ├── tpch-index.sql
│ ├── tpch-schema-encrypted.sql
│ └── tpch-schema.sql
├── log4j.properties
├── patches
│ └── oltpbenchmark.patch
└── tools
│ ├── README
│ ├── dbgen
│ └── dists.dss
├── docker
├── Dockerfile
└── sgx-deps.mk
├── docs
├── developer
│ └── dirlayout.md
└── user
│ ├── README.md
│ ├── character.md
│ ├── datetime.md
│ ├── install.md
│ ├── numeric.md
│ ├── oblvs.md
│ └── utils.md
├── src
├── enclave.mk
├── enclave
│ ├── enc_float32_ops.cpp
│ ├── enc_int32_ops.cpp
│ ├── enc_oblvs_int32_ops.cpp
│ ├── enc_text_ops.cpp
│ ├── enc_timestamp_ops.cpp
│ ├── enclave.config.xml
│ ├── enclave.cpp
│ ├── enclave.edl
│ └── enclave.lds
├── include
│ ├── defs.h
│ ├── enclave
│ │ ├── Queue.hpp
│ │ ├── enc_float32_ops.hpp
│ │ ├── enc_int32_ops.hpp
│ │ ├── enc_text_ops.hpp
│ │ ├── enc_timestamp_ops.hpp
│ │ └── enclave.hpp
│ ├── tools
│ │ ├── base64.hpp
│ │ ├── bytes.hpp
│ │ ├── like_match.h
│ │ ├── oblvs_int32_ops.h
│ │ ├── sync_utils.hpp
│ │ └── timestamp.h
│ └── untrusted
│ │ ├── extensions
│ │ └── stdafx.h
│ │ └── interface
│ │ ├── interface.h
│ │ └── stdafx.h
├── tools
│ ├── Queue.cpp
│ ├── base64.cpp
│ ├── bytes.cpp
│ ├── like_match.c
│ ├── oblvs_int32_ops.S
│ ├── sync_utils.cpp
│ └── timestamp.c
├── untrusted.mk
├── untrusted
│ ├── Makefile
│ ├── extensions
│ │ ├── enc_float4.c
│ │ ├── enc_int4.c
│ │ ├── enc_text.c
│ │ ├── enc_timestamp.c
│ │ ├── encdb--0.0.1.sql
│ │ ├── encdb.c
│ │ └── encdb.control
│ └── interface
│ │ ├── enc_float32.cpp
│ │ ├── enc_int32.cpp
│ │ ├── enc_text.cpp
│ │ ├── enc_timestamp.cpp
│ │ └── interface.cpp
└── vars.mk
└── test
├── README.md
├── encdb
└── run_test.sql
└── sql
├── pgtap--0.90.0--0.91.0.sql
├── pgtap--0.91.0--0.92.0.sql
├── pgtap--0.92.0--0.93.0.sql
├── pgtap--0.93.0--0.94.0.sql
├── pgtap--0.94.0--0.95.0.sql
├── pgtap--0.95.0--0.96.0.sql
├── pgtap--unpackaged--0.91.0.sql
├── pgtap.sql
├── pgtap.sql.bak
├── pgtap.sql.in
└── setup.sql
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | AccessModifierOffset: -1
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: false
6 | AlignConsecutiveDeclarations: false
7 | AlignEscapedNewlines: Right
8 | AlignOperands: true
9 | AlignTrailingComments: false
10 | AllowAllParametersOfDeclarationOnNextLine: false
11 | AllowShortBlocksOnASingleLine: false
12 | AllowShortCaseLabelsOnASingleLine: false
13 | AllowShortFunctionsOnASingleLine: All
14 | AllowShortIfStatementsOnASingleLine: false
15 | AllowShortLoopsOnASingleLine: false
16 | AlwaysBreakAfterDefinitionReturnType: None
17 | AlwaysBreakAfterReturnType: None
18 | AlwaysBreakBeforeMultilineStrings: true
19 | AlwaysBreakTemplateDeclarations: true
20 | BinPackArguments: true
21 | BinPackParameters: false
22 | BreakBeforeBinaryOperators: All
23 | BreakBeforeBraces: Allman
24 | BreakBeforeInheritanceComma: false
25 | BreakBeforeTernaryOperators: true
26 | BreakConstructorInitializersBeforeComma: false
27 | BreakConstructorInitializers: BeforeComma
28 | BreakAfterJavaFieldAnnotations: false
29 | BreakStringLiterals: true
30 | ColumnLimit: 0
31 | CommentPragmas: '^ IWYU pragma:'
32 | CompactNamespaces: false
33 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
34 | ConstructorInitializerIndentWidth: 4
35 | ContinuationIndentWidth: 4
36 | Cpp11BracedListStyle: false
37 | DerivePointerAlignment: false
38 | DisableFormat: false
39 | ExperimentalAutoDetectBinPacking: false
40 | FixNamespaceComments: false
41 | ForEachMacros:
42 | - foreach
43 | - Q_FOREACH
44 | - BOOST_FOREACH
45 | IncludeBlocks: Preserve
46 | IncludeCategories:
47 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
48 | Priority: 2
49 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
50 | Priority: 3
51 | - Regex: '.*'
52 | Priority: 1
53 | IncludeIsMainRegex: '(Test)?$'
54 | IndentCaseLabels: false
55 | IndentPPDirectives: None
56 | IndentWidth: 4
57 | IndentWrappedFunctionNames: false
58 | JavaScriptQuotes: Leave
59 | JavaScriptWrapImports: true
60 | KeepEmptyLinesAtTheStartOfBlocks: true
61 | MacroBlockBegin: ''
62 | MacroBlockEnd: ''
63 | MaxEmptyLinesToKeep: 1
64 | NamespaceIndentation: Inner
65 | ObjCBlockIndentWidth: 4
66 | ObjCSpaceAfterProperty: true
67 | ObjCSpaceBeforeProtocolList: true
68 | PenaltyBreakAssignment: 2
69 | PenaltyBreakBeforeFirstCallParameter: 19
70 | PenaltyBreakComment: 300
71 | PenaltyBreakFirstLessLess: 120
72 | PenaltyBreakString: 1000
73 | PenaltyExcessCharacter: 1000000
74 | PenaltyReturnTypeOnItsOwnLine: 60
75 | PointerAlignment: Left
76 | RawStringFormats:
77 | - Delimiter: pb
78 | Language: TextProto
79 | BasedOnStyle: google
80 | ReflowComments: false
81 | SortIncludes: true
82 | SortUsingDeclarations: true
83 | SpaceAfterCStyleCast: false
84 | SpaceAfterTemplateKeyword: true
85 | SpaceBeforeAssignmentOperators: true
86 | SpaceBeforeParens: ControlStatements
87 | SpaceInEmptyParentheses: false
88 | SpacesBeforeTrailingComments: 1
89 | SpacesInAngles: false
90 | SpacesInContainerLiterals: true
91 | SpacesInCStyleCastParentheses: false
92 | SpacesInParentheses: false
93 | SpacesInSquareBrackets: false
94 | Standard: Cpp11
95 | TabWidth: 8
96 | UseTab: Never
97 | ...
98 |
99 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | #ctags
26 | tags
27 |
28 | # Shared objects (inc. Windows DLLs)
29 | *.dll
30 | *.so
31 | *.so.*
32 | *.dylib
33 |
34 | # Executables
35 | *.exe
36 | *.out
37 | *.app
38 | *.i*86
39 | *.x86_64
40 | *.hex
41 |
42 | # Debug files
43 | *.dSYM/
44 | *.su
45 | *.idb
46 | *.pdb
47 |
48 | #SGX
49 | enclave_t.*
50 | enclave_u.*
51 | enclave.debug.*
52 |
53 | #Swap
54 | .Makefile.*
55 | *.swp
56 |
57 | #Vim
58 | .vimrc
59 |
60 | #Project Artifacts
61 | status.mk
62 | build
63 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | UNTRUSTED_MK:= src/untrusted.mk
2 | ENCLAVE_MK:= src/enclave.mk
3 |
4 | .PHONY: all
5 | all:
6 | $(MAKE) -C $(shell dirname $(UNTRUSTED_MK)) -f $(shell basename $(UNTRUSTED_MK)) $@
7 | $(MAKE) -C $(shell dirname $(ENCLAVE_MK)) -f $(shell basename $(ENCLAVE_MK)) $@
8 |
9 | .PHONY: docker
10 | docker:
11 | docker build -f docker/Dockerfile -t stealthdb:1.0 docker/
12 | docker run -it -d --rm --device=/dev/isgx --volume=/var/run/aesmd/aesm.socket:/var/run/aesmd/aesm.socket -p 5432:5432 --name sdb stealthdb:1.0
13 |
14 | .PHONY: install
15 | install:
16 | $(MAKE) -C $(shell dirname $(UNTRUSTED_MK)) -f $(shell basename $(UNTRUSTED_MK)) $@
17 | $(MAKE) -C $(shell dirname $(ENCLAVE_MK)) -f $(shell basename $(ENCLAVE_MK)) $@
18 |
19 | .PHONY: clean
20 | clean:
21 | $(MAKE) -C $(shell dirname $(UNTRUSTED_MK)) -f $(shell basename $(UNTRUSTED_MK)) $@
22 | $(MAKE) -C $(shell dirname $(ENCLAVE_MK)) -f $(shell basename $(ENCLAVE_MK)) $@
23 | $(RM) -r build
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | StealthDB
2 | =======================================================================
3 |
4 | StealthDB is an extension to PostgreSQL, leveraging Intel SGX, that endows it with encrypted database functionality (i.e. encrypted values can be persisted in tables, and queries with encrypted expressions and predicates can be specified). The database's integrity and confidentiality is guaranteed under a threat model in which only the CPU is trusted. Further information can be found [here](https://arxiv.org/pdf/1711.02279.pdf).
5 |
6 | ## Status
7 |
8 | StealthDB is a research project and is **not** suitable for production use.
9 |
10 | ## Requirements
11 |
12 | * An Intel:registered: SGX-enabled CPU. In addition:
13 | * The [Intel:registered: SGX PSW and SDK](https://github.com/01org/linux-sgx#build-the-intelr-sgx-sdk-and-intelr-sgx-psw-package) installed in the `/opt` directory
14 | * Version 2.0 of the [Intel:registered: SGX Driver](https://github.com/01org/linux-sgx-driver#build-and-install-the-intelr-sgx-driver)
15 |
16 | * The NASM assembler.
17 |
18 | ## Quickstart
19 |
20 | ### Installing on 64-bit Ubuntu Desktop-16.04
21 |
22 | 0. Install PostgreSQL server and the PostgreSQL extension build tool:
23 |
24 | ```
25 | sudo apt-get install postgresql postgresql-server-dev-all
26 | ```
27 |
28 | 1. Run:
29 |
30 | ```
31 | make
32 | sudo make install
33 | ```
34 |
35 | ### Creating a Debian-based Docker Container
36 |
37 | 1. If you have a PostgreSQL service already running, be sure to stop it with `sudo service postgresql stop`.
38 |
39 | 2. Run
40 |
41 | ```
42 | make docker
43 | ```
44 |
45 | ### Running Queries
46 |
47 | 0. Run the PostgreSQL client.
48 |
49 | 1. Load the extension into the database, generate the default master key, and load the key.
50 |
51 | ```
52 | CREATE EXTENSION encdb;
53 | SELECT generate_key();
54 | SELECT load_key(0);
55 | ```
56 |
57 | 2. Try some examples
58 |
59 | ```
60 | SELECT pg_enc_int4_encrypt(1) + pg_enc_int4_encrypt(2);
61 | SELECT pg_enc_int4_decrypt(pg_enc_int4_encrypt(1) + pg_enc_int4_encrypt(2));
62 | ```
63 |
64 | `pg_enc_int4_decrypt` and `pg_enc_int4_encrypt` are wrappers around the `enc_int4` data type, which in turn corresponds to the `int4` type offered by PostgreSQL.
65 |
66 | `pg_enc_int4_encrypt(x)` encrypts the number `x` and stores it as an `enc_int4` value. `pg_enc_int4_decrypt(x)` takes an `enc_int4` value `x` and decrypts it. Further information can be found [here](https://github.com/cryptograph/stealthdb/blob/master/docs/user/README.md).
67 |
68 | Consult the [manual](https://github.com/cryptograph/stealthdb/blob/master/docs/user/install.md) for further information.
69 |
--------------------------------------------------------------------------------
/benchmark/README.md:
--------------------------------------------------------------------------------
1 | # Benchmarking suite
2 |
3 | We use modified open-source OLTP Benchmarking Framework (http://oltpbenchmark.com) to measure TPC-C and TPC-H performance. One can clone the source code of the framework and apply the patch or just use jar executable file to get numbers.
4 |
5 | ## Build from the source code.
6 |
7 | ```
8 | git clone https://github.com/oltpbenchmark/oltpbench.git
9 | git checkout 51f9aa011defb33cfe4c8ebd902c495830c2824f
10 | git apply patches/oltpbenchmark.patch
11 | ```
12 |
13 | ## Configuration
14 |
15 | * setup database credentials in configuration file config/tpcc_config_postgres.xml
16 | * setup logger configuration in log4j.properties
17 | * create TPC-C database schema, select which columns to encrypt
18 | (ex. ol_number int NOT NULL --> ol_number enc_int4 NOT NULL)
19 |
20 | See more information in the [original repository](https://github.com/oltpbenchmark/oltpbench/wiki/Quickstart)
21 |
22 | ## How to start
23 |
24 | 0. Create the user and the database
25 |
26 | ```
27 | psql
28 | postgres> CREATE USER test WITH PASSWORD 'password';
29 | postgres> CREATE DATABASE test;
30 | postgres> \c test;
31 | postgres> CREATE EXTENSION encdb;
32 | ```
33 |
34 | ### TPC-C
35 | 1. Create tables and relations
36 |
37 | ```
38 | psql -U test -d test -f db_schemas/tpcc-schema.sql
39 | (or psql -U test -d test -f db_schemas/tpcc-schema_encrypted.sql)
40 | ```
41 |
42 | 2. Run experiments
43 |
44 | ```
45 | java -Dlog4j.configuration=log4j.properties -jar bin/oltp.jar -b tpcc -o output -s 10 --config config/tpcc_config.xml --load true --execute true
46 | ```
47 |
48 | 3. The output will be in the folder results/ containing files with the listing of start time and duration for each transaction type (output.raw), the throughput and different latency measures in milliseconds (output.res)
49 |
50 | ### TPC-H
51 | 1. Create tables and relations between them
52 |
53 | ```
54 | psql -U test -d test -f db_schemas/tpch-schema.sql
55 | (or psql -U test -d test -f db_schemas/tpch-schema_encrypted.sql)
56 | psql -U test -d test -f db_schemas/tpch-index.sql
57 | ```
58 |
59 | 2. Generate tables
60 |
61 | ```
62 | tool/dbgen -s 2
63 | ```
64 |
65 | 3. Run experiments
66 |
67 | ```
68 | java -Dlog4j.configuration=log4j.properties -jar bin/tpch.jar -b tpch -o output -s 10 --config config/tpch_config.xml --load true --execute true
69 | ```
70 |
71 | 4. The output will be in the folder results/ containing files with the listing of start time and duration for each transaction type (output.csv), the throughput and different latency measures in milliseconds (output.res)
72 |
73 |
--------------------------------------------------------------------------------
/benchmark/bin/oltp.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cryptograph/stealthdb/1ca645ae1613c146d59900ce50abc873dc8a6d01/benchmark/bin/oltp.jar
--------------------------------------------------------------------------------
/benchmark/bin/tpch.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cryptograph/stealthdb/1ca645ae1613c146d59900ce50abc873dc8a6d01/benchmark/bin/tpch.jar
--------------------------------------------------------------------------------
/benchmark/config/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.mysql.jdbc.Driver
4 | jdbc:mysql://127.0.0.1:3500/wiki1k
5 | wiki1k
6 | root
7 |
8 |
9 |
10 |
11 | 10
12 | 5,5,5,5
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/benchmark/config/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.oltpbenchmark.benchmarks.tpcc.TPCCBenchmark
4 | com.oltpbenchmark.benchmarks.tpch.TPCHBenchmark
5 | com.oltpbenchmark.benchmarks.tatp.TATPBenchmark
6 | com.oltpbenchmark.benchmarks.wikipedia.WikipediaBenchmark
7 | com.oltpbenchmark.benchmarks.resourcestresser.ResourceStresserBenchmark
8 | com.oltpbenchmark.benchmarks.twitter.TwitterBenchmark
9 | com.oltpbenchmark.benchmarks.epinions.EpinionsBenchmark
10 | com.oltpbenchmark.benchmarks.ycsb.YCSBBenchmark
11 | com.oltpbenchmark.benchmarks.jpab.JPABBenchmark
12 | com.oltpbenchmark.benchmarks.seats.SEATSBenchmark
13 | com.oltpbenchmark.benchmarks.auctionmark.AuctionMarkBenchmark
14 | com.oltpbenchmark.benchmarks.chbenchmark.CHBenCHmark
15 | com.oltpbenchmark.benchmarks.voter.VoterBenchmark
16 | com.oltpbenchmark.benchmarks.linkbench.LinkBenchBenchmark
17 | com.oltpbenchmark.benchmarks.sibench.SIBenchmark
18 | com.oltpbenchmark.benchmarks.noop.NoOpBenchmark
19 | com.oltpbenchmark.benchmarks.smallbank.SmallBankBenchmark
20 | com.oltpbenchmark.benchmarks.hyadapt.HYADAPTBenchmark
21 |
22 |
--------------------------------------------------------------------------------
/benchmark/config/tpcc_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | postgres
6 | org.postgresql.Driver
7 | jdbc:postgresql://localhost:5432/test
8 | test
9 | password
10 | TRANSACTION_READ_COMMITTED
11 |
12 |
13 | 1
14 |
15 |
16 | 1
17 |
18 |
19 |
20 | 10000
21 | true
22 | 45,43,4,4,4
23 |
24 |
25 |
26 |
27 |
28 |
29 | NewOrder
30 |
31 |
32 | Payment
33 |
34 |
35 | OrderStatus
36 |
37 |
38 | Delivery
39 |
40 |
41 | StockLevel
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/benchmark/config/tpch_postgres.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | postgres
6 | org.postgresql.Driver
7 | jdbc:postgresql://localhost:5432/test
8 | test_user
9 | test_password
10 | TRANSACTION_READ_COMMITTED
11 | tools/
12 | tbl
13 |
14 |
15 | 1
16 |
17 |
18 | 1
19 |
20 |
21 |
22 | false
23 | 10000
24 | 3, 2, 3, 2 , 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
25 |
26 |
27 |
28 |
29 |
30 |
31 | Q1
32 |
33 |
34 | Q2
35 |
36 |
37 | Q3
38 |
39 |
40 | Q4
41 |
42 |
43 | Q5
44 |
45 |
46 | Q6
47 |
48 |
49 | Q7
50 |
51 |
52 | Q8
53 |
54 |
55 | Q9
56 |
57 |
58 | Q10
59 |
60 |
61 | Q11
62 |
63 |
64 | Q12
65 |
66 |
67 | Q13
68 |
69 |
70 | Q14
71 |
72 |
73 |
74 | Q15
75 |
76 |
77 | Q16
78 |
79 |
80 | Q17
81 |
82 |
83 | Q18
84 |
85 |
86 | Q19
87 |
88 |
89 | Q20
90 |
91 |
92 | Q21
93 |
94 |
95 | Q22
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/benchmark/db_schemas/tpcc-schema.sql:
--------------------------------------------------------------------------------
1 | CREATE EXTENSION IF NOT EXISTS encdb;
2 |
3 | DROP TABLE IF EXISTS order_line;
4 | CREATE TABLE order_line (
5 | ol_w_id int NOT NULL,
6 | ol_d_id int NOT NULL,
7 | ol_o_id int NOT NULL,
8 | ol_number int NOT NULL,
9 | ol_i_id int NOT NULL,
10 | ol_delivery_d timestamp NULL DEFAULT NULL,
11 | ol_amount decimal(6,2) NOT NULL,
12 | ol_supply_w_id int NOT NULL,
13 | ol_quantity decimal(2,0) NOT NULL,
14 | ol_dist_info char(24) NOT NULL,
15 | PRIMARY KEY (ol_w_id,ol_d_id,ol_o_id,ol_number)
16 | );
17 |
18 | DROP TABLE IF EXISTS new_order;
19 | CREATE TABLE new_order (
20 | no_w_id int NOT NULL,
21 | no_d_id int NOT NULL,
22 | no_o_id int NOT NULL,
23 | PRIMARY KEY (no_w_id,no_d_id,no_o_id)
24 | );
25 |
26 | DROP TABLE IF EXISTS stock;
27 | CREATE TABLE stock (
28 | s_w_id int NOT NULL,
29 | s_i_id int NOT NULL,
30 | s_quantity decimal(4,0) NOT NULL,
31 | s_ytd decimal(8,2) NOT NULL,
32 | s_order_cnt int NOT NULL,
33 | s_remote_cnt int NOT NULL,
34 | s_data varchar(50) NOT NULL,
35 | s_dist_01 char(24) NOT NULL,
36 | s_dist_02 char(24) NOT NULL,
37 | s_dist_03 char(24) NOT NULL,
38 | s_dist_04 char(24) NOT NULL,
39 | s_dist_05 char(24) NOT NULL,
40 | s_dist_06 char(24) NOT NULL,
41 | s_dist_07 char(24) NOT NULL,
42 | s_dist_08 char(24) NOT NULL,
43 | s_dist_09 char(24) NOT NULL,
44 | s_dist_10 char(24) NOT NULL,
45 | PRIMARY KEY (s_w_id,s_i_id)
46 | );
47 |
48 | DROP TABLE IF EXISTS oorder;
49 | CREATE TABLE oorder (
50 | o_w_id int NOT NULL,
51 | o_d_id int NOT NULL,
52 | o_id int NOT NULL,
53 | o_c_id int NOT NULL,
54 | o_carrier_id int DEFAULT NULL,
55 | o_ol_cnt decimal(2,0) NOT NULL,
56 | o_all_local decimal(1,0) NOT NULL,
57 | o_entry_d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
58 | PRIMARY KEY (o_w_id,o_d_id,o_id),
59 | UNIQUE (o_w_id,o_d_id,o_c_id,o_id)
60 | );
61 |
62 | DROP TABLE IF EXISTS history;
63 | CREATE TABLE history (
64 | h_c_id int NOT NULL,
65 | h_c_d_id int NOT NULL,
66 | h_c_w_id int NOT NULL,
67 | h_d_id int NOT NULL,
68 | h_w_id int NOT NULL,
69 | h_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
70 | h_amount decimal(6,2) NOT NULL,
71 | h_data varchar(24) NOT NULL
72 | );
73 |
74 | DROP TABLE IF EXISTS customer;
75 | CREATE TABLE customer (
76 | c_w_id int NOT NULL,
77 | c_d_id int NOT NULL,
78 | c_id int NOT NULL,
79 | c_discount decimal(4,4) NOT NULL,
80 | c_credit char(2) NOT NULL,
81 | c_last varchar(16) NOT NULL,
82 | c_first varchar(16) NOT NULL,
83 | c_credit_lim decimal(12,2) NOT NULL,
84 | c_balance decimal(12,2) NOT NULL,
85 | c_ytd_payment float NOT NULL,
86 | c_payment_cnt int NOT NULL,
87 | c_delivery_cnt int NOT NULL,
88 | c_street_1 varchar(20) NOT NULL,
89 | c_street_2 varchar(20) NOT NULL,
90 | c_city varchar(20) NOT NULL,
91 | c_state char(2) NOT NULL,
92 | c_zip char(9) NOT NULL,
93 | c_phone char(16) NOT NULL,
94 | c_since timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
95 | c_middle char(2) NOT NULL,
96 | c_data varchar(500) NOT NULL,
97 | PRIMARY KEY (c_w_id,c_d_id,c_id)
98 | );
99 |
100 | DROP TABLE IF EXISTS district;
101 | CREATE TABLE district (
102 | d_w_id int NOT NULL,
103 | d_id int NOT NULL,
104 | d_ytd decimal(12,2) NOT NULL,
105 | d_tax decimal(4,4) NOT NULL,
106 | d_next_o_id int NOT NULL,
107 | d_name varchar(10) NOT NULL,
108 | d_street_1 varchar(20) NOT NULL,
109 | d_street_2 varchar(20) NOT NULL,
110 | d_city varchar(20) NOT NULL,
111 | d_state char(2) NOT NULL,
112 | d_zip char(9) NOT NULL,
113 | PRIMARY KEY (d_w_id,d_id)
114 | );
115 |
116 |
117 | DROP TABLE IF EXISTS item;
118 | CREATE TABLE item (
119 | i_id int NOT NULL,
120 | i_name varchar(24) NOT NULL,
121 | i_price decimal(5,2) NOT NULL,
122 | i_data varchar(50) NOT NULL,
123 | i_im_id int NOT NULL,
124 | PRIMARY KEY (i_id)
125 | );
126 |
127 |
128 | DROP TABLE IF EXISTS warehouse;
129 | CREATE TABLE warehouse (
130 | w_id int NOT NULL,
131 | w_ytd decimal(12,2) NOT NULL,
132 | w_tax decimal(4,4) NOT NULL,
133 | w_name varchar(10) NOT NULL,
134 | w_street_1 varchar(20) NOT NULL,
135 | w_street_2 varchar(20) NOT NULL,
136 | w_city varchar(20) NOT NULL,
137 | w_state char(2) NOT NULL,
138 | w_zip char(9) NOT NULL,
139 | PRIMARY KEY (w_id)
140 | );
141 |
142 |
143 | --add constraints and indexes
144 | CREATE INDEX idx_customer_name ON customer (c_w_id,c_d_id,c_last,c_first);
145 | CREATE INDEX idx_order ON oorder (o_w_id,o_d_id,o_c_id,o_id);
146 | -- tpcc-mysql create two indexes for the foreign key constraints, Is it really necessary?
147 | -- CREATE INDEX FKEY_STOCK_2 ON STOCK (S_I_ID);
148 | -- CREATE INDEX FKEY_ORDER_LINE_2 ON ORDER_LINE (OL_SUPPLY_W_ID,OL_I_ID);
149 |
150 | --add 'ON DELETE CASCADE' to clear table work correctly
151 |
152 | ALTER TABLE district ADD CONSTRAINT fkey_district_1 FOREIGN KEY(d_w_id) REFERENCES warehouse(w_id) ON DELETE CASCADE;
153 | ALTER TABLE customer ADD CONSTRAINT fkey_customer_1 FOREIGN KEY(c_w_id,c_d_id) REFERENCES district(d_w_id,d_id) ON DELETE CASCADE ;
154 | ALTER TABLE history ADD CONSTRAINT fkey_history_1 FOREIGN KEY(h_c_w_id,h_c_d_id,h_c_id) REFERENCES customer(c_w_id,c_d_id,c_id) ON DELETE CASCADE;
155 | ALTER TABLE history ADD CONSTRAINT fkey_history_2 FOREIGN KEY(h_w_id,h_d_id) REFERENCES district(d_w_id,d_id) ON DELETE CASCADE;
156 | ALTER TABLE new_order ADD CONSTRAINT fkey_new_order_1 FOREIGN KEY(no_w_id,no_d_id,no_o_id) REFERENCES oorder(o_w_id,o_d_id,o_id) ON DELETE CASCADE;
157 | ALTER TABLE oorder ADD CONSTRAINT fkey_order_1 FOREIGN KEY(o_w_id,o_d_id,o_c_id) REFERENCES customer(c_w_id,c_d_id,c_id) ON DELETE CASCADE;
158 | ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_1 FOREIGN KEY(ol_w_id,ol_d_id,ol_o_id) REFERENCES oorder(o_w_id,o_d_id,o_id) ON DELETE CASCADE;
159 | ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_2 FOREIGN KEY(ol_supply_w_id,ol_i_id) REFERENCES stock(s_w_id,s_i_id) ON DELETE CASCADE;
160 | ALTER TABLE stock ADD CONSTRAINT fkey_stock_1 FOREIGN KEY(s_w_id) REFERENCES warehouse(w_id) ON DELETE CASCADE;
161 | ALTER TABLE stock ADD CONSTRAINT fkey_stock_2 FOREIGN KEY(s_i_id) REFERENCES item(i_id) ON DELETE CASCADE;
162 |
163 |
--------------------------------------------------------------------------------
/benchmark/db_schemas/tpcc-schema_encrypted.sql:
--------------------------------------------------------------------------------
1 | CREATE EXTENSION IF NOT EXISTS encdb;
2 |
3 | DROP TABLE IF EXISTS order_line;
4 | CREATE TABLE order_line (
5 | ol_w_id int NOT NULL,
6 | ol_d_id int NOT NULL,
7 | ol_o_id int NOT NULL,
8 | ol_number enc_int4 NOT NULL,
9 | ol_i_id int NOT NULL,
10 | ol_delivery_d enc_timestamp NULL DEFAULT NULL,
11 | ol_amount enc_float4 NOT NULL,
12 | ol_supply_w_id int NOT NULL,
13 | ol_quantity enc_float4 NOT NULL,
14 | ol_dist_info char(24) NOT NULL,
15 | PRIMARY KEY (ol_w_id,ol_d_id,ol_o_id,ol_number)
16 | );
17 |
18 | DROP TABLE IF EXISTS new_order;
19 | CREATE TABLE new_order (
20 | no_w_id int NOT NULL,
21 | no_d_id int NOT NULL,
22 | no_o_id int NOT NULL,
23 | PRIMARY KEY (no_w_id,no_d_id,no_o_id)
24 | );
25 |
26 | DROP TABLE IF EXISTS stock;
27 | CREATE TABLE stock (
28 | s_w_id int NOT NULL,
29 | s_i_id int NOT NULL,
30 | s_quantity enc_float4 NOT NULL,
31 | s_ytd enc_float4 NOT NULL,
32 | s_order_cnt enc_int4 NOT NULL,
33 | s_remote_cnt enc_int4 NOT NULL,
34 | s_data varchar(50) NOT NULL,
35 | s_dist_01 char(24) NOT NULL,
36 | s_dist_02 char(24) NOT NULL,
37 | s_dist_03 char(24) NOT NULL,
38 | s_dist_04 char(24) NOT NULL,
39 | s_dist_05 char(24) NOT NULL,
40 | s_dist_06 char(24) NOT NULL,
41 | s_dist_07 char(24) NOT NULL,
42 | s_dist_08 char(24) NOT NULL,
43 | s_dist_09 char(24) NOT NULL,
44 | s_dist_10 char(24) NOT NULL,
45 | PRIMARY KEY (s_w_id,s_i_id)
46 | );
47 |
48 | DROP TABLE IF EXISTS oorder;
49 | CREATE TABLE oorder (
50 | o_w_id int NOT NULL,
51 | o_d_id int NOT NULL,
52 | o_id int NOT NULL,
53 | o_c_id int NOT NULL,
54 | o_carrier_id int DEFAULT NULL,
55 | o_ol_cnt enc_float4 NOT NULL,
56 | o_all_local enc_float4 NOT NULL,
57 | o_entry_d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
58 | PRIMARY KEY (o_w_id,o_d_id,o_id),
59 | UNIQUE (o_w_id,o_d_id,o_c_id,o_id)
60 | );
61 |
62 | DROP TABLE IF EXISTS history;
63 | CREATE TABLE history (
64 | h_c_id int NOT NULL,
65 | h_c_d_id int NOT NULL,
66 | h_c_w_id int NOT NULL,
67 | h_d_id int NOT NULL,
68 | h_w_id int NOT NULL,
69 | h_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
70 | h_amount enc_float4 NOT NULL,
71 | h_data varchar(24) NOT NULL
72 | );
73 |
74 | DROP TABLE IF EXISTS customer;
75 | CREATE TABLE customer (
76 | c_w_id int NOT NULL,
77 | c_d_id int NOT NULL,
78 | c_id int NOT NULL,
79 | c_discount enc_float4 NOT NULL,
80 | c_credit char(2) NOT NULL,
81 | c_last varchar(16) NOT NULL,
82 | c_first varchar(16) NOT NULL,
83 | c_credit_lim enc_float4 NOT NULL,
84 | c_balance enc_float4 NOT NULL,
85 | c_ytd_payment enc_float4 NOT NULL,
86 | c_payment_cnt enc_int4 NOT NULL,
87 | c_delivery_cnt enc_int4 NOT NULL,
88 | c_street_1 varchar(20) NOT NULL,
89 | c_street_2 varchar(20) NOT NULL,
90 | c_city varchar(20) NOT NULL,
91 | c_state char(2) NOT NULL,
92 | c_zip char(9) NOT NULL,
93 | c_phone char(16) NOT NULL,
94 | c_since timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
95 | c_middle char(2) NOT NULL,
96 | c_data varchar(500) NOT NULL,
97 | PRIMARY KEY (c_w_id,c_d_id,c_id)
98 | );
99 |
100 | DROP TABLE IF EXISTS district;
101 | CREATE TABLE district (
102 | d_w_id int NOT NULL,
103 | d_id int NOT NULL,
104 | d_ytd enc_float4 NOT NULL,
105 | d_tax enc_float4 NOT NULL,
106 | d_next_o_id int NOT NULL,
107 | d_name varchar(10) NOT NULL,
108 | d_street_1 varchar(20) NOT NULL,
109 | d_street_2 varchar(20) NOT NULL,
110 | d_city varchar(20) NOT NULL,
111 | d_state char(2) NOT NULL,
112 | d_zip char(9) NOT NULL,
113 | PRIMARY KEY (d_w_id,d_id)
114 | );
115 |
116 |
117 | DROP TABLE IF EXISTS item;
118 | CREATE TABLE item (
119 | i_id int NOT NULL,
120 | i_name varchar(24) NOT NULL,
121 | i_price enc_float4 NOT NULL,
122 | i_data varchar(50) NOT NULL,
123 | i_im_id int NOT NULL,
124 | PRIMARY KEY (i_id)
125 | );
126 |
127 |
128 | DROP TABLE IF EXISTS warehouse;
129 | CREATE TABLE warehouse (
130 | w_id int NOT NULL,
131 | w_ytd enc_float4 NOT NULL,
132 | w_tax enc_float4 NOT NULL,
133 | w_name enc_text NOT NULL,
134 | w_street_1 varchar(20) NOT NULL,
135 | w_street_2 varchar(20) NOT NULL,
136 | w_city varchar(20) NOT NULL,
137 | w_state char(2) NOT NULL,
138 | w_zip char(9) NOT NULL,
139 | PRIMARY KEY (w_id)
140 | );
141 |
142 |
143 | --add constraints and indexes
144 | CREATE INDEX idx_customer_name ON customer (c_w_id,c_d_id,c_last,c_first);
145 | CREATE INDEX idx_order ON oorder (o_w_id,o_d_id,o_c_id,o_id);
146 | -- tpcc-mysql create two indexes for the foreign key constraints, Is it really necessary?
147 | -- CREATE INDEX FKEY_STOCK_2 ON STOCK (S_I_ID);
148 | -- CREATE INDEX FKEY_ORDER_LINE_2 ON ORDER_LINE (OL_SUPPLY_W_ID,OL_I_ID);
149 |
150 | --add 'ON DELETE CASCADE' to clear table work correctly
151 |
152 | ALTER TABLE district ADD CONSTRAINT fkey_district_1 FOREIGN KEY(d_w_id) REFERENCES warehouse(w_id) ON DELETE CASCADE;
153 | ALTER TABLE customer ADD CONSTRAINT fkey_customer_1 FOREIGN KEY(c_w_id,c_d_id) REFERENCES district(d_w_id,d_id) ON DELETE CASCADE ;
154 | ALTER TABLE history ADD CONSTRAINT fkey_history_1 FOREIGN KEY(h_c_w_id,h_c_d_id,h_c_id) REFERENCES customer(c_w_id,c_d_id,c_id) ON DELETE CASCADE;
155 | ALTER TABLE history ADD CONSTRAINT fkey_history_2 FOREIGN KEY(h_w_id,h_d_id) REFERENCES district(d_w_id,d_id) ON DELETE CASCADE;
156 | ALTER TABLE new_order ADD CONSTRAINT fkey_new_order_1 FOREIGN KEY(no_w_id,no_d_id,no_o_id) REFERENCES oorder(o_w_id,o_d_id,o_id) ON DELETE CASCADE;
157 | ALTER TABLE oorder ADD CONSTRAINT fkey_order_1 FOREIGN KEY(o_w_id,o_d_id,o_c_id) REFERENCES customer(c_w_id,c_d_id,c_id) ON DELETE CASCADE;
158 | ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_1 FOREIGN KEY(ol_w_id,ol_d_id,ol_o_id) REFERENCES oorder(o_w_id,o_d_id,o_id) ON DELETE CASCADE;
159 | ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_2 FOREIGN KEY(ol_supply_w_id,ol_i_id) REFERENCES stock(s_w_id,s_i_id) ON DELETE CASCADE;
160 | ALTER TABLE stock ADD CONSTRAINT fkey_stock_1 FOREIGN KEY(s_w_id) REFERENCES warehouse(w_id) ON DELETE CASCADE;
161 | ALTER TABLE stock ADD CONSTRAINT fkey_stock_2 FOREIGN KEY(s_i_id) REFERENCES item(i_id) ON DELETE CASCADE;
162 |
163 |
--------------------------------------------------------------------------------
/benchmark/db_schemas/tpch-index.sql:
--------------------------------------------------------------------------------
1 | create unique index c_ck on customer (c_custkey asc) ;
2 | create index c_nk on customer (c_nationkey asc) ;
3 | create unique index p_pk on part (p_partkey asc) ;
4 | create unique index s_sk on supplier (s_suppkey asc) ;
5 | create index s_nk on supplier (s_nationkey asc) ;
6 | create index ps_pk on partsupp (ps_partkey asc) ;
7 | create index ps_sk on partsupp (ps_suppkey asc) ;
8 | create unique index ps_pk_sk on partsupp (ps_partkey asc, ps_suppkey asc) ;
9 | create unique index ps_sk_pk on partsupp (ps_suppkey asc, ps_partkey asc) ;
10 | create unique index o_ok on orders (o_orderkey asc) ;
11 | create index o_ck on orders (o_custkey asc) ;
12 | create index o_od on orders (o_orderdate asc) ;
13 | create index l_ok on lineitem (l_orderkey asc) ;
14 | create index l_pk on lineitem (l_partkey asc) ;
15 | create index l_sk on lineitem (l_suppkey asc) ;
16 | --create index l_ln on lineitem (l_linenumber asc) ;
17 | create index l_sd on lineitem (l_shipdate asc) ;
18 | create index l_cd on lineitem (l_commitdate asc) ;
19 | create index l_rd on lineitem (l_receiptdate asc) ;
20 | --create unique index l_ok_ln on lineitem (l_orderkey asc, l_linenumber asc) ;
21 | --create unique index l_ln_ok on lineitem (l_linenumber asc, l_orderkey asc) ;
22 | create index l_pk_sk on lineitem (l_partkey asc, l_suppkey asc) ;
23 | create index l_sk_pk on lineitem (l_suppkey asc, l_partkey asc) ;
24 | create unique index n_nk on nation (n_nationkey asc) ;
25 | create index n_rk on nation (n_regionkey asc) ;
26 | create unique index r_rk on region (r_regionkey asc) ;
27 |
--------------------------------------------------------------------------------
/benchmark/db_schemas/tpch-schema-encrypted.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS nation CASCADE;
2 | DROP TABLE IF EXISTS region CASCADE;
3 | DROP TABLE IF EXISTS part CASCADE;
4 | DROP TABLE IF EXISTS supplier CASCADE;
5 | DROP TABLE IF EXISTS partsupp CASCADE;
6 | DROP TABLE IF EXISTS orders CASCADE;
7 | DROP TABLE IF EXISTS customer CASCADE;
8 | DROP TABLE IF EXISTS lineitem CASCADE;
9 |
10 | CREATE TABLE nation ( n_nationkey INTEGER NOT NULL,
11 | n_name enc_text NOT NULL,
12 | n_regionkey INTEGER NOT NULL,
13 | n_comment enc_text);
14 |
15 | CREATE TABLE region ( r_regionkey INTEGER NOT NULL,
16 | r_name enc_text NOT NULL,
17 | r_comment enc_text);
18 |
19 | CREATE TABLE part ( p_partkey INTEGER NOT NULL,
20 | p_name enc_text NOT NULL,
21 | p_mfgr enc_text NOT NULL,
22 | p_brand enc_text NOT NULL,
23 | p_type enc_text NOT NULL,
24 | p_size enc_int4 NOT NULL,
25 | p_container enc_text NOT NULL,
26 | p_retailprice enc_float4 NOT NULL,
27 | p_comment enc_text NOT NULL );
28 |
29 | CREATE TABLE supplier ( s_suppkey INTEGER NOT NULL,
30 | s_name enc_text NOT NULL,
31 | s_address enc_text NOT NULL,
32 | s_nationkey INTEGER NOT NULL,
33 | s_phone enc_text NOT NULL,
34 | s_acctbal enc_float4 NOT NULL,
35 | s_comment enc_text NOT NULL);
36 |
37 | CREATE TABLE partsupp ( ps_partkey INTEGER NOT NULL,
38 | ps_suppkey INTEGER NOT NULL,
39 | ps_availqty enc_float4 NOT NULL,
40 | ps_supplycost enc_float4 NOT NULL,
41 | ps_comment enc_text NOT NULL );
42 |
43 | CREATE TABLE customer ( c_custkey INTEGER NOT NULL,
44 | c_name enc_text NOT NULL,
45 | c_address enc_text NOT NULL,
46 | c_nationkey INTEGER NOT NULL,
47 | c_phone enc_text NOT NULL,
48 | c_acctbal enc_float4 NOT NULL,
49 | c_mktsegment enc_text NOT NULL,
50 | c_comment enc_text NOT NULL);
51 |
52 | CREATE TABLE orders ( o_orderkey INTEGER NOT NULL,
53 | o_custkey INTEGER NOT NULL,
54 | o_orderstatus enc_text NOT NULL,
55 | o_totalprice enc_float4 NOT NULL,
56 | o_orderdate DATE NOT NULL,
57 | o_orderpriority enc_text NOT NULL,
58 | o_clerk enc_text NOT NULL,
59 | o_shippriority enc_int4 NOT NULL,
60 | o_comment enc_text NOT NULL);
61 |
62 | CREATE TABLE lineitem ( l_orderkey INTEGER NOT NULL,
63 | l_partkey INTEGER NOT NULL,
64 | l_suppkey INTEGER NOT NULL,
65 | l_linenumber INTEGER NOT NULL,
66 | l_quantity enc_float4 NOT NULL,
67 | l_extendedprice enc_float4 NOT NULL,
68 | l_discount enc_float4 NOT NULL,
69 | l_tax enc_float4 NOT NULL,
70 | l_returnflag enc_text NOT NULL,
71 | l_linestatus enc_text NOT NULL,
72 | l_shipdate DATE NOT NULL,
73 | l_commitdate DATE NOT NULL,
74 | l_receiptdate DATE NOT NULL,
75 | l_shipinstruct enc_text NOT NULL,
76 | l_shipmode enc_text NOT NULL,
77 | l_comment enc_text NOT NULL);
78 |
--------------------------------------------------------------------------------
/benchmark/db_schemas/tpch-schema.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS nation CASCADE;
2 | DROP TABLE IF EXISTS region CASCADE;
3 | DROP TABLE IF EXISTS part CASCADE;
4 | DROP TABLE IF EXISTS supplier CASCADE;
5 | DROP TABLE IF EXISTS partsupp CASCADE;
6 | DROP TABLE IF EXISTS orders CASCADE;
7 | DROP TABLE IF EXISTS customer CASCADE;
8 | DROP TABLE IF EXISTS lineitem CASCADE;
9 |
10 | CREATE TABLE nation ( n_nationkey INTEGER NOT NULL,
11 | n_name CHAR(25) NOT NULL,
12 | n_regionkey INTEGER NOT NULL,
13 | n_comment VARCHAR(152));
14 |
15 | CREATE TABLE region ( r_regionkey INTEGER NOT NULL,
16 | r_name CHAR(25) NOT NULL,
17 | r_comment VARCHAR(152));
18 |
19 | CREATE TABLE part ( p_partkey INTEGER NOT NULL,
20 | p_name VARCHAR(55) NOT NULL,
21 | p_mfgr CHAR(25) NOT NULL,
22 | p_brand CHAR(10) NOT NULL,
23 | p_type VARCHAR(25) NOT NULL,
24 | p_size INTEGER NOT NULL,
25 | p_container CHAR(10) NOT NULL,
26 | p_retailprice DECIMAL(15,2) NOT NULL,
27 | p_comment VARCHAR(23) NOT NULL );
28 |
29 | CREATE TABLE supplier ( s_suppkey INTEGER NOT NULL,
30 | s_name CHAR(25) NOT NULL,
31 | s_address VARCHAR(40) NOT NULL,
32 | s_nationkey INTEGER NOT NULL,
33 | s_phone CHAR(15) NOT NULL,
34 | s_acctbal DECIMAL(15,2) NOT NULL,
35 | s_comment VARCHAR(101) NOT NULL);
36 |
37 | CREATE TABLE partsupp ( ps_partkey INTEGER NOT NULL,
38 | ps_suppkey INTEGER NOT NULL,
39 | ps_availqty INTEGER NOT NULL,
40 | ps_supplycost DECIMAL(15,2) NOT NULL,
41 | ps_comment VARCHAR(199) NOT NULL );
42 |
43 | CREATE TABLE customer ( c_custkey INTEGER NOT NULL,
44 | c_name VARCHAR(25) NOT NULL,
45 | c_address VARCHAR(40) NOT NULL,
46 | c_nationkey INTEGER NOT NULL,
47 | c_phone CHAR(15) NOT NULL,
48 | c_acctbal DECIMAL(15,2) NOT NULL,
49 | c_mktsegment CHAR(10) NOT NULL,
50 | c_comment VARCHAR(117) NOT NULL);
51 |
52 | CREATE TABLE orders ( o_orderkey INTEGER NOT NULL,
53 | o_custkey INTEGER NOT NULL,
54 | o_orderstatus CHAR(1) NOT NULL,
55 | o_totalprice DECIMAL(15,2) NOT NULL,
56 | o_orderdate DATE NOT NULL,
57 | o_orderpriority CHAR(15) NOT NULL,
58 | o_clerk CHAR(15) NOT NULL,
59 | o_shippriority INTEGER NOT NULL,
60 | o_comment VARCHAR(79) NOT NULL);
61 |
62 | CREATE TABLE lineitem ( l_orderkey INTEGER NOT NULL,
63 | l_partkey INTEGER NOT NULL,
64 | l_suppkey INTEGER NOT NULL,
65 | l_linenumber INTEGER NOT NULL,
66 | l_quantity DECIMAL(15,2) NOT NULL,
67 | l_extendedprice DECIMAL(15,2) NOT NULL,
68 | l_discount DECIMAL(15,2) NOT NULL,
69 | l_tax DECIMAL(15,2) NOT NULL,
70 | l_returnflag CHAR(1) NOT NULL,
71 | l_linestatus CHAR(1) NOT NULL,
72 | l_shipdate DATE NOT NULL,
73 | l_commitdate DATE NOT NULL,
74 | l_receiptdate DATE NOT NULL,
75 | l_shipinstruct CHAR(25) NOT NULL,
76 | l_shipmode CHAR(10) NOT NULL,
77 | l_comment VARCHAR(44) NOT NULL);
78 |
--------------------------------------------------------------------------------
/benchmark/log4j.properties:
--------------------------------------------------------------------------------
1 | # Set root logger level to DEBUG and its only appender to A1.
2 | log4j.rootLogger=INFO, A1
3 | log4j.rootLogger.layout=org.apache.log4j.PatternLayout
4 |
5 | # A1 is set to be a ConsoleAppender.
6 | log4j.appender.A1=org.apache.log4j.ConsoleAppender
7 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} (%F:%L) %-5p - %m%n
9 |
10 | # API
11 | log4j.logger.com.oltpbenchmark=DEBUG
12 | log4j.logger.com.oltpbenchmark.api=DEBUG
13 |
14 | # Benchmarks
15 | log4j.logger.com.oltpbenchmark.benchmarks.tatp=INFO
16 | log4j.logger.com.oltpbenchmark.benchmarks.twitter=INFO
17 | log4j.logger.com.oltpbenchmark.benchmarks.wikipedia=INFO
18 | log4j.logger.com.oltpbenchmark.benchmarks.epinions=INFO
19 | log4j.logger.com.oltpbenchmark.benchmarks.ycsb=INFO
20 | log4j.logger.com.oltpbenchmark.benchmarks.seats=INFO
21 | log4j.logger.com.oltpbenchmark.benchmarks.linkbench=INFO
22 | log4j.logger.com.oltpbenchmark.benchmarks.sibench=INFO
23 | log4j.logger.com.oltpbenchmark.benchmarks.seats=INFO
24 | log4j.logger.com.oltpbenchmark.benchmarks.auctionmark=INFO
25 | log4j.logger.com.oltpbenchmark.benchmarks.chbenchmark=INFO
26 |
27 | # Loaders
28 | log4j.logger.com.oltpbenchmark.benchmarks.wikipedia.WikipediaLoader=INFO
29 |
30 |
31 | !==============================================================================
32 | ! log4j.properties - An example configuration properties file for log4j.
33 | !
34 | ! Logging levels are:
35 | ! DEBUG < INFO < WARN < ERROR < FATAL
36 | !==============================================================================
37 |
38 | ! turn on the internal log4j debugging flag so we can see what it is doing
39 | #log4j.debug=true
40 |
41 | !==============================================================================
42 | ! JDBC API layer call logging :
43 | ! INFO shows logging, DEBUG also shows where in code the jdbc calls were made,
44 | ! setting DEBUG to true might cause minor slow-down in some environments.
45 | ! If you experience too much slowness, use INFO instead.
46 |
47 | ! Log only the SQL that is executed.
48 | log4j.logger.jdbc.sqlonly=DEBUG,A1
49 | log4j.additivity.jdbc.sqlonly=false
50 |
--------------------------------------------------------------------------------
/benchmark/tools/dbgen:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cryptograph/stealthdb/1ca645ae1613c146d59900ce50abc873dc8a6d01/benchmark/tools/dbgen
--------------------------------------------------------------------------------
/benchmark/tools/dists.dss:
--------------------------------------------------------------------------------
1 | #
2 | # $Id: dists.dss,v 1.2 2005/01/03 20:08:58 jms Exp $
3 | #
4 | # Revision History
5 | # ===================
6 | # $Log: dists.dss,v $
7 | # Revision 1.2 2005/01/03 20:08:58 jms
8 | # change line terminations
9 | #
10 | # Revision 1.1.1.1 2004/11/24 23:31:46 jms
11 | # re-establish external server
12 | #
13 | # Revision 1.1.1.1 2003/04/03 18:54:21 jms
14 | # recreation after CVS crash
15 | #
16 | # Revision 1.1.1.1 2003/04/03 18:54:21 jms
17 | # initial checkin
18 | #
19 | #
20 | #
21 | #
22 | # distributions have the following format:
23 | #
24 | # | # comment
25 | #
26 | # Distributions are used to bias the selection of a token
27 | # based on its associated weight. The list of tokens and values
28 | # between the keywords BEGIN and END define the distribution named after
29 | # the BEGIN. A uniformly random value from [0, sum(weights)]
30 | # will be chosen and the first token whose cumulative weight is greater than
31 | # or equal to the result will be returned. In essence, the weights for each
32 | # token represent its relative weight within a distribution.
33 | #
34 | # one special token is defined: count (number of data points in the
35 | # distribution). It MUST be defined for each named distribution.
36 | #-----------------------------------------------------------------------
37 | # currently defined distributions and their use:
38 | # NAME FIELD/NOTES
39 | # ======== ==============
40 | # category parts.category
41 | # container parts.container
42 | # instruct shipping instructions
43 | # msegmnt market segment
44 | # names parts.name
45 | # nations must be ordered along with regions
46 | # nations2 stand alone nations set for use with qgen
47 | # o_prio order priority
48 | # regions must be ordered along with nations
49 | # rflag lineitems.returnflag
50 | # types parts.type
51 | # colors embedded string creation; CANNOT BE USED FOR pick_str(), agg_str() perturbs order
52 | # articles comment generation
53 | # nouns
54 | # verbs
55 | # adverbs
56 | # auxillaries
57 | # prepositions
58 | # terminators
59 | # grammar sentence formation
60 | # np
61 | # vp
62 | ###
63 | # category
64 | ###
65 | BEGIN category
66 | COUNT|5
67 | FURNITURE|1
68 | STORAGE EQUIP|1
69 | TOOLS|1
70 | MACHINE TOOLS|1
71 | OTHER|1
72 | END category
73 | ###
74 | # container
75 | ###
76 | begin p_cntr
77 | count|40
78 | SM CASE|1
79 | SM BOX|1
80 | SM BAG|1
81 | SM JAR|1
82 | SM PACK|1
83 | SM PKG|1
84 | SM CAN|1
85 | SM DRUM|1
86 | LG CASE|1
87 | LG BOX|1
88 | LG BAG|1
89 | LG JAR|1
90 | LG PACK|1
91 | LG PKG|1
92 | LG CAN|1
93 | LG DRUM|1
94 | MED CASE|1
95 | MED BOX|1
96 | MED BAG|1
97 | MED JAR|1
98 | MED PACK|1
99 | MED PKG|1
100 | MED CAN|1
101 | MED DRUM|1
102 | JUMBO CASE|1
103 | JUMBO BOX|1
104 | JUMBO BAG|1
105 | JUMBO JAR|1
106 | JUMBO PACK|1
107 | JUMBO PKG|1
108 | JUMBO CAN|1
109 | JUMBO DRUM|1
110 | WRAP CASE|1
111 | WRAP BOX|1
112 | WRAP BAG|1
113 | WRAP JAR|1
114 | WRAP PACK|1
115 | WRAP PKG|1
116 | WRAP CAN|1
117 | WRAP DRUM|1
118 | end p_cntr
119 | ###
120 | # instruct
121 | ###
122 | begin instruct
123 | count|4
124 | DELIVER IN PERSON|1
125 | COLLECT COD|1
126 | TAKE BACK RETURN|1
127 | NONE|1
128 | end instruct
129 | ###
130 | # msegmnt
131 | ###
132 | begin msegmnt
133 | count|5
134 | AUTOMOBILE|1
135 | BUILDING|1
136 | FURNITURE|1
137 | HOUSEHOLD|1
138 | MACHINERY|1
139 | end msegmnt
140 | ###
141 | # names
142 | ###
143 | begin p_names
144 | COUNT|4
145 | CLEANER|1
146 | SOAP|1
147 | DETERGENT|1
148 | EXTRA|1
149 | end p_names
150 | ###
151 | # nations
152 | # NOTE: this is a special case; the weights here are adjustments to
153 | # map correctly into the regions table, and are *NOT* cummulative
154 | # values to mimic a distribution
155 | ###
156 | begin nations
157 | count|25
158 | ALGERIA|0
159 | ARGENTINA|1
160 | BRAZIL|0
161 | CANADA|0
162 | EGYPT|3
163 | ETHIOPIA|-4
164 | FRANCE|3
165 | GERMANY|0
166 | INDIA|-1
167 | INDONESIA|0
168 | IRAN|2
169 | IRAQ|0
170 | JAPAN|-2
171 | JORDAN|2
172 | KENYA|-4
173 | MOROCCO|0
174 | MOZAMBIQUE|0
175 | PERU|1
176 | CHINA|1
177 | ROMANIA|1
178 | SAUDI ARABIA|1
179 | VIETNAM|-2
180 | RUSSIA|1
181 | UNITED KINGDOM|0
182 | UNITED STATES|-2
183 | end nations
184 | ###
185 | # nations2
186 | ###
187 | begin nations2
188 | count|25
189 | ALGERIA|1
190 | ARGENTINA|1
191 | BRAZIL|1
192 | CANADA|1
193 | EGYPT|1
194 | ETHIOPIA|1
195 | FRANCE|1
196 | GERMANY|1
197 | INDIA|1
198 | INDONESIA|1
199 | IRAN|1
200 | IRAQ|1
201 | JAPAN|1
202 | JORDAN|1
203 | KENYA|1
204 | MOROCCO|1
205 | MOZAMBIQUE|1
206 | PERU|1
207 | CHINA|1
208 | ROMANIA|1
209 | SAUDI ARABIA|1
210 | VIETNAM|1
211 | RUSSIA|1
212 | UNITED KINGDOM|1
213 | UNITED STATES|1
214 | end nations2
215 | ###
216 | # regions
217 | ###
218 | begin regions
219 | count|5
220 | AFRICA|1
221 | AMERICA|1
222 | ASIA|1
223 | EUROPE|1
224 | MIDDLE EAST|1
225 | end regions
226 | ###
227 | # o_prio
228 | ###
229 | begin o_oprio
230 | count|5
231 | 1-URGENT|1
232 | 2-HIGH|1
233 | 3-MEDIUM|1
234 | 4-NOT SPECIFIED|1
235 | 5-LOW|1
236 | end o_oprio
237 | ###
238 | # rflag
239 | ###
240 | begin rflag
241 | count|2
242 | R|1
243 | A|1
244 | end rflag
245 | ###
246 | # smode
247 | ###
248 | begin smode
249 | count|7
250 | REG AIR|1
251 | AIR|1
252 | RAIL|1
253 | TRUCK|1
254 | MAIL|1
255 | FOB|1
256 | SHIP|1
257 | end smode
258 | ###
259 | # types
260 | ###
261 | begin p_types
262 | COUNT|150
263 | STANDARD ANODIZED TIN|1
264 | STANDARD ANODIZED NICKEL|1
265 | STANDARD ANODIZED BRASS|1
266 | STANDARD ANODIZED STEEL|1
267 | STANDARD ANODIZED COPPER|1
268 | STANDARD BURNISHED TIN|1
269 | STANDARD BURNISHED NICKEL|1
270 | STANDARD BURNISHED BRASS|1
271 | STANDARD BURNISHED STEEL|1
272 | STANDARD BURNISHED COPPER|1
273 | STANDARD PLATED TIN|1
274 | STANDARD PLATED NICKEL|1
275 | STANDARD PLATED BRASS|1
276 | STANDARD PLATED STEEL|1
277 | STANDARD PLATED COPPER|1
278 | STANDARD POLISHED TIN|1
279 | STANDARD POLISHED NICKEL|1
280 | STANDARD POLISHED BRASS|1
281 | STANDARD POLISHED STEEL|1
282 | STANDARD POLISHED COPPER|1
283 | STANDARD BRUSHED TIN|1
284 | STANDARD BRUSHED NICKEL|1
285 | STANDARD BRUSHED BRASS|1
286 | STANDARD BRUSHED STEEL|1
287 | STANDARD BRUSHED COPPER|1
288 | SMALL ANODIZED TIN|1
289 | SMALL ANODIZED NICKEL|1
290 | SMALL ANODIZED BRASS|1
291 | SMALL ANODIZED STEEL|1
292 | SMALL ANODIZED COPPER|1
293 | SMALL BURNISHED TIN|1
294 | SMALL BURNISHED NICKEL|1
295 | SMALL BURNISHED BRASS|1
296 | SMALL BURNISHED STEEL|1
297 | SMALL BURNISHED COPPER|1
298 | SMALL PLATED TIN|1
299 | SMALL PLATED NICKEL|1
300 | SMALL PLATED BRASS|1
301 | SMALL PLATED STEEL|1
302 | SMALL PLATED COPPER|1
303 | SMALL POLISHED TIN|1
304 | SMALL POLISHED NICKEL|1
305 | SMALL POLISHED BRASS|1
306 | SMALL POLISHED STEEL|1
307 | SMALL POLISHED COPPER|1
308 | SMALL BRUSHED TIN|1
309 | SMALL BRUSHED NICKEL|1
310 | SMALL BRUSHED BRASS|1
311 | SMALL BRUSHED STEEL|1
312 | SMALL BRUSHED COPPER|1
313 | MEDIUM ANODIZED TIN|1
314 | MEDIUM ANODIZED NICKEL|1
315 | MEDIUM ANODIZED BRASS|1
316 | MEDIUM ANODIZED STEEL|1
317 | MEDIUM ANODIZED COPPER|1
318 | MEDIUM BURNISHED TIN|1
319 | MEDIUM BURNISHED NICKEL|1
320 | MEDIUM BURNISHED BRASS|1
321 | MEDIUM BURNISHED STEEL|1
322 | MEDIUM BURNISHED COPPER|1
323 | MEDIUM PLATED TIN|1
324 | MEDIUM PLATED NICKEL|1
325 | MEDIUM PLATED BRASS|1
326 | MEDIUM PLATED STEEL|1
327 | MEDIUM PLATED COPPER|1
328 | MEDIUM POLISHED TIN|1
329 | MEDIUM POLISHED NICKEL|1
330 | MEDIUM POLISHED BRASS|1
331 | MEDIUM POLISHED STEEL|1
332 | MEDIUM POLISHED COPPER|1
333 | MEDIUM BRUSHED TIN|1
334 | MEDIUM BRUSHED NICKEL|1
335 | MEDIUM BRUSHED BRASS|1
336 | MEDIUM BRUSHED STEEL|1
337 | MEDIUM BRUSHED COPPER|1
338 | LARGE ANODIZED TIN|1
339 | LARGE ANODIZED NICKEL|1
340 | LARGE ANODIZED BRASS|1
341 | LARGE ANODIZED STEEL|1
342 | LARGE ANODIZED COPPER|1
343 | LARGE BURNISHED TIN|1
344 | LARGE BURNISHED NICKEL|1
345 | LARGE BURNISHED BRASS|1
346 | LARGE BURNISHED STEEL|1
347 | LARGE BURNISHED COPPER|1
348 | LARGE PLATED TIN|1
349 | LARGE PLATED NICKEL|1
350 | LARGE PLATED BRASS|1
351 | LARGE PLATED STEEL|1
352 | LARGE PLATED COPPER|1
353 | LARGE POLISHED TIN|1
354 | LARGE POLISHED NICKEL|1
355 | LARGE POLISHED BRASS|1
356 | LARGE POLISHED STEEL|1
357 | LARGE POLISHED COPPER|1
358 | LARGE BRUSHED TIN|1
359 | LARGE BRUSHED NICKEL|1
360 | LARGE BRUSHED BRASS|1
361 | LARGE BRUSHED STEEL|1
362 | LARGE BRUSHED COPPER|1
363 | ECONOMY ANODIZED TIN|1
364 | ECONOMY ANODIZED NICKEL|1
365 | ECONOMY ANODIZED BRASS|1
366 | ECONOMY ANODIZED STEEL|1
367 | ECONOMY ANODIZED COPPER|1
368 | ECONOMY BURNISHED TIN|1
369 | ECONOMY BURNISHED NICKEL|1
370 | ECONOMY BURNISHED BRASS|1
371 | ECONOMY BURNISHED STEEL|1
372 | ECONOMY BURNISHED COPPER|1
373 | ECONOMY PLATED TIN|1
374 | ECONOMY PLATED NICKEL|1
375 | ECONOMY PLATED BRASS|1
376 | ECONOMY PLATED STEEL|1
377 | ECONOMY PLATED COPPER|1
378 | ECONOMY POLISHED TIN|1
379 | ECONOMY POLISHED NICKEL|1
380 | ECONOMY POLISHED BRASS|1
381 | ECONOMY POLISHED STEEL|1
382 | ECONOMY POLISHED COPPER|1
383 | ECONOMY BRUSHED TIN|1
384 | ECONOMY BRUSHED NICKEL|1
385 | ECONOMY BRUSHED BRASS|1
386 | ECONOMY BRUSHED STEEL|1
387 | ECONOMY BRUSHED COPPER|1
388 | PROMO ANODIZED TIN|1
389 | PROMO ANODIZED NICKEL|1
390 | PROMO ANODIZED BRASS|1
391 | PROMO ANODIZED STEEL|1
392 | PROMO ANODIZED COPPER|1
393 | PROMO BURNISHED TIN|1
394 | PROMO BURNISHED NICKEL|1
395 | PROMO BURNISHED BRASS|1
396 | PROMO BURNISHED STEEL|1
397 | PROMO BURNISHED COPPER|1
398 | PROMO PLATED TIN|1
399 | PROMO PLATED NICKEL|1
400 | PROMO PLATED BRASS|1
401 | PROMO PLATED STEEL|1
402 | PROMO PLATED COPPER|1
403 | PROMO POLISHED TIN|1
404 | PROMO POLISHED NICKEL|1
405 | PROMO POLISHED BRASS|1
406 | PROMO POLISHED STEEL|1
407 | PROMO POLISHED COPPER|1
408 | PROMO BRUSHED TIN|1
409 | PROMO BRUSHED NICKEL|1
410 | PROMO BRUSHED BRASS|1
411 | PROMO BRUSHED STEEL|1
412 | PROMO BRUSHED COPPER|1
413 | end p_types
414 | ###
415 | # colors
416 | # NOTE: This distribution CANNOT be used by pick_str(), since agg_str() perturbs its order
417 | ###
418 | begin colors
419 | COUNT|92
420 | almond|1
421 | antique|1
422 | aquamarine|1
423 | azure|1
424 | beige|1
425 | bisque|1
426 | black|1
427 | blanched|1
428 | blue|1
429 | blush|1
430 | brown|1
431 | burlywood|1
432 | burnished|1
433 | chartreuse|1
434 | chiffon|1
435 | chocolate|1
436 | coral|1
437 | cornflower|1
438 | cornsilk|1
439 | cream|1
440 | cyan|1
441 | dark|1
442 | deep|1
443 | dim|1
444 | dodger|1
445 | drab|1
446 | firebrick|1
447 | floral|1
448 | forest|1
449 | frosted|1
450 | gainsboro|1
451 | ghost|1
452 | goldenrod|1
453 | green|1
454 | grey|1
455 | honeydew|1
456 | hot|1
457 | indian|1
458 | ivory|1
459 | khaki|1
460 | lace|1
461 | lavender|1
462 | lawn|1
463 | lemon|1
464 | light|1
465 | lime|1
466 | linen|1
467 | magenta|1
468 | maroon|1
469 | medium|1
470 | metallic|1
471 | midnight|1
472 | mint|1
473 | misty|1
474 | moccasin|1
475 | navajo|1
476 | navy|1
477 | olive|1
478 | orange|1
479 | orchid|1
480 | pale|1
481 | papaya|1
482 | peach|1
483 | peru|1
484 | pink|1
485 | plum|1
486 | powder|1
487 | puff|1
488 | purple|1
489 | red|1
490 | rose|1
491 | rosy|1
492 | royal|1
493 | saddle|1
494 | salmon|1
495 | sandy|1
496 | seashell|1
497 | sienna|1
498 | sky|1
499 | slate|1
500 | smoke|1
501 | snow|1
502 | spring|1
503 | steel|1
504 | tan|1
505 | thistle|1
506 | tomato|1
507 | turquoise|1
508 | violet|1
509 | wheat|1
510 | white|1
511 | yellow|1
512 | end colors
513 | ################
514 | ################
515 | ## psuedo text distributions
516 | ################
517 | ################
518 | ###
519 | # nouns
520 | ###
521 | BEGIN nouns
522 | COUNT|45
523 | packages|40
524 | requests|40
525 | accounts|40
526 | deposits|40
527 | foxes|20
528 | ideas|20
529 | theodolites|20
530 | pinto beans|20
531 | instructions|20
532 | dependencies|10
533 | excuses|10
534 | platelets|10
535 | asymptotes|10
536 | courts|5
537 | dolphins|5
538 | multipliers|1
539 | sauternes|1
540 | warthogs|1
541 | frets|1
542 | dinos|1
543 | attainments|1
544 | somas|1
545 | Tiresias|1
546 | patterns|1
547 | forges|1
548 | braids|1
549 | frays|1
550 | warhorses|1
551 | dugouts|1
552 | notornis|1
553 | epitaphs|1
554 | pearls|1
555 | tithes|1
556 | waters|1
557 | orbits|1
558 | gifts|1
559 | sheaves|1
560 | depths|1
561 | sentiments|1
562 | decoys|1
563 | realms|1
564 | pains|1
565 | grouches|1
566 | escapades|1
567 | hockey players|1
568 | END nouns
569 | ###
570 | # verbs
571 | ###
572 | BEGIN verbs
573 | COUNT|40
574 | sleep|20
575 | wake|20
576 | are|20
577 | cajole|20
578 | haggle|20
579 | nag|10
580 | use|10
581 | boost|10
582 | affix|5
583 | detect|5
584 | integrate|5
585 | maintain|1
586 | nod|1
587 | was|1
588 | lose|1
589 | sublate|1
590 | solve|1
591 | thrash|1
592 | promise|1
593 | engage|1
594 | hinder|1
595 | print|1
596 | x-ray|1
597 | breach|1
598 | eat|1
599 | grow|1
600 | impress|1
601 | mold|1
602 | poach|1
603 | serve|1
604 | run|1
605 | dazzle|1
606 | snooze|1
607 | doze|1
608 | unwind|1
609 | kindle|1
610 | play|1
611 | hang|1
612 | believe|1
613 | doubt|1
614 | END verbs
615 | ###
616 | # adverbs
617 | ##
618 | BEGIN adverbs
619 | COUNT|28
620 | sometimes|1
621 | always|1
622 | never|1
623 | furiously|50
624 | slyly|50
625 | carefully|50
626 | blithely|40
627 | quickly|30
628 | fluffily|20
629 | slowly|1
630 | quietly|1
631 | ruthlessly|1
632 | thinly|1
633 | closely|1
634 | doggedly|1
635 | daringly|1
636 | bravely|1
637 | stealthily|1
638 | permanently|1
639 | enticingly|1
640 | idly|1
641 | busily|1
642 | regularly|1
643 | finally|1
644 | ironically|1
645 | evenly|1
646 | boldly|1
647 | silently|1
648 | END adverbs
649 | ###
650 | # articles
651 | ##
652 | BEGIN articles
653 | COUNT|3
654 | the|50
655 | a|20
656 | an|5
657 | END articles
658 | ###
659 | # prepositions
660 | ##
661 | BEGIN prepositions
662 | COUNT|47
663 | about|50
664 | above|50
665 | according to|50
666 | across|50
667 | after|50
668 | against|40
669 | along|40
670 | alongside of|30
671 | among|30
672 | around|20
673 | at|10
674 | atop|1
675 | before|1
676 | behind|1
677 | beneath|1
678 | beside|1
679 | besides|1
680 | between|1
681 | beyond|1
682 | by|1
683 | despite|1
684 | during|1
685 | except|1
686 | for|1
687 | from|1
688 | in place of|1
689 | inside|1
690 | instead of|1
691 | into|1
692 | near|1
693 | of|1
694 | on|1
695 | outside|1
696 | over|1
697 | past|1
698 | since|1
699 | through|1
700 | throughout|1
701 | to|1
702 | toward|1
703 | under|1
704 | until|1
705 | up|1
706 | upon|1
707 | whithout|1
708 | with|1
709 | within|1
710 | END prepositions
711 | ###
712 | # auxillaries
713 | ##
714 | BEGIN auxillaries
715 | COUNT|18
716 | do|1
717 | may|1
718 | might|1
719 | shall|1
720 | will|1
721 | would|1
722 | can|1
723 | could|1
724 | should|1
725 | ought to|1
726 | must|1
727 | will have to|1
728 | shall have to|1
729 | could have to|1
730 | should have to|1
731 | must have to|1
732 | need to|1
733 | try to|1
734 | END auxiallaries
735 | ###
736 | # terminators
737 | ##
738 | BEGIN terminators
739 | COUNT|6
740 | .|50
741 | ;|1
742 | :|1
743 | ?|1
744 | !|1
745 | --|1
746 | END terminators
747 | ###
748 | # adjectives
749 | ##
750 | BEGIN adjectives
751 | COUNT|29
752 | special|20
753 | pending|20
754 | unusual|20
755 | express|20
756 | furious|1
757 | sly|1
758 | careful|1
759 | blithe|1
760 | quick|1
761 | fluffy|1
762 | slow|1
763 | quiet|1
764 | ruthless|1
765 | thin|1
766 | close|1
767 | dogged|1
768 | daring|1
769 | brave|1
770 | stealthy|1
771 | permanent|1
772 | enticing|1
773 | idle|1
774 | busy|1
775 | regular|50
776 | final|40
777 | ironic|40
778 | even|30
779 | bold|20
780 | silent|10
781 | END adjectives
782 | ###
783 | # grammar
784 | # first level grammar. N=noun phrase, V=verb phrase,
785 | # P=prepositional phrase, T=setence termination
786 | ##
787 | BEGIN grammar
788 | COUNT|5
789 | N V T|3
790 | N V P T|3
791 | N V N T|3
792 | N P V N T|1
793 | N P V P T|1
794 | END grammar
795 | ###
796 | # NP
797 | # second level grammar. Noun phrases. N=noun, A=article,
798 | # J=adjective, D=adverb
799 | ##
800 | BEGIN np
801 | COUNT|4
802 | N|10
803 | J N|20
804 | J, J N|10
805 | D J N|50
806 | END np
807 | ###
808 | # VP
809 | # second level grammar. Verb phrases. V=verb, X=auxiallary,
810 | # D=adverb
811 | ##
812 | BEGIN vp
813 | COUNT|4
814 | V|30
815 | X V|1
816 | V D|40
817 | X V D|1
818 | END vp
819 | ###
820 | # Q13
821 | # Substitution parameters for Q13
822 | ##
823 | BEGIN Q13a
824 | COUNT|4
825 | special|20
826 | pending|20
827 | unusual|20
828 | express|20
829 | END Q13a
830 | BEGIN Q13b
831 | COUNT|4
832 | packages|40
833 | requests|40
834 | accounts|40
835 | deposits|40
836 | END Q13b
837 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM postgres:latest
2 |
3 | RUN apt-get update \
4 | && apt-get install --yes \
5 | nasm \
6 | build-essential \
7 | ocaml \
8 | automake \
9 | autoconf \
10 | git \
11 | libtool \
12 | wget \
13 | python \
14 | #Have to use downgraded openSSL headers due to compilation errors.
15 | libssl1.0-dev \
16 | libcurl4-openssl-dev \
17 | protobuf-compiler \
18 | libprotobuf-dev \
19 | postgresql-server-dev-all \
20 | && rm -rf /var/lib/apt/lists/*
21 |
22 | COPY sgx-deps.mk /opt/Makefile
23 | WORKDIR /opt
24 | RUN make
25 |
26 | RUN git clone https://github.com/cryptograph/stealthdb /home/stealthDB
27 |
28 | WORKDIR /home/stealthDB
29 | RUN make && make install
30 |
--------------------------------------------------------------------------------
/docker/sgx-deps.mk:
--------------------------------------------------------------------------------
1 | #Builds Intel SGX libraries and binaries required by StealthDB.
2 | #Does not include those corresponding to the AESMD service and SGX driver.
3 |
4 | SGX_MODE ?= HW
5 | export SGX_MODE
6 |
7 | USE_OPT_LIBS = 1
8 | export USE_OPT_LIBS
9 |
10 | SDK_REV := sgx_2.0
11 | SDK_SRC := $(SDK_REV)
12 | SDK_BUILD_DIR := $(SDK_SRC)/build/linux
13 | SDK_INSTALL_PATH := /opt/intel/sgxsdk
14 |
15 | SGX_BUILD_LIBS := libsgx_trts.a libsgx_tservice.a libsgx_tstdc.a libsgx_tcrypto.a libsgx_tstdcxx.a libsgx_tcxx.a
16 | SGX_RUNTIME_LIBS := libsgx_urts.so libsgx_uae_service.so
17 | SGX_LIBS_INSTALL_DIR := $(SDK_INSTALL_PATH)/lib64
18 |
19 | SGX_BINS := sgx_sign sgx_edger8r
20 | SGX_BINS_INSTALL_DIR := $(SDK_INSTALL_PATH)/bin/x64
21 |
22 | SGX_HEADERS_INSTALL_DIR := $(SDK_INSTALL_PATH)/include
23 |
24 | .PHONY: all
25 | all: $(addprefix $(SGX_LIBS_INSTALL_DIR)/, $(SGX_BUILD_LIBS) $(SGX_RUNTIME_LIBS)) $(addprefix $(SGX_BINS_INSTALL_DIR)/, $(SGX_BINS)) sgx_headers
26 |
27 | $(SGX_LIBS_INSTALL_DIR)/libsgx_%: $(SDK_BUILD_DIR)/libsgx_% | $(SGX_LIBS_INSTALL_DIR)
28 | cp $(SDK_BUILD_DIR)/libsgx_$* $@
29 |
30 | $(SDK_BUILD_DIR)/libsgx_%.a: | $(SDK_SRC)
31 | $(MAKE) -C $(SDK_SRC)/sdk $*
32 |
33 | $(SDK_BUILD_DIR)/libsgx_%.so: | $(SDK_SRC)
34 | $(MAKE) -C $(SDK_SRC)/psw CXXFLAGS="-Wno-unused-parameter -fPIC" $*
35 |
36 | $(SGX_BINS_INSTALL_DIR)/sgx_%: $(SDK_BUILD_DIR)/sgx_% | $(SGX_BINS_INSTALL_DIR)
37 | cp $(SDK_BUILD_DIR)/sgx_$* $@
38 |
39 | $(SDK_BUILD_DIR)/sgx_sign: | $(SDK_SRC)
40 | $(MAKE) -C $(SDK_SRC)/sdk signtool
41 |
42 | $(SDK_BUILD_DIR)/sgx_edger8r: | $(SDK_SRC)
43 | $(MAKE) -C $(SDK_SRC)/sdk edger8r
44 |
45 | .PHONY: sgx_headers
46 | sgx_headers: | $(SGX_HEADERS_INSTALL_DIR)
47 | cp -R $(SDK_SRC)/common/inc/* $|
48 |
49 | $(SGX_HEADERS_INSTALL_DIR) $(SGX_BINS_INSTALL_DIR) $(SGX_LIBS_INSTALL_DIR):
50 | mkdir -p $@
51 |
52 | $(SDK_SRC): $(SDK_REV).git
53 | git --git-dir=$< fetch origin master
54 | git --git-dir=$< archive --prefix=$@/ HEAD | tar -x
55 | ifeq ($(USE_OPT_LIBS),1)
56 | cd $@ && ./download_prebuilt.sh
57 | endif
58 |
59 | $(SDK_REV).git:
60 | git clone --depth 1 --branch $(SDK_REV) --bare https://github.com/01org/linux-sgx.git $@
61 |
62 | .PHONY: uninstall
63 | uninstall:
64 | $(RM) $(addprefix $(SGX_LIBS_INSTALL_DIR), $(SGX_LIBS))\
65 | $(addprefix $(SGX_BINS_INSTALL_DIR), $(SGX_BINS))\
66 | -r $(SGX_HEADERS_INSTALL_DIR)
67 |
68 | .PHONY: clean
69 | clean:
70 | $(RM) -r $(SDK_SRC) $(SDK_REV)
71 |
--------------------------------------------------------------------------------
/docs/developer/dirlayout.md:
--------------------------------------------------------------------------------
1 | # Source Directory Layout
2 |
3 | * `src` contains the source code for the enclave as well as the PostgreSQL interface.
4 | * `docker` contains all that is necessary to build and run a docker container.
5 | * `benchmark` and `test` contain tools to respectively benchmark and test the extension.
6 |
--------------------------------------------------------------------------------
/docs/user/README.md:
--------------------------------------------------------------------------------
1 | The installation process is described in detail [here](install.md).
2 |
3 | #Supported Data Types and Operations
4 |
5 | * [Numeric Types](numeric.md)
6 | * [Character Types](character.md)
7 | * [Date/Time Types](datetime.md)
8 | * [StealthDB defined functions](utils.md)
9 |
10 | For each supported type `x`, we provide a corresponding encrypted type `enc_x`. All operations valid for type `x` are valid for `enc_x`.
11 |
12 |
--------------------------------------------------------------------------------
/docs/user/character.md:
--------------------------------------------------------------------------------
1 | # Supported Character Types
2 |
3 | ## Text
4 |
5 | ### Types
6 |
7 | * text
8 |
9 | ### Functions
10 |
11 | * Relational operators: `!=`, `<>`, `=`, `<=`, `<`, `>`, `>=`
12 | * BETWEEN x AND y
13 | * NOT BETWEEN x AND y
14 | * BETWEEN SYMMETRIC x AND y
15 | * NOT BETWEEN SYMMETRIC x AND y
16 | * IS DISTINCT FROM b
17 | * IS NOT DISTINCT FROM b
18 | * expression IS NULL
19 | * expression IS NOT NULL
20 | * expression ISNULL
21 | * expression NOTNULL
22 |
23 | * Mathematical Operators: +, -, \*, /, %
24 |
25 | * String functions: `||`, `LIKE`, `SUBSTRING`
26 |
--------------------------------------------------------------------------------
/docs/user/datetime.md:
--------------------------------------------------------------------------------
1 | # Supported Date/Time Types
2 |
3 | ## Timestamp
4 |
5 | ### Types
6 |
7 | * timestamp
8 |
9 | ### Functions
10 |
11 | * Relational operators: `!=`, `<>`, `=`, `<=`, `<`, `>`, `>=`
12 | * BETWEEN x AND y
13 | * NOT BETWEEN x AND y
14 | * BETWEEN SYMMETRIC x AND y
15 | * NOT BETWEEN SYMMETRIC x AND y
16 | * IS DISTINCT FROM b
17 | * IS NOT DISTINCT FROM b
18 | * expression IS NULL
19 | * expression IS NOT NULL
20 | * expression ISNULL
21 | * expression NOTNULL
22 |
23 | * date_part with the 'field' argument being 'year'
24 |
--------------------------------------------------------------------------------
/docs/user/install.md:
--------------------------------------------------------------------------------
1 | # The StealthDB Installation Process
2 |
3 | ## 1. a) Building and Installing StealthDB on Ubuntu
4 |
5 | The build process, which is kicked off by running `make`, consists of the building the enclave used by StealthDB as well as the interface it presents to PostgreSQL. The enclave is built as a shared library (`enclave.so`) and is signed using a signing key generated during the build process. The extension itself is also a shared library (`encdb.so`). All the build artifacts can be found in the `build/` folder.
6 |
7 | `sudo make install` starts the installation process, which involes copying the artifacts in the `build` directory into various system and PostgreSQL directories.
8 |
9 | ## 1. b) Building and Installing StealthDB in a Debian-based Docker container
10 |
11 | To build the docker image, we bypass the `install_dependencies.sh` script and specify that the Dockerfile install dependencies and clone the StealthDB GitHub repository. This built image is then run, and we specify that the running container use the Intel SGX driver (installed on the host kernel) and Intel AESMD service (running on the host) using the `--device=/dev/isgx` and `--volume=/var/run/aesmd/aesm.socket` flags.
12 |
13 | As a result, we need only build in the docker container a subset of all the Intel SGX artifacts. The Dockerfile invokes the `sgx-deps.mk` Makefile to do exactly this, and proceeds to build StealthDB inside the running container through a process analogous to the one described in Section 1. a).
14 |
15 | ## Note
16 |
17 | The enclave created by the above build process is created with SGX_DEBUG=1 flag and is signed with an automatically generated signing key. It is thus a debug enclave. To use an enclave in production, the signing key must be whitelisted by Intel.
18 |
19 |
--------------------------------------------------------------------------------
/docs/user/numeric.md:
--------------------------------------------------------------------------------
1 | # Supported Numeric Types
2 |
3 | ## Integers
4 |
5 | ### Types
6 |
7 | * int4
8 |
9 | ### Functions
10 |
11 | * Relational operators: `!=`, `<>`, `=`, `<=`, `<`, `>`, `>=`
12 | * BETWEEN x AND y
13 | * NOT BETWEEN x AND y
14 | * BETWEEN SYMMETRIC x AND y
15 | * NOT BETWEEN SYMMETRIC x AND y
16 | * IS DISTINCT FROM b
17 | * IS NOT DISTINCT FROM b
18 | * expression IS NULL
19 | * expression IS NOT NULL
20 | * expression ISNULL
21 | * expression NOTNULL
22 |
23 | * Mathematical Operators: +, -, \*, /, %
24 | * Aggregate: AVG, MIN, MAX, SUM
25 |
26 | ## Floating Point
27 |
28 | ### Types
29 |
30 | * float4
31 |
32 | ### Functions
33 |
34 | * Relational operators: `!=`, `<>`, `=`, `<=`, `<`, `>`, `>=`
35 | * BETWEEN x AND y
36 | * NOT BETWEEN x AND y
37 | * BETWEEN SYMMETRIC x AND y
38 | * NOT BETWEEN SYMMETRIC x AND y
39 | * IS DISTINCT FROM b
40 | * IS NOT DISTINCT FROM b
41 | * expression IS NULL
42 | * expression IS NOT NULL
43 | * expression ISNULL
44 | * expression NOTNULL
45 |
46 | * Mathematical Operators: +, -, \*, /, %
47 | * Aggregate: AVG, SUM
48 |
--------------------------------------------------------------------------------
/docs/user/oblvs.md:
--------------------------------------------------------------------------------
1 | ## Oblivious Operators
2 |
3 | Operations such as addition, comparison, mutliplication that form the building blocks for queries are carried out inside an SGX enclave. While this is done to ensure confidentiality of the operands, the enclave is still vulnerable to side channel timing attacks.
4 |
5 | We presently have oblivious implementations of operations involving the enc_int4 type. To enable these, run `make` with the `OBLVS=1` option. By default, `OBLVS` is 0.
6 |
--------------------------------------------------------------------------------
/docs/user/utils.md:
--------------------------------------------------------------------------------
1 | # StealthDB special functions
2 | * ```
3 | generate_key()
4 | ```
5 | Generates a new key, seals it with SGX hardware key and appends to the local file DATA_FILENAME. All computations with the secret data are performed inside an enclave. The function returns the serial number of the key (note: temporarily, serial number is always 0).
6 |
7 | * ```
8 | load_key(int4)
9 | ```
10 | Reads sealed key from the local file DATA_FILENAME, unseals it and uploads into an enclave as the master key. The argument is a serial number of a previously generated key (note: temporarily, serial number is always 0).
11 |
12 | * ```
13 | enable_debug_mode(int4)
14 | ```
15 | Enables/disables encryption of PostgreSQL datatypes and their conversion into encrypted ones, it also allows automatically decrypt the query result. The argument is 0 (disable) or 1 (enable). This function makes the system insecure, because a malicious DBMS can potentially extract and decrypt all encrypted values. Eventually, the function will be moved to an independent enclave according to the paper.
16 | * ```
17 | pg_enc_int4_encrypt(int4)
18 | ```
19 | Encrypts an int4 with the master key, returns enc_int4 element.
20 | * ```
21 | pg_enc_int4_decrypt(enc_int4)
22 | ```
23 | Decrypts an enc_int4 element with the master key and returns int4.
24 | * ```
25 | pg_enc_float4_encrypt(float4)
26 | ```
27 | Encrypts a float4 with the master key, returns enc_float4 element.
28 | * ```
29 | pg_enc_float4_decrypt(enc_float4)
30 | ```
31 | Decrypts an enc_float4 element with the master key and returns float4.
32 | * ```
33 | pg_enc_text_encrypt(varchar)
34 | ```
35 | Encrypts a string with the master key, returns enc_text element as a string (note: temporarily, the length of the input string is limited by 1024 characters)
36 | * ```
37 | pg_enc_text_decrypt(enc_text)
38 | ```
39 | Decrypts an enc_text element with the master key and returns a string.
40 | * ```
41 | pg_enc_timestamp_enrypt(timestamp)
42 | ```
43 | Encrypts the timestamp with the master key, returns enc_timestamp element.
44 | * ```
45 | pg_enc_timestamp_decrypt(enc_timestamp)
46 | ```
47 | Decrypts an enc_timestamp element with the master key and returns timestamp.
48 |
49 |
--------------------------------------------------------------------------------
/src/enclave.mk:
--------------------------------------------------------------------------------
1 | include vars.mk
2 | -include status.mk
3 |
4 | SIGNDATA := $(ENCLAVE_DIR)/$(ENCLAVE_NAME).signdata
5 | MRENCLAVE := $(ENCLAVE_DIR)/$(ENCLAVE_NAME).mrenclave
6 | SIGNED_TARGET := $(ENCLAVE_DIR)/$(ENCLAVE_NAME).signed.so
7 | ENCLAVE_CONFIG := $(ENCLAVE_DIR)/$(ENCLAVE_NAME).config.xml
8 | SGX_ENCLAVE_SIGNER := $(SDK_INSTALL_PATH)/bin/x64/sgx_sign
9 |
10 | DEBUG_ENCLAVE_NAME := $(ENCLAVE_NAME).debug
11 | DEBUG_SIGNDATA := $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).signdata
12 | DEBUG_SIGNED_TARGET := $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).signed.so
13 | DEBUG_ENCLAVE_CONFIG := $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).config.xml
14 |
15 | CXX_SRCS := $(wildcard tools/*.cpp) $(filter-out $(wildcard $(ENCLAVE_DIR)/*int32*.cpp),$(wildcard $(ENCLAVE_DIR)/*.cpp))
16 | ifeq ($(OBLVS), 1)
17 | BUILD_TARGET = oblvs
18 | CXX_SRCS += $(ENCLAVE_DIR)/enc_oblvs_int32_ops.cpp
19 | else
20 | BUILD_TARGET = non_oblvs
21 | CXX_SRCS += $(ENCLAVE_DIR)/enc_int32_ops.cpp
22 | endif
23 | CXX_OBJS := $(CXX_SRCS:.cpp=.o)
24 |
25 | TARGET := $(ENCLAVE_DIR)/$(ENCLAVE_NAME).so
26 |
27 | ifndef BUILT_TARGET
28 | BUILT_TARGET = $(BUILD_TARGET)
29 | endif
30 |
31 | ASM_SRCS := $(wildcard tools/*.S)
32 | ASM_OBJS := $(ASM_SRCS:.S=.o)
33 |
34 | C_SRCS := $(wildcard tools/*.c)
35 | C_OBJS := $(C_SRCS:.c=.o)
36 |
37 | CPPFLAGS := $(addprefix -I, include $(SGX_INCLUDE_PATH) $(SGX_INCLUDE_PATH)/tlibc)
38 |
39 | FLAGS:= -m64 -O0 -g -fvisibility=hidden -fpie -fstack-protector -fno-builtin-printf -Wall -Wextra -Wpedantic
40 | CFLAGS := $(FLAGS) $(CPPFLAGS) -nostdinc -std=c11
41 | CXXFLAGS := $(FLAGS) $(CPPFLAGS) -nostdinc++ -std=c++11
42 |
43 | LDFLAGS := \
44 | -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SDK_INSTALL_PATH)/lib64\
45 | -Wl,--whole-archive -lsgx_trts -Wl,--no-whole-archive \
46 | -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -lsgx_tservice -Wl,--end-group \
47 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
48 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
49 | -Wl,--defsym,__ImageBase=0 \
50 | -Wl,--version-script=$(ENCLAVE_DIR)/enclave.lds
51 |
52 | .PHONY: check_target
53 | check_target:
54 | ifneq ($(BUILT_TARGET),$(BUILD_TARGET))
55 | $(error "A different target was built earlier. Run 'make clean' first.")
56 | endif
57 | @echo "BUILT_TARGET=$(BUILD_TARGET)" > status.mk
58 |
59 | .PHONY: all
60 | all: check_target $(DEBUG_SIGNED_TARGET) $(TARGET)
61 |
62 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).key:
63 | @openssl genrsa -out $@ -3 3072
64 |
65 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).pub: %.pub: %.key
66 | @openssl rsa -out $@ -in $< -pubout
67 |
68 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).sig: %.sig: %.signdata %.key
69 | @openssl dgst -sha256 -out $@ -sign $*.key $*.signdata
70 |
71 | $(ENCLAVE_DIR)/enclave_t.c: $(SGX_EDGER8R) $(ENCLAVE_DIR)/enclave.edl
72 | @cd $(ENCLAVE_DIR) && $(SGX_EDGER8R) --trusted enclave.edl
73 | @mv $(ENCLAVE_DIR)/enclave_t.h include/enclave
74 | @echo "GEN => $@"
75 |
76 | $(ENCLAVE_DIR)/enclave_t.o: $(ENCLAVE_DIR)/enclave_t.c
77 | @$(CC) -Iinclude/enclave $(CFLAGS) -c $< -o $@
78 | @echo "CC <= $<"
79 |
80 | $(C_OBJS): %.o: %.c
81 | @$(CC) $(CFLAGS) -c $< -o $@
82 | @echo "CC <= $<"
83 |
84 | $(CXX_OBJS): %.o: %.cpp
85 | @$(CXX) $(CXXFLAGS) -c $< -o $@
86 | @echo "CXX <= $<"
87 |
88 | $(ASM_OBJS): %.o: %.S
89 | @nasm -f elf64 $< -o $@
90 | @echo "NASM <= $<"
91 |
92 | $(TARGET): $(ENCLAVE_DIR)/enclave_t.o $(CXX_OBJS) $(ASM_OBJS) $(C_OBJS)
93 | @$(CXX) $^ -o $@ $(LDFLAGS)
94 | @echo "LINK => $@"
95 |
96 | $(DEBUG_ENCLAVE_CONFIG): $(ENCLAVE_CONFIG)
97 | @sed -e 's@1@0@' $< > $@
98 |
99 | $(SIGNDATA) $(DEBUG_SIGNDATA): %.signdata: $(TARGET) %.config.xml | $(SGX_SIGN)
100 | $(SGX_ENCLAVE_SIGNER) gendata -out $@ -enclave $(TARGET) -config $*.config.xml
101 | @echo "GENDATA => $@"
102 |
103 | $(DEBUG_SIGNED_TARGET): %.signed.so: $(TARGET) %.pub %.sig %.signdata
104 | @$(SGX_ENCLAVE_SIGNER) catsig -enclave $(TARGET) -unsigned $*.signdata -out $@ -config $*.config.xml -key $*.pub -sig $*.sig
105 | cp $(DEBUG_SIGNED_TARGET) $(BUILD_DIR)
106 | @echo "SIGN => $@"
107 |
108 | .PHONY: install
109 | install:
110 | @if [ -e $(SIGNED_TARGET) ]; then cp $(SIGNED_TARGET) $(STEALTHDIR)/$(ENCLAVE_NAME).signed.so; fi
111 | @if [ -e $(DEBUG_SIGNED_TARGET) ]; then cp $(DEBUG_SIGNED_TARGET) $(STEALTHDIR)/$(ENCLAVE_NAME).signed.so; fi
112 | @echo cp $(BUILD_DIR)/$(DEBUG_ENCLAVE_NAME).signed.so $(STEALTHDIR)/$(ENCLAVE_NAME).signed.so;
113 |
114 | .PHONY: clean
115 | clean:
116 | @$(RM) status.mk *.so \
117 | $(ASM_OBJS) $(CXX_OBJS) $(TARGET) \
118 | $(SIGNDATA) $(MRENCLAVE) $(SIGNED_TARGET) \
119 | $(ENCLAVE_DIR)/enclave_t.* \
120 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).key \
121 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).pub \
122 | $(ENCLAVE_DIR)/$(DEBUG_ENCLAVE_NAME).sig \
123 | $(DEBUG_SIGNDATA) $(DEBUG_SIGNED_TARGET)
124 |
--------------------------------------------------------------------------------
/src/enclave/enc_float32_ops.cpp:
--------------------------------------------------------------------------------
1 | #include "enclave/enc_float32_ops.hpp"
2 |
3 | /* Compare two aes_gcm-encrypted floats
4 | @input: uint8_t array - encrypted lhs
5 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
6 | SGX_AESGCM_MAC_SIZE = 32)
7 | uint8_t array - encrypted rhs
8 | size_t - length of
9 | encrypted rhs (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
10 | uint8_t array - which contains the output 1 (if lhs > rhs). -1 (if lhs
11 | < rhs), 0 (if lhs == rhs) size_t - length of out (INT64_LENGTH = 4)
12 |
13 | @return:
14 | * SGX_error, if there was an error during decryption
15 | */
16 | int enc_float32_cmp(uint8_t* in1,
17 | size_t in1_size,
18 | uint8_t* in2,
19 | size_t in2_size,
20 | uint8_t* out,
21 | size_t out_size)
22 | {
23 | int result, resp;
24 | union_float4 lhs, rhs;
25 |
26 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
27 | if (resp != SGX_SUCCESS)
28 | return resp;
29 |
30 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
31 | if (resp != SGX_SUCCESS)
32 | return resp;
33 |
34 | result = (lhs.val == rhs.val) ? 0 : (lhs.val < rhs.val) ? -1 : 1;
35 |
36 | memcpy(out, &result, out_size);
37 |
38 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
39 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
40 |
41 | return resp;
42 | }
43 |
44 | /* Add two aes_gcm-encrypted floats
45 | @input: uint8_t array - encrypted lhs
46 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
47 | SGX_AESGCM_MAC_SIZE = 32)
48 | uint8_t array - encrypted rhs
49 | size_t - length of
50 | encrypted rhs (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
51 | uint8_t array - encrypted out
52 | size_t - length of encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH +
53 | SGX_AESGCM_MAC_SIZE = 32)
54 | @return:
55 | * SGX_error, if there was an error during encryption/decryption
56 | 0, otherwise
57 | */
58 | /* comment from PSQL code
59 | * There isn't any way to check for underflow of addition/subtraction
60 | * because numbers near the underflow value have already been rounded to
61 | * the point where we can't detect that the two values were originally
62 | * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
63 | * 1.4013e-45.
64 | * we have only 4 bytes for float4 datatype
65 | * we can check if the out size is less 8^4
66 | *
67 | */
68 | int enc_float32_add(uint8_t* in1,
69 | size_t in1_size,
70 | uint8_t* in2,
71 | size_t in2_size,
72 | uint8_t* out,
73 | size_t out_size)
74 | {
75 | union_float4 lhs, rhs, result;
76 | int resp;
77 |
78 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
79 | if (resp != SGX_SUCCESS)
80 | return resp;
81 |
82 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
83 | if (resp != SGX_SUCCESS)
84 | return resp;
85 |
86 | result.val = lhs.val + rhs.val;
87 |
88 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
89 |
90 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
91 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
92 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
93 |
94 | return resp;
95 | }
96 |
97 | /* Subtract one aes_gcm-encrypted float from another
98 | @input: uint8_t array - encrypted lhs
99 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
100 | SGX_AESGCM_MAC_SIZE = 32)
101 | uint8_t array - encrypted rhs size_t - length of
102 | encrypted rhs (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
103 | uint8_t array - encrypted out
104 | size_t - length of encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH +
105 | SGX_AESGCM_MAC_SIZE = 32)
106 | @return:
107 | * SGX_error, if there was an error during encryption/decryption
108 | 0, otherwise
109 | */
110 | int enc_float32_sub(uint8_t* in1,
111 | size_t in1_size,
112 | uint8_t* in2,
113 | size_t in2_size,
114 | uint8_t* out,
115 | size_t out_size)
116 | {
117 | union_float4 lhs, rhs, result;
118 | int resp;
119 |
120 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
121 | if (resp != SGX_SUCCESS)
122 | return resp;
123 |
124 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
125 | if (resp != SGX_SUCCESS)
126 | return resp;
127 |
128 | result.val = lhs.val - rhs.val;
129 |
130 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
131 |
132 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
133 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
134 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
135 |
136 | return resp;
137 | }
138 |
139 | /* Multiply two aes_gcm-encrypted floats
140 | @input: uint8_t array - encrypted lhs
141 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
142 | SGX_AESGCM_MAC_SIZE = 32)
143 | uint8_t array - encrypted rhs size_t - length of
144 | encrypted rhs (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
145 | uint8_t array - encrypted out
146 | size_t - length of encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH +
147 | SGX_AESGCM_MAC_SIZE = 32)
148 | @return:
149 | * SGX_error, if there was an error during encryption/decryption
150 | 0, otherwise
151 | */
152 | int enc_float32_mult(uint8_t* in1,
153 | size_t in1_size,
154 | uint8_t* in2,
155 | size_t in2_size,
156 | uint8_t* out,
157 | size_t out_size)
158 | {
159 | union_float4 lhs, rhs, result;
160 | int resp;
161 |
162 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
163 | if (resp != SGX_SUCCESS)
164 | return resp;
165 |
166 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
167 | if (resp != SGX_SUCCESS)
168 | return resp;
169 |
170 | /*TODO: Check for overflow*/
171 | result.val = lhs.val * rhs.val;
172 |
173 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
174 |
175 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
176 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
177 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
178 |
179 | return resp;
180 | }
181 |
182 | /* Take the power of one aes_gcm-encrypted float by another
183 | @input: uint8_t array - encrypted float base
184 | size_t - length of encrypted base (SGX_AESGCM_IV_SIZE + INT_LENGTH +
185 | SGX_AESGCM_MAC_SIZE = 32)
186 | uint8_t array - encrypted float exponent
187 | size_t - length of encrypted exponent (SGX_AESGCM_IV_SIZE + INT_LENGTH +
188 | SGX_AESGCM_MAC_SIZE = 32)
189 | uint8_t array - encrypted out size_t - length of
190 | encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
191 | @return:
192 | * SGX_error, if there was an error during encryption/decryption
193 | 0, otherwise
194 | */
195 | int enc_float32_pow(uint8_t* in1,
196 | size_t in1_size,
197 | uint8_t* in2,
198 | size_t in2_size,
199 | uint8_t* out,
200 | size_t out_size)
201 | {
202 | union_float4 lhs, rhs, result;
203 | int resp;
204 |
205 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
206 | if (resp != SGX_SUCCESS)
207 | return resp;
208 |
209 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
210 | if (resp != SGX_SUCCESS)
211 | return resp;
212 |
213 | /*TODO: Check for overflow*/
214 | result.val = pow(lhs.val, rhs.val);
215 |
216 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
217 |
218 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
219 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
220 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
221 |
222 | return resp;
223 | }
224 |
225 | /* Divide two aes_gcm-encrypted floats
226 | @input: uint8_t array - encrypted lhs
227 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
228 | SGX_AESGCM_MAC_SIZE = 32)
229 | uint8_t array - encrypted rhs size_t - length of
230 | encrypted src3 (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
231 | uint8_t array - encrypted out
232 | size_t - length of encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH +
233 | SGX_AESGCM_MAC_SIZE = 32)
234 | @return:
235 | * SGX_error, if there was an error during encryption/decryption
236 | 0, otherwise
237 | */
238 | int enc_float32_div(uint8_t* in1,
239 | size_t in1_size,
240 | uint8_t* in2,
241 | size_t in2_size,
242 | uint8_t* out,
243 | size_t out_size)
244 | {
245 | union_float4 lhs, rhs, result;
246 | int resp;
247 |
248 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
249 | if (resp != SGX_SUCCESS)
250 | return resp;
251 |
252 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
253 | if (resp != SGX_SUCCESS)
254 | return resp;
255 |
256 | /*TODO: Check for overflow*/
257 | if (rhs.val == 0)
258 | return ARITHMETIC_ERROR;
259 | result.val = lhs.val / rhs.val;
260 |
261 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
262 |
263 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
264 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
265 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
266 |
267 | return resp;
268 | }
269 |
270 | /* Take the modulus of one aes_gcm-encrypted float with respect to another
271 | @input: uint8_t array - encrypted lhs
272 | size_t - length of encrypted lhs (SGX_AESGCM_IV_SIZE + INT_LENGTH +
273 | SGX_AESGCM_MAC_SIZE = 32)
274 | uint8_t array - encrypted module size_t - length of
275 | encrypted module (SGX_AESGCM_IV_SIZE + INT_LENGTH + SGX_AESGCM_MAC_SIZE = 32)
276 | uint8_t array - encrypted out
277 | size_t - length of encrypted out (SGX_AESGCM_IV_SIZE + INT_LENGTH +
278 | SGX_AESGCM_MAC_SIZE = 32)
279 | @return:
280 | * SGX_error, if there was an error during encryption/decryption
281 | 0, otherwise
282 | */
283 | int enc_float32_mod(uint8_t* in1,
284 | size_t in1_size,
285 | uint8_t* in2,
286 | size_t in2_size,
287 | uint8_t* out,
288 | size_t out_size)
289 | {
290 | union_float4 lhs, rhs, result;
291 | int resp;
292 |
293 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, FLOAT4_LENGTH);
294 | if (resp != SGX_SUCCESS)
295 | return resp;
296 |
297 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, FLOAT4_LENGTH);
298 | if (resp != SGX_SUCCESS)
299 | return resp;
300 |
301 | /*TODO: Check for correctness*/
302 | result.val = (int)lhs.val % (int)rhs.val;
303 |
304 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_size);
305 |
306 | memset_s(lhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
307 | memset_s(rhs.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
308 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
309 |
310 | return resp;
311 | }
312 |
313 | int enc_float32_sum_bulk(uint8_t* in1,
314 | size_t in1_len,
315 | uint8_t* in2,
316 | size_t in2_len,
317 | uint8_t* out,
318 | size_t out_len)
319 | {
320 | union_float4 temp, result;
321 | int32_t bulk_size = 0, current_position = 0;
322 | int resp, counter = 0;
323 |
324 | if (bytearray2int(in1, bulk_size, INT32_LENGTH))
325 | return MEMORY_COPY_ERROR;
326 |
327 | result.val = 0;
328 | while (counter < bulk_size)
329 | {
330 | resp = decrypt_bytes(
331 | in2 + current_position, ENC_FLOAT4_LENGTH, temp.bytes, FLOAT4_LENGTH);
332 | if (resp != SGX_SUCCESS)
333 | return resp;
334 | current_position += ENC_FLOAT4_LENGTH;
335 |
336 | result.val += temp.val;
337 | counter++;
338 | }
339 |
340 | resp = encrypt_bytes(result.bytes, FLOAT4_LENGTH, out, out_len);
341 |
342 | memset_s(temp.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
343 | memset_s(result.bytes, FLOAT4_LENGTH, 0, FLOAT4_LENGTH);
344 |
345 | return resp;
346 | }
347 |
--------------------------------------------------------------------------------
/src/enclave/enc_text_ops.cpp:
--------------------------------------------------------------------------------
1 | #include "enclave/enc_text_ops.hpp"
2 |
3 | /* Compare two encrypted by aes_gcm strings
4 | @input: uint8_t array - encrypted string1
5 | size_t - length of encrypted string1 (max lenght = SGX_AESGCM_IV_SIZE +
6 | ??? + SGX_AESGCM_MAC_SIZE = 32)
7 | uint8_t array - encrypted string2 size_t -
8 | length of encrypted string2 (SGX_AESGCM_IV_SIZE + ??? + SGX_AESGCM_MAC_SIZE =
9 | 32)
10 | uint8_t array - which contains the result 1 (if a > b). -1 (if b > a),
11 | 0 (if a == b)
12 | size_t - length of result (INT32_LENGTH = 4)
13 | @return:
14 | * SGX_error, if there was an error during decryption
15 | */
16 | int enc_text_like(uint8_t* in1,
17 | size_t in1_size,
18 | uint8_t* in2,
19 | size_t in2_size,
20 | uint8_t* out,
21 | size_t out_size)
22 | {
23 | int str_raw_size = in1_size - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
24 | int pattern_raw_size = in2_size - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
25 | int resp, result;
26 | char* str = (char*)malloc(str_raw_size + 1);
27 | char* pattern = (char*)malloc(pattern_raw_size + 1);
28 |
29 | resp = decrypt_bytes((uint8_t*)in1, in1_size, (uint8_t*)str, str_raw_size);
30 | if (resp != SGX_SUCCESS)
31 | return resp;
32 |
33 | resp = decrypt_bytes((uint8_t*)in2, in2_size, (uint8_t*)pattern, pattern_raw_size);
34 | if (resp != SGX_SUCCESS)
35 | return resp;
36 |
37 | result = (MatchText(str, str_raw_size, pattern, pattern_raw_size) == LIKE_TRUE);
38 |
39 | memcpy(out, &result, out_size);
40 |
41 | memset_s(str, str_raw_size + 1, 0, str_raw_size + 1);
42 | memset_s(pattern, pattern_raw_size + 1, 0, pattern_raw_size + 1);
43 | memset_s(&result, sizeof(result), 0, sizeof(result));
44 |
45 | free(str);
46 | free(pattern);
47 |
48 | return resp;
49 | }
50 | /* Compare two encrypted by aes_gcm strings
51 | @input: uint8_t array - encrypted string1
52 | size_t - length of encrypted string1 (max lenght = SGX_AESGCM_IV_SIZE +
53 | ??? + SGX_AESGCM_MAC_SIZE = 32)
54 | uint8_t array - encrypted string2 size_t -
55 | length of encrypted string2 (SGX_AESGCM_IV_SIZE + ??? + SGX_AESGCM_MAC_SIZE =
56 | 32)
57 | uint8_t array - which contains the result 1 (if a > b). -1 (if b > a),
58 | 0 (if a == b)
59 | size_t - length of result (INT32_LENGTH = 4)
60 |
61 | @return:
62 | * SGX_error, if there was an error during decryption
63 | */
64 | int enc_text_cmp(uint8_t* string1,
65 | size_t string1_len,
66 | uint8_t* string2,
67 | size_t string2_len,
68 | uint8_t* result,
69 | size_t res_len)
70 | {
71 | if ((string1_len < SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE) || (string2_len < SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE))
72 | return MEMORY_COPY_ERROR;
73 |
74 | int raw_str1_len = string1_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
75 | int raw_str2_len = string2_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
76 | int resp, cmp;
77 | uint8_t* dec_string1 = (uint8_t*)malloc(raw_str1_len + 1);
78 | uint8_t* dec_string2 = (uint8_t*)malloc(raw_str2_len + 1);
79 |
80 | resp = decrypt_bytes(string1, string1_len, dec_string1, raw_str1_len);
81 | if (resp != SGX_SUCCESS)
82 | return resp;
83 |
84 | resp = decrypt_bytes(string2, string2_len, dec_string2, raw_str2_len);
85 | if (resp != SGX_SUCCESS)
86 | return resp;
87 |
88 | dec_string1[raw_str1_len] = dec_string2[raw_str2_len] = '\0';
89 |
90 | cmp = strcmp((const char*)dec_string1, (const char*)dec_string2);
91 |
92 | memcpy(result, &cmp, res_len);
93 |
94 | memset_s(dec_string1, raw_str1_len + 1, 0, raw_str1_len + 1);
95 | memset_s(dec_string2, raw_str2_len + 1, 0, raw_str2_len + 1);
96 |
97 | free(dec_string1);
98 | free(dec_string2);
99 |
100 | return resp;
101 | }
102 |
103 | /* Concatenation of two encrypted by aes_gcm strings
104 | @input: uint8_t array - encrypted integer1
105 | size_t - length of encrypted integer1 (SGX_AESGCM_IV_SIZE + ?? +
106 | SGX_AESGCM_MAC_SIZE = 32)
107 | uint8_t array - encrypted integer2 size_t - length of
108 | encrypted integer2 (SGX_AESGCM_IV_SIZE + ?? + SGX_AESGCM_MAC_SIZE = 32)
109 | uint8_t array - encrypted result size_t - length of encrypted result
110 | (SGX_AESGCM_IV_SIZE + ?? + SGX_AESGCM_MAC_SIZE = 32)
111 | @return:
112 | * SGX_error, if there was an error during encryption/decryption
113 | 0, otherwise
114 | */
115 | int enc_text_concatenate(uint8_t* string1,
116 | size_t string1_len,
117 | uint8_t* string2,
118 | size_t string2_len,
119 | uint8_t* string3,
120 | size_t string3_len)
121 | {
122 | int raw_str1_len = string1_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
123 | int raw_str2_len = string2_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
124 | int raw_str3_len = string3_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
125 | int resp;
126 |
127 | uint8_t* dec_string1 = (uint8_t*)malloc(raw_str1_len + 1);
128 | uint8_t* dec_string2 = (uint8_t*)malloc(raw_str2_len + 1);
129 | uint8_t* dec_string3 = (uint8_t*)malloc(raw_str3_len + 1);
130 |
131 | resp = decrypt_bytes(string1, string1_len, dec_string1, raw_str1_len);
132 | if (resp != SGX_SUCCESS)
133 | return resp;
134 |
135 | resp = decrypt_bytes(string2, string2_len, dec_string2, raw_str2_len);
136 | if (resp != SGX_SUCCESS)
137 | return resp;
138 |
139 | memcpy(dec_string3, dec_string1, raw_str1_len);
140 | memcpy(dec_string3 + raw_str1_len, dec_string2, raw_str2_len);
141 |
142 | resp = encrypt_bytes(dec_string3, raw_str3_len, string3, string3_len);
143 |
144 | memset_s(dec_string1, raw_str1_len + 1, 0, raw_str1_len + 1);
145 | memset_s(dec_string2, raw_str2_len + 1, 0, raw_str2_len + 1);
146 | memset_s(dec_string3, raw_str3_len + 1, 0, raw_str3_len + 1);
147 |
148 | free_allocated_memory(dec_string1);
149 | free_allocated_memory(dec_string2);
150 | free_allocated_memory(dec_string3);
151 |
152 | return resp;
153 | }
154 |
155 | /* Search for substring in the string (both are encrypted by aes_gcm)
156 | @input: uint8_t array - encrypted string
157 | size_t - length of encrypted string (SGX_AESGCM_IV_SIZE + ?? +
158 | SGX_AESGCM_MAC_SIZE = 32)
159 | uint8_t array - encrypted substring size_t - length
160 | of encrypted substring (SGX_AESGCM_IV_SIZE + ?? + SGX_AESGCM_MAC_SIZE = 32)
161 | @return:
162 | * SGX_error, if there was an error during encryption/decryption
163 | 0, if the strings contains the substring
164 | 1, it not
165 | */
166 | int enc_text_substring(uint8_t* in1,
167 | size_t in1_size,
168 | uint8_t* in2,
169 | size_t in2_size,
170 | uint8_t* in3,
171 | size_t in3_size,
172 | uint8_t* out,
173 | size_t* out_size)
174 | {
175 | size_t str_size = in1_size - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
176 |
177 | union {
178 | int val;
179 | unsigned char bytes[sizeof(val)];
180 | } from, n_chars;
181 |
182 | char* str = (char*)malloc(str_size + 1);
183 | uint8_t* result = (uint8_t*)malloc(*out_size + 1);
184 | int resp = decrypt_bytes(in1, in1_size, (uint8_t*)str, str_size);
185 | if (resp != SGX_SUCCESS)
186 | return resp;
187 |
188 | if ((in2_size == INT32_LENGTH) && (in3_size == INT32_LENGTH))
189 | {
190 | memcpy(from.bytes, in2, INT32_LENGTH);
191 | memcpy(n_chars.bytes, in3, INT32_LENGTH);
192 | }
193 | else
194 | {
195 | resp = decrypt_bytes(in2, in2_size, from.bytes, INT32_LENGTH);
196 | if (resp != SGX_SUCCESS)
197 | return resp;
198 |
199 | resp = decrypt_bytes(in3, in3_size, n_chars.bytes, INT32_LENGTH);
200 | if (resp != SGX_SUCCESS)
201 | return resp;
202 | }
203 |
204 | if ((from.val < 0 || n_chars.val < 0) || (from.val + n_chars.val > str_size))
205 | {
206 | return OUT_OF_THE_RANGE_ERROR;
207 | }
208 |
209 | for (size_t i = 0; i < n_chars.val; i++)
210 | {
211 | result[i] = str[from.val + i - 1];
212 | }
213 |
214 | resp = encrypt_bytes(result, n_chars.val, out, *out_size);
215 |
216 | memset_s(result, *out_size + 1, 0, *out_size + 1);
217 |
218 | *out_size = n_chars.val + SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE;
219 |
220 | memset_s(str, str_size + 1, 0, str_size + 1);
221 | memset_s(from.bytes, INT32_LENGTH, 0, INT32_LENGTH);
222 | memset_s(n_chars.bytes, INT32_LENGTH, 0, INT32_LENGTH);
223 |
224 | free(str);
225 | free(result);
226 |
227 | return resp;
228 | }
229 |
--------------------------------------------------------------------------------
/src/enclave/enc_timestamp_ops.cpp:
--------------------------------------------------------------------------------
1 | #include "enclave/enc_timestamp_ops.hpp"
2 |
3 | /* Compare two encrypted timestamps(int64 - 8 bytes) by aes_gcm algorithm
4 | @input: uint8_t array - encrypted source1
5 | size_t - sizegth of encrypted source1 (SGX_AESGCM_IV_SIZE +
6 | INT64_LENGTH + SGX_AESGCM_MAC_SIZE = 36)
7 | uint8_t array - encrypted source2
8 | size_t - sizegth of encrypted source2 (SGX_AESGCM_IV_SIZE +
9 | INT64_LENGTH + SGX_AESGCM_MAC_SIZE = 36)
10 | uint8_t array - which contains the result 1 (if a > b). -1 (if b > a),
11 | 0 (if a == b)
12 | size_t - size of result (TIMESTAMP_LENGTH = 4)
13 |
14 | @return:
15 | * SGX_error, if there was an error during decryption
16 | */
17 | int enc_timestamp_cmp(uint8_t* in1,
18 | size_t in1_size,
19 | uint8_t* in2,
20 | size_t in2_size,
21 | uint8_t* out,
22 | size_t out_size)
23 | {
24 | int resp, cmp;
25 |
26 | union {
27 | TIMESTAMP ts;
28 | unsigned char bytes[TIMESTAMP_LENGTH];
29 | } lhs, rhs;
30 |
31 | resp = decrypt_bytes(in1, in1_size, lhs.bytes, TIMESTAMP_LENGTH);
32 | if (resp != SGX_SUCCESS)
33 | return resp;
34 |
35 | resp = decrypt_bytes(in2, in2_size, rhs.bytes, TIMESTAMP_LENGTH);
36 | if (resp != SGX_SUCCESS)
37 | return resp;
38 |
39 | cmp = (lhs.ts == rhs.ts) ? 0 : ((lhs.ts < rhs.ts) ? -1 : 1);
40 |
41 | memcpy(out, &cmp, out_size);
42 |
43 | memset_s(lhs.bytes, TIMESTAMP_LENGTH, 0, TIMESTAMP_LENGTH);
44 | memset_s(rhs.bytes, TIMESTAMP_LENGTH, 0, TIMESTAMP_LENGTH);
45 |
46 | return resp;
47 | }
48 |
49 | int enc_timestamp_extract_year(uint8_t* in,
50 | size_t in_size,
51 | uint8_t* out,
52 | size_t out_size)
53 | {
54 | union {
55 | int val;
56 | unsigned char bytes[INT32_LENGTH];
57 | } year;
58 |
59 | union {
60 | TIMESTAMP val;
61 | unsigned char bytes[TIMESTAMP_LENGTH];
62 | } timestamp;
63 |
64 | int resp = decrypt_bytes(in, in_size, timestamp.bytes, TIMESTAMP_LENGTH);
65 | if (resp != SGX_SUCCESS)
66 | return resp;
67 |
68 | year.val = year_from_timestamp(timestamp.val);
69 |
70 | resp = encrypt_bytes(year.bytes, INT32_LENGTH, out, out_size);
71 | memset_s(timestamp.bytes, TIMESTAMP_LENGTH, 0, TIMESTAMP_LENGTH);
72 | memset_s(year.bytes, INT32_LENGTH, 0, INT32_LENGTH);
73 |
74 | return resp;
75 | }
76 |
--------------------------------------------------------------------------------
/src/enclave/enclave.config.xml:
--------------------------------------------------------------------------------
1 |
2 | 0
3 | 0
4 | 0x40000
5 | 0x100000
6 | 10
7 | 1
8 | 0
9 |
10 |
--------------------------------------------------------------------------------
/src/enclave/enclave.edl:
--------------------------------------------------------------------------------
1 | /* enclave.edl - Top EDL file. */
2 |
3 | enclave {
4 | /*
5 | * ocall_enclave_sample - invokes OCALL to display string buffer inside the enclave.
6 | * [in]: copy the string buffer to App outside.
7 | * [string]: specifies 'str' is a NULL terminated buffer.
8 | */
9 | untrusted {
10 |
11 | };
12 |
13 | trusted {
14 | public int generateKeyEnclave([out, size = sealedkey_len] uint8_t *sealed_key, size_t sealedkey_len);
15 | public int loadKeyEnclave ([in, size = len] uint8_t *key, size_t len);
16 | public int enclaveProcess ([user_check]void* inQueue);
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/src/enclave/enclave.lds:
--------------------------------------------------------------------------------
1 | enclave.so
2 | {
3 | global:
4 | g_global_data_sim;
5 | g_global_data;
6 | enclave_entry;
7 | local:
8 | *;
9 | };
10 |
--------------------------------------------------------------------------------
/src/include/defs.h:
--------------------------------------------------------------------------------
1 | // not sure what is better to use
2 | // #define(appropriate in c) or const int (c++ standard)
3 | // my vote for 'const int'
4 |
5 | typedef unsigned char BYTE; // 1byte
6 | typedef unsigned short WORD; // 2bytes
7 | typedef unsigned long DWORD; //4bytes
8 |
9 | #define SEALED_KEY_LENGTH 576
10 |
11 | #define ENC_INT32_LENGTH_B64 45 //((4 * n / 3) + 3) & ~3
12 | #define ENC_INT32_LENGTH 32
13 | #define INT32_LENGTH sizeof(int)
14 |
15 | #define ENC_FLOAT4_LENGTH_B64 45 //((4 * n / 3) + 3) & ~3
16 | #define ENC_FLOAT4_LENGTH 32
17 | #define FLOAT4_LENGTH sizeof(float)
18 |
19 | #define ENC_TIMESTAMP_LENGTH_B64 49 //((4 * n / 3) + 3) & ~3
20 | #define ENC_TIMESTAMP_LENGTH 36
21 | #define TIMESTAMP int64_t
22 | #define TIMESTAMP_LENGTH sizeof(int64_t)
23 |
24 | #define ENC_STRING_LENGTH_B64 1405 //((4 * n / 3) + 3) & ~3
25 | #define ENC_STRING_LENGTH 1052
26 | #define STRING_LENGTH 1024
27 | #define INPUT_BUFFER_SIZE ENC_STRING_LENGTH_B64 + ENC_STRING_LENGTH_B64 + 1
28 |
29 | #define BULK_SIZE 256
30 |
31 | // errors
32 | #define ENCLAVE_IS_NOT_RUNNING -2
33 | #define MEMORY_COPY_ERROR -3
34 | #define ARITHMETIC_ERROR -4
35 | #define MEMORY_ALLOCATION_ERROR -5
36 | #define OUT_OF_THE_RANGE_ERROR -6
37 | #define BASE64DECODER_ERROR -7
38 | #define IS_NOT_INITIALIZE -8
39 | #define NO_KEYS_STORAGE -9
40 | #define NO_KEY_ID -10
41 | #define NOT_IMPLEMENTED_OPERATOR -11
42 | #define TOO_MANY_ELEMENTS_IN_BULK -12
43 |
44 | // COMMANDS
45 | #define CMD_INT64_PLUS 1
46 | #define CMD_INT64_MINUS 2
47 | #define CMD_INT64_MULT 3
48 | #define CMD_INT64_DIV 4
49 | #define CMD_INT64_CMP 5
50 | #define CMD_INT64_ENC 6
51 | #define CMD_INT64_DEC 7
52 | #define CMD_INT64_EXP 8
53 | #define CMD_INT64_MOD 9
54 | #define CMD_INT32_SUM_BULK 10
55 |
56 | #define CMD_FLOAT4_PLUS 101
57 | #define CMD_FLOAT4_MINUS 102
58 | #define CMD_FLOAT4_MULT 103
59 | #define CMD_FLOAT4_DIV 104
60 | #define CMD_FLOAT4_CMP 105
61 | #define CMD_FLOAT4_ENC 106
62 | #define CMD_FLOAT4_DEC 107
63 | #define CMD_FLOAT4_EXP 108
64 | #define CMD_FLOAT4_MOD 109
65 | #define CMD_FLOAT4_SUM_BULK 110
66 |
67 | #define CMD_STRING_CMP 201
68 | #define CMD_STRING_ENC 202
69 | #define CMD_STRING_DEC 203
70 | #define CMD_STRING_SUBSTRING 204
71 | #define CMD_STRING_CONCAT 205
72 | #define CMD_STRING_LIKE 206
73 |
74 | #define CMD_TIMESTAMP_CMP 150
75 | #define CMD_TIMESTAMP_ENC 151
76 | #define CMD_TIMESTAMP_DEC 152
77 | #define CMD_TIMESTAMP_EXTRACT_YEAR 153
78 |
--------------------------------------------------------------------------------
/src/include/enclave/Queue.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "tools/sync_utils.hpp"
3 | #include
4 |
5 | struct request
6 | {
7 | static const int max_buffer_size = 65536;
8 | int ocall_index;
9 | unsigned char buffer[max_buffer_size];
10 | volatile int is_done;
11 | int resp;
12 | };
13 |
14 | class Queue
15 | {
16 | public:
17 | Queue();
18 | virtual ~Queue();
19 | int enqueue(request* elem);
20 | request* dequeue();
21 | int front, rear;
22 |
23 | private:
24 | static const int queue_size = 1024000;
25 | request* q[queue_size];
26 | int volatile _lock;
27 | };
28 |
--------------------------------------------------------------------------------
/src/include/enclave/enc_float32_ops.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "enclave/enclave.hpp"
4 | #include "enclave/enclave_t.h"
5 |
6 | typedef union {
7 | float val;
8 | unsigned char bytes[FLOAT4_LENGTH];
9 | } union_float4;
10 |
11 | int enc_float32_add(uint8_t* in1,
12 | size_t in1_size,
13 | uint8_t* in2,
14 | size_t in2_size,
15 | uint8_t* out,
16 | size_t out_size);
17 | int enc_float32_cmp(uint8_t* in1,
18 | size_t in1_size,
19 | uint8_t* in2,
20 | size_t in2_size,
21 | uint8_t* out,
22 | size_t out_size);
23 | int enc_float32_sub(uint8_t* in1,
24 | size_t in1_size,
25 | uint8_t* in2,
26 | size_t in2_size,
27 | uint8_t* out,
28 | size_t out_size);
29 | int enc_float32_mult(uint8_t* in1,
30 | size_t in1_size,
31 | uint8_t* in2,
32 | size_t in2_size,
33 | uint8_t* out,
34 | size_t out_size);
35 | int enc_float32_div(uint8_t* in1,
36 | size_t in1_size,
37 | uint8_t* in2,
38 | size_t in2_size,
39 | uint8_t* out,
40 | size_t out_size);
41 | int enc_float32_mod(uint8_t* in1,
42 | size_t in1_size,
43 | uint8_t* in2,
44 | size_t in2_size,
45 | uint8_t* out,
46 | size_t out_size);
47 | int enc_float32_pow(uint8_t* in1,
48 | size_t in1_size,
49 | uint8_t* in2,
50 | size_t in2_size,
51 | uint8_t* out,
52 | size_t out_size);
53 | int enc_float32_sum_bulk(uint8_t* in1,
54 | size_t in1_size,
55 | uint8_t* in2,
56 | size_t in2_size,
57 | uint8_t* out,
58 | size_t out_size);
59 |
--------------------------------------------------------------------------------
/src/include/enclave/enc_int32_ops.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "enclave/enclave.hpp"
4 | #include "enclave/enclave_t.h" /* print_string */
5 | #include "tools/bytes.hpp"
6 | int enc_int32_add(uint8_t* int1,
7 | size_t int1_len,
8 | uint8_t* int2,
9 | size_t int2_len,
10 | uint8_t* int3,
11 | size_t int3_len);
12 | int enc_int32_cmp(uint8_t* int1,
13 | size_t int1_len,
14 | uint8_t* int2,
15 | size_t int2_len,
16 | uint8_t* result,
17 | size_t res_len);
18 | int enc_int32_sub(uint8_t* int1,
19 | size_t int1_len,
20 | uint8_t* int2,
21 | size_t int2_len,
22 | uint8_t* result,
23 | size_t res_len);
24 | int enc_int32_mult(uint8_t* int1,
25 | size_t int1_len,
26 | uint8_t* int2,
27 | size_t int2_len,
28 | uint8_t* result,
29 | size_t res_len);
30 | int enc_int32_div(uint8_t* int1,
31 | size_t int1_len,
32 | uint8_t* int2,
33 | size_t int2_len,
34 | uint8_t* result,
35 | size_t res_len);
36 | int enc_int32_mod(uint8_t* int1,
37 | size_t int1_len,
38 | uint8_t* int2,
39 | size_t int2_len,
40 | uint8_t* result,
41 | size_t res_len);
42 | int enc_int32_pow(uint8_t* int1,
43 | size_t int1_len,
44 | uint8_t* int2,
45 | size_t int2_len,
46 | uint8_t* result,
47 | size_t res_len);
48 | int enc_int32_sum_bulk(uint8_t* arg1,
49 | size_t arg1_len,
50 | uint8_t* arg2,
51 | size_t arg2_len,
52 | uint8_t* result,
53 | size_t res_len);
54 |
--------------------------------------------------------------------------------
/src/include/enclave/enc_text_ops.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "defs.h"
4 | #include "enclave/enclave.hpp"
5 | #include "tools/like_match.h"
6 | #include
7 |
8 | #ifdef __cplusplus
9 | extern "C"
10 | {
11 | #endif
12 |
13 | int enc_text_cmp(uint8_t* in1,
14 | size_t in1_size,
15 | uint8_t* in2,
16 | size_t in2_size,
17 | uint8_t* out,
18 | size_t out_size);
19 | int enc_text_like(uint8_t* in1,
20 | size_t in1_size,
21 | uint8_t* in2,
22 | size_t in2_size,
23 | uint8_t* out,
24 | size_t out_size);
25 | int enc_text_concatenate(uint8_t* in1,
26 | size_t in1_size,
27 | uint8_t* in2,
28 | size_t in2_size,
29 | uint8_t* out,
30 | size_t out_size);
31 | int enc_text_substring(uint8_t* in1,
32 | size_t in1_size,
33 | uint8_t* in2,
34 | size_t in2_size,
35 | uint8_t* in3,
36 | size_t in3_size,
37 | uint8_t* out,
38 | size_t* out_size);
39 |
40 | #ifdef __cplusplus
41 | }
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/include/enclave/enc_timestamp_ops.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "enclave/enclave.hpp"
3 | #include "enclave/enclave_t.h"
4 | #include "tools/timestamp.h"
5 |
6 | int enc_timestamp_cmp(uint8_t* src1,
7 | size_t src1_len,
8 | uint8_t* src2,
9 | size_t src2_len,
10 | uint8_t* result,
11 | size_t res_len);
12 | int enc_timestamp_extract_year(uint8_t* in1,
13 | size_t in1_len,
14 | uint8_t* out,
15 | size_t out_size);
16 |
--------------------------------------------------------------------------------
/src/include/enclave/enclave.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "sgx_eid.h"
4 | #include "sgx_tcrypto.h"
5 | #include "sgx_trts.h"
6 | #include "sgx_tseal.h"
7 | #include
8 | #include
9 |
10 | #include "math.h"
11 | #include
12 | #include
13 |
14 | #include "defs.h"
15 | #include "enclave/Queue.hpp"
16 | #include "enclave/enc_float32_ops.hpp"
17 | #include "enclave/enc_int32_ops.hpp"
18 | #include "enclave/enc_text_ops.hpp"
19 | #include "enclave/enc_timestamp_ops.hpp"
20 | #include "tools/sync_utils.hpp"
21 |
22 | #if defined(__cplusplus)
23 | extern "C"
24 | {
25 | #endif
26 |
27 | void free_allocated_memory(void* pointer);
28 |
29 | // FUNCTIONS
30 | int decrypt_bytes(uint8_t* pSrc, size_t srcLen, uint8_t* pDst, size_t dstLen);
31 | int encrypt_bytes(uint8_t* pSrc, size_t srcLen, uint8_t* pDst, size_t dstLen);
32 | #if defined(__cplusplus)
33 | }
34 | #endif
35 |
--------------------------------------------------------------------------------
/src/include/tools/base64.hpp:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 |
3 | int ToBase64Fast(const unsigned char* pSrc, int nLenSrc, char* pDst, int nLenDst);
4 | int FromBase64Fast(const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst);
5 | int FromBase64Fast(const BYTE* pSrc, int nLenSrc, BYTE* pDst, int nLenDst);
6 |
--------------------------------------------------------------------------------
/src/include/tools/bytes.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "defs.h"
3 | #include
4 | #include
5 | #include
6 |
7 | int int2bytearray(int, uint8_t*, size_t);
8 | int bytearray2int(uint8_t*, int&, size_t);
9 |
--------------------------------------------------------------------------------
/src/include/tools/like_match.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define GETCHAR(t) (t)
3 | #define LIKE_TRUE 1
4 | #define LIKE_FALSE 0
5 | #define LIKE_ABORT (-1)
6 |
7 | #define CHAREQ(p1, p2) (*(p1) == *(p2))
8 | #define NextByte(p, plen) ((p)++, (plen)--)
9 | #define NextChar(p, plen) NextByte((p), (plen))
10 | #define CopyAdvChar(dst, src, srclen) (*(dst)++ = *(src)++, (srclen)--)
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | int MatchText(char*, int, char*, int);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/include/tools/oblvs_int32_ops.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 | /*Return 1 if lhs == rhs and 0 otherwise*/
7 | int32_t obs_int32_eq(int32_t lhs, int32_t rhs);
8 |
9 | /* Return 1 if lhs < rhs and 0 otherwise*/
10 | int32_t obs_int32_lt(int32_t lhs, int32_t rhs);
11 |
12 | /*Return rhs if sel = 0 and lhs otherwise*/
13 | int32_t obs_int32_select(int32_t lhs, int32_t rhs, int32_t sel);
14 |
15 | /* Return base^exp*/
16 | int32_t obs_int32_pow(int32_t base, int32_t exp);
17 | #ifdef __cplusplus
18 | }
19 | #endif
20 |
21 | int32_t obs_int32_neq(int32_t lhs, int32_t rhs)
22 | {
23 | return 1 ^ obs_int32_eq(lhs, rhs);
24 | }
25 |
26 | /*Return 1 if lhs > rhs and 0 otherwise*/
27 | int32_t obs_int32_gt(int32_t lhs, int32_t rhs) {
28 | return obs_int32_lt(rhs, lhs);
29 | }
30 |
31 | /*Return 1 if lhs >= rhs and 0 otherwise*/
32 | int32_t obs_int32_ge(int32_t lhs, int32_t rhs) {
33 | return 1 ^ obs_int32_lt(lhs, rhs);
34 | }
35 |
36 | /*Return 1 if lhs <= rhs and 0 otherwise*/
37 | int32_t obs_int32_le(int32_t lhs, int32_t rhs) {
38 | return 1 ^ obs_int32_gt(rhs, lhs);
39 | }
40 |
41 | /*Return 1 if lhs > rhs, -1 if lhs < rhs and 0 otherwise*/
42 | int32_t obs_int32_cmp(int32_t lhs, int32_t rhs) {
43 | return obs_int32_gt(lhs, rhs) | -obs_int32_lt(lhs, rhs);
44 | }
45 |
--------------------------------------------------------------------------------
/src/include/tools/sync_utils.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void spin_lock(int volatile* p);
4 | void spin_unlock(int volatile* p);
5 | void spin_lock(unsigned char volatile* p);
6 | void spin_unlock(unsigned char volatile* p);
7 |
--------------------------------------------------------------------------------
/src/include/tools/timestamp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | /* TMODULO()
6 | * Implements modf() in for the timestamp (aka int64) datatype.
7 | * We assume that int64 follows the C99 semantics for division (negative
8 | * quotients truncate towards zero).
9 | */
10 | #define TMODULO(t,q,u) \
11 | do { \
12 | (q) = ((t) / (u)); \
13 | if ((q) != 0) (t) -= ((q) * (u)); \
14 | } while(0)
15 |
16 | #define INT64CONST(x) (x##L)
17 | #define USECS_PER_DAY INT64CONST(86400000000)
18 | #define POSTGRES_EPOCH_JDATE 2451545
19 |
20 | #ifdef __cplusplus
21 | extern "C" {
22 | #endif
23 |
24 | int year_from_timestamp(int64_t timestamp);
25 | #ifdef __cplusplus
26 | }
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/include/untrusted/extensions/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 | #include
8 | #include
9 | #include
10 |
11 | #include "enclave_u.h"
12 | #include "sgx_eid.h" /* sgx_enclave_id_t */
13 | #include "sgx_tcrypto.h"
14 |
15 | #include "postgres.h"
16 | #include "fmgr.h"
17 | #include
18 |
19 | #include
20 | #include
21 | #include "utils/builtins.h"
22 |
23 | #include "defs.h"
24 | #include "untrusted/interface/interface.h"
25 |
26 | typedef struct _sgx_errlist_t {
27 | sgx_status_t err;
28 | const char* msg;
29 | const char* sug; /* Suggestion */
30 | } sgx_errlist_t;
31 |
32 | void sgxErrorHandler(int code);
33 |
34 | /* Error code returned by sgx_create_enclave */
35 | static sgx_errlist_t sgx_errlist[] = {
36 | {
37 | SGX_ERROR_INVALID_KEYNAME,
38 | "The key name is an unsupported value",
39 | NULL
40 | },
41 | {
42 | SGX_ERROR_INVALID_ISVSVN,
43 | "The isv svn is greater than the enclave's isv svn",
44 | NULL
45 | },
46 | {
47 | SGX_ERROR_MAC_MISMATCH,
48 | "Indicates verification error for reports, sealed datas, MAC checks and etc",
49 | NULL
50 | },
51 | {
52 | SGX_ERROR_INVALID_ATTRIBUTE,
53 | "The cpu svn is beyond platform's cpu svn value",
54 | NULL
55 | },
56 |
57 | {
58 | SGX_ERROR_INVALID_PARAMETER,
59 | "Invalid parameter.",
60 | NULL
61 | },
62 | {
63 | SGX_ERROR_OUT_OF_MEMORY,
64 | "Out of memory.",
65 | NULL
66 | },
67 | {
68 | SGX_ERROR_ENCLAVE_LOST,
69 | "Power transition occurred.",
70 | "Please refer to the sample \"PowerTransition\" for details."
71 | },
72 | {
73 | SGX_ERROR_INVALID_ENCLAVE,
74 | "Invalid enclave image.",
75 | NULL
76 | },
77 | {
78 | SGX_ERROR_INVALID_ENCLAVE_ID,
79 | "Invalid enclave identification.",
80 | NULL
81 | },
82 | {
83 | SGX_ERROR_INVALID_SIGNATURE,
84 | "Invalid enclave signature.",
85 | NULL
86 | },
87 | {
88 | SGX_ERROR_OUT_OF_EPC,
89 | "Out of EPC memory.",
90 | NULL
91 | },
92 | {
93 | SGX_ERROR_NO_DEVICE,
94 | "Invalid SGX device.",
95 | "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
96 | },
97 | {
98 | SGX_ERROR_MEMORY_MAP_CONFLICT,
99 | "Memory map conflicted.",
100 | NULL
101 | },
102 | {
103 | SGX_ERROR_INVALID_METADATA,
104 | "Invalid enclave metadata.",
105 | NULL
106 | },
107 | {
108 | SGX_ERROR_DEVICE_BUSY,
109 | "SGX device was busy.",
110 | NULL
111 | },
112 | {
113 | SGX_ERROR_INVALID_VERSION,
114 | "Enclave version was invalid.",
115 | NULL
116 | },
117 | {
118 | SGX_ERROR_INVALID_ATTRIBUTE,
119 | "Enclave was not authorized.",
120 | NULL
121 | },
122 | {
123 | SGX_ERROR_ENCLAVE_FILE_ACCESS,
124 | "Can't open enclave file.",
125 | NULL
126 | },
127 | {
128 | SGX_ERROR_SERVICE_UNAVAILABLE,
129 | "Indicates aesm didn't respond or the requested service is not supported",
130 | NULL
131 | },
132 | };
133 |
--------------------------------------------------------------------------------
/src/include/untrusted/interface/interface.h:
--------------------------------------------------------------------------------
1 | #ifndef _APP_H_
2 | #define _APP_H_
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "sgx_eid.h" /* sgx_enclave_id_t */
9 | #include "enclave_u.h"
10 |
11 | #ifndef TRUE
12 | # define TRUE 1
13 | #endif
14 |
15 | #ifndef FALSE
16 | # define FALSE 0
17 | #endif
18 |
19 | #if defined(__cplusplus)
20 | extern "C" {
21 | #endif
22 | extern sgx_enclave_id_t global_eid; /* global enclave id */
23 |
24 | int generateKey();
25 | int loadKey(int item);
26 |
27 | int initMultithreading();
28 | int enc_int32_add(char *int1, char *int2, char *res);
29 | int enc_int32_sub(char *int1, char *int2, char *res);
30 | int enc_int32_mult(char *int1, char *int2, char *res);
31 | int enc_int32_div(char *int1, char *int2, char *res);
32 | int enc_int32_pow(char *int1, char *int2, char *res);
33 | int enc_int32_mod(char *int1, char *int2, char *res);
34 | int enc_int32_cmp(char *int1, char *int2, char *res);
35 | int enc_int32_encrypt(int pSrc, char *pDst);
36 | int enc_int32_decrypt(char *pSrc, char *pDst);
37 | int enc_int32_sum_bulk(size_t bulk_size, char *arg1, char *res);
38 |
39 | int enc_text_cmp(char *arg1, size_t arg1_len, char *arg2, size_t arg2_len, char *res);
40 | int enc_text_concatenate(char *arg1, size_t arg1_len, char *arg2, size_t arg2_len, char *dst, size_t* dst_len);
41 | int enc_text_substring(char* in1, size_t in1_size, char* in2, size_t in2_size, char* in3, size_t in3_size, char* out, size_t* out_size);
42 |
43 | int enc_text_like(char* in1, size_t in1_size, char* in2, size_t in2_size, int* out);
44 |
45 | int enc_text_encrypt(char* arg1, size_t arg1_len, char* res, size_t dst_len);
46 | int enc_text_decrypt(char* arg1, size_t arg1_len, char* res, size_t dst_len);
47 |
48 | int enc_float32_cmp(char *arg1, char *arg2, char *res);
49 | int enc_float32_encrypt(float pSrc, char *pDst);
50 | int enc_float32_decrypt(char *pSrc, char *pDst);
51 | int enc_float32_add(char *arg1, char *arg2, char *res);
52 | int enc_float32_sub(char *arg1, char *arg2, char *res);
53 | int enc_float32_mult(char *arg1, char *arg2, char *res);
54 | int enc_float32_div(char *arg1, char *arg2, char *res);
55 | int enc_float32_pow(char *arg1, char *arg2, char *res);
56 | int enc_float32_mod(char *arg1, char *arg2, char *res);
57 | int enc_float32_sum_bulk(size_t bulk_size, char *arg1, char *res);
58 |
59 | int enc_timestamp_decrypt(char* src, char *dst);
60 | int enc_timestamp_encrypt(char* src, char *dst);
61 | int enc_timestamp_cmp(char* src1, char *src2, char *dst);
62 | int enc_timestamp_extract_year(char* in, char* out);
63 |
64 | #if defined(__cplusplus)
65 | }
66 | #endif
67 |
68 | #endif /* !_APP_H_ */
69 |
--------------------------------------------------------------------------------
/src/include/untrusted/interface/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 | #include
8 | #include "sgx_urts.h"
9 | #include "sgx_tcrypto.h"
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "enclave/Queue.hpp"
19 | #include "tools/sync_utils.hpp"
20 | #include "tools/base64.hpp"
21 | #include "defs.h"
22 |
--------------------------------------------------------------------------------
/src/tools/Queue.cpp:
--------------------------------------------------------------------------------
1 | #include "enclave/Queue.hpp"
2 |
3 | Queue::Queue()
4 | {
5 | front = rear = 0;
6 | for (int i = 0; i < queue_size; i++)
7 | {
8 | q[i] = NULL;
9 | }
10 | }
11 |
12 | Queue::~Queue() {}
13 |
14 | int Queue::enqueue(request* elem)
15 | {
16 | spin_lock(&_lock);
17 |
18 | if (rear - front == queue_size)
19 | {
20 | spin_unlock(&_lock);
21 | abort();
22 | return -1;
23 | }
24 |
25 | q[rear % queue_size] = elem;
26 | ++rear;
27 |
28 | spin_unlock(&_lock);
29 | return 0;
30 | }
31 |
32 | request*
33 | Queue::dequeue()
34 | {
35 | spin_lock(&_lock);
36 |
37 | if (front == rear)
38 | {
39 | spin_unlock(&_lock);
40 | return NULL;
41 | }
42 |
43 | request* result = q[front % queue_size];
44 | ++front;
45 | spin_unlock(&_lock);
46 |
47 | return result;
48 | }
49 |
--------------------------------------------------------------------------------
/src/tools/bytes.cpp:
--------------------------------------------------------------------------------
1 | #include "tools/bytes.hpp"
2 |
3 | /* Convert an integer to a byte array.
4 | Should pay attention to the endian.
5 | @input: src - integer
6 | pDst - pointer to the result array with size INT32_LENGTH
7 | dstLen - length of the array
8 | @return:
9 | 1, if the size of array is less than INT32_LENGTH
10 | 0 otherwise
11 | */
12 | int int2bytearray(int src, uint8_t* pDst, size_t dstLen)
13 | {
14 | if (dstLen < INT32_LENGTH)
15 | return 1;
16 |
17 | memcpy(pDst, &src, INT32_LENGTH);
18 |
19 | return 0;
20 | }
21 |
22 | /* Convert an array to an integer.
23 | Should pay attention to the endian.
24 | @input:
25 | pDst - pointer to the result array with size INT32_LENGTH
26 | src - output integer
27 | dstLen - length of the array
28 | @return:
29 | 1, if the size of array is less than INT32_LENGTH
30 | 0 otherwise
31 |
32 | */
33 | int bytearray2int(uint8_t* pSrc, int& dst, size_t srcLen)
34 | {
35 | if (srcLen < INT32_LENGTH)
36 | return 1;
37 |
38 | memcpy(&dst, pSrc, INT32_LENGTH);
39 |
40 | return 0;
41 | }
42 |
--------------------------------------------------------------------------------
/src/tools/like_match.c:
--------------------------------------------------------------------------------
1 | /*-------------------------------------------------------------------------
2 | *
3 | * like_match.c
4 | * LIKE pattern matching internal code.
5 | *
6 | * This file is included by like.c four times, to provide matching code for
7 | * (1) single-byte encodings, (2) UTF8, (3) other multi-byte encodings,
8 | * and (4) case insensitive matches in single-byte encodings.
9 | * (UTF8 is a special case because we can use a much more efficient version
10 | * of NextChar than can be used for general multi-byte encodings.)
11 | *
12 | * Before the inclusion, we need to define the following macros:
13 | *
14 | * NextChar
15 | * MatchText - to name of function wanted
16 | * do_like_escape - name of function if wanted - needs CHAREQ and CopyAdvChar
17 | * MATCH_LOWER - define for case (4) to specify case folding for 1-byte chars
18 | *
19 | * Copyright (c) 1996-2018, PostgreSQL Global Development Group
20 | *
21 | * IDENTIFICATION
22 | * src/backend/utils/adt/like_match.c
23 | *
24 | *-------------------------------------------------------------------------
25 | */
26 |
27 | /*
28 | * Originally written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
29 | * Rich $alz is now .
30 | * Special thanks to Lars Mathiesen for the LABORT code.
31 | *
32 | * This code was shamelessly stolen from the "pql" code by myself and
33 | * slightly modified :)
34 | *
35 | * All references to the word "star" were replaced by "percent"
36 | * All references to the word "wild" were replaced by "like"
37 | *
38 | * All the nice shell RE matching stuff was replaced by just "_" and "%"
39 | *
40 | * As I don't have a copy of the SQL standard handy I wasn't sure whether
41 | * to leave in the '\' escape character handling.
42 | *
43 | * Keith Parks.
44 | *
45 | * SQL lets you specify the escape character by saying
46 | * LIKE ESCAPE . We are a small operation
47 | * so we force you to use '\'. - ay 7/95
48 | *
49 | * Now we have the like_escape() function that converts patterns with
50 | * any specified escape character (or none at all) to the internal
51 | * default escape character, which is still '\'. - tgl 9/2000
52 | *
53 | * The code is rewritten to avoid requiring null-terminated strings,
54 | * which in turn allows us to leave out some memcpy() operations.
55 | * This code should be faster and take less memory, but no promises...
56 | * - thomas 2000-08-06
57 | */
58 |
59 |
60 | /*--------------------
61 | * Match text and pattern, return LIKE_TRUE, LIKE_FALSE, or LIKE_ABORT.
62 | *
63 | * LIKE_TRUE: they match
64 | * LIKE_FALSE: they don't match
65 | * LIKE_ABORT: not only don't they match, but the text is too short.
66 | *
67 | * If LIKE_ABORT is returned, then no suffix of the text can match the
68 | * pattern either, so an upper-level % scan can stop scanning now.
69 | *--------------------
70 | */
71 |
72 | #include "tools/like_match.h"
73 |
74 | int
75 | MatchText(char *t, int tlen, char *p, int plen)
76 | {
77 | /* Fast path for match-everything pattern */
78 | if (plen == 1 && *p == '%')
79 | return LIKE_TRUE;
80 |
81 | /* Since this function recurses, it could be driven to stack overflow */
82 | /*check_stack_depth();*/
83 |
84 | /*
85 | * In this loop, we advance by char when matching wildcards (and thus on
86 | * recursive entry to this function we are properly char-synced). On other
87 | * occasions it is safe to advance by byte, as the text and pattern will
88 | * be in lockstep. This allows us to perform all comparisons between the
89 | * text and pattern on a byte by byte basis, even for multi-byte
90 | * encodings.
91 | */
92 | while (tlen > 0 && plen > 0)
93 | {
94 | if (*p == '\\')
95 | {
96 | /* Next pattern byte must match literally, whatever it is */
97 | NextByte(p, plen);
98 | /* ... and there had better be one, per SQL standard */
99 | if (plen <= 0)
100 | return LIKE_ABORT;
101 | if (GETCHAR(*p) != GETCHAR(*t))
102 | return LIKE_FALSE;
103 | }
104 | else if (*p == '%')
105 | {
106 | char firstpat;
107 |
108 | /*
109 | * % processing is essentially a search for a text position at
110 | * which the remainder of the text matches the remainder of the
111 | * pattern, using a recursive call to check each potential match.
112 | *
113 | * If there are wildcards immediately following the %, we can skip
114 | * over them first, using the idea that any sequence of N _'s and
115 | * one or more %'s is equivalent to N _'s and one % (ie, it will
116 | * match any sequence of at least N text characters). In this way
117 | * we will always run the recursive search loop using a pattern
118 | * fragment that begins with a literal character-to-match, thereby
119 | * not recursing more than we have to.
120 | */
121 | NextByte(p, plen);
122 |
123 | while (plen > 0)
124 | {
125 | if (*p == '%')
126 | NextByte(p, plen);
127 | else if (*p == '_')
128 | {
129 | /* If not enough text left to match the pattern, ABORT */
130 | if (tlen <= 0)
131 | return LIKE_ABORT;
132 | NextChar(t, tlen);
133 | NextByte(p, plen);
134 | }
135 | else
136 | break; /* Reached a non-wildcard pattern char */
137 | }
138 |
139 | /*
140 | * If we're at end of pattern, match: we have a trailing % which
141 | * matches any remaining text string.
142 | */
143 | if (plen <= 0)
144 | return LIKE_TRUE;
145 |
146 | /*
147 | * Otherwise, scan for a text position at which we can match the
148 | * rest of the pattern. The first remaining pattern char is known
149 | * to be a regular or escaped literal character, so we can compare
150 | * the first pattern byte to each text byte to avoid recursing
151 | * more than we have to. This fact also guarantees that we don't
152 | * have to consider a match to the zero-length substring at the
153 | * end of the text.
154 | */
155 | if (*p == '\\')
156 | {
157 | if (plen < 2)
158 | return LIKE_ABORT;
159 | firstpat = GETCHAR(p[1]);
160 | }
161 | else
162 | firstpat = GETCHAR(*p);
163 |
164 | while (tlen > 0)
165 | {
166 | if (GETCHAR(*t) == firstpat)
167 | {
168 | int matched = MatchText(t, tlen, p, plen);
169 |
170 | if (matched != LIKE_FALSE)
171 | return matched; /* TRUE or ABORT */
172 | }
173 |
174 | NextChar(t, tlen);
175 | }
176 |
177 | /*
178 | * End of text with no match, so no point in trying later places
179 | * to start matching this pattern.
180 | */
181 | return LIKE_ABORT;
182 | }
183 | else if (*p == '_')
184 | {
185 | /* _ matches any single character, and we know there is one */
186 | NextChar(t, tlen);
187 | NextByte(p, plen);
188 | continue;
189 | }
190 | else if (GETCHAR(*p) != GETCHAR(*t))
191 | {
192 | /* non-wildcard pattern char fails to match text char */
193 | return LIKE_FALSE;
194 | }
195 |
196 | /*
197 | * Pattern and text match, so advance.
198 | *
199 | * It is safe to use NextByte instead of NextChar here, even for
200 | * multi-byte character sets, because we are not following immediately
201 | * after a wildcard character. If we are in the middle of a multibyte
202 | * character, we must already have matched at least one byte of the
203 | * character from both text and pattern; so we cannot get out-of-sync
204 | * on character boundaries. And we know that no backend-legal
205 | * encoding allows ASCII characters such as '%' to appear as non-first
206 | * bytes of characters, so we won't mistakenly detect a new wildcard.
207 | */
208 | NextByte(t, tlen);
209 | NextByte(p, plen);
210 | }
211 |
212 | if (tlen > 0)
213 | return LIKE_FALSE; /* end of pattern, but not of text */
214 |
215 | /*
216 | * End of text, but perhaps not of pattern. Match iff the remaining
217 | * pattern can match a zero-length string, ie, it's zero or more %'s.
218 | */
219 | while (plen > 0 && *p == '%')
220 | NextByte(p, plen);
221 | if (plen <= 0)
222 | return LIKE_TRUE;
223 |
224 | /*
225 | * End of text with no match, so no point in trying later places to start
226 | * matching this pattern.
227 | */
228 | return LIKE_ABORT;
229 | } /* MatchText() */
230 |
--------------------------------------------------------------------------------
/src/tools/oblvs_int32_ops.S:
--------------------------------------------------------------------------------
1 | %macro DEF 1
2 | global %1:function
3 | %1:
4 | %endmacro
5 |
6 | section .text
7 |
8 | DEF obs_int32_eq
9 | xor eax, eax
10 | cmp edi, esi
11 | sete al
12 | ret
13 |
14 | DEF obs_int32_lt
15 | xor eax, eax
16 | cmp edi, esi
17 | setl al
18 | ret
19 |
20 | DEF obs_int32_select
21 | test edx, edx
22 | cmovne edi, esi
23 | mov eax, edi
24 | ret
25 |
26 | obs_int32_bits:
27 | xor eax, eax
28 | cmp edi, 65535
29 | seta al
30 | shl eax, 4
31 | mov ecx, eax
32 | shr edi, cl
33 | xor edx, edx
34 | cmp edi, 255
35 | seta dl
36 | lea ecx, [8*rdx]
37 | shr edi, cl
38 | lea eax, [rax + 8*rdx]
39 | xor edx, edx
40 | cmp edi, 15
41 | seta dl
42 | lea ecx, [4*rdx]
43 | shr edi, cl
44 | lea eax, [rax + 4*rdx]
45 | xor edx, edx
46 | cmp edi, 3
47 | seta dl
48 | lea ecx, [rdx + rdx]
49 | shr edi, cl
50 | lea eax, [rax + 2*rdx]
51 | shr edi, 1
52 | or eax, edi
53 | ret
54 |
55 | DEF obs_int32_pow
56 | push r14
57 | push rbx
58 |
59 | mov r14d, edi
60 | mov edi, esi
61 | call obs_int32_bits
62 | mov edi, r14d
63 | mov r14d, eax
64 |
65 | mov eax, 1
66 |
67 | .loop:
68 | mov ebx, 1
69 | mov ecx, r14d
70 | shl ebx, cl
71 | and ebx, esi
72 |
73 | mov r8d, eax
74 |
75 | imul eax, eax
76 | imul r8d, edi
77 | imul edi, edi
78 |
79 | xor edx, edx
80 | test ebx, ebx
81 | setne dl
82 | neg edx
83 | mov ebx, edx
84 |
85 | and ebx, r8d
86 | mov ecx, edx
87 | not ecx
88 | and eax, ecx
89 | or eax, ebx
90 |
91 | and edx, edi
92 | and ecx, r8d
93 | or ecx, edx
94 |
95 | test r14d, r14d
96 |
97 | lea edx, [r14 - 1]
98 | mov r14d, edx
99 | mov edi, ecx
100 | jg .loop
101 |
102 | pop rbx
103 | pop r14
104 | ret
105 |
--------------------------------------------------------------------------------
/src/tools/sync_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "tools/sync_utils.hpp"
2 |
3 | void spin_lock(int volatile* p)
4 | {
5 | while (!__sync_bool_compare_and_swap(p, 0, 1))
6 | {
7 | while (*p)
8 | __asm__("pause");
9 | }
10 | }
11 |
12 | void spin_unlock(int volatile* p)
13 | {
14 | asm volatile(""); // acts as a memory barrier.
15 | *p = 0;
16 | }
17 |
18 | void spin_lock(unsigned char volatile* p)
19 | {
20 | while (!__sync_bool_compare_and_swap(p, 0, 1))
21 | {
22 | while (*p)
23 | __asm__("pause");
24 | }
25 | }
26 |
27 | void spin_unlock(unsigned char volatile* p)
28 | {
29 | asm volatile(""); // acts as a memory barrier.
30 | *p = 0;
31 | }
32 |
--------------------------------------------------------------------------------
/src/tools/timestamp.c:
--------------------------------------------------------------------------------
1 | #include "tools/timestamp.h"
2 |
3 | /*-------------------------------------------------------------------------
4 | *
5 | * This function has been adapted from the timestamp2tm function found in
6 | * src/backend/utils/adt/timestamp.c of the PostgreSQL source, a file
7 | * for which:
8 | *
9 | * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
10 | * Portions Copyright (c) 1994, Regents of the University of California
11 | */
12 |
13 | int year_from_timestamp(int64_t timestamp)
14 | {
15 |
16 | int64_t date;
17 | unsigned int quad;
18 | unsigned int extra;
19 | int year;
20 |
21 | TMODULO(timestamp, date, USECS_PER_DAY);
22 | if (timestamp < INT64CONST(0))
23 | {
24 | timestamp += USECS_PER_DAY;
25 | date -= 1;
26 | }
27 |
28 | /* add offset to go from J2000 back to standard Julian date */
29 | date += POSTGRES_EPOCH_JDATE;
30 |
31 | /* Julian day routine does not work for negative Julian days */
32 | if (date < 0 || date > (int64_t)INT_MAX)
33 | return -1;
34 |
35 | date += 32044;
36 | quad = date / 146097;
37 | extra = (date - quad * 146097) * 4 + 3;
38 |
39 | date += 60 + quad * 3 + extra / 146097;
40 | quad = date / 1461;
41 | date -= quad * 1461;
42 |
43 | year = date * 4 / 1461;
44 | year += quad * 4;
45 | return year - 4800;
46 | }
47 |
--------------------------------------------------------------------------------
/src/untrusted.mk:
--------------------------------------------------------------------------------
1 | include vars.mk
2 |
3 | UNTRUSTED_DIR=untrusted
4 | INTERFACE_DIR=untrusted/interface
5 | EXTENSION_DIR=untrusted/extensions
6 | PSQL_PKG_LIBDIR = $(shell pg_config --pkglibdir)
7 | PSQL_SHAREDIR = $(shell pg_config --sharedir)/extension
8 | PSQL_LIBDIR = $(shell pg_config --libdir)
9 |
10 | EXTENSION = $(EXTENSION_DIR)/encdb # the extension's name
11 | DATA = $(EXTENSION_DIR)/encdb--0.0.1.sql # scripts to install
12 |
13 | C_SRCS := $(wildcard $(EXTENSION_DIR)/*.c)
14 | C_OBJS := $(C_SRCS:.c=.o)
15 |
16 | CXX_SRCS := $(wildcard tools/*.cpp) $(wildcard $(INTERFACE_DIR)/*.cpp)
17 | CXX_OBJS := $(CXX_SRCS:.cpp=.o)
18 |
19 | PSQL_CPPFLAGS := $(addprefix -I, $(CURDIR) $(shell pg_config --includedir-server) $(shell pg_config --includedir))
20 |
21 | CPPFLAGS := -DTOKEN_FILENAME=\"$(STEALTHDIR)/$(ENCLAVE_NAME).token\" \
22 | -DENCLAVE_FILENAME=\"$(STEALTHDIR)/$(ENCLAVE_NAME).signed.so\" \
23 | -DDATA_FILENAME=\"$(STEALTHDIR)/stealthDB.data\" \
24 | $(addprefix -I, include $(SGX_INCLUDE_PATH) $(UNTRUSTED_DIR))
25 |
26 | FLAGS := -m64 -O0 -g -fPIC -Wall -Wextra -Wpedantic
27 | CFLAGS := $(FLAGS) $(CPPFLAGS)
28 | CXXFLAGS := $(FLAGS) $(CPPFLAGS) -std=c++11
29 | LDFLAGS := -lsgx_urts -lpthread
30 |
31 | .PHONY: all
32 | all: $(UNTRUSTED_DIR)/encdb.so
33 |
34 | tools/%.o: tools/%.cpp
35 | @$(CXX) $(CXXFLAGS) -c $< -o $@
36 | @echo "CXX <= $<"
37 |
38 | $(UNTRUSTED_DIR)/enclave_u.c: $(SGX_EDGER8R) $(ENCLAVE_DIR)/enclave.edl
39 | @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../$(ENCLAVE_DIR)/enclave.edl
40 | @echo "GEN => $@"
41 |
42 | $(UNTRUSTED_DIR)/enclave_u.o: $(UNTRUSTED_DIR)/enclave_u.c
43 | @$(CC) $(CFLAGS) -c $< -o $@
44 | @echo "CC <= $<"
45 |
46 | $(INTERFACE_DIR)/%.o: $(INTERFACE_DIR)/%.cpp
47 | @$(CXX) $(CXXFLAGS) -o $@ -c $^
48 | @echo "CXX interface <= $<"
49 |
50 |
51 | $(EXTENSION_DIR)/%.o: $(EXTENSION_DIR)/%.c
52 | @$(CC) $(CFLAGS) $(PSQL_CPPFLAGS) -o $@ -c $^
53 | @echo "CC extension <= $<"
54 |
55 | $(UNTRUSTED_DIR)/encdb.so: $(UNTRUSTED_DIR)/enclave_u.o $(CXX_OBJS) $(C_OBJS)
56 | @$(CC) -shared -L$(PSQL_LIBDIR) $^ -o $@ $(LDFLAGS)
57 | @echo "CC extension <= $<"
58 | @mkdir -p $(BUILD_DIR)
59 | @mv $(UNTRUSTED_DIR)/encdb.so $(BUILD_DIR)
60 | @cp $(EXTENSION_DIR)/*.control $(BUILD_DIR)
61 | @cp $(EXTENSION_DIR)/*.sql $(BUILD_DIR)
62 |
63 |
64 | .PHONY: install
65 | install: | $(STEALTHDIR)
66 | cp $(BUILD_DIR)/encdb.so $(PSQL_PKG_LIBDIR)
67 | cp $(BUILD_DIR)/*.control $(PSQL_SHAREDIR)
68 | cp $(BUILD_DIR)/*.sql $(PSQL_SHAREDIR)
69 | @test -e $(STEALTHDIR)/stealthDB.data || touch $(STEALTHDIR)/stealthDB.data
70 | @chown postgres:postgres $(STEALTHDIR)/stealthDB.data
71 |
72 | $(STEALTHDIR):
73 | mkdir -p $@
74 |
75 | .PHONY: uninstall
76 | uninstall:
77 | $(RM) $(PSQL_PKG_LIBDIR).encdb.so \
78 | $(PSQL_SHAREDIR)/*.control \
79 | $(PSQL_SHAREDIR)/*.sql \
80 | -r $(STEALTHDIR) $(BUILD_DIR)
81 |
82 | .PHONY: clean
83 | clean:
84 | @$(RM) $(CXX_OBJS) $(C_OBJS) $(UNTRUSTED_DIR)/enclave_u.*
85 |
--------------------------------------------------------------------------------
/src/untrusted/Makefile:
--------------------------------------------------------------------------------
1 | MODULES = encdb
2 | EXTENSION = encdb
3 | DATA = encdb--0.0.1.sql
4 | PG_CONFIG = pg_config
5 | PGXS := $(shell $(PG_CONFIG) --pgxs)
6 | include $(PGXS)
7 |
--------------------------------------------------------------------------------
/src/untrusted/extensions/encdb.c:
--------------------------------------------------------------------------------
1 | #include "untrusted/extensions/stdafx.h"
2 |
3 | PG_MODULE_MAGIC;
4 | bool debugMode = false;
5 |
6 | void sgxErrorHandler(int code)
7 | {
8 | size_t i;
9 | size_t ttl = sizeof sgx_errlist / sizeof sgx_errlist[0];
10 |
11 | if ((code > 1) || (code < -6))
12 | {
13 | for (i = 0; i < ttl; i++)
14 | {
15 | if (sgx_errlist[i].err == code)
16 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: %s \n", code, sgx_errlist[i].msg)));
17 | }
18 | //ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE: %d \n", code)));
19 | }
20 |
21 | if (code == -2)
22 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: ENCLAVE IS NOT RUNNING", code)));
23 | if (code == -3)
24 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: MEMORY_COPY_ERROR", code)));
25 | if (code == -4)
26 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: ARITHMETIC_ERROR", code)));
27 | if (code == -5)
28 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: MEMORY_ALLOCATION_ERROR", code)));
29 | if (code == -6)
30 | ereport(ERROR, (-1, errmsg("SGX_ERROR_CODE %d: OUT_OF_THE_RANGE_ERROR", code)));
31 | if (code == -7)
32 | ereport(ERROR, (-1, errmsg("INTERFACE_ERROR_CODE %d: BASE64DECODER_ERROR", code)));
33 | if (code == -8)
34 | ereport(ERROR, (-1, errmsg("INTERFACE_ERROR_CODE %d: \n The extension was not initialized. Run 'select launch();'", code)));
35 | if (code == -9)
36 | ereport(ERROR, (-1, errmsg("INTERFACE_ERROR_CODE %d: \n Cannot open key storage file.'", code)));
37 | if (code == -10)
38 | ereport(ERROR, (-1, errmsg("INTERFACE_ERROR_CODE %d: \n The default master key was not set up. Run 'select generate_key();'.", code)));
39 | if (code == TOO_MANY_ELEMENTS_IN_BULK)
40 | ereport(ERROR, (-1, errmsg("INTERFACE_ERROR_CODE %d: Too many elements in a bulk for an aggregation function.", code)));
41 | }
42 |
43 | PG_FUNCTION_INFO_V1(launch);
44 | Datum
45 | launch(PG_FUNCTION_ARGS)
46 | {
47 | int resp = initMultithreading();
48 | sgxErrorHandler(resp);
49 | resp = loadKey(0);
50 | sgxErrorHandler(resp);
51 | ereport(INFO, (errmsg("StealthDB is initialized: the default key has been loaded.")));
52 |
53 | PG_RETURN_INT32(resp);
54 | }
55 |
56 | PG_FUNCTION_INFO_V1(generate_key);
57 | Datum
58 | generate_key(PG_FUNCTION_ARGS)
59 | {
60 | int resp = generateKey();
61 | sgxErrorHandler(resp);
62 |
63 | PG_RETURN_INT32(resp);
64 | }
65 |
66 | PG_FUNCTION_INFO_V1(load_key);
67 | Datum
68 | load_key(PG_FUNCTION_ARGS)
69 | {
70 | int item = PG_GETARG_INT64(0);
71 |
72 | int resp = loadKey(item);
73 | sgxErrorHandler(resp);
74 |
75 | PG_RETURN_INT32(resp);
76 | }
77 |
78 | PG_FUNCTION_INFO_V1(enable_debug_mode);
79 | Datum
80 | enable_debug_mode(PG_FUNCTION_ARGS)
81 | {
82 | int item = PG_GETARG_INT64(0);
83 | debugMode = item;
84 |
85 | PG_RETURN_INT32(0);
86 | }
87 |
--------------------------------------------------------------------------------
/src/untrusted/extensions/encdb.control:
--------------------------------------------------------------------------------
1 | # encrypted database extension
2 | default_version = '0.0.1'
3 | module_pathname = '$libdir/encdb'
4 | relocatable = true
5 |
--------------------------------------------------------------------------------
/src/untrusted/interface/enc_float32.cpp:
--------------------------------------------------------------------------------
1 | #include "untrusted/interface/interface.h"
2 | #include "untrusted/interface/stdafx.h"
3 | #include // for copy
4 | #include
5 |
6 | extern sgx_enclave_id_t global_eid;
7 | extern Queue* inQueue;
8 | extern bool status;
9 |
10 | int enc_float32_sum_bulk(size_t bulk_size, char* arg1, char* res)
11 | {
12 | if (!status)
13 | {
14 | int resp = initMultithreading();
15 | resp = loadKey(0);
16 | // return resp;//IS_NOT_INITIALIZE;
17 | }
18 | int current_position = 0, arg_position = 0;
19 | int resp = ENCLAVE_IS_NOT_RUNNING;
20 | request* req = new request;
21 |
22 | uint8_t* int2_v = (uint8_t*)malloc(bulk_size * ENC_FLOAT4_LENGTH);
23 | uint8_t* int3_v = (uint8_t*)malloc(ENC_FLOAT4_LENGTH);
24 |
25 | memcpy(req->buffer, &bulk_size, FLOAT4_LENGTH);
26 | current_position += FLOAT4_LENGTH;
27 |
28 | size_t counter = 0;
29 |
30 | if (req->max_buffer_size < bulk_size * ENC_FLOAT4_LENGTH)
31 | return TOO_MANY_ELEMENTS_IN_BULK;
32 |
33 | while (counter < bulk_size)
34 | {
35 | if (!FromBase64Fast((const BYTE*)arg1 + arg_position,
36 | ENC_FLOAT4_LENGTH_B64 - 1,
37 | int2_v,
38 | ENC_FLOAT4_LENGTH))
39 | return BASE64DECODER_ERROR;
40 |
41 | memcpy(req->buffer + current_position, int2_v, ENC_FLOAT4_LENGTH);
42 | current_position += ENC_FLOAT4_LENGTH;
43 | arg_position += ENC_FLOAT4_LENGTH_B64;
44 | counter++;
45 | }
46 |
47 | req->ocall_index = CMD_FLOAT4_SUM_BULK;
48 | req->is_done = -1;
49 |
50 | inQueue->enqueue(req);
51 | while (true)
52 | {
53 | if (req->is_done == -1)
54 | {
55 | __asm__("pause");
56 | }
57 | else
58 | {
59 | memcpy(int3_v, req->buffer + current_position, ENC_FLOAT4_LENGTH);
60 | resp = req->resp;
61 | if (!ToBase64Fast(
62 | (const BYTE*)int3_v, ENC_FLOAT4_LENGTH, res, ENC_FLOAT4_LENGTH_B64))
63 | resp = BASE64DECODER_ERROR;
64 | spin_unlock(&req->is_done);
65 | break;
66 | }
67 | }
68 |
69 | delete req;
70 | return resp;
71 | }
72 |
73 | int enc_float32_ops(int cmd, char* src1, char* src2, char* res)
74 | {
75 | if (!status)
76 | {
77 | int resp = initMultithreading();
78 | resp = loadKey(0);
79 | // return resp;//IS_NOT_INITIALIZE;
80 | }
81 |
82 | int resp = ENCLAVE_IS_NOT_RUNNING;
83 | request* req = new request;
84 |
85 | std::array src1_decoded;
86 | std::array src2_decoded;
87 | std::array dst_decoded;
88 |
89 | if (!FromBase64Fast((const BYTE*)src1,
90 | ENC_FLOAT4_LENGTH_B64 - 1,
91 | src1_decoded.begin(),
92 | ENC_FLOAT4_LENGTH))
93 | return BASE64DECODER_ERROR;
94 |
95 | if (!FromBase64Fast((const BYTE*)src2,
96 | ENC_FLOAT4_LENGTH_B64 - 1,
97 | src2_decoded.begin(),
98 | ENC_FLOAT4_LENGTH))
99 | return BASE64DECODER_ERROR;
100 |
101 | std::copy(src1_decoded.begin(), src1_decoded.end(), &req->buffer[0]);
102 | std::copy(
103 | src2_decoded.begin(), src2_decoded.end(), &req->buffer[ENC_FLOAT4_LENGTH]);
104 |
105 | req->ocall_index = cmd;
106 | req->is_done = -1;
107 |
108 | inQueue->enqueue(req);
109 |
110 | while (true)
111 | {
112 | if (req->is_done == -1)
113 | {
114 | __asm__("pause");
115 | }
116 | else
117 | {
118 | std::copy(&req->buffer[2 * ENC_FLOAT4_LENGTH],
119 | &req->buffer[3 * ENC_FLOAT4_LENGTH],
120 | dst_decoded.begin());
121 | resp = req->resp;
122 | if (!ToBase64Fast((const BYTE*)dst_decoded.begin(),
123 | ENC_FLOAT4_LENGTH,
124 | res,
125 | ENC_FLOAT4_LENGTH_B64))
126 | resp = BASE64DECODER_ERROR;
127 | spin_unlock(&req->is_done);
128 | break;
129 | }
130 | }
131 |
132 | delete req;
133 | return resp;
134 | }
135 |
136 | int enc_float32_add(char* src1, char* src2, char* res)
137 | {
138 | int resp = enc_float32_ops(CMD_FLOAT4_PLUS, src1, src2, res);
139 | return resp;
140 | }
141 |
142 | int enc_float32_sub(char* src1, char* src2, char* res)
143 | {
144 | int resp = enc_float32_ops(CMD_FLOAT4_MINUS, src1, src2, res);
145 | return resp;
146 | }
147 |
148 | int enc_float32_mult(char* src1, char* src2, char* res)
149 | {
150 | int resp = enc_float32_ops(CMD_FLOAT4_MULT, src1, src2, res);
151 | return resp;
152 | }
153 |
154 | int enc_float32_div(char* src1, char* src2, char* res)
155 | {
156 | int resp = enc_float32_ops(CMD_FLOAT4_DIV, src1, src2, res);
157 | return resp;
158 | }
159 |
160 | int enc_float32_pow(char* src1, char* src2, char* res)
161 | {
162 | int resp = enc_float32_ops(CMD_FLOAT4_EXP, src1, src2, res);
163 | return resp;
164 | }
165 |
166 | int enc_float32_mod(char* src1, char* src2, char* res)
167 | {
168 | int resp = enc_float32_ops(CMD_FLOAT4_MOD, src1, src2, res);
169 | return resp;
170 | }
171 |
172 | int enc_float32_cmp(char* src1, char* src2, char* res)
173 | {
174 | if (!status)
175 | {
176 | int resp = initMultithreading();
177 | resp = loadKey(0);
178 | // return resp;//IS_NOT_INITIALIZE;
179 | }
180 |
181 | int resp = ENCLAVE_IS_NOT_RUNNING;
182 | request* req = new request;
183 |
184 | std::array src1_decoded;
185 | std::array src2_decoded;
186 |
187 | if (!FromBase64Fast((const BYTE*)src1,
188 | ENC_FLOAT4_LENGTH_B64 - 1,
189 | src1_decoded.begin(),
190 | ENC_FLOAT4_LENGTH))
191 | return BASE64DECODER_ERROR;
192 |
193 | if (!FromBase64Fast((const BYTE*)src2,
194 | ENC_FLOAT4_LENGTH_B64 - 1,
195 | src2_decoded.begin(),
196 | ENC_FLOAT4_LENGTH))
197 | return BASE64DECODER_ERROR;
198 |
199 | std::copy(src1_decoded.begin(), src1_decoded.end(), &req->buffer[0]);
200 | std::copy(
201 | src2_decoded.begin(), src2_decoded.end(), &req->buffer[ENC_FLOAT4_LENGTH]);
202 | req->ocall_index = CMD_FLOAT4_CMP;
203 | req->is_done = -1;
204 |
205 | inQueue->enqueue(req);
206 |
207 | while (true)
208 | {
209 | if (req->is_done == -1)
210 | {
211 | __asm__("pause");
212 | }
213 | else
214 | {
215 | resp = req->resp;
216 | std::copy(&req->buffer[2 * ENC_FLOAT4_LENGTH],
217 | &req->buffer[2 * ENC_FLOAT4_LENGTH + FLOAT4_LENGTH],
218 | &res[0]);
219 | spin_unlock(&req->is_done);
220 |
221 | // res[0] = req->ocall_index;
222 | break;
223 | }
224 | }
225 | delete req;
226 |
227 | return resp;
228 | }
229 |
230 | int enc_float32_encrypt(float pSrc, char* pDst)
231 | {
232 | if (!status)
233 | {
234 | int resp = initMultithreading();
235 | resp = loadKey(0);
236 | // return resp;//IS_NOT_INITIALIZE;
237 | }
238 |
239 | int resp = ENCLAVE_IS_NOT_RUNNING;
240 | request* req = new request();
241 | std::array encrypted_src;
242 |
243 | memcpy(req->buffer, &pSrc, FLOAT4_LENGTH);
244 | req->ocall_index = CMD_FLOAT4_ENC;
245 | req->is_done = -1;
246 |
247 | inQueue->enqueue(req);
248 |
249 | while (true)
250 | {
251 | if (req->is_done == -1)
252 | {
253 | __asm__("pause");
254 | }
255 | else
256 | {
257 | std::copy(&req->buffer[FLOAT4_LENGTH],
258 | &req->buffer[FLOAT4_LENGTH + ENC_FLOAT4_LENGTH],
259 | encrypted_src.begin());
260 | resp = req->resp;
261 | spin_unlock(&req->is_done);
262 | break;
263 | }
264 | }
265 |
266 | if (!ToBase64Fast((const BYTE*)encrypted_src.begin(),
267 | ENC_FLOAT4_LENGTH,
268 | pDst,
269 | ENC_FLOAT4_LENGTH_B64))
270 | resp = BASE64DECODER_ERROR;
271 |
272 | pDst[ENC_FLOAT4_LENGTH_B64 - 1] = '\0';
273 | delete req;
274 |
275 | return resp;
276 | }
277 |
278 | int enc_float32_decrypt(char* pSrc, char* pDst)
279 | {
280 | if (!status)
281 | {
282 | int resp = initMultithreading();
283 | resp = loadKey(0);
284 | // return resp;//IS_NOT_INITIALIZE;
285 | }
286 |
287 | int resp = ENCLAVE_IS_NOT_RUNNING;
288 | request* req = new request;
289 |
290 | std::array src_decoded;
291 | if (!FromBase64Fast((const BYTE*)pSrc,
292 | ENC_FLOAT4_LENGTH_B64 - 1,
293 | src_decoded.begin(),
294 | ENC_FLOAT4_LENGTH))
295 | return BASE64DECODER_ERROR;
296 |
297 | std::copy(src_decoded.begin(), src_decoded.end(), &req->buffer[0]);
298 | req->ocall_index = CMD_FLOAT4_DEC;
299 | req->is_done = -1;
300 |
301 | inQueue->enqueue(req);
302 |
303 | while (true)
304 | {
305 | if (req->is_done == -1)
306 | {
307 | __asm__("pause");
308 | }
309 | else
310 | {
311 | std::copy(&req->buffer[ENC_FLOAT4_LENGTH],
312 | &req->buffer[ENC_FLOAT4_LENGTH + FLOAT4_LENGTH],
313 | &pDst[0]);
314 | resp = req->resp;
315 | spin_unlock(&req->is_done);
316 | break;
317 | }
318 | }
319 |
320 | delete req;
321 |
322 | return resp;
323 | }
324 |
--------------------------------------------------------------------------------
/src/untrusted/interface/enc_int32.cpp:
--------------------------------------------------------------------------------
1 | #include "untrusted/interface/interface.h"
2 | #include "untrusted/interface/stdafx.h"
3 |
4 | extern sgx_enclave_id_t global_eid;
5 | extern Queue* inQueue;
6 | extern bool status;
7 |
8 | int enc_int32_sum_bulk(size_t bulk_size, char* arg1, char* res)
9 | {
10 | if (!status)
11 | {
12 | int resp = initMultithreading();
13 | resp = loadKey(0);
14 | // return resp;//IS_NOT_INITIALIZE;
15 | }
16 | int current_position = 0, arg_position = 0;
17 | int resp = ENCLAVE_IS_NOT_RUNNING;
18 | request* req = new request;
19 |
20 | uint8_t* int2_v = (uint8_t*)malloc(bulk_size * ENC_INT32_LENGTH);
21 | uint8_t* int3_v = (uint8_t*)malloc(ENC_INT32_LENGTH);
22 |
23 | memcpy(req->buffer, &bulk_size, INT32_LENGTH);
24 | current_position += INT32_LENGTH;
25 |
26 | size_t counter = 0;
27 |
28 | if (req->max_buffer_size < bulk_size * ENC_INT32_LENGTH)
29 | return TOO_MANY_ELEMENTS_IN_BULK;
30 |
31 | while (counter < bulk_size)
32 | {
33 | if (!FromBase64Fast((const BYTE*)arg1 + arg_position,
34 | ENC_INT32_LENGTH_B64 - 1,
35 | int2_v,
36 | ENC_INT32_LENGTH))
37 | return BASE64DECODER_ERROR;
38 |
39 | memcpy(req->buffer + current_position, int2_v, ENC_INT32_LENGTH);
40 | current_position += ENC_INT32_LENGTH;
41 | arg_position += ENC_INT32_LENGTH_B64;
42 | counter++;
43 | }
44 |
45 | req->ocall_index = CMD_INT32_SUM_BULK;
46 | req->is_done = -1;
47 |
48 | inQueue->enqueue(req);
49 | while (true)
50 | {
51 | if (req->is_done == -1)
52 | {
53 | __asm__("pause");
54 | }
55 | else
56 | {
57 | memcpy(int3_v, req->buffer + current_position, ENC_INT32_LENGTH);
58 | resp = req->resp;
59 | if (!ToBase64Fast(
60 | (const BYTE*)int3_v, ENC_INT32_LENGTH, res, ENC_INT32_LENGTH_B64))
61 | resp = BASE64DECODER_ERROR;
62 | spin_unlock(&req->is_done);
63 | break;
64 | }
65 | }
66 |
67 | delete req;
68 |
69 | return resp;
70 | }
71 |
72 | int enc_int32_ops(int cmd, char* int1, char* int2, char* res)
73 | {
74 | if (!status)
75 | {
76 | int resp = initMultithreading();
77 | resp = loadKey(0);
78 | // return resp;//IS_NOT_INITIALIZE;
79 | }
80 |
81 | int resp = ENCLAVE_IS_NOT_RUNNING;
82 | request* req = new request;
83 |
84 | std::array int1_v;
85 | std::array int2_v;
86 | std::array int3_v;
87 |
88 | if (!FromBase64Fast((const BYTE*)int1,
89 | ENC_INT32_LENGTH_B64 - 1,
90 | int1_v.begin(),
91 | ENC_INT32_LENGTH))
92 | return BASE64DECODER_ERROR;
93 |
94 | if (!FromBase64Fast((const BYTE*)int2,
95 | ENC_INT32_LENGTH_B64 - 1,
96 | int2_v.begin(),
97 | ENC_INT32_LENGTH))
98 | return BASE64DECODER_ERROR;
99 |
100 | std::copy(int1_v.begin(), int1_v.end(), &req->buffer[0]);
101 | std::copy(int2_v.begin(), int2_v.end(), &req->buffer[ENC_INT32_LENGTH]);
102 |
103 | req->ocall_index = cmd;
104 | req->is_done = -1;
105 |
106 | inQueue->enqueue(req);
107 |
108 | while (true)
109 | {
110 | if (req->is_done == -1)
111 | {
112 | __asm__("pause");
113 | }
114 | else
115 | {
116 | std::copy(&req->buffer[2 * ENC_INT32_LENGTH],
117 | &req->buffer[3 * ENC_INT32_LENGTH],
118 | int3_v.begin());
119 | resp = req->resp;
120 | if (!ToBase64Fast((const BYTE*)int3_v.begin(),
121 | ENC_INT32_LENGTH,
122 | res,
123 | ENC_INT32_LENGTH_B64))
124 | resp = BASE64DECODER_ERROR;
125 | spin_unlock(&req->is_done);
126 | break;
127 | }
128 | }
129 |
130 | delete req;
131 |
132 | return resp;
133 | }
134 |
135 | int enc_int32_add(char* int1, char* int2, char* res)
136 | {
137 | return enc_int32_ops(CMD_INT64_PLUS, int1, int2, res);
138 | }
139 |
140 | int enc_int32_sub(char* int1, char* int2, char* res)
141 | {
142 | int resp = enc_int32_ops(CMD_INT64_MINUS, int1, int2, res);
143 | return resp;
144 | }
145 |
146 | int enc_int32_mult(char* int1, char* int2, char* res)
147 | {
148 | int resp = enc_int32_ops(CMD_INT64_MULT, int1, int2, res);
149 | return resp;
150 | }
151 |
152 | int enc_int32_div(char* int1, char* int2, char* res)
153 | {
154 | int resp = enc_int32_ops(CMD_INT64_DIV, int1, int2, res);
155 | return resp;
156 | }
157 |
158 | int enc_int32_pow(char* int1, char* int2, char* res)
159 | {
160 | int resp = enc_int32_ops(CMD_INT64_EXP, int1, int2, res);
161 | return resp;
162 | }
163 |
164 | int enc_int32_mod(char* int1, char* int2, char* res)
165 | {
166 | int resp = enc_int32_ops(CMD_INT64_MOD, int1, int2, res);
167 | return resp;
168 | }
169 |
170 | int enc_int32_cmp(char* int1, char* int2, char* res)
171 | {
172 | if (!status)
173 | {
174 | int resp = initMultithreading();
175 | resp = loadKey(0);
176 | // return resp;//IS_NOT_INITIALIZE;
177 | }
178 | int resp = ENCLAVE_IS_NOT_RUNNING;
179 | request* req = new request;
180 |
181 | std::array int1_v;
182 | std::array int2_v;
183 |
184 | if (!FromBase64Fast((const BYTE*)int1,
185 | ENC_INT32_LENGTH_B64 - 1,
186 | int1_v.begin(),
187 | ENC_INT32_LENGTH))
188 | return BASE64DECODER_ERROR;
189 |
190 | if (!FromBase64Fast((const BYTE*)int2,
191 | ENC_INT32_LENGTH_B64 - 1,
192 | int2_v.begin(),
193 | ENC_INT32_LENGTH))
194 | return BASE64DECODER_ERROR;
195 |
196 | std::copy(int1_v.begin(), int1_v.end(), &req->buffer[0]);
197 | std::copy(int2_v.begin(), int2_v.end(), &req->buffer[ENC_INT32_LENGTH]);
198 |
199 | req->ocall_index = CMD_INT64_CMP;
200 | req->is_done = -1;
201 | inQueue->enqueue(req);
202 |
203 | while (true)
204 | {
205 | if (req->is_done == -1)
206 | {
207 | __asm__("pause");
208 | }
209 | else
210 | {
211 | resp = req->resp;
212 | std::copy(&req->buffer[2 * ENC_INT32_LENGTH],
213 | &req->buffer[2 * ENC_INT32_LENGTH + INT32_LENGTH],
214 | &res[0]);
215 | spin_unlock(&req->is_done);
216 | break;
217 | }
218 | }
219 | delete req;
220 | return resp;
221 | }
222 |
223 | int enc_int32_encrypt(int pSrc, char* pDst)
224 | {
225 | if (!status)
226 | {
227 | int resp = initMultithreading();
228 | resp = loadKey(0);
229 | // return resp;//IS_NOT_INITIALIZE;
230 | }
231 |
232 | int resp = ENCLAVE_IS_NOT_RUNNING;
233 | request* req = new request;
234 | std::array int1_v;
235 |
236 | memcpy(req->buffer, &pSrc, INT32_LENGTH);
237 | req->ocall_index = CMD_INT64_ENC;
238 | req->is_done = -1;
239 |
240 | inQueue->enqueue(req);
241 | while (true)
242 | {
243 | if (req->is_done == -1)
244 | {
245 | __asm__("pause");
246 | }
247 | else
248 | {
249 | std::copy(&req->buffer[INT32_LENGTH],
250 | &req->buffer[INT32_LENGTH + ENC_INT32_LENGTH],
251 | int1_v.begin());
252 | resp = req->resp;
253 | // spin_unlock(&req->is_done);
254 | break;
255 | }
256 | }
257 |
258 | if (!ToBase64Fast((const BYTE*)int1_v.begin(),
259 | ENC_INT32_LENGTH,
260 | pDst,
261 | ENC_INT32_LENGTH_B64))
262 | resp = BASE64DECODER_ERROR;
263 | pDst[ENC_INT32_LENGTH_B64 - 1] = '\0';
264 |
265 | delete req;
266 | return resp;
267 | }
268 |
269 | int enc_int32_decrypt(char* pSrc, char* pDst)
270 | {
271 | if (!status)
272 | {
273 | int resp = initMultithreading();
274 | resp = loadKey(0);
275 | // return resp;//IS_NOT_INITIALIZE;
276 | }
277 |
278 | int resp = ENCLAVE_IS_NOT_RUNNING;
279 | request* req = new request;
280 |
281 | std::array int1_v;
282 | if (!FromBase64Fast((const BYTE*)pSrc,
283 | ENC_INT32_LENGTH_B64 - 1,
284 | int1_v.begin(),
285 | ENC_INT32_LENGTH))
286 | return BASE64DECODER_ERROR;
287 |
288 | std::copy(int1_v.begin(), int1_v.end(), &req->buffer[0]);
289 | req->ocall_index = CMD_INT64_DEC;
290 | req->is_done = -1;
291 | inQueue->enqueue(req);
292 |
293 | while (true)
294 | {
295 | if (req->is_done == -1)
296 | {
297 | __asm__("pause");
298 | }
299 | else
300 | {
301 | std::copy(&req->buffer[ENC_INT32_LENGTH],
302 | &req->buffer[ENC_INT32_LENGTH + INT32_LENGTH],
303 | &pDst[0]);
304 | resp = req->resp;
305 | spin_unlock(&req->is_done);
306 | break;
307 | }
308 | }
309 |
310 | delete req;
311 | return resp;
312 | }
313 |
--------------------------------------------------------------------------------
/src/untrusted/interface/enc_text.cpp:
--------------------------------------------------------------------------------
1 | #include "untrusted/interface/interface.h"
2 | #include "untrusted/interface/stdafx.h"
3 | #include
4 |
5 | extern sgx_enclave_id_t global_eid;
6 | extern Queue* inQueue;
7 | extern bool status;
8 |
9 | int enc_text_concatenate(char* src1,
10 | size_t src1_len,
11 | char* src2,
12 | size_t src2_len,
13 | char* dst,
14 | size_t* dst_len)
15 | {
16 | int resp = ENCLAVE_IS_NOT_RUNNING;
17 | if (!status)
18 | {
19 | resp = initMultithreading();
20 | resp = loadKey(0);
21 | }
22 |
23 | int str3_len;
24 | int len_raw_str1, len_raw_str2, len_raw_str3;
25 |
26 | memcpy(&str3_len, dst_len, sizeof(uint8_t));
27 |
28 | uint8_t* str1 = new uint8_t[src1_len];
29 | uint8_t* str2 = new uint8_t[src2_len];
30 | uint8_t* str3 = new uint8_t[str3_len];
31 |
32 | request* req = new request;
33 |
34 | len_raw_str1 = FromBase64Fast((const BYTE*)src1, src1_len, str1, src1_len);
35 | len_raw_str2 = FromBase64Fast((const BYTE*)src2, src2_len, str2, src2_len);
36 |
37 | if (!len_raw_str1 || !len_raw_str2)
38 | return BASE64DECODER_ERROR;
39 |
40 | memcpy(req->buffer, &len_raw_str1, INT32_LENGTH);
41 | memcpy(req->buffer + INT32_LENGTH, str1, len_raw_str1);
42 |
43 | memcpy(
44 | req->buffer + len_raw_str1 + INT32_LENGTH, &len_raw_str2, INT32_LENGTH);
45 | memcpy(req->buffer + len_raw_str1 + INT32_LENGTH + INT32_LENGTH,
46 | str2,
47 | len_raw_str2);
48 |
49 | req->ocall_index = CMD_STRING_CONCAT;
50 | req->is_done = -1;
51 |
52 | inQueue->enqueue(req);
53 |
54 | while (true)
55 | {
56 | if (req->is_done == -1)
57 | {
58 | __asm__("pause");
59 | }
60 | else
61 | {
62 | memcpy(&len_raw_str3,
63 | req->buffer + len_raw_str1 + 2 * INT32_LENGTH + len_raw_str2,
64 | INT32_LENGTH);
65 | if (str3_len < len_raw_str3)
66 | return MEMORY_ALLOCATION_ERROR;
67 |
68 | memcpy(str3,
69 | req->buffer + len_raw_str1 + 3 * INT32_LENGTH + len_raw_str2,
70 | len_raw_str3);
71 | resp = req->resp;
72 | spin_unlock(&req->is_done);
73 | break;
74 | }
75 | }
76 |
77 | int dst_b64_len = ToBase64Fast((const unsigned char*)str3, len_raw_str3, dst, str3_len);
78 | if (!dst_b64_len)
79 | return BASE64DECODER_ERROR;
80 | dst[dst_b64_len] = '\0';
81 | memcpy(dst_len, &dst_b64_len, sizeof(uint8_t));
82 |
83 | delete[] str1;
84 | delete[] str2;
85 | delete[] str3;
86 | delete req;
87 |
88 | return resp;
89 | }
90 |
91 | int enc_text_substring(char* in1,
92 | size_t in1_size,
93 | char* in2,
94 | size_t in2_size,
95 | char* in3,
96 | size_t in3_size,
97 | char* out,
98 | size_t* out_size)
99 | {
100 | int resp = ENCLAVE_IS_NOT_RUNNING;
101 | if (!status)
102 | {
103 | resp = initMultithreading();
104 | resp = loadKey(0);
105 | }
106 |
107 | request* req = new request;
108 |
109 | uint8_t* str = new uint8_t[in1_size];
110 | size_t str_size, in_size;
111 |
112 | uint8_t* from = new uint8_t[in2_size];
113 | uint8_t* n_chars = new uint8_t[in3_size];
114 |
115 | uint8_t* result = new uint8_t[*out_size];
116 | int result_raw_size = 0;
117 |
118 | int buf_pos = 0;
119 |
120 | str_size = FromBase64Fast((const unsigned char*)in1, in1_size, str, in1_size);
121 | if (!str_size)
122 | return BASE64DECODER_ERROR;
123 |
124 | if ((in2_size == INT32_LENGTH) && (in3_size == INT32_LENGTH))
125 | {
126 | memcpy(from, in2, in2_size);
127 | memcpy(n_chars, in3, in3_size);
128 | in_size = INT32_LENGTH;
129 | }
130 | else
131 | {
132 | if (!FromBase64Fast((const unsigned char*)in2,
133 | ENC_INT32_LENGTH_B64 - 1,
134 | from,
135 | ENC_INT32_LENGTH))
136 | return BASE64DECODER_ERROR;
137 |
138 | if (!FromBase64Fast((const unsigned char*)in3,
139 | ENC_INT32_LENGTH_B64 - 1,
140 | n_chars,
141 | ENC_INT32_LENGTH))
142 | return BASE64DECODER_ERROR;
143 | in_size = ENC_INT32_LENGTH;
144 | }
145 |
146 | memcpy(req->buffer + buf_pos, &str_size, INT32_LENGTH);
147 | buf_pos += INT32_LENGTH;
148 |
149 | memcpy(req->buffer + buf_pos, str, str_size);
150 | buf_pos += str_size;
151 |
152 | memcpy(req->buffer + buf_pos, &in_size, INT32_LENGTH);
153 | buf_pos += INT32_LENGTH;
154 |
155 | memcpy(req->buffer + buf_pos, from, in_size);
156 | buf_pos += in_size;
157 |
158 | memcpy(req->buffer + buf_pos, &in_size, INT32_LENGTH);
159 | buf_pos += INT32_LENGTH;
160 |
161 | memcpy(req->buffer + buf_pos, n_chars, in_size);
162 | buf_pos += in_size;
163 |
164 | memcpy(req->buffer + buf_pos, out_size, INT32_LENGTH);
165 | buf_pos += INT32_LENGTH;
166 |
167 | memcpy(req->buffer + buf_pos, out, *out_size);
168 | buf_pos += *out_size;
169 |
170 | req->ocall_index = CMD_STRING_SUBSTRING;
171 | req->is_done = -1;
172 |
173 | inQueue->enqueue(req);
174 |
175 | while (true)
176 | {
177 | if (req->is_done == -1)
178 | {
179 | __asm__("pause");
180 | }
181 | else
182 | {
183 | memcpy(&result_raw_size, req->buffer + buf_pos, INT32_LENGTH);
184 | buf_pos += INT32_LENGTH;
185 | memcpy(result, req->buffer + buf_pos, result_raw_size + 1);
186 | resp = req->resp;
187 | spin_unlock(&req->is_done);
188 | break;
189 | }
190 | }
191 |
192 | size_t result_b64_size = ToBase64Fast((const unsigned char*)result, result_raw_size, out, *out_size);
193 | if (!result_b64_size)
194 | return BASE64DECODER_ERROR;
195 | out[result_b64_size] = '\0';
196 | *out_size = result_b64_size;
197 | delete[] str;
198 | delete[] result;
199 | delete[] from;
200 | delete[] n_chars;
201 | delete req;
202 |
203 | return resp;
204 | }
205 |
206 | int enc_text_like(char* in1, size_t in1_size, char* in2, size_t in2_size, int* out)
207 | {
208 | int resp = ENCLAVE_IS_NOT_RUNNING;
209 | if (!status)
210 | {
211 | resp = initMultithreading();
212 | resp = loadKey(0);
213 | }
214 |
215 | request* req = new request;
216 |
217 | uint8_t* str = new uint8_t[in1_size];
218 | uint8_t* pattern = new uint8_t[in2_size];
219 |
220 | int str_raw_size = FromBase64Fast((const unsigned char*)in1, in1_size, str, in1_size);
221 | int pattern_raw_size = FromBase64Fast((const unsigned char*)in2, in2_size, pattern, in2_size);
222 | if (!str_raw_size || !pattern_raw_size)
223 | return BASE64DECODER_ERROR;
224 |
225 | size_t buf_pos = 0;
226 | memcpy(req->buffer + buf_pos, &str_raw_size, INT32_LENGTH);
227 | buf_pos += INT32_LENGTH;
228 |
229 | memcpy(req->buffer + buf_pos, str, str_raw_size);
230 | buf_pos += str_raw_size;
231 |
232 | memcpy(req->buffer + buf_pos, &pattern_raw_size, INT32_LENGTH);
233 | buf_pos += INT32_LENGTH;
234 |
235 | memcpy(req->buffer + buf_pos, pattern, pattern_raw_size);
236 | buf_pos += pattern_raw_size;
237 |
238 | req->ocall_index = CMD_STRING_LIKE;
239 | req->is_done = -1;
240 |
241 | inQueue->enqueue(req);
242 |
243 | while (true)
244 | {
245 | if (req->is_done == -1)
246 | {
247 | __asm__("pause");
248 | }
249 | else
250 | {
251 | resp = req->resp;
252 | std::copy(
253 | &req->buffer[buf_pos], &req->buffer[buf_pos + INT32_LENGTH], out);
254 | spin_unlock(&req->is_done);
255 | break;
256 | }
257 | }
258 |
259 | delete req;
260 | delete[] str;
261 | delete[] pattern;
262 |
263 | return resp;
264 | }
265 |
266 | int enc_text_encrypt(char* pSrc, size_t src_len, char* pDst, size_t dst_len)
267 | {
268 | int resp = ENCLAVE_IS_NOT_RUNNING;
269 | if (!status)
270 | {
271 | resp = initMultithreading();
272 | resp = loadKey(0);
273 | }
274 |
275 | int len, raw_dst_len;
276 |
277 | request* req = new request;
278 | uint8_t* dst = new uint8_t[dst_len + 1];
279 |
280 | memcpy(req->buffer, &src_len, INT32_LENGTH);
281 | memcpy(req->buffer + INT32_LENGTH, pSrc, src_len);
282 |
283 | req->ocall_index = CMD_STRING_ENC;
284 | req->is_done = -1;
285 |
286 | inQueue->enqueue(req);
287 |
288 | while (true)
289 | {
290 | if (req->is_done == -1)
291 | {
292 | __asm__("pause");
293 | }
294 | else
295 | {
296 | memcpy(&raw_dst_len, req->buffer + src_len + INT32_LENGTH, INT32_LENGTH);
297 | memcpy(dst, req->buffer + src_len + 2 * INT32_LENGTH, raw_dst_len);
298 | resp = req->resp;
299 | spin_unlock(&req->is_done);
300 | break;
301 | }
302 | }
303 |
304 | len = ToBase64Fast((const unsigned char*)dst, raw_dst_len, pDst, dst_len + 1);
305 | if (!len)
306 | return BASE64DECODER_ERROR;
307 | pDst[dst_len] = '\0';
308 |
309 | delete req;
310 | delete[] dst;
311 |
312 | return resp;
313 | }
314 | int enc_text_cmp(char* src1,
315 | size_t src1_len,
316 | char* src2,
317 | size_t src2_len,
318 | char* res)
319 | {
320 | int resp = ENCLAVE_IS_NOT_RUNNING;
321 | if (!status)
322 | {
323 | resp = initMultithreading();
324 | resp = loadKey(0);
325 | }
326 |
327 | request* req = new request;
328 |
329 | uint8_t* arg1 = new uint8_t[src1_len];
330 | uint8_t* arg2 = new uint8_t[src2_len];
331 |
332 | int len_raw_str1 = FromBase64Fast((const BYTE*)src1, src1_len, arg1, src1_len);
333 | int len_raw_str2 = FromBase64Fast((const BYTE*)src2, src2_len, arg2, src2_len);
334 |
335 | if (!len_raw_str1 || !len_raw_str2)
336 | return BASE64DECODER_ERROR;
337 |
338 | memcpy(req->buffer, &len_raw_str1, INT32_LENGTH);
339 | memcpy(req->buffer + INT32_LENGTH, arg1, len_raw_str1);
340 | memcpy(
341 | req->buffer + len_raw_str1 + INT32_LENGTH, &len_raw_str2, INT32_LENGTH);
342 | memcpy(req->buffer + len_raw_str1 + INT32_LENGTH + INT32_LENGTH,
343 | arg2,
344 | len_raw_str2);
345 |
346 | req->ocall_index = CMD_STRING_CMP;
347 | req->is_done = -1;
348 |
349 | inQueue->enqueue(req);
350 |
351 | while (true)
352 | {
353 | if (req->is_done == -1)
354 | {
355 | __asm__("pause");
356 | }
357 | else
358 | {
359 | resp = req->resp;
360 | std::copy(&req->buffer[len_raw_str1 + 2 * INT32_LENGTH + len_raw_str2],
361 | &req->buffer[len_raw_str1 + 2 * INT32_LENGTH + len_raw_str2 + INT32_LENGTH],
362 | &res[0]);
363 | spin_unlock(&req->is_done);
364 | break;
365 | }
366 | }
367 |
368 | delete req;
369 | delete[] arg1;
370 | delete[] arg2;
371 |
372 | return resp;
373 | }
374 |
375 | int enc_text_decrypt(char* pSrc, size_t src_len, char* pDst, size_t dst_len)
376 | {
377 | int resp = ENCLAVE_IS_NOT_RUNNING;
378 | if (!status)
379 | {
380 | resp = initMultithreading();
381 | resp = loadKey(0);
382 | }
383 |
384 | int src_decrypted_len, src_bytearray_len;
385 | request* req = new request;
386 | uint8_t* dst = new uint8_t[src_len];
387 |
388 | src_bytearray_len = FromBase64Fast((const BYTE*)pSrc, src_len, dst, src_len);
389 | src_decrypted_len = src_bytearray_len - SGX_AESGCM_IV_SIZE - SGX_AESGCM_MAC_SIZE;
390 |
391 | if (src_decrypted_len > dst_len)
392 | return MEMORY_ALLOCATION_ERROR;
393 |
394 | memcpy(req->buffer, &src_bytearray_len, INT32_LENGTH);
395 | memcpy(req->buffer + INT32_LENGTH, dst, src_bytearray_len);
396 |
397 | req->ocall_index = CMD_STRING_DEC;
398 | req->is_done = -1;
399 |
400 | inQueue->enqueue(req);
401 |
402 | while (true)
403 | {
404 | if (req->is_done == -1)
405 | {
406 | __asm__("pause");
407 | }
408 | else
409 | {
410 | memcpy(
411 | &dst_len, req->buffer + src_bytearray_len + INT32_LENGTH, INT32_LENGTH);
412 | memcpy(pDst,
413 | req->buffer + src_bytearray_len + 2 * INT32_LENGTH,
414 | src_bytearray_len);
415 | resp = req->resp;
416 | spin_unlock(&req->is_done);
417 | break;
418 | }
419 | }
420 |
421 | pDst[dst_len] = '\0';
422 |
423 | delete req;
424 | delete[] dst;
425 |
426 | return resp;
427 | }
428 |
--------------------------------------------------------------------------------
/src/untrusted/interface/enc_timestamp.cpp:
--------------------------------------------------------------------------------
1 | #include "untrusted/interface/interface.h"
2 | #include "untrusted/interface/stdafx.h"
3 |
4 | extern sgx_enclave_id_t global_eid;
5 | extern Queue* inQueue;
6 | extern bool status;
7 |
8 | int enc_timestamp_extract_year(char* in, char* result)
9 | {
10 | if (!status)
11 | {
12 | int resp = initMultithreading();
13 | resp = loadKey(0);
14 | }
15 | int resp = ENCLAVE_IS_NOT_RUNNING;
16 | request* req = new request;
17 | size_t buf_pos = 0;
18 | std::array timestamp;
19 |
20 | if (!FromBase64Fast((const BYTE*)in,
21 | ENC_TIMESTAMP_LENGTH_B64 - 1,
22 | timestamp.begin(),
23 | ENC_TIMESTAMP_LENGTH))
24 | return BASE64DECODER_ERROR;
25 |
26 | std::copy(timestamp.begin(), timestamp.end(), &req->buffer[buf_pos]);
27 | buf_pos += ENC_TIMESTAMP_LENGTH;
28 |
29 | req->ocall_index = CMD_TIMESTAMP_EXTRACT_YEAR;
30 | req->is_done = -1;
31 | inQueue->enqueue(req);
32 |
33 | while (true)
34 | {
35 | if (req->is_done == -1)
36 | {
37 | __asm__("pause");
38 | }
39 | else
40 | {
41 | resp = req->resp;
42 | if (!ToBase64Fast((const BYTE*)&req->buffer[buf_pos],
43 | ENC_INT32_LENGTH,
44 | result,
45 | ENC_INT32_LENGTH_B64))
46 | resp = BASE64DECODER_ERROR;
47 |
48 | spin_unlock(&req->is_done);
49 | break;
50 | }
51 | }
52 | delete req;
53 | return resp;
54 | }
55 |
56 | int enc_timestamp_cmp(char* src1, char* src2, char* res)
57 | {
58 | if (!status)
59 | {
60 | int resp = initMultithreading();
61 | resp = loadKey(0);
62 | // return resp;//IS_NOT_INITIALIZE;
63 | }
64 | int resp = ENCLAVE_IS_NOT_RUNNING;
65 | request* req = new request;
66 |
67 | std::array src1_decoded;
68 | std::array src2_decoded;
69 |
70 | if (!FromBase64Fast((const BYTE*)src1,
71 | ENC_TIMESTAMP_LENGTH_B64 - 1,
72 | src1_decoded.begin(),
73 | ENC_TIMESTAMP_LENGTH))
74 | return BASE64DECODER_ERROR;
75 |
76 | if (!FromBase64Fast((const BYTE*)src2,
77 | ENC_TIMESTAMP_LENGTH_B64 - 1,
78 | src2_decoded.begin(),
79 | ENC_TIMESTAMP_LENGTH))
80 | return BASE64DECODER_ERROR;
81 |
82 | std::copy(src1_decoded.begin(), src1_decoded.end(), &req->buffer[0]);
83 | std::copy(src2_decoded.begin(),
84 | src2_decoded.end(),
85 | &req->buffer[ENC_TIMESTAMP_LENGTH]);
86 |
87 | req->ocall_index = CMD_TIMESTAMP_CMP;
88 | req->is_done = -1;
89 | inQueue->enqueue(req);
90 |
91 | while (true)
92 | {
93 | if (req->is_done == -1)
94 | {
95 | __asm__("pause");
96 | }
97 | else
98 | {
99 | resp = req->resp;
100 | std::copy(&req->buffer[2 * ENC_TIMESTAMP_LENGTH],
101 | &req->buffer[2 * ENC_TIMESTAMP_LENGTH + INT32_LENGTH],
102 | &res[0]);
103 | spin_unlock(&req->is_done);
104 | break;
105 | }
106 | }
107 | delete req;
108 |
109 | return resp;
110 | }
111 |
112 | int enc_timestamp_encrypt(char* src, char* dst)
113 | {
114 | if (!status)
115 | {
116 | int resp = initMultithreading();
117 | resp = loadKey(0);
118 | // return resp;//IS_NOT_INITIALIZE;
119 | }
120 |
121 | int resp = ENCLAVE_IS_NOT_RUNNING;
122 | request* req = new request;
123 | std::array src_encrypted;
124 |
125 | memcpy(req->buffer, src, TIMESTAMP_LENGTH);
126 | req->ocall_index = CMD_TIMESTAMP_ENC;
127 | req->is_done = -1;
128 |
129 | inQueue->enqueue(req);
130 |
131 | while (true)
132 | {
133 | if (req->is_done == -1)
134 | {
135 | __asm__("pause");
136 | }
137 | else
138 | {
139 | std::copy(&req->buffer[TIMESTAMP_LENGTH],
140 | &req->buffer[TIMESTAMP_LENGTH + ENC_TIMESTAMP_LENGTH],
141 | src_encrypted.begin());
142 | resp = req->resp;
143 | spin_unlock(&req->is_done);
144 | break;
145 | }
146 | }
147 |
148 | if (!ToBase64Fast((const BYTE*)src_encrypted.begin(),
149 | ENC_TIMESTAMP_LENGTH,
150 | dst,
151 | ENC_TIMESTAMP_LENGTH_B64))
152 | return BASE64DECODER_ERROR;
153 |
154 | dst[ENC_TIMESTAMP_LENGTH_B64 - 1] = '\0';
155 |
156 | delete req;
157 | return resp;
158 | }
159 |
160 | int enc_timestamp_decrypt(char* src, char* dst)
161 | {
162 | if (!status)
163 | {
164 | int resp = initMultithreading();
165 | resp = loadKey(0);
166 | // return resp;//IS_NOT_INITIALIZE;
167 | }
168 |
169 | int resp = ENCLAVE_IS_NOT_RUNNING;
170 | request* req = new request;
171 |
172 | std::array src_decoded;
173 | if (!FromBase64Fast((const BYTE*)src,
174 | ENC_TIMESTAMP_LENGTH_B64 - 1,
175 | src_decoded.begin(),
176 | ENC_TIMESTAMP_LENGTH))
177 | return BASE64DECODER_ERROR;
178 |
179 | std::copy(src_decoded.begin(), src_decoded.end(), req->buffer);
180 | req->ocall_index = CMD_TIMESTAMP_DEC;
181 | req->is_done = -1;
182 |
183 | inQueue->enqueue(req);
184 |
185 | while (true)
186 | {
187 | if (req->is_done == -1)
188 | {
189 | __asm__("pause");
190 | }
191 | else
192 | {
193 | std::copy(&req->buffer[ENC_TIMESTAMP_LENGTH],
194 | &req->buffer[ENC_TIMESTAMP_LENGTH + TIMESTAMP_LENGTH],
195 | dst);
196 | resp = req->resp;
197 | spin_unlock(&req->is_done);
198 | break;
199 | }
200 | }
201 |
202 | delete req;
203 | return resp;
204 | }
205 |
--------------------------------------------------------------------------------
/src/untrusted/interface/interface.cpp:
--------------------------------------------------------------------------------
1 | #define MAX_PATH FILENAME_MAX
2 |
3 | #include "untrusted/interface/interface.h"
4 | #include "untrusted/interface/stdafx.h"
5 | #include
6 | #include
7 |
8 | /* Global EID shared by multiple threads */
9 | sgx_enclave_id_t global_eid = 0;
10 |
11 | uint8_t INPUT_BUFFER[INPUT_BUFFER_SIZE];
12 | uint8_t OUTPUT_BUFFER[INPUT_BUFFER_SIZE];
13 | Queue* inQueue;
14 | bool status = false;
15 |
16 | int launch_enclave(sgx_launch_token_t* token, int* updated)
17 | {
18 | sgx_status_t ret = SGX_ERROR_UNEXPECTED;
19 |
20 | ret = sgx_create_enclave(
21 | ENCLAVE_FILENAME, TRUE, token, updated, &global_eid, NULL);
22 | if (ret != SGX_SUCCESS)
23 | return ret;
24 | else
25 | return 0;
26 | }
27 |
28 | int init()
29 | {
30 | sgx_launch_token_t token = { 0 };
31 | int updated = 0;
32 | int resp = launch_enclave(&token, &updated);
33 |
34 | return resp;
35 | }
36 |
37 | // void *enclaveThread(void *) {
38 | void enclaveThread()
39 | {
40 | int resp = 0;
41 | enclaveProcess(global_eid, &resp, inQueue);
42 | }
43 | int initMultithreading()
44 | {
45 | sgx_launch_token_t token = { 0 };
46 | int updated = 0;
47 | status = true;
48 | int ans = launch_enclave(&token, &updated);
49 |
50 | inQueue = new Queue();
51 |
52 | for (int i = 0; i < INPUT_BUFFER_SIZE; i++)
53 | INPUT_BUFFER[i] = OUTPUT_BUFFER[i] = 0;
54 |
55 | std::thread th = std::thread(&enclaveThread);
56 |
57 | th.detach();
58 |
59 | return ans;
60 | }
61 |
62 | int generateKey()
63 | {
64 | if (!status)
65 | {
66 | int resp = initMultithreading();
67 | if (resp != SGX_SUCCESS)
68 | return resp;
69 | }
70 |
71 | int resp, resp_enclave, flength;
72 | uint8_t* sealed_key_b = new uint8_t[SEALED_KEY_LENGTH];
73 |
74 | std::fstream data_file;
75 | data_file.open(DATA_FILENAME,
76 | std::fstream::in | std::fstream::out | std::fstream::binary);
77 | if (data_file)
78 | {
79 | data_file.seekg(0, data_file.end);
80 | flength = data_file.tellg();
81 |
82 | if (flength == SEALED_KEY_LENGTH)
83 | return 0;
84 |
85 | else
86 | {
87 | resp = generateKeyEnclave(
88 | global_eid, &resp_enclave, sealed_key_b, SEALED_KEY_LENGTH);
89 | if (resp != SGX_SUCCESS)
90 | return resp;
91 | data_file.write((char*)sealed_key_b, SEALED_KEY_LENGTH);
92 | }
93 | }
94 | else
95 | return NO_KEYS_STORAGE;
96 |
97 | data_file.close();
98 | delete[] sealed_key_b;
99 |
100 | return (int)flength / SEALED_KEY_LENGTH;
101 | }
102 |
103 | int loadKey(int item)
104 | {
105 | if (!status)
106 | {
107 | int resp = initMultithreading();
108 | if (resp != SGX_SUCCESS)
109 | return resp;
110 | }
111 | int resp, resp_enclave;
112 | uint8_t sealed_key_b[SEALED_KEY_LENGTH];
113 |
114 | std::fstream data_file;
115 | data_file.open(DATA_FILENAME, std::fstream::in | std::fstream::binary);
116 | if (data_file)
117 | {
118 | data_file.seekg(0, data_file.end);
119 | int flength = data_file.tellg();
120 | if (flength < item * SEALED_KEY_LENGTH + SEALED_KEY_LENGTH)
121 | return NO_KEY_ID;
122 |
123 | data_file.seekg(item * SEALED_KEY_LENGTH);
124 | data_file.read((char*)sealed_key_b, SEALED_KEY_LENGTH);
125 | resp = loadKeyEnclave(
126 | global_eid, &resp_enclave, sealed_key_b, SEALED_KEY_LENGTH);
127 | if (resp != SGX_SUCCESS)
128 | return resp;
129 | }
130 | else
131 | return NO_KEYS_STORAGE;
132 |
133 | data_file.close();
134 | return 0;
135 | }
136 |
--------------------------------------------------------------------------------
/src/vars.mk:
--------------------------------------------------------------------------------
1 | BUILD_DIR := $(CURDIR)/../build
2 | ENCLAVE_DIR := enclave
3 | ENCLAVE_NAME := enclave
4 | STEALTHDIR := /usr/local/lib/stealthDB
5 |
6 | SDK_INSTALL_PATH := /opt/intel/sgxsdk
7 | SGX_INCLUDE_PATH := $(SDK_INSTALL_PATH)/include
8 | SGX_EDGER8R := $(SDK_INSTALL_PATH)/bin/x64/sgx_edger8r
9 |
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | # Test suite
2 |
3 | We use pgTAP tool to make testing cases based on SQL queries.
4 |
5 | ## Install
6 |
7 | ```
8 | sudo apt-get install libtap-parser-sourcehandler-pgtap-perl
9 |
10 | ```
11 |
12 | ## Run
13 |
14 | ```
15 | pg_prove -U postgres -d postgres encdb/run_test.sql
16 |
17 | ```
18 |
19 |
--------------------------------------------------------------------------------
/test/encdb/run_test.sql:
--------------------------------------------------------------------------------
1 | \unset ECHO
2 | \i sql/setup.sql
3 |
4 | select plan(47);
5 |
6 | DROP TABLE IF EXISTS test_table;
7 | CREATE TABLE test_table (id int, num_i enc_int4, num_f enc_float4, str enc_text, time enc_timestamp);
8 |
9 |
10 | --CREATE FUNCTION TEST_INSERT ()
11 | --DECLARE
12 | -- counter INTEGER := 0 ;
13 | ---BEGIN
14 |
15 | -- WHILE counter <= 20 LOOP
16 | --counter := counter + 1 ;
17 | -- END LOOP ; END ;
18 |
19 | --INSERT INTO test_table VALUES (1,'qPi1p4veVIVUTOauaOlrKcnY0aj5K+GS9q6QWYlmKkH=','+G3Bb/jHI78D3Hq3gbo+DEfOtLdWEPqYYs9baZrNobP=','dtf8fCOV4LuswydUmfzFsrHkjHupFElIjD5K26pANmk8');
20 | --INSERT INTO test_table VALUES (2,'imddM6yDio+8m9YjdgHAd8W2Zr+PCE0Yfh3PCpoMyQX=','AJrPjKwICexdS5dsuQKiwQBQs7eZ/zUlDaNCTYHNjDD=','JclPi1jtjtI7nnxbZ/xZoRleWHHdXdtLKmZ5JW3pTv4ziAP9ZkAEMw==');
21 | --INSERT INTO test_table VALUES (3,'cYJSlL5Z1LQwHSHa9iDAIG3xg/2x9RLhxAHBkVWGrqv=','5ptgfZb2N6s0jo+pnJM8nwQw3vQWWmELg8Le6zv/oBn=','VJ6kaUSHFcQU25XCKIGi8VHdFM5Di/kUCz67QQ==');
22 |
23 | select ok(pg_enc_int4_decrypt(pg_enc_int4_encrypt(1)) = 1::int4, 'enc_int4: encryption/decryption test');
24 | select ok(pg_enc_float4_decrypt(pg_enc_float4_encrypt(1.1)) = 1.1::float4, 'enc_float4: encryption/decryption test');
25 | --select is(pg_enc_timestamp_decrypt(pg_enc_timestamp_encrypt('11/11/11 11:11:11')), '11/11/11 11:11:11'::timestamp, 'enc_timestamp: encryption/decryption test');
26 | --select ok(pg_enc_text_decrypt(pg_enc_text_encrypt('test')) = 'test'::cstring, 'enc_test: encryption/decryption test');
27 |
28 | select enable_debug_mode(1);
29 |
30 | INSERT INTO test_table VALUES (1, '1', '1.1', 'hello', '01/01/2020');
31 | INSERT INTO test_table VALUES (2, '2', '2.1', 'world', '01/01/2019');
32 | INSERT INTO test_table VALUES (3, '3', '3.1', 'from', '01/01/2018');
33 | INSERT INTO test_table VALUES (3, '3', '3.1', 'stealth', '01/01/2017');
34 |
35 |
36 | SELECT results_eq(
37 | 'select SUM(num_i) from test_table',
38 | $$VALUES (9::enc_int4)$$,
39 | 'enc_int4: SUM function '
40 | );
41 |
42 | SELECT results_eq(
43 | 'select MIN(num_i) from test_table',
44 | $$VALUES (1::enc_int4)$$,
45 | 'enc_int4: MIN function '
46 | );
47 |
48 | SELECT results_eq(
49 | 'select MAX(num_i) from test_table',
50 | $$VALUES (3::enc_int4)$$,
51 | 'enc_int4: MAX function '
52 | );
53 |
54 | SELECT results_eq(
55 | 'select AVG(num_i) from test_table',
56 | $$VALUES (2::enc_int4)$$,
57 | 'enc_int4: AVG function (with rounding)'
58 | );
59 |
60 | SELECT results_eq(
61 | 'select SUM(num_f) from test_table',
62 | $$VALUES (9.4::enc_float4)$$,
63 | 'enc_float4: SUM function'
64 | );
65 |
66 | SELECT results_eq(
67 | 'select AVG(num_f) from test_table',
68 | $$VALUES (2.35::enc_float4)$$,
69 | 'enc_float4: AVG function'
70 | );
71 |
72 | DECLARE q1 CURSOR FOR select id from test_table where time < '01/01/2018';
73 | SELECT results_eq(
74 | 'q1'::refcursor,
75 | $$VALUES (3::int4)$$,
76 | 'enc_float: < operator in a table'
77 | );
78 |
79 | DECLARE q2 CURSOR FOR select id from test_table where str = 'stealth';
80 | SELECT results_eq(
81 | 'q2'::refcursor,
82 | $$VALUES (3)$$,
83 | 'enc_text: = operator in a table'
84 | );
85 |
86 | --select ok(0::enc_int4 = 0::int4, 'enc_int4: encryption/decryption test in a preprocessing form');
87 | --select ok(0.5::enc_float4 = 0.5::float4, 'enc_float4: encryption/decryption test in a preprocessing form');
88 | --select ok('11/11/11 11:11:11'::enc_timestamp = '11/11/11 11:11:11'::timestamp, 'enc_timestamp: encryption/decryption test in a preprocessing form');
89 | --select ok('test2'::enc_text = 'test2'::cstring, 'enc_text: encryption/decryption test in a preprocessing form');
90 |
91 | select ok(1::enc_int4 = 1::enc_int4, 'enc_int4: inequality test, operator =');
92 | select ok(0::enc_int4 != 1::enc_int4, 'enc_int4: inequality test, operator !=');
93 | select ok(0::enc_int4 <> 1::enc_int4, 'enc_int4: inequality test, operator <>');
94 | select ok(1::enc_int4 <= 2::enc_int4, 'enc_int4: inequality test, operator <=');
95 | select ok(1::enc_int4 <= 1::enc_int4, 'enc_int4: inequality test, operator <=');
96 | select ok(3::enc_int4 >= 2::enc_int4, 'enc_int4: inequality test, operator >=');
97 | select ok(1::enc_int4 >= 1::enc_int4, 'enc_int4: inequality test, operator >=');
98 | select ok(2::enc_int4 < 3::enc_int4, 'enc_int4: inequality test, operator <');
99 | select ok(3::enc_int4 > 2::enc_int4, 'enc_int4: inequality test, operator >');
100 |
101 | select ok(2::enc_int4 + 1::enc_int4 = 3::enc_int4, 'enc_int4: operator +');
102 | select ok(2::enc_int4 - 1::enc_int4 = 1::enc_int4, 'enc_int4: operator -');
103 | select ok(2::enc_int4 * 2::enc_int4 = 4::enc_int4, 'enc_int4: operator *');
104 | select ok(6::enc_int4 / 2::enc_int4 = 3::enc_int4, 'enc_int4: operator /');
105 | --SELECT throws_ok(6::enc_int4 / 0::enc_int4, '', 'SGX_ERROR_CODE -4: ARITHMETIC_ERROR', '' );
106 |
107 |
108 | select ok(1.1::enc_float4 = 1.1::enc_float4, 'enc_float4: inequality test, operator =');
109 | select ok(0.2::enc_float4 != 1.1::enc_float4, 'enc_float4: inequality test, operator !=');
110 | select ok(0.2::enc_float4 <> 1.1::enc_float4, 'enc_float4: inequality test, operator <>');
111 | select ok(1.1::enc_float4 <= 2.3::enc_float4, 'enc_float4: inequality test, operator <=');
112 | select ok(1.1::enc_float4 <= 1.1::enc_float4, 'enc_float4: inequality test, operator <=');
113 | select ok(3.4::enc_float4 >= 2.3::enc_float4, 'enc_float4: inequality test, operator >=');
114 | select ok(1.1::enc_float4 >= 1.1::enc_float4, 'enc_float4: inequality test, operator >=');
115 | select ok(2.3::enc_float4 < 3.4::enc_float4, 'enc_float4: inequality test, operator <');
116 | select ok(3.4::enc_float4 > 2.3::enc_float4, 'enc_float4: inequality test, operator >');
117 |
118 | select ok(2.3::enc_float4 + 1.1::enc_float4 = 3.4::enc_float4, 'enc_float4: operator +');
119 | --select ok(pg_enc_float4_encrypt(2.3) - pg_enc_float4_encrypt(1.1) = pg_enc_float4_encrypt(1.2), 'enc_float4: operator -');
120 | --select ok(2.3::enc_float4 - 1.1::enc_float4 = 1.2::enc_float4, 'enc_float4: operator -');
121 | --select ok(2.3::enc_float4 * 2.3::enc_float4 = 5.29::enc_float4, 'enc_float4: operator *');
122 | select ok(9.9::enc_float4 / 3.3::enc_float4 = 3::enc_float4, 'enc_float4: operator /');
123 |
124 | select ok('11/11/12'::enc_timestamp = '11/11/12'::enc_timestamp, 'enc_timestamp: inequality test, operator =');
125 | select ok('11/11/12 00:00:01'::enc_timestamp != '11/11/12 00:00:02'::enc_timestamp, 'enc_timestamp: inequality test, operator !=');
126 | select ok('11/11/12 00:00:01'::enc_timestamp <> '11/11/12 00:00:02'::enc_timestamp, 'enc_timestamp: inequality test, operator <>');
127 | select ok('11/11/12 00:00:01'::enc_timestamp <= '11/11/12 00:00:01'::enc_timestamp, 'enc_timestamp: inequality test, operator <=');
128 | select ok('11/11/12 00:00:01'::enc_timestamp <= '11/11/12 00:00:03'::enc_timestamp, 'enc_timestamp: inequality test, operator <=');
129 | select ok('11/11/12 00:00:01'::enc_timestamp >= '11/11/12 00:00:01'::enc_timestamp, 'enc_timestamp: inequality test, operator >=');
130 | select ok('11/11/12 00:00:02'::enc_timestamp >= '11/11/12 00:00:01'::enc_timestamp, 'enc_timestamp: inequality test, operator >=');
131 | select ok('11/11/12 00:00:01'::enc_timestamp < '11/11/12 00:00:03'::enc_timestamp, 'enc_timestamp: inequality test, operator <');
132 | select ok('11/11/12 00:00:03'::enc_timestamp > '11/11/12 00:00:01'::enc_timestamp, 'enc_timestamp: inequality test, operator >');
133 |
134 | select ok('test1'::enc_text = 'test1'::enc_text, 'enc_text: inequality test, operator =');
135 | select ok('test1'::enc_text != 'test2'::enc_text, 'enc_text: inequality test, operator !=');
136 | select ok('test1'::enc_text <> 'test2'::enc_text, 'enc_text: inequality test, operator <>');
137 | select ok('hello'::enc_text || 'world'::enc_text = 'helloworld'::enc_text, 'enc_text: operator ||');
138 |
139 |
140 | select * from finish();
141 | --DROP TABLE IF EXISTS test_table;
142 | ROLLBACK;
143 |
--------------------------------------------------------------------------------
/test/sql/pgtap--0.90.0--0.91.0.sql:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE FUNCTION pgtap_version()
2 | RETURNS NUMERIC AS 'SELECT 0.91;'
3 | LANGUAGE SQL IMMUTABLE;
4 |
5 | CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT, TEXT )
6 | RETURNS TEXT AS $$
7 | BEGIN
8 | IF pg_version_num() >= 90200 THEN
9 | RETURN ok(
10 | EXISTS(
11 | SELECT true
12 | FROM pg_catalog.pg_tablespace
13 | WHERE spcname = $1
14 | AND pg_tablespace_location(oid) = $2
15 | ), $3
16 | );
17 | ELSE
18 | RETURN ok(
19 | EXISTS(
20 | SELECT true
21 | FROM pg_catalog.pg_tablespace
22 | WHERE spcname = $1
23 | AND spclocation = $2
24 | ), $3
25 | );
26 | END IF;
27 | END;
28 | $$ LANGUAGE plpgsql;
29 |
30 |
--------------------------------------------------------------------------------
/test/sql/pgtap--0.93.0--0.94.0.sql:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE FUNCTION pgtap_version()
2 | RETURNS NUMERIC AS 'SELECT 0.94;'
3 | LANGUAGE SQL IMMUTABLE;
4 |
5 | CREATE OR REPLACE FUNCTION _get_func_privs(TEXT, TEXT)
6 | RETURNS TEXT[] AS $$
7 | BEGIN
8 | IF pg_catalog.has_function_privilege($1, $2, 'EXECUTE') THEN
9 | RETURN '{EXECUTE}';
10 | ELSE
11 | RETURN '{}';
12 | END IF;
13 | EXCEPTION
14 | -- Not a valid func name.
15 | WHEN undefined_function THEN RETURN '{undefined_function}';
16 | -- Not a valid role.
17 | WHEN undefined_object THEN RETURN '{undefined_role}';
18 | END;
19 | $$ LANGUAGE plpgsql;
20 |
21 | CREATE OR REPLACE FUNCTION _fprivs_are ( TEXT, NAME, NAME[], TEXT )
22 | RETURNS TEXT AS $$
23 | DECLARE
24 | grants TEXT[] := _get_func_privs($2, $1);
25 | BEGIN
26 | IF grants[1] = 'undefined_function' THEN
27 | RETURN ok(FALSE, $4) || E'\n' || diag(
28 | ' Function ' || $1 || ' does not exist'
29 | );
30 | ELSIF grants[1] = 'undefined_role' THEN
31 | RETURN ok(FALSE, $4) || E'\n' || diag(
32 | ' Role ' || quote_ident($2) || ' does not exist'
33 | );
34 | END IF;
35 | RETURN _assets_are('privileges', grants, $3, $4);
36 | END;
37 | $$ LANGUAGE plpgsql;
38 |
39 | -- has_table( schema, table )
40 | CREATE OR REPLACE FUNCTION has_table ( NAME, NAME )
41 | RETURNS TEXT AS $$
42 | SELECT ok(
43 | _rexists( 'r', $1, $2 ),
44 | 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist'
45 | );
46 | $$ LANGUAGE SQL;
47 |
48 | -- hasnt_table( schema, table )
49 | CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME )
50 | RETURNS TEXT AS $$
51 | SELECT ok(
52 | NOT _rexists( 'r', $1, $2 ),
53 | 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist'
54 | );
55 | $$ LANGUAGE SQL;
56 |
57 | -- has_foreign_table( schema, table )
58 | CREATE OR REPLACE FUNCTION has_foreign_table ( NAME, NAME )
59 | RETURNS TEXT AS $$
60 | SELECT ok(
61 | _rexists( 'f', $1, $2 ),
62 | 'Foreign table ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist'
63 | );
64 | $$ LANGUAGE SQL;
65 |
66 | -- hasnt_foreign_table( schema, table )
67 | CREATE OR REPLACE FUNCTION hasnt_foreign_table ( NAME, NAME )
68 | RETURNS TEXT AS $$
69 | SELECT ok(
70 | NOT _rexists( 'f', $1, $2 ),
71 | 'Foreign table ' || quote_ident($1) || '.' || quote_ident($2) || ' not should exist'
72 | );
73 | $$ LANGUAGE SQL;
74 |
75 | CREATE OR REPLACE FUNCTION skip ( why text, how_many int )
76 | RETURNS TEXT AS $$
77 | DECLARE
78 | output TEXT[];
79 | BEGIN
80 | output := '{}';
81 | FOR i IN 1..how_many LOOP
82 | output = array_append(
83 | output,
84 | ok( TRUE ) || ' ' || diag( 'SKIP' || COALESCE( ' ' || why, '') )
85 | );
86 | END LOOP;
87 | RETURN array_to_string(output, E'\n');
88 | END;
89 | $$ LANGUAGE plpgsql;
90 |
91 | CREATE OR REPLACE FUNCTION skip ( text )
92 | RETURNS TEXT AS $$
93 | SELECT ok( TRUE ) || ' ' || diag( 'SKIP' || COALESCE(' ' || $1, '') );
94 | $$ LANGUAGE sql;
95 |
96 | -- check_test( test_output, pass, name, description, diag, match_diag )
97 | CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN )
98 | RETURNS SETOF TEXT AS $$
99 | DECLARE
100 | tnumb INTEGER;
101 | aok BOOLEAN;
102 | adescr TEXT;
103 | res BOOLEAN;
104 | descr TEXT;
105 | adiag TEXT;
106 | have ALIAS FOR $1;
107 | eok ALIAS FOR $2;
108 | name ALIAS FOR $3;
109 | edescr ALIAS FOR $4;
110 | ediag ALIAS FOR $5;
111 | matchit ALIAS FOR $6;
112 | BEGIN
113 | -- What test was it that just ran?
114 | tnumb := currval('__tresults___numb_seq');
115 |
116 | -- Fetch the results.
117 | EXECUTE 'SELECT aok, descr FROM __tresults__ WHERE numb = ' || tnumb
118 | INTO aok, adescr;
119 |
120 | -- Now delete those results.
121 | EXECUTE 'DELETE FROM __tresults__ WHERE numb = ' || tnumb;
122 | EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH ' || tnumb;
123 |
124 | -- Set up the description.
125 | descr := coalesce( name || ' ', 'Test ' ) || 'should ';
126 |
127 | -- So, did the test pass?
128 | RETURN NEXT is(
129 | aok,
130 | eok,
131 | descr || CASE eok WHEN true then 'pass' ELSE 'fail' END
132 | );
133 |
134 | -- Was the description as expected?
135 | IF edescr IS NOT NULL THEN
136 | RETURN NEXT is(
137 | adescr,
138 | edescr,
139 | descr || 'have the proper description'
140 | );
141 | END IF;
142 |
143 | -- Were the diagnostics as expected?
144 | IF ediag IS NOT NULL THEN
145 | -- Remove ok and the test number.
146 | adiag := substring(
147 | have
148 | FROM CASE WHEN aok THEN 4 ELSE 9 END + char_length(tnumb::text)
149 | );
150 |
151 | -- Remove the description, if there is one.
152 | IF adescr <> '' THEN
153 | adiag := substring(
154 | adiag FROM 1 + char_length( ' - ' || substr(diag( adescr ), 3) )
155 | );
156 | END IF;
157 |
158 | IF NOT aok THEN
159 | -- Remove failure message from ok().
160 | adiag := substring(adiag FROM 1 + char_length(diag(
161 | 'Failed test ' || tnumb ||
162 | CASE adescr WHEN '' THEN '' ELSE COALESCE(': "' || adescr || '"', '') END
163 | )));
164 | END IF;
165 |
166 | IF ediag <> '' THEN
167 | -- Remove the space before the diagnostics.
168 | adiag := substring(adiag FROM 2);
169 | END IF;
170 |
171 | -- Remove the #s.
172 | adiag := replace( substring(adiag from 3), E'\n# ', E'\n' );
173 |
174 | -- Now compare the diagnostics.
175 | IF matchit THEN
176 | RETURN NEXT matches(
177 | adiag,
178 | ediag,
179 | descr || 'have the proper diagnostics'
180 | );
181 | ELSE
182 | RETURN NEXT is(
183 | adiag,
184 | ediag,
185 | descr || 'have the proper diagnostics'
186 | );
187 | END IF;
188 | END IF;
189 |
190 | -- And we're done
191 | RETURN;
192 | END;
193 | $$ LANGUAGE plpgsql;
194 |
--------------------------------------------------------------------------------
/test/sql/pgtap--0.95.0--0.96.0.sql:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE FUNCTION pgtap_version()
2 | RETURNS NUMERIC AS 'SELECT 0.96;'
3 | LANGUAGE SQL IMMUTABLE;
4 |
5 | CREATE OR REPLACE FUNCTION findfuncs( NAME, TEXT, TEXT )
6 | RETURNS TEXT[] AS $$
7 | SELECT ARRAY(
8 | SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname
9 | FROM pg_catalog.pg_proc p
10 | JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
11 | WHERE n.nspname = $1
12 | AND p.proname ~ $2
13 | AND ($3 IS NULL OR p.proname !~ $3)
14 | ORDER BY pname
15 | );
16 | $$ LANGUAGE sql;
17 | CREATE OR REPLACE FUNCTION findfuncs( NAME, TEXT )
18 | RETURNS TEXT[] AS $$
19 | SELECT findfuncs( $1, $2, NULL )
20 | $$ LANGUAGE sql;
21 |
22 | CREATE OR REPLACE FUNCTION findfuncs( TEXT, TEXT )
23 | RETURNS TEXT[] AS $$
24 | SELECT ARRAY(
25 | SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname
26 | FROM pg_catalog.pg_proc p
27 | JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
28 | WHERE pg_catalog.pg_function_is_visible(p.oid)
29 | AND p.proname ~ $1
30 | AND ($2 IS NULL OR p.proname !~ $2)
31 | ORDER BY pname
32 | );
33 | $$ LANGUAGE sql;
34 | CREATE OR REPLACE FUNCTION findfuncs( TEXT )
35 | RETURNS TEXT[] AS $$
36 | SELECT findfuncs( $1, NULL )
37 | $$ LANGUAGE sql;
38 |
39 | CREATE OR REPLACE FUNCTION runtests( NAME, TEXT )
40 | RETURNS SETOF TEXT AS $$
41 | SELECT * FROM _runner(
42 | findfuncs( $1, '^startup' ),
43 | findfuncs( $1, '^shutdown' ),
44 | findfuncs( $1, '^setup' ),
45 | findfuncs( $1, '^teardown' ),
46 | findfuncs( $1, $2, '^(startup|shutdown|setup|teardown)' )
47 | );
48 | $$ LANGUAGE sql;
49 |
50 | -- runtests( match )
51 | CREATE OR REPLACE FUNCTION runtests( TEXT )
52 | RETURNS SETOF TEXT AS $$
53 | SELECT * FROM _runner(
54 | findfuncs( '^startup' ),
55 | findfuncs( '^shutdown' ),
56 | findfuncs( '^setup' ),
57 | findfuncs( '^teardown' ),
58 | findfuncs( $1, '^(startup|shutdown|setup|teardown)' )
59 | );
60 | $$ LANGUAGE sql;
61 |
62 | -- database_privs_are ( db, user, privileges[], description )
63 | CREATE OR REPLACE FUNCTION database_privs_are ( NAME, NAME, NAME[], TEXT )
64 | RETURNS TEXT AS $$
65 | DECLARE
66 | grants TEXT[] := _get_db_privs( $2, $1::TEXT );
67 | BEGIN
68 | IF grants[1] = 'invalid_catalog_name' THEN
69 | RETURN ok(FALSE, $4) || E'\n' || diag(
70 | ' Database ' || quote_ident($1) || ' does not exist'
71 | );
72 | ELSIF grants[1] = 'undefined_role' THEN
73 | RETURN ok(FALSE, $4) || E'\n' || diag(
74 | ' Role ' || quote_ident($2) || ' does not exist'
75 | );
76 | END IF;
77 | RETURN _assets_are('privileges', grants, $3, $4);
78 | END;
79 | $$ LANGUAGE plpgsql;
80 |
81 | -- schema_privs_are ( schema, user, privileges[], description )
82 | CREATE OR REPLACE FUNCTION schema_privs_are ( NAME, NAME, NAME[], TEXT )
83 | RETURNS TEXT AS $$
84 | DECLARE
85 | grants TEXT[] := _get_schema_privs( $2, $1::TEXT );
86 | BEGIN
87 | IF grants[1] = 'invalid_schema_name' THEN
88 | RETURN ok(FALSE, $4) || E'\n' || diag(
89 | ' Schema ' || quote_ident($1) || ' does not exist'
90 | );
91 | ELSIF grants[1] = 'undefined_role' THEN
92 | RETURN ok(FALSE, $4) || E'\n' || diag(
93 | ' Role ' || quote_ident($2) || ' does not exist'
94 | );
95 | END IF;
96 | RETURN _assets_are('privileges', grants, $3, $4);
97 | END;
98 | $$ LANGUAGE plpgsql;
99 |
100 | -- tablespace_privs_are ( tablespace, user, privileges[], description )
101 | CREATE OR REPLACE FUNCTION tablespace_privs_are ( NAME, NAME, NAME[], TEXT )
102 | RETURNS TEXT AS $$
103 | DECLARE
104 | grants TEXT[] := _get_tablespaceprivs( $2, $1::TEXT );
105 | BEGIN
106 | IF grants[1] = 'undefined_tablespace' THEN
107 | RETURN ok(FALSE, $4) || E'\n' || diag(
108 | ' Tablespace ' || quote_ident($1) || ' does not exist'
109 | );
110 | ELSIF grants[1] = 'undefined_role' THEN
111 | RETURN ok(FALSE, $4) || E'\n' || diag(
112 | ' Role ' || quote_ident($2) || ' does not exist'
113 | );
114 | END IF;
115 | RETURN _assets_are('privileges', grants, $3, $4);
116 | END;
117 | $$ LANGUAGE plpgsql;
118 |
119 | CREATE OR REPLACE FUNCTION fdw_privs_are ( NAME, NAME, NAME[], TEXT )
120 | RETURNS TEXT AS $$
121 | DECLARE
122 | grants TEXT[] := _get_fdw_privs( $2, $1::TEXT );
123 | BEGIN
124 | IF grants[1] = 'undefined_fdw' THEN
125 | RETURN ok(FALSE, $4) || E'\n' || diag(
126 | ' FDW ' || quote_ident($1) || ' does not exist'
127 | );
128 | ELSIF grants[1] = 'undefined_role' THEN
129 | RETURN ok(FALSE, $4) || E'\n' || diag(
130 | ' Role ' || quote_ident($2) || ' does not exist'
131 | );
132 | END IF;
133 | RETURN _assets_are('privileges', grants, $3, $4);
134 | END;
135 | $$ LANGUAGE plpgsql;
136 |
137 | -- server_privs_are ( server, user, privileges[], description )
138 | CREATE OR REPLACE FUNCTION server_privs_are ( NAME, NAME, NAME[], TEXT )
139 | RETURNS TEXT AS $$
140 | DECLARE
141 | grants TEXT[] := _get_server_privs( $2, $1::TEXT );
142 | BEGIN
143 | IF grants[1] = 'undefined_server' THEN
144 | RETURN ok(FALSE, $4) || E'\n' || diag(
145 | ' Server ' || quote_ident($1) || ' does not exist'
146 | );
147 | ELSIF grants[1] = 'undefined_role' THEN
148 | RETURN ok(FALSE, $4) || E'\n' || diag(
149 | ' Role ' || quote_ident($2) || ' does not exist'
150 | );
151 | END IF;
152 | RETURN _assets_are('privileges', grants, $3, $4);
153 | END;
154 | $$ LANGUAGE plpgsql;
155 |
156 | -- Get extensions in a given schema
157 | CREATE OR REPLACE FUNCTION _extensions( NAME )
158 | RETURNS SETOF NAME AS $$
159 | SELECT e.extname
160 | FROM pg_catalog.pg_namespace n
161 | JOIN pg_catalog.pg_extension e ON n.oid = e.extnamespace
162 | WHERE n.nspname = $1
163 | $$ LANGUAGE SQL;
164 |
165 | CREATE OR REPLACE FUNCTION _extensions()
166 | RETURNS SETOF NAME AS $$
167 | SELECT extname FROM pg_catalog.pg_extension
168 | $$ LANGUAGE SQL;
169 |
170 | -- extensions_are( schema, extensions, description )
171 | CREATE OR REPLACE FUNCTION extensions_are( NAME, NAME[], TEXT )
172 | RETURNS TEXT AS $$
173 | SELECT _are(
174 | 'extensions',
175 | ARRAY(SELECT _extensions($1) EXCEPT SELECT unnest($2)),
176 | ARRAY(SELECT unnest($2) EXCEPT SELECT _extensions($1)),
177 | $3
178 | );
179 | $$ LANGUAGE SQL;
180 |
181 | -- extensions_are( schema, extensions)
182 | CREATE OR REPLACE FUNCTION extensions_are( NAME, NAME[] )
183 | RETURNS TEXT AS $$
184 | SELECT extensions_are(
185 | $1, $2,
186 | 'Schema ' || quote_ident($1) || ' should have the correct extensions'
187 | );
188 | $$ LANGUAGE SQL;
189 |
190 | -- extensions_are( extensions, description )
191 | CREATE OR REPLACE FUNCTION extensions_are( NAME[], TEXT )
192 | RETURNS TEXT AS $$
193 | SELECT _are(
194 | 'extensions',
195 | ARRAY(SELECT _extensions() EXCEPT SELECT unnest($1)),
196 | ARRAY(SELECT unnest($1) EXCEPT SELECT _extensions()),
197 | $2
198 | );
199 | $$ LANGUAGE SQL;
200 |
201 | -- extensions_are( schema, extensions)
202 | CREATE OR REPLACE FUNCTION extensions_are( NAME[] )
203 | RETURNS TEXT AS $$
204 | SELECT extensions_are($1, 'Should have the correct extensions');
205 | $$ LANGUAGE SQL;
206 |
207 | CREATE OR REPLACE FUNCTION _error_diag(
208 | sqlstate TEXT DEFAULT NULL,
209 | errmsg TEXT DEFAULT NULL,
210 | detail TEXT DEFAULT NULL,
211 | hint TEXT DEFAULT NULL,
212 | context TEXT DEFAULT NULL,
213 | schname TEXT DEFAULT NULL,
214 | tabname TEXT DEFAULT NULL,
215 | colname TEXT DEFAULT NULL,
216 | chkname TEXT DEFAULT NULL,
217 | typname TEXT DEFAULT NULL
218 | ) RETURNS TEXT AS $$
219 | SELECT COALESCE(
220 | COALESCE( NULLIF(sqlstate, '') || ': ', '' ) || COALESCE( NULLIF(errmsg, ''), '' ),
221 | 'NO ERROR FOUND'
222 | )
223 | || COALESCE(E'\n DETAIL: ' || nullif(detail, ''), '')
224 | || COALESCE(E'\n HINT: ' || nullif(hint, ''), '')
225 | || COALESCE(E'\n SCHEMA: ' || nullif(schname, ''), '')
226 | || COALESCE(E'\n TABLE: ' || nullif(tabname, ''), '')
227 | || COALESCE(E'\n COLUMN: ' || nullif(colname, ''), '')
228 | || COALESCE(E'\n CONSTRAINT: ' || nullif(chkname, ''), '')
229 | || COALESCE(E'\n TYPE: ' || nullif(typname, ''), '')
230 | -- We need to manually indent all the context lines
231 | || COALESCE(E'\n CONTEXT:\n'
232 | || regexp_replace(NULLIF( context, ''), '^', ' ', 'gn'
233 | ), '');
234 | $$ LANGUAGE sql IMMUTABLE;
235 |
236 | -- lives_ok( sql, description )
237 | CREATE OR REPLACE FUNCTION lives_ok ( TEXT, TEXT )
238 | RETURNS TEXT AS $$
239 | DECLARE
240 | code TEXT := _query($1);
241 | descr ALIAS FOR $2;
242 | detail text;
243 | hint text;
244 | context text;
245 | schname text;
246 | tabname text;
247 | colname text;
248 | chkname text;
249 | typname text;
250 | BEGIN
251 | EXECUTE code;
252 | RETURN ok( TRUE, descr );
253 | EXCEPTION WHEN OTHERS THEN
254 | -- There should have been no exception.
255 | GET STACKED DIAGNOSTICS
256 | detail = PG_EXCEPTION_DETAIL,
257 | hint = PG_EXCEPTION_HINT,
258 | context = PG_EXCEPTION_CONTEXT,
259 | schname = SCHEMA_NAME,
260 | tabname = TABLE_NAME,
261 | colname = COLUMN_NAME,
262 | chkname = CONSTRAINT_NAME,
263 | typname = PG_DATATYPE_NAME;
264 | RETURN ok( FALSE, descr ) || E'\n' || diag(
265 | ' died: ' || _error_diag(SQLSTATE, SQLERRM, detail, hint, context, schname, tabname, colname, chkname, typname)
266 | );
267 | END;
268 | $$ LANGUAGE plpgsql;
269 |
270 | CREATE OR REPLACE FUNCTION _runner( text[], text[], text[], text[], text[] )
271 | RETURNS SETOF TEXT AS $$
272 | DECLARE
273 | startup ALIAS FOR $1;
274 | shutdown ALIAS FOR $2;
275 | setup ALIAS FOR $3;
276 | teardown ALIAS FOR $4;
277 | tests ALIAS FOR $5;
278 | tap TEXT;
279 | tfaild INTEGER := 0;
280 | ffaild INTEGER := 0;
281 | tnumb INTEGER := 0;
282 | fnumb INTEGER := 0;
283 | tok BOOLEAN := TRUE;
284 | BEGIN
285 | BEGIN
286 | -- No plan support.
287 | PERFORM * FROM no_plan();
288 | FOR tap IN SELECT * FROM _runem(startup, false) LOOP RETURN NEXT tap; END LOOP;
289 | EXCEPTION
290 | -- Catch all exceptions and simply rethrow custom exceptions. This
291 | -- will roll back everything in the above block.
292 | WHEN raise_exception THEN RAISE EXCEPTION '%', SQLERRM;
293 | END;
294 |
295 | -- Record how startup tests have failed.
296 | tfaild := num_failed();
297 |
298 | FOR i IN 1..COALESCE(array_upper(tests, 1), 0) LOOP
299 |
300 | -- What subtest are we running?
301 | RETURN NEXT ' ' || diag_test_name('Subtest: ' || tests[i]);
302 |
303 | -- Reset the results.
304 | tok := TRUE;
305 | tnumb := COALESCE(_get('curr_test'), 0);
306 |
307 | IF tnumb > 0 THEN
308 | EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH 1';
309 | PERFORM _set('curr_test', 0);
310 | PERFORM _set('failed', 0);
311 | END IF;
312 |
313 | DECLARE
314 | errstate text;
315 | errmsg text;
316 | detail text;
317 | hint text;
318 | context text;
319 | schname text;
320 | tabname text;
321 | colname text;
322 | chkname text;
323 | typname text;
324 | BEGIN
325 | BEGIN
326 | -- Run the setup functions.
327 | FOR tap IN SELECT * FROM _runem(setup, false) LOOP
328 | RETURN NEXT regexp_replace(tap, '^', ' ', 'gn');
329 | END LOOP;
330 |
331 | -- Run the actual test function.
332 | FOR tap IN EXECUTE 'SELECT * FROM ' || tests[i] || '()' LOOP
333 | RETURN NEXT regexp_replace(tap, '^', ' ', 'gn');
334 | END LOOP;
335 |
336 | -- Run the teardown functions.
337 | FOR tap IN SELECT * FROM _runem(teardown, false) LOOP
338 | RETURN NEXT regexp_replace(tap, '^', ' ', 'gn');
339 | END LOOP;
340 |
341 | -- Emit the plan.
342 | fnumb := COALESCE(_get('curr_test'), 0);
343 | RETURN NEXT ' 1..' || fnumb;
344 |
345 | -- Emit any error messages.
346 | IF fnumb = 0 THEN
347 | RETURN NEXT ' # No tests run!';
348 | tok = false;
349 | ELSE
350 | -- Report failures.
351 | ffaild := num_failed();
352 | IF ffaild > 0 THEN
353 | tok := FALSE;
354 | RETURN NEXT ' ' || diag(
355 | 'Looks like you failed ' || ffaild || ' test' ||
356 | CASE tfaild WHEN 1 THEN '' ELSE 's' END
357 | || ' of ' || fnumb
358 | );
359 | END IF;
360 | END IF;
361 |
362 | EXCEPTION WHEN raise_exception THEN
363 | -- Something went wrong. Record that fact.
364 | errstate := SQLSTATE;
365 | errmsg := SQLERRM;
366 | GET STACKED DIAGNOSTICS
367 | detail = PG_EXCEPTION_DETAIL,
368 | hint = PG_EXCEPTION_HINT,
369 | context = PG_EXCEPTION_CONTEXT,
370 | schname = SCHEMA_NAME,
371 | tabname = TABLE_NAME,
372 | colname = COLUMN_NAME,
373 | chkname = CONSTRAINT_NAME,
374 | typname = PG_DATATYPE_NAME;
375 | END;
376 |
377 | -- Always raise an exception to rollback any changes.
378 | RAISE EXCEPTION '__TAP_ROLLBACK__';
379 |
380 | EXCEPTION WHEN raise_exception THEN
381 | IF errmsg IS NOT NULL THEN
382 | -- Something went wrong. Emit the error message.
383 | tok := FALSE;
384 | RETURN NEXT regexp_replace( diag('Test died: ' || _error_diag(
385 | errstate, errmsg, detail, hint, context, schname, tabname, colname, chkname, typname
386 | )), '^', ' ', 'gn');
387 | errmsg := NULL;
388 | END IF;
389 | END;
390 |
391 | -- Restore the sequence.
392 | EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH ' || tnumb + 1;
393 | PERFORM _set('curr_test', tnumb);
394 | PERFORM _set('failed', tfaild);
395 |
396 | -- Record this test.
397 | RETURN NEXT ok(tok, tests[i]);
398 | IF NOT tok THEN tfaild := tfaild + 1; END IF;
399 |
400 | END LOOP;
401 |
402 | -- Run the shutdown functions.
403 | FOR tap IN SELECT * FROM _runem(shutdown, false) LOOP RETURN NEXT tap; END LOOP;
404 |
405 | -- Finish up.
406 | FOR tap IN SELECT * FROM _finish( COALESCE(_get('curr_test'), 0), 0, tfaild ) LOOP
407 | RETURN NEXT tap;
408 | END LOOP;
409 |
410 | -- Clean up and return.
411 | PERFORM _cleanup();
412 | RETURN;
413 | END;
414 | $$ LANGUAGE plpgsql;
415 |
416 |
--------------------------------------------------------------------------------
/test/sql/setup.sql:
--------------------------------------------------------------------------------
1 | \set QUIET 1
2 |
3 | --
4 | -- Tests for pgTAP.
5 | --
6 | --
7 | -- Format the output for nice TAP.
8 | \pset format unaligned
9 | \pset tuples_only true
10 | \pset pager
11 |
12 | -- Revert all changes on failure.
13 | \set ON_ERROR_ROLLBACK 1
14 | \set ON_ERROR_STOP true
15 |
16 | BEGIN;
17 |
18 | -- Uncomment when testing with PGOPTIONS=--search_path=tap
19 | -- CREATE SCHEMA tap; SET search_path TO tap,public;
20 |
21 | -- Load the TAP functions.
22 | \i sql/pgtap.sql
23 |
--------------------------------------------------------------------------------