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