EVP_PKEY_DSA_paramvalidate.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*-
  2. * Copyright 2022-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. * Example showing how to validate DSA parameters.
  11. *
  12. * Proper FIPS 186-4 DSA (FFC) parameter validation requires that all
  13. * the parameters used during parameter generation are supplied
  14. * when doing the validation. Unfortunately saving DSA parameters as
  15. * a PEM or DER file does not write out all required fields. Because
  16. * of this the default provider normally only does a partial
  17. * validation. The FIPS provider will however try to do a full
  18. * validation. To force the default provider to use full
  19. * validation the 'seed' that is output during generation must be
  20. * added to the key. See doc/man7/EVP_PKEY-FFC for more information.
  21. */
  22. #include <openssl/evp.h>
  23. #include <openssl/core_names.h>
  24. #include <openssl/pem.h>
  25. #include "dsa.inc"
  26. /* The following values were output from the EVP_PKEY_DSA_paramgen demo */
  27. static const char dsapem[] =
  28. "-----BEGIN DSA PARAMETERS-----\n"
  29. "MIICLAKCAQEA1pobSR1FJ3+Tvi0J6Tk1PSV2owZey1Nuo847hGw/59VCS6RPQEqr\n"
  30. "vp5fhbvBjupBeVGA/AMH6rI4i4h6jlhurrqH1CqUHVcDhJzxV668bMLiP3mIxg5o\n"
  31. "9Yq8x6BnSOtH5Je0tpeE0/fEvvLjCwBUbwnwWxzjANcvDUEt9XYeRrtB2v52fr56\n"
  32. "hVYz3wMMNog4CEDOLTvx7/84eVPuUeWDRQFH1EaHMdulP34KBcatEEpEZapkepng\n"
  33. "nohm9sFSPQhq2utpkH7pNXdG0EILBtRDCvUpF5720a48LYofdggh2VEZfgElAGFk\n"
  34. "dW/CkvyBDmGIzil5aTz4MMsdudaVYgzt6wIhAPsSGC42Qa+X0AFGvonb5nmfUVm/\n"
  35. "8aC+tHk7Nb2AYLHXAoIBADx5C0H1+QHsmGKvuOaY+WKUt7aWUrEivD1zBMJAQ6bL\n"
  36. "Wv9lbCq1CFHvVzojeOVpn872NqDEpkx4HTpvqhxWL5CkbN/HaGItsQzkD59AQg3v\n"
  37. "4YsLlkesq9Jq6x/aWetJXWO36fszFv1gpD3NY3wliBvMYHx62jfc5suh9D3ZZvu7\n"
  38. "PLGH4X4kcfzK/R2b0oVbEBjVTe5GMRYZRqnvfSW2f2fA7BzI1OL83UxDDe58cL2M\n"
  39. "GcAoUYXOBAfZ37qLMm2juf+o5gCrT4CXfRPu6kbapt7V/YIc1nsNgeAOKKoFBHBQ\n"
  40. "gc5u5G6G/j79FVoSDq9DYwTJcHPsU+eHj1uWHso1AjQ=\n"
  41. "-----END DSA PARAMETERS-----\n";
  42. static const char hexseed[] =
  43. "cba30ccd905aa7675a0b81769704bf3c"
  44. "ccf2ca1892b2eaf6b9e2b38d9bf6affc"
  45. "42ada55986d8a1772b442770954d0b65";
  46. const int gindex = 42;
  47. const int pcounter = 363;
  48. static const char digest[] = "SHA384";
  49. /*
  50. * Create a new dsa param key that is the combination of an existing param key
  51. * plus extra parameters.
  52. */
  53. EVP_PKEY_CTX *create_merged_key(EVP_PKEY *dsaparams, const OSSL_PARAM *newparams,
  54. OSSL_LIB_CTX *libctx, const char *propq)
  55. {
  56. EVP_PKEY_CTX *out = NULL;
  57. EVP_PKEY_CTX *ctx = NULL;
  58. EVP_PKEY *pkey = NULL;
  59. OSSL_PARAM *mergedparams = NULL;
  60. OSSL_PARAM *loadedparams = NULL;
  61. /* Specify EVP_PKEY_KEY_PUBLIC here if you have a public key */
  62. if (EVP_PKEY_todata(dsaparams, EVP_PKEY_KEY_PARAMETERS, &loadedparams) <= 0) {
  63. fprintf(stderr, "EVP_PKEY_todata() failed\n");
  64. goto cleanup;
  65. }
  66. mergedparams = OSSL_PARAM_merge(loadedparams, newparams);
  67. if (mergedparams == NULL) {
  68. fprintf(stderr, "OSSL_PARAM_merge() failed\n");
  69. goto cleanup;
  70. }
  71. ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", propq);
  72. if (ctx == NULL) {
  73. fprintf(stderr, "EVP_PKEY_CTX_new_from_name() failed\n");
  74. goto cleanup;
  75. }
  76. if (EVP_PKEY_fromdata_init(ctx) <= 0
  77. || EVP_PKEY_fromdata(ctx, &pkey,
  78. EVP_PKEY_KEY_PARAMETERS, mergedparams) <= 0) {
  79. fprintf(stderr, "EVP_PKEY_fromdata() failed\n");
  80. goto cleanup;
  81. }
  82. out = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
  83. if (out == NULL) {
  84. fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey() failed\n");
  85. goto cleanup;
  86. }
  87. cleanup:
  88. EVP_PKEY_free(pkey);
  89. OSSL_PARAM_free(loadedparams);
  90. OSSL_PARAM_free(mergedparams);
  91. EVP_PKEY_CTX_free(ctx);
  92. return out;
  93. }
  94. int main(int argc, char **argv)
  95. {
  96. int ret = EXIT_FAILURE;
  97. OSSL_LIB_CTX *libctx = NULL;
  98. const char *propq = NULL;
  99. EVP_PKEY *dsaparamskey = NULL;
  100. EVP_PKEY_CTX *ctx = NULL;
  101. EVP_PKEY_CTX *ctx1 = NULL;
  102. EVP_PKEY_CTX *ctx2 = NULL;
  103. BIO *in = NULL;
  104. OSSL_PARAM params[6];
  105. unsigned char seed[64];
  106. size_t seedlen;
  107. if (!OPENSSL_hexstr2buf_ex(seed, sizeof(seed), &seedlen, hexseed, '\0'))
  108. goto cleanup;
  109. /*
  110. * This example loads the PEM data from a memory buffer
  111. * Use BIO_new_fp() to load a PEM file instead
  112. */
  113. in = BIO_new_mem_buf(dsapem, strlen(dsapem));
  114. if (in == NULL) {
  115. fprintf(stderr, "BIO_new_mem_buf() failed\n");
  116. goto cleanup;
  117. }
  118. /* Load DSA params from pem data */
  119. dsaparamskey = PEM_read_bio_Parameters_ex(in, NULL, libctx, propq);
  120. if (dsaparamskey == NULL) {
  121. fprintf(stderr, "Failed to load dsa params\n");
  122. goto cleanup;
  123. }
  124. ctx = EVP_PKEY_CTX_new_from_pkey(libctx, dsaparamskey, propq);
  125. if (ctx == NULL) {
  126. fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey() failed\n");
  127. goto cleanup;
  128. }
  129. /*
  130. * When using the default provider this only does a partial check to
  131. * make sure that the values of p, q and g are ok.
  132. * This will fail however if the FIPS provider is used since it does
  133. * a proper FIPS 186-4 key validation which requires extra parameters
  134. */
  135. if (EVP_PKEY_param_check(ctx) <= 0) {
  136. fprintf(stderr, "Simple EVP_PKEY_param_check() failed \n");
  137. goto cleanup;
  138. }
  139. /*
  140. * Setup parameters that we want to add.
  141. * For illustration purposes it deliberately omits a required parameter.
  142. */
  143. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE,
  144. "fips186_4", 0);
  145. /* Force it to do a proper validation by setting the seed */
  146. params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
  147. (void *)seed, seedlen);
  148. params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, (int *)&gindex);
  149. params[3] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, (int *)&pcounter);
  150. params[4] = OSSL_PARAM_construct_end();
  151. /* generate a new key that is the combination of the existing key and the new params */
  152. ctx1 = create_merged_key(dsaparamskey, params, libctx, propq);
  153. if (ctx1 == NULL)
  154. goto cleanup;
  155. /* This will fail since not all the parameters used for key generation are added */
  156. if (EVP_PKEY_param_check(ctx1) > 0) {
  157. fprintf(stderr, "EVP_PKEY_param_check() should fail\n");
  158. goto cleanup;
  159. }
  160. /*
  161. * Add the missing parameters onto the end of the existing list of params
  162. * If the default was used for the generation then this parameter is not
  163. * needed
  164. */
  165. params[4] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST,
  166. (char *)digest, 0);
  167. params[5] = OSSL_PARAM_construct_end();
  168. ctx2 = create_merged_key(dsaparamskey, params, libctx, propq);
  169. if (ctx2 == NULL)
  170. goto cleanup;
  171. if (EVP_PKEY_param_check(ctx2) <= 0) {
  172. fprintf(stderr, "EVP_PKEY_param_check() failed\n");
  173. goto cleanup;
  174. }
  175. if (!dsa_print_key(EVP_PKEY_CTX_get0_pkey(ctx2), 0, libctx, propq))
  176. goto cleanup;
  177. ret = EXIT_SUCCESS;
  178. cleanup:
  179. EVP_PKEY_free(dsaparamskey);
  180. EVP_PKEY_CTX_free(ctx2);
  181. EVP_PKEY_CTX_free(ctx1);
  182. EVP_PKEY_CTX_free(ctx);
  183. BIO_free(in);
  184. return ret;
  185. }