keymgmt_lib.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright 2019 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 "internal/cryptlib.h"
  10. #include "internal/nelem.h"
  11. #include "crypto/evp.h"
  12. #include "crypto/asn1.h"
  13. #include "internal/provider.h"
  14. #include "evp_local.h"
  15. static OSSL_PARAM *paramdefs_to_params(const OSSL_PARAM *paramdefs)
  16. {
  17. size_t cnt;
  18. const OSSL_PARAM *p;
  19. OSSL_PARAM *params, *q;
  20. for (cnt = 1, p = paramdefs; p->key != NULL; p++, cnt++)
  21. continue;
  22. params = OPENSSL_zalloc(cnt * sizeof(*params));
  23. for (p = paramdefs, q = params; ; p++, q++) {
  24. *q = *p;
  25. if (p->key == NULL)
  26. break;
  27. q->data = NULL; /* In case the provider used it */
  28. q->return_size = 0;
  29. }
  30. return params;
  31. }
  32. typedef union align_block_un {
  33. OSSL_UNION_ALIGN;
  34. } ALIGN_BLOCK;
  35. #define ALIGN_SIZE sizeof(ALIGN_BLOCK)
  36. static void *allocate_params_space(OSSL_PARAM *params)
  37. {
  38. unsigned char *data = NULL;
  39. size_t space;
  40. OSSL_PARAM *p;
  41. for (space = 0, p = params; p->key != NULL; p++)
  42. space += ((p->return_size + ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE;
  43. data = OPENSSL_zalloc(space);
  44. for (space = 0, p = params; p->key != NULL; p++) {
  45. p->data = data + space;
  46. space += ((p->return_size + ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE;
  47. }
  48. return data;
  49. }
  50. void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
  51. {
  52. void *provkey = NULL;
  53. size_t i, j;
  54. /*
  55. * If there is an underlying legacy key and it has changed, invalidate
  56. * the cache of provider keys.
  57. */
  58. if (pk->pkey.ptr != NULL) {
  59. /*
  60. * If there is no dirty counter, this key can't be used with
  61. * providers.
  62. */
  63. if (pk->ameth->dirty_cnt == NULL)
  64. return NULL;
  65. if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
  66. evp_keymgmt_clear_pkey_cache(pk);
  67. }
  68. /*
  69. * See if we have exported to this provider already.
  70. * If we have, return immediately.
  71. */
  72. for (i = 0;
  73. i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
  74. i++) {
  75. if (keymgmt == pk->pkeys[i].keymgmt)
  76. return pk->pkeys[i].provkey;
  77. }
  78. if (pk->pkey.ptr != NULL) {
  79. /* There is a legacy key, try to export that one to the provider */
  80. /* If the legacy key doesn't have an export function, give up */
  81. if (pk->ameth->export_to == NULL)
  82. return NULL;
  83. /* Otherwise, simply use it */
  84. provkey = pk->ameth->export_to(pk, keymgmt);
  85. /* Synchronize the dirty count, but only if we exported successfully */
  86. if (provkey != NULL)
  87. pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
  88. } else {
  89. /*
  90. * Here, there is no legacy key, so we look at the already cached
  91. * provider keys, and import from the first that supports it
  92. * (i.e. use its export function), and export the imported data to
  93. * the new provider.
  94. */
  95. /*
  96. * If the given keymgmt doesn't have an import function, give up
  97. */
  98. if (keymgmt->importkey == NULL)
  99. return NULL;
  100. for (j = 0; j < i && pk->pkeys[j].keymgmt != NULL; j++) {
  101. if (pk->pkeys[j].keymgmt->exportkey != NULL) {
  102. const OSSL_PARAM *paramdefs = NULL;
  103. OSSL_PARAM *params = NULL;
  104. void *data = NULL;
  105. void *provctx =
  106. ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  107. paramdefs = pk->pkeys[j].keymgmt->exportkey_types();
  108. /*
  109. * All params have 'data' set to NULL. In that case,
  110. * the exportkey call should just fill in 'return_size'
  111. * in all applicable params.
  112. */
  113. params = paramdefs_to_params(paramdefs);
  114. /* Get 'return_size' filled */
  115. pk->pkeys[j].keymgmt->exportkey(pk->pkeys[j].provkey, params);
  116. /*
  117. * Allocate space and assign 'data' to point into the
  118. * data block
  119. */
  120. data = allocate_params_space(params);
  121. /*
  122. * Call the exportkey function a second time, to get
  123. * the data filled
  124. */
  125. pk->pkeys[j].keymgmt->exportkey(pk->pkeys[j].provkey, params);
  126. /*
  127. * We should have all the data at this point, so import
  128. * into the new provider and hope to get a key back.
  129. */
  130. provkey = keymgmt->importkey(provctx, params);
  131. OPENSSL_free(params);
  132. OPENSSL_free(data);
  133. if (provkey != NULL)
  134. break;
  135. }
  136. }
  137. }
  138. /*
  139. * TODO(3.0) Right now, we assume we have ample space. We will
  140. * have to think about a cache aging scheme, though, if |i| indexes
  141. * outside the array.
  142. */
  143. j = ossl_assert(i < OSSL_NELEM(pk->pkeys));
  144. if (provkey != NULL) {
  145. EVP_KEYMGMT_up_ref(keymgmt);
  146. pk->pkeys[i].keymgmt = keymgmt;
  147. pk->pkeys[i].provkey = provkey;
  148. }
  149. return provkey;
  150. }
  151. void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
  152. {
  153. size_t i;
  154. if (pk != NULL) {
  155. for (i = 0;
  156. i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
  157. i++) {
  158. EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
  159. void *provkey = pk->pkeys[i].provkey;
  160. pk->pkeys[i].keymgmt = NULL;
  161. pk->pkeys[i].provkey = NULL;
  162. keymgmt->freekey(provkey);
  163. EVP_KEYMGMT_free(keymgmt);
  164. }
  165. }
  166. }
  167. /* internal functions */
  168. /* TODO(3.0) decide if these should be public or internal */
  169. void *evp_keymgmt_importdomparams(const EVP_KEYMGMT *keymgmt,
  170. const OSSL_PARAM params[])
  171. {
  172. void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  173. return keymgmt->importdomparams(provctx, params);
  174. }
  175. void *evp_keymgmt_gendomparams(const EVP_KEYMGMT *keymgmt,
  176. const OSSL_PARAM params[])
  177. {
  178. void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  179. return keymgmt->gendomparams(provctx, params);
  180. }
  181. void evp_keymgmt_freedomparams(const EVP_KEYMGMT *keymgmt,
  182. void *provdomparams)
  183. {
  184. keymgmt->freedomparams(provdomparams);
  185. }
  186. int evp_keymgmt_exportdomparams(const EVP_KEYMGMT *keymgmt,
  187. void *provdomparams, OSSL_PARAM params[])
  188. {
  189. return keymgmt->exportdomparams(provdomparams, params);
  190. }
  191. const OSSL_PARAM *evp_keymgmt_importdomparam_types(const EVP_KEYMGMT *keymgmt)
  192. {
  193. return keymgmt->importdomparam_types();
  194. }
  195. const OSSL_PARAM *evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT *keymgmt)
  196. {
  197. return keymgmt->exportdomparam_types();
  198. }
  199. void *evp_keymgmt_importkey(const EVP_KEYMGMT *keymgmt,
  200. const OSSL_PARAM params[])
  201. {
  202. void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  203. return keymgmt->importkey(provctx, params);
  204. }
  205. void *evp_keymgmt_genkey(const EVP_KEYMGMT *keymgmt, void *domparams,
  206. const OSSL_PARAM params[])
  207. {
  208. void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  209. return keymgmt->genkey(provctx, domparams, params);
  210. }
  211. void *evp_keymgmt_loadkey(const EVP_KEYMGMT *keymgmt,
  212. void *id, size_t idlen)
  213. {
  214. void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
  215. return keymgmt->loadkey(provctx, id, idlen);
  216. }
  217. void evp_keymgmt_freekey(const EVP_KEYMGMT *keymgmt, void *provkey)
  218. {
  219. keymgmt->freekey(provkey);
  220. }
  221. int evp_keymgmt_exportkey(const EVP_KEYMGMT *keymgmt, void *provkey,
  222. OSSL_PARAM params[])
  223. {
  224. return keymgmt->exportkey(provkey, params);
  225. }
  226. const OSSL_PARAM *evp_keymgmt_importkey_types(const EVP_KEYMGMT *keymgmt)
  227. {
  228. return keymgmt->importkey_types();
  229. }
  230. const OSSL_PARAM *evp_keymgmt_exportkey_types(const EVP_KEYMGMT *keymgmt)
  231. {
  232. return keymgmt->exportkey_types();
  233. }