From 83321f97557e27ec0afcef4408d130c160cad019 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Wed, 15 Feb 2017 00:03:52 +0800 Subject: [PATCH] add ecies ECIES share the same err num with EC --- Configure | 2 +- crypto/ec/ec_err.c | 27 +- crypto/ecies/build.info | 2 + crypto/ecies/ecies_asn1.c | 271 +++++++++++++ crypto/ecies/ecies_lib.c | 738 +++++++++++++++++++++++++++++++++++ include/openssl/ec.h | 23 ++ include/openssl/ecies.h | 165 ++++++++ test/build.info | 6 +- test/eciestest.c | 164 ++++++++ test/recipes/15-test_ecies.t | 12 + test/x509-f.p | 16 + test/x509-fff.p | 16 + util/mkdef.pl | 2 +- util/shlib_wrap.sh | 92 ----- 14 files changed, 1440 insertions(+), 96 deletions(-) create mode 100644 crypto/ecies/build.info create mode 100644 crypto/ecies/ecies_asn1.c create mode 100644 crypto/ecies/ecies_lib.c create mode 100644 include/openssl/ecies.h create mode 100755 test/eciestest.c create mode 100644 test/recipes/15-test_ecies.t create mode 100644 test/x509-f.p create mode 100644 test/x509-fff.p delete mode 100755 util/shlib_wrap.sh diff --git a/Configure b/Configure index f00c5ca1..c47b4360 100755 --- a/Configure +++ b/Configure @@ -311,7 +311,7 @@ $config{sdirs} = [ "buffer", "bio", "stack", "lhash", "rand", "err", "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", "cms", "ts", "srp", "cmac", "ct", "async", "kdf", - "sm3", "sms4", "kdf2" + "sm3", "sms4", "kdf2", "ecies" ]; # Known TLS and DTLS protocols diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index e4c2c1c1..dcc90c42 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,6 +20,7 @@ static ERR_STRING_DATA EC_str_functs[] = { {ERR_FUNC(EC_F_BN_TO_FELEM), "BN_to_felem"}, + {ERR_FUNC(EC_F_D2I_ECIESPARAMETERS), "d2i_ECIESParameters"}, {ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, {ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, {ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"}, @@ -34,6 +35,15 @@ static ERR_STRING_DATA EC_str_functs[] = { {ERR_FUNC(EC_F_ECDSA_SIGN_SETUP), "ECDSA_sign_setup"}, {ERR_FUNC(EC_F_ECDSA_SIG_NEW), "ECDSA_SIG_new"}, {ERR_FUNC(EC_F_ECDSA_VERIFY), "ECDSA_verify"}, + {ERR_FUNC(EC_F_ECIES_DECRYPT), "ECIES_decrypt"}, + {ERR_FUNC(EC_F_ECIES_DO_DECRYPT), "ECIES_do_decrypt"}, + {ERR_FUNC(EC_F_ECIES_DO_ENCRYPT), "ECIES_do_encrypt"}, + {ERR_FUNC(EC_F_ECIES_ENCRYPT), "ECIES_encrypt"}, + {ERR_FUNC(EC_F_ECIES_PARAMS_GET_ENC), "ECIES_PARAMS_get_enc"}, + {ERR_FUNC(EC_F_ECIES_PARAMS_GET_KDF), "ECIES_PARAMS_get_kdf"}, + {ERR_FUNC(EC_F_ECIES_PARAMS_GET_MAC), "ECIES_PARAMS_get_mac"}, + {ERR_FUNC(EC_F_ECIES_PARAMS_INIT_WITH_RECOMMENDED), + "ECIES_PARAMS_init_with_recommended"}, {ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "eckey_param2type"}, {ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "eckey_param_decode"}, {ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "eckey_priv_decode"}, @@ -182,6 +192,7 @@ static ERR_STRING_DATA EC_str_functs[] = { {ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "ec_pre_comp_new"}, {ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"}, {ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"}, + {ERR_FUNC(EC_F_I2D_ECIESPARAMETERS), "i2d_ECIESParameters"}, {ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"}, {ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, {ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, @@ -209,6 +220,9 @@ static ERR_STRING_DATA EC_str_reasons[] = { {ERR_REASON(EC_R_BAD_SIGNATURE), "bad signature"}, {ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"}, {ERR_REASON(EC_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_REASON(EC_R_CMAC_FINAL_FAILURE), "cmac final failure"}, + {ERR_REASON(EC_R_CMAC_INIT_FAILURE), "cmac init failure"}, + {ERR_REASON(EC_R_CMAC_UPDATE_FAILURE), "cmac update failure"}, {ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"}, {ERR_REASON(EC_R_CURVE_DOES_NOT_SUPPORT_ECDH), "curve does not support ecdh"}, @@ -217,13 +231,22 @@ static ERR_STRING_DATA EC_str_reasons[] = { {ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE), "d2i ecpkparameters failure"}, {ERR_REASON(EC_R_DECODE_ERROR), "decode error"}, + {ERR_REASON(EC_R_DECRYPT_FAILED), "decrypt failed"}, {ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"}, + {ERR_REASON(EC_R_ECDH_FAILED), "ecdh failed"}, + {ERR_REASON(EC_R_ECDH_FAILURE), "ecdh failure"}, + {ERR_REASON(EC_R_ECIES_DECRYPT_INIT_FAILURE), + "ecies decrypt init failure"}, + {ERR_REASON(EC_R_ECIES_VERIFY_MAC_FAILURE), "ecies verify mac failure"}, {ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), "ec group new by name failure"}, + {ERR_REASON(EC_R_ENCRYPT_FAILED), "encrypt failed"}, {ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"}, + {ERR_REASON(EC_R_GEN_MAC_FAILED), "gen mac failed"}, {ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, {ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE), "group2pkparameters failure"}, + {ERR_REASON(EC_R_HMAC_FAILURE), "hmac failure"}, {ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE), "i2d ecpkparameters failure"}, {ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, @@ -233,6 +256,8 @@ static ERR_STRING_DATA EC_str_reasons[] = { {ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"}, {ERR_REASON(EC_R_INVALID_DIGEST), "invalid digest"}, {ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"}, + {ERR_REASON(EC_R_INVALID_ECIES_CIPHERTEXT), "invalid ecies ciphertext"}, + {ERR_REASON(EC_R_INVALID_ECIES_PARAMETERS), "invalid ecies parameters"}, {ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"}, {ERR_REASON(EC_R_INVALID_FIELD), "invalid field"}, {ERR_REASON(EC_R_INVALID_FORM), "invalid form"}, diff --git a/crypto/ecies/build.info b/crypto/ecies/build.info new file mode 100644 index 00000000..6983895d --- /dev/null +++ b/crypto/ecies/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=ecies_asn1.c ecies_lib.c diff --git a/crypto/ecies/ecies_asn1.c b/crypto/ecies/ecies_asn1.c new file mode 100644 index 00000000..340d68e2 --- /dev/null +++ b/crypto/ecies/ecies_asn1.c @@ -0,0 +1,271 @@ +/* ==================================================================== + * Copyright (c) 2007 - 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * From SEC 1, Version 1.9 Draft, 2008 + * +secg-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) certicom(132) schemes(1) } + +ECIESAlgorithmSet ALGORITHM ::= { + { OID ecies-recommendedParameters} | + { OID ecies-specifiedParameters PARMS ECIESParameters} +} + + +KeyDerivationFunction ::= AlgorithmIdentifier {{KDFSet}} +KDFSet ALGORITHM ::= { + { OID x9-63-kdf PARMS HashAlgorithm } | + { OID nist-concatenation-kdf PARMS HashAlgorithm } | + { OID tls-kdf PARMS HashAlgorithm } | + { OID ikev2-kdf PARMS HashAlgorithm } +} + +SymmetricEncryption ::= AlgorithmIdentifier {{SYMENCSet}} +SYMENCSet ALGORITHM ::= { + { OID xor-in-ecies } | + { OID tdes-cbc-in-ecies } | -- IV should all be set to ZEROs + { OID aes128-cbc-in-ecies } | + { OID aes192-cbc-in-ecies } | + { OID aes256-cbc-in-ecies } | + { OID aes128-ctr-in-ecies } | + { OID aes192-ctr-in-ecies } | + { OID aes256-ctr-in-ecies } , +} + +MessageAuthenticationCode ::= AlgorithmIdentifier {{MACSet}} +MACSet ALGORITHM ::= { + { OID hmac-full-ecies PARMS HashAlgorithm} | + { OID hmac-half-ecies PARMS HashAlgorithm} | + { OID cmac-aes128-ecies } | + { OID cmac-aes192-ecies } | + { OID cmac-aes256-ecies } , +} + +*/ + +/* +ECIESParameters ::= SEQUENCE { + kdf [0] KeyDerivationFunction OPTIONAL, + sym [1] SymmetricEncryption OPTIONAL, + mac [2] MessageAuthenticationCode OPTIONAL +} +*/ + +typedef struct ecies_parameters_st { + X509_ALGOR *kdf; + X509_ALGOR *sym; + X509_ALGOR *mac; +} ECIES_PARAMETERS; + +ASN1_SEQUENCE(ECIES_PARAMETERS) = { + ASN1_EXP_OPT(ECIES_PARAMETERS, kdf, X509_ALGOR, 0), + ASN1_EXP_OPT(ECIES_PARAMETERS, sym, X509_ALGOR, 1), + ASN1_EXP_OPT(ECIES_PARAMETERS, mac, X509_ALGOR, 2) +} ASN1_SEQUENCE_END(ECIES_PARAMETERS) +IMPLEMENT_ASN1_FUNCTIONS(ECIES_PARAMETERS) +IMPLEMENT_ASN1_DUP_FUNCTION(ECIES_PARAMETERS) + +ASN1_SEQUENCE(ECIES_CIPHERTEXT_VALUE) = { + ASN1_SIMPLE(ECIES_CIPHERTEXT_VALUE, ephem_point, ASN1_OCTET_STRING), + ASN1_SIMPLE(ECIES_CIPHERTEXT_VALUE, ciphertext, ASN1_OCTET_STRING), + ASN1_SIMPLE(ECIES_CIPHERTEXT_VALUE, mactag, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(ECIES_CIPHERTEXT_VALUE) +IMPLEMENT_ASN1_FUNCTIONS(ECIES_CIPHERTEXT_VALUE) +IMPLEMENT_ASN1_DUP_FUNCTION(ECIES_CIPHERTEXT_VALUE) + + +int i2d_ECIESParameters(const ECIES_PARAMS *param, unsigned char **out) +{ + int ret = 0; + ECIES_PARAMETERS *asn1 = NULL; + + if (!(asn1 = ECIES_PARAMETERS_new())) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_MALLOC_FAILURE); + goto end; + } + + OPENSSL_assert(asn1->kdf && asn1->sym && asn1->mac); + + if (!X509_ALGOR_set0(asn1->kdf, OBJ_nid2obj(param->kdf_nid), + V_ASN1_OBJECT, OBJ_nid2obj(EVP_MD_nid(param->kdf_md)))) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_X509_LIB); + goto end; + } + if (!X509_ALGOR_set0(asn1->sym, OBJ_nid2obj(param->enc_nid), + V_ASN1_UNDEF, NULL)) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_X509_LIB); + goto end; + } + if (param->mac_nid == NID_hmac_full_ecies || + param->mac_nid == NID_hmac_half_ecies) { + if (!X509_ALGOR_set0(asn1->mac, OBJ_nid2obj(param->mac_nid), + V_ASN1_OBJECT, OBJ_nid2obj(EVP_MD_nid(param->hmac_md)))) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_MALLOC_FAILURE); + goto end; + } + } else { + if (!X509_ALGOR_set0(asn1->mac, OBJ_nid2obj(param->mac_nid), + V_ASN1_UNDEF, NULL)) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_MALLOC_FAILURE); + goto end; + } + } + + if ((ret = i2d_ECIES_PARAMETERS(asn1, out)) <= 0) { + ECerr(EC_F_I2D_ECIESPARAMETERS, ERR_R_ASN1_LIB); + goto end; + } + +end: + ECIES_PARAMETERS_free(asn1); + return ret; +} + +ECIES_PARAMS *d2i_ECIESParameters(ECIES_PARAMS **param, + const unsigned char **in, long len) +{ + int e = 1; + ECIES_PARAMS *ret = NULL; + ECIES_PARAMETERS *asn1 = NULL; + + if (!(ret = OPENSSL_zalloc(sizeof(ECIES_PARAMS)))) { + ECerr(EC_F_D2I_ECIESPARAMETERS, ERR_R_ASN1_LIB); + goto end; + } + if (!(asn1 = d2i_ECIES_PARAMETERS(NULL, in, len))) { + ECerr(EC_F_D2I_ECIESPARAMETERS, ERR_R_ASN1_LIB); + goto end; + } + + OpenSSL_add_all_digests(); + + /* kdf */ + ret->kdf_nid = OBJ_obj2nid(asn1->kdf->algorithm); + if (ret->kdf_nid != NID_x9_63_kdf) { + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (asn1->kdf->parameter->type != V_ASN1_OBJECT) { + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!(ret->kdf_md = EVP_get_digestbynid( + OBJ_obj2nid(asn1->kdf->parameter->value.object)))) { + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + + /* sym */ + ret->enc_nid = OBJ_obj2nid(asn1->sym->algorithm); + switch (ret->enc_nid) { + case NID_xor_in_ecies: + case NID_tdes_cbc_in_ecies: + case NID_aes128_cbc_in_ecies: + case NID_aes192_cbc_in_ecies: + case NID_aes256_cbc_in_ecies: + case NID_aes128_ctr_in_ecies: + case NID_aes192_ctr_in_ecies: + case NID_aes256_ctr_in_ecies: + break; + default: + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + + /* mac */ + ret->mac_nid = OBJ_obj2nid(asn1->mac->algorithm); + switch (ret->enc_nid) { + case NID_hmac_full_ecies: + case NID_hmac_half_ecies: + if (asn1->mac->parameter->type != V_ASN1_OBJECT) { + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!(ret->hmac_md = EVP_get_digestbynid( + OBJ_obj2nid(asn1->mac->parameter->value.object)))) { + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + break; + case NID_cmac_aes128_ecies: + case NID_cmac_aes192_ecies: + case NID_cmac_aes256_ecies: + break; + default: + ECerr(EC_F_D2I_ECIESPARAMETERS, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + + if (param && *param) + OPENSSL_free(*param); + if (param) + *param = ret; + + e = 0; +end: + if (e && ret) { + OPENSSL_free(ret); + ret = NULL; + } + ECIES_PARAMETERS_free(asn1); + return ret; +} + diff --git a/crypto/ecies/ecies_lib.c b/crypto/ecies/ecies_lib.c new file mode 100644 index 00000000..2f32a18e --- /dev/null +++ b/crypto/ecies/ecies_lib.c @@ -0,0 +1,738 @@ +/* ==================================================================== + * Copyright (c) 2007 - 2017 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/o_str.h" + +#define ECIES_ENC_RANDOM_IV 1 + +int ECIES_PARAMS_init_with_recommended(ECIES_PARAMS *param) +{ + if (!param) { + ECerr(EC_F_ECIES_PARAMS_INIT_WITH_RECOMMENDED, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + memset(param, 0, sizeof(*param)); + param->kdf_nid = NID_x9_63_kdf; + param->kdf_md = EVP_sha256(); + param->enc_nid = NID_xor_in_ecies; + param->mac_nid = NID_hmac_full_ecies; + param->hmac_md = EVP_sha256(); + return 1; +} + +ECIES_PARAMS *ECIES_PARAMS_new(void) +{ + ECIES_PARAMS *ret = NULL; + + if (!(ret = OPENSSL_malloc(sizeof(*ret)))) { + return NULL; + } + + ECIES_PARAMS_init_with_recommended(ret); + return ret; +} + +ECIES_PARAMS *ECIES_PARAMS_dup(const ECIES_PARAMS *param) +{ + ECIES_PARAMS *ret = NULL; + + if (!(ret = OPENSSL_zalloc(sizeof(*ret)))) { + return NULL; + } + + /* check param */ + + memcpy(ret, param, sizeof(*param)); + return ret; +} + +void ECIES_PARAMS_free(ECIES_PARAMS *param) +{ + OPENSSL_free(param); +} + +KDF_FUNC ECIES_PARAMS_get_kdf(const ECIES_PARAMS *param) +{ + if (!param || !param->kdf_md) { + ECerr(EC_F_ECIES_PARAMS_GET_KDF, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + switch (param->kdf_nid) { + case NID_x9_63_kdf: + return KDF_get_x9_63(param->kdf_md); + case NID_nist_concatenation_kdf: + case NID_tls_kdf: + case NID_ikev2_kdf: + ECerr(EC_F_ECIES_PARAMS_GET_KDF, EC_R_NOT_IMPLEMENTED); + return NULL; + } + + ECerr(EC_F_ECIES_PARAMS_GET_KDF, EC_R_INVALID_ECIES_PARAMETERS); + return NULL; +} + +int ECIES_PARAMS_get_enc(const ECIES_PARAMS *param, size_t inlen, + const EVP_CIPHER **enc_cipher, size_t *enckeylen, size_t *ciphertextlen) +{ + const EVP_CIPHER *cipher = NULL; + size_t keylen; + size_t outlen; + + if (!param || !enc_cipher || !enckeylen || !ciphertextlen) { + ECerr(EC_F_ECIES_PARAMS_GET_ENC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + switch (param->enc_nid) { + case NID_xor_in_ecies: + cipher = NULL; + keylen = inlen; + break; + case NID_tdes_cbc_in_ecies: + cipher = EVP_des_ede_cbc(); + break; + case NID_aes128_cbc_in_ecies: + cipher = EVP_aes_128_cbc(); + break; + case NID_aes192_cbc_in_ecies: + cipher = EVP_aes_192_cbc(); + break; + case NID_aes256_cbc_in_ecies: + cipher = EVP_aes_256_cbc(); + break; + case NID_aes128_ctr_in_ecies: + cipher = EVP_aes_128_ctr(); + break; + case NID_aes192_ctr_in_ecies: + cipher = EVP_aes_192_ctr(); + break; + case NID_aes256_ctr_in_ecies: + cipher = EVP_aes_256_ctr(); + break; + default: + ECerr(EC_F_ECIES_PARAMS_GET_ENC, EC_R_INVALID_ECIES_PARAMETERS); + return 0; + } + + outlen = inlen; + if (cipher) { + int blocksize = EVP_CIPHER_block_size(cipher); + keylen = EVP_CIPHER_key_length(cipher); + if (ECIES_ENC_RANDOM_IV) { + outlen += blocksize; + } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CBC_MODE) { + outlen += blocksize - inlen % blocksize; + } + } + + *enc_cipher = cipher; + *enckeylen = keylen; + *ciphertextlen = outlen; + + return 1; +} + +int ECIES_PARAMS_get_mac(const ECIES_PARAMS *param, + const EVP_MD **hmac_md, const EVP_CIPHER **cmac_cipher, + unsigned int *mackeylen, unsigned int *maclen) +{ + const EVP_CIPHER *cipher = NULL; + const EVP_MD *md = NULL; + unsigned int keylen; + unsigned int outlen; + + if (!param || !hmac_md || !cmac_cipher || !mackeylen || !maclen) { + ECerr(EC_F_ECIES_PARAMS_GET_MAC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + switch (param->mac_nid) { + case NID_hmac_full_ecies: + if (!(md = param->hmac_md)) { + ECerr(EC_F_ECIES_PARAMS_GET_MAC, + EC_R_INVALID_ECIES_PARAMETERS); + return 0; + } + keylen = EVP_MD_size(md); + outlen = EVP_MD_size(md); + break; + case NID_hmac_half_ecies: + if (!(md = param->hmac_md)) { + ECerr(EC_F_ECIES_PARAMS_GET_MAC, + EC_R_INVALID_ECIES_PARAMETERS); + return 0; + } + keylen = EVP_MD_size(md); + outlen = EVP_MD_size(md)/2; + break; + case NID_cmac_aes128_ecies: + cipher = EVP_aes_128_ecb(); + break; + case NID_cmac_aes192_ecies: + cipher = EVP_aes_192_ecb(); + break; + case NID_cmac_aes256_ecies: + cipher = EVP_aes_256_ecb(); + break; + default: + ECerr(EC_F_ECIES_PARAMS_GET_MAC, + EC_R_INVALID_ECIES_PARAMETERS); + return 0; + } + + if (cipher) { + keylen = EVP_CIPHER_key_length(cipher); + outlen = EVP_CIPHER_block_size(cipher); + } + + *hmac_md = md; + *cmac_cipher = cipher; + *mackeylen = keylen; + *maclen = outlen; + + return 1; +} + +ECIES_CIPHERTEXT_VALUE *ECIES_do_encrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, EC_KEY *ec_key) +{ + int e = 1; + KDF_FUNC kdf_func; + const EVP_CIPHER *enc_cipher = NULL; + size_t enckeylen, ciphertextlen; + const EVP_MD *hmac_md = NULL; + const EVP_CIPHER *mac_cipher = NULL; + unsigned int mackeylen, maclen; + ECIES_CIPHERTEXT_VALUE *ret = NULL; + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + EC_KEY *ephem_key = NULL; + int point_form = POINT_CONVERSION_COMPRESSED; + unsigned char *sharekey = NULL; + unsigned int sharekeylen; + unsigned char *enckey, *mackey; + unsigned char mac[EVP_MAX_MD_SIZE]; + size_t len; + + if (!param || !in || !inlen || !ec_key || !group) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* parse parameters */ + if (!(kdf_func = ECIES_PARAMS_get_kdf(param))) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!ECIES_PARAMS_get_enc(param, inlen, &enc_cipher, &enckeylen, &ciphertextlen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!ECIES_PARAMS_get_mac(param, &hmac_md, &mac_cipher, &mackeylen, &maclen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + + /* malloc ciphertext value */ + if (!(ret = ECIES_CIPHERTEXT_VALUE_new())) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* generate ephem keypair */ + if (!(ephem_key = EC_KEY_new())) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EC_KEY_set_group(ephem_key, group)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_KEY_generate_key(ephem_key)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* output ephem_point */ + len = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ephem_key), + point_form, NULL, 0, NULL); + if (!ASN1_OCTET_STRING_set(ret->ephem_point, NULL, len)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_ASN1_LIB); + goto end; + } + if (EC_POINT_point2oct(group, EC_KEY_get0_public_key(ephem_key), + point_form, ret->ephem_point->data, len, NULL) <= 0) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* ecdh to generate enckey and mackey */ + sharekeylen = enckeylen + mackeylen; + if (!(sharekey = OPENSSL_malloc(sharekeylen))) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!ECDH_compute_key(sharekey, sharekeylen, + EC_KEY_get0_public_key(ec_key), ephem_key, + kdf_func)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_ECDH_FAILED); + goto end; + } + enckey = sharekey; + mackey = sharekey + enckeylen; + + /* encrypt */ + if (!ASN1_OCTET_STRING_set(ret->ciphertext, NULL, ciphertextlen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (enc_cipher) { + EVP_CIPHER_CTX *cipher_ctx = NULL; + unsigned char ivbuf[EVP_MAX_IV_LENGTH]; + unsigned char *iv, *pout; + unsigned int ivlen, len; + + ivlen = EVP_CIPHER_iv_length(enc_cipher); + if (ECIES_ENC_RANDOM_IV) { + iv = ret->ciphertext->data; + pout = ret->ciphertext->data + ivlen; + RAND_bytes(iv, ivlen); + } else { + iv = ivbuf; + pout = ret->ciphertext->data; + memset(iv, 0, ivlen); + } + + if (!(cipher_ctx = EVP_CIPHER_CTX_new())) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EVP_EncryptInit(cipher_ctx, enc_cipher, enckey, iv)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_ENCRYPT_FAILED); + EVP_CIPHER_CTX_free(cipher_ctx); + goto end; + } + if (!EVP_EncryptUpdate(cipher_ctx, pout, (int *)&len, in, inlen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_ENCRYPT_FAILED); + EVP_CIPHER_CTX_free(cipher_ctx); + goto end; + } + pout += len; + if (!EVP_EncryptFinal(cipher_ctx, pout, (int *)&len)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_ENCRYPT_FAILED); + goto end; + } + pout += len; + + OPENSSL_assert(pout - ret->ciphertext->data == ciphertextlen); + + } else { + unsigned int i; + for (i = 0; i < ret->ciphertext->length; i++) { + ret->ciphertext->data[i] = in[i] ^ enckey[i]; + } + } + + /* generate mac */ + if (mac_cipher) { + CMAC_CTX *cmac_ctx; + if (!(cmac_ctx = CMAC_CTX_new())) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!CMAC_Init(cmac_ctx, mackey, mackeylen, mac_cipher, NULL)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_CMAC_INIT_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + if (!CMAC_Update(cmac_ctx, ret->ciphertext->data, ret->ciphertext->length)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_CMAC_UPDATE_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + len = sizeof(mac); + if (!CMAC_Final(cmac_ctx, mac, &len)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_CMAC_FINAL_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + OPENSSL_assert(len == maclen); + CMAC_CTX_free(cmac_ctx); + + } else { + len = sizeof(mac); + if (!HMAC(param->hmac_md, mackey, mackeylen, + ret->ciphertext->data, ret->ciphertext->length, + mac, &maclen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, EC_R_HMAC_FAILURE); + goto end; + } + OPENSSL_assert(len == maclen || len/2 == maclen); + } + + if (!ASN1_OCTET_STRING_set(ret->mactag, mac, maclen)) { + ECerr(EC_F_ECIES_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + + e = 0; +end: + EC_KEY_free(ephem_key); + OPENSSL_free(sharekey); + if (e && ret) { + ECIES_CIPHERTEXT_VALUE_free(ret); + ret = NULL; + } + return ret; +} + +int ECIES_do_decrypt(const ECIES_PARAMS *param, const ECIES_CIPHERTEXT_VALUE *in, + unsigned char *out, size_t *outlen, EC_KEY *ec_key) +{ + int ret = 0; + KDF_FUNC kdf_func; + const EVP_CIPHER *enc_cipher = NULL; + size_t enckeylen, ciphertextlen; + const EVP_MD *hmac_md = NULL; + const EVP_CIPHER *mac_cipher = NULL; + unsigned int mackeylen, maclen; + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + EC_POINT *ephem_point = NULL; + unsigned char *sharekey = NULL; + unsigned int sharekeylen; + unsigned char *enckey, *mackey; + unsigned char mac[EVP_MAX_MD_SIZE]; + size_t len; + + if (!param || !in || !outlen || !ec_key || !group) { + ECerr(EC_F_ECIES_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!out) { + *outlen = in->ciphertext->length; + return 1; + } + if (*outlen < in->ciphertext->length) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + /* parse parameters */ + if (!(kdf_func = ECIES_PARAMS_get_kdf(param))) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!ECIES_PARAMS_get_enc(param, in->ciphertext->length, + &enc_cipher, &enckeylen, &ciphertextlen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + if (!ECIES_PARAMS_get_mac(param, &hmac_md, &mac_cipher, &mackeylen, &maclen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_PARAMETERS); + goto end; + } + + /* parse ephem_point */ + if (!in->ephem_point || !in->ephem_point->data || in->ephem_point->length <= 0) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_CIPHERTEXT); + goto end; + } + if (!(ephem_point = EC_POINT_new(group))) { + ECerr(EC_F_ECIES_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EC_POINT_oct2point(group, ephem_point, + in->ephem_point->data, in->ephem_point->length, NULL)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_CIPHERTEXT); + goto end; + } + + /* compute ecdh, get enckey and mackey */ + sharekeylen = enckeylen + mackeylen; + if (!(sharekey = OPENSSL_malloc(sharekeylen))) { + ECerr(EC_F_ECIES_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!ECDH_compute_key(sharekey, sharekeylen, + ephem_point, ec_key, kdf_func)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_ECDH_FAILURE); + goto end; + } + enckey = sharekey; + mackey = sharekey + enckeylen; + + /* generate and verify mac */ + if (!in->mactag || !in->mactag->data) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_CIPHERTEXT); + goto end; + } + + if (mac_cipher) { + CMAC_CTX *cmac_ctx; + if (!(cmac_ctx = CMAC_CTX_new())) { + ECerr(EC_F_ECIES_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!CMAC_Init(cmac_ctx, mackey, mackeylen, mac_cipher, NULL)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_CMAC_INIT_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + if (!CMAC_Update(cmac_ctx, in->ciphertext->data, in->ciphertext->length)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_CMAC_UPDATE_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + len = sizeof(mac); + if (!CMAC_Final(cmac_ctx, mac, &len)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_CMAC_FINAL_FAILURE); + CMAC_CTX_free(cmac_ctx); + goto end; + } + OPENSSL_assert(len == maclen); + CMAC_CTX_free(cmac_ctx); + + } else { + unsigned int ulen; + ulen = sizeof(mac); + if (!HMAC(param->hmac_md, mackey, mackeylen, + in->ciphertext->data, in->ciphertext->length, + mac, &ulen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_GEN_MAC_FAILED); + goto end; + } + len = (size_t)ulen; + OPENSSL_assert(len == maclen || len/2 == maclen); + } + + if (maclen != in->mactag->length) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_ECIES_VERIFY_MAC_FAILURE); + goto end; + } + if (OPENSSL_memcmp(in->mactag->data, mac, maclen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_ECIES_VERIFY_MAC_FAILURE); + goto end; + } + + /* decrypt */ + if (enc_cipher) { + EVP_CIPHER_CTX *cipher_ctx = NULL; + unsigned char ivbuf[EVP_MAX_IV_LENGTH]; + unsigned char *iv, *pin, *pout; + unsigned int ivlen, inlen; + int ilen; + + /* prepare iv */ + ivlen = EVP_CIPHER_iv_length(enc_cipher); + if (ECIES_ENC_RANDOM_IV) { + iv = in->ciphertext->data; + pin = in->ciphertext->data + ivlen; + if (in->ciphertext->length < ivlen) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_CIPHERTEXT); + goto end; + } + inlen = in->ciphertext->length - ivlen; + } else { + /* use fixed all-zero iv */ + memset(ivbuf, 0, ivlen); + iv = ivbuf; + pin = in->ciphertext->data; + if (in->ciphertext->length <= 0) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_INVALID_ECIES_CIPHERTEXT); + goto end; + } + inlen = in->ciphertext->length; + } + + /* decrypt */ + if (!(cipher_ctx = EVP_CIPHER_CTX_new())) { + ECerr(EC_F_ECIES_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!EVP_DecryptInit(cipher_ctx, enc_cipher, enckey, iv)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_ECIES_DECRYPT_INIT_FAILURE); + EVP_CIPHER_CTX_free(cipher_ctx); + goto end; + } + pout = out; + ilen = (int)*outlen; //FIXME: do we need to check it? + if (!EVP_DecryptUpdate(cipher_ctx, pout, &ilen, pin, inlen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_DECRYPT_FAILED); + EVP_CIPHER_CTX_free(cipher_ctx); + goto end; + } + pout += ilen; + if (!EVP_DecryptFinal(cipher_ctx, pout, &ilen)) { + ECerr(EC_F_ECIES_DO_DECRYPT, EC_R_DECRYPT_FAILED); + EVP_CIPHER_CTX_free(cipher_ctx); + goto end; + } + pout += ilen; + EVP_CIPHER_CTX_free(cipher_ctx); + *outlen = pout - out; + + } else { + unsigned int i; + for (i = 0; i < in->ciphertext->length; i++) { + out[i] = in->ciphertext->data[i] ^ enckey[i]; + } + *outlen = in->ciphertext->length; + } + + ret = 1; +end: + OPENSSL_free(sharekey); + EC_POINT_free(ephem_point); + return ret; +} + +int ECIES_encrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key) +{ + int ret = 0; + ECIES_CIPHERTEXT_VALUE *cv = NULL; + unsigned char *p = out; + int len; + + if (!(cv = ECIES_do_encrypt(param, in, inlen, ec_key))) { + ECerr(EC_F_ECIES_ENCRYPT, EC_R_ENCRYPT_FAILED); + return 0; + } + + if ((len = i2d_ECIES_CIPHERTEXT_VALUE(cv, NULL)) <= 0) { + ECerr(EC_F_ECIES_ENCRYPT, EC_R_ENCRYPT_FAILED); + goto end; + } + + if (!out) { + *outlen = (size_t)len; + ret = 1; + goto end; + } + + if (*outlen < len) { + ECerr(EC_F_ECIES_ENCRYPT, EC_R_ENCRYPT_FAILED); + *outlen = (size_t)len; + goto end; + } + + if ((len = i2d_ECIES_CIPHERTEXT_VALUE(cv, &p)) <= 0) { + ECerr(EC_F_ECIES_ENCRYPT, EC_R_ENCRYPT_FAILED); + goto end; + } + + *outlen = (size_t)len; + ret = 1; + +end: + ECIES_CIPHERTEXT_VALUE_free(cv); + return ret; +} + + +int ECIES_decrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key) +{ + int ret = 0; + ECIES_CIPHERTEXT_VALUE *cv = NULL; + const unsigned char *p = in; + + if (!(cv = d2i_ECIES_CIPHERTEXT_VALUE(NULL, &p, (long)inlen))) { + ECerr(EC_F_ECIES_DECRYPT, EC_R_ENCRYPT_FAILED); + return 0; + } + + if (!ECIES_do_decrypt(param, cv, out, outlen, ec_key)) { + ECerr(EC_F_ECIES_DECRYPT, EC_R_ENCRYPT_FAILED); + goto end; + } + + ret = 1; +end: + ECIES_CIPHERTEXT_VALUE_free(cv); + return ret; +} + + +int ECIES_encrypt_with_recommended(const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key) +{ + ECIES_PARAMS param; + ECIES_PARAMS_init_with_recommended(¶m); + return ECIES_encrypt(¶m, in, inlen, out, outlen, ec_key); +} + +int ECIES_decrypt_with_recommended(const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key) +{ + ECIES_PARAMS param; + ECIES_PARAMS_init_with_recommended(¶m); + return ECIES_decrypt(¶m, in, inlen, out, outlen, ec_key); +} + diff --git a/include/openssl/ec.h b/include/openssl/ec.h index 656cb410..0bcf3f11 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -1368,6 +1368,7 @@ int ERR_load_EC_strings(void); /* Function codes. */ # define EC_F_BN_TO_FELEM 224 +# define EC_F_D2I_ECIESPARAMETERS 270 # define EC_F_D2I_ECPARAMETERS 144 # define EC_F_D2I_ECPKPARAMETERS 145 # define EC_F_D2I_ECPRIVATEKEY 146 @@ -1382,6 +1383,14 @@ int ERR_load_EC_strings(void); # define EC_F_ECDSA_SIGN_SETUP 248 # define EC_F_ECDSA_SIG_NEW 265 # define EC_F_ECDSA_VERIFY 253 +# define EC_F_ECIES_DECRYPT 271 +# define EC_F_ECIES_DO_DECRYPT 272 +# define EC_F_ECIES_DO_ENCRYPT 273 +# define EC_F_ECIES_ENCRYPT 274 +# define EC_F_ECIES_PARAMS_GET_ENC 275 +# define EC_F_ECIES_PARAMS_GET_KDF 276 +# define EC_F_ECIES_PARAMS_GET_MAC 277 +# define EC_F_ECIES_PARAMS_INIT_WITH_RECOMMENDED 278 # define EC_F_ECKEY_PARAM2TYPE 223 # define EC_F_ECKEY_PARAM_DECODE 212 # define EC_F_ECKEY_PRIV_DECODE 213 @@ -1493,6 +1502,7 @@ int ERR_load_EC_strings(void); # define EC_F_EC_PRE_COMP_NEW 196 # define EC_F_EC_WNAF_MUL 187 # define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +# define EC_F_I2D_ECIESPARAMETERS 279 # define EC_F_I2D_ECPARAMETERS 190 # define EC_F_I2D_ECPKPARAMETERS 191 # define EC_F_I2D_ECPRIVATEKEY 192 @@ -1518,16 +1528,27 @@ int ERR_load_EC_strings(void); # define EC_R_BAD_SIGNATURE 156 # define EC_R_BIGNUM_OUT_OF_RANGE 144 # define EC_R_BUFFER_TOO_SMALL 100 +# define EC_R_CMAC_FINAL_FAILURE 136 +# define EC_R_CMAC_INIT_FAILURE 153 +# define EC_R_CMAC_UPDATE_FAILURE 162 # define EC_R_COORDINATES_OUT_OF_RANGE 146 # define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 # define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 # define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 # define EC_R_DECODE_ERROR 142 +# define EC_R_DECRYPT_FAILED 163 # define EC_R_DISCRIMINANT_IS_ZERO 118 +# define EC_R_ECDH_FAILED 164 +# define EC_R_ECDH_FAILURE 165 +# define EC_R_ECIES_DECRYPT_INIT_FAILURE 166 +# define EC_R_ECIES_VERIFY_MAC_FAILURE 167 # define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +# define EC_R_ENCRYPT_FAILED 168 # define EC_R_FIELD_TOO_LARGE 143 +# define EC_R_GEN_MAC_FAILED 169 # define EC_R_GF2M_NOT_SUPPORTED 147 # define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +# define EC_R_HMAC_FAILURE 170 # define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 # define EC_R_INCOMPATIBLE_OBJECTS 101 # define EC_R_INVALID_ARGUMENT 112 @@ -1536,6 +1557,8 @@ int ERR_load_EC_strings(void); # define EC_R_INVALID_CURVE 141 # define EC_R_INVALID_DIGEST 151 # define EC_R_INVALID_DIGEST_TYPE 138 +# define EC_R_INVALID_ECIES_CIPHERTEXT 171 +# define EC_R_INVALID_ECIES_PARAMETERS 172 # define EC_R_INVALID_ENCODING 102 # define EC_R_INVALID_FIELD 103 # define EC_R_INVALID_FORM 104 diff --git a/include/openssl/ecies.h b/include/openssl/ecies.h new file mode 100644 index 00000000..4e51e68f --- /dev/null +++ b/include/openssl/ecies.h @@ -0,0 +1,165 @@ +/* ==================================================================== + * Copyright (c) 2007 - 2017 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ +/* + * Ellitpic Curve Integrated Encryption Scheme (ECIES) + * see http://www.secg.org/sec1-v2.pdf (section 5) + * SEC1: Elliptic Curve Cryptography version 2.0 + */ + +#ifndef HEADER_ECIES_H +#define HEADER_ECIES_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +ECIESAlgorithmSet ALGORITHM ::= { + {OID ecies-recommendedParameters} | + {OID ecies-specifiedParameters PARMS ECIESParameters}, + ... -- Future combinations may be added +} +*/ + +typedef struct ecies_params_st { + /* + KDFSet ALGORITHM ::= { + { OID x9-63-kdf PARMS HashAlgorithm } | + { OID nist-concatenation-kdf PARMS HashAlgorithm } | + { OID tls-kdf PARMS HashAlgorithm } | + { OID ikev2-kdf PARMS HashAlgorithm } + ... -- Future combinations may be added + } + */ + int kdf_nid; + const EVP_MD *kdf_md; + + /* + SYMENCSet ALGORITHM ::= { + { OID xor-in-ecies } | + { OID tdes-cbc-in-ecies } | + { OID aes128-cbc-in-ecies } | + { OID aes192-cbc-in-ecies } | + { OID aes256-cbc-in-ecies } | + { OID aes128-ctr-in-ecies } | + { OID aes192-ctr-in-ecies } | + { OID aes256-ctr-in-ecies } , + ... -- Future combinations may be added + } + */ + int enc_nid; + + /* + MACSet ALGORITHM ::= { + { OID hmac-full-ecies PARMS HashAlgorithm} | + { OID hmac-half-ecies PARMS HashAlgorithm} | + { OID cmac-aes128-ecies } | + { OID cmac-aes192-ecies } | + { OID cmac-aes256-ecies } , + ... -- Future combinations may be added + } + */ + int mac_nid; + const EVP_MD *hmac_md; + +} ECIES_PARAMS; + +ECIES_PARAMS *ECIES_PARAMS_new(void); +int ECIES_PARAMS_init_with_recommended(ECIES_PARAMS *param); +ECIES_PARAMS *ECIES_PARAMS_dup(const ECIES_PARAMS *param); +KDF_FUNC ECIES_PARAMS_get_kdf(const ECIES_PARAMS *param); +int ECIES_PARAMS_get_enc(const ECIES_PARAMS *param, size_t inlen, + const EVP_CIPHER **enc_cipher, size_t *enckeylen, size_t *ciphertextlen); +int ECIES_PARAMS_get_mac(const ECIES_PARAMS *param, + const EVP_MD **hmac_md, const EVP_CIPHER **cmac_cipher, + unsigned int *mackeylen, unsigned int *maclen); +void ECIES_PARAMS_free(ECIES_PARAMS *param); + +int i2d_ECIESParameters(const ECIES_PARAMS *param, unsigned char **out); +ECIES_PARAMS *d2i_ECIESParameters(ECIES_PARAMS **param, + const unsigned char **in, long len); + + +typedef struct ecies_ciphertext_value_st { + ASN1_OCTET_STRING *ephem_point; + ASN1_OCTET_STRING *ciphertext; + ASN1_OCTET_STRING *mactag; +} ECIES_CIPHERTEXT_VALUE; + +DECLARE_ASN1_FUNCTIONS(ECIES_CIPHERTEXT_VALUE) + + +ECIES_CIPHERTEXT_VALUE *ECIES_do_encrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, EC_KEY *ec_key); +int ECIES_do_decrypt(const ECIES_PARAMS *param, const ECIES_CIPHERTEXT_VALUE *in, + unsigned char *out, size_t *outlen, EC_KEY *ec_key); +int ECIES_encrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key); +int ECIES_decrypt(const ECIES_PARAMS *param, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key); + +int ECIES_encrypt_with_recommended(const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key); +int ECIES_decrypt_with_recommended(const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, EC_KEY *ec_key); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/test/build.info b/test/build.info index 7de38dc3..8b0723d0 100644 --- a/test/build.info +++ b/test/build.info @@ -17,7 +17,7 @@ IF[{- !$disabled{tests} -}] dtlsv1listentest ct_test threadstest afalgtest d2i_test \ ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \ bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \ - sm3test sms4test kdf2test + sm3test sms4test kdf2test eciestest SOURCE[aborttest]=aborttest.c INCLUDE[aborttest]=../include @@ -296,6 +296,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[kdf2test]=../include DEPEND[kdf2test]=../libcrypto + SOURCE[eciestest]=eciestest.c + INCLUDE[eciestest]=../include + DEPEND[eciestest]=../libcrypto + IF[{- !$disabled{shared} -}] PROGRAMS_NO_INST=shlibloadtest SOURCE[shlibloadtest]=shlibloadtest.c diff --git a/test/eciestest.c b/test/eciestest.c new file mode 100755 index 00000000..a3111488 --- /dev/null +++ b/test/eciestest.c @@ -0,0 +1,164 @@ +/* ==================================================================== + * Copyright (c) 2007 - 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ + +#include +#include +#include +#include "../e_os.h" + +#ifdef OPENSSL_NO_ECIES +int main(int argc, char **argv) +{ + printf("NO ECIES support\n"); + return 0; +} +#else +# include +# include +# include +# include + +static int ECIES_test(int verbose) +{ + int ret = 0; + EC_KEY *ec_key = NULL; + unsigned char mbuf[] = "message to be encrypted"; + size_t mlen = sizeof(mbuf); + unsigned char *cbuf = NULL; + unsigned char *pbuf = NULL; + size_t clen, plen; + + /* generate key pair */ + if (!(ec_key = EC_KEY_new_by_curve_name(NID_secp192k1))) { + ERR_print_errors_fp(stderr); + goto end; + } + if (!EC_KEY_generate_key(ec_key)) { + ERR_print_errors_fp(stderr); + goto end; + } + + /* estimate output buffer size */ + if (!ECIES_encrypt_with_recommended(mbuf, sizeof(mbuf), NULL, &clen, ec_key)) { + ERR_print_errors_fp(stderr); + goto end; + } + /* prepare buffer */ + if (!(cbuf = OPENSSL_malloc(clen))) { + ERR_print_errors_fp(stderr); + goto end; + } + /* encrypt */ + if (!ECIES_encrypt_with_recommended(mbuf, sizeof(mbuf), cbuf, &clen, ec_key)) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (verbose) { + printf("plaintext = %s\n", (char *)mbuf); + } + + if (verbose) { + int i; + printf("ciphertext = "); + for (i = 0; i < clen; i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + } + + /* estimate output buffer size */ + if (!ECIES_decrypt_with_recommended(cbuf, clen, NULL, &plen, ec_key)) { + ERR_print_errors_fp(stderr); + goto end; + } + /* prepare buffer */ + if (!(pbuf = OPENSSL_zalloc(plen))) { + ERR_print_errors_fp(stderr); + goto end; + } + /* decrypt */ + if (!ECIES_decrypt_with_recommended(cbuf, clen, pbuf, &plen, ec_key)) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (verbose) { + printf("plaintext = %s\n", pbuf); + } + + /* compare plaintext, and set result */ + if (plen == mlen && memcmp(mbuf, pbuf, mlen) == 0) { + ret = 1; + } + + if (verbose) { + printf("%s() %s\n", __FUNCTION__, + ret == 1 ? "passed" : "failed"); + } + +end: + EC_KEY_free(ec_key); + OPENSSL_free(cbuf); + OPENSSL_free(pbuf); + return ret; +} + +int main(int argc, char **argv) +{ + int verbose = 2; + if (!ECIES_test(verbose)) { + printf("test failed\n"); + return 1; + } else { + printf("test ok\n"); + return 0; + } +} +#endif diff --git a/test/recipes/15-test_ecies.t b/test/recipes/15-test_ecies.t new file mode 100644 index 00000000..f4726cf8 --- /dev/null +++ b/test/recipes/15-test_ecies.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use OpenSSL::Test::Simple; + +simple_test("test_ecies", "eciestest", "ecies"); diff --git a/test/x509-f.p b/test/x509-f.p new file mode 100644 index 00000000..0da253d5 --- /dev/null +++ b/test/x509-f.p @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx +NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz +dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw +ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu +ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2 +ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp +miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C +AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK +Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x +DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR +MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB +AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21 +X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3 +WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO +-----END CERTIFICATE----- diff --git a/test/x509-fff.p b/test/x509-fff.p new file mode 100644 index 00000000..0da253d5 --- /dev/null +++ b/test/x509-fff.p @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx +NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz +dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw +ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu +ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2 +ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp +miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C +AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK +Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x +DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR +MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB +AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21 +X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3 +WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO +-----END CERTIFICATE----- diff --git a/util/mkdef.pl b/util/mkdef.pl index e91dc761..e5715fc7 100755 --- a/util/mkdef.pl +++ b/util/mkdef.pl @@ -132,7 +132,7 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF", "CMAC", # APPLINK (win build feature?) "APPLINK", - "SM3", "SMS4", "KDF2" + "SM3", "SMS4", "KDF2", "ECIES" ); my %disabled_algorithms; diff --git a/util/shlib_wrap.sh b/util/shlib_wrap.sh deleted file mode 100755 index 811a08d6..00000000 --- a/util/shlib_wrap.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh - -[ $# -ne 0 ] || set -x # debug mode without arguments:-) - -THERE="`echo $0 | sed -e 's|[^/]*$||' 2>/dev/null`.." -[ -d "${THERE}" ] || exec "$@" # should never happen... - -# Alternative to this is to parse ${THERE}/Makefile... -LIBCRYPTOSO="${THERE}/libcrypto.so" -if [ -f "$LIBCRYPTOSO" ]; then - while [ -h "$LIBCRYPTOSO" ]; do - LIBCRYPTOSO="${THERE}/`ls -l "$LIBCRYPTOSO" | sed -e 's|.*\-> ||'`" - done - SOSUFFIX=`echo ${LIBCRYPTOSO} | sed -e 's|.*\.so||' 2>/dev/null` - LIBSSLSO="${THERE}/libssl.so${SOSUFFIX}" -fi - -SYSNAME=`(uname -s) 2>/dev/null`; -case "$SYSNAME" in -SunOS|IRIX*) - # SunOS and IRIX run-time linkers evaluate alternative - # variables depending on target ABI... - rld_var=LD_LIBRARY_PATH - case "`(/usr/bin/file "$LIBCRYPTOSO") 2>/dev/null`" in - *ELF\ 64*SPARC*|*ELF\ 64*AMD64*) - [ -n "$LD_LIBRARY_PATH_64" ] && rld_var=LD_LIBRARY_PATH_64 - LD_PRELOAD_64="$LIBCRYPTOSO $LIBSSLSO"; export LD_PRELOAD_64 - preload_var=LD_PRELOAD_64 - ;; - *ELF\ 32*SPARC*|*ELF\ 32*80386*) - # We only need to change LD_PRELOAD_32 and LD_LIBRARY_PATH_32 - # on a multi-arch system. Otherwise, trust the fallbacks. - if [ -f /lib/64/ld.so.1 ]; then - [ -n "$LD_LIBRARY_PATH_32" ] && rld_var=LD_LIBRARY_PATH_32 - LD_PRELOAD_32="$LIBCRYPTOSO $LIBSSLSO"; export LD_PRELOAD_32 - preload_var=LD_PRELOAD_32 - fi - ;; - # Why are newly built .so's preloaded anyway? Because run-time - # .so lookup path embedded into application takes precedence - # over LD_LIBRARY_PATH and as result application ends up linking - # to previously installed .so's. On IRIX instead of preloading - # newly built .so's we trick run-time linker to fail to find - # the installed .so by setting _RLD_ROOT variable. - *ELF\ 32*MIPS*) - #_RLD_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLD_LIST - _RLD_ROOT=/no/such/dir; export _RLD_ROOT - eval $rld_var=\"/usr/lib'${'$rld_var':+:$'$rld_var'}'\" - preload_var=_RLD_LIST - ;; - *ELF\ N32*MIPS*) - [ -n "$LD_LIBRARYN32_PATH" ] && rld_var=LD_LIBRARYN32_PATH - #_RLDN32_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLDN32_LIST - _RLDN32_ROOT=/no/such/dir; export _RLDN32_ROOT - eval $rld_var=\"/usr/lib32'${'$rld_var':+:$'$rld_var'}'\" - preload_var=_RLDN32_LIST - ;; - *ELF\ 64*MIPS*) - [ -n "$LD_LIBRARY64_PATH" ] && rld_var=LD_LIBRARY64_PATH - #_RLD64_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLD64_LIST - _RLD64_ROOT=/no/such/dir; export _RLD64_ROOT - eval $rld_var=\"/usr/lib64'${'$rld_var':+:$'$rld_var'}'\" - preload_var=_RLD64_LIST - ;; - esac - eval $rld_var=\"${THERE}'${'$rld_var':+:$'$rld_var'}'\"; export $rld_var - unset rld_var - ;; -*) LD_LIBRARY_PATH="${THERE}:$LD_LIBRARY_PATH" # Linux, ELF HP-UX - DYLD_LIBRARY_PATH="${THERE}:$DYLD_LIBRARY_PATH" # MacOS X - SHLIB_PATH="${THERE}:$SHLIB_PATH" # legacy HP-UX - LIBPATH="${THERE}:$LIBPATH" # AIX, OS/2 - export LD_LIBRARY_PATH DYLD_LIBRARY_PATH SHLIB_PATH LIBPATH - # Even though $PATH is adjusted [for Windows sake], it doesn't - # necessarily does the trick. Trouble is that with introduction - # of SafeDllSearchMode in XP/2003 it's more appropriate to copy - # .DLLs in vicinity of executable, which is done elsewhere... - if [ "$OSTYPE" != msdosdjgpp ]; then - PATH="${THERE}:$PATH"; export PATH - fi - ;; -esac - - - -cmd="$1"; [ -x "$cmd" ] || cmd="$cmd${EXE_EXT}" -shift -if [ $# -eq 0 ]; then - exec "$cmd" # old sh, such as Tru64 4.x, fails to expand empty "$@" -else - exec "$cmd" "$@" -fi