EVP_ED_Signature_demo.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*-
  2. * Copyright 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. * This demonstration will calculate and verify an ED25519 signature of
  11. * a message using EVP_DigestSign() and EVP_DigestVerify().
  12. */
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <openssl/err.h>
  16. #include <openssl/evp.h>
  17. #include <openssl/core_names.h>
  18. /* A test message to be signed (TBS) */
  19. static const unsigned char hamlet[] =
  20. "To be, or not to be, that is the question,\n"
  21. "Whether tis nobler in the minde to suffer\n"
  22. "The slings and arrowes of outragious fortune,\n"
  23. "Or to take Armes again in a sea of troubles,\n";
  24. static int demo_sign(EVP_PKEY *priv,
  25. const unsigned char *tbs, size_t tbs_len,
  26. OSSL_LIB_CTX *libctx,
  27. unsigned char **sig_out_value,
  28. size_t *sig_out_len)
  29. {
  30. int ret = 0;
  31. size_t sig_len;
  32. unsigned char *sig_value = NULL;
  33. EVP_MD_CTX *sign_context = NULL;
  34. /* Create a signature context */
  35. sign_context = EVP_MD_CTX_new();
  36. if (sign_context == NULL) {
  37. fprintf(stderr, "EVP_MD_CTX_new failed.\n");
  38. goto cleanup;
  39. }
  40. /*
  41. * Initialize the sign context using an ED25519 private key
  42. * Notice that the digest name must NOT be used.
  43. * In this demo we don't specify any additional parameters via
  44. * OSSL_PARAM, which means it will use default values.
  45. * For more information, refer to doc/man7/EVP_SIGNATURE-ED25519.pod
  46. * "ED25519 and ED448 Signature Parameters"
  47. */
  48. if (!EVP_DigestSignInit_ex(sign_context, NULL, NULL, libctx, NULL, priv, NULL)) {
  49. fprintf(stderr, "EVP_DigestSignInit_ex failed.\n");
  50. goto cleanup;
  51. }
  52. /* Calculate the required size for the signature by passing a NULL buffer. */
  53. if (!EVP_DigestSign(sign_context, NULL, &sig_len, tbs, tbs_len)) {
  54. fprintf(stderr, "EVP_DigestSign using NULL buffer failed.\n");
  55. goto cleanup;
  56. }
  57. sig_value = OPENSSL_malloc(sig_len);
  58. if (sig_value == NULL) {
  59. fprintf(stderr, "OPENSSL_malloc failed.\n");
  60. goto cleanup;
  61. }
  62. fprintf(stdout, "Generating signature:\n");
  63. if (!EVP_DigestSign(sign_context, sig_value, &sig_len, tbs, tbs_len)) {
  64. fprintf(stderr, "EVP_DigestSign failed.\n");
  65. goto cleanup;
  66. }
  67. *sig_out_len = sig_len;
  68. *sig_out_value = sig_value;
  69. BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);
  70. fprintf(stdout, "\n");
  71. ret = 1;
  72. cleanup:
  73. if (!ret)
  74. OPENSSL_free(sig_value);
  75. EVP_MD_CTX_free(sign_context);
  76. return ret;
  77. }
  78. static int demo_verify(EVP_PKEY *pub,
  79. const unsigned char *tbs, size_t tbs_len,
  80. const unsigned char *sig_value, size_t sig_len,
  81. OSSL_LIB_CTX *libctx)
  82. {
  83. int ret = 0;
  84. EVP_MD_CTX *verify_context = NULL;
  85. /*
  86. * Make a verify signature context to hold temporary state
  87. * during signature verification
  88. */
  89. verify_context = EVP_MD_CTX_new();
  90. if (verify_context == NULL) {
  91. fprintf(stderr, "EVP_MD_CTX_new failed.\n");
  92. goto cleanup;
  93. }
  94. /* Initialize the verify context with a ED25519 public key */
  95. if (!EVP_DigestVerifyInit_ex(verify_context, NULL, NULL,
  96. libctx, NULL, pub, NULL)) {
  97. fprintf(stderr, "EVP_DigestVerifyInit_ex failed.\n");
  98. goto cleanup;
  99. }
  100. /*
  101. * ED25519 only supports the one shot interface using EVP_DigestVerify()
  102. * The streaming EVP_DigestVerifyUpdate() API is not supported.
  103. */
  104. if (!EVP_DigestVerify(verify_context, sig_value, sig_len,
  105. tbs, tbs_len)) {
  106. fprintf(stderr, "EVP_DigestVerify() failed.\n");
  107. goto cleanup;
  108. }
  109. fprintf(stdout, "Signature verified.\n");
  110. ret = 1;
  111. cleanup:
  112. EVP_MD_CTX_free(verify_context);
  113. return ret;
  114. }
  115. static int create_key(OSSL_LIB_CTX *libctx,
  116. EVP_PKEY **privout, EVP_PKEY **pubout)
  117. {
  118. int ret = 0;
  119. EVP_PKEY *priv = NULL, *pub = NULL;
  120. unsigned char pubdata[32];
  121. size_t pubdata_len = 0;
  122. /*
  123. * In this demo we just create a keypair, and extract the
  124. * public key. We could also use EVP_PKEY_new_raw_private_key_ex()
  125. * to create a key from raw data.
  126. */
  127. priv = EVP_PKEY_Q_keygen(libctx, NULL, "ED25519");
  128. if (priv == NULL) {
  129. fprintf(stderr, "EVP_PKEY_Q_keygen() failed\n");
  130. goto end;
  131. }
  132. if (!EVP_PKEY_get_octet_string_param(priv,
  133. OSSL_PKEY_PARAM_PUB_KEY,
  134. pubdata,
  135. sizeof(pubdata),
  136. &pubdata_len)) {
  137. fprintf(stderr, "EVP_PKEY_get_octet_string_param() failed\n");
  138. goto end;
  139. }
  140. pub = EVP_PKEY_new_raw_public_key_ex(libctx, "ED25519", NULL, pubdata, pubdata_len);
  141. if (pub == NULL) {
  142. fprintf(stderr, "EVP_PKEY_new_raw_public_key_ex() failed\n");
  143. goto end;
  144. }
  145. ret = 1;
  146. end:
  147. if (ret) {
  148. *pubout = pub;
  149. *privout = priv;
  150. } else {
  151. EVP_PKEY_free(priv);
  152. }
  153. return ret;
  154. }
  155. int main(void)
  156. {
  157. OSSL_LIB_CTX *libctx = NULL;
  158. size_t sig_len = 0;
  159. unsigned char *sig_value = NULL;
  160. int ret = EXIT_FAILURE;
  161. EVP_PKEY *priv = NULL, *pub = NULL;
  162. libctx = OSSL_LIB_CTX_new();
  163. if (libctx == NULL) {
  164. fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
  165. goto cleanup;
  166. }
  167. if (!create_key(libctx, &priv, &pub)) {
  168. fprintf(stderr, "Failed to create key.\n");
  169. goto cleanup;
  170. }
  171. if (!demo_sign(priv, hamlet, sizeof(hamlet), libctx,
  172. &sig_value, &sig_len)) {
  173. fprintf(stderr, "demo_sign failed.\n");
  174. goto cleanup;
  175. }
  176. if (!demo_verify(pub, hamlet, sizeof(hamlet),
  177. sig_value, sig_len, libctx)) {
  178. fprintf(stderr, "demo_verify failed.\n");
  179. goto cleanup;
  180. }
  181. ret = EXIT_SUCCESS;
  182. cleanup:
  183. if (ret != EXIT_SUCCESS)
  184. ERR_print_errors_fp(stderr);
  185. EVP_PKEY_free(pub);
  186. EVP_PKEY_free(priv);
  187. OSSL_LIB_CTX_free(libctx);
  188. OPENSSL_free(sig_value);
  189. return ret;
  190. }