Path: blob/main/crypto/openssl/demos/signature/EVP_DSA_Signature_demo.c
34914 views
/*-1* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* An example that uses the EVP_PKEY*, EVP_DigestSign* and EVP_DigestVerify*11* methods to calculate public/private DSA keypair and to sign and verify12* two static buffers.13*/1415#include <string.h>16#include <stdio.h>17#include <openssl/err.h>18#include <openssl/evp.h>19#include <openssl/decoder.h>20#include <openssl/dsa.h>2122/*23* This demonstration will calculate and verify a signature of data using24* the soliloquy from Hamlet scene 1 act 325*/2627static const char *hamlet_1 =28"To be, or not to be, that is the question,\n"29"Whether tis nobler in the minde to suffer\n"30"The slings and arrowes of outragious fortune,\n"31"Or to take Armes again in a sea of troubles,\n"32;33static const char *hamlet_2 =34"And by opposing, end them, to die to sleep;\n"35"No more, and by a sleep, to say we end\n"36"The heart-ache, and the thousand natural shocks\n"37"That flesh is heir to? tis a consumation\n"38;3940static const char ALG[] = "DSA";41static const char DIGEST[] = "SHA256";42static const int NUMBITS = 2048;43static const char * const PROPQUERY = NULL;4445static int generate_dsa_params(OSSL_LIB_CTX *libctx,46EVP_PKEY **p_params)47{48int ret = 0;4950EVP_PKEY_CTX *pkey_ctx = NULL;51EVP_PKEY *params = NULL;5253pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);54if (pkey_ctx == NULL)55goto end;5657if (EVP_PKEY_paramgen_init(pkey_ctx) <= 0)58goto end;5960if (EVP_PKEY_CTX_set_dsa_paramgen_bits(pkey_ctx, NUMBITS) <= 0)61goto end;62if (EVP_PKEY_paramgen(pkey_ctx, ¶ms) <= 0)63goto end;64if (params == NULL)65goto end;6667ret = 1;68end:69if(ret != 1) {70EVP_PKEY_free(params);71params = NULL;72}73EVP_PKEY_CTX_free(pkey_ctx);74*p_params = params;75fprintf(stdout, "Params:\n");76EVP_PKEY_print_params_fp(stdout, params, 4, NULL);77fprintf(stdout, "\n");7879return ret;80}8182static int generate_dsa_key(OSSL_LIB_CTX *libctx,83EVP_PKEY *params,84EVP_PKEY **p_pkey)85{86int ret = 0;8788EVP_PKEY_CTX *ctx = NULL;89EVP_PKEY *pkey = NULL;9091ctx = EVP_PKEY_CTX_new_from_pkey(libctx, params,92NULL);93if (ctx == NULL)94goto end;95if (EVP_PKEY_keygen_init(ctx) <= 0)96goto end;9798if (EVP_PKEY_keygen(ctx, &pkey) <= 0)99goto end;100if (pkey == NULL)101goto end;102103ret = 1;104end:105if(ret != 1) {106EVP_PKEY_free(pkey);107pkey = NULL;108}109EVP_PKEY_CTX_free(ctx);110*p_pkey = pkey;111fprintf(stdout, "Generating public/private key pair:\n");112EVP_PKEY_print_public_fp(stdout, pkey, 4, NULL);113fprintf(stdout, "\n");114EVP_PKEY_print_private_fp(stdout, pkey, 4, NULL);115fprintf(stdout, "\n");116EVP_PKEY_print_params_fp(stdout, pkey, 4, NULL);117fprintf(stdout, "\n");118119return ret;120}121122static int extract_public_key(const EVP_PKEY *pkey,123OSSL_PARAM **p_public_key)124{125int ret = 0;126OSSL_PARAM *public_key = NULL;127128if (EVP_PKEY_todata(pkey, EVP_PKEY_PUBLIC_KEY, &public_key) != 1)129goto end;130131ret = 1;132end:133if (ret != 1) {134OSSL_PARAM_free(public_key);135public_key = NULL;136}137*p_public_key = public_key;138139return ret;140}141142static int extract_keypair(const EVP_PKEY *pkey,143OSSL_PARAM **p_keypair)144{145int ret = 0;146OSSL_PARAM *keypair = NULL;147148if (EVP_PKEY_todata(pkey, EVP_PKEY_KEYPAIR, &keypair) != 1)149goto end;150151ret = 1;152end:153if (ret != 1) {154OSSL_PARAM_free(keypair);155keypair = NULL;156}157*p_keypair = keypair;158159return ret;160}161162static int demo_sign(OSSL_LIB_CTX *libctx,163size_t *p_sig_len, unsigned char **p_sig_value,164OSSL_PARAM keypair[])165{166int ret = 0;167size_t sig_len = 0;168unsigned char *sig_value = NULL;169EVP_MD_CTX *ctx = NULL;170EVP_PKEY_CTX *pkey_ctx = NULL;171EVP_PKEY *pkey = NULL;172173pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);174if (pkey_ctx == NULL)175goto end;176if (EVP_PKEY_fromdata_init(pkey_ctx) != 1)177goto end;178if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_KEYPAIR, keypair) != 1)179goto end;180181ctx = EVP_MD_CTX_create();182if (ctx == NULL)183goto end;184185if (EVP_DigestSignInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1)186goto end;187188if (EVP_DigestSignUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1)189goto end;190191if (EVP_DigestSignUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1)192goto end;193194/* Calculate the signature size */195if (EVP_DigestSignFinal(ctx, NULL, &sig_len) != 1)196goto end;197if (sig_len == 0)198goto end;199200sig_value = OPENSSL_malloc(sig_len);201if (sig_value == NULL)202goto end;203204/* Calculate the signature */205if (EVP_DigestSignFinal(ctx, sig_value, &sig_len) != 1)206goto end;207208ret = 1;209end:210EVP_MD_CTX_free(ctx);211if (ret != 1) {212OPENSSL_free(sig_value);213sig_len = 0;214sig_value = NULL;215}216*p_sig_len = sig_len;217*p_sig_value = sig_value;218EVP_PKEY_free(pkey);219EVP_PKEY_CTX_free(pkey_ctx);220221fprintf(stdout, "Generating signature:\n");222BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);223fprintf(stdout, "\n");224return ret;225}226227static int demo_verify(OSSL_LIB_CTX *libctx,228size_t sig_len, unsigned char *sig_value,229OSSL_PARAM public_key[])230{231int ret = 0;232EVP_MD_CTX *ctx = NULL;233EVP_PKEY_CTX *pkey_ctx = NULL;234EVP_PKEY *pkey = NULL;235236pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);237if (pkey_ctx == NULL)238goto end;239if (EVP_PKEY_fromdata_init(pkey_ctx) != 1)240goto end;241if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_PUBLIC_KEY, public_key) != 1)242goto end;243244ctx = EVP_MD_CTX_create();245if(ctx == NULL)246goto end;247248if (EVP_DigestVerifyInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1)249goto end;250251if (EVP_DigestVerifyUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1)252goto end;253254if (EVP_DigestVerifyUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1)255goto end;256257if (EVP_DigestVerifyFinal(ctx, sig_value, sig_len) != 1)258goto end;259260ret = 1;261end:262EVP_PKEY_free(pkey);263EVP_PKEY_CTX_free(pkey_ctx);264EVP_MD_CTX_free(ctx);265return ret;266}267268int main(void)269{270int ret = EXIT_FAILURE;271OSSL_LIB_CTX *libctx = NULL;272EVP_PKEY *params = NULL;273EVP_PKEY *pkey = NULL;274OSSL_PARAM *public_key = NULL;275OSSL_PARAM *keypair = NULL;276size_t sig_len = 0;277unsigned char *sig_value = NULL;278279libctx = OSSL_LIB_CTX_new();280if (libctx == NULL)281goto end;282283if (generate_dsa_params(libctx, ¶ms) != 1)284goto end;285286if (generate_dsa_key(libctx, params, &pkey) != 1)287goto end;288289if (extract_public_key(pkey, &public_key) != 1)290goto end;291292if (extract_keypair(pkey, &keypair) != 1)293goto end;294295/* The signer signs with his private key, and distributes his public key */296if (demo_sign(libctx, &sig_len, &sig_value, keypair) != 1)297goto end;298299/* A verifier uses the signers public key to verify the signature */300if (demo_verify(libctx, sig_len, sig_value, public_key) != 1)301goto end;302303ret = EXIT_SUCCESS;304end:305if (ret != EXIT_SUCCESS)306ERR_print_errors_fp(stderr);307308OPENSSL_free(sig_value);309EVP_PKEY_free(params);310EVP_PKEY_free(pkey);311OSSL_PARAM_free(public_key);312OSSL_PARAM_free(keypair);313OSSL_LIB_CTX_free(libctx);314315return ret;316}317318319