Path: blob/main/crypto/openssl/demos/signature/rsa_pss_hash.c
111746 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#include <stdio.h>10#include <stdlib.h>11#include <openssl/core_names.h>12#include <openssl/evp.h>13#include <openssl/rsa.h>14#include <openssl/params.h>15#include <openssl/err.h>16#include <openssl/bio.h>17#include "rsa_pss.h"1819/* The data to be signed. This will be hashed. */20static const char test_message[] = "This is an example message to be signed.";2122/* A property query used for selecting algorithm implementations. */23static const char *propq = NULL;2425/*26* This function demonstrates RSA signing of an arbitrary-length message.27* Hashing is performed automatically. In this example, SHA-256 is used. If you28* have already hashed your message and simply want to sign the hash directly,29* see rsa_pss_direct.c.30*/31static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len)32{33int ret = 0;34EVP_PKEY *pkey = NULL;35EVP_MD_CTX *mctx = NULL;36OSSL_PARAM params[2], *p = params;37const unsigned char *ppriv_key = NULL;3839*sig = NULL;4041/* Load DER-encoded RSA private key. */42ppriv_key = rsa_priv_key;43pkey = d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &ppriv_key,44sizeof(rsa_priv_key), libctx, propq);45if (pkey == NULL) {46fprintf(stderr, "Failed to load private key\n");47goto end;48}4950/* Create MD context used for signing. */51mctx = EVP_MD_CTX_new();52if (mctx == NULL) {53fprintf(stderr, "Failed to create MD context\n");54goto end;55}5657/* Initialize MD context for signing. */58*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,59OSSL_PKEY_RSA_PAD_MODE_PSS, 0);60*p = OSSL_PARAM_construct_end();6162if (EVP_DigestSignInit_ex(mctx, NULL, "SHA256", libctx, propq,63pkey, params)64== 0) {65fprintf(stderr, "Failed to initialize signing context\n");66goto end;67}6869/*70* Feed data to be signed into the algorithm. This may71* be called multiple times.72*/73if (EVP_DigestSignUpdate(mctx, test_message, sizeof(test_message)) == 0) {74fprintf(stderr, "Failed to hash message into signing context\n");75goto end;76}7778/* Determine signature length. */79if (EVP_DigestSignFinal(mctx, NULL, sig_len) == 0) {80fprintf(stderr, "Failed to get signature length\n");81goto end;82}8384/* Allocate memory for signature. */85*sig = OPENSSL_malloc(*sig_len);86if (*sig == NULL) {87fprintf(stderr, "Failed to allocate memory for signature\n");88goto end;89}9091/* Generate signature. */92if (EVP_DigestSignFinal(mctx, *sig, sig_len) == 0) {93fprintf(stderr, "Failed to sign\n");94goto end;95}9697ret = 1;98end:99EVP_MD_CTX_free(mctx);100EVP_PKEY_free(pkey);101102if (ret == 0)103OPENSSL_free(*sig);104105return ret;106}107108/*109* This function demonstrates verification of an RSA signature over an110* arbitrary-length message using the PSS signature scheme. Hashing is performed111* automatically.112*/113static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len)114{115int ret = 0;116EVP_PKEY *pkey = NULL;117EVP_MD_CTX *mctx = NULL;118OSSL_PARAM params[2], *p = params;119const unsigned char *ppub_key = NULL;120121/* Load DER-encoded RSA public key. */122ppub_key = rsa_pub_key;123pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ppub_key, sizeof(rsa_pub_key));124if (pkey == NULL) {125fprintf(stderr, "Failed to load public key\n");126goto end;127}128129/* Create MD context used for verification. */130mctx = EVP_MD_CTX_new();131if (mctx == NULL) {132fprintf(stderr, "Failed to create MD context\n");133goto end;134}135136/* Initialize MD context for verification. */137*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,138OSSL_PKEY_RSA_PAD_MODE_PSS, 0);139*p = OSSL_PARAM_construct_end();140141if (EVP_DigestVerifyInit_ex(mctx, NULL, "SHA256", libctx, propq,142pkey, params)143== 0) {144fprintf(stderr, "Failed to initialize signing context\n");145goto end;146}147148/*149* Feed data to be signed into the algorithm. This may150* be called multiple times.151*/152if (EVP_DigestVerifyUpdate(mctx, test_message, sizeof(test_message)) == 0) {153fprintf(stderr, "Failed to hash message into signing context\n");154goto end;155}156157/* Verify signature. */158if (EVP_DigestVerifyFinal(mctx, sig, sig_len) == 0) {159fprintf(stderr, "Failed to verify signature; "160"signature may be invalid\n");161goto end;162}163164ret = 1;165end:166EVP_MD_CTX_free(mctx);167EVP_PKEY_free(pkey);168return ret;169}170171int main(int argc, char **argv)172{173int ret = EXIT_FAILURE;174OSSL_LIB_CTX *libctx = NULL;175unsigned char *sig = NULL;176size_t sig_len = 0;177178if (sign(libctx, &sig, &sig_len) == 0)179goto end;180181if (verify(libctx, sig, sig_len) == 0)182goto end;183184printf("Success\n");185186ret = EXIT_SUCCESS;187end:188OPENSSL_free(sig);189OSSL_LIB_CTX_free(libctx);190return ret;191}192193194