p≡p engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2934 lines
98 KiB

3 years ago
3 years ago
3 years ago
3 years ago
  1. // This file is under GNU General Public License 3.0
  2. // see LICENSE.txt
  3. #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
  4. #define _GNU_SOURCE 1
  5. #include "platform.h"
  6. #include "pEp_internal.h"
  7. #include "pgp_sequoia.h"
  8. #include <limits.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include "wrappers.h"
  12. #define TRACING 0
  13. #ifndef TRACING
  14. # ifndef NDEBUG
  15. # define TRACING 0
  16. # else
  17. # define TRACING 1
  18. # endif
  19. #endif
  20. // enable tracing if in debugging mode
  21. #if TRACING
  22. #include "status_to_string.h"
  23. # ifdef ANDROID
  24. # include <android/log.h>
  25. # define _T(...) do { \
  26. __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine-sequoia", \
  27. ##__VA_ARGS__); \
  28. } while (0)
  29. # elif _WIN32
  30. # define _T(...) do { \
  31. char str[256]; \
  32. snprintf(str, 256, ##__VA_ARGS__); \
  33. OutputDebugStringA(str); \
  34. fprintf(stderr, ##__VA_ARGS__); \
  35. } while (0)
  36. # else
  37. # define _T(...) do { \
  38. fprintf(stderr, ##__VA_ARGS__); \
  39. } while (0)
  40. # endif
  41. #else
  42. # define _T(...) do { } while (0)
  43. #endif
  44. // Show the start of a tracepoint (i.e., don't print a newline).
  45. #define TC(...) do { \
  46. _T("%s: ", __func__); \
  47. _T(__VA_ARGS__); \
  48. } while (0)
  49. // Show a trace point.
  50. # define T(...) do { \
  51. TC(__VA_ARGS__); \
  52. _T("\n"); \
  53. } while(0)
  54. // Verbosely displays errors.
  55. # define DUMP_STATUS(__de_sq_status, __de_pep_status, ...) do { \
  56. TC(__VA_ARGS__); \
  57. _T(": "); \
  58. if (__de_sq_status) { \
  59. _T("Sequoia: %s => ", pgp_status_to_string(__de_sq_status)); \
  60. } \
  61. _T("%s\n", pEp_status_to_string(__de_pep_status)); \
  62. } while(0)
  63. # define DUMP_ERR(__de_err, __de_status, ...) do { \
  64. TC(__VA_ARGS__); \
  65. _T(": "); \
  66. if (__de_err) { \
  67. _T("Sequoia: %s => ", pgp_error_to_string(__de_err)); \
  68. pgp_error_free(__de_err); \
  69. } \
  70. _T("%s\n", pEp_status_to_string(__de_status)); \
  71. } while(0)
  72. // If __ec_status is an error, then disable the error, set 'status' to
  73. // it, and jump to 'out'.
  74. #define ERROR_OUT(__e_err, __ec_status, ...) do { \
  75. PEP_STATUS ___ec_status = (__ec_status); \
  76. if ((___ec_status) != PEP_STATUS_OK) { \
  77. DUMP_ERR((__e_err), (___ec_status), ##__VA_ARGS__); \
  78. status = (___ec_status); \
  79. goto out; \
  80. } \
  81. } while(0)
  82. #ifdef _PEP_SQLITE_DEBUG
  83. int sq_sql_trace_callback (unsigned trace_constant,
  84. void* context_ptr,
  85. void* P,
  86. void* X) {
  87. switch (trace_constant) {
  88. case SQLITE_TRACE_STMT:
  89. fprintf(stderr, "SEQUOIA_SQL_DEBUG: STMT - ");
  90. const char* X_str = (const char*) X;
  91. if (!EMPTYSTR(X_str) && X_str[0] == '-' && X_str[1] == '-')
  92. fprintf(stderr, "%s\n", X_str);
  93. else
  94. fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
  95. break;
  96. case SQLITE_TRACE_ROW:
  97. fprintf(stderr, "SEQUOIA_SQL_DEBUG: ROW - ");
  98. fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
  99. break;
  100. case SQLITE_TRACE_CLOSE:
  101. fprintf(stderr, "SEQUOIA_SQL_DEBUG: CLOSE - ");
  102. break;
  103. default:
  104. break;
  105. }
  106. return 0;
  107. }
  108. #endif
  109. PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session,
  110. PEP_CIPHER_SUITE suite)
  111. {
  112. switch (suite) {
  113. // supported cipher suites
  114. case PEP_CIPHER_SUITE_RSA2K:
  115. case PEP_CIPHER_SUITE_RSA3K:
  116. case PEP_CIPHER_SUITE_CV25519:
  117. case PEP_CIPHER_SUITE_P256:
  118. case PEP_CIPHER_SUITE_P384:
  119. case PEP_CIPHER_SUITE_P521:
  120. session->cipher_suite = suite;
  121. return PEP_STATUS_OK;
  122. case PEP_CIPHER_SUITE_DEFAULT:
  123. session->cipher_suite = PEP_CIPHER_SUITE_RSA2K;
  124. return PEP_STATUS_OK;
  125. // unsupported cipher suites
  126. default:
  127. session->cipher_suite = PEP_CIPHER_SUITE_RSA2K;
  128. return PEP_CANNOT_CONFIG;
  129. }
  130. }
  131. static pgp_tpk_cipher_suite_t cipher_suite(PEP_CIPHER_SUITE suite)
  132. {
  133. switch (suite) {
  134. // supported cipher suites
  135. case PEP_CIPHER_SUITE_RSA2K:
  136. return PGP_TPK_CIPHER_SUITE_RSA2K;
  137. case PEP_CIPHER_SUITE_RSA3K:
  138. return PGP_TPK_CIPHER_SUITE_RSA3K;
  139. case PEP_CIPHER_SUITE_CV25519:
  140. return PGP_TPK_CIPHER_SUITE_CV25519;
  141. case PEP_CIPHER_SUITE_P256:
  142. return PGP_TPK_CIPHER_SUITE_P256;
  143. case PEP_CIPHER_SUITE_P384:
  144. return PGP_TPK_CIPHER_SUITE_P384;
  145. case PEP_CIPHER_SUITE_P521:
  146. return PGP_TPK_CIPHER_SUITE_P521;
  147. default:
  148. return PGP_TPK_CIPHER_SUITE_RSA2K;
  149. }
  150. }
  151. int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b)
  152. {
  153. pgp_packet_t a_userid = pgp_user_id_from_raw (a, a_len);
  154. pgp_packet_t b_userid = pgp_user_id_from_raw (b, b_len);
  155. char *a_email = NULL;
  156. pgp_user_id_email_normalized(NULL, a_userid, &a_email);
  157. if (!a_email)
  158. pgp_user_id_uri(NULL, a_userid, &a_email);
  159. char *b_email = NULL;
  160. pgp_user_id_email_normalized(NULL, b_userid, &b_email);
  161. if (!b_email)
  162. pgp_user_id_uri(NULL, b_userid, &b_email);
  163. pgp_packet_free(a_userid);
  164. pgp_packet_free(b_userid);
  165. // return an integer that is negative, zero, or positive if the
  166. // first string is less than, equal to, or greater than the
  167. // second, respectively.
  168. int result;
  169. if (!a_email && !b_email)
  170. result = 0;
  171. else if (!a_email)
  172. result = -1;
  173. else if (!b_email)
  174. result = 1;
  175. else
  176. result = strcmp(a_email, b_email);
  177. if (true) {
  178. T("'%s' %s '%s'",
  179. a_email,
  180. result == 0 ? "==" : result < 0 ? "<" : ">",
  181. b_email);
  182. }
  183. free(a_email);
  184. free(b_email);
  185. return result;
  186. }
  187. PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
  188. {
  189. PEP_STATUS status = PEP_STATUS_OK;
  190. #ifdef _WIN32
  191. int sqlite_result;
  192. sqlite_result = sqlite3_open_v2(KEYS_DB,
  193. &session->key_db,
  194. SQLITE_OPEN_READWRITE
  195. | SQLITE_OPEN_CREATE
  196. | SQLITE_OPEN_FULLMUTEX
  197. | SQLITE_OPEN_PRIVATECACHE,
  198. NULL);
  199. #else
  200. // Create the home directory.
  201. char *home_env = NULL;
  202. #ifndef NDEBUG
  203. home_env = getenv("PEP_HOME");
  204. #endif
  205. #define PEP_KEYS_PATH "/.pEp/keys.db"
  206. if (!home_env)
  207. home_env = getenv("HOME");
  208. if (!home_env)
  209. ERROR_OUT(NULL, PEP_INIT_GPGME_INIT_FAILED, "HOME unset");
  210. // Create the DB and initialize it.
  211. size_t path_size = strlen(home_env) + sizeof(PEP_KEYS_PATH);
  212. char *path = (char *) calloc(path_size, 1);
  213. assert(path);
  214. if (!path)
  215. ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  216. int r = snprintf(path, path_size, "%s" PEP_KEYS_PATH, home_env);
  217. assert(r >= 0 && r < path_size);
  218. if (r < 0) {
  219. free(path);
  220. ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, "snprintf");
  221. }
  222. int sqlite_result;
  223. sqlite_result = sqlite3_open_v2(path,
  224. &session->key_db,
  225. SQLITE_OPEN_READWRITE
  226. | SQLITE_OPEN_CREATE
  227. | SQLITE_OPEN_FULLMUTEX
  228. | SQLITE_OPEN_PRIVATECACHE,
  229. NULL);
  230. free(path);
  231. #endif
  232. #ifdef _PEP_SQLITE_DEBUG
  233. sqlite3_trace_v2(session->key_db,
  234. SQLITE_TRACE_STMT | SQLITE_TRACE_ROW | SQLITE_TRACE_CLOSE,
  235. sq_sql_trace_callback,
  236. NULL);
  237. #endif
  238. if (sqlite_result != SQLITE_OK)
  239. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  240. "opening keys DB: %s", sqlite3_errmsg(session->key_db));
  241. sqlite_result = sqlite3_exec(session->key_db,
  242. "PRAGMA secure_delete=true;\n"
  243. "PRAGMA foreign_keys=true;\n"
  244. "PRAGMA locking_mode=NORMAL;\n"
  245. "PRAGMA journal_mode=WAL;\n",
  246. NULL, NULL, NULL);
  247. if (sqlite_result != SQLITE_OK)
  248. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  249. "setting pragmas: %s", sqlite3_errmsg(session->key_db));
  250. sqlite3_busy_timeout(session->key_db, BUSY_WAIT_TIME);
  251. sqlite_result =
  252. sqlite3_create_collation(session->key_db,
  253. "EMAIL",
  254. SQLITE_UTF8,
  255. /* pArg (cookie) */ NULL,
  256. email_cmp);
  257. if (sqlite_result != SQLITE_OK)
  258. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  259. "registering EMAIL collation function: %s",
  260. sqlite3_errmsg(session->key_db));
  261. sqlite_result = sqlite3_exec(session->key_db,
  262. "CREATE TABLE IF NOT EXISTS keys (\n"
  263. " primary_key TEXT UNIQUE PRIMARY KEY,\n"
  264. " secret BOOLEAN,\n"
  265. " tpk BLOB\n"
  266. ");\n"
  267. "CREATE INDEX IF NOT EXISTS keys_index\n"
  268. " ON keys (primary_key, secret)\n",
  269. NULL, NULL, NULL);
  270. if (sqlite_result != SQLITE_OK)
  271. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  272. "creating keys table: %s",
  273. sqlite3_errmsg(session->key_db));
  274. sqlite_result = sqlite3_exec(session->key_db,
  275. "CREATE TABLE IF NOT EXISTS subkeys (\n"
  276. " subkey TEXT NOT NULL,\n"
  277. " primary_key TEXT NOT NULL,\n"
  278. " UNIQUE(subkey, primary_key),\n"
  279. " FOREIGN KEY (primary_key)\n"
  280. " REFERENCES keys(primary_key)\n"
  281. " ON DELETE CASCADE\n"
  282. ");\n"
  283. "CREATE INDEX IF NOT EXISTS subkeys_index\n"
  284. " ON subkeys (subkey, primary_key)\n",
  285. NULL, NULL, NULL);
  286. if (sqlite_result != SQLITE_OK)
  287. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  288. "creating subkeys table: %s",
  289. sqlite3_errmsg(session->key_db));
  290. sqlite_result = sqlite3_exec(session->key_db,
  291. "CREATE TABLE IF NOT EXISTS userids (\n"
  292. " userid TEXT NOT NULL COLLATE EMAIL,\n"
  293. " primary_key TEXT NOT NULL,\n"
  294. " UNIQUE(userid, primary_key),\n"
  295. " FOREIGN KEY (primary_key)\n"
  296. " REFERENCES keys(primary_key)\n"
  297. " ON DELETE CASCADE\n"
  298. ");\n"
  299. "CREATE INDEX IF NOT EXISTS userids_index\n"
  300. " ON userids (userid COLLATE EMAIL, primary_key)\n",
  301. NULL, NULL, NULL);
  302. if (sqlite_result != SQLITE_OK)
  303. ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
  304. "creating userids table: %s",
  305. sqlite3_errmsg(session->key_db));
  306. sqlite_result
  307. = sqlite3_prepare_v2(session->key_db, "begin transaction",
  308. -1, &session->sq_sql.begin_transaction, NULL);
  309. assert(sqlite_result == SQLITE_OK);
  310. sqlite_result
  311. = sqlite3_prepare_v2(session->key_db, "commit transaction",
  312. -1, &session->sq_sql.commit_transaction, NULL);
  313. assert(sqlite_result == SQLITE_OK);
  314. sqlite_result
  315. = sqlite3_prepare_v2(session->key_db, "rollback transaction",
  316. -1, &session->sq_sql.rollback_transaction, NULL);
  317. assert(sqlite_result == SQLITE_OK);
  318. sqlite_result
  319. = sqlite3_prepare_v2(session->key_db,
  320. "SELECT tpk, secret FROM keys"
  321. " WHERE primary_key == ?",
  322. -1, &session->sq_sql.tpk_find, NULL);
  323. assert(sqlite_result == SQLITE_OK);
  324. sqlite_result
  325. = sqlite3_prepare_v2(session->key_db,
  326. "SELECT tpk, secret FROM keys"
  327. " WHERE primary_key == ? and secret == 1",
  328. -1, &session->sq_sql.tsk_find, NULL);
  329. assert(sqlite_result == SQLITE_OK);
  330. sqlite_result
  331. = sqlite3_prepare_v2(session->key_db,
  332. "SELECT tpk, secret FROM subkeys"
  333. " LEFT JOIN keys"
  334. " ON subkeys.primary_key == keys.primary_key"
  335. " WHERE subkey == ?",
  336. -1, &session->sq_sql.tpk_find_by_keyid, NULL);
  337. assert(sqlite_result == SQLITE_OK);
  338. sqlite_result
  339. = sqlite3_prepare_v2(session->key_db,
  340. "SELECT tpk, secret FROM subkeys"
  341. " LEFT JOIN keys"
  342. " ON subkeys.primary_key == keys.primary_key"
  343. " WHERE subkey == ?",
  344. -1, &session->sq_sql.tpk_find_by_keyid, NULL);
  345. assert(sqlite_result == SQLITE_OK);
  346. sqlite_result
  347. = sqlite3_prepare_v2(sess