ct_log.c 7.3 KB

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