ct_log.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <openssl/conf.h>
  12. #include <openssl/ct.h>
  13. #include <openssl/err.h>
  14. #include <openssl/evp.h>
  15. #include <openssl/safestack.h>
  16. #include "internal/cryptlib.h"
  17. /*
  18. * Information about a CT log server.
  19. */
  20. struct ctlog_st {
  21. OSSL_LIB_CTX *libctx;
  22. char *propq;
  23. char *name;
  24. uint8_t log_id[CT_V1_HASHLEN];
  25. EVP_PKEY *public_key;
  26. };
  27. /*
  28. * A store for multiple CTLOG instances.
  29. * It takes ownership of any CTLOG instances added to it.
  30. */
  31. struct ctlog_store_st {
  32. OSSL_LIB_CTX *libctx;
  33. char *propq;
  34. STACK_OF(CTLOG) *logs;
  35. };
  36. /* The context when loading a CT log list from a CONF file. */
  37. typedef struct ctlog_store_load_ctx_st {
  38. CTLOG_STORE *log_store;
  39. CONF *conf;
  40. size_t invalid_log_entries;
  41. } CTLOG_STORE_LOAD_CTX;
  42. /*
  43. * Creates an empty context for loading a CT log store.
  44. * It should be populated before use.
  45. */
  46. static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void);
  47. /*
  48. * Deletes a CT log store load context.
  49. * Does not delete any of the fields.
  50. */
  51. static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx);
  52. static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void)
  53. {
  54. CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
  55. if (ctx == NULL)
  56. CTerr(CT_F_CTLOG_STORE_LOAD_CTX_NEW, ERR_R_MALLOC_FAILURE);
  57. return ctx;
  58. }
  59. static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx)
  60. {
  61. OPENSSL_free(ctx);
  62. }
  63. /* Converts a log's public key into a SHA256 log ID */
  64. static int ct_v1_log_id_from_pkey(CTLOG *log, EVP_PKEY *pkey)
  65. {
  66. int ret = 0;
  67. unsigned char *pkey_der = NULL;
  68. int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
  69. unsigned int len;
  70. EVP_MD *sha256 = NULL;
  71. if (pkey_der_len <= 0) {
  72. CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID);
  73. goto err;
  74. }
  75. sha256 = EVP_MD_fetch(log->libctx, "SHA2-256", log->propq);
  76. if (sha256 == NULL) {
  77. CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, ERR_LIB_EVP);
  78. goto err;
  79. }
  80. ret = EVP_Digest(pkey_der, pkey_der_len, log->log_id, &len, sha256,
  81. NULL);
  82. err:
  83. EVP_MD_free(sha256);
  84. OPENSSL_free(pkey_der);
  85. return ret;
  86. }
  87. CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
  88. {
  89. CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
  90. if (ret == NULL) {
  91. CTerr(0, ERR_R_MALLOC_FAILURE);
  92. return NULL;
  93. }
  94. ret->libctx = libctx;
  95. if (propq != NULL) {
  96. ret->propq = OPENSSL_strdup(propq);
  97. if (ret->propq == NULL) {
  98. CTerr(0, ERR_R_MALLOC_FAILURE);
  99. goto err;
  100. }
  101. }
  102. ret->logs = sk_CTLOG_new_null();
  103. if (ret->logs == NULL) {
  104. CTerr(0, ERR_R_MALLOC_FAILURE);
  105. goto err;
  106. }
  107. return ret;
  108. err:
  109. CTLOG_STORE_free(ret);
  110. return NULL;
  111. }
  112. CTLOG_STORE *CTLOG_STORE_new(void)
  113. {
  114. return CTLOG_STORE_new_ex(NULL, NULL);
  115. }
  116. void CTLOG_STORE_free(CTLOG_STORE *store)
  117. {
  118. if (store != NULL) {
  119. OPENSSL_free(store->propq);
  120. sk_CTLOG_pop_free(store->logs, CTLOG_free);
  121. OPENSSL_free(store);
  122. }
  123. }
  124. static int ctlog_new_from_conf(CTLOG_STORE *store, CTLOG **ct_log,
  125. const CONF *conf, const char *section)
  126. {
  127. const char *description = NCONF_get_string(conf, section, "description");
  128. char *pkey_base64;
  129. if (description == NULL) {
  130. CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_DESCRIPTION);
  131. return 0;
  132. }
  133. pkey_base64 = NCONF_get_string(conf, section, "key");
  134. if (pkey_base64 == NULL) {
  135. CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_KEY);
  136. return 0;
  137. }
  138. return CTLOG_new_from_base64_ex(ct_log, pkey_base64, description,
  139. store->libctx, store->propq);
  140. }
  141. int CTLOG_STORE_load_default_file(CTLOG_STORE *store)
  142. {
  143. const char *fpath = ossl_safe_getenv(CTLOG_FILE_EVP);
  144. if (fpath == NULL)
  145. fpath = CTLOG_FILE;
  146. return CTLOG_STORE_load_file(store, fpath);
  147. }
  148. /*
  149. * Called by CONF_parse_list, which stops if this returns <= 0,
  150. * Otherwise, one bad log entry would stop loading of any of
  151. * the following log entries.
  152. * It may stop parsing and returns -1 on any internal (malloc) error.
  153. */
  154. static int ctlog_store_load_log(const char *log_name, int log_name_len,
  155. void *arg)
  156. {
  157. CTLOG_STORE_LOAD_CTX *load_ctx = arg;
  158. CTLOG *ct_log = NULL;
  159. /* log_name may not be null-terminated, so fix that before using it */
  160. char *tmp;
  161. int ret = 0;
  162. /* log_name will be NULL for empty list entries */
  163. if (log_name == NULL)
  164. return 1;
  165. tmp = OPENSSL_strndup(log_name, log_name_len);
  166. if (tmp == NULL)
  167. goto mem_err;
  168. ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp);
  169. OPENSSL_free(tmp);
  170. if (ret < 0) {
  171. /* Propagate any internal error */
  172. return ret;
  173. }
  174. if (ret == 0) {
  175. /* If we can't load this log, record that fact and skip it */
  176. ++load_ctx->invalid_log_entries;
  177. return 1;
  178. }
  179. if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) {
  180. goto mem_err;
  181. }
  182. return 1;
  183. mem_err:
  184. CTLOG_free(ct_log);
  185. CTerr(CT_F_CTLOG_STORE_LOAD_LOG, ERR_R_MALLOC_FAILURE);
  186. return -1;
  187. }
  188. int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
  189. {
  190. int ret = 0;
  191. char *enabled_logs;
  192. CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new();
  193. if (load_ctx == NULL)
  194. return 0;
  195. load_ctx->log_store = store;
  196. load_ctx->conf = NCONF_new(NULL);
  197. if (load_ctx->conf == NULL)
  198. goto end;
  199. if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
  200. CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
  201. goto end;
  202. }
  203. enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
  204. if (enabled_logs == NULL) {
  205. CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
  206. goto end;
  207. }
  208. if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) ||
  209. load_ctx->invalid_log_entries > 0) {
  210. CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
  211. goto end;
  212. }
  213. ret = 1;
  214. end:
  215. NCONF_free(load_ctx->conf);
  216. ctlog_store_load_ctx_free(load_ctx);
  217. return ret;
  218. }
  219. /*
  220. * Initialize a new CTLOG object.
  221. * Takes ownership of the public key.
  222. * Copies the name.
  223. */
  224. CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name, OSSL_LIB_CTX *libctx,
  225. const char *propq)
  226. {
  227. CTLOG *ret = OPENSSL_zalloc(sizeof(*ret));
  228. if (ret == NULL) {
  229. CTerr(0, ERR_R_MALLOC_FAILURE);
  230. return NULL;
  231. }
  232. ret->libctx = libctx;
  233. if (propq != NULL) {
  234. ret->name = OPENSSL_strdup(propq);
  235. if (ret->propq == NULL) {
  236. CTerr(0, ERR_R_MALLOC_FAILURE);
  237. goto err;
  238. }
  239. }
  240. ret->name = OPENSSL_strdup(name);
  241. if (ret->name == NULL) {
  242. CTerr(0, ERR_R_MALLOC_FAILURE);
  243. goto err;
  244. }
  245. if (ct_v1_log_id_from_pkey(ret, public_key) != 1)
  246. goto err;
  247. ret->public_key = public_key;
  248. return ret;
  249. err:
  250. CTLOG_free(ret);
  251. return NULL;
  252. }
  253. CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
  254. {
  255. return CTLOG_new_ex(public_key, name, NULL, NULL);
  256. }
  257. /* Frees CT log and associated structures */
  258. void CTLOG_free(CTLOG *log)
  259. {
  260. if (log != NULL) {
  261. OPENSSL_free(log->name);
  262. EVP_PKEY_free(log->public_key);
  263. OPENSSL_free(log->propq);
  264. OPENSSL_free(log);
  265. }
  266. }
  267. const char *CTLOG_get0_name(const CTLOG *log)
  268. {
  269. return log->name;
  270. }
  271. void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id,
  272. size_t *log_id_len)
  273. {
  274. *log_id = log->log_id;
  275. *log_id_len = CT_V1_HASHLEN;
  276. }
  277. EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log)
  278. {
  279. return log->public_key;
  280. }
  281. /*
  282. * Given a log ID, finds the matching log.
  283. * Returns NULL if no match found.
  284. */
  285. const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store,
  286. const uint8_t *log_id,
  287. size_t log_id_len)
  288. {
  289. int i;
  290. for (i = 0; i < sk_CTLOG_num(store->logs); ++i) {
  291. const CTLOG *log = sk_CTLOG_value(store->logs, i);
  292. if (memcmp(log->log_id, log_id, log_id_len) == 0)
  293. return log;
  294. }
  295. return NULL;
  296. }