encode_key2blob.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2021-2023 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. * Low level APIs are deprecated for public use, but still ok for internal use.
  11. */
  12. #include "internal/deprecated.h"
  13. #include <openssl/core.h>
  14. #include <openssl/core_dispatch.h>
  15. #include <openssl/core_names.h>
  16. #include <openssl/params.h>
  17. #include <openssl/err.h>
  18. #include <openssl/evp.h>
  19. #include <openssl/ec.h>
  20. #include "internal/passphrase.h"
  21. #include "internal/nelem.h"
  22. #include "prov/implementations.h"
  23. #include "prov/bio.h"
  24. #include "prov/provider_ctx.h"
  25. #include "endecoder_local.h"
  26. static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
  27. void *data, int len)
  28. {
  29. BIO *out = ossl_bio_new_from_core_bio(provctx, cout);
  30. int ret;
  31. if (out == NULL)
  32. return 0;
  33. ret = BIO_write(out, data, len);
  34. BIO_free(out);
  35. return ret;
  36. }
  37. static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
  38. static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
  39. static void *key2blob_newctx(void *provctx)
  40. {
  41. return provctx;
  42. }
  43. static void key2blob_freectx(void *vctx)
  44. {
  45. }
  46. static int key2blob_check_selection(int selection, int selection_mask)
  47. {
  48. /*
  49. * The selections are kinda sorta "levels", i.e. each selection given
  50. * here is assumed to include those following.
  51. */
  52. int checks[] = {
  53. OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
  54. OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
  55. OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
  56. };
  57. size_t i;
  58. /* The decoder implementations made here support guessing */
  59. if (selection == 0)
  60. return 1;
  61. for (i = 0; i < OSSL_NELEM(checks); i++) {
  62. int check1 = (selection & checks[i]) != 0;
  63. int check2 = (selection_mask & checks[i]) != 0;
  64. /*
  65. * If the caller asked for the currently checked bit(s), return
  66. * whether the decoder description says it's supported.
  67. */
  68. if (check1)
  69. return check2;
  70. }
  71. /* This should be dead code, but just to be safe... */
  72. return 0;
  73. }
  74. static int key2blob_encode(void *vctx, const void *key, int selection,
  75. OSSL_CORE_BIO *cout)
  76. {
  77. int pubkey_len = 0, ok = 0;
  78. unsigned char *pubkey = NULL;
  79. pubkey_len = i2o_ECPublicKey(key, &pubkey);
  80. if (pubkey_len > 0 && pubkey != NULL)
  81. ok = write_blob(vctx, cout, pubkey, pubkey_len);
  82. OPENSSL_free(pubkey);
  83. return ok;
  84. }
  85. /*
  86. * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
  87. * encoder
  88. *
  89. * impl: The keytype to encode
  90. * type: The C structure type holding the key data
  91. * selection_name: The acceptable selections. This translates into
  92. * the macro EVP_PKEY_##selection_name.
  93. *
  94. * The selection is understood as a "level" rather than an exact set of
  95. * requests from the caller. The encoder has to decide what contents fit
  96. * the encoded format. For example, the EC public key blob will only contain
  97. * the encoded public key itself, no matter if the selection bits include
  98. * OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes
  99. * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
  100. * cooperate, because it cannot output the private key.
  101. *
  102. * EVP_PKEY_##selection_name are convenience macros that combine "typical"
  103. * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
  104. */
  105. #define MAKE_BLOB_ENCODER(impl, type, selection_name) \
  106. static OSSL_FUNC_encoder_import_object_fn \
  107. impl##2blob_import_object; \
  108. static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \
  109. static OSSL_FUNC_encoder_does_selection_fn \
  110. impl##2blob_does_selection; \
  111. static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \
  112. \
  113. static void *impl##2blob_import_object(void *ctx, int selection, \
  114. const OSSL_PARAM params[]) \
  115. { \
  116. return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
  117. ctx, selection, params); \
  118. } \
  119. static void impl##2blob_free_object(void *key) \
  120. { \
  121. ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
  122. } \
  123. static int impl##2blob_does_selection(void *ctx, int selection) \
  124. { \
  125. return key2blob_check_selection(selection, \
  126. EVP_PKEY_##selection_name); \
  127. } \
  128. static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \
  129. const void *key, \
  130. const OSSL_PARAM key_abstract[], \
  131. int selection, \
  132. OSSL_PASSPHRASE_CALLBACK *cb, \
  133. void *cbarg) \
  134. { \
  135. /* We don't deal with abstract objects */ \
  136. if (key_abstract != NULL) { \
  137. ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
  138. return 0; \
  139. } \
  140. return key2blob_encode(vctx, key, selection, cout); \
  141. } \
  142. const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \
  143. { OSSL_FUNC_ENCODER_NEWCTX, \
  144. (void (*)(void))key2blob_newctx }, \
  145. { OSSL_FUNC_ENCODER_FREECTX, \
  146. (void (*)(void))key2blob_freectx }, \
  147. { OSSL_FUNC_ENCODER_DOES_SELECTION, \
  148. (void (*)(void))impl##2blob_does_selection }, \
  149. { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
  150. (void (*)(void))impl##2blob_import_object }, \
  151. { OSSL_FUNC_ENCODER_FREE_OBJECT, \
  152. (void (*)(void))impl##2blob_free_object }, \
  153. { OSSL_FUNC_ENCODER_ENCODE, \
  154. (void (*)(void))impl##2blob_encode }, \
  155. OSSL_DISPATCH_END \
  156. }
  157. #ifndef OPENSSL_NO_EC
  158. MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
  159. # ifndef OPENSSL_NO_SM2
  160. MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
  161. # endif
  162. #endif