Loading crypto/ecdsa/ecdsa.h +138 −15 Original line number Diff line number Diff line /* crypto/ecdsa/ecdsa.h */ /** * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions * \author Written by Nils Larsch for the OpenSSL project */ /* ==================================================================== * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -96,7 +100,7 @@ typedef struct ecdsa_data_st { /* EC_KEY_METH_DATA part */ int (*init)(EC_KEY *); void (*finish)(EC_KEY *); /* method specific part */ /* method (ECDSA) specific part */ BIGNUM *kinv; /* signing pre-calc */ BIGNUM *r; /* signing pre-calc */ ENGINE *engine; Loading @@ -105,38 +109,157 @@ typedef struct ecdsa_data_st { CRYPTO_EX_DATA ex_data; } ECDSA_DATA; /* signature functions */ /** ECDSA_SIG *ECDSA_SIG_new(void) * allocates and initialize a ECDSA_SIG structure * \return pointer to a ECDSA_SIG structure or NULL if an error occurred */ ECDSA_SIG *ECDSA_SIG_new(void); /** ECDSA_SIG_free * frees a ECDSA_SIG structure * \param a pointer to the ECDSA_SIG structure */ void ECDSA_SIG_free(ECDSA_SIG *a); /** i2d_ECDSA_SIG * DER encode content of ECDSA_SIG object (note: this function modifies *pp * (*pp += length of the DER encoded signature)). * \param a pointer to the ECDSA_SIG object * \param pp pointer to a unsigned char pointer for the output or NULL * \return the length of the DER encoded ECDSA_SIG object or 0 */ int i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **pp); ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long length); /* ECDSA_DATA functions */ /** d2i_ECDSA_SIG * decodes a DER encoded ECDSA signature (note: this function changes *pp * (*pp += len)). * \param v pointer to ECDSA_SIG pointer (may be NULL) * \param pp buffer with the DER encoded signature * \param len bufferlength * \return pointer to the decoded ECDSA_SIG structure (or NULL) */ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long len); /** ECDSA_DATA_new * creates a new ECDSA_DATA object * \return pointer to a newly allocated (and initialized) ECDSA_DATA object */ ECDSA_DATA *ECDSA_DATA_new(void); ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *); void ECDSA_DATA_free(ECDSA_DATA *); ECDSA_DATA *ecdsa_check(EC_KEY *); /** ECDSA_DATA_new_method * creates a new ECDSA_DATA object using a specified ENGINE * \param eng pointer to a ENGINE structure * \return pointer to a newly allocated (and initialized) ECDSA_DATA object */ ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *eng); /** ECDSA_DATA_free * frees ECDSA_DATA structure * \param data pointer to a ECDSA_DATA structure */ void ECDSA_DATA_free(ECDSA_DATA *data); /** ecdsa_check * checks whether ECKEY->meth_data is a pointer to a ECDSA_DATA structure * and if not it removes the old meth_data and creates a ECDSA_DATA structure. * \param eckey pointer to a EC_KEY object * \return pointer to a ECDSA_DATA structure */ ECDSA_DATA *ecdsa_check(EC_KEY *eckey); /** ECDSA_do_sign * computes the ECDSA signature of the given hash value using * the supplied private key and returns the created signature. * \param dgst pointer to the hash value * \param dgst_len length of the hash value * \param eckey pointer to the EC_KEY object containing a private EC key * \return pointer to a ECDSA_SIG structure or NULL */ ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,int dgst_len,EC_KEY *eckey); ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, EC_KEY *); /** ECDSA_do_verify * verifies that the supplied signature is a valid ECDSA * signature of the supplied hash value using the supplied public key. * \param dgst pointer to the hash value * \param dgst_len length of the hash value * \param sig pointer to the ECDSA_SIG structure * \param eckey pointer to the EC_KEY object containing a public EC key * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error */ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, ECDSA_SIG *sig, EC_KEY* eckey); const ECDSA_METHOD *ECDSA_OpenSSL(void); void ECDSA_set_default_method(const ECDSA_METHOD *); /** ECDSA_set_default_method * sets the default ECDSA method * \param meth the new default ECDSA_METHOD */ void ECDSA_set_default_method(const ECDSA_METHOD *meth); /** ECDSA_get_default_method * returns the default ECDSA method * \return pointer to ECDSA_METHOD structure containing the default method */ const ECDSA_METHOD *ECDSA_get_default_method(void); int ECDSA_set_method(EC_KEY *, const ECDSA_METHOD *); int ECDSA_size(const EC_KEY *); /** ECDSA_set_method * sets method to be used for the ECDSA operations * \param eckey pointer to the EC_KEY object * \param meth pointer to the new method * \return 1 on success and 0 otherwise */ int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth); /** ECDSA_size * returns the maximum length of the DER encoded signature * \param eckey pointer to a EC_KEY object * \return numbers of bytes required for the DER encoded signature */ int ECDSA_size(const EC_KEY *eckey); /** ECDSA_sign_setup * precompute parts of the signing operation (the computed values may be * passed to ECDSA_DATA->kinv and ECDSA_DATA->r for a later signature * computation). * \param eckey pointer to the EC_KEY object containing a private EC key * \param ctx pointer to a BN_CTX object (may be NULL) * \param kinv pointer to a BIGNUM pointer for the inverse of k * \param rp pointer to a BIGNUM pointer for x coordinate of k * generator * \return 1 on success and 0 otherwise */ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); int ECDSA_sign(int type, const unsigned char *dgst, int dgst_len, /** ECDSA_sign * computes ECDSA signature of a given hash value using the supplied * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). * \param type this parameter is ignored * \param dgst pointer to the hash value to sign * \param dgstlen length of the hash value * \param sig buffer to hold the DER encoded signature * \param siglen pointer to the length of the returned signature * \param eckey pointer to the EC_KEY object containing a private EC key * \return 1 on success and 0 otherwise */ int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sig, int sig_len, EC_KEY *eckey); /** ECDSA_verify * verifies that the given signature is valid ECDSA signature * of the supplied hash value using the specified public key. * \param type this parameter is ignored * \param dgst pointer to the hash value * \param dgstlen length of the hash value * \param sig pointer to the DER encoded signature * \param siglen length of the DER encoded signature * \param eckey pointer to the EC_KEY object containing a public EC key * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error */ int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, const unsigned char *sig, int siglen, EC_KEY *eckey); /* the standard ex_data functions */ int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg); Loading crypto/ecdsa/ecs_ossl.c +116 −134 Original line number Diff line number Diff line /* crypto/ecdsa/ecs_ossl.c */ /* * Written by Nils Larsch for the OpenSSL project */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -86,49 +89,43 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx = NULL; BIGNUM k,*kinv=NULL,*r=NULL,*order=NULL,*X=NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point=NULL; EC_GROUP *group; int ret = 0; if (!eckey || !eckey->group || !eckey->pub_key || !eckey->priv_key) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } BN_init(&k); group = eckey->group; if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE); goto err; return 0; } } else ctx = ctx_in; if ((r = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if ((order = BN_new()) == NULL) k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if ((X = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(eckey->group)) == NULL) if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(eckey->group,order,ctx)) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; Loading @@ -138,38 +135,35 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, { /* get random k */ do if (!BN_rand_range(&k,order)) if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } while (BN_is_zero(&k)); while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(eckey->group, tmp_point, &k, NULL, NULL, ctx)) if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(eckey->group)) == NID_X9_62_prime_field) if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(eckey->group, if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(eckey->group, if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } Loading @@ -182,36 +176,34 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, while (BN_is_zero(r)); /* compute the inverse of k */ if ((kinv = BN_mod_inverse(NULL,&k,order,ctx)) == NULL) if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (*rp == NULL) /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); *rp = r; if (*kinvp == NULL) if (*kinvp != NULL) BN_clear_free(*kinvp); *kinvp = kinv; kinv = NULL; /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (kinv != NULL) BN_clear_free(kinv); if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (kinv != NULL) BN_clear_free(kinv); if (order != NULL) BN_clear_free(order); BN_free(order); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); BN_clear_free(&k); if (X) BN_clear_free(X); return(ret); } Loading @@ -219,32 +211,38 @@ err: static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, EC_KEY *eckey) { BIGNUM *kinv=NULL,*r=NULL,*s=NULL,*m=NULL,*tmp=NULL,*order=NULL; BIGNUM xr; int ok = 0; BIGNUM *kinv=NULL, *r, *s, *m=NULL,*tmp=NULL,*order=NULL; BN_CTX *ctx = NULL; ECDSA_SIG *ret=NULL; EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; BN_init(&xr); ecdsa = ecdsa_check(eckey); if (!eckey || !eckey->group || !eckey->pub_key || !eckey->priv_key || !ecdsa) if (!eckey->group || !eckey->pub_key || !eckey->priv_key || !ecdsa) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); goto err; return NULL; } group = eckey->group; ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL || (s = BN_new()) == NULL ) (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(eckey->group,order,ctx)) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; Loading @@ -256,7 +254,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, goto err; } if (BN_bin2bn(dgst,dgst_len,m) == NULL) if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; Loading @@ -265,18 +263,20 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, { if (ecdsa->kinv == NULL || ecdsa->r == NULL) { if (!ECDSA_sign_setup(eckey,ctx,&kinv,&r)) if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_ECDSA_LIB); ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB); goto err; } r = ret->r; } else { BN_free(ret->r); kinv = ecdsa->kinv; ecdsa->kinv = NULL; r = ecdsa->r; ret->r = r; ecdsa->kinv = NULL; ecdsa->r = NULL; } Loading @@ -285,13 +285,11 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_add(s,tmp,m)) if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_cmp(s,order) > 0) BN_sub(s,s,order); if (!BN_mod_mul(s, s, kinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); Loading @@ -300,23 +298,13 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, } while (BN_is_zero(s)); if ((ret = ECDSA_SIG_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (BN_copy(ret->r, r) == NULL || BN_copy(ret->s, s) == NULL) ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); } err: if (r) BN_clear_free(r); if (s) BN_clear_free(s); if (ctx) BN_CTX_free(ctx); if (m) Loading @@ -324,61 +312,69 @@ err: if (tmp) BN_clear_free(tmp); if (order) BN_clear_free(order); BN_free(order); if (kinv) BN_clear_free(kinv); return(ret); return ret; } static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1; BN_CTX *ctx; BIGNUM *order=NULL,*u1=NULL,*u2=NULL,*m=NULL,*X=NULL; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; int ret = -1; EC_GROUP *group; /* check input values */ if (!eckey || !eckey->group || !eckey->pub_key || !sig) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (u1 = BN_new()) == NULL || (u2 = BN_new()) == NULL || (m = BN_new()) == NULL || (X = BN_new()) == NULL) group = eckey->group; ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; return -1; } if (!EC_GROUP_get_order(eckey->group, order, ctx)) BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_is_zero(sig->r) || BN_get_sign(sig->r) || BN_ucmp(sig->r, order) >= 0) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->s) || BN_get_sign(sig->s) || BN_ucmp(sig->s, order) >= 0) if (BN_is_zero(sig->r) || BN_get_sign(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_get_sign(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if ((BN_mod_inverse(u2,sig->s,order,ctx)) == NULL) if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ if (BN_bin2bn(dgst,dgst_len,m) == NULL) if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; Loading @@ -396,20 +392,19 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, goto err; } if ((point = EC_POINT_new(eckey->group)) == NULL) if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(eckey->group, point, u1, eckey->pub_key, u2, ctx)) if (!EC_POINT_mul(group, point, u1, eckey->pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(eckey->group)) == NID_X9_62_prime_field) if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(eckey->group, if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); Loading @@ -418,7 +413,7 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(eckey->group, if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); Loading @@ -431,25 +426,12 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* is now in u1. If the signature is correct, it will be * equal to R. */ /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); if (u1) BN_clear_free(u1); if (u2) BN_clear_free(u2); if (m) BN_clear_free(m); if (X) BN_clear_free(X); if (order) BN_clear_free(order); if (point) EC_POINT_free(point); return(ret); return ret; } Loading
crypto/ecdsa/ecdsa.h +138 −15 Original line number Diff line number Diff line /* crypto/ecdsa/ecdsa.h */ /** * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions * \author Written by Nils Larsch for the OpenSSL project */ /* ==================================================================== * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -96,7 +100,7 @@ typedef struct ecdsa_data_st { /* EC_KEY_METH_DATA part */ int (*init)(EC_KEY *); void (*finish)(EC_KEY *); /* method specific part */ /* method (ECDSA) specific part */ BIGNUM *kinv; /* signing pre-calc */ BIGNUM *r; /* signing pre-calc */ ENGINE *engine; Loading @@ -105,38 +109,157 @@ typedef struct ecdsa_data_st { CRYPTO_EX_DATA ex_data; } ECDSA_DATA; /* signature functions */ /** ECDSA_SIG *ECDSA_SIG_new(void) * allocates and initialize a ECDSA_SIG structure * \return pointer to a ECDSA_SIG structure or NULL if an error occurred */ ECDSA_SIG *ECDSA_SIG_new(void); /** ECDSA_SIG_free * frees a ECDSA_SIG structure * \param a pointer to the ECDSA_SIG structure */ void ECDSA_SIG_free(ECDSA_SIG *a); /** i2d_ECDSA_SIG * DER encode content of ECDSA_SIG object (note: this function modifies *pp * (*pp += length of the DER encoded signature)). * \param a pointer to the ECDSA_SIG object * \param pp pointer to a unsigned char pointer for the output or NULL * \return the length of the DER encoded ECDSA_SIG object or 0 */ int i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **pp); ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long length); /* ECDSA_DATA functions */ /** d2i_ECDSA_SIG * decodes a DER encoded ECDSA signature (note: this function changes *pp * (*pp += len)). * \param v pointer to ECDSA_SIG pointer (may be NULL) * \param pp buffer with the DER encoded signature * \param len bufferlength * \return pointer to the decoded ECDSA_SIG structure (or NULL) */ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long len); /** ECDSA_DATA_new * creates a new ECDSA_DATA object * \return pointer to a newly allocated (and initialized) ECDSA_DATA object */ ECDSA_DATA *ECDSA_DATA_new(void); ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *); void ECDSA_DATA_free(ECDSA_DATA *); ECDSA_DATA *ecdsa_check(EC_KEY *); /** ECDSA_DATA_new_method * creates a new ECDSA_DATA object using a specified ENGINE * \param eng pointer to a ENGINE structure * \return pointer to a newly allocated (and initialized) ECDSA_DATA object */ ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *eng); /** ECDSA_DATA_free * frees ECDSA_DATA structure * \param data pointer to a ECDSA_DATA structure */ void ECDSA_DATA_free(ECDSA_DATA *data); /** ecdsa_check * checks whether ECKEY->meth_data is a pointer to a ECDSA_DATA structure * and if not it removes the old meth_data and creates a ECDSA_DATA structure. * \param eckey pointer to a EC_KEY object * \return pointer to a ECDSA_DATA structure */ ECDSA_DATA *ecdsa_check(EC_KEY *eckey); /** ECDSA_do_sign * computes the ECDSA signature of the given hash value using * the supplied private key and returns the created signature. * \param dgst pointer to the hash value * \param dgst_len length of the hash value * \param eckey pointer to the EC_KEY object containing a private EC key * \return pointer to a ECDSA_SIG structure or NULL */ ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,int dgst_len,EC_KEY *eckey); ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, EC_KEY *); /** ECDSA_do_verify * verifies that the supplied signature is a valid ECDSA * signature of the supplied hash value using the supplied public key. * \param dgst pointer to the hash value * \param dgst_len length of the hash value * \param sig pointer to the ECDSA_SIG structure * \param eckey pointer to the EC_KEY object containing a public EC key * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error */ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, ECDSA_SIG *sig, EC_KEY* eckey); const ECDSA_METHOD *ECDSA_OpenSSL(void); void ECDSA_set_default_method(const ECDSA_METHOD *); /** ECDSA_set_default_method * sets the default ECDSA method * \param meth the new default ECDSA_METHOD */ void ECDSA_set_default_method(const ECDSA_METHOD *meth); /** ECDSA_get_default_method * returns the default ECDSA method * \return pointer to ECDSA_METHOD structure containing the default method */ const ECDSA_METHOD *ECDSA_get_default_method(void); int ECDSA_set_method(EC_KEY *, const ECDSA_METHOD *); int ECDSA_size(const EC_KEY *); /** ECDSA_set_method * sets method to be used for the ECDSA operations * \param eckey pointer to the EC_KEY object * \param meth pointer to the new method * \return 1 on success and 0 otherwise */ int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth); /** ECDSA_size * returns the maximum length of the DER encoded signature * \param eckey pointer to a EC_KEY object * \return numbers of bytes required for the DER encoded signature */ int ECDSA_size(const EC_KEY *eckey); /** ECDSA_sign_setup * precompute parts of the signing operation (the computed values may be * passed to ECDSA_DATA->kinv and ECDSA_DATA->r for a later signature * computation). * \param eckey pointer to the EC_KEY object containing a private EC key * \param ctx pointer to a BN_CTX object (may be NULL) * \param kinv pointer to a BIGNUM pointer for the inverse of k * \param rp pointer to a BIGNUM pointer for x coordinate of k * generator * \return 1 on success and 0 otherwise */ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); int ECDSA_sign(int type, const unsigned char *dgst, int dgst_len, /** ECDSA_sign * computes ECDSA signature of a given hash value using the supplied * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). * \param type this parameter is ignored * \param dgst pointer to the hash value to sign * \param dgstlen length of the hash value * \param sig buffer to hold the DER encoded signature * \param siglen pointer to the length of the returned signature * \param eckey pointer to the EC_KEY object containing a private EC key * \return 1 on success and 0 otherwise */ int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sig, int sig_len, EC_KEY *eckey); /** ECDSA_verify * verifies that the given signature is valid ECDSA signature * of the supplied hash value using the specified public key. * \param type this parameter is ignored * \param dgst pointer to the hash value * \param dgstlen length of the hash value * \param sig pointer to the DER encoded signature * \param siglen length of the DER encoded signature * \param eckey pointer to the EC_KEY object containing a public EC key * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error */ int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, const unsigned char *sig, int siglen, EC_KEY *eckey); /* the standard ex_data functions */ int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg); Loading
crypto/ecdsa/ecs_ossl.c +116 −134 Original line number Diff line number Diff line /* crypto/ecdsa/ecs_ossl.c */ /* * Written by Nils Larsch for the OpenSSL project */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -86,49 +89,43 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx = NULL; BIGNUM k,*kinv=NULL,*r=NULL,*order=NULL,*X=NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point=NULL; EC_GROUP *group; int ret = 0; if (!eckey || !eckey->group || !eckey->pub_key || !eckey->priv_key) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } BN_init(&k); group = eckey->group; if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE); goto err; return 0; } } else ctx = ctx_in; if ((r = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if ((order = BN_new()) == NULL) k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if ((X = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(eckey->group)) == NULL) if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(eckey->group,order,ctx)) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; Loading @@ -138,38 +135,35 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, { /* get random k */ do if (!BN_rand_range(&k,order)) if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } while (BN_is_zero(&k)); while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(eckey->group, tmp_point, &k, NULL, NULL, ctx)) if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(eckey->group)) == NID_X9_62_prime_field) if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(eckey->group, if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(eckey->group, if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } Loading @@ -182,36 +176,34 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, while (BN_is_zero(r)); /* compute the inverse of k */ if ((kinv = BN_mod_inverse(NULL,&k,order,ctx)) == NULL) if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (*rp == NULL) /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); *rp = r; if (*kinvp == NULL) if (*kinvp != NULL) BN_clear_free(*kinvp); *kinvp = kinv; kinv = NULL; /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (kinv != NULL) BN_clear_free(kinv); if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (kinv != NULL) BN_clear_free(kinv); if (order != NULL) BN_clear_free(order); BN_free(order); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); BN_clear_free(&k); if (X) BN_clear_free(X); return(ret); } Loading @@ -219,32 +211,38 @@ err: static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, EC_KEY *eckey) { BIGNUM *kinv=NULL,*r=NULL,*s=NULL,*m=NULL,*tmp=NULL,*order=NULL; BIGNUM xr; int ok = 0; BIGNUM *kinv=NULL, *r, *s, *m=NULL,*tmp=NULL,*order=NULL; BN_CTX *ctx = NULL; ECDSA_SIG *ret=NULL; EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; BN_init(&xr); ecdsa = ecdsa_check(eckey); if (!eckey || !eckey->group || !eckey->pub_key || !eckey->priv_key || !ecdsa) if (!eckey->group || !eckey->pub_key || !eckey->priv_key || !ecdsa) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); goto err; return NULL; } group = eckey->group; ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL || (s = BN_new()) == NULL ) (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(eckey->group,order,ctx)) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; Loading @@ -256,7 +254,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, goto err; } if (BN_bin2bn(dgst,dgst_len,m) == NULL) if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; Loading @@ -265,18 +263,20 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, { if (ecdsa->kinv == NULL || ecdsa->r == NULL) { if (!ECDSA_sign_setup(eckey,ctx,&kinv,&r)) if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_ECDSA_LIB); ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB); goto err; } r = ret->r; } else { BN_free(ret->r); kinv = ecdsa->kinv; ecdsa->kinv = NULL; r = ecdsa->r; ret->r = r; ecdsa->kinv = NULL; ecdsa->r = NULL; } Loading @@ -285,13 +285,11 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_add(s,tmp,m)) if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_cmp(s,order) > 0) BN_sub(s,s,order); if (!BN_mod_mul(s, s, kinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); Loading @@ -300,23 +298,13 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, } while (BN_is_zero(s)); if ((ret = ECDSA_SIG_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (BN_copy(ret->r, r) == NULL || BN_copy(ret->s, s) == NULL) ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); } err: if (r) BN_clear_free(r); if (s) BN_clear_free(s); if (ctx) BN_CTX_free(ctx); if (m) Loading @@ -324,61 +312,69 @@ err: if (tmp) BN_clear_free(tmp); if (order) BN_clear_free(order); BN_free(order); if (kinv) BN_clear_free(kinv); return(ret); return ret; } static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1; BN_CTX *ctx; BIGNUM *order=NULL,*u1=NULL,*u2=NULL,*m=NULL,*X=NULL; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; int ret = -1; EC_GROUP *group; /* check input values */ if (!eckey || !eckey->group || !eckey->pub_key || !sig) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (u1 = BN_new()) == NULL || (u2 = BN_new()) == NULL || (m = BN_new()) == NULL || (X = BN_new()) == NULL) group = eckey->group; ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; return -1; } if (!EC_GROUP_get_order(eckey->group, order, ctx)) BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_is_zero(sig->r) || BN_get_sign(sig->r) || BN_ucmp(sig->r, order) >= 0) if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->s) || BN_get_sign(sig->s) || BN_ucmp(sig->s, order) >= 0) if (BN_is_zero(sig->r) || BN_get_sign(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_get_sign(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if ((BN_mod_inverse(u2,sig->s,order,ctx)) == NULL) if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ if (BN_bin2bn(dgst,dgst_len,m) == NULL) if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; Loading @@ -396,20 +392,19 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, goto err; } if ((point = EC_POINT_new(eckey->group)) == NULL) if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(eckey->group, point, u1, eckey->pub_key, u2, ctx)) if (!EC_POINT_mul(group, point, u1, eckey->pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(eckey->group)) == NID_X9_62_prime_field) if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(eckey->group, if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); Loading @@ -418,7 +413,7 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(eckey->group, if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); Loading @@ -431,25 +426,12 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* is now in u1. If the signature is correct, it will be * equal to R. */ /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); if (u1) BN_clear_free(u1); if (u2) BN_clear_free(u2); if (m) BN_clear_free(m); if (X) BN_clear_free(X); if (order) BN_clear_free(order); if (point) EC_POINT_free(point); return(ret); return ret; }