diff options
author | Bodo Möller <bodo@openssl.org> | 2002-08-07 10:49:54 +0000 |
---|---|---|
committer | Bodo Möller <bodo@openssl.org> | 2002-08-07 10:49:54 +0000 |
commit | 14a7cfb32a0347a4bc620ae1b552b21c4c1e270b (patch) | |
tree | 13c4bcc3d58ba7db5e598cd668670873b51e8ce3 /crypto/ec | |
parent | 7a8645d1716d7f84435b0f3d8d2fd122d6f75113 (diff) |
use a generic EC_KEY structure (EC keys are not ECDSA specific)
Submitted by: Nils Larsch
Diffstat (limited to 'crypto/ec')
-rw-r--r-- | crypto/ec/Makefile.ssl | 16 | ||||
-rw-r--r-- | crypto/ec/ec.h | 102 | ||||
-rw-r--r-- | crypto/ec/ec_asn1.c | 393 | ||||
-rw-r--r-- | crypto/ec/ec_err.c | 23 | ||||
-rw-r--r-- | crypto/ec/ec_key.c | 354 |
5 files changed, 803 insertions, 85 deletions
diff --git a/crypto/ec/Makefile.ssl b/crypto/ec/Makefile.ssl index fbc80ff05e..d183f679c4 100644 --- a/crypto/ec/Makefile.ssl +++ b/crypto/ec/Makefile.ssl @@ -23,12 +23,12 @@ TEST=ectest.c APPS= LIB=$(TOP)/libcrypto.a -LIBSRC= ec_lib.c ecp_smpl.c ecp_mont.c ecp_recp.c ecp_nist.c ec_cvt.c ec_mult.c \ - ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c \ +LIBSRC= ec_lib.c ecp_smpl.c ecp_mont.c ecp_recp.c ecp_nist.c ec_cvt.c ec_mult.c\ + ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c\ ec2_smpl.c ec2_smpt.c ec2_mult.c -LIBOBJ= ec_lib.o ecp_smpl.o ecp_mont.o ecp_recp.o ecp_nist.o ec_cvt.o ec_mult.o \ - ec_err.o ec_curve.o ec_check.o ec_print.o ec_asn1.o \ +LIBOBJ= ec_lib.o ecp_smpl.o ecp_mont.o ecp_recp.o ecp_nist.o ec_cvt.o ec_mult.o\ + ec_err.o ec_curve.o ec_check.o ec_print.o ec_asn1.o ec_key.o\ ec2_smpl.o ec2_mult.o SRC= $(LIBSRC) @@ -142,6 +142,14 @@ ec_err.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h ec_err.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h ec_err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h ec_err.o: ec_err.c +ec_key.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +ec_key.o: ../../include/openssl/bn.h ../../include/openssl/crypto.h +ec_key.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +ec_key.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +ec_key.o: ../../include/openssl/obj_mac.h ../../include/openssl/opensslconf.h +ec_key.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +ec_key.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +ec_key.o: ../../include/openssl/symhacks.h ec_key.c ec_lcl.h ec_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h ec_lib.o: ../../include/openssl/bn.h ../../include/openssl/crypto.h ec_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index ff9af9f8e4..4a1787f0b7 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -334,21 +334,8 @@ int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *); /* ASN1 stuff */ #define OPENSSL_EC_NAMED_CURVE 0x001 -typedef struct ec_parameters_st ECPARAMETERS; typedef struct ecpk_parameters_st ECPKPARAMETERS; -DECLARE_ASN1_ITEM(ECPARAMETERS) -DECLARE_ASN1_ITEM(ECPKPARAMETERS) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPARAMETERS, ECPARAMETERS) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) - -EC_GROUP *EC_ASN1_pkparameters2group(const ECPKPARAMETERS *); -ECPKPARAMETERS *EC_ASN1_group2pkparameters(const EC_GROUP *, ECPKPARAMETERS *); - - -EC_GROUP *d2i_ECParameters(EC_GROUP **, const unsigned char **in, long len); -int i2d_ECParameters(const EC_GROUP *, unsigned char **out); - EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); @@ -368,18 +355,65 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); #endif -/* SEC1 ECPrivateKey */ -typedef struct ec_privatekey_st { - int version; - ASN1_OCTET_STRING *privateKey; - ECPKPARAMETERS *parameters; - ASN1_BIT_STRING *publicKey; - } EC_PRIVATEKEY; +/* the EC_KEY stuff */ +typedef struct ec_key_st EC_KEY; + +typedef struct ec_key_meth_data_st { + int (*init)(EC_KEY *); + void (*finish)(EC_KEY *); + } EC_KEY_METH_DATA; + +struct ec_key_st { + int version; + + EC_GROUP *group; + + EC_POINT *pub_key; + BIGNUM *priv_key; + + unsigned int enc_flag; + point_conversion_form_t conv_form; + + int references; -DECLARE_ASN1_ITEM(EC_PRIVATEKEY) -DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) + EC_KEY_METH_DATA *meth_data; + }/* EC_KEY */; +/* some values for the encoding_flag */ +#define EC_PKEY_NO_PARAMETERS 0x001 +#define EC_PKEY_NO_PUBKEY 0x002 + +EC_KEY *EC_KEY_new(void); +void EC_KEY_free(EC_KEY *); +EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *); +EC_KEY *EC_KEY_dup(const EC_KEY *); + +/* EC_KEY_generate_key() creates a ec private (public) key */ +int EC_KEY_generate_key(EC_KEY *); +/* EC_KEY_check_key() */ +int EC_KEY_check_key(const EC_KEY *); + +/* de- and encode functions for the SEC1 ECPrivateKey */ +EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len); +int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out); +/* de- and encode functions for the elliptic curve parameters */ +EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len); +int i2d_ECParameters(EC_KEY *a, unsigned char **out); + +EC_KEY *ECPublicKey_set_octet_string(EC_KEY **a, const unsigned char **in, + long len); +int ECPublicKey_get_octet_string(EC_KEY *a, unsigned char **out); + +#ifndef OPENSSL_NO_BIO +int ECParameters_print(BIO *bp, const EC_KEY *x); +int EC_KEY_print(BIO *bp, const EC_KEY *x, int off); +#endif +#ifndef OPENSSL_NO_FP_API +int ECParameters_print_fp(FILE *fp, const EC_KEY *x); +int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off); +#endif +#define ECParameters_dup(x) (EC_KEY *)ASN1_dup((int (*)())i2d_ECParameters,\ + (char *(*)())d2i_ECParameters,(char *)(x)) /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes @@ -391,11 +425,15 @@ void ERR_load_EC_strings(void); /* Function codes. */ #define EC_F_COMPUTE_WNAF 143 -#define EC_F_D2I_ECDSAPARAMETERS 154 #define EC_F_D2I_ECPARAMETERS 155 #define EC_F_D2I_ECPKPARAMETERS 161 +#define EC_F_D2I_ECPRIVATEKEY 168 +#define EC_F_ECPARAMETERS_PRINT 173 +#define EC_F_ECPARAMETERS_PRINT_FP 174 #define EC_F_ECPKPARAMETERS_PRINT 166 #define EC_F_ECPKPARAMETERS_PRINT_FP 167 +#define EC_F_ECPUBLICKEY_GET_OCTET 170 +#define EC_F_ECPUBLICKEY_SET_OCTET 171 #define EC_F_EC_ASN1_GROUP2CURVE 159 #define EC_F_EC_ASN1_GROUP2FIELDID 156 #define EC_F_EC_ASN1_GROUP2PARAMETERS 160 @@ -419,9 +457,9 @@ void ERR_load_EC_strings(void); #define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 #define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 #define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 -#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 105 -#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 128 -#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 129 +#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 105 +#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 128 +#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 129 #define EC_F_EC_GROUP_CHECK 150 #define EC_F_EC_GROUP_CHECK_DISCRIMINANT 153 #define EC_F_EC_GROUP_COPY 106 @@ -443,6 +481,12 @@ void ERR_load_EC_strings(void); #define EC_F_EC_GROUP_SET_CURVE_GFP 109 #define EC_F_EC_GROUP_SET_EXTRA_DATA 110 #define EC_F_EC_GROUP_SET_GENERATOR 111 +#define EC_F_EC_KEY_CHECK_KEY 184 +#define EC_F_EC_KEY_COPY 186 +#define EC_F_EC_KEY_GENERATE_KEY 185 +#define EC_F_EC_KEY_PRINT 175 +#define EC_F_EC_KEY_PRINT_FP 176 +#define EC_F_EC_NEW 172 #define EC_F_EC_POINTS_MAKE_AFFINE 136 #define EC_F_EC_POINTS_MUL 138 #define EC_F_EC_POINT_ADD 112 @@ -471,6 +515,7 @@ void ERR_load_EC_strings(void); #define EC_F_I2D_ECDSAPARAMETERS 158 #define EC_F_I2D_ECPARAMETERS 164 #define EC_F_I2D_ECPKPARAMETERS 165 +#define EC_F_I2D_ECPRIVATEKEY 169 /* Reason codes. */ #define EC_R_ASN1_ERROR 130 @@ -493,7 +538,9 @@ void ERR_load_EC_strings(void); #define EC_R_INVALID_FIELD 103 #define EC_R_INVALID_FORM 104 #define EC_R_INVALID_GROUP_ORDER 119 +#define EC_R_INVALID_PRIVATE_KEY 139 #define EC_R_MISSING_PARAMETERS 127 +#define EC_R_MISSING_PRIVATE_KEY 138 #define EC_R_NOT_IMPLEMENTED 136 #define EC_R_NOT_INITIALIZED 111 #define EC_R_NO_SUCH_EXTRA_DATA 105 @@ -508,6 +555,7 @@ void ERR_load_EC_strings(void); #define EC_R_UNKNOWN_NID 117 #define EC_R_UNKNOWN_ORDER 114 #define EC_R_UNKNOWN_PARAMETERS_TYPE 129 +#define EC_R_WRONG_ORDER 140 #ifdef __cplusplus } diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 90b64b0e04..bb81cfb3c3 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -82,14 +82,14 @@ typedef struct x9_62_curve_st { ASN1_BIT_STRING *seed; } X9_62_CURVE; -struct ec_parameters_st { +typedef struct ec_parameters_st { ASN1_INTEGER *version; X9_62_FIELDID *fieldID; X9_62_CURVE *curve; ASN1_OCTET_STRING *base; ASN1_INTEGER *order; ASN1_INTEGER *cofactor; - }/* ECPARAMETERS */; + } ECPARAMETERS; struct ecpk_parameters_st { int type; @@ -100,6 +100,14 @@ struct ecpk_parameters_st { } value; }/* ECPKPARAMETERS */; +/* SEC1 ECPrivateKey */ +typedef struct ec_privatekey_st { + int version; + ASN1_OCTET_STRING *privateKey; + ECPKPARAMETERS *parameters; + ASN1_BIT_STRING *publicKey; + } EC_PRIVATEKEY; + /* the OpenSSL asn1 definitions */ ASN1_SEQUENCE(X9_62_FIELDID) = { @@ -151,6 +159,7 @@ ASN1_SEQUENCE(ECPARAMETERS) = { } ASN1_SEQUENCE_END(ECPARAMETERS) DECLARE_ASN1_FUNCTIONS_const(ECPARAMETERS) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPARAMETERS, ECPARAMETERS) IMPLEMENT_ASN1_FUNCTIONS_const(ECPARAMETERS) ASN1_CHOICE(ECPKPARAMETERS) = { @@ -160,15 +169,18 @@ ASN1_CHOICE(ECPKPARAMETERS) = { } ASN1_CHOICE_END(ECPKPARAMETERS) DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) ASN1_SEQUENCE(EC_PRIVATEKEY) = { ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), - ASN1_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS), - ASN1_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING) + ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), + ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) } ASN1_SEQUENCE_END(EC_PRIVATEKEY) +DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) /* some internal functions */ @@ -178,6 +190,8 @@ static X9_62_CURVE *ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, ECPARAMETERS *); +EC_GROUP *EC_ASN1_pkparameters2group(const ECPKPARAMETERS *); +ECPKPARAMETERS *EC_ASN1_group2pkparameters(const EC_GROUP *, ECPKPARAMETERS *); static X9_62_FIELDID *ec_asn1_group2field(const EC_GROUP *group, X9_62_FIELDID *field) @@ -786,34 +800,7 @@ EC_GROUP *EC_ASN1_pkparameters2group(const ECPKPARAMETERS *params) return ret; } -/* EC_GROUP <-> DER encoding of EC[PK]PARAMETERS */ - -EC_GROUP *d2i_ECParameters(EC_GROUP **a, const unsigned char **in, long len) - { - EC_GROUP *group = NULL; - ECPARAMETERS *params = NULL; - - if ((params = d2i_ECPARAMETERS(NULL, in, len)) == NULL) - { - ECerr(EC_F_D2I_ECPARAMETERS, EC_R_D2I_ECPARAMETERS_FAILURE); - ECPARAMETERS_free(params); - return NULL; - } - - if ((group = ec_asn1_parameters2group(params)) == NULL) - { - ECerr(EC_F_D2I_ECPARAMETERS, EC_R_PARAMETERS2GROUP_FAILURE); - return NULL; - } - - if (a && *a) - EC_GROUP_clear_free(*a); - if (a) - *a = group; - - ECPARAMETERS_free(params); - return(group); - } +/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) { @@ -843,40 +830,346 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) return(group); } -int i2d_ECParameters(const EC_GROUP *a, unsigned char **out) +int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) { int ret=0; - ECPARAMETERS *tmp = ec_asn1_group2parameters(a, NULL); + ECPKPARAMETERS *tmp = EC_ASN1_group2pkparameters(a, NULL); if (tmp == NULL) { - ECerr(EC_F_I2D_ECPARAMETERS, EC_R_GROUP2PARAMETERS_FAILURE); + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); return 0; } - if ((ret = i2d_ECPARAMETERS(tmp, out)) == 0) + if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { - ECerr(EC_F_I2D_ECPARAMETERS, EC_R_I2D_EC_PARAMETERS_FAILURE); - ECPARAMETERS_free(tmp); + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); + ECPKPARAMETERS_free(tmp); return 0; } - ECPARAMETERS_free(tmp); + ECPKPARAMETERS_free(tmp); return(ret); } -int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) +/* some EC_KEY functions */ + +EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) { - int ret=0; - ECPKPARAMETERS *tmp = EC_ASN1_group2pkparameters(a, NULL); - if (tmp == NULL) + int ok=0; + EC_KEY *ret=NULL; + EC_PRIVATEKEY *priv_key=NULL; + + if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + EC_PRIVATEKEY_free(priv_key); + return NULL; + } + + if (a == NULL || *a == NULL) + { + if ((ret = EC_KEY_new()) == NULL) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (a) + *a = ret; + } + else + ret = *a; + + if (priv_key->parameters) + { + if (ret->group) + EC_GROUP_clear_free(ret->group); + ret->group = EC_ASN1_pkparameters2group(priv_key->parameters); + } + + if (ret->group == NULL) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + ret->version = priv_key->version; + + if (priv_key->privateKey) + { + ret->priv_key = BN_bin2bn( + M_ASN1_STRING_data(priv_key->privateKey), + M_ASN1_STRING_length(priv_key->privateKey), + ret->priv_key); + if (ret->priv_key == NULL) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, + ERR_R_BN_LIB); + goto err; + } + } + else + { + ECerr(EC_F_D2I_ECPRIVATEKEY, + EC_R_MISSING_PRIVATE_KEY); + goto err; + } + + if (priv_key->publicKey) + { + if (ret->pub_key) + EC_POINT_clear_free(ret->pub_key); + ret->pub_key = EC_POINT_new(ret->group); + if (ret->pub_key == NULL) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_oct2point(ret->group, ret->pub_key, + M_ASN1_STRING_data(priv_key->publicKey), + M_ASN1_STRING_length(priv_key->publicKey), NULL)) + { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } + + ok = 1; +err: + if (!ok) + { + if (ret) + EC_KEY_free(ret); + ret = NULL; + } + + if (priv_key) + EC_PRIVATEKEY_free(priv_key); + + return(ret); + } + +int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) + { + int ret=0, ok=0; + unsigned char *buffer=NULL; + size_t buf_len=0, tmp_len; + EC_PRIVATEKEY *priv_key=NULL; + + if (a == NULL || a->group == NULL || a->priv_key == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, + ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if ((priv_key = EC_PRIVATEKEY_new()) == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + priv_key->version = a->version; + + buf_len = (size_t)BN_num_bytes(a->priv_key); + buffer = OPENSSL_malloc(buf_len); + if (buffer == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BN_bn2bin(a->priv_key, buffer)) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); + goto err; + } + + if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); + goto err; + } + + if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) + { + if ((priv_key->parameters = EC_ASN1_group2pkparameters( + a->group, priv_key->parameters)) == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } + + if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) + { + priv_key->publicKey = M_ASN1_BIT_STRING_new(); + if (priv_key->publicKey == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + tmp_len = EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, NULL, 0, NULL); + + if (tmp_len > buf_len) + buffer = OPENSSL_realloc(buffer, tmp_len); + if (buffer == NULL) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + buf_len = tmp_len; + + if (!EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, buffer, buf_len, NULL)) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, + buf_len)) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); + goto err; + } + } + + if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) + { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + ok=1; +err: + if (buffer) + OPENSSL_free(buffer); + if (priv_key) + EC_PRIVATEKEY_free(priv_key); + return(ok?ret:0); + } + +int i2d_ECParameters(EC_KEY *a, unsigned char **out) + { + if (a == NULL) + { + ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) + return i2d_ECPKParameters(a->group, out); + } + +EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) + { + EC_GROUP *group; + EC_KEY *ret; + + if (in == NULL || *in == NULL) { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); - ECPKPARAMETERS_free(tmp); + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + group = d2i_ECPKParameters(NULL, in, len); + + if (group == NULL) + { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); + return NULL; + } + + if (a == NULL || *a == NULL) + { + if ((ret = EC_KEY_new()) == NULL) + { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (a) + *a = ret; + } + else + ret = *a; + + if (ret->group) + EC_GROUP_clear_free(ret->group); + + ret->group = group; + + return ret; + } + +EC_KEY *ECPublicKey_set_octet_string(EC_KEY **a, const unsigned char **in, + long len) + { + EC_KEY *ret=NULL; + + if (a == NULL || (*a) == NULL || (*a)->group == NULL) + { + /* sorry, but a EC_GROUP-structur is necessary + * to set the public key */ + ECerr(EC_F_ECPUBLICKEY_SET_OCTET, ERR_R_PASSED_NULL_PARAMETER); return 0; - } - ECPKPARAMETERS_free(tmp); - return(ret); + } + ret = *a; + if (ret->pub_key == NULL && + (ret->pub_key = EC_POINT_new(ret->group)) == NULL) + { + ECerr(EC_F_ECPUBLICKEY_SET_OCTET, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) + { + ECerr(EC_F_ECPUBLICKEY_SET_OCTET, ERR_R_EC_LIB); + return 0; + } + /* save the point conversion form */ + ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01); + return ret; + } + +int ECPublicKey_get_octet_string(EC_KEY *a, unsigned char **out) + { + size_t buf_len=0; + + if (a == NULL) + { + ECerr(EC_F_ECPUBLICKEY_GET_OCTET, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + buf_len = EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, NULL, 0, NULL); + + if (out == NULL || buf_len == 0) + /* out == NULL => just return the length of the octet string */ + return buf_len; + + if (*out == NULL) + if ((*out = OPENSSL_malloc(buf_len)) == NULL) + { + ECerr(EC_F_ECPUBLICKEY_GET_OCTET, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, + *out, buf_len, NULL)) + { + ECerr(EC_F_ECPUBLICKEY_GET_OCTET, ERR_R_EC_LIB); + OPENSSL_free(*out); + *out = NULL; + return 0; + } + return buf_len; } diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index c5ff12b366..8626ef0d3a 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -67,17 +67,21 @@ static ERR_STRING_DATA EC_str_functs[]= { {ERR_PACK(0,EC_F_COMPUTE_WNAF,0), "COMPUTE_WNAF"}, -{ERR_PACK(0,EC_F_D2I_ECDSAPARAMETERS,0), "d2i_ECDSAParameters"}, {ERR_PACK(0,EC_F_D2I_ECPARAMETERS,0), "d2i_ECParameters"}, {ERR_PACK(0,EC_F_D2I_ECPKPARAMETERS,0), "d2i_ECPKParameters"}, +{ERR_PACK(0,EC_F_D2I_ECPRIVATEKEY,0), "d2i_ECPrivateKey"}, +{ERR_PACK(0,EC_F_ECPARAMETERS_PRINT,0), "ECParameters_print"}, +{ERR_PACK(0,EC_F_ECPARAMETERS_PRINT_FP,0), "ECParameters_print_fp"}, {ERR_PACK(0,EC_F_ECPKPARAMETERS_PRINT,0), "ECPKParameters_print"}, {ERR_PACK(0,EC_F_ECPKPARAMETERS_PRINT_FP,0), "ECPKParameters_print_fp"}, +{ERR_PACK(0,EC_F_ECPUBLICKEY_GET_OCTET,0), "ECPUBLICKEY_GET_OCTET"}, +{ERR_PACK(0,EC_F_ECPUBLICKEY_SET_OCTET,0), "ECPUBLICKEY_SET_OCTET"}, {ERR_PACK(0,EC_F_EC_ASN1_GROUP2CURVE,0), "EC_ASN1_GROUP2CURVE"}, {ERR_PACK(0,EC_F_EC_ASN1_GROUP2FIELDID,0), "EC_ASN1_GROUP2FIELDID"}, {ERR_PACK(0,EC_F_EC_ASN1_GROUP2PARAMETERS,0), "EC_ASN1_GROUP2PARAMETERS"}, -{ERR_PACK(0,EC_F_EC_ASN1_GROUP2PKPARAMETERS,0), "EC_ASN1_group2pkparameters"}, +{ERR_PACK(0,EC_F_EC_ASN1_GROUP2PKPARAMETERS,0), "EC_ASN1_GROUP2PKPARAMETERS"}, {ERR_PACK(0,EC_F_EC_ASN1_PARAMETERS2GROUP,0), "EC_ASN1_PARAMETERS2GROUP"}, -{ERR_PACK(0,EC_F_EC_ASN1_PKPARAMETERS2GROUP,0), "EC_ASN1_pkparameters2group"}, +{ERR_PACK(0,EC_F_EC_ASN1_PKPARAMETERS2GROUP,0), "EC_ASN1_PKPARAMETERS2GROUP"}, {ERR_PACK(0,EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,0), "ec_GF2m_simple_group_check_discriminant"}, {ERR_PACK(0,EC_F_EC_GF2M_SIMPLE_OCT2POINT,0), "ec_GF2m_simple_oct2point"}, {ERR_PACK(0,EC_F_EC_GF2M_SIMPLE_POINT2OCT,0), "ec_GF2m_simple_point2oct"}, @@ -119,12 +123,19 @@ static ERR_STRING_DATA EC_str_functs[]= {ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0), "EC_GROUP_set_curve_GFp"}, {ERR_PACK(0,EC_F_EC_GROUP_SET_EXTRA_DATA,0), "EC_GROUP_set_extra_data"}, {ERR_PACK(0,EC_F_EC_GROUP_SET_GENERATOR,0), "EC_GROUP_set_generator"}, +{ERR_PACK(0,EC_F_EC_KEY_CHECK_KEY,0), "EC_KEY_check_key"}, +{ERR_PACK(0,EC_F_EC_KEY_COPY,0), "EC_KEY_copy"}, +{ERR_PACK(0,EC_F_EC_KEY_GENERATE_KEY,0), "EC_KEY_generate_key"}, +{ERR_PACK(0,EC_F_EC_KEY_PRINT,0), "EC_KEY_print"}, +{ERR_PACK(0,EC_F_EC_KEY_PRINT_FP,0), "EC_KEY_print_fp"}, +{ERR_PACK(0,EC_F_EC_NEW,0), "EC_NEW"}, {ERR_PACK(0,EC_F_EC_POINTS_MAKE_AFFINE,0), "EC_POINTs_make_affine"}, {ERR_PACK(0,EC_F_EC_POINTS_MUL,0), "EC_POINTs_mul"}, {ERR_PACK(0,EC_F_EC_POINT_ADD,0), "EC_POINT_add"}, {ERR_PACK(0,EC_F_EC_POINT_CMP,0), "EC_POINT_cmp"}, {ERR_PACK(0,EC_F_EC_POINT_COPY,0), "EC_POINT_copy"}, {ERR_PACK(0,EC_F_EC_POINT_DBL,0), "EC_POINT_dbl"}, +{ERR_PACK(0,EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,0), "EC_POINT_get_affine_coordinates_GF2m"}, {ERR_PACK(0,EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,0), "EC_POINT_get_affine_coordinates_GFp"}, {ERR_PACK(0,EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,0), "EC_POINT_get_Jprojective_coordinates_GFp"}, {ERR_PACK(0,EC_F_EC_POINT_IS_AT_INFINITY,0), "EC_POINT_is_at_infinity"}, @@ -143,9 +154,10 @@ static ERR_STRING_DATA EC_str_functs[]= {ERR_PACK(0,EC_F_EC_WNAF_MUL,0), "ec_wNAF_mul"}, {ERR_PACK(0,EC_F_EC_WNAF_PRECOMPUTE_MULT,0), "ec_wNAF_precompute_mult"}, {ERR_PACK(0,EC_F_GFP_MONT_GROUP_SET_CURVE,0), "GFP_MONT_GROUP_SET_CURVE"}, -{ERR_PACK(0,EC_F_I2D_ECDSAPARAMETERS,0), "i2d_ECDSAParameters"}, +{ERR_PACK(0,EC_F_I2D_ECDSAPARAMETERS,0), "I2D_ECDSAPARAMETERS"}, {ERR_PACK(0,EC_F_I2D_ECPARAMETERS,0), "i2d_ECParameters"}, {ERR_PACK(0,EC_F_I2D_ECPKPARAMETERS,0), "i2d_ECPKParameters"}, +{ERR_PACK(0,EC_F_I2D_ECPRIVATEKEY,0), "i2d_ECPrivateKey"}, {0,NULL} }; @@ -171,7 +183,9 @@ static ERR_STRING_DATA EC_str_reasons[]= {EC_R_INVALID_FIELD ,"invalid field"}, {EC_R_INVALID_FORM ,"invalid form"}, {EC_R_INVALID_GROUP_ORDER ,"invalid group order"}, +{EC_R_INVALID_PRIVATE_KEY ,"invalid private key"}, {EC_R_MISSING_PARAMETERS ,"missing parameters"}, +{EC_R_MISSING_PRIVATE_KEY ,"missing private key"}, {EC_R_NOT_IMPLEMENTED ,"not implemented"}, {EC_R_NOT_INITIALIZED ,"not initialized"}, {EC_R_NO_SUCH_EXTRA_DATA ,"no such extra data"}, @@ -186,6 +200,7 @@ static ERR_STRING_DATA EC_str_reasons[]= {EC_R_UNKNOWN_NID ,"unknown nid"}, {EC_R_UNKNOWN_ORDER ,"unknown order"}, {EC_R_UNKNOWN_PARAMETERS_TYPE ,"unknown parameters type"}, +{EC_R_WRONG_ORDER ,"wrong order"}, {0,NULL} }; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c new file mode 100644 index 0000000000..790d930225 --- /dev/null +++ b/crypto/ec/ec_key.c @@ -0,0 +1,354 @@ +/* crypto/ec/ec_key.c */ +/* + * Written by Nils Larsch for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ec_lcl.h" +#include <openssl/err.h> + +EC_KEY *EC_KEY_new(void) + { + EC_KEY *ret; + + ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); + if (ret == NULL) + { + ECerr(EC_F_EC_NEW, ERR_R_MALLOC_FAILURE); + return(NULL); + } + + ret->version = 1; + ret->group = NULL; + ret->pub_key = NULL; + ret->priv_key= NULL; + ret->enc_flag= 0; + ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; + ret->references= 1; + ret->meth_data = NULL; + return(ret); + } + + +void EC_KEY_free(EC_KEY *r) + { + int i; + + if (r == NULL) return; + + i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC); +#ifdef REF_PRINT + REF_PRINT("EC_KEY",r); +#endif + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"EC_KEY_free, bad reference count\n"); + abort(); + } +#endif + + if (r->group != NULL) + EC_GROUP_free(r->group); + if (r->pub_key != NULL) + EC_POINT_free(r->pub_key); + if (r->priv_key != NULL) + BN_clear_free(r->priv_key); + + if (r->meth_data && r->meth_data->finish) + r->meth_data->finish(r); + + memset((void *)r, 0x0, sizeof(EC_KEY)); + + OPENSSL_free(r); + } + +EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) + { + if (dest == NULL || src == NULL) + { + ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* copy the parameters */ + if (src->group) + { + const EC_METHOD *meth = EC_GROUP_method_of(src->group); + /* clear the old group */ + if (dest->group) + EC_GROUP_free(dest->group); + dest->group = EC_GROUP_new(meth); + if (dest->group == NULL) + return NULL; + if (!EC_GROUP_copy(dest->group, src->group)) + return NULL; + } + /* copy the public key */ + if (src->pub_key && src->group) + { + if (dest->pub_key) + EC_POINT_free(dest->pub_key); + dest->pub_key = EC_POINT_new(src->group); + if (dest->pub_key == NULL) + return NULL; + if (!EC_POINT_copy(dest->pub_key, src->pub_key)) + return NULL; + } + /* copy the private key */ + if (src->priv_key) + { + if (dest->priv_key == NULL) + { + dest->priv_key = BN_new(); + if (dest->priv_key == NULL) + return NULL; + } + if (!BN_copy(dest->priv_key, src->priv_key)) + return NULL; + } + /* copy the rest */ + dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; + dest->version = src->version; + + return dest; + } + +EC_KEY *EC_KEY_dup(const EC_KEY *eckey) + { + EC_KEY *ret = NULL; + int ok = 1; + + ret = EC_KEY_new(); + if (ret == NULL) + return NULL; + /* copy the parameters */ + if (eckey->group) + { + ret->group = EC_GROUP_dup(eckey->group); + if (ret->group == NULL) + ok = 0; + } + /* copy the public key */ + if (eckey->pub_key && eckey->group) + { + ret->pub_key = EC_POINT_dup(eckey->pub_key, eckey->group); + if (ret->pub_key == NULL) + ok = 0; + } + /* copy the private key */ + if (eckey->priv_key) + { + ret->priv_key = BN_dup(ret->priv_key); + if (ret->priv_key == NULL) + ok = 0; + } + /* copy the rest */ + ret->enc_flag = eckey->enc_flag; + ret->conv_form = eckey->conv_form; + ret->version = eckey->version; + + if (!ok) + { + EC_KEY_free(ret); + ret = NULL; + } + + return ret; + } + +int EC_KEY_generate_key(EC_KEY *eckey) + { + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *priv_key = NULL, *order = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey || !eckey->group) + { + ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if ((order = BN_new()) == NULL) goto err; + if ((ctx = BN_CTX_new()) == NULL) goto err; + + if (eckey->priv_key == NULL) + { + priv_key = BN_new(); + if (priv_key == NULL) + goto err; + } + else + priv_key = eckey->priv_key; + + if (!EC_GROUP_get_order(eckey->group, order, ctx)) + goto err; + + do + if (!BN_rand_range(priv_key, order)) + goto err; + while (BN_is_zero(priv_key)); + + if (eckey->pub_key == NULL) + { + pub_key = EC_POINT_new(eckey->group); + if (pub_key == NULL) + goto err; + } + else + pub_key = eckey->pub_key; + |