pem_local.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright 2019-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 <openssl/core_dispatch.h>
  10. #include <openssl/pem.h>
  11. #include <openssl/encoder.h>
  12. /*
  13. * Selectors, named according to the ASN.1 names used throughout libcrypto.
  14. *
  15. * Note that these are not absolutely mandatory, they are rather a wishlist
  16. * of sorts. The provider implementations are free to make choices that
  17. * make sense for them, based on these selectors.
  18. * For example, the EC backend is likely to really just output the private
  19. * key to a PKCS#8 structure, even thought PEM_SELECTION_PrivateKey specifies
  20. * the public key as well. This is fine, as long as the corresponding
  21. * decoding operation can return an object that contains what libcrypto
  22. * expects.
  23. */
  24. # define PEM_SELECTION_PUBKEY EVP_PKEY_PUBLIC_KEY
  25. # define PEM_SELECTION_PrivateKey EVP_PKEY_KEYPAIR
  26. # define PEM_SELECTION_Parameters EVP_PKEY_KEY_PARAMETERS
  27. /*
  28. * Properties, named according to the ASN.1 names used throughout libcrypto.
  29. */
  30. # define PEM_STRUCTURE_PUBKEY "SubjectPublicKeyInfo"
  31. # define PEM_STRUCTURE_PrivateKey "PrivateKeyInfo"
  32. # define PEM_STRUCTURE_Parameters "type-specific"
  33. # define PEM_STRUCTURE_RSAPrivateKey "type-specific"
  34. # define PEM_STRUCTURE_RSAPublicKey "type-specific"
  35. /* Alternative IMPLEMENT macros for provided encoders */
  36. # define IMPLEMENT_PEM_provided_write_body_vars(type, asn1, pq) \
  37. int ret = 0; \
  38. OSSL_ENCODER_CTX *ctx = \
  39. OSSL_ENCODER_CTX_new_for_##type(x, PEM_SELECTION_##asn1, \
  40. "PEM", PEM_STRUCTURE_##asn1, \
  41. (pq)); \
  42. \
  43. if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) { \
  44. OSSL_ENCODER_CTX_free(ctx); \
  45. goto legacy; \
  46. }
  47. # define IMPLEMENT_PEM_provided_write_body_pass() \
  48. ret = 1; \
  49. if (kstr == NULL && cb == NULL) { \
  50. if (u != NULL) { \
  51. kstr = u; \
  52. klen = strlen(u); \
  53. } else { \
  54. cb = PEM_def_callback; \
  55. } \
  56. } \
  57. if (enc != NULL) { \
  58. ret = 0; \
  59. if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc), \
  60. NULL)) { \
  61. ret = 1; \
  62. if (kstr != NULL \
  63. && !OSSL_ENCODER_CTX_set_passphrase(ctx, kstr, klen)) \
  64. ret = 0; \
  65. else if (cb != NULL \
  66. && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, \
  67. cb, u)) \
  68. ret = 0; \
  69. } \
  70. } \
  71. if (!ret) { \
  72. OSSL_ENCODER_CTX_free(ctx); \
  73. return 0; \
  74. }
  75. # define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \
  76. ret = OSSL_ENCODER_to_##outtype(ctx, out); \
  77. OSSL_ENCODER_CTX_free(ctx); \
  78. return ret
  79. # define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
  80. writename) \
  81. legacy: \
  82. return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \
  83. x, NULL, NULL, 0, NULL, NULL)
  84. # define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
  85. writename) \
  86. legacy: \
  87. return PEM_ASN1_##writename##((i2d_of_void *)i2d_##asn1, str, out, \
  88. x, enc, kstr, klen, cb, u)
  89. # define IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, \
  90. OUTTYPE, outtype, writename) \
  91. PEM_write_fnsig(name, TYPE, OUTTYPE, writename) \
  92. { \
  93. IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
  94. IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
  95. IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
  96. writename); \
  97. } \
  98. PEM_write_ex_fnsig(name, TYPE, OUTTYPE, writename) \
  99. { \
  100. IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
  101. IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
  102. IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
  103. writename); \
  104. }
  105. # define IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, \
  106. OUTTYPE, outtype, writename) \
  107. PEM_write_cb_fnsig(name, TYPE, OUTTYPE, writename) \
  108. { \
  109. IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
  110. IMPLEMENT_PEM_provided_write_body_pass(); \
  111. IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
  112. IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
  113. writename); \
  114. } \
  115. PEM_write_ex_cb_fnsig(name, TYPE, OUTTYPE, writename) \
  116. { \
  117. IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
  118. IMPLEMENT_PEM_provided_write_body_pass(); \
  119. IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
  120. IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
  121. writename); \
  122. }
  123. # ifdef OPENSSL_NO_STDIO
  124. # define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
  125. # define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
  126. # else
  127. # define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) \
  128. IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, FILE, fp, write)
  129. # define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) \
  130. IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, FILE, fp, write)
  131. # endif
  132. # define IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
  133. IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
  134. # define IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
  135. IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
  136. # define IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1) \
  137. IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
  138. IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
  139. # define IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1) \
  140. IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
  141. IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
  142. # define IMPLEMENT_PEM_provided_rw(name, TYPE, type, str, asn1) \
  143. IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
  144. IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1)
  145. # define IMPLEMENT_PEM_provided_rw_cb(name, TYPE, type, str, asn1) \
  146. IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
  147. IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1)