diff options
author | Daniel Fiala <daniel@openssl.org> | 2022-10-21 06:28:12 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2022-11-22 17:23:11 +0100 |
commit | 858b5d12b85b0639519d21206c9da7e1bb976a00 (patch) | |
tree | 85fb6e4763bda0c929f01d521142a7ee0d14f21a /demos | |
parent | 122ea851de77f761d7bc0ec5f3a7fc23e3a5d8be (diff) | |
download | openssl-858b5d12b85b0639519d21206c9da7e1bb976a00.tar.gz |
Add an EVP signature demo using DSA
Fixes openssl#14114
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19492)
Diffstat (limited to 'demos')
-rw-r--r-- | demos/signature/EVP_DSA_Signature_demo.c | 317 | ||||
-rw-r--r-- | demos/signature/EVP_EC_Signature_demo.c (renamed from demos/signature/EVP_Signature_demo.c) | 2 | ||||
-rw-r--r-- | demos/signature/EVP_EC_Signature_demo.h (renamed from demos/signature/EVP_Signature_demo.h) | 0 | ||||
-rw-r--r-- | demos/signature/Makefile | 7 |
4 files changed, 322 insertions, 4 deletions
diff --git a/demos/signature/EVP_DSA_Signature_demo.c b/demos/signature/EVP_DSA_Signature_demo.c new file mode 100644 index 0000000000..ca41ef34d6 --- /dev/null +++ b/demos/signature/EVP_DSA_Signature_demo.c @@ -0,0 +1,317 @@ +/*- + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * An example that uses the EVP_PKEY*, EVP_DigestSign* and EVP_DigestVerify* + * methods to calculate public/private DSA keypair and to sign and verify + * two static buffers. + */ + +#include <string.h> +#include <stdio.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/decoder.h> +#include <openssl/dsa.h> + +/* + * This demonstration will calculate and verify a signature of data using + * the soliloquy from Hamlet scene 1 act 3 + */ + +static const char *hamlet_1 = + "To be, or not to be, that is the question,\n" + "Whether tis nobler in the minde to suffer\n" + "The slings and arrowes of outragious fortune,\n" + "Or to take Armes again in a sea of troubles,\n" +; +static const char *hamlet_2 = + "And by opposing, end them, to die to sleep;\n" + "No more, and by a sleep, to say we end\n" + "The heart-ache, and the thousand natural shocks\n" + "That flesh is heir to? tis a consumation\n" +; + +static const char ALG[] = "DSA"; +static const char DIGEST[] = "SHA256"; +static const int NUMBITS = 2048; +static const char * const PROPQUERY = NULL; + +static int generate_dsa_params(OSSL_LIB_CTX *libctx, + EVP_PKEY **p_params) +{ + int result = 0; + + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *params = NULL; + + pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY); + if (pkey_ctx == NULL) + goto end; + + if (EVP_PKEY_paramgen_init(pkey_ctx) <= 0) + goto end; + + if (EVP_PKEY_CTX_set_dsa_paramgen_bits(pkey_ctx, NUMBITS) <= 0) + goto end; + if (EVP_PKEY_paramgen(pkey_ctx, ¶ms) <= 0) + goto end; + if (params == NULL) + goto end; + + result = 1; +end: + if(result != 1) { + EVP_PKEY_free(params); + params = NULL; + } + EVP_PKEY_CTX_free(pkey_ctx); + *p_params = params; + fprintf(stdout, "Params:\n"); + EVP_PKEY_print_params_fp(stdout, params, 4, NULL); + fprintf(stdout, "\n"); + + return result; +} + +static int generate_dsa_key(OSSL_LIB_CTX *libctx, + EVP_PKEY *params, + EVP_PKEY **p_pkey) +{ + int result = 0; + + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + + ctx = EVP_PKEY_CTX_new_from_pkey(libctx, params, + NULL); + if (ctx == NULL) + goto end; + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto end; + + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + goto end; + if (pkey == NULL) + goto end; + + result = 1; +end: + if(result != 1) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + EVP_PKEY_CTX_free(ctx); + *p_pkey = pkey; + fprintf(stdout, "Generating public/private key pair:\n"); + EVP_PKEY_print_public_fp(stdout, pkey, 4, NULL); + fprintf(stdout, "\n"); + EVP_PKEY_print_private_fp(stdout, pkey, 4, NULL); + fprintf(stdout, "\n"); + EVP_PKEY_print_params_fp(stdout, pkey, 4, NULL); + fprintf(stdout, "\n"); + + return result; +} + +static int extract_public_key(const EVP_PKEY *pkey, + OSSL_PARAM **p_public_key) +{ + int result = 0; + OSSL_PARAM *public_key = NULL; + + if (EVP_PKEY_todata(pkey, EVP_PKEY_PUBLIC_KEY, &public_key) != 1) + goto end; + + result = 1; +end: + if (result != 1) { + OSSL_PARAM_free(public_key); + public_key = NULL; + } + *p_public_key = public_key; + + return result; +} + +static int extract_keypair(const EVP_PKEY *pkey, + OSSL_PARAM **p_keypair) +{ + int result = 0; + OSSL_PARAM *keypair = NULL; + + if (EVP_PKEY_todata(pkey, EVP_PKEY_KEYPAIR, &keypair) != 1) + goto end; + + result = 1; +end: + if (result != 1) { + OSSL_PARAM_free(keypair); + keypair = NULL; + } + *p_keypair = keypair; + + return result; +} + +static int demo_sign(OSSL_LIB_CTX *libctx, + size_t *p_sig_len, unsigned char **p_sig_value, + OSSL_PARAM keypair[]) +{ + int result = 0; + size_t sig_len = 0; + unsigned char *sig_value = NULL; + EVP_MD_CTX *ctx = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + + pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY); + if (pkey_ctx == NULL) + goto end; + if (EVP_PKEY_fromdata_init(pkey_ctx) != 1) + goto end; + if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_KEYPAIR, keypair) != 1) + goto end; + + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) + goto end; + + if (EVP_DigestSignInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1) + goto end; + + if (EVP_DigestSignUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1) + goto end; + + if (EVP_DigestSignUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1) + goto end; + + /* Calculate the signature size */ + if (EVP_DigestSignFinal(ctx, NULL, &sig_len) != 1) + goto end; + if (sig_len == 0) + goto end; + + sig_value = OPENSSL_malloc(sig_len); + if (sig_value == NULL) + goto end; + + /* Calculate the signature */ + if (EVP_DigestSignFinal(ctx, sig_value, &sig_len) != 1) + goto end; + + result = 1; +end: + EVP_MD_CTX_free(ctx); + if (result != 1) { + OPENSSL_free(sig_value); + sig_len = 0; + sig_value = NULL; + } + *p_sig_len = sig_len; + *p_sig_value = sig_value; + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pkey_ctx); + + fprintf(stdout, "Generating signature:\n"); + BIO_dump_indent_fp(stdout, sig_value, sig_len, 2); + fprintf(stdout, "\n"); + return result; +} + +static int demo_verify(OSSL_LIB_CTX *libctx, + size_t sig_len, unsigned char *sig_value, + OSSL_PARAM public_key[]) +{ + int result = 0; + EVP_MD_CTX *ctx = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + + pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY); + if (pkey_ctx == NULL) + goto end; + if (EVP_PKEY_fromdata_init(pkey_ctx) != 1) + goto end; + if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_PUBLIC_KEY, public_key) != 1) + goto end; + + ctx = EVP_MD_CTX_create(); + if(ctx == NULL) + goto end; + + if (EVP_DigestVerifyInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1) + goto end; + + if (EVP_DigestVerifyUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1) + goto end; + + if (EVP_DigestVerifyUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1) + goto end; + + if (EVP_DigestVerifyFinal(ctx, sig_value, sig_len) != 1) + goto end; + + result = 1; +end: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_MD_CTX_free(ctx); + return result; +} + +int main(void) +{ + int result = 0; + OSSL_LIB_CTX *libctx = NULL; + EVP_PKEY *params = NULL; + EVP_PKEY *pkey = NULL; + OSSL_PARAM *public_key = NULL; + OSSL_PARAM *keypair = NULL; + size_t sig_len = 0; + unsigned char *sig_value = NULL; + + libctx = OSSL_LIB_CTX_new(); + if (libctx == NULL) + goto end; + + if (generate_dsa_params(libctx, ¶ms) != 1) + goto end; + + if (generate_dsa_key(libctx, params, &pkey) != 1) + goto end; + + if (extract_public_key(pkey, &public_key) != 1) + goto end; + + if (extract_keypair(pkey, &keypair) != 1) + goto end; + + /* The signer signs with his private key, and distributes his public key */ + if (demo_sign(libctx, &sig_len, &sig_value, keypair) != 1) + goto end; + + /* A verifier uses the signers public key to verify the signature */ + if (demo_verify(libctx, sig_len, sig_value, public_key) != 1) + goto end; + + result = 1; +end: + if (result != 1) + ERR_print_errors_fp(stderr); + + OPENSSL_free(sig_value); + EVP_PKEY_free(params); + EVP_PKEY_free(pkey); + OSSL_PARAM_free(public_key); + OSSL_PARAM_free(keypair); + OSSL_LIB_CTX_free(libctx); + + return result ? 0 : 1; +} diff --git a/demos/signature/EVP_Signature_demo.c b/demos/signature/EVP_EC_Signature_demo.c index 123c95c26a..b5270f398c 100644 --- a/demos/signature/EVP_Signature_demo.c +++ b/demos/signature/EVP_EC_Signature_demo.c @@ -17,7 +17,7 @@ #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/decoder.h> -#include "EVP_Signature_demo.h" +#include "EVP_EC_Signature_demo.h" /* * This demonstration will calculate and verify a signature of data using diff --git a/demos/signature/EVP_Signature_demo.h b/demos/signature/EVP_EC_Signature_demo.h index aef3e60783..aef3e60783 100644 --- a/demos/signature/EVP_Signature_demo.h +++ b/demos/signature/EVP_EC_Signature_demo.h diff --git a/demos/signature/Makefile b/demos/signature/Makefile index 563ec7799f..394eef6d42 100644 --- a/demos/signature/Makefile +++ b/demos/signature/Makefile @@ -7,16 +7,17 @@ CFLAGS = -I../../include -g -Wall LDFLAGS = -L../.. LDLIBS = -lcrypto -all: EVP_Signature_demo rsa_pss_direct rsa_pss_hash +all: EVP_EC_Signature_demo EVP_DSA_Signature_demo rsa_pss_direct rsa_pss_hash %.o: %.c $(CC) $(CFLAGS) -c $< -EVP_Signature_demo: EVP_Signature_demo.o +EVP_EC_Signature_demo: EVP_EC_Signature_demo.o +EVP_DSA_Signature_demo: EVP_DSA_Signature_demo.o rsa_pss_direct: rsa_pss_direct.o rsa_pss_hash: rsa_pss_hash.o test: ; clean: - $(RM) *.o EVP_Signature_demo rsa_pss_direct rsa_pss_hash + $(RM) *.o EVP_EC_Signature_demo EVP_DSA_Signature_demo rsa_pss_direct rsa_pss_hash |