mirror of
https://github.com/openssl/openssl.git
synced 2025-04-06 20:20:50 +08:00
Provisional support for EC pkey method, supporting ECDH and ECDSA.
This commit is contained in:
parent
ba3b2f1538
commit
9ca7047d71
3
CHANGES
3
CHANGES
@ -4,6 +4,9 @@
|
||||
|
||||
Changes between 0.9.8a and 0.9.9 [xx XXX xxxx]
|
||||
|
||||
*) Add provisional EC pkey method with support for ECDSA and ECDH.
|
||||
[Steve Henson]
|
||||
|
||||
*) Add support for key derivation (agreement) in the API, DH method and
|
||||
pkeyutl.
|
||||
[Steve Henson]
|
||||
|
@ -19,11 +19,11 @@ APPS=
|
||||
LIB=$(TOP)/libcrypto.a
|
||||
LIBSRC= ec_lib.c ecp_smpl.c ecp_mont.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_mult.c ec_ameth.c eck_prn.c
|
||||
ec2_smpl.c ec2_mult.c ec_ameth.c ec_pmeth.c eck_prn.c
|
||||
|
||||
LIBOBJ= ec_lib.o ecp_smpl.o ecp_mont.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 ec_ameth.o eck_prn.o
|
||||
ec2_smpl.o ec2_mult.o ec_ameth.o ec_pmeth.o eck_prn.o
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
|
@ -905,6 +905,13 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \
|
||||
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
|
||||
|
||||
|
||||
#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@ -1028,6 +1035,12 @@ void ERR_load_EC_strings(void);
|
||||
#define EC_F_I2D_ECPRIVATEKEY 192
|
||||
#define EC_F_I2O_ECPUBLICKEY 151
|
||||
#define EC_F_O2I_ECPUBLICKEY 152
|
||||
#define EC_F_PKEY_EC_CTRL 197
|
||||
#define EC_F_PKEY_EC_CTRL_STR 198
|
||||
#define EC_F_PKEY_EC_DERIVE 217
|
||||
#define EC_F_PKEY_EC_KEYGEN 199
|
||||
#define EC_F_PKEY_EC_PARAMGEN 219
|
||||
#define EC_F_PKEY_EC_SIGN 218
|
||||
|
||||
/* Reason codes. */
|
||||
#define EC_R_ASN1_ERROR 115
|
||||
@ -1043,11 +1056,14 @@ void ERR_load_EC_strings(void);
|
||||
#define EC_R_INVALID_ARGUMENT 112
|
||||
#define EC_R_INVALID_COMPRESSED_POINT 110
|
||||
#define EC_R_INVALID_COMPRESSION_BIT 109
|
||||
#define EC_R_INVALID_CURVE 132
|
||||
#define EC_R_INVALID_DIGEST_TYPE 138
|
||||
#define EC_R_INVALID_ENCODING 102
|
||||
#define EC_R_INVALID_FIELD 103
|
||||
#define EC_R_INVALID_FORM 104
|
||||
#define EC_R_INVALID_GROUP_ORDER 122
|
||||
#define EC_R_INVALID_PRIVATE_KEY 123
|
||||
#define EC_R_KEYS_NOT_SET 140
|
||||
#define EC_R_MISSING_PARAMETERS 124
|
||||
#define EC_R_MISSING_PRIVATE_KEY 125
|
||||
#define EC_R_NOT_A_NIST_PRIME 135
|
||||
@ -1055,6 +1071,7 @@ void ERR_load_EC_strings(void);
|
||||
#define EC_R_NOT_IMPLEMENTED 126
|
||||
#define EC_R_NOT_INITIALIZED 111
|
||||
#define EC_R_NO_FIELD_MOD 133
|
||||
#define EC_R_NO_PARAMETERS_SET 139
|
||||
#define EC_R_PASSED_NULL_PARAMETER 134
|
||||
#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
|
||||
#define EC_R_POINT_AT_INFINITY 106
|
||||
|
@ -184,6 +184,12 @@ static ERR_STRING_DATA EC_str_functs[]=
|
||||
{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
|
||||
{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
|
||||
{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "PKEY_EC_CTRL_STR"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_DERIVE), "PKEY_EC_DERIVE"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "PKEY_EC_KEYGEN"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "PKEY_EC_PARAMGEN"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_SIGN), "PKEY_EC_SIGN"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
@ -202,11 +208,14 @@ static ERR_STRING_DATA EC_str_reasons[]=
|
||||
{ERR_REASON(EC_R_INVALID_ARGUMENT) ,"invalid argument"},
|
||||
{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"},
|
||||
{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT),"invalid compression bit"},
|
||||
{ERR_REASON(EC_R_INVALID_CURVE) ,"invalid curve"},
|
||||
{ERR_REASON(EC_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
|
||||
{ERR_REASON(EC_R_INVALID_ENCODING) ,"invalid encoding"},
|
||||
{ERR_REASON(EC_R_INVALID_FIELD) ,"invalid field"},
|
||||
{ERR_REASON(EC_R_INVALID_FORM) ,"invalid form"},
|
||||
{ERR_REASON(EC_R_INVALID_GROUP_ORDER) ,"invalid group order"},
|
||||
{ERR_REASON(EC_R_INVALID_PRIVATE_KEY) ,"invalid private key"},
|
||||
{ERR_REASON(EC_R_KEYS_NOT_SET) ,"keys not set"},
|
||||
{ERR_REASON(EC_R_MISSING_PARAMETERS) ,"missing parameters"},
|
||||
{ERR_REASON(EC_R_MISSING_PRIVATE_KEY) ,"missing private key"},
|
||||
{ERR_REASON(EC_R_NOT_A_NIST_PRIME) ,"not a NIST prime"},
|
||||
@ -214,6 +223,7 @@ static ERR_STRING_DATA EC_str_reasons[]=
|
||||
{ERR_REASON(EC_R_NOT_IMPLEMENTED) ,"not implemented"},
|
||||
{ERR_REASON(EC_R_NOT_INITIALIZED) ,"not initialized"},
|
||||
{ERR_REASON(EC_R_NO_FIELD_MOD) ,"no field mod"},
|
||||
{ERR_REASON(EC_R_NO_PARAMETERS_SET) ,"no parameters set"},
|
||||
{ERR_REASON(EC_R_PASSED_NULL_PARAMETER) ,"passed null parameter"},
|
||||
{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),"pkparameters2group failure"},
|
||||
{ERR_REASON(EC_R_POINT_AT_INFINITY) ,"point at infinity"},
|
||||
|
315
crypto/ec/ec_pmeth.c
Normal file
315
crypto/ec/ec_pmeth.c
Normal file
@ -0,0 +1,315 @@
|
||||
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 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
|
||||
* licensing@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 <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "evp_locl.h"
|
||||
|
||||
/* EC pkey context structure */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Key and paramgen group */
|
||||
EC_GROUP *gen_group;
|
||||
/* message digest */
|
||||
const EVP_MD *md;
|
||||
} EC_PKEY_CTX;
|
||||
|
||||
static int pkey_ec_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
EC_PKEY_CTX *dctx;
|
||||
dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
|
||||
if (!dctx)
|
||||
return 0;
|
||||
dctx->gen_group = NULL;
|
||||
dctx->md = NULL;
|
||||
|
||||
ctx->data = dctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
if (dctx)
|
||||
{
|
||||
if (dctx->gen_group)
|
||||
EC_GROUP_free(dctx->gen_group);
|
||||
OPENSSL_free(dctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
|
||||
const unsigned char *tbs, int tbslen)
|
||||
{
|
||||
int ret, type;
|
||||
unsigned int sltmp;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_KEY *ec = ctx->pkey->pkey.ec;
|
||||
|
||||
if (!sig)
|
||||
{
|
||||
*siglen = ECDSA_size(ec);
|
||||
return 1;
|
||||
}
|
||||
else if(*siglen < ECDSA_size(ec))
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dctx->md)
|
||||
type = EVP_MD_type(dctx->md);
|
||||
else
|
||||
type = NID_sha1;
|
||||
|
||||
|
||||
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*siglen = sltmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
|
||||
const unsigned char *sig, int siglen,
|
||||
const unsigned char *tbs, int tbslen)
|
||||
{
|
||||
int ret, type;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_KEY *ec = ctx->pkey->pkey.ec;
|
||||
|
||||
if (dctx->md)
|
||||
type = EVP_MD_type(dctx->md);
|
||||
else
|
||||
type = NID_sha1;
|
||||
|
||||
ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, int *keylen)
|
||||
{
|
||||
int ret;
|
||||
size_t outlen;
|
||||
const EC_POINT *pubkey = NULL;
|
||||
if (!ctx->pkey || !ctx->peerkey)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!key)
|
||||
{
|
||||
const EC_GROUP *group;
|
||||
group = EC_KEY_get0_group(ctx->pkey->pkey.ec);
|
||||
*keylen = (EC_GROUP_get_degree(group) + 7)/8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
|
||||
|
||||
/* NB: unlike PKS#3 DH, if *outlen is less than maximum size this is
|
||||
* not an error, the result is truncated.
|
||||
*/
|
||||
|
||||
outlen = *keylen;
|
||||
|
||||
ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*keylen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_GROUP *group;
|
||||
switch (type)
|
||||
{
|
||||
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
|
||||
group = EC_GROUP_new_by_curve_name(p1);
|
||||
if (group == NULL)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
|
||||
return 0;
|
||||
}
|
||||
if (dctx->gen_group)
|
||||
EC_GROUP_free(dctx->gen_group);
|
||||
dctx->gen_group = group;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
|
||||
return 0;
|
||||
}
|
||||
dctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
/* Default behaviour is OK */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (!strcmp(type, "ec_paramgen_curve"))
|
||||
{
|
||||
int nid;
|
||||
nid = OBJ_sn2nid(value);
|
||||
if (nid == NID_undef)
|
||||
nid = OBJ_ln2nid(value);
|
||||
if (nid == NID_undef)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
int ret = 0;
|
||||
if (dctx->gen_group == NULL)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
ec = EC_KEY_new();
|
||||
if (!ec)
|
||||
return 0;
|
||||
ret = EC_KEY_set_group(ec, dctx->gen_group);
|
||||
if (ret)
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
else
|
||||
EC_KEY_free(ec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
if (ctx->pkey == NULL)
|
||||
{
|
||||
ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
ec = EC_KEY_new();
|
||||
if (!ec)
|
||||
return 0;
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
/* Note: if error return, pkey is freed by parent routine */
|
||||
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
|
||||
return 0;
|
||||
return EC_KEY_generate_key(pkey->pkey.ec);
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD ec_pkey_meth =
|
||||
{
|
||||
EVP_PKEY_EC,
|
||||
0,
|
||||
pkey_ec_init,
|
||||
pkey_ec_cleanup,
|
||||
|
||||
0,
|
||||
pkey_ec_paramgen,
|
||||
|
||||
0,
|
||||
pkey_ec_keygen,
|
||||
|
||||
0,
|
||||
pkey_ec_sign,
|
||||
|
||||
0,
|
||||
pkey_ec_verify,
|
||||
|
||||
0,0,
|
||||
|
||||
0,0,0,0,
|
||||
|
||||
0,0,
|
||||
|
||||
0,0,
|
||||
|
||||
0,
|
||||
pkey_ec_derive,
|
||||
|
||||
pkey_ec_ctrl,
|
||||
pkey_ec_ctrl_str
|
||||
|
||||
};
|
@ -67,13 +67,14 @@
|
||||
typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
|
||||
STACK *app_pkey_methods = NULL;
|
||||
|
||||
extern EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth;
|
||||
extern EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth, ec_pkey_meth;
|
||||
|
||||
static const EVP_PKEY_METHOD *standard_methods[] =
|
||||
{
|
||||
&rsa_pkey_meth,
|
||||
&dh_pkey_meth,
|
||||
&dsa_pkey_meth
|
||||
&dsa_pkey_meth,
|
||||
&ec_pkey_meth
|
||||
};
|
||||
|
||||
static int pmeth_cmp(const EVP_PKEY_METHOD * const *a,
|
||||
|
Loading…
x
Reference in New Issue
Block a user