EVP_EC_Signature_demo.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*-
  2. * Copyright 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. /*
  10. * An example that uses the EVP_MD*, EVP_DigestSign* and EVP_DigestVerify*
  11. * methods to calculate and verify a signature of two static buffers.
  12. */
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <openssl/err.h>
  16. #include <openssl/evp.h>
  17. #include <openssl/decoder.h>
  18. #include "EVP_EC_Signature_demo.h"
  19. /*
  20. * This demonstration will calculate and verify a signature of data using
  21. * the soliloquy from Hamlet scene 1 act 3
  22. */
  23. static const char *hamlet_1 =
  24. "To be, or not to be, that is the question,\n"
  25. "Whether tis nobler in the minde to suffer\n"
  26. "The slings and arrowes of outragious fortune,\n"
  27. "Or to take Armes again in a sea of troubles,\n"
  28. ;
  29. static const char *hamlet_2 =
  30. "And by opposing, end them, to die to sleep;\n"
  31. "No more, and by a sleep, to say we end\n"
  32. "The heart-ache, and the thousand natural shocks\n"
  33. "That flesh is heir to? tis a consumation\n"
  34. ;
  35. /*
  36. * For demo_sign, load EC private key priv_key from priv_key_der[].
  37. * For demo_verify, load EC public key pub_key from pub_key_der[].
  38. */
  39. static EVP_PKEY *get_key(OSSL_LIB_CTX *libctx, const char *propq, int public)
  40. {
  41. OSSL_DECODER_CTX *dctx = NULL;
  42. EVP_PKEY *pkey = NULL;
  43. int selection;
  44. const unsigned char *data;
  45. size_t data_len;
  46. if (public) {
  47. selection = EVP_PKEY_PUBLIC_KEY;
  48. data = pub_key_der;
  49. data_len = sizeof(pub_key_der);
  50. } else {
  51. selection = EVP_PKEY_KEYPAIR;
  52. data = priv_key_der;
  53. data_len = sizeof(priv_key_der);
  54. }
  55. dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC",
  56. selection, libctx, propq);
  57. (void)OSSL_DECODER_from_data(dctx, &data, &data_len);
  58. OSSL_DECODER_CTX_free(dctx);
  59. if (pkey == NULL)
  60. fprintf(stderr, "Failed to load %s key.\n", public ? "public" : "private");
  61. return pkey;
  62. }
  63. static int demo_sign(OSSL_LIB_CTX *libctx, const char *sig_name,
  64. size_t *sig_out_len, unsigned char **sig_out_value)
  65. {
  66. int ret = 0, public = 0;
  67. size_t sig_len;
  68. unsigned char *sig_value = NULL;
  69. const char *propq = NULL;
  70. EVP_MD_CTX *sign_context = NULL;
  71. EVP_PKEY *priv_key = NULL;
  72. /* Get private key */
  73. priv_key = get_key(libctx, propq, public);
  74. if (priv_key == NULL) {
  75. fprintf(stderr, "Get private key failed.\n");
  76. goto cleanup;
  77. }
  78. /*
  79. * Make a message signature context to hold temporary state
  80. * during signature creation
  81. */
  82. sign_context = EVP_MD_CTX_new();
  83. if (sign_context == NULL) {
  84. fprintf(stderr, "EVP_MD_CTX_new failed.\n");
  85. goto cleanup;
  86. }
  87. /*
  88. * Initialize the sign context to use the fetched
  89. * sign provider.
  90. */
  91. if (!EVP_DigestSignInit_ex(sign_context, NULL, sig_name,
  92. libctx, NULL, priv_key, NULL)) {
  93. fprintf(stderr, "EVP_DigestSignInit_ex failed.\n");
  94. goto cleanup;
  95. }
  96. /*
  97. * EVP_DigestSignUpdate() can be called several times on the same context
  98. * to include additional data.
  99. */
  100. if (!EVP_DigestSignUpdate(sign_context, hamlet_1, strlen(hamlet_1))) {
  101. fprintf(stderr, "EVP_DigestSignUpdate(hamlet_1) failed.\n");
  102. goto cleanup;
  103. }
  104. if (!EVP_DigestSignUpdate(sign_context, hamlet_2, strlen(hamlet_2))) {
  105. fprintf(stderr, "EVP_DigestSignUpdate(hamlet_2) failed.\n");
  106. goto cleanup;
  107. }
  108. /* Call EVP_DigestSignFinal to get signature length sig_len */
  109. if (!EVP_DigestSignFinal(sign_context, NULL, &sig_len)) {
  110. fprintf(stderr, "EVP_DigestSignFinal failed.\n");
  111. goto cleanup;
  112. }
  113. if (sig_len <= 0) {
  114. fprintf(stderr, "EVP_DigestSignFinal returned invalid signature length.\n");
  115. goto cleanup;
  116. }
  117. sig_value = OPENSSL_malloc(sig_len);
  118. if (sig_value == NULL) {
  119. fprintf(stderr, "No memory.\n");
  120. goto cleanup;
  121. }
  122. if (!EVP_DigestSignFinal(sign_context, sig_value, &sig_len)) {
  123. fprintf(stderr, "EVP_DigestSignFinal failed.\n");
  124. goto cleanup;
  125. }
  126. *sig_out_len = sig_len;
  127. *sig_out_value = sig_value;
  128. fprintf(stdout, "Generating signature:\n");
  129. BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);
  130. fprintf(stdout, "\n");
  131. ret = 1;
  132. cleanup:
  133. /* OpenSSL free functions will ignore NULL arguments */
  134. if (!ret)
  135. OPENSSL_free(sig_value);
  136. EVP_PKEY_free(priv_key);
  137. EVP_MD_CTX_free(sign_context);
  138. return ret;
  139. }
  140. static int demo_verify(OSSL_LIB_CTX *libctx, const char *sig_name,
  141. size_t sig_len, unsigned char *sig_value)
  142. {
  143. int ret = 0, public = 1;
  144. const char *propq = NULL;
  145. EVP_MD_CTX *verify_context = NULL;
  146. EVP_PKEY *pub_key = NULL;
  147. /*
  148. * Make a verify signature context to hold temporary state
  149. * during signature verification
  150. */
  151. verify_context = EVP_MD_CTX_new();
  152. if (verify_context == NULL) {
  153. fprintf(stderr, "EVP_MD_CTX_new failed.\n");
  154. goto cleanup;
  155. }
  156. /* Get public key */
  157. pub_key = get_key(libctx, propq, public);
  158. if (pub_key == NULL) {
  159. fprintf(stderr, "Get public key failed.\n");
  160. goto cleanup;
  161. }
  162. /* Verify */
  163. if (!EVP_DigestVerifyInit_ex(verify_context, NULL, sig_name,
  164. libctx, NULL, pub_key, NULL)) {
  165. fprintf(stderr, "EVP_DigestVerifyInit failed.\n");
  166. goto cleanup;
  167. }
  168. /*
  169. * EVP_DigestVerifyUpdate() can be called several times on the same context
  170. * to include additional data.
  171. */
  172. if (!EVP_DigestVerifyUpdate(verify_context, hamlet_1, strlen(hamlet_1))) {
  173. fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_1) failed.\n");
  174. goto cleanup;
  175. }
  176. if (!EVP_DigestVerifyUpdate(verify_context, hamlet_2, strlen(hamlet_2))) {
  177. fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_2) failed.\n");
  178. goto cleanup;
  179. }
  180. if (EVP_DigestVerifyFinal(verify_context, sig_value, sig_len) <= 0) {
  181. fprintf(stderr, "EVP_DigestVerifyFinal failed.\n");
  182. goto cleanup;
  183. }
  184. fprintf(stdout, "Signature verified.\n");
  185. ret = 1;
  186. cleanup:
  187. /* OpenSSL free functions will ignore NULL arguments */
  188. EVP_PKEY_free(pub_key);
  189. EVP_MD_CTX_free(verify_context);
  190. return ret;
  191. }
  192. int main(void)
  193. {
  194. OSSL_LIB_CTX *libctx = NULL;
  195. const char *sig_name = "SHA3-512";
  196. size_t sig_len = 0;
  197. unsigned char *sig_value = NULL;
  198. int ret = EXIT_FAILURE;
  199. libctx = OSSL_LIB_CTX_new();
  200. if (libctx == NULL) {
  201. fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
  202. goto cleanup;
  203. }
  204. if (!demo_sign(libctx, sig_name, &sig_len, &sig_value)) {
  205. fprintf(stderr, "demo_sign failed.\n");
  206. goto cleanup;
  207. }
  208. if (!demo_verify(libctx, sig_name, sig_len, sig_value)) {
  209. fprintf(stderr, "demo_verify failed.\n");
  210. goto cleanup;
  211. }
  212. ret = EXIT_SUCCESS;
  213. cleanup:
  214. if (ret != EXIT_SUCCESS)
  215. ERR_print_errors_fp(stderr);
  216. /* OpenSSL free functions will ignore NULL arguments */
  217. OSSL_LIB_CTX_free(libctx);
  218. OPENSSL_free(sig_value);
  219. return ret;
  220. }