engine_loader.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright 2018-2022 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. /*
  10. * Here is an STORE loader for ENGINE backed keys. It relies on deprecated
  11. * functions, and therefore need to have deprecation warnings suppressed.
  12. * This file is not compiled at all in a '--api=3 no-deprecated' configuration.
  13. */
  14. #define OPENSSL_SUPPRESS_DEPRECATED
  15. #include "apps.h"
  16. #ifndef OPENSSL_NO_ENGINE
  17. # include <stdarg.h>
  18. # include <string.h>
  19. # include <openssl/engine.h>
  20. # include <openssl/store.h>
  21. /*
  22. * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
  23. *
  24. * org.openssl.engine:{engineid}:{keyid}
  25. *
  26. * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
  27. * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
  28. * this sort of purpose.
  29. */
  30. /* Local definition of OSSL_STORE_LOADER_CTX */
  31. struct ossl_store_loader_ctx_st {
  32. ENGINE *e; /* Structural reference */
  33. char *keyid;
  34. int expected;
  35. int loaded; /* 0 = key not loaded yet, 1 = key loaded */
  36. };
  37. static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
  38. {
  39. OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
  40. if (ctx != NULL) {
  41. ctx->e = e;
  42. ctx->keyid = keyid;
  43. }
  44. return ctx;
  45. }
  46. static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
  47. {
  48. if (ctx != NULL) {
  49. ENGINE_free(ctx->e);
  50. OPENSSL_free(ctx->keyid);
  51. OPENSSL_free(ctx);
  52. }
  53. }
  54. static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
  55. const char *uri,
  56. const UI_METHOD *ui_method,
  57. void *ui_data)
  58. {
  59. const char *p = uri, *q;
  60. ENGINE *e = NULL;
  61. char *keyid = NULL;
  62. OSSL_STORE_LOADER_CTX *ctx = NULL;
  63. if (!CHECK_AND_SKIP_CASE_PREFIX(p, ENGINE_SCHEME_COLON))
  64. return NULL;
  65. /* Look for engine ID */
  66. q = strchr(p, ':');
  67. if (q != NULL /* There is both an engine ID and a key ID */
  68. && p[0] != ':' /* The engine ID is at least one character */
  69. && q[1] != '\0') { /* The key ID is at least one character */
  70. char engineid[256];
  71. size_t engineid_l = q - p;
  72. strncpy(engineid, p, engineid_l);
  73. engineid[engineid_l] = '\0';
  74. e = ENGINE_by_id(engineid);
  75. keyid = OPENSSL_strdup(q + 1);
  76. }
  77. if (e != NULL && keyid != NULL)
  78. ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
  79. if (ctx == NULL) {
  80. OPENSSL_free(keyid);
  81. ENGINE_free(e);
  82. }
  83. return ctx;
  84. }
  85. static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
  86. {
  87. if (expected == 0
  88. || expected == OSSL_STORE_INFO_PUBKEY
  89. || expected == OSSL_STORE_INFO_PKEY) {
  90. ctx->expected = expected;
  91. return 1;
  92. }
  93. return 0;
  94. }
  95. static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
  96. const UI_METHOD *ui_method, void *ui_data)
  97. {
  98. EVP_PKEY *pkey = NULL, *pubkey = NULL;
  99. OSSL_STORE_INFO *info = NULL;
  100. if (ctx->loaded == 0) {
  101. if (ENGINE_init(ctx->e)) {
  102. if (ctx->expected == 0
  103. || ctx->expected == OSSL_STORE_INFO_PKEY)
  104. pkey =
  105. ENGINE_load_private_key(ctx->e, ctx->keyid,
  106. (UI_METHOD *)ui_method, ui_data);
  107. if ((pkey == NULL && ctx->expected == 0)
  108. || ctx->expected == OSSL_STORE_INFO_PUBKEY)
  109. pubkey =
  110. ENGINE_load_public_key(ctx->e, ctx->keyid,
  111. (UI_METHOD *)ui_method, ui_data);
  112. ENGINE_finish(ctx->e);
  113. }
  114. }
  115. ctx->loaded = 1;
  116. if (pubkey != NULL)
  117. info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
  118. else if (pkey != NULL)
  119. info = OSSL_STORE_INFO_new_PKEY(pkey);
  120. if (info == NULL) {
  121. EVP_PKEY_free(pkey);
  122. EVP_PKEY_free(pubkey);
  123. }
  124. return info;
  125. }
  126. static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
  127. {
  128. return ctx->loaded != 0;
  129. }
  130. static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
  131. {
  132. return 0;
  133. }
  134. static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
  135. {
  136. OSSL_STORE_LOADER_CTX_free(ctx);
  137. return 1;
  138. }
  139. int setup_engine_loader(void)
  140. {
  141. OSSL_STORE_LOADER *loader = NULL;
  142. if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
  143. || !OSSL_STORE_LOADER_set_open(loader, engine_open)
  144. || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
  145. || !OSSL_STORE_LOADER_set_load(loader, engine_load)
  146. || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
  147. || !OSSL_STORE_LOADER_set_error(loader, engine_error)
  148. || !OSSL_STORE_LOADER_set_close(loader, engine_close)
  149. || !OSSL_STORE_register_loader(loader)) {
  150. OSSL_STORE_LOADER_free(loader);
  151. loader = NULL;
  152. }
  153. return loader != NULL;
  154. }
  155. void destroy_engine_loader(void)
  156. {
  157. OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
  158. OSSL_STORE_LOADER_free(loader);
  159. }
  160. #else /* !OPENSSL_NO_ENGINE */
  161. int setup_engine_loader(void)
  162. {
  163. return 0;
  164. }
  165. void destroy_engine_loader(void)
  166. {
  167. }
  168. #endif