ct_log.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright 2016-2021 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. return ctx;
  56. }
  57. static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx)
  58. {
  59. OPENSSL_free(ctx);
  60. }
  61. /* Converts a log's public key into a SHA256 log ID */
  62. static int ct_v1_log_id_from_pkey(CTLOG *log, EVP_PKEY *pkey)
  63. {
  64. int ret = 0;
  65. unsigned char *pkey_der = NULL;
  66. int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
  67. unsigned int len;
  68. EVP_MD *sha256 = NULL;
  69. if (pkey_der_len <= 0) {
  70. ERR_raise(ERR_LIB_CT, CT_R_LOG_KEY_INVALID);
  71. goto err;
  72. }
  73. sha256 = EVP_MD_fetch(log->libctx, "SHA2-256", log->propq);
  74. if (sha256 == NULL) {
  75. ERR_raise(ERR_LIB_CT, ERR_R_EVP_LIB);
  76. goto err;
  77. }
  78. ret = EVP_Digest(pkey_der, pkey_der_len, log->log_id, &len, sha256,
  79. NULL);
  80. err:
  81. EVP_MD_free(sha256);
  82. OPENSSL_free(pkey_der);
  83. return ret;
  84. }
  85. CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
  86. {
  87. CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
  88. if (ret == NULL)
  89. return NULL;
  90. ret->libctx = libctx;
  91. if (propq != NULL) {
  92. ret->propq = OPENSSL_strdup(propq);
  93. if (ret->propq == NULL)
  94. goto err;
  95. }
  96. ret->logs = sk_CTLOG_new_null();
  97. if (ret->logs == NULL) {
  98. ERR_raise(ERR_LIB_CT, ERR_R_CRYPTO_LIB);
  99. goto err;
  100. }
  101. return ret;
  102. err:
  103. CTLOG_STORE_free(ret);
  104. return NULL;
  105. }
  106. CTLOG_STORE *CTLOG_STORE_new(void)
  107. {
  108. return CTLOG_STORE_new_ex(NULL, NULL);
  109. }
  110. void CTLOG_STORE_free(CTLOG_STORE *store)
  111. {
  112. if (store != NULL) {
  113. OPENSSL_free(store->propq);
  114. sk_CTLOG_pop_free(store->logs, CTLOG_free);
  115. OPENSSL_free(store);
  116. }
  117. }
  118. static int ctlog_new_from_conf(CTLOG_STORE *store, CTLOG **ct_log,
  119. const CONF *conf, const char *section)
  120. {
  121. const char *description = NCONF_get_string(conf, section, "description");
  122. char *pkey_base64;
  123. if (description == NULL) {
  124. ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_MISSING_DESCRIPTION);
  125. return 0;
  126. }
  127. pkey_base64 = NCONF_get_string(conf, section, "key");
  128. if (pkey_base64 == NULL) {
  129. ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_MISSING_KEY);
  130. return 0;
  131. }
  132. return CTLOG_new_from_base64_ex(ct_log, pkey_base64, description,
  133. store->libctx, store->propq);
  134. }
  135. int CTLOG_STORE_load_default_file(CTLOG_STORE *store)
  136. {
  137. const char *fpath = ossl_safe_getenv(CTLOG_FILE_EVP);
  138. if (fpath == NULL)
  139. fpath = CTLOG_FILE;
  140. return CTLOG_STORE_load_file(store, fpath);
  141. }
  142. /*
  143. * Called by CONF_parse_list, which stops if this returns <= 0,
  144. * Otherwise, one bad log entry would stop loading of any of
  145. * the following log entries.
  146. * It may stop parsing and returns -1 on any internal (malloc) error.
  147. */
  148. static int ctlog_store_load_log(const char *log_name, int log_name_len,
  149. void *arg)
  150. {
  151. CTLOG_STORE_LOAD_CTX *load_ctx = arg;
  152. CTLOG *ct_log = NULL;
  153. /* log_name may not be null-terminated, so fix that before using it */
  154. char *tmp;
  155. int ret = 0;
  156. /* log_name will be NULL for empty list entries */
  157. if (log_name == NULL)
  158. return 1;
  159. tmp = OPENSSL_strndup(log_name, log_name_len);
  160. if (tmp == NULL)
  161. return -1;
  162. ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp);
  163. OPENSSL_free(tmp);
  164. if (ret < 0) {
  165. /* Propagate any internal error */
  166. return ret;
  167. }
  168. if (ret == 0) {
  169. /* If we can't load this log, record that fact and skip it */
  170. ++load_ctx->invalid_log_entries;
  171. return 1;
  172. }
  173. if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) {
  174. CTLOG_free(ct_log);
  175. ERR_raise(ERR_LIB_CT, ERR_R_CRYPTO_LIB);
  176. return -1;
  177. }
  178. return 1;
  179. }
  180. int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
  181. {
  182. int ret = 0;
  183. char *enabled_logs;
  184. CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new();
  185. if (load_ctx == NULL)
  186. return 0;
  187. load_ctx->log_store = store;
  188. load_ctx->conf = NCONF_new(NULL);
  189. if (load_ctx->conf == NULL)
  190. goto end;
  191. if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
  192. ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
  193. goto end;
  194. }
  195. enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
  196. if (enabled_logs == NULL) {
  197. ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
  198. goto end;
  199. }
  200. if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) ||
  201. load_ctx->invalid_log_entries > 0) {
  202. ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
  203. goto end;
  204. }
  205. ret = 1;
  206. end:
  207. NCONF_free(load_ctx->conf);
  208. ctlog_store_load_ctx_free(load_ctx);
  209. return ret;
  210. }
  211. /*
  212. * Initialize a new CTLOG object.
  213. * Takes ownership of the public key.
  214. * Copies the name.
  215. */
  216. CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name, OSSL_LIB_CTX *libctx,
  217. const char *propq)
  218. {
  219. CTLOG *ret = OPENSSL_zalloc(sizeof(*ret));
  220. if (ret == NULL)
  221. return NULL;
  222. ret->libctx = libctx;
  223. if (propq != NULL) {
  224. ret->propq = OPENSSL_strdup(propq);
  225. if (ret->propq == NULL)
  226. goto err;
  227. }
  228. ret->name = OPENSSL_strdup(name);
  229. if (ret->name == NULL)
  230. goto err;
  231. if (ct_v1_log_id_from_pkey(ret, public_key) != 1)
  232. goto err;
  233. ret->public_key = public_key;
  234. return ret;
  235. err:
  236. CTLOG_free(ret);
  237. return NULL;
  238. }
  239. CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
  240. {
  241. return CTLOG_new_ex(public_key, name, NULL, NULL);
  242. }
  243. /* Frees CT log and associated structures */
  244. void CTLOG_free(CTLOG *log)
  245. {
  246. if (log != NULL) {
  247. OPENSSL_free(log->name);
  248. EVP_PKEY_free(log->public_key);
  249. OPENSSL_free(log->propq);
  250. OPENSSL_free(log);
  251. }
  252. }
  253. const char *CTLOG_get0_name(const CTLOG *log)
  254. {
  255. return log->name;
  256. }
  257. void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id,
  258. size_t *log_id_len)
  259. {
  260. *log_id = log->log_id;
  261. *log_id_len = CT_V1_HASHLEN;
  262. }
  263. EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log)
  264. {
  265. return log->public_key;
  266. }
  267. /*
  268. * Given a log ID, finds the matching log.
  269. * Returns NULL if no match found.
  270. */
  271. const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store,
  272. const uint8_t *log_id,
  273. size_t log_id_len)
  274. {
  275. int i;
  276. for (i = 0; i < sk_CTLOG_num(store->logs); ++i) {
  277. const CTLOG *log = sk_CTLOG_value(store->logs, i);
  278. if (memcmp(log->log_id, log_id, log_id_len) == 0)
  279. return log;
  280. }
  281. return NULL;
  282. }