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.

2953 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 <stdlib.h>
  12. #include "wrappers.h"
  13. #define TRACING 0
  14. #ifndef TRACING
  15. # ifndef NDEBUG
  16. # define TRACING 0
  17. # else
  18. # define TRACING 1
  19. # endif
  20. #endif
  21. // enable tracing if in debugging mode
  22. #if TRACING
  23. #include "status_to_string.h"
  24. # ifdef ANDROID
  25. # include <android/log.h>
  26. # define _T(...) do { \
  27. __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine-sequoia", \
  28. ##__VA_ARGS__); \
  29. } while (0)
  30. # elif _WIN32
  31. # define _T(...) do { \
  32. char str[256]; \
  33. snprintf(str, 256, ##__VA_ARGS__); \
  34. OutputDebugStringA(str); \
  35. fprintf(stderr, ##__VA_ARGS__); \
  36. } while (0)
  37. # else
  38. # define _T(...) do { \
  39. fprintf(stderr, ##__VA_ARGS__); \
  40. } while (0)
  41. # endif
  42. #else
  43. # define _T(...) do { } while (0)
  44. #endif
  45. // Show the start of a tracepoint (i.e., don't print a newline).
  46. #define TC(...) do { \
  47. _T("%s: ", __func__); \
  48. _T(__VA_ARGS__); \
  49. } while (0)
  50. // Show a trace point.
  51. # define T(...) do { \
  52. TC(__VA_ARGS__); \
  53. _T("\n"); \
  54. } while(0)
  55. // Verbosely displays errors.
  56. # define DUMP_STATUS(__de_sq_status, __de_pep_status, ...) do { \
  57. TC(__VA_ARGS__); \
  58. _T(": "); \
  59. if (__de_sq_status) { \
  60. _T("Sequoia: %s => ", pgp_status_to_string(__de_sq_status)); \
  61. } \
  62. _T("%s\n", pEp_status_to_string(__de_pep_status)); \
  63. } while(0)
  64. # define DUMP_ERR(__de_err, __de_status, ...) do { \
  65. TC(__VA_ARGS__); \
  66. _T(": "); \
  67. if (__de_err) { \
  68. _T("Sequoia: %s => ", pgp_error_to_string(__de_err)); \
  69. pgp_error_free(__de_err); \
  70. } \
  71. _T("%s\n", pEp_status_to_string(__de_status)); \
  72. } while(0)
  73. // If __ec_status is an error, then disable the error, set 'status' to
  74. // it, and jump to 'out'.
  75. #define ERROR_OUT(__e_err, __ec_status, ...) do { \
  76. PEP_STATUS ___ec_status = (__ec_status); \
  77. if ((___ec_status) != PEP_STATUS_OK) { \
  78. DUMP_ERR((__e_err), (___ec_status), ##__VA_ARGS__); \
  79. status = (___ec_status); \
  80. goto out; \
  81. } \
  82. } while(0)
  83. #ifdef _PEP_SQLITE_DEBUG
  84. int sq_sql_trace_callback (unsigned trace_constant,
  85. void* context_ptr,
  86. void* P,
  87. void* X) {
  88. switch (trace_constant) {
  89. case SQLITE_TRACE_STMT:
  90. fprintf(stderr, "SEQUOIA_SQL_DEBUG: STMT - ");
  91. const char* X_str = (const char*) X;
  92. if (!EMPTYSTR(X_str) && X_str[0] == '-' && X_str[1] == '-')
  93. fprintf(stderr, "%s\n", X_str);
  94. else
  95. fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
  96. break;
  97. case SQLITE_TRACE_ROW:
  98. fprintf(stderr, "SEQUOIA_SQL_DEBUG: ROW - ");
  99. fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
  100. break;
  101. case SQLITE_TRACE_CLOSE:
  102. fprintf(stderr, "SEQUOIA_SQL_DEBUG: CLOSE - ");
  103. break;
  104. default:
  105. break;
  106. }
  107. return 0;
  108. }
  109. #endif
  110. /* This is reallocarray taken from OpenBSD. See README.md for licensing. */
  111. /* Symbols are renamed for clashes, not to hide source. */
  112. /*
  113. * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
  114. * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
  115. */
  116. #define PEP_MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
  117. static void* _pEp_reallocarray(void *optr, size_t nmemb, size_t size)
  118. {
  119. if ((nmemb >= PEP_MUL_NO_OVERFLOW || size >= PEP_MUL_NO_OVERFLOW) &&
  120. nmemb > 0 && SIZE_MAX / nmemb < size) {
  121. errno = ENOMEM;
  122. return NULL;
  123. }
  124. return realloc(optr, size * nmemb);
  125. }
  126. PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session,
  127. PEP_CIPHER_SUITE suite)
  128. {
  129. switch (suite) {
  130. // supported cipher suites
  131. case PEP_CIPHER_SUITE_RSA2K:
  132. case PEP_CIPHER_SUITE_RSA3K:
  133. case PEP_CIPHER_SUITE_CV25519:
  134. case PEP_CIPHER_SUITE_P256:
  135. case PEP_CIPHER_SUITE_P384:
  136. case PEP_CIPHER_SUITE_P521:
  137. session->cipher_suite = suite;
  138. return PEP_STATUS_OK;
  139. case PEP_CIPHER_SUITE_DEFAULT:
  140. session->cipher_suite = PEP_CIPHER_SUITE_RSA2K;
  141. return PEP_STATUS_OK;
  142. // unsupported cipher suites
  143. default:
  144. session->cipher_suite = PEP_CIPHER_SUITE_RSA2K;
  145. return PEP_CANNOT_CONFIG;
  146. }
  147. }
  148. static pgp_tpk_cipher_suite_t cipher_suite(PEP_CIPHER_SUITE suite)
  149. {
  150. switch (suite) {
  151. // supported cipher suites
  152. case PEP_CIPHER_SUITE_RSA2K:
  153. return PGP_TPK_CIPHER_SUITE_RSA2K;
  154. case PEP_CIPHER_SUITE_RSA3K:
  155. return PGP_TPK_CIPHER_SUITE_RSA3K;
  156. case PEP_CIPHER_SUITE_CV25519:
  157. return PGP_TPK_CIPHER_SUITE_CV25519;
  158. case PEP_CIPHER_SUITE_P256:
  159. return PGP_TPK_CIPHER_SUITE_P256;
  160. case PEP_CIPHER_SUITE_P384:
  161. return PGP_TPK_CIPHER_SUITE_P384;
  162. case PEP_CIPHER_SUITE_P521:
  163. return PGP_TPK_CIPHER_SUITE_P521;
  164. default:
  165. return PGP_TPK_CIPHER_SUITE_RSA2K;
  166. }
  167. }
  168. int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b)
  169. {
  170. pgp_packet_t a_userid = pgp_user_id_from_raw (a, a_len);
  171. pgp_packet_t b_userid = pgp_user_id_from_raw (b, b_len);
  172. char *a_email = NULL;
  173. pgp_user_id_email_normalized(NULL, a_userid, &a_email);
  174. if (!a_email)
  175. pgp_user_id_uri(NULL, a_userid, &a_email);
  176. char *b_email = NULL;
  177. pgp_user_id_email_normalized(NULL, b_userid, &b_email);
  178. if (!b_email)
  179. pgp_user_id_uri(NULL, b_userid, &b_email);
  180. pgp_packet_free(a_userid);
  181. pgp_packet_free(b_userid);
  182. // return an integer that is negative, zero, or positive if the
  183. // first string is less than, equal to, or greater than the
  184. // second, respectively.
  185. int result;
  186. if (!a_email && !b_email)
  187. result = 0;
  188. else if (!a_email)
  189. result = -1;
  190. else if (!b_email)
  191. result = 1;
  192. else
  193. result = strcmp(a_email, b_email);
  194. if (true) {
  195. T("'%s' %s '%s'",
  196. a_email,
  197. result == 0 ? "==" : result < 0 ? "<" : ">",
  198. b_email);
  199. }
  200. free(a_email);
  201. free(b_email);
  202. return result;
  203. }
  204. PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
  205. {
  206. PEP_STATUS status = PEP_STATUS_OK;
  207. #ifdef _WIN32
  208. int sqlite_result;
  209. sqlite_result = sqlite3_open_v2(KEYS_DB,
  210. &session->key_db,
  211. SQLITE_OPEN_READWRITE
  212. | SQLITE_OPEN_CREATE
  213. | SQLITE_OPEN_FULLMUTEX
  214. | SQLITE_OPEN_PRIVATECACHE,
  215. NULL);
  216. #else
  217. // Create the home directory.
  218. char *home_env = NULL;
  219. #ifndef NDEBUG
  220. home_env = getenv("PEP_HOME");
  221. #endif
  222. #define PEP_KEYS_PATH "/.pEp/keys.db"
  223. if (!home_env)
  224. home_env = getenv("HOME");
  225. if (!home_env)
  226. ERROR_OUT(NULL, PEP_INIT_GPGME_INIT_FAILED, "HOME unset");
  227. // Create the DB and initialize it.
  228. size_t path_size = strlen(home_env) + sizeof(PEP_KEYS_PATH);
  229. char *path = (char *) calloc(path_size, 1);
  230. assert(path);
  231. if (!path)
  232. ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  233. int r = snprintf(path, path_size, "%s" PEP_KEYS_PATH, home_env);
  234. assert(r >= 0 && r < path_size);
  235. if (r < 0) {
  236. free(path);
  237. ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, "snprintf");
  238. }
  239. int sqlite_result;
  240. sqlite_result = sqlite3_open_v2(path,
  241. &session->key_db,