summaryrefslogtreecommitdiffstats
path: root/engines
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2009-06-16 16:39:20 +0000
committerDr. Stephen Henson <steve@openssl.org>2009-06-16 16:39:20 +0000
commitbfd502f027ffb83131f3e9c634f95d3176477591 (patch)
tree7f56da6b2bef7e95fb6ecedfcb4f5d000565c885 /engines
parentf1ed5fa827ac63420ffac8fcc69d5609716ba297 (diff)
Updates from HEAD.
Diffstat (limited to 'engines')
-rw-r--r--engines/ccgost/e_gost_err.c4
-rw-r--r--engines/ccgost/e_gost_err.h2
-rw-r--r--engines/ccgost/gost2001_keyx.c51
-rw-r--r--engines/ccgost/gost94_keyx.c52
-rw-r--r--engines/ccgost/gost_asn1.c2
-rw-r--r--engines/ccgost/gost_lcl.h1
-rw-r--r--engines/ccgost/gost_pmeth.c9
7 files changed, 91 insertions, 30 deletions
diff --git a/engines/ccgost/e_gost_err.c b/engines/ccgost/e_gost_err.c
index 469027051a..9a79a374e2 100644
--- a/engines/ccgost/e_gost_err.c
+++ b/engines/ccgost/e_gost_err.c
@@ -1,6 +1,6 @@
/* e_gost_err.c */
/* ====================================================================
- * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2009 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
@@ -120,10 +120,12 @@ static ERR_STRING_DATA GOST_str_reasons[]=
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
+{ERR_REASON(GOST_R_CTRL_CALL_FAILED) ,"ctrl call failed"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
{ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"},
{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
+{ERR_REASON(GOST_R_INCOMPATIBLE_PEER_KEY),"incompatible peer key"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
diff --git a/engines/ccgost/e_gost_err.h b/engines/ccgost/e_gost_err.h
index 652d1bb392..6dc500079d 100644
--- a/engines/ccgost/e_gost_err.h
+++ b/engines/ccgost/e_gost_err.h
@@ -118,10 +118,12 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
#define GOST_R_BAD_KEY_PARAMETERS_FORMAT 99
#define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 100
#define GOST_R_CANNOT_PACK_EPHEMERAL_KEY 101
+#define GOST_R_CTRL_CALL_FAILED 132
#define GOST_R_ERROR_COMPUTING_SHARED_KEY 102
#define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO 103
#define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 104
#define GOST_R_INCOMPATIBLE_ALGORITHMS 105
+#define GOST_R_INCOMPATIBLE_PEER_KEY 131
#define GOST_R_INVALID_CIPHER_PARAMS 106
#define GOST_R_INVALID_CIPHER_PARAM_OID 107
#define GOST_R_INVALID_DIGEST_TYPE 108
diff --git a/engines/ccgost/gost2001_keyx.c b/engines/ccgost/gost2001_keyx.c
index 3b5a78ac3d..00759bcab0 100644
--- a/engines/ccgost/gost2001_keyx.c
+++ b/engines/ccgost/gost2001_keyx.c
@@ -203,6 +203,16 @@ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_le
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key);
+ if (!key_is_ephemeral)
+ {
+ /* Set control "public key from client certificate used" */
+ if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
+ {
+ GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
+ GOST_R_CTRL_CALL_FAILED);
+ goto err;
+ }
+ }
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1;
GOST_KEY_TRANSPORT_free(gkt);
return ret;
@@ -225,7 +235,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
unsigned char sharedKey[32];
gost_ctx ctx;
const struct gost_cipher_info *param=NULL;
- EVP_PKEY *eph_key=NULL;
+ EVP_PKEY *eph_key=NULL, *peerkey=NULL;
if (!key)
{
@@ -239,18 +249,35 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return -1;
}
-
+
+ /* If key transport structure contains public key, use it */
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
- if (!eph_key) {
- eph_key = EVP_PKEY_CTX_get0_peerkey(pctx);
- if (! eph_key) {
+ if (eph_key)
+ {
+ if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0)
+ {
GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
- GOST_R_NO_PEER_KEY);
+ GOST_R_INCOMPATIBLE_PEER_KEY);
goto err;
+ }
+ }
+ else
+ {
+ /* Set control "public key from client certificate used" */
+ if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
+ {
+ GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
+ GOST_R_CTRL_CALL_FAILED);
+ goto err;
+ }
+ }
+ peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
+ if (!peerkey)
+ {
+ GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
+ GOST_R_NO_PEER_KEY);
+ goto err;
}
- /* Increment reference count of peer key */
- CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
- }
param = get_encryption_params(gkt->key_agreement_info->cipher);
gost_init(&ctx,param->sblock);
@@ -260,7 +287,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32);
OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
- VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)),
+ VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(peerkey)),
EVP_PKEY_get0(priv),wrappedKey);
if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key))
{
@@ -269,9 +296,9 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
goto err;
}
- EVP_PKEY_free(eph_key);
- GOST_KEY_TRANSPORT_free(gkt);
ret=1;
err:
+ if (eph_key) EVP_PKEY_free(eph_key);
+ if (gkt) GOST_KEY_TRANSPORT_free(gkt);
return ret;
}
diff --git a/engines/ccgost/gost94_keyx.c b/engines/ccgost/gost94_keyx.c
index 5d04a17821..624be586a5 100644
--- a/engines/ccgost/gost94_keyx.c
+++ b/engines/ccgost/gost94_keyx.c
@@ -92,7 +92,6 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
const struct gost_cipher_info *param=get_encryption_params(NULL);
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
- int size=-1;
gost_ctx cctx;
int key_is_ephemeral=1;
EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx);
@@ -178,10 +177,20 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL);
- if (!size)
+ if (*outlen <= 0)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO);
- size=-1;
+ goto err;
+ }
+ if (!key_is_ephemeral)
+ {
+ /* Set control "public key from client certificate used" */
+ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
+ {
+ GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
+ GOST_R_CTRL_CALL_FAILED);
+ goto err;
+ }
}
GOST_KEY_TRANSPORT_free(gkt);
return 1;
@@ -207,7 +216,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
unsigned char sharedKey[32];
gost_ctx cctx;
const struct gost_cipher_info *param=NULL;
- EVP_PKEY *eph_key=NULL;
+ EVP_PKEY *eph_key=NULL, *peerkey=NULL;
EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx);
if (!key)
@@ -224,19 +233,32 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
return 0;
}
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
- /* No ephemeral key in the structure. Check peer key in the context
- */
- if (!eph_key) {
- eph_key = EVP_PKEY_CTX_get0_peerkey(ctx);
- if (! eph_key) {
+ if (eph_key)
+ {
+ if (EVP_PKEY_derive_set_peer(ctx, eph_key) <= 0)
+ {
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
- GOST_R_NO_PEER_KEY);
+ GOST_R_INCOMPATIBLE_PEER_KEY);
goto err;
+ }
+ }
+ else
+ {
+ /* Set control "public key from client certificate used" */
+ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
+ {
+ GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
+ GOST_R_CTRL_CALL_FAILED);
+ goto err;
+ }
+ }
+ peerkey = EVP_PKEY_CTX_get0_peerkey(ctx);
+ if (!peerkey)
+ {
+ GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
+ GOST_R_NO_PEER_KEY);
+ goto err;
}
- /* Increment reference count of peer key */
- CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
- }
-
param = get_encryption_params(gkt->key_agreement_info->cipher);
gost_init(&cctx,param->sblock);
@@ -246,7 +268,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32);
OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
- make_cp_exchange_key(gost_get0_priv_key(priv),eph_key,sharedKey);
+ make_cp_exchange_key(gost_get0_priv_key(priv),peerkey,sharedKey);
if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key))
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
diff --git a/engines/ccgost/gost_asn1.c b/engines/ccgost/gost_asn1.c
index 76c18c1c66..318ecfce57 100644
--- a/engines/ccgost/gost_asn1.c
+++ b/engines/ccgost/gost_asn1.c
@@ -27,7 +27,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KEY_INFO)
ASN1_NDEF_SEQUENCE(GOST_KEY_AGREEMENT_INFO) = {
ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, cipher, ASN1_OBJECT),
- ASN1_IMP(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0),
+ ASN1_IMP_OPT(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0),
ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, eph_iv, ASN1_OCTET_STRING)
} ASN1_NDEF_SEQUENCE_END(GOST_KEY_AGREEMENT_INFO)
diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h
index 81fecd38a2..437a48cc86 100644
--- a/engines/ccgost/gost_lcl.h
+++ b/engines/ccgost/gost_lcl.h
@@ -47,6 +47,7 @@
int sign_param_nid; /* Should be set whenever parameters are filled */
EVP_MD *md;
unsigned char *shared_ukm;
+ int peer_key_used;
};
struct gost_mac_pmeth_data {
diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c
index 2861d38327..caaea99d36 100644
--- a/engines/ccgost/gost_pmeth.c
+++ b/engines/ccgost/gost_pmeth.c
@@ -98,7 +98,14 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
pctx->shared_ukm=OPENSSL_malloc((int)p1);
memcpy(pctx->shared_ukm,p2,(int) p1);
return 1;
-
+ case EVP_PKEY_CTRL_PEER_KEY:
+ if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
+ return 1;
+ if (p1 == 2) /* TLS: peer key used? */
+ return pctx->peer_key_used;
+ if (p1 == 3) /* TLS: peer key used! */
+ return (pctx->peer_key_used = 1);
+ return -2;
}
return -2;
}