Path: blob/main/crypto/openssl/demos/signature/rsa_pss_hash.c
34870 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[] =21"This is an example message to be signed.";2223/* A property query used for selecting algorithm implementations. */24static const char *propq = NULL;2526/*27* This function demonstrates RSA signing of an arbitrary-length message.28* Hashing is performed automatically. In this example, SHA-256 is used. If you29* have already hashed your message and simply want to sign the hash directly,30* see rsa_pss_direct.c.31*/32static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len)33{34int ret = 0;35EVP_PKEY *pkey = NULL;36EVP_MD_CTX *mctx = NULL;37OSSL_PARAM params[2], *p = params;38const unsigned char *ppriv_key = NULL;3940*sig = NULL;4142/* Load DER-encoded RSA private key. */43ppriv_key = rsa_priv_key;44pkey = d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &ppriv_key,45sizeof(rsa_priv_key), libctx, propq);46if (pkey == NULL) {47fprintf(stderr, "Failed to load private key\n");48goto end;49}5051/* Create MD context used for signing. */52mctx = EVP_MD_CTX_new();53if (mctx == NULL) {54fprintf(stderr, "Failed to create MD context\n");55goto end;56}5758/* Initialize MD context for signing. */59*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,60OSSL_PKEY_RSA_PAD_MODE_PSS, 0);61*p = OSSL_PARAM_construct_end();6263if (EVP_DigestSignInit_ex(mctx, NULL, "SHA256", libctx, propq,64pkey, params) == 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) == 0) {143fprintf(stderr, "Failed to initialize signing context\n");144goto end;145}146147/*148* Feed data to be signed into the algorithm. This may149* be called multiple times.150*/151if (EVP_DigestVerifyUpdate(mctx, test_message, sizeof(test_message)) == 0) {152fprintf(stderr, "Failed to hash message into signing context\n");153goto end;154}155156/* Verify signature. */157if (EVP_DigestVerifyFinal(mctx, sig, sig_len) == 0) {158fprintf(stderr, "Failed to verify signature; "159"signature may be invalid\n");160goto end;161}162163ret = 1;164end:165EVP_MD_CTX_free(mctx);166EVP_PKEY_free(pkey);167return ret;168}169170int main(int argc, char **argv)171{172int ret = EXIT_FAILURE;173OSSL_LIB_CTX *libctx = NULL;174unsigned char *sig = NULL;175size_t sig_len = 0;176177if (sign(libctx, &sig, &sig_len) == 0)178goto end;179180if (verify(libctx, sig, sig_len) == 0)181goto end;182183printf("Success\n");184185ret = EXIT_SUCCESS;186end:187OPENSSL_free(sig);188OSSL_LIB_CTX_free(libctx);189return ret;190}191192193