From 580b557b1398e0ad15dec2c833129ea965b2e3de Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 14 Mar 2016 16:45:51 +0000 Subject: [PATCH] Update and clarify ECDSA documentation. Reviewed-by: Richard Levitte --- doc/crypto/ecdsa.pod | 240 +++++++++++++++++++++---------------------- 1 file changed, 119 insertions(+), 121 deletions(-) diff --git a/doc/crypto/ecdsa.pod b/doc/crypto/ecdsa.pod index be0f4826c2..dbd678f7c1 100644 --- a/doc/crypto/ecdsa.pod +++ b/doc/crypto/ecdsa.pod @@ -2,113 +2,117 @@ =head1 NAME -ECDSA_SIG_new, ECDSA_SIG_free, i2d_ECDSA_SIG, d2i_ECDSA_SIG, ECDSA_size, ECDSA_sign_setup, ECDSA_sign, ECDSA_sign_ex, ECDSA_verify, ECDSA_do_sign, ECDSA_do_sign_ex, ECDSA_do_verify - Elliptic Curve Digital Signature Algorithm +ECDSA_SIG_new, ECDSA_SIG_free, i2d_ECDSA_SIG, d2i_ECDSA_SIG, ECDSA_size, +ECDSA_sign, ECDSA_do_sign, ECDSA_verify, ECDSA_do_verify, ECDSA_sign_setup, +ECDSA_sign_ex, ECDSA_do_sign_ex - low level elliptic curve digital signature +algorithm (ECDSA) functions. =head1 SYNOPSIS #include - ECDSA_SIG* ECDSA_SIG_new(void); - void ECDSA_SIG_free(ECDSA_SIG *sig); - int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); - ECDSA_SIG* d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, - long len); - - ECDSA_SIG* ECDSA_do_sign(const unsigned char *dgst, int dgst_len, - EC_KEY *eckey); - ECDSA_SIG* ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, - const BIGNUM *kinv, const BIGNUM *rp, - EC_KEY *eckey); - int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, - const ECDSA_SIG *sig, EC_KEY* eckey); - int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, - BIGNUM **kinv, BIGNUM **rp); - int ECDSA_sign(int type, const unsigned char *dgst, - int dgstlen, unsigned char *sig, - unsigned int *siglen, EC_KEY *eckey); - int ECDSA_sign_ex(int type, const unsigned char *dgst, - int dgstlen, unsigned char *sig, - unsigned int *siglen, const BIGNUM *kinv, - const BIGNUM *rp, EC_KEY *eckey); - int ECDSA_verify(int type, const unsigned char *dgst, - int dgstlen, const unsigned char *sig, - int siglen, EC_KEY *eckey); - int ECDSA_size(const EC_KEY *eckey); - - const ECDSA_METHOD* ECDSA_OpenSSL(void); - void ECDSA_set_default_method(const ECDSA_METHOD *meth); - const ECDSA_METHOD* ECDSA_get_default_method(void); - int ECDSA_set_method(EC_KEY *eckey,const ECDSA_METHOD *meth); + ECDSA_SIG *ECDSA_SIG_new(void); + void ECDSA_SIG_free(ECDSA_SIG *sig); + void ECDSA_SIG_get0(BIGNUM **pr, BIGNUM **ps, ECDSA_SIG *sig); + int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); + ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); + int ECDSA_size(const EC_KEY *eckey); + + int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); + ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); + + int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); + int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY* eckey); + + ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey); + int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); + int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); =head1 DESCRIPTION -The B structure consists of two BIGNUMs for the -r and s value of a ECDSA signature (see X9.62 or FIPS 186-2). +Note: these functions provide a low level interface to ECDSA. Most +applications should use the higher level B interface such as +L or L instead. - struct - { - BIGNUM *r; - BIGNUM *s; - } ECDSA_SIG; +B is an opaque structure consisting of two BIGNUMs for the +B and B value of an ECDSA signature (see X9.62 or FIPS 186-2). ECDSA_SIG_new() allocates a new B structure (note: this -function also allocates the BIGNUMs) and initialize it. +function also allocates the BIGNUMs) and initializes it. ECDSA_SIG_free() frees the B structure B. -i2d_ECDSA_SIG() creates the DER encoding of the ECDSA signature -B and writes the encoded signature to B<*pp> (note: if B -is NULL B returns the expected length in bytes of -the DER encoded signature). B returns the length -of the DER encoded signature (or 0 on error). +ECDSA_SIG_get0() returns internal pointers the B and B values contained +in B. The values can then be examined or initialised. -d2i_ECDSA_SIG() decodes a DER encoded ECDSA signature and returns -the decoded signature in a newly allocated B structure. -B<*sig> points to the buffer containing the DER encoded signature -of size B. +i2d_ECDSA_SIG() creates the DER encoding of the ECDSA signature B and +writes the encoded signature to B<*pp> (note: if B is NULL i2d_ECDSA_SIG() +returns the expected length in bytes of the DER encoded signature). +i2d_ECDSA_SIG() returns the length of the DER encoded signature (or 0 on +error). -ECDSA_size() returns the maximum length of a DER encoded -ECDSA signature created with the private EC key B. +d2i_ECDSA_SIG() decodes a DER encoded ECDSA signature and returns the decoded +signature in a newly allocated B structure. B<*sig> points to the +buffer containing the DER encoded signature of size B. -ECDSA_sign_setup() may be used to precompute parts of the -signing operation. B is the private EC key and B -is a pointer to B structure (or NULL). The precomputed -values or returned in B and B and can be used in a -later call to B or B. +ECDSA_size() returns the maximum length of a DER encoded ECDSA signature +created with the private EC key B. -ECDSA_sign() is wrapper function for ECDSA_sign_ex with B +ECDSA_sign() computes a digital signature of the B bytes hash value +B using the private EC key B. The DER encoded signatures is +stored in B and it's length is returned in B. Note: B must +point to ECDSA_size(eckey) bytes of memory. The parameter B is currently +ignored. ECDSA_sign() is wrapper function for ECDSA_sign_ex() with B and B set to NULL. -ECDSA_sign_ex() computes a digital signature of the B bytes -hash value B using the private EC key B and the optional -pre-computed values B and B. The DER encoded signatures is -stored in B and it's length is returned in B. Note: B -must point to B bytes of memory. The parameter B -is ignored. +ECDSA_do_sign() is similar to ECDSA_sign() except the signature is returned +as a newly allocated B structure (or NULL on error). ECDSA_do_sign() +is a wrapper function for ECDSA_do_sign_ex() with B and B set to +NULL. -ECDSA_verify() verifies that the signature in B of size -B is a valid ECDSA signature of the hash value -B of size B using the public key B. -The parameter B is ignored. +ECDSA_verify() verifies that the signature in B of size B is a +valid ECDSA signature of the hash value B of size B using the +public key B. The parameter B is ignored. -ECDSA_do_sign() is wrapper function for ECDSA_do_sign_ex with B -and B set to NULL. +ECDSA_do_verify() is similar to ECDSA_verify() except the signature is +presented in the form of a pointer to an B structure. + +The remaining functions utilise the internal B and B values used +during signature computation. Most applications will never need to call these +and some external ECDSA ENGINE implementations may not support them at all if +either B or B is not B. -ECDSA_do_sign_ex() computes a digital signature of the B -bytes hash value B using the private key B and the -optional pre-computed values B and B. The signature is -returned in a newly allocated B structure (or NULL on error). +ECDSA_sign_setup() may be used to precompute parts of the signing operation. +B is the private EC key and B is a pointer to B structure +(or NULL). The precomputed values or returned in B and B and can be +used in a later call to ECDSA_sign_ex() or ECDSA_do_sign_ex(). -ECDSA_do_verify() verifies that the signature B is a valid -ECDSA signature of the hash value B of size B -using the public key B. +ECDSA_sign_ex() computes a digital signature of the B bytes hash value +B using the private EC key B and the optional pre-computed values +B and B. The DER encoded signatures is stored in B and it's +length is returned in B. Note: B must point to ECDSA_size(eckey) +bytes of memory. The parameter B is ignored. + +ECDSA_do_sign_ex() is similar to ECDSA_sign_ex() except the signature is +returned as a newly allocated B structure (or NULL on error). =head1 RETURN VALUES ECDSA_size() returns the maximum length signature or 0 on error. -ECDSA_sign_setup() and ECDSA_sign() return 1 if successful or 0 -on error. +ECDSA_sign(), ECDSA_sign_ex() and ECDSA_sign_setup() return 1 if successful +or 0 on error. + +ECDSA_do_sign() and ECDSA_do_sign_ex() return a pointer to an allocated +B structure or NULL on error. ECDSA_verify() and ECDSA_do_verify() return 1 for a valid signature, 0 for an invalid signature and -1 on error. @@ -116,8 +120,8 @@ The error codes can be obtained by L. =head1 EXAMPLES -Creating a ECDSA signature of given SHA-1 hash value using the -named curve secp192k1. +Creating an ECDSA signature of a given SHA-256 hash value using the +named curve prime256v1 (aka P-256). First step: create a EC_KEY object (note: this part is B ECDSA specific) @@ -125,59 +129,50 @@ specific) int ret; ECDSA_SIG *sig; EC_KEY *eckey; - eckey = EC_KEY_new_by_curve_name(NID_secp192k1); - if (eckey == NULL) - { - /* error */ - } - if (!EC_KEY_generate_key(eckey)) - { - /* error */ - } - -Second step: compute the ECDSA signature of a SHA-1 hash value -using B - - sig = ECDSA_do_sign(digest, 20, eckey); - if (sig == NULL) - { - /* error */ - } - -or using B + eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (eckey == NULL) { + /* error */ + } + if (EC_KEY_generate_key(eckey) == 0) { + /* error */ + } + +Second step: compute the ECDSA signature of a SHA-256 hash value +using ECDSA_do_sign(): + + sig = ECDSA_do_sign(digest, 32, eckey); + if (sig == NULL) { + /* error */ + } + +or using ECDSA_sign(): unsigned char *buffer, *pp; int buf_len; buf_len = ECDSA_size(eckey); buffer = OPENSSL_malloc(buf_len); pp = buffer; - if (!ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey); - { - /* error */ - } + if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0) { + /* error */ + } -Third step: verify the created ECDSA signature using B +Third step: verify the created ECDSA signature using ECDSA_do_verify(): - ret = ECDSA_do_verify(digest, 20, sig, eckey); + ret = ECDSA_do_verify(digest, 32, sig, eckey); -or using B +or using ECDSA_verify(): - ret = ECDSA_verify(0, digest, 20, buffer, buf_len, eckey); + ret = ECDSA_verify(0, digest, 32, buffer, buf_len, eckey); and finally evaluate the return value: - if (ret == -1) - { - /* error */ - } - else if (ret == 0) - { - /* incorrect signature */ - } - else /* ret == 1 */ - { - /* signature ok */ - } + if (ret == 1) { + /* signature ok */ + } else if (ret == 0) { + /* incorrect signature */ + } else { + /* error */ + } =head1 CONFORMING TO @@ -186,6 +181,9 @@ ANSI X9.62, US Federal Information Processing Standard FIPS 186-2 =head1 SEE ALSO -L, L +L, +L, +L, +L =cut -- 2.25.1