mirror of
https://github.com/openssl/openssl.git
synced 2024-12-21 06:09:35 +08:00
7ed6de997f
Reviewed-by: Neil Horman <nhorman@openssl.org> Release: yes
357 lines
12 KiB
Plaintext
357 lines
12 KiB
Plaintext
=pod
|
|
|
|
=head1 NAME
|
|
|
|
EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify_init_ex2,
|
|
EVP_PKEY_verify, EVP_PKEY_verify_message_init, EVP_PKEY_verify_message_update,
|
|
EVP_PKEY_verify_message_final, EVP_PKEY_CTX_set_signature - signature
|
|
verification using a public key algorithm
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
#include <openssl/evp.h>
|
|
|
|
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
|
|
int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
|
|
int EVP_PKEY_verify_init_ex2(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo,
|
|
const OSSL_PARAM params[]);
|
|
int EVP_PKEY_verify_message_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo,
|
|
const OSSL_PARAM params[]);
|
|
int EVP_PKEY_CTX_set_signature(EVP_PKEY_CTX *pctx,
|
|
const unsigned char *sig, size_t siglen);
|
|
int EVP_PKEY_verify_message_update(EVP_PKEY_CTX *ctx,
|
|
unsigned char *in, size_t inlen);
|
|
int EVP_PKEY_verify_message_final(EVP_PKEY_CTX *ctx);
|
|
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
|
|
const unsigned char *sig, size_t siglen,
|
|
const unsigned char *tbs, size_t tbslen);
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
EVP_PKEY_verify_init() initializes a public key algorithm context I<ctx> for
|
|
verification using the algorithm given when the context was created
|
|
using L<EVP_PKEY_CTX_new(3)> or variants thereof. The algorithm is used to
|
|
fetch a B<EVP_SIGNATURE> method implicitly, see L<provider(7)/Implicit fetch>
|
|
for more information about implicit fetches.
|
|
|
|
EVP_PKEY_verify_init_ex() is the same as EVP_PKEY_verify_init() but additionally
|
|
sets the passed parameters I<params> on the context before returning.
|
|
|
|
EVP_PKEY_verify_init_ex2() is the same as EVP_PKEY_verify_init_ex(), but works
|
|
with an explicitly fetched B<EVP_SIGNATURE> I<algo>.
|
|
A context I<ctx> without a pre-loaded key cannot be used with this function.
|
|
Depending on what algorithm was fetched, certain details revolving around the
|
|
treatment of the input to EVP_PKEY_verify() may be pre-determined, and in that
|
|
case, those details may normally not be changed.
|
|
See L</NOTES> below for a deeper explanation.
|
|
|
|
EVP_PKEY_verify_message_init() initializes a public key algorithm context
|
|
I<ctx> for verifying an unlimited size message using the algorithm given by
|
|
I<algo> and the key given through L<EVP_PKEY_CTX_new(3)> or
|
|
L<EVP_PKEY_CTX_new_from_pkey(3)>.
|
|
Passing the message is supported both in a one-shot fashion using
|
|
EVP_PKEY_verify(), and through the combination of EVP_PKEY_verify_update() and
|
|
EVP_PKEY_verify_final().
|
|
This function enables using algorithms that can process input of arbitrary
|
|
length, such as ED25519, RSA-SHA256 and similar.
|
|
|
|
EVP_PKEY_CTX_set_signature() specifies the I<siglen> bytes long signature
|
|
I<sig> to be verified against by EVP_PKEY_verify_final().
|
|
It I<must> be used together with EVP_PKEY_verify_update() and
|
|
EVP_PKEY_verify_final().
|
|
See L</NOTES> below for a deeper explanation.
|
|
|
|
EVP_PKEY_verify_update() adds I<inlen> bytes from I<in> to the data to be
|
|
processed for verification. The signature algorithm specification and
|
|
implementation determine how the input bytes are processed and if there's a
|
|
limit on the total size of the input. See L</NOTES> below for a deeper
|
|
explanation.
|
|
|
|
EVP_PKEY_verify_final() verifies the processed data, given only I<ctx>.
|
|
The signature to verify against must have been given with
|
|
EVP_PKEY_CTX_set_signature().
|
|
|
|
EVP_PKEY_verify() is a one-shot function that performs the same thing as
|
|
EVP_PKEY_CTX_set_signature() call with I<sig> and I<siglen> as parameters,
|
|
followed by a single EVP_PKEY_verify_update() call with I<tbs> and I<tbslen>,
|
|
followed by EVP_PKEY_verify_final() call.
|
|
|
|
=head1 NOTES
|
|
|
|
=begin comment
|
|
|
|
These notes are largely replicated in EVP_PKEY_sign.pod, please keep them
|
|
in sync.
|
|
|
|
=end comment
|
|
|
|
=head2 General
|
|
|
|
Some signature implementations only accumulate the input data and do no
|
|
further processing before verifying it (they expect the input to be a digest),
|
|
while others compress the data, typically by internally producing a digest,
|
|
and signing the result, which is then verified against a given signature.
|
|
Some of them support both modes of operation at the same time.
|
|
The caller is expected to know how the chosen algorithm is supposed to behave
|
|
and under what conditions.
|
|
|
|
For example, an RSA implementation can be expected to only expect a digest as
|
|
input, while ED25519 can be expected to process the input with a hash, i.e.
|
|
to produce the digest internally, and while RSA-SHA256 can be expected to
|
|
handle either mode of operation, depending on if the operation was initialized
|
|
with EVP_PKEY_verify_init_ex2() or with EVP_PKEY_verify_message_init().
|
|
|
|
Similarly, an RSA implementation usually expects additional details to be set,
|
|
like the message digest algorithm that the input is supposed to be digested
|
|
with, as well as the padding mode (see L<EVP_PKEY_CTX_set_signature_md(3)> and
|
|
L<EVP_PKEY_CTX_set_rsa_padding(3)> and similar others), while an RSA-SHA256
|
|
implementation usually has these details pre-set and immutable.
|
|
|
|
The functions described here can't be used to combine separate algorithms. In
|
|
particular, neither L<EVP_PKEY_CTX_set_signature_md(3)> nor the B<OSSL_PARAM>
|
|
parameter "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) can be used to combine a
|
|
signature algorithm with a hash algorithm to process the input. In other
|
|
words, it's not possible to specify a I<ctx> pre-loaded with an RSA pkey, or
|
|
an I<algo> that fetched C<RSA> and try to specify SHA256 separately to get the
|
|
functionality of RSA-SHA256. If combining algorithms in that manner is
|
|
desired, please use L<EVP_DigestVerifyInit(3)> and associated functions, or
|
|
L<EVP_VerifyInit(3)> and associated functions.
|
|
|
|
=head2 Performing multiple verifications
|
|
|
|
When initialized using EVP_PKEY_verify_init_ex() or EVP_PKEY_verify_init_ex2(),
|
|
EVP_PKEY_verify() can be called more than once on the same context to have
|
|
several one-shot operations performed using the same parameters.
|
|
|
|
When initialized using EVP_PKEY_verify_message_init(), it's not possible to
|
|
call EVP_PKEY_verify() multiple times.
|
|
|
|
=head2 On EVP_PKEY_CTX_set_signature()
|
|
|
|
Some signature algorithms (such as LMS) require the signature verification
|
|
data be specified before verifying the message.
|
|
Other algorithms allow the signature to be specified late.
|
|
To allow either way (which may depend on the application's flow of input), the
|
|
signature to be verified against I<must> be specified using this function when
|
|
using EVP_PKEY_verify_message_update() and EVP_PKEY_verify_message_final() to
|
|
perform the verification.
|
|
|
|
=head1 RETURN VALUES
|
|
|
|
All functions return 1 for success and 0 or a negative value for failure.
|
|
However, unlike other functions, the return value 0 from EVP_PKEY_verify(),
|
|
EVP_PKEY_verify_recover() and EVP_PKEY_verify_message_final() only indicates
|
|
that the signature did not verify successfully (that is tbs did not match the
|
|
original data or the signature was of invalid form) it is not an indication of
|
|
a more serious error.
|
|
|
|
A negative value indicates an error other that signature verification failure.
|
|
In particular a return value of -2 indicates the operation is not supported by
|
|
the public key algorithm.
|
|
|
|
=head1 EXAMPLES
|
|
|
|
=begin comment
|
|
|
|
These examples are largely replicated in EVP_PKEY_sign.pod, please keep them
|
|
in sync.
|
|
|
|
=end comment
|
|
|
|
=head2 RSA with PKCS#1 padding for SHA256
|
|
|
|
Verify signature using PKCS#1 padding and a SHA256 digest as input:
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
unsigned char *md, *sig;
|
|
size_t mdlen, siglen;
|
|
EVP_PKEY *verify_key;
|
|
|
|
/*
|
|
* NB: assumes verify_key, sig, siglen md and mdlen are already set up
|
|
* and that verify_key is an RSA public key
|
|
*/
|
|
ctx = EVP_PKEY_CTX_new(verify_key, NULL /* no engine */);
|
|
if (ctx == NULL)
|
|
/* Error occurred */
|
|
if (EVP_PKEY_verify_init(ctx) <= 0)
|
|
/* Error */
|
|
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
|
|
/* Error */
|
|
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
|
|
/* Error */
|
|
|
|
/* Perform operation */
|
|
ret = EVP_PKEY_verify(ctx, sig, siglen, md, mdlen);
|
|
|
|
/*
|
|
* ret == 1 indicates success, 0 verify failure and < 0 for some
|
|
* other error.
|
|
*/
|
|
|
|
=head2 RSA-SHA256 with a pre-computed digest
|
|
|
|
Verify a digest with RSA-SHA256 using one-shot functions. To be noted is that
|
|
RSA-SHA256 is assumed to be an implementation of C<sha256WithRSAEncryption>,
|
|
for which the padding is pre-determined to be B<RSA_PKCS1_PADDING>, and the
|
|
input digest is assumed to have been computed using SHA256.
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
/* md is a SHA-256 digest in this example. */
|
|
unsigned char *md, *sig;
|
|
size_t mdlen = 32, siglen;
|
|
EVP_PKEY *signing_key;
|
|
|
|
/*
|
|
* NB: assumes verify_key, sig, siglen, md and mdlen are already set up
|
|
* and that verify_key is an RSA public key
|
|
*/
|
|
ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
|
|
alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL);
|
|
|
|
if (ctx == NULL)
|
|
/* Error occurred */
|
|
if (EVP_PKEY_verify_init_ex2(ctx, alg, NULL) <= 0)
|
|
/* Error */
|
|
|
|
/* Determine buffer length */
|
|
if (EVP_PKEY_verify(ctx, sig, siglen, md, mdlen) <= 0)
|
|
/* Error or signature doesn't verify */
|
|
|
|
/* Perform operation */
|
|
ret = EVP_PKEY_verify(ctx, sig, siglen, md, mdlen);
|
|
|
|
/*
|
|
* ret == 1 indicates success, 0 verify failure and < 0 for some
|
|
* other error.
|
|
*/
|
|
|
|
=head2 RSA-SHA256, one-shot
|
|
|
|
Verify a document with RSA-SHA256 using one-shot functions.
|
|
To be noted is that RSA-SHA256 is assumed to be an implementation of
|
|
C<sha256WithRSAEncryption>, for which the padding is pre-determined to be
|
|
B<RSA_PKCS1_PADDING>.
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
/* in the input in this example. */
|
|
unsigned char *in, *sig;
|
|
/* inlen is the length of the input in this example. */
|
|
size_t inlen, siglen;
|
|
EVP_PKEY *signing_key;
|
|
EVP_SIGNATURE *alg;
|
|
|
|
/*
|
|
* NB: assumes signing_key, in and inlen are set up before
|
|
* the next step. signing_key must be an RSA private key,
|
|
* in must point to data to be digested and signed, and
|
|
* inlen must be the size of the data in bytes.
|
|
*/
|
|
ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
|
|
alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL);
|
|
|
|
if (ctx == NULL || alg == NULL)
|
|
/* Error occurred */
|
|
if (EVP_PKEY_verify_message_init(ctx, alg, NULL) <= 0)
|
|
/* Error */
|
|
|
|
/* Perform operation */
|
|
ret = EVP_PKEY_verify(ctx, sig, siglen, in, inlen);
|
|
|
|
/*
|
|
* ret == 1 indicates success, 0 verify failure and < 0 for some
|
|
* other error.
|
|
*/
|
|
|
|
=head2 RSA-SHA256, using update and final
|
|
|
|
This is the same as the previous example, but allowing stream-like
|
|
functionality.
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rsa.h>
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
/* in is the input in this example. */
|
|
unsigned char *in, *sig;
|
|
/* inlen is the length of the input in this example. */
|
|
size_t inlen, siglen;
|
|
EVP_PKEY *signing_key;
|
|
EVP_SIGNATURE *alg;
|
|
|
|
/*
|
|
* NB: assumes signing_key, in and inlen are set up before
|
|
* the next step. signing_key must be an RSA private key,
|
|
* in must point to data to be digested and signed, and
|
|
* inlen must be the size of the data in bytes.
|
|
*/
|
|
ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
|
|
alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL);
|
|
|
|
if (ctx == NULL || alg == NULL)
|
|
/* Error occurred */
|
|
if (EVP_PKEY_verify_message_init(ctx, alg, NULL) <= 0)
|
|
/* Error */
|
|
|
|
/* We have the signature, specify it early */
|
|
EVP_PKEY_CTX_set_signature(ctx, sig, siglen);
|
|
|
|
/* Perform operation */
|
|
while (inlen > 0) {
|
|
if (EVP_PKEY_verify_message_update(ctx, in, inlen)) <= 0)
|
|
/* Error */
|
|
if (inlen > 256) {
|
|
inlen -= 256;
|
|
in += 256;
|
|
} else {
|
|
inlen = 0;
|
|
}
|
|
}
|
|
ret = EVP_PKEY_verify_message_final(ctx);
|
|
|
|
/*
|
|
* ret == 1 indicates success, 0 verify failure and < 0 for some
|
|
* other error.
|
|
*/
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
L<EVP_PKEY_CTX_new(3)>,
|
|
L<EVP_PKEY_encrypt(3)>,
|
|
L<EVP_PKEY_decrypt(3)>,
|
|
L<EVP_PKEY_sign(3)>,
|
|
L<EVP_PKEY_verify_recover(3)>,
|
|
L<EVP_PKEY_derive(3)>
|
|
|
|
=head1 HISTORY
|
|
|
|
The EVP_PKEY_verify_init() and EVP_PKEY_verify() functions were added in
|
|
OpenSSL 1.0.0.
|
|
|
|
The EVP_PKEY_verify_init_ex() function was added in OpenSSL 3.0.
|
|
|
|
The EVP_PKEY_verify_init_ex2(), EVP_PKEY_verify_message_init(),
|
|
EVP_PKEY_verify_message_update(), EVP_PKEY_verify_message_final() and
|
|
EVP_PKEY_CTX_set_signature() functions where added in OpenSSL 3.4.
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
Copyright 2006-2024 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
|
|
L<https://www.openssl.org/source/license.html>.
|
|
|
|
=cut
|