diff --git a/Feature-shim-cryptlib-support-sm2-signature-verify.patch b/Feature-shim-cryptlib-support-sm2-signature-verify.patch new file mode 100644 index 0000000000000000000000000000000000000000..105a0656c0beb9b92e7fa4e42b0907e5cfc72f7c --- /dev/null +++ b/Feature-shim-cryptlib-support-sm2-signature-verify.patch @@ -0,0 +1,1825 @@ +From 9137b68d161ccb95b1019c4885d0519ebbf4678a Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Mon, 7 Nov 2022 11:46:33 +0800 +Subject: [PATCH 4/5] shim cryptlib support sm2 signature verify + +Co-authored-by: Yusong Gao +Signed-off-by: Yusong Gao +Signed-off-by: Huaxin Lu +--- + Cryptlib/Hash/CryptSm3.c | 231 +++++++++++++++++++++ + Cryptlib/Include/openssl/crypto.h | 10 + + Cryptlib/Include/openssl/ec.h | 20 ++ + Cryptlib/Include/openssl/ecdsa.h | 7 + + Cryptlib/Include/openssl/err.h | 6 + + Cryptlib/Include/openssl/evp.h | 25 +++ + Cryptlib/Include/openssl/obj_mac.h | 33 +++ + Cryptlib/Include/openssl/opensslconf.h | 8 +- + Cryptlib/Include/openssl/x509.h | 7 + + Cryptlib/Library/BaseCryptLib.h | 111 ++++++++++ + Cryptlib/Makefile | 6 + + Cryptlib/OpenSSL/Makefile | 38 +++- + Cryptlib/OpenSSL/crypto/asn1/a_sign.c | 11 +- + Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c | 8 +- + Cryptlib/OpenSSL/crypto/asn1/x_req.c | 13 ++ + Cryptlib/OpenSSL/crypto/asn1/x_x509.c | 6 + + Cryptlib/OpenSSL/crypto/bn/bn_lib.c | 3 - + Cryptlib/OpenSSL/crypto/err/err.c | 1 + + Cryptlib/OpenSSL/crypto/evp/c_alld.c | 3 + + Cryptlib/OpenSSL/crypto/evp/digest.c | 62 +++++- + Cryptlib/OpenSSL/crypto/evp/evp_lib.c | 5 + + Cryptlib/OpenSSL/crypto/evp/evp_locl.h | 10 + + Cryptlib/OpenSSL/crypto/evp/m_sigver.c | 17 ++ + Cryptlib/OpenSSL/crypto/evp/p_lib.c | 44 ++++ + Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c | 16 +- + Cryptlib/OpenSSL/crypto/mem.c | 18 ++ + Cryptlib/OpenSSL/crypto/o_str.c | 87 ++++++++ + Cryptlib/OpenSSL/crypto/objects/obj_dat.h | 46 +++- + Cryptlib/OpenSSL/crypto/objects/obj_xref.h | 2 + + Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c | 34 ++- + Cryptlib/OpenSSL/crypto/x509/x_all.c | 142 +++++++++++++ + Cryptlib/Pk/CryptPkcs7Verify.c | 5 + + 32 files changed, 997 insertions(+), 38 deletions(-) + create mode 100644 Cryptlib/Hash/CryptSm3.c + +diff --git a/Cryptlib/Hash/CryptSm3.c b/Cryptlib/Hash/CryptSm3.c +new file mode 100644 +index 0000000..c522365 +--- /dev/null ++++ b/Cryptlib/Hash/CryptSm3.c +@@ -0,0 +1,231 @@ ++/** @file ++ SM3 Digest Wrapper Implementation over OpenSSL. ++ ++Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include "InternalCryptLib.h" ++#include ++ ++/** ++ Retrieves the size, in bytes, of the context buffer required for SM3 hash operations. ++ ++ @return The size, in bytes, of the context buffer required for SM3 hash operations. ++ ++**/ ++UINTN ++EFIAPI ++Sm3GetContextSize ( ++ VOID ++ ) ++{ ++ // ++ // Retrieves OpenSSL SM3 Context Size ++ // ++ return (UINTN) (sizeof (SM3_CTX)); ++} ++ ++/** ++ Initializes user-supplied memory pointed by Sm3Context as SM3 hash context for ++ subsequent use. ++ ++ If Sm3Context is NULL, then return FALSE. ++ ++ @param[out] Sm3Context Pointer to SM3 context being initialized. ++ ++ @retval TRUE SM3 context initialization succeeded. ++ @retval FALSE SM3 context initialization failed. ++ ++**/ ++BOOLEAN ++EFIAPI ++Sm3Init ( ++ OUT VOID *Sm3Context ++ ) ++{ ++ // ++ // Check input parameters. ++ // ++ if (Sm3Context == NULL) { ++ return FALSE; ++ } ++ ++ // ++ // OpenSSL SM3 Context Initialization ++ // ++ return (BOOLEAN) (sm3_init ((SM3_CTX *) Sm3Context)); ++} ++ ++/** ++ Makes a copy of an existing SM3 context. ++ ++ If Sm3Context is NULL, then return FALSE. ++ If NewSm3Context is NULL, then return FALSE. ++ ++ @param[in] Sm3Context Pointer to SM3 context being copied. ++ @param[out] NewSm3Context Pointer to new SM3 context. ++ ++ @retval TRUE SM3 context copy succeeded. ++ @retval FALSE SM3 context copy failed. ++ ++**/ ++BOOLEAN ++EFIAPI ++Sm3Duplicate ( ++ IN CONST VOID *Sm3Context, ++ OUT VOID *NewSm3Context ++ ) ++{ ++ // ++ // Check input parameters. ++ // ++ if (Sm3Context == NULL || NewSm3Context == NULL) { ++ return FALSE; ++ } ++ ++ CopyMem (NewSm3Context, (void *)Sm3Context, sizeof (SM3_CTX)); ++ ++ return TRUE; ++} ++ ++/** ++ Digests the input data and updates SM3 context. ++ ++ This function performs SM3 digest on a data buffer of the specified size. ++ It can be called multiple times to compute the digest of long or discontinuous data streams. ++ SM3 context should be already correctly initialized by Sm3Init(), and should not be finalized ++ by Sm3Final(). Behavior with invalid context is undefined. ++ ++ If Sm3Context is NULL, then return FALSE. ++ ++ @param[in, out] Sm3Context Pointer to the SM3 context. ++ @param[in] Data Pointer to the buffer containing the data to be hashed. ++ @param[in] DataSize Size of Data buffer in bytes. ++ ++ @retval TRUE SM3 data digest succeeded. ++ @retval FALSE SM3 data digest failed. ++ ++**/ ++BOOLEAN ++EFIAPI ++Sm3Update ( ++ IN OUT VOID *Sm3Context, ++ IN CONST VOID *Data, ++ IN UINTN DataSize ++ ) ++{ ++ // ++ // Check input parameters. ++ // ++ if (Sm3Context == NULL) { ++ return FALSE; ++ } ++ ++ // ++ // Check invalid parameters, in case that only DataLength was checked in OpenSSL ++ // ++ if (Data == NULL && DataSize != 0) { ++ return FALSE; ++ } ++ ++ // ++ // OpenSSL SM3 Hash Update ++ // ++ return (BOOLEAN) (sm3_update ((SM3_CTX *) Sm3Context, Data, DataSize)); ++} ++ ++/** ++ Completes computation of the SM3 digest value. ++ ++ This function completes SM3 hash computation and retrieves the digest value into ++ the specified memory. After this function has been called, the SM3 context cannot ++ be used again. ++ SM3 context should be already correctly initialized by Sm3Init(), and should not be ++ finalized by Sm3Final(). Behavior with invalid SM3 context is undefined. ++ ++ If Sm3Context is NULL, then return FALSE. ++ If HashValue is NULL, then return FALSE. ++ ++ @param[in, out] Sm3Context Pointer to the SM3 context. ++ @param[out] HashValue Pointer to a buffer that receives the SM3 digest ++ value (32 bytes). ++ ++ @retval TRUE SM3 digest computation succeeded. ++ @retval FALSE SM3 digest computation failed. ++ ++**/ ++BOOLEAN ++EFIAPI ++Sm3Final ( ++ IN OUT VOID *Sm3Context, ++ OUT UINT8 *HashValue ++ ) ++{ ++ // ++ // Check input parameters. ++ // ++ if (Sm3Context == NULL || HashValue == NULL) { ++ return FALSE; ++ } ++ ++ // ++ // OpenSSL SM3 Hash Finalization ++ // ++ return (BOOLEAN) (sm3_final (HashValue, (SM3_CTX *) Sm3Context)); ++} ++ ++/** ++ Computes the SM3 message digest of a input data buffer. ++ ++ This function performs the SM3 message digest of a given data buffer, and places ++ the digest value into the specified memory. ++ ++ If this interface is not supported, then return FALSE. ++ ++ @param[in] Data Pointer to the buffer containing the data to be hashed. ++ @param[in] DataSize Size of Data buffer in bytes. ++ @param[out] HashValue Pointer to a buffer that receives the SM3 digest ++ value (32 bytes). ++ ++ @retval TRUE SM3 digest computation succeeded. ++ @retval FALSE SM3 digest computation failed. ++ @retval FALSE This interface is not supported. ++ ++**/ ++BOOLEAN ++EFIAPI ++Sm3HashAll ( ++ IN CONST VOID *Data, ++ IN UINTN DataSize, ++ OUT UINT8 *HashValue ++ ) ++{ ++ // ++ // Check input parameters. ++ // ++ if (HashValue == NULL) { ++ return FALSE; ++ } ++ if (Data == NULL && DataSize != 0) { ++ return FALSE; ++ } ++ ++ // ++ // OpenSSL SM3 Hash Computation. ++ // ++ ++ SM3_CTX c; ++ sm3_init(&c); ++ sm3_update(&c, Data, DataSize); ++ sm3_final(HashValue, &c); ++ ++ return TRUE; ++} +diff --git a/Cryptlib/Include/openssl/crypto.h b/Cryptlib/Include/openssl/crypto.h +index e201a12..b0fbe1c 100644 +--- a/Cryptlib/Include/openssl/crypto.h ++++ b/Cryptlib/Include/openssl/crypto.h +@@ -380,6 +380,7 @@ int CRYPTO_is_mem_check_on(void); + # define is_MemCheck_on() CRYPTO_is_mem_check_on() + + # define OPENSSL_malloc(num) CRYPTO_malloc((int)num,OPENSSL_FILE,OPENSSL_LINE) ++# define OPENSSL_zalloc(num) CRYPTO_zalloc((int)num,OPENSSL_FILE,OPENSSL_LINE) + # define OPENSSL_strdup(str) CRYPTO_strdup((str),OPENSSL_FILE,OPENSSL_LINE) + # define OPENSSL_realloc(addr,num) \ + CRYPTO_realloc((char *)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE) +@@ -389,6 +390,8 @@ int CRYPTO_is_mem_check_on(void); + CRYPTO_remalloc((char **)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE) + # define OPENSSL_freeFunc CRYPTO_free + # define OPENSSL_free(addr) CRYPTO_free(addr) ++# define OPENSSL_clear_free(addr, num) \ ++ CRYPTO_clear_free(addr,num,OPENSSL_FILE,OPENSSL_LINE) + + # define OPENSSL_malloc_locked(num) \ + CRYPTO_malloc_locked((int)num,OPENSSL_FILE,OPENSSL_LINE) +@@ -399,6 +402,8 @@ unsigned long SSLeay(void); + + int OPENSSL_issetugid(void); + ++unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); ++ + /* An opaque type representing an implementation of "ex_data" support */ + typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; + /* Return an opaque pointer to the current "ex_data" implementation */ +@@ -533,12 +538,14 @@ void CRYPTO_get_mem_debug_functions(void (**m) + void *CRYPTO_malloc_locked(int num, const char *file, int line); + void CRYPTO_free_locked(void *ptr); + void *CRYPTO_malloc(int num, const char *file, int line); ++void *CRYPTO_zalloc(int num, const char *file, int line); + char *CRYPTO_strdup(const char *str, const char *file, int line); + void CRYPTO_free(void *ptr); + void *CRYPTO_realloc(void *addr, int num, const char *file, int line); + void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file, + int line); + void *CRYPTO_remalloc(void *addr, int num, const char *file, int line); ++void CRYPTO_clear_free(void *ptr, int num, const char *file, int line); + + void OPENSSL_cleanse(void *ptr, size_t len); + +@@ -651,10 +658,13 @@ void ERR_load_CRYPTO_strings(void); + # define CRYPTO_F_INT_DUP_EX_DATA 106 + # define CRYPTO_F_INT_FREE_EX_DATA 107 + # define CRYPTO_F_INT_NEW_EX_DATA 108 ++# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118 + + /* Reason codes. */ + # define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 + # define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100 ++# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 ++# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 + + #ifdef __cplusplus + } +diff --git a/Cryptlib/Include/openssl/ec.h b/Cryptlib/Include/openssl/ec.h +index 81e6faf..e315025 100644 +--- a/Cryptlib/Include/openssl/ec.h ++++ b/Cryptlib/Include/openssl/ec.h +@@ -254,6 +254,12 @@ BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group); + */ + int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); + ++/** Gets the order of an EC_GROUP ++ * \param group EC_GROUP object ++ * \return the group order ++ */ ++const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); ++ + /** Gets the cofactor of a EC_GROUP + * \param group EC_GROUP object + * \param cofactor BIGNUM to which the cofactor is copied +@@ -1053,6 +1059,17 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p) ++# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ ++ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ ++ EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) ++ ++# define EVP_PKEY_CTX_get1_id(ctx, id) \ ++ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ ++ EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) ++ ++# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ ++ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ ++ EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) + + # define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) + # define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +@@ -1064,6 +1081,9 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + # define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) + # define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) + # define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) ++# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) ++# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) ++# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) + /* KDF types */ + # define EVP_PKEY_ECDH_KDF_NONE 1 + # define EVP_PKEY_ECDH_KDF_X9_62 2 +diff --git a/Cryptlib/Include/openssl/ecdsa.h b/Cryptlib/Include/openssl/ecdsa.h +index a6f0930..e51d924 100644 +--- a/Cryptlib/Include/openssl/ecdsa.h ++++ b/Cryptlib/Include/openssl/ecdsa.h +@@ -90,6 +90,13 @@ ECDSA_SIG *ECDSA_SIG_new(void); + */ + void ECDSA_SIG_free(ECDSA_SIG *sig); + ++/** Accessor for r and s fields of ECDSA_SIG ++ * \param sig pointer to ECDSA_SIG structure ++ * \param pr pointer to BIGNUM pointer for r (may be NULL) ++ * \param ps pointer to BIGNUM pointer for s (may be NULL) ++ */ ++void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); ++ + /** DER encode content of ECDSA_SIG object (note: this function modifies *pp + * (*pp += length of the DER encoded signature)). + * \param sig pointer to the ECDSA_SIG object +diff --git a/Cryptlib/Include/openssl/err.h b/Cryptlib/Include/openssl/err.h +index 5a01980..c8286e1 100644 +--- a/Cryptlib/Include/openssl/err.h ++++ b/Cryptlib/Include/openssl/err.h +@@ -197,6 +197,8 @@ typedef struct err_state_st { + # define ERR_LIB_TS 47 + # define ERR_LIB_HMAC 48 + # define ERR_LIB_JPAKE 49 ++# define ERR_LIB_SM2 53 ++ + + # define ERR_LIB_USER 128 + +@@ -233,6 +235,7 @@ typedef struct err_state_st { + # define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) + # define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) + # define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) ++# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE) + + /* + * Borland C seems too stupid to be able to shift and do longs in the +@@ -304,6 +307,9 @@ typedef struct err_state_st { + # define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) + # define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) + # define ERR_R_DISABLED (5|ERR_R_FATAL) ++# define ERR_R_INIT_FAIL (6|ERR_R_FATAL) ++# define ERR_R_PASSED_INVALID_ARGUMENT (7) ++# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL) + + /* + * 99 is the maximum possible ERR_R_... code, higher values are reserved for +diff --git a/Cryptlib/Include/openssl/evp.h b/Cryptlib/Include/openssl/evp.h +index 376f260..4e1d9bb 100644 +--- a/Cryptlib/Include/openssl/evp.h ++++ b/Cryptlib/Include/openssl/evp.h +@@ -115,6 +115,7 @@ + # define EVP_PKEY_DH NID_dhKeyAgreement + # define EVP_PKEY_DHX NID_dhpublicnumber + # define EVP_PKEY_EC NID_X9_62_id_ecPublicKey ++# define EVP_PKEY_SM2 NID_sm2 + # define EVP_PKEY_HMAC NID_hmac + # define EVP_PKEY_CMAC NID_cmac + +@@ -122,6 +123,12 @@ + extern "C" { + #endif + ++/* ++ * Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag ++ * values in evp.h ++ */ ++#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400 ++ + /* + * Type needs to be a bit field Sub-type needs to be for variations on the + * method, as in, can it do arbitrary encryption.... +@@ -526,6 +533,8 @@ const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); + # define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) + # define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) + ++void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); ++ + int EVP_CIPHER_nid(const EVP_CIPHER *cipher); + # define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) + int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); +@@ -583,6 +592,9 @@ int EVP_Cipher(EVP_CIPHER_CTX *c, + # define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + ++EVP_MD_CTX *EVP_MD_CTX_new(void); ++int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); ++void EVP_MD_CTX_free(EVP_MD_CTX *ctx); + void EVP_MD_CTX_init(EVP_MD_CTX *ctx); + int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); + EVP_MD_CTX *EVP_MD_CTX_create(void); +@@ -666,6 +678,10 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, + const unsigned char *sig, size_t siglen); + ++int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen); ++ + int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, const unsigned char *iv, + EVP_PKEY *priv); +@@ -741,6 +757,9 @@ const EVP_MD *EVP_ripemd160(void); + # ifndef OPENSSL_NO_WHIRLPOOL + const EVP_MD *EVP_whirlpool(void); + # endif ++# ifndef OPENSSL_NO_SM3 ++const EVP_MD *EVP_sm3(void); ++# endif + const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ + # ifndef OPENSSL_NO_DES + const EVP_CIPHER *EVP_des_ecb(void); +@@ -954,10 +973,15 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey); + int EVP_PKEY_bits(EVP_PKEY *pkey); + int EVP_PKEY_size(EVP_PKEY *pkey); + int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); ++int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); + int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); + int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); + void *EVP_PKEY_get0(EVP_PKEY *pkey); + ++# ifndef OPENSSL_NO_SM2 ++int EVP_PKEY_is_sm2(EVP_PKEY *pkey); ++# endif ++ + # ifndef OPENSSL_NO_RSA + struct rsa_st; + int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +@@ -976,6 +1000,7 @@ struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); + # ifndef OPENSSL_NO_EC + struct ec_key_st; + int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); ++struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); + struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); + # endif + +diff --git a/Cryptlib/Include/openssl/obj_mac.h b/Cryptlib/Include/openssl/obj_mac.h +index 779c309..91b75e0 100644 +--- a/Cryptlib/Include/openssl/obj_mac.h ++++ b/Cryptlib/Include/openssl/obj_mac.h +@@ -4192,3 +4192,36 @@ + #define LN_jurisdictionCountryName "jurisdictionCountryName" + #define NID_jurisdictionCountryName 957 + #define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L ++ ++#define SN_ISO_CN "ISO-CN" ++#define LN_ISO_CN "ISO CN Member Body" ++#define NID_ISO_CN 958 ++#define OBJ_ISO_CN OBJ_member_body,156L ++ ++#define SN_oscca "oscca" ++#define NID_oscca 959 ++#define OBJ_oscca OBJ_ISO_CN,10197L ++ ++#define SN_sm_scheme "sm-scheme" ++#define NID_sm_scheme 960 ++#define OBJ_sm_scheme OBJ_oscca,1L ++ ++#define SN_sm2 "SM2" ++#define LN_sm2 "sm2" ++#define NID_sm2 961 ++#define OBJ_sm2 OBJ_sm_scheme,301L ++ ++#define SN_sm3 "SM3" ++#define LN_sm3 "sm3" ++#define NID_sm3 962 ++#define OBJ_sm3 OBJ_sm_scheme,401L ++ ++#define SN_sm3WithRSAEncryption "RSA-SM3" ++#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption" ++#define NID_sm3WithRSAEncryption 963 ++#define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L ++ ++#define SN_SM2_with_SM3 "SM2-SM3" ++#define LN_SM2_with_SM3 "SM2-with-SM3" ++#define NID_SM2_with_SM3 964 ++#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L +diff --git a/Cryptlib/Include/openssl/opensslconf.h b/Cryptlib/Include/openssl/opensslconf.h +index 4a36e9f..6f19ce6 100644 +--- a/Cryptlib/Include/openssl/opensslconf.h ++++ b/Cryptlib/Include/openssl/opensslconf.h +@@ -10,7 +10,6 @@ extern "C" { + #endif + #ifndef OPENSSL_DOING_MAKEDEPEND + +- + #ifndef OPENSSL_NO_BF + # define OPENSSL_NO_BF + #endif +@@ -41,8 +40,8 @@ extern "C" { + #ifndef OPENSSL_NO_DYNAMIC_ENGINE + # define OPENSSL_NO_DYNAMIC_ENGINE + #endif +-#ifndef OPENSSL_NO_EC +-# define OPENSSL_NO_EC ++#ifndef OPENSSL_NO_EC2M ++# define OPENSSL_NO_EC2M + #endif + #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + # define OPENSSL_NO_EC_NISTP_64_GCC_128 +@@ -50,9 +49,6 @@ extern "C" { + #ifndef OPENSSL_NO_ECDH + # define OPENSSL_NO_ECDH + #endif +-#ifndef OPENSSL_NO_ECDSA +-# define OPENSSL_NO_ECDSA +-#endif + #ifndef OPENSSL_NO_ENGINE + # define OPENSSL_NO_ENGINE + #endif +diff --git a/Cryptlib/Include/openssl/x509.h b/Cryptlib/Include/openssl/x509.h +index 6fa28eb..eda456b 100644 +--- a/Cryptlib/Include/openssl/x509.h ++++ b/Cryptlib/Include/openssl/x509.h +@@ -237,6 +237,9 @@ typedef struct X509_req_st { + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *sm2_id; ++# endif + } X509_REQ; + + typedef struct x509_cinf_st { +@@ -296,6 +299,10 @@ struct x509_st { + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; + # endif + X509_CERT_AUX *aux; ++ volatile int ex_cached; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *sm2_id; ++# endif + } /* X509 */ ; + + DECLARE_STACK_OF(X509) +diff --git a/Cryptlib/Library/BaseCryptLib.h b/Cryptlib/Library/BaseCryptLib.h +index 2df8bd2..a7fea2c 100644 +--- a/Cryptlib/Library/BaseCryptLib.h ++++ b/Cryptlib/Library/BaseCryptLib.h +@@ -52,6 +52,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + /// + #define SHA512_DIGEST_SIZE 64 + ++/// ++/// SM3 digest size in bytes ++/// ++#define SM3_DIGEST_SIZE 32 ++ + /// + /// TDES block size in bytes + /// +@@ -893,6 +898,112 @@ Sha512HashAll ( + OUT UINT8 *HashValue + ); + ++/** ++ Retrieves the size, in bytes, of the context buffer required for SM3 hash operations. ++ @return The size, in bytes, of the context buffer required for SM3 hash operations. ++**/ ++UINTN ++EFIAPI ++Sm3GetContextSize ( ++ VOID ++ ); ++ ++/** ++ Initializes user-supplied memory pointed by Sm3Context as SM3 hash context for ++ subsequent use. ++ If Sm3Context is NULL, then return FALSE. ++ @param[out] Sm3Context Pointer to SM3 context being initialized. ++ @retval TRUE SM3 context initialization succeeded. ++ @retval FALSE SM3 context initialization failed. ++**/ ++BOOLEAN ++EFIAPI ++Sm3Init ( ++ OUT VOID *Sm3Context ++ ); ++ ++/** ++ Makes a copy of an existing SM3 context. ++ If Sm3Context is NULL, then return FALSE. ++ If NewSm3Context is NULL, then return FALSE. ++ If this interface is not supported, then return FALSE. ++ @param[in] Sm3Context Pointer to SM3 context being copied. ++ @param[out] NewSm3Context Pointer to new SM3 context. ++ @retval TRUE SM3 context copy succeeded. ++ @retval FALSE SM3 context copy failed. ++ @retval FALSE This interface is not supported. ++**/ ++BOOLEAN ++EFIAPI ++Sm3Duplicate ( ++ IN CONST VOID *Sm3Context, ++ OUT VOID *NewSm3Context ++ ); ++ ++/** ++ Digests the input data and updates SM3 context. ++ This function performs SM3 digest on a data buffer of the specified size. ++ It can be called multiple times to compute the digest of long or discontinuous data streams. ++ SM3 context should be already correctly initialized by Sm3Init(), and should not be finalied ++ by Sm3Final(). Behavior with invalid context is undefined. ++ If Sm3Context is NULL, then return FALSE. ++ @param[in, out] Sm3Context Pointer to the SM3 context. ++ @param[in] Data Pointer to the buffer containing the data to be hashed. ++ @param[in] DataSize Size of Data buffer in bytes. ++ @retval TRUE SM3 data digest succeeded. ++ @retval FALSE SM3 data digest failed. ++**/ ++BOOLEAN ++EFIAPI ++Sm3Update ( ++ IN OUT VOID *Sm3Context, ++ IN CONST VOID *Data, ++ IN UINTN DataSize ++ ); ++ ++/** ++ Completes computation of the SM3 digest value. ++ This function completes SM3 hash computation and retrieves the digest value into ++ the specified memory. After this function has been called, the SM3 context cannot ++ be used again. ++ SM3 context should be already correctly initialized by Sm3Init(), and should not be ++ finalized by Sm3Final(). Behavior with invalid SM3 context is undefined. ++ If Sm3Context is NULL, then return FALSE. ++ If HashValue is NULL, then return FALSE. ++ @param[in, out] Sm3Context Pointer to the SM3 context. ++ @param[out] HashValue Pointer to a buffer that receives the SM3 digest ++ value (32 bytes). ++ @retval TRUE SM3 digest computation succeeded. ++ @retval FALSE SM3 digest computation failed. ++**/ ++BOOLEAN ++EFIAPI ++Sm3Final ( ++ IN OUT VOID *Sm3Context, ++ OUT UINT8 *HashValue ++ ); ++ ++/** ++ Computes the SM3 message digest of a input data buffer. ++ This function performs the SM3 message digest of a given data buffer, and places ++ the digest value into the specified memory. ++ If this interface is not supported, then return FALSE. ++ @param[in] Data Pointer to the buffer containing the data to be hashed. ++ @param[in] DataSize Size of Data buffer in bytes. ++ @param[out] HashValue Pointer to a buffer that receives the SM3 digest ++ value (32 bytes). ++ @retval TRUE SM3 digest computation succeeded. ++ @retval FALSE SM3 digest computation failed. ++ @retval FALSE This interface is not supported. ++**/ ++BOOLEAN ++EFIAPI ++Sm3HashAll ( ++ IN CONST VOID *Data, ++ IN UINTN DataSize, ++ OUT UINT8 *HashValue ++ ); ++ + //===================================================================================== + // MAC (Message Authentication Code) Primitive + //===================================================================================== +diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile +index 89fd5cd..7885a1a 100644 +--- a/Cryptlib/Makefile ++++ b/Cryptlib/Makefile +@@ -66,6 +66,12 @@ OBJS = Hash/CryptMd4Null.o \ + SysCall/BaseMemAllocation.o \ + SysCall/BaseStrings.o + ++ifdef SHIM_ENABLE_SM ++OBJS += Hash/CryptSm3.o ++else ++DEFINES += -DOPENSSL_NO_SM3 ++endif ++ + all: $(TARGET) + + libcryptlib.a: $(OBJS) +diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile +index 795f471..32fb235 100644 +--- a/Cryptlib/OpenSSL/Makefile ++++ b/Cryptlib/OpenSSL/Makefile +@@ -459,7 +459,43 @@ OBJS = crypto/cryptlib.o \ + crypto/ocsp/ocsp_err.o \ + crypto/cmac/cmac.o \ + crypto/cmac/cm_ameth.o \ +- crypto/cmac/cm_pmeth.o \ ++ crypto/cmac/cm_pmeth.o ++ ++ifdef SHIM_ENABLE_SM ++OBJS +=crypto/ec/ec_ameth.o \ ++ crypto/ec/ec_cvt.o \ ++ crypto/ec/eck_prn.o \ ++ crypto/ec/ec_oct.o \ ++ crypto/ec/ecp_smpl.o \ ++ crypto/ec/ec_asn1.o \ ++ crypto/ec/ec_err.o \ ++ crypto/ec/ec_pmeth.o \ ++ crypto/ec/ec_check.o \ ++ crypto/ec/ec_lib.o \ ++ crypto/ec/ecp_mont.o \ ++ crypto/ec/ecp_oct.o \ ++ crypto/ec/ec_curve.o \ ++ crypto/ec/ec_key.o \ ++ crypto/ec/ec_mult.o \ ++ crypto/ec/ecp_nist.o \ ++ crypto/ec/ec_print.o \ ++ crypto/ecdsa/ecs_asn1.o \ ++ crypto/ecdsa/ecs_err.o \ ++ crypto/ecdsa/ecs_lib.o \ ++ crypto/ecdsa/ecs_ossl.o \ ++ crypto/ecdsa/ecs_sign.o \ ++ crypto/ecdsa/ecs_vrf.o \ ++ crypto/sm3/sm3.o \ ++ crypto/sm3/m_sm3.o \ ++ crypto/sm2/sm2_err.o \ ++ crypto/sm2/sm2_pmeth.o \ ++ crypto/sm2/sm2_sign.o ++else ++DEFINES +=-DOPENSSL_NO_EC \ ++ -DOPENSSL_NO_ECDSA \ ++ -DOPENSSL_NO_SM2 \ ++ -DOPENSSL_NO_SM3 ++endif + + all: $(TARGET) + +diff --git a/Cryptlib/OpenSSL/crypto/asn1/a_sign.c b/Cryptlib/OpenSSL/crypto/asn1/a_sign.c +index 51c6a0c..68a2ae6 100644 +--- a/Cryptlib/OpenSSL/crypto/asn1/a_sign.c ++++ b/Cryptlib/OpenSSL/crypto/asn1/a_sign.c +@@ -238,7 +238,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + int signid, paramtype; +- int rv; ++ int rv, pkey_id; + + type = EVP_MD_CTX_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); +@@ -268,10 +268,17 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + + if (rv == 2) { + if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { ++ ++ pkey_id = ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_id(pkey) == NID_sm2 ? NID_sm2 : ++#endif ++ pkey->ameth->pkey_id; ++ + if (!pkey->ameth || + !OBJ_find_sigid_by_algs(&signid, + EVP_MD_nid(type), +- pkey->ameth->pkey_id)) { ++ pkey_id)) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, + ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + return 0; +diff --git a/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c b/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c +index 43ddebb..db3d27d 100644 +--- a/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c ++++ b/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c +@@ -64,6 +64,7 @@ + # include + #endif + #include "asn1_locl.h" ++#include + + extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; + extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; +@@ -72,6 +73,8 @@ extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth; + extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; + extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; + extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth; ++extern const EVP_PKEY_ASN1_METHOD sm2_asn1_meth; ++ + + /* Keep this sorted in type order !! */ + static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { +@@ -97,7 +100,10 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { + &cmac_asn1_meth, + #endif + #ifndef OPENSSL_NO_DH +- &dhx_asn1_meth ++ &dhx_asn1_meth, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ &sm2_asn1_meth, + #endif + }; + +diff --git a/Cryptlib/OpenSSL/crypto/asn1/x_req.c b/Cryptlib/OpenSSL/crypto/asn1/x_req.c +index ae293aa..575564e 100644 +--- a/Cryptlib/OpenSSL/crypto/asn1/x_req.c ++++ b/Cryptlib/OpenSSL/crypto/asn1/x_req.c +@@ -114,3 +114,16 @@ ASN1_SEQUENCE_ref(X509_REQ, 0, CRYPTO_LOCK_X509_REQ) = { + IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + + IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) ++ ++#ifndef OPENSSL_NO_SM2 ++void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id) ++{ ++ ASN1_OCTET_STRING_free(x->sm2_id); ++ x->sm2_id = sm2_id; ++} ++ ++ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x) ++{ ++ return x->sm2_id; ++} ++#endif +diff --git a/Cryptlib/OpenSSL/crypto/asn1/x_x509.c b/Cryptlib/OpenSSL/crypto/asn1/x_x509.c +index aada4a8..8969918 100644 +--- a/Cryptlib/OpenSSL/crypto/asn1/x_x509.c ++++ b/Cryptlib/OpenSSL/crypto/asn1/x_x509.c +@@ -98,6 +98,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + #ifndef OPENSSL_NO_RFC3779 + ret->rfc3779_addr = NULL; + ret->rfc3779_asid = NULL; ++#endif ++#ifndef OPENSSL_NO_SM2 ++ ret->sm2_id = NULL; + #endif + ret->aux = NULL; + ret->crldp = NULL; +@@ -123,6 +126,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); + #endif ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++#endif + + if (ret->name != NULL) + OPENSSL_free(ret->name); +diff --git a/Cryptlib/OpenSSL/crypto/bn/bn_lib.c b/Cryptlib/OpenSSL/crypto/bn/bn_lib.c +index 2671f35..10b78f5 100644 +--- a/Cryptlib/OpenSSL/crypto/bn/bn_lib.c ++++ b/Cryptlib/OpenSSL/crypto/bn/bn_lib.c +@@ -496,9 +496,6 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) + if (bn_wexpand(a, b->top) == NULL) + return (NULL); + +- if (!a || !b || !a->d || !b->d) +- return (NULL); +- + #if 1 + A = a->d; + B = b->d; +diff --git a/Cryptlib/OpenSSL/crypto/err/err.c b/Cryptlib/OpenSSL/crypto/err/err.c +index e225145..aac5956 100644 +--- a/Cryptlib/OpenSSL/crypto/err/err.c ++++ b/Cryptlib/OpenSSL/crypto/err/err.c +@@ -155,6 +155,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = { + {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"}, + {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"}, + {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"}, + {0, NULL}, + }; + +diff --git a/Cryptlib/OpenSSL/crypto/evp/c_alld.c b/Cryptlib/OpenSSL/crypto/evp/c_alld.c +index fdbe3ee..6cad383 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/c_alld.c ++++ b/Cryptlib/OpenSSL/crypto/evp/c_alld.c +@@ -111,4 +111,7 @@ void OpenSSL_add_all_digests(void) + #ifndef OPENSSL_NO_WHIRLPOOL + EVP_add_digest(EVP_whirlpool()); + #endif ++#ifndef OPENSSL_NO_SM3 ++ EVP_add_digest(EVP_sm3()); ++#endif + } +diff --git a/Cryptlib/OpenSSL/crypto/evp/digest.c b/Cryptlib/OpenSSL/crypto/evp/digest.c +index 4db1796..ffc03ef 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/digest.c ++++ b/Cryptlib/OpenSSL/crypto/evp/digest.c +@@ -122,6 +122,48 @@ + # include "evp_locl.h" + #endif + ++/* This call frees resources associated with the context */ ++int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) ++{ ++ if (ctx == NULL) ++ return 1; ++ ++ /* ++ * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because ++ * sometimes only copies of the context are ever finalised. ++ */ ++ if (ctx->digest && ctx->digest->cleanup ++ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) ++ ctx->digest->cleanup(ctx); ++ if (ctx->digest && ctx->digest->ctx_size && ctx->md_data ++ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { ++ OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); ++ } ++ /* ++ * pctx should be freed by the user of EVP_MD_CTX ++ * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set ++ */ ++ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) ++ EVP_PKEY_CTX_free(ctx->pctx); ++#ifndef OPENSSL_NO_ENGINE ++ ENGINE_finish(ctx->engine); ++#endif ++ OPENSSL_cleanse(ctx, sizeof(*ctx)); ++ ++ return 1; ++} ++ ++EVP_MD_CTX *EVP_MD_CTX_new(void) ++{ ++ return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); ++} ++ ++void EVP_MD_CTX_free(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_reset(ctx); ++ OPENSSL_free(ctx); ++} ++ + void EVP_MD_CTX_init(EVP_MD_CTX *ctx) + { + memset(ctx, '\0', sizeof *ctx); +@@ -139,7 +181,7 @@ EVP_MD_CTX *EVP_MD_CTX_create(void) + + int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) + { +- EVP_MD_CTX_init(ctx); ++ EVP_MD_CTX_reset(ctx); + return EVP_DigestInit_ex(ctx, type, NULL); + } + +@@ -264,7 +306,7 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) + { + int ret; + ret = EVP_DigestFinal_ex(ctx, md, size); +- EVP_MD_CTX_cleanup(ctx); ++ EVP_MD_CTX_reset(ctx); + return ret; + } + +@@ -291,7 +333,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) + + int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) + { +- EVP_MD_CTX_init(out); ++ EVP_MD_CTX_reset(out); + return EVP_MD_CTX_copy_ex(out, in); + } + +@@ -315,9 +357,19 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) + EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE); + } else + tmp_buf = NULL; +- EVP_MD_CTX_cleanup(out); ++ EVP_MD_CTX_reset(out); + memcpy(out, in, sizeof *out); + ++ /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */ ++ EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); ++ ++ /* Null these variables, since they are getting fixed up ++ * properly below. Anything else may cause a memleak and/or ++ * double free if any of the memory allocations below fail ++ */ ++ out->md_data = NULL; ++ out->pctx = NULL; ++ + if (in->md_data && out->digest->ctx_size) { + if (tmp_buf) + out->md_data = tmp_buf; +@@ -336,7 +388,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) + if (in->pctx) { + out->pctx = EVP_PKEY_CTX_dup(in->pctx); + if (!out->pctx) { +- EVP_MD_CTX_cleanup(out); ++ EVP_MD_CTX_reset(out); + return 0; + } + } +diff --git a/Cryptlib/OpenSSL/crypto/evp/evp_lib.c b/Cryptlib/OpenSSL/crypto/evp/evp_lib.c +index 7e0bab9..5945494 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/evp_lib.c ++++ b/Cryptlib/OpenSSL/crypto/evp/evp_lib.c +@@ -389,3 +389,8 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags) + { + return (ctx->flags & flags); + } ++ ++void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) ++{ ++ return ctx->md_data; ++} +diff --git a/Cryptlib/OpenSSL/crypto/evp/evp_locl.h b/Cryptlib/OpenSSL/crypto/evp/evp_locl.h +index 2bb709a..1d179ef 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/evp_locl.h ++++ b/Cryptlib/OpenSSL/crypto/evp/evp_locl.h +@@ -324,6 +324,16 @@ struct evp_pkey_method_st { + int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); + int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); ++ int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, ++ const unsigned char *tbs, size_t tbslen); ++ int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen); ++ int (*check) (EVP_PKEY *pkey); ++ int (*public_check) (EVP_PKEY *pkey); ++ int (*param_check) (EVP_PKEY *pkey); ++ ++ int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + } /* EVP_PKEY_METHOD */ ; + + void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx); +diff --git a/Cryptlib/OpenSSL/crypto/evp/m_sigver.c b/Cryptlib/OpenSSL/crypto/evp/m_sigver.c +index 4492d20..771b659 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/m_sigver.c ++++ b/Cryptlib/OpenSSL/crypto/evp/m_sigver.c +@@ -110,6 +110,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + return 1; + if (!EVP_DigestInit_ex(ctx, type, e)) + return 0; ++ /* ++ * This indicates the current algorithm requires ++ * special treatment before hashing the tbs-message. ++ */ ++ if (ctx->pctx->pmeth->digest_custom != NULL) ++ return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); ++ + return 1; + } + +@@ -201,3 +208,13 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + return r; + return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen); + } ++ ++int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, ++ size_t siglen, const unsigned char *tbs, size_t tbslen) ++{ ++ if (ctx->pctx->pmeth->digestverify != NULL) ++ return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); ++ if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) ++ return -1; ++ return EVP_DigestVerifyFinal(ctx, sigret, siglen); ++} +diff --git a/Cryptlib/OpenSSL/crypto/evp/p_lib.c b/Cryptlib/OpenSSL/crypto/evp/p_lib.c +index 545d04f..c95d038 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/p_lib.c ++++ b/Cryptlib/OpenSSL/crypto/evp/p_lib.c +@@ -259,6 +259,24 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) + return pkey_set_type(pkey, EVP_PKEY_NONE, str, len); + } + ++int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) ++{ ++ if (pkey->type == type) { ++ return 1; /* it already is that type */ ++ } ++ ++ /* ++ * The application is requesting to alias this to a different pkey type, ++ * but not one that resolves to the base type. ++ */ ++ if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) { ++ return 0; ++ } ++ ++ pkey->type = type; ++ return 1; ++} ++ + int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) + { + if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) +@@ -272,6 +290,24 @@ void *EVP_PKEY_get0(EVP_PKEY *pkey) + return pkey->pkey.ptr; + } + ++# ifndef OPENSSL_NO_SM2 ++int EVP_PKEY_is_sm2(EVP_PKEY *pkey) ++{ ++ EC_KEY *eckey; ++ const EC_GROUP *group; ++ if (pkey == NULL) { ++ return 0; ++ } ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC ++ && (eckey = EVP_PKEY_get1_EC_KEY(pkey)) != NULL ++ && (group = EC_KEY_get0_group(eckey)) != NULL ++ && EC_GROUP_get_curve_name(group) == NID_sm2) { ++ return 1; ++ } ++ return EVP_PKEY_id(pkey) == EVP_PKEY_SM2; ++} ++# endif ++ + #ifndef OPENSSL_NO_RSA + int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) + { +@@ -322,6 +358,14 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) + return ret; + } + ++EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) ++{ ++ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { ++ return NULL; ++ } ++ return pkey->pkey.ec; ++} ++ + EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) + { + if (pkey->type != EVP_PKEY_EC) { +diff --git a/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c b/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c +index d066862..8e52917 100644 +--- a/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c ++++ b/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c +@@ -75,7 +75,7 @@ STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; + + extern const EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth; + extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth, cmac_pkey_meth; +-extern const EVP_PKEY_METHOD dhx_pkey_meth; ++extern const EVP_PKEY_METHOD dhx_pkey_meth, sm2_pkey_meth; + + static const EVP_PKEY_METHOD *standard_methods[] = { + #ifndef OPENSSL_NO_RSA +@@ -95,7 +95,10 @@ static const EVP_PKEY_METHOD *standard_methods[] = { + &cmac_pkey_meth, + #endif + #ifndef OPENSSL_NO_DH +- &dhx_pkey_meth ++ &dhx_pkey_meth, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ &sm2_pkey_meth, + #endif + }; + +@@ -135,9 +138,9 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) + EVP_PKEY_CTX *ret; + const EVP_PKEY_METHOD *pmeth; + if (id == -1) { +- if (!pkey || !pkey->ameth) ++ if (!pkey) + return NULL; +- id = pkey->ameth->pkey_id; ++ id = pkey->type; + } + #ifndef OPENSSL_NO_ENGINE + if (pkey && pkey->engine) +@@ -365,6 +368,10 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) + return -1; + ++/* Skip the operation checks since this is called in a very early stage */ ++ if (ctx->pmeth->digest_custom != NULL) ++ goto doit; ++ + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); + return -1; +@@ -375,6 +382,7 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + return -1; + } + ++doit: + ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); + + if (ret == -2) +diff --git a/Cryptlib/OpenSSL/crypto/mem.c b/Cryptlib/OpenSSL/crypto/mem.c +index 06c3960..ae5a165 100644 +--- a/Cryptlib/OpenSSL/crypto/mem.c ++++ b/Cryptlib/OpenSSL/crypto/mem.c +@@ -456,3 +456,21 @@ long CRYPTO_get_mem_debug_options(void) + return get_debug_options_func(); + return 0; + } ++ ++void *CRYPTO_zalloc(int num, const char *file, int line) ++{ ++ void *ret = CRYPTO_malloc(num, file, line); ++ ++ if (ret != NULL) ++ memset(ret, 0, num); ++ return ret; ++} ++ ++void CRYPTO_clear_free(void *str, int num, const char *file, int line) ++{ ++ if (str == NULL) ++ return; ++ if (num) ++ OPENSSL_cleanse(str, num); ++ CRYPTO_free(str); ++} +diff --git a/Cryptlib/OpenSSL/crypto/o_str.c b/Cryptlib/OpenSSL/crypto/o_str.c +index 7e61cde..c46c631 100644 +--- a/Cryptlib/OpenSSL/crypto/o_str.c ++++ b/Cryptlib/OpenSSL/crypto/o_str.c +@@ -60,6 +60,8 @@ + #include + #include + #include "o_str.h" ++#include "openssl/crypto.h" ++#include "openssl/err.h" + + #if !defined(OPENSSL_IMPLEMENTS_strncasecmp) && \ + !defined(OPENSSL_SYSNAME_WIN32) && !defined(OPENSSL_SYSNAME_WINCE) && \ +@@ -114,3 +116,88 @@ int OPENSSL_memcmp(const void *v1, const void *v2, size_t n) + + return ret; + } ++ ++int OPENSSL_hexchar2int(unsigned char c) ++{ ++#ifdef CHARSET_EBCDIC ++ c = os_toebcdic[c]; ++#endif ++ ++ switch (c) { ++ case '0': ++ return 0; ++ case '1': ++ return 1; ++ case '2': ++ return 2; ++ case '3': ++ return 3; ++ case '4': ++ return 4; ++ case '5': ++ return 5; ++ case '6': ++ return 6; ++ case '7': ++ return 7; ++ case '8': ++ return 8; ++ case '9': ++ return 9; ++ case 'a': case 'A': ++ return 0x0A; ++ case 'b': case 'B': ++ return 0x0B; ++ case 'c': case 'C': ++ return 0x0C; ++ case 'd': case 'D': ++ return 0x0D; ++ case 'e': case 'E': ++ return 0x0E; ++ case 'f': case 'F': ++ return 0x0F; ++ } ++ return -1; ++} ++ ++/* ++ * Give a string of hex digits convert to a buffer ++ */ ++unsigned char *OPENSSL_hexstr2buf(const char *str, long *len) ++{ ++ unsigned char *hexbuf, *q; ++ unsigned char ch, cl; ++ int chi, cli; ++ const unsigned char *p; ++ size_t s; ++ ++ s = strlen(str); ++ if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) { ++ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ for (p = (const unsigned char *)str, q = hexbuf; *p; ) { ++ ch = *p++; ++ if (ch == ':') ++ continue; ++ cl = *p++; ++ if (!cl) { ++ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ++ CRYPTO_R_ODD_NUMBER_OF_DIGITS); ++ OPENSSL_free(hexbuf); ++ return NULL; ++ } ++ cli = OPENSSL_hexchar2int(cl); ++ chi = OPENSSL_hexchar2int(ch); ++ if (cli < 0 || chi < 0) { ++ OPENSSL_free(hexbuf); ++ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT); ++ return NULL; ++ } ++ *q++ = (unsigned char)((chi << 4) | cli); ++ } ++ ++ if (len) ++ *len = q - hexbuf; ++ return hexbuf; ++} +diff --git a/Cryptlib/OpenSSL/crypto/objects/obj_dat.h b/Cryptlib/OpenSSL/crypto/objects/obj_dat.h +index b7e3cf2..30ea261 100644 +--- a/Cryptlib/OpenSSL/crypto/objects/obj_dat.h ++++ b/Cryptlib/OpenSSL/crypto/objects/obj_dat.h +@@ -62,12 +62,12 @@ + * [including the GNU Public Licence.] + */ + +-#define NUM_NID 958 +-#define NUM_SN 951 +-#define NUM_LN 951 +-#define NUM_OBJ 890 ++#define NUM_NID 965 ++#define NUM_SN 958 ++#define NUM_LN 958 ++#define NUM_OBJ 897 + +-static const unsigned char lvalues[6255]={ ++static const unsigned char lvalues[6301]={ + 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ +@@ -952,6 +952,13 @@ static const unsigned char lvalues[6255]={ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x01,/* [6221] OBJ_jurisdictionLocalityName */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,/* [6232] OBJ_jurisdictionStateOrProvinceName */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,/* [6243] OBJ_jurisdictionCountryName */ ++0x2A,0x81,0x1C, /* [6254] OBJ_ISO_CN */ ++0x2A,0x81,0x1C,0xCF,0x55, /* [6257] OBJ_oscca */ ++0x2A,0x81,0x1C,0xCF,0x55,0x01, /* [6262] OBJ_sm_scheme */ ++0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2D, /* [6268] OBJ_sm2 */ ++0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11, /* [6276] OBJ_sm3 */ ++0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78, /* [6284] OBJ_sm3WithRSAEncryption */ ++0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [6292] OBJ_SM2_with_SM3 */ + }; + + static const ASN1_OBJECT nid_objs[NUM_NID]={ +@@ -2514,6 +2521,14 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={ + NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0}, + {"jurisdictionC","jurisdictionCountryName", + NID_jurisdictionCountryName,11,&(lvalues[6243]),0}, ++{"ISO-CN","ISO CN Member Body",NID_ISO_CN,3,&(lvalues[6254]),0}, ++{"oscca","oscca",NID_oscca,5,&(lvalues[6257]),0}, ++{"sm-scheme","sm-scheme",NID_sm_scheme,6,&(lvalues[6262]),0}, ++{"SM2","sm2",NID_sm2,8,&(lvalues[6268]),0}, ++{"SM3","sm3",NID_sm3,8,&(lvalues[6276]),0}, ++{"RSA-SM3","sm3WithRSAEncryption",NID_sm3WithRSAEncryption,8, ++ &(lvalues[6284]),0}, ++{"SM2-SM3","SM2-with-SM3",NID_SM2_with_SM3,8,&(lvalues[6292]),0}, + }; + + static const unsigned int sn_objs[NUM_SN]={ +@@ -2615,6 +2630,7 @@ static const unsigned int sn_objs[NUM_SN]={ + 36, /* "IDEA-ECB" */ + 46, /* "IDEA-OFB" */ + 181, /* "ISO" */ ++958, /* "ISO-CN" */ + 183, /* "ISO-US" */ + 645, /* "ITU-T" */ + 646, /* "JOINT-ISO-ITU-T" */ +@@ -2685,6 +2701,10 @@ static const unsigned int sn_objs[NUM_SN]={ + 668, /* "RSA-SHA256" */ + 669, /* "RSA-SHA384" */ + 670, /* "RSA-SHA512" */ ++963, /* "RSA-SM3" */ ++961, /* "SM2" */ ++964, /* "SM2-SM3" */ ++962, /* "SM3" */ + 919, /* "RSAES-OAEP" */ + 912, /* "RSASSA-PSS" */ + 777, /* "SEED-CBC" */ +@@ -3176,6 +3196,7 @@ static const unsigned int sn_objs[NUM_SN]={ + 77, /* "nsSslServerName" */ + 681, /* "onBasis" */ + 491, /* "organizationalStatus" */ ++959, /* "oscca" */ + 475, /* "otherMailbox" */ + 876, /* "owner" */ + 489, /* "pagerTelephoneNumber" */ +@@ -3422,6 +3443,7 @@ static const unsigned int sn_objs[NUM_SN]={ + 52, /* "signingTime" */ + 454, /* "simpleSecurityObject" */ + 496, /* "singleLevelQuality" */ ++960, /* "sm-scheme" */ + 387, /* "snmpv2" */ + 660, /* "street" */ + 85, /* "subjectAltName" */ +@@ -3519,6 +3541,7 @@ static const unsigned int ln_objs[NUM_LN]={ + 294, /* "IPSec End System" */ + 295, /* "IPSec Tunnel" */ + 296, /* "IPSec User" */ ++958, /* "ISO CN Member Body" */ + 182, /* "ISO Member Body" */ + 183, /* "ISO US Member Body" */ + 667, /* "Independent" */ +@@ -3573,6 +3596,7 @@ static const unsigned int ln_objs[NUM_LN]={ + 2, /* "RSA Data Security, Inc. PKCS" */ + 188, /* "S/MIME" */ + 167, /* "S/MIME Capabilities" */ ++964, /* "SM2-with-SM3" */ + 387, /* "SNMPv2" */ + 512, /* "Secure Electronic Transactions" */ + 386, /* "Security" */ +@@ -4105,6 +4129,7 @@ static const unsigned int ln_objs[NUM_LN]={ + 17, /* "organizationName" */ + 491, /* "organizationalStatus" */ + 18, /* "organizationalUnitName" */ ++959, /* "oscca" */ + 475, /* "otherMailbox" */ + 876, /* "owner" */ + 935, /* "pSpecified" */ +@@ -4379,6 +4404,10 @@ static const unsigned int ln_objs[NUM_LN]={ + 52, /* "signingTime" */ + 454, /* "simpleSecurityObject" */ + 496, /* "singleLevelQuality" */ ++960, /* "sm-scheme" */ ++961, /* "sm2" */ ++962, /* "sm3" */ ++963, /* "sm3WithRSAEncryption" */ + 16, /* "stateOrProvinceName" */ + 660, /* "streetAddress" */ + 498, /* "subtreeMaximumQuality" */ +@@ -4444,6 +4473,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ + 512, /* OBJ_id_set 2 23 42 */ + 678, /* OBJ_wap 2 23 43 */ + 435, /* OBJ_pss 0 9 2342 */ ++958, /* OBJ_ISO_CN 1 2 156 */ + 183, /* OBJ_ISO_US 1 2 840 */ + 381, /* OBJ_iana 1 3 6 1 */ + 677, /* OBJ_certicom_arc 1 3 132 */ +@@ -4659,6 +4689,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ + 637, /* OBJ_set_brand_Diners 2 23 42 8 30 */ + 638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */ + 639, /* OBJ_set_brand_JCB 2 23 42 8 35 */ ++959, /* OBJ_oscca 1 2 156 10197 */ + 805, /* OBJ_cryptopro 1 2 643 2 2 */ + 806, /* OBJ_cryptocom 1 2 643 2 9 */ + 184, /* OBJ_X9_57 1 2 840 10040 */ +@@ -4733,6 +4764,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ + 745, /* OBJ_wap_wsg_idm_ecid_wtls12 2 23 43 1 4 12 */ + 804, /* OBJ_whirlpool 1 0 10118 3 0 55 */ + 124, /* OBJ_rle_compression 1 1 1 1 666 1 */ ++960, /* OBJ_sm_scheme 1 2 156 10197 1 */ + 773, /* OBJ_kisa 1 2 410 200004 */ + 807, /* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */ + 808, /* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */ +@@ -4836,6 +4868,10 @@ static const unsigned int obj_objs[NUM_OBJ]={ + 768, /* OBJ_camellia_256_ofb128 0 3 4401 5 3 1 9 43 */ + 759, /* OBJ_camellia_256_cfb128 0 3 4401 5 3 1 9 44 */ + 437, /* OBJ_pilot 0 9 2342 19200300 100 */ ++961, /* OBJ_sm2 1 2 156 10197 1 301 */ ++962, /* OBJ_sm3 1 2 156 10197 1 401 */ ++964, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */ ++963, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */ + 776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */ + 777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */ + 779, /* OBJ_seed_cfb128 1 2 410 200004 1 5 */ +diff --git a/Cryptlib/OpenSSL/crypto/objects/obj_xref.h b/Cryptlib/OpenSSL/crypto/objects/obj_xref.h +index e453e99..cf08a14 100644 +--- a/Cryptlib/OpenSSL/crypto/objects/obj_xref.h ++++ b/Cryptlib/OpenSSL/crypto/objects/obj_xref.h +@@ -56,6 +56,7 @@ static const nid_triple sigoid_srt[] = { + NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, + NID_dh_cofactor_kdf}, ++ {NID_SM2_with_SM3, NID_sm3, NID_sm2}, + }; + + static const nid_triple *const sigoid_srt_xref[] = { +@@ -96,4 +97,5 @@ static const nid_triple *const sigoid_srt_xref[] = { + &sigoid_srt[26], + &sigoid_srt[27], + &sigoid_srt[28], ++ &sigoid_srt[40], + }; +diff --git a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c +index dd6c73f..846fcf8 100644 +--- a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c ++++ b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c +@@ -1036,10 +1036,10 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + ASN1_OCTET_STRING *os; + EVP_MD_CTX mdc_tmp, *mdc; + int ret = 0, i; +- int md_type; ++ int md_type, is_sm2 = 0; + STACK_OF(X509_ATTRIBUTE) *sk; + BIO *btmp; +- EVP_PKEY *pkey; ++ EVP_PKEY *pkey = NULL; + + EVP_MD_CTX_init(&mdc_tmp); + +@@ -1074,6 +1074,18 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + btmp = BIO_next(btmp); + } + ++#ifndef OPENSSL_NO_SM2 ++ pkey = X509_get_pubkey(x509); ++ if (!pkey) ++ goto err; ++ ++ if (EVP_PKEY_is_sm2(pkey)) { ++ is_sm2 = 1; ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) ++ goto err; ++ } ++#endif ++ + /* + * mdc is the digest ctx that we want, unless there are attributes, in + * which case the digest is the signed attributes +@@ -1114,7 +1126,12 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + goto err; + } + +- if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) ++ ret = is_sm2 ? EVP_DigestVerifyInit(&mdc_tmp, NULL, EVP_get_digestbynid(md_type), NULL, pkey) : ++ EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL); ++ if (!ret) ++ goto err; ++ ++ if (!EVP_DigestVerifyInit(&mdc_tmp, NULL, EVP_get_digestbynid(md_type), NULL, pkey)) + goto err; + + alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, +@@ -1131,14 +1148,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + } + + os = si->enc_digest; +- pkey = X509_get_pubkey(x509); +- if (!pkey) { +- ret = -1; +- goto err; +- } +- +- i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); +- EVP_PKEY_free(pkey); ++ i = is_sm2 ? EVP_DigestVerifyFinal(&mdc_tmp, os->data, os->length) : ++ EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); + if (i <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); + ret = -1; +@@ -1146,6 +1157,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + } else + ret = 1; + err: ++ EVP_PKEY_free(pkey); + EVP_MD_CTX_cleanup(&mdc_tmp); + return (ret); + } +diff --git a/Cryptlib/OpenSSL/crypto/x509/x_all.c b/Cryptlib/OpenSSL/crypto/x509/x_all.c +index 0f26c54..0228582 100644 +--- a/Cryptlib/OpenSSL/crypto/x509/x_all.c ++++ b/Cryptlib/OpenSSL/crypto/x509/x_all.c +@@ -71,16 +71,158 @@ + # include + #endif + ++#ifndef OPENSSL_NO_SM2 ++ ++# include "openssl/asn1.h" ++# include "openssl/evp.h" ++# include "crypto/asn1/asn1_locl.h" ++ ++static int common_verify_sm2(void *data, EVP_PKEY *pkey, ++ int mdnid, int pknid, int req) ++{ ++ X509 *x = NULL; ++ X509_REQ *r = NULL; ++ EVP_MD_CTX ctx; ++ unsigned char *buf_in = NULL; ++ int ret = -1, inl = 0; ++ size_t inll = 0; ++ EVP_PKEY_CTX *pctx = NULL; ++ const EVP_MD *type = EVP_get_digestbynid(mdnid); ++ ASN1_BIT_STRING *signature = NULL; ++ ASN1_OCTET_STRING *sm2_id = NULL; ++ ASN1_VALUE *tbv = NULL; ++ ++ if (type == NULL) { ++ goto err; ++ } ++ ++ if (pkey == NULL) { ++ return -1; ++ } ++ ++ if (req == 1) { ++ r = (X509_REQ *)data; ++ signature = r->signature; ++ sm2_id = r->sm2_id; ++ tbv = (ASN1_VALUE *)&r->req_info; ++ } else { ++ x = (X509 *)data; ++ signature = x->signature; ++ sm2_id = x->sm2_id; ++ tbv = (ASN1_VALUE *)x->cert_info; ++ } ++ ++ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { ++ return -1; ++ } ++ ++ EVP_MD_CTX_init(&ctx); ++ ++ /* Check public key OID matches public key type */ ++ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { ++ goto err; ++ } ++ ++ if (!EVP_PKEY_set_type(pkey, EVP_PKEY_SM2)) { ++ ret = 0; ++ goto err; ++ } ++ pctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (pctx == NULL) { ++ ret = 0; ++ goto err; ++ } ++ /* NOTE: we tolerate no actual ID, to provide maximum flexibility */ ++ if (sm2_id != NULL ++ && EVP_PKEY_CTX_set1_id(pctx, sm2_id->data, sm2_id->length) != 1) { ++ ret = 0; ++ goto err; ++ } ++ EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); ++ ++ if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) { ++ ret = 0; ++ goto err; ++ } ++ ++ inl = ASN1_item_i2d(tbv, &buf_in, ++ req == 1 ? ++ ASN1_ITEM_rptr(X509_REQ_INFO) : ++ ASN1_ITEM_rptr(X509_CINF)); ++ if (inl <= 0) { ++ goto err; ++ } ++ if (buf_in == NULL) { ++ goto err; ++ } ++ inll = inl; ++ ++ ret = EVP_DigestVerify(&ctx, signature->data, ++ (size_t)signature->length, buf_in, inl); ++ if (ret <= 0) { ++ goto err; ++ } ++ ret = 1; ++ err: ++ OPENSSL_cleanse(buf_in, inll); ++ EVP_MD_CTX_cleanup(&ctx); ++ EVP_PKEY_CTX_free(pctx); ++ return ret; ++} ++ ++static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 0); ++} ++ ++static int x509_req_verify_sm2(X509_REQ *x, EVP_PKEY *pkey, ++ int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 1); ++} ++ ++#endif ++ ++ ++ + int X509_verify(X509 *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++#endif + if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature)) + return 0; ++ ++#ifndef OPENSSL_NO_SM2 ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg->algorithm), ++ &mdnid, &pknid)) { ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), a->sig_alg, + a->signature, a->cert_info, r)); + } + + int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++ ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg->algorithm), ++ &mdnid, &pknid)) { ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_req_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + a->sig_alg, a->signature, a->req_info, r)); + } +diff --git a/Cryptlib/Pk/CryptPkcs7Verify.c b/Cryptlib/Pk/CryptPkcs7Verify.c +index c189384..7fa8c41 100644 +--- a/Cryptlib/Pk/CryptPkcs7Verify.c ++++ b/Cryptlib/Pk/CryptPkcs7Verify.c +@@ -878,6 +878,11 @@ Pkcs7Verify ( + if (EVP_add_digest (EVP_sha512 ()) == 0) { + return FALSE; + } ++#ifndef OPENSSL_NO_SM3 ++ if (EVP_add_digest (EVP_sm3 ()) == 0) { ++ return FALSE; ++ } ++#endif + if (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA) == 0) { + return FALSE; + } +-- +2.33.0 + diff --git a/Feature-shim-openssl-add-ec-support.patch b/Feature-shim-openssl-add-ec-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a95a826954e6b9f9b26dc8c3540e862a139fa74 --- /dev/null +++ b/Feature-shim-openssl-add-ec-support.patch @@ -0,0 +1,9511 @@ +From c298798dcb50c72d1584ddec34e1cab01fee7096 Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Mon, 7 Nov 2022 11:43:34 +0800 +Subject: [PATCH 1/5] shim openssl add ec support + +Co-authored-by: Yusong Gao +Signed-off-by: Yusong Gao +Signed-off-by: Huaxin Lu +--- + Cryptlib/OpenSSL/crypto/ec/ec_ameth.c | 646 +++++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_asn1.c | 1278 ++++++++++++++++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_check.c | 120 +++ + Cryptlib/OpenSSL/crypto/ec/ec_curve.c | 343 ++++++ + Cryptlib/OpenSSL/crypto/ec/ec_cvt.c | 154 +++ + Cryptlib/OpenSSL/crypto/ec/ec_err.c | 332 ++++++ + Cryptlib/OpenSSL/crypto/ec/ec_key.c | 564 ++++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_lcl.h | 470 ++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_lib.c | 1077 +++++++++++++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_mult.c | 913 ++++++++++++++++ + Cryptlib/OpenSSL/crypto/ec/ec_oct.c | 163 +++ + Cryptlib/OpenSSL/crypto/ec/ec_pmeth.c | 410 +++++++ + Cryptlib/OpenSSL/crypto/ec/ec_print.c | 179 ++++ + Cryptlib/OpenSSL/crypto/ec/eck_prn.c | 330 ++++++ + Cryptlib/OpenSSL/crypto/ec/ecp_mont.c | 308 ++++++ + Cryptlib/OpenSSL/crypto/ec/ecp_nist.c | 220 ++++ + Cryptlib/OpenSSL/crypto/ec/ecp_oct.c | 428 ++++++++ + Cryptlib/OpenSSL/crypto/ec/ecp_smpl.c | 1418 +++++++++++++++++++++++++ + 18 files changed, 9353 insertions(+) + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_ameth.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_asn1.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_check.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_curve.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_cvt.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_err.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_key.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_lcl.h + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_lib.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_mult.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_oct.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_pmeth.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ec_print.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/eck_prn.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ecp_mont.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ecp_nist.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ecp_oct.c + create mode 100644 Cryptlib/OpenSSL/crypto/ec/ecp_smpl.c + +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_ameth.c b/Cryptlib/OpenSSL/crypto/ec/ec_ameth.c +new file mode 100644 +index 0000000..d55dcca +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_ameth.c +@@ -0,0 +1,646 @@ ++/* ++ * Written by Dr Stephen N Henson (steve@openssl.org) 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 ++#include "cryptlib.h" ++#include ++#include ++#include ++#include ++#include "asn1_locl.h" ++#include "ec_lcl.h" ++ ++#ifndef OPENSSL_NO_SM2 ++const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = { ++ EVP_PKEY_SM2, ++ EVP_PKEY_EC, ++ ASN1_PKEY_ALIAS ++}; ++#endif ++ ++extern UINTN EFIAPI console_print(const CHAR16 *fmt, ...); ++ ++static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) ++{ ++ const EC_GROUP *group; ++ int nid; ++ if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { ++ ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); ++ return 0; ++ } ++ if (EC_GROUP_get_asn1_flag(group) ++ && (nid = EC_GROUP_get_curve_name(group))) ++ /* we have a 'named curve' => just set the OID */ ++ { ++ *ppval = OBJ_nid2obj(nid); ++ *pptype = V_ASN1_OBJECT; ++ } else { /* explicit parameters */ ++ ++ ASN1_STRING *pstr = NULL; ++ pstr = ASN1_STRING_new(); ++ if (!pstr) ++ return 0; ++ pstr->length = i2d_ECParameters(ec_key, &pstr->data); ++ if (pstr->length <= 0) { ++ ASN1_STRING_free(pstr); ++ ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); ++ return 0; ++ } ++ *ppval = pstr; ++ *pptype = V_ASN1_SEQUENCE; ++ } ++ return 1; ++} ++ ++static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) ++{ ++ EC_KEY *ec_key = pkey->pkey.ec; ++ void *pval = NULL; ++ int ptype; ++ unsigned char *penc = NULL, *p; ++ int penclen; ++ ++ if (!eckey_param2type(&ptype, &pval, ec_key)) { ++ ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); ++ return 0; ++ } ++ penclen = i2o_ECPublicKey(ec_key, NULL); ++ if (penclen <= 0) ++ goto err; ++ penc = OPENSSL_malloc(penclen); ++ if (!penc) ++ goto err; ++ p = penc; ++ penclen = i2o_ECPublicKey(ec_key, &p); ++ if (penclen <= 0) ++ goto err; ++ if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ++ ptype, pval, penc, penclen)) ++ return 1; ++ err: ++ if (ptype == V_ASN1_OBJECT) ++ ASN1_OBJECT_free(pval); ++ else ++ ASN1_STRING_free(pval); ++ if (penc) ++ OPENSSL_free(penc); ++ return 0; ++} ++ ++static EC_KEY *eckey_type2param(int ptype, void *pval) ++{ ++ EC_KEY *eckey = NULL; ++ if (ptype == V_ASN1_SEQUENCE) { ++ ASN1_STRING *pstr = pval; ++ const unsigned char *pm = NULL; ++ int pmlen; ++ pm = pstr->data; ++ pmlen = pstr->length; ++ if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) { ++ ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); ++ goto ecerr; ++ } ++ } else if (ptype == V_ASN1_OBJECT) { ++ ASN1_OBJECT *poid = pval; ++ EC_GROUP *group; ++ ++ /* ++ * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID ++ */ ++ if ((eckey = EC_KEY_new()) == NULL) { ++ ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); ++ goto ecerr; ++ } ++ group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); ++ if (group == NULL){ ++ goto ecerr;} ++ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); ++ if (EC_KEY_set_group(eckey, group) == 0) { ++ goto ecerr; ++ } ++ EC_GROUP_free(group); ++ } else { ++ ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); ++ goto ecerr; ++ } ++ ++ return eckey; ++ ++ ecerr: ++ if (eckey) ++ EC_KEY_free(eckey); ++ return NULL; ++} ++ ++static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) ++{ ++ const unsigned char *p = NULL; ++ void *pval; ++ int ptype, pklen; ++ EC_KEY *eckey = NULL; ++ X509_ALGOR *palg; ++ ++ if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) ++ return 0; ++ X509_ALGOR_get0(NULL, &ptype, &pval, palg); ++ ++ eckey = eckey_type2param(ptype, pval); ++ ++ if (!eckey) { ++ ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); ++ return 0; ++ } ++ ++ /* We have parameters now set public key */ ++ if (!o2i_ECPublicKey(&eckey, &p, pklen)) { ++ ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); ++ goto ecerr; ++ } ++ ++ EVP_PKEY_assign_EC_KEY(pkey, eckey); ++ return 1; ++ ++ ecerr: ++ if (eckey) ++ EC_KEY_free(eckey); ++ return 0; ++} ++ ++static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) ++{ ++ int r; ++ const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); ++ const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), ++ *pb = EC_KEY_get0_public_key(b->pkey.ec); ++ if (group == NULL || pa == NULL || pb == NULL) ++ return -2; ++ r = EC_POINT_cmp(group, pa, pb, NULL); ++ if (r == 0) ++ return 1; ++ if (r == 1) ++ return 0; ++ return -2; ++} ++ ++static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) ++{ ++ const unsigned char *p = NULL; ++ void *pval; ++ int ptype, pklen; ++ EC_KEY *eckey = NULL; ++ X509_ALGOR *palg; ++ ++ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) ++ return 0; ++ X509_ALGOR_get0(NULL, &ptype, &pval, palg); ++ ++ eckey = eckey_type2param(ptype, pval); ++ ++ if (!eckey) ++ goto ecliberr; ++ ++ /* We have parameters now set private key */ ++ if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { ++ ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); ++ goto ecerr; ++ } ++ ++ /* calculate public key (if necessary) */ ++ if (EC_KEY_get0_public_key(eckey) == NULL) { ++ const BIGNUM *priv_key; ++ const EC_GROUP *group; ++ EC_POINT *pub_key; ++ /* ++ * the public key was not included in the SEC1 private key => ++ * calculate the public key ++ */ ++ group = EC_KEY_get0_group(eckey); ++ pub_key = EC_POINT_new(group); ++ if (pub_key == NULL) { ++ ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ++ goto ecliberr; ++ } ++ if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { ++ EC_POINT_free(pub_key); ++ ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ++ goto ecliberr; ++ } ++ priv_key = EC_KEY_get0_private_key(eckey); ++ if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { ++ EC_POINT_free(pub_key); ++ ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ++ goto ecliberr; ++ } ++ if (EC_KEY_set_public_key(eckey, pub_key) == 0) { ++ EC_POINT_free(pub_key); ++ ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ++ goto ecliberr; ++ } ++ EC_POINT_free(pub_key); ++ } ++ ++ EVP_PKEY_assign_EC_KEY(pkey, eckey); ++ return 1; ++ ++ ecliberr: ++ ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ++ ecerr: ++ if (eckey) ++ EC_KEY_free(eckey); ++ return 0; ++} ++ ++static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) ++{ ++ EC_KEY ec_key = *(pkey->pkey.ec); ++ unsigned char *ep, *p; ++ int eplen, ptype; ++ void *pval; ++ unsigned int old_flags; ++ ++ if (!eckey_param2type(&ptype, &pval, &ec_key)) { ++ ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); ++ return 0; ++ } ++ ++ /* set the private key */ ++ ++ /* ++ * do not include the parameters in the SEC1 private key see PKCS#11 ++ * 12.11 ++ */ ++ old_flags = EC_KEY_get_enc_flags(&ec_key); ++ EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); ++ ++ eplen = i2d_ECPrivateKey(&ec_key, NULL); ++ if (!eplen) { ++ ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); ++ return 0; ++ } ++ ep = (unsigned char *)OPENSSL_malloc(eplen); ++ if (!ep) { ++ ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ p = ep; ++ if (!i2d_ECPrivateKey(&ec_key, &p)) { ++ OPENSSL_free(ep); ++ ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); ++ return 0; ++ } ++ ++ if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, ++ ptype, pval, ep, eplen)) ++ return 0; ++ ++ return 1; ++} ++ ++static int int_ec_size(const EVP_PKEY *pkey) ++{ ++ return ECDSA_size(pkey->pkey.ec); ++} ++ ++static int ec_bits(const EVP_PKEY *pkey) ++{ ++ BIGNUM *order = BN_new(); ++ const EC_GROUP *group; ++ int ret; ++ ++ if (!order) { ++ ERR_clear_error(); ++ return 0; ++ } ++ group = EC_KEY_get0_group(pkey->pkey.ec); ++ if (!EC_GROUP_get_order(group, order, NULL)) { ++ ERR_clear_error(); ++ return 0; ++ } ++ ++ ret = BN_num_bits(order); ++ BN_free(order); ++ return ret; ++} ++ ++static int ec_missing_parameters(const EVP_PKEY *pkey) ++{ ++ if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) ++ return 1; ++ return 0; ++} ++ ++static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) ++{ ++ EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); ++ if (group == NULL) ++ return 0; ++ if (EC_KEY_set_group(to->pkey.ec, group) == 0) ++ return 0; ++ EC_GROUP_free(group); ++ return 1; ++} ++ ++static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) ++{ ++ const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), ++ *group_b = EC_KEY_get0_group(b->pkey.ec); ++ if (group_a == NULL || group_b == NULL) ++ return -2; ++ if (EC_GROUP_cmp(group_a, group_b, NULL)) ++ return 0; ++ else ++ return 1; ++} ++ ++static void int_ec_free(EVP_PKEY *pkey) ++{ ++ EC_KEY_free(pkey->pkey.ec); ++} ++ ++static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) ++{ ++ unsigned char *buffer = NULL; ++ const char *ecstr; ++ size_t buf_len = 0, i; ++ int ret = 0, reason = ERR_R_BIO_LIB; ++ BIGNUM *pub_key = NULL, *order = NULL; ++ BN_CTX *ctx = NULL; ++ const EC_GROUP *group; ++ const EC_POINT *public_key; ++ const BIGNUM *priv_key; ++ ++ if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { ++ reason = ERR_R_PASSED_NULL_PARAMETER; ++ goto err; ++ } ++ ++ ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ reason = ERR_R_MALLOC_FAILURE; ++ goto err; ++ } ++ ++ if (ktype > 0) { ++ public_key = EC_KEY_get0_public_key(x); ++ if (public_key != NULL) { ++ if ((pub_key = EC_POINT_point2bn(group, public_key, ++ EC_KEY_get_conv_form(x), NULL, ++ ctx)) == NULL) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ buf_len = (size_t)BN_num_bytes(pub_key); ++ } ++ } ++ ++ if (ktype == 2) { ++ priv_key = EC_KEY_get0_private_key(x); ++ if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) ++ buf_len = i; ++ } else ++ priv_key = NULL; ++ ++ if (ktype > 0) { ++ buf_len += 10; ++ if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { ++ reason = ERR_R_MALLOC_FAILURE; ++ goto err; ++ } ++ } ++ if (ktype == 2) ++ ecstr = "Private-Key"; ++ else if (ktype == 1) ++ ecstr = "Public-Key"; ++ else ++ ecstr = "ECDSA-Parameters"; ++ ++ if (!BIO_indent(bp, off, 128)) ++ goto err; ++ if ((order = BN_new()) == NULL) ++ goto err; ++ if (!EC_GROUP_get_order(group, order, NULL)) ++ goto err; ++ if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) ++ goto err; ++ ++ if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, ++ buffer, off)) ++ goto err; ++ if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, ++ buffer, off)) ++ goto err; ++ if (!ECPKParameters_print(bp, group, off)) ++ goto err; ++ ret = 1; ++ err: ++ if (!ret) ++ ECerr(EC_F_DO_EC_KEY_PRINT, reason); ++ if (pub_key) ++ BN_free(pub_key); ++ if (order) ++ BN_free(order); ++ if (ctx) ++ BN_CTX_free(ctx); ++ if (buffer != NULL) ++ OPENSSL_free(buffer); ++ return (ret); ++} ++ ++static int eckey_param_decode(EVP_PKEY *pkey, ++ const unsigned char **pder, int derlen) ++{ ++ EC_KEY *eckey; ++ if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) { ++ ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); ++ return 0; ++ } ++ EVP_PKEY_assign_EC_KEY(pkey, eckey); ++ return 1; ++} ++ ++static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) ++{ ++ return i2d_ECParameters(pkey->pkey.ec, pder); ++} ++ ++static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ++ ASN1_PCTX *ctx) ++{ ++ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); ++} ++ ++static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ++ ASN1_PCTX *ctx) ++{ ++ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); ++} ++ ++static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ++ ASN1_PCTX *ctx) ++{ ++ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); ++} ++ ++static int old_ec_priv_decode(EVP_PKEY *pkey, ++ const unsigned char **pder, int derlen) ++{ ++ EC_KEY *ec; ++ if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) { ++ ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); ++ return 0; ++ } ++ EVP_PKEY_assign_EC_KEY(pkey, ec); ++ return 1; ++} ++ ++static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) ++{ ++ return i2d_ECPrivateKey(pkey->pkey.ec, pder); ++} ++ ++static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) ++{ ++ switch (op) { ++ case ASN1_PKEY_CTRL_PKCS7_SIGN: ++ if (arg1 == 0) { ++ int snid, hnid; ++ X509_ALGOR *alg1, *alg2; ++ PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); ++ if (alg1 == NULL || alg1->algorithm == NULL) ++ return -1; ++ hnid = OBJ_obj2nid(alg1->algorithm); ++ if (hnid == NID_undef) ++ return -1; ++ if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) ++ return -1; ++ X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); ++ } ++ return 1; ++#ifndef OPENSSL_NO_CMS ++ case ASN1_PKEY_CTRL_CMS_SIGN: ++ if (arg1 == 0) { ++ int snid, hnid; ++ X509_ALGOR *alg1, *alg2; ++ CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); ++ if (alg1 == NULL || alg1->algorithm == NULL) ++ return -1; ++ hnid = OBJ_obj2nid(alg1->algorithm); ++ if (hnid == NID_undef) ++ return -1; ++ if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) ++ return -1; ++ X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); ++ } ++ return 1; ++ ++ case ASN1_PKEY_CTRL_CMS_ENVELOPE: ++ if (arg1 == 1) ++ return ecdh_cms_decrypt(arg2); ++ else if (arg1 == 0) ++ return ecdh_cms_encrypt(arg2); ++ return -2; ++ ++ case ASN1_PKEY_CTRL_CMS_RI_TYPE: ++ *(int *)arg2 = CMS_RECIPINFO_AGREE; ++ return 1; ++#endif ++ ++ case ASN1_PKEY_CTRL_DEFAULT_MD_NID: ++ /* For SM2, the only valid digest-alg is SM3 */ ++ *(int *)arg2 = NID_sm3; ++ return 1; ++ ++ default: ++ return -2; ++ ++ } ++ ++} ++ ++const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { ++ EVP_PKEY_EC, ++ EVP_PKEY_EC, ++ 0, ++ "EC", ++ "OpenSSL EC algorithm", ++ ++ eckey_pub_decode, ++ eckey_pub_encode, ++ eckey_pub_cmp, ++ eckey_pub_print, ++ ++ eckey_priv_decode, ++ eckey_priv_encode, ++ eckey_priv_print, ++ ++ int_ec_size, ++ ec_bits, ++ ++ eckey_param_decode, ++ eckey_param_encode, ++ ec_missing_parameters, ++ ec_copy_parameters, ++ ec_cmp_parameters, ++ eckey_param_print, ++ 0, ++ ++ int_ec_free, ++ ec_pkey_ctrl, ++ old_ec_priv_decode, ++ old_ec_priv_encode ++}; +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_asn1.c b/Cryptlib/OpenSSL/crypto/ec/ec_asn1.c +new file mode 100644 +index 0000000..cc0ce8e +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_asn1.c +@@ -0,0 +1,1278 @@ ++/* crypto/ec/ec_asn1.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * 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 ++#include "ec_lcl.h" ++#include ++#include ++#include ++ ++int EC_GROUP_get_basis_type(const EC_GROUP *group) ++{ ++ int i = 0; ++ ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != ++ NID_X9_62_characteristic_two_field) ++ /* everything else is currently not supported */ ++ return 0; ++ ++ while (group->poly[i] != 0) ++ i++; ++ ++ if (i == 4) ++ return NID_X9_62_ppBasis; ++ else if (i == 2) ++ return NID_X9_62_tpBasis; ++ else ++ /* everything else is currently not supported */ ++ return 0; ++} ++ ++/* some structures needed for the asn1 encoding */ ++typedef struct x9_62_pentanomial_st { ++ long k1; ++ long k2; ++ long k3; ++} X9_62_PENTANOMIAL; ++ ++typedef struct x9_62_characteristic_two_st { ++ long m; ++ ASN1_OBJECT *type; ++ union { ++ char *ptr; ++ /* NID_X9_62_onBasis */ ++ ASN1_NULL *onBasis; ++ /* NID_X9_62_tpBasis */ ++ ASN1_INTEGER *tpBasis; ++ /* NID_X9_62_ppBasis */ ++ X9_62_PENTANOMIAL *ppBasis; ++ /* anything else */ ++ ASN1_TYPE *other; ++ } p; ++} X9_62_CHARACTERISTIC_TWO; ++ ++typedef struct x9_62_fieldid_st { ++ ASN1_OBJECT *fieldType; ++ union { ++ char *ptr; ++ /* NID_X9_62_prime_field */ ++ ASN1_INTEGER *prime; ++ /* NID_X9_62_characteristic_two_field */ ++ X9_62_CHARACTERISTIC_TWO *char_two; ++ /* anything else */ ++ ASN1_TYPE *other; ++ } p; ++} X9_62_FIELDID; ++ ++typedef struct x9_62_curve_st { ++ ASN1_OCTET_STRING *a; ++ ASN1_OCTET_STRING *b; ++ ASN1_BIT_STRING *seed; ++} X9_62_CURVE; ++ ++typedef struct ec_parameters_st { ++ long version; ++ X9_62_FIELDID *fieldID; ++ X9_62_CURVE *curve; ++ ASN1_OCTET_STRING *base; ++ ASN1_INTEGER *order; ++ ASN1_INTEGER *cofactor; ++} ECPARAMETERS; ++ ++struct ecpk_parameters_st { ++ int type; ++ union { ++ ASN1_OBJECT *named_curve; ++ ECPARAMETERS *parameters; ++ ASN1_NULL *implicitlyCA; ++ } value; ++} /* ECPKPARAMETERS */ ; ++ ++/* SEC1 ECPrivateKey */ ++typedef struct ec_privatekey_st { ++ long version; ++ ASN1_OCTET_STRING *privateKey; ++ ECPKPARAMETERS *parameters; ++ ASN1_BIT_STRING *publicKey; ++} EC_PRIVATEKEY; ++ ++/* the OpenSSL ASN.1 definitions */ ++ASN1_SEQUENCE(X9_62_PENTANOMIAL) = { ++ ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), ++ ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), ++ ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) ++} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) ++ ++DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) ++IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) ++ ++ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY); ++ ++ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { ++ ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), ++ ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), ++ ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) ++} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); ++ ++ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { ++ ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), ++ ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), ++ ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) ++} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) ++ ++DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) ++IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) ++ ++ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY); ++ ++ASN1_ADB(X9_62_FIELDID) = { ++ ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), ++ ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) ++} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL); ++ ++ASN1_SEQUENCE(X9_62_FIELDID) = { ++ ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), ++ ASN1_ADB_OBJECT(X9_62_FIELDID) ++} ASN1_SEQUENCE_END(X9_62_FIELDID) ++ ++ASN1_SEQUENCE(X9_62_CURVE) = { ++ ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), ++ ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), ++ ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) ++} ASN1_SEQUENCE_END(X9_62_CURVE) ++ ++ASN1_SEQUENCE(ECPARAMETERS) = { ++ ASN1_SIMPLE(ECPARAMETERS, version, LONG), ++ ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), ++ ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), ++ ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), ++ ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), ++ ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) ++} ASN1_SEQUENCE_END(ECPARAMETERS) ++ ++DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) ++IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) ++ ++ASN1_CHOICE(ECPKPARAMETERS) = { ++ ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), ++ ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), ++ ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) ++} 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_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 declarations of internal function */ ++ ++/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ ++static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); ++/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ ++static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); ++/* ++ * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS ++ * object ++ */ ++static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); ++/* ++ * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP ++ * object ++ */ ++static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, ++ ECPARAMETERS *); ++/* ++ * ec_asn1_pkparameters2group() creates a EC_GROUP object from a ++ * ECPKPARAMETERS object ++ */ ++static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); ++/* ++ * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a ++ * EC_GROUP object ++ */ ++static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, ++ ECPKPARAMETERS *); ++ ++/* the function definitions */ ++ ++static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) ++{ ++ int ok = 0, nid; ++ BIGNUM *tmp = NULL; ++ ++ if (group == NULL || field == NULL) ++ return 0; ++ ++ /* clear the old values (if necessary) */ ++ if (field->fieldType != NULL) ++ ASN1_OBJECT_free(field->fieldType); ++ if (field->p.other != NULL) ++ ASN1_TYPE_free(field->p.other); ++ ++ nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); ++ /* set OID for the field */ ++ if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); ++ goto err; ++ } ++ ++ if (nid == NID_X9_62_prime_field) { ++ if ((tmp = BN_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ /* the parameters are specified by the prime number p */ ++ if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); ++ goto err; ++ } ++ /* set the prime number */ ++ field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL); ++ if (field->p.prime == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ } else /* nid == NID_X9_62_characteristic_two_field */ ++#ifdef OPENSSL_NO_EC2M ++ { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); ++ goto err; ++ } ++#else ++ { ++ int field_type; ++ X9_62_CHARACTERISTIC_TWO *char_two; ++ ++ field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); ++ char_two = field->p.char_two; ++ ++ if (char_two == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ char_two->m = (long)EC_GROUP_get_degree(group); ++ ++ field_type = EC_GROUP_get_basis_type(group); ++ ++ if (field_type == 0) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); ++ goto err; ++ } ++ /* set base type OID */ ++ if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); ++ goto err; ++ } ++ ++ if (field_type == NID_X9_62_tpBasis) { ++ unsigned int k; ++ ++ if (!EC_GROUP_get_trinomial_basis(group, &k)) ++ goto err; ++ ++ char_two->p.tpBasis = ASN1_INTEGER_new(); ++ if (!char_two->p.tpBasis) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ } else if (field_type == NID_X9_62_ppBasis) { ++ unsigned int k1, k2, k3; ++ ++ if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) ++ goto err; ++ ++ char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); ++ if (!char_two->p.ppBasis) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /* set k? values */ ++ char_two->p.ppBasis->k1 = (long)k1; ++ char_two->p.ppBasis->k2 = (long)k2; ++ char_two->p.ppBasis->k3 = (long)k3; ++ } else { /* field_type == NID_X9_62_onBasis */ ++ ++ /* for ONB the parameters are (asn1) NULL */ ++ char_two->p.onBasis = ASN1_NULL_new(); ++ if (!char_two->p.onBasis) { ++ ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } ++ } ++#endif ++ ++ ok = 1; ++ ++ err:if (tmp) ++ BN_free(tmp); ++ return (ok); ++} ++ ++static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) ++{ ++ int ok = 0, nid; ++ BIGNUM *tmp_1 = NULL, *tmp_2 = NULL; ++ unsigned char *buffer_1 = NULL, *buffer_2 = NULL, ++ *a_buf = NULL, *b_buf = NULL; ++ size_t len_1, len_2; ++ unsigned char char_zero = 0; ++ ++ if (!group || !curve || !curve->a || !curve->b) ++ return 0; ++ ++ if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); ++ ++ /* get a and b */ ++ if (nid == NID_X9_62_prime_field) { ++ if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#ifndef OPENSSL_NO_EC2M ++ else { /* nid == NID_X9_62_characteristic_two_field */ ++ ++ if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#endif ++ len_1 = (size_t)BN_num_bytes(tmp_1); ++ len_2 = (size_t)BN_num_bytes(tmp_2); ++ ++ if (len_1 == 0) { ++ /* len_1 == 0 => a == 0 */ ++ a_buf = &char_zero; ++ len_1 = 1; ++ } else { ++ if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); ++ goto err; ++ } ++ a_buf = buffer_1; ++ } ++ ++ if (len_2 == 0) { ++ /* len_2 == 0 => b == 0 */ ++ b_buf = &char_zero; ++ len_2 = 1; ++ } else { ++ if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); ++ goto err; ++ } ++ b_buf = buffer_2; ++ } ++ ++ /* set a and b */ ++ if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) || ++ !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ ++ /* set the seed (optional) */ ++ if (group->seed) { ++ if (!curve->seed) ++ if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); ++ curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; ++ if (!ASN1_BIT_STRING_set(curve->seed, group->seed, ++ (int)group->seed_len)) { ++ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ } else { ++ if (curve->seed) { ++ ASN1_BIT_STRING_free(curve->seed); ++ curve->seed = NULL; ++ } ++ } ++ ++ ok = 1; ++ ++ err:if (buffer_1) ++ OPENSSL_free(buffer_1); ++ if (buffer_2) ++ OPENSSL_free(buffer_2); ++ if (tmp_1) ++ BN_free(tmp_1); ++ if (tmp_2) ++ BN_free(tmp_2); ++ return (ok); ++} ++ ++static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group, ++ ECPARAMETERS *param) ++{ ++ int ok = 0; ++ size_t len = 0; ++ ECPARAMETERS *ret = NULL; ++ BIGNUM *tmp = NULL; ++ unsigned char *buffer = NULL; ++ const EC_POINT *point = NULL; ++ point_conversion_form_t form; ++ ++ if ((tmp = BN_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (param == NULL) { ++ if ((ret = ECPARAMETERS_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } else ++ ret = param; ++ ++ /* set the version (always one) */ ++ ret->version = (long)0x1; ++ ++ /* set the fieldID */ ++ if (!ec_asn1_group2fieldid(group, ret->fieldID)) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /* set the curve */ ++ if (!ec_asn1_group2curve(group, ret->curve)) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /* set the base point */ ++ if ((point = EC_GROUP_get0_generator(group)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); ++ goto err; ++ } ++ ++ form = EC_GROUP_get_point_conversion_form(group); ++ ++ len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); ++ if (len == 0) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); ++ goto err; ++ } ++ if ((buffer = OPENSSL_malloc(len)) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ ++ /* set the order */ ++ if (!EC_GROUP_get_order(group, tmp, NULL)) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); ++ goto err; ++ } ++ ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); ++ if (ret->order == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ ++ /* set the cofactor (optional) */ ++ if (EC_GROUP_get_cofactor(group, tmp, NULL)) { ++ ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); ++ if (ret->cofactor == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ } ++ ++ ok = 1; ++ ++ err:if (!ok) { ++ if (ret && !param) ++ ECPARAMETERS_free(ret); ++ ret = NULL; ++ } ++ if (tmp) ++ BN_free(tmp); ++ if (buffer) ++ OPENSSL_free(buffer); ++ return (ret); ++} ++ ++ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, ++ ECPKPARAMETERS *params) ++{ ++ int ok = 1, tmp; ++ ECPKPARAMETERS *ret = params; ++ ++ if (ret == NULL) { ++ if ((ret = ECPKPARAMETERS_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ } else { ++ if (ret->type == 0 && ret->value.named_curve) ++ ASN1_OBJECT_free(ret->value.named_curve); ++ else if (ret->type == 1 && ret->value.parameters) ++ ECPARAMETERS_free(ret->value.parameters); ++ } ++ ++ if (EC_GROUP_get_asn1_flag(group)) { ++ /* ++ * use the asn1 OID to describe the the elliptic curve parameters ++ */ ++ tmp = EC_GROUP_get_curve_name(group); ++ if (tmp) { ++ ret->type = 0; ++ if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) ++ ok = 0; ++ } else ++ /* we don't kmow the nid => ERROR */ ++ ok = 0; ++ } else { ++ /* use the ECPARAMETERS structure */ ++ ret->type = 1; ++ if ((ret->value.parameters = ++ ec_asn1_group2parameters(group, NULL)) == NULL) ++ ok = 0; ++ } ++ ++ if (!ok) { ++ ECPKPARAMETERS_free(ret); ++ return NULL; ++ } ++ return ret; ++} ++ ++static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) ++{ ++ int ok = 0, tmp; ++ EC_GROUP *ret = NULL; ++ BIGNUM *p = NULL, *a = NULL, *b = NULL; ++ EC_POINT *point = NULL; ++ long field_bits; ++ ++ if (!params->fieldID || !params->fieldID->fieldType || ++ !params->fieldID->p.ptr) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ ++ /* now extract the curve parameters a and b */ ++ if (!params->curve || !params->curve->a || ++ !params->curve->a->data || !params->curve->b || ++ !params->curve->b->data) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); ++ if (a == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); ++ if (b == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /* get the field parameters */ ++ tmp = OBJ_obj2nid(params->fieldID->fieldType); ++ if (tmp == NID_X9_62_characteristic_two_field) ++#ifdef OPENSSL_NO_EC2M ++ { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED); ++ goto err; ++ } ++#else ++ { ++ X9_62_CHARACTERISTIC_TWO *char_two; ++ ++ char_two = params->fieldID->p.char_two; ++ ++ field_bits = char_two->m; ++ if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); ++ goto err; ++ } ++ ++ if ((p = BN_new()) == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /* get the base type */ ++ tmp = OBJ_obj2nid(char_two->type); ++ ++ if (tmp == NID_X9_62_tpBasis) { ++ long tmp_long; ++ ++ if (!char_two->p.tpBasis) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ ++ tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); ++ ++ if (!(char_two->m > tmp_long && tmp_long > 0)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ++ EC_R_INVALID_TRINOMIAL_BASIS); ++ goto err; ++ } ++ ++ /* create the polynomial */ ++ if (!BN_set_bit(p, (int)char_two->m)) ++ goto err; ++ if (!BN_set_bit(p, (int)tmp_long)) ++ goto err; ++ if (!BN_set_bit(p, 0)) ++ goto err; ++ } else if (tmp == NID_X9_62_ppBasis) { ++ X9_62_PENTANOMIAL *penta; ++ ++ penta = char_two->p.ppBasis; ++ if (!penta) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ ++ if (! ++ (char_two->m > penta->k3 && penta->k3 > penta->k2 ++ && penta->k2 > penta->k1 && penta->k1 > 0)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ++ EC_R_INVALID_PENTANOMIAL_BASIS); ++ goto err; ++ } ++ ++ /* create the polynomial */ ++ if (!BN_set_bit(p, (int)char_two->m)) ++ goto err; ++ if (!BN_set_bit(p, (int)penta->k1)) ++ goto err; ++ if (!BN_set_bit(p, (int)penta->k2)) ++ goto err; ++ if (!BN_set_bit(p, (int)penta->k3)) ++ goto err; ++ if (!BN_set_bit(p, 0)) ++ goto err; ++ } else if (tmp == NID_X9_62_onBasis) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); ++ goto err; ++ } else { /* error */ ++ ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ ++ /* create the EC_GROUP structure */ ++ ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); ++ } ++#endif ++ else if (tmp == NID_X9_62_prime_field) { ++ /* we have a curve over a prime field */ ++ /* extract the prime number */ ++ if (!params->fieldID->p.prime) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); ++ if (p == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ ++ if (BN_is_negative(p) || BN_is_zero(p)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); ++ goto err; ++ } ++ ++ field_bits = BN_num_bits(p); ++ if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); ++ goto err; ++ } ++ ++ /* create the EC_GROUP structure */ ++ ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); ++ } else { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); ++ goto err; ++ } ++ ++ if (ret == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /* extract seed (optional) */ ++ if (params->curve->seed != NULL) { ++ if (ret->seed != NULL) ++ OPENSSL_free(ret->seed); ++ if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ memcpy(ret->seed, params->curve->seed->data, ++ params->curve->seed->length); ++ ret->seed_len = params->curve->seed->length; ++ } ++ ++ if (!params->order || !params->base || !params->base->data) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ goto err; ++ } ++ ++ if ((point = EC_POINT_new(ret)) == NULL) ++ goto err; ++ ++ /* set the point conversion form */ ++ EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) ++ (params->base->data[0] & ~0x01)); ++ ++ /* extract the ec point */ ++ if (!EC_POINT_oct2point(ret, point, params->base->data, ++ params->base->length, NULL)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /* extract the order */ ++ if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ if (BN_is_negative(a) || BN_is_zero(a)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); ++ goto err; ++ } ++ if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); ++ goto err; ++ } ++ ++ /* extract the cofactor (optional) */ ++ if (params->cofactor == NULL) { ++ if (b) { ++ BN_free(b); ++ b = NULL; ++ } ++ } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); ++ goto err; ++ } ++ /* set the generator, order and cofactor (if present) */ ++ if (!EC_GROUP_set_generator(ret, point, a, b)) { ++ ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ ok = 1; ++ ++ err:if (!ok) { ++ if (ret) ++ EC_GROUP_clear_free(ret); ++ ret = NULL; ++ } ++ ++ if (p) ++ BN_free(p); ++ if (a) ++ BN_free(a); ++ if (b) ++ BN_free(b); ++ if (point) ++ EC_POINT_free(point); ++ return (ret); ++} ++ ++EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) ++{ ++ EC_GROUP *ret = NULL; ++ int tmp = 0; ++ ++ if (params == NULL) { ++ ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS); ++ return NULL; ++ } ++ ++ if (params->type == 0) { /* the curve is given by an OID */ ++ tmp = OBJ_obj2nid(params->value.named_curve); ++ if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { ++ ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ++ EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); ++ return NULL; ++ } ++ EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); ++ } else if (params->type == 1) { /* the parameters are given by a ++ * ECPARAMETERS structure */ ++ ret = ec_asn1_parameters2group(params->value.parameters); ++ if (!ret) { ++ ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); ++ return NULL; ++ } ++ EC_GROUP_set_asn1_flag(ret, 0x0); ++ } else if (params->type == 2) { /* implicitlyCA */ ++ return NULL; ++ } else { ++ ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); ++ return NULL; ++ } ++ ++ return ret; ++} ++ ++/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ ++ ++EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) ++{ ++ EC_GROUP *group = NULL; ++ ECPKPARAMETERS *params = NULL; ++ const unsigned char *p = *in; ++ ++ if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) { ++ ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); ++ ECPKPARAMETERS_free(params); ++ return NULL; ++ } ++ ++ if ((group = ec_asn1_pkparameters2group(params)) == NULL) { ++ ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); ++ ECPKPARAMETERS_free(params); ++ return NULL; ++ } ++ ++ if (a && *a) ++ EC_GROUP_clear_free(*a); ++ if (a) ++ *a = group; ++ ++ ECPKPARAMETERS_free(params); ++ *in = p; ++ return (group); ++} ++ ++int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) ++{ ++ int ret = 0; ++ ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); ++ if (tmp == NULL) { ++ ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); ++ return 0; ++ } ++ if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { ++ ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); ++ ECPKPARAMETERS_free(tmp); ++ return 0; ++ } ++ ECPKPARAMETERS_free(tmp); ++ return (ret); ++} ++ ++/* some EC_KEY functions */ ++ ++EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) ++{ ++ int ok = 0; ++ EC_KEY *ret = NULL; ++ EC_PRIVATEKEY *priv_key = NULL; ++ const unsigned char *p = *in; ++ ++ if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) { ++ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); ++ return NULL; ++ } ++ ++ if (a == NULL || *a == NULL) { ++ if ((ret = EC_KEY_new()) == NULL) { ++ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } 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 (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 (priv_key->publicKey) { ++ const unsigned char *pub_oct; ++ int pub_oct_len; ++ ++ pub_oct = M_ASN1_STRING_data(priv_key->publicKey); ++ pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey); ++ /* ++ * The first byte - point conversion form - must be present. ++ */ ++ if (pub_oct_len <= 0) { ++ ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); ++ goto err; ++ } ++ /* Save the point conversion form. */ ++ ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01); ++ if (!EC_POINT_oct2point(ret->group, ret->pub_key, ++ pub_oct, (size_t)(pub_oct_len), NULL)) { ++ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ } else { ++ if (!EC_POINT_mul ++ (ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { ++ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ /* Remember the original private-key-only encoding. */ ++ ret->enc_flag |= EC_PKEY_NO_PUBKEY; ++ } ++ ++ if (a) ++ *a = ret; ++ *in = p; ++ ok = 1; ++ err: ++ if (!ok) { ++ if (ret && (a == NULL || *a != 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, bn_len; ++ EC_PRIVATEKEY *priv_key = NULL; ++ ++ if (a == NULL || a->group == NULL || a->priv_key == NULL || ++ (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_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; ++ ++ bn_len = (size_t)BN_num_bytes(a->priv_key); ++ ++ /* Octetstring may need leading zeros if BN is to short */ ++ ++ buf_len = (EC_GROUP_get_degree(a->group) + 7) / 8; ++ ++ if (bn_len > buf_len) { ++ ECerr(EC_F_I2D_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); ++ goto err; ++ } ++ ++ 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 + buf_len - bn_len)) { ++ ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (buf_len - bn_len > 0) { ++ memset(buffer, 0, buf_len - bn_len); ++ } ++ ++ 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) { ++ unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); ++ if (!tmp_buffer) { ++ ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ buffer = tmp_buffer; ++ 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; ++ } ++ ++ priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); ++ priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; ++ 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; ++ } ++ return i2d_ECPKParameters(a->group, out); ++} ++ ++EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) ++{ ++ EC_KEY *ret; ++ ++ if (in == NULL || *in == NULL) { ++ ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); ++ return NULL; ++ } ++ ++ if (a == NULL || *a == NULL) { ++ if ((ret = EC_KEY_new()) == NULL) { ++ ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ } else ++ ret = *a; ++ ++ if (!d2i_ECPKParameters(&ret->group, in, len)) { ++ ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); ++ if (a == NULL || *a != ret) ++ EC_KEY_free(ret); ++ return NULL; ++ } ++ ++ if (a) ++ *a = ret; ++ ++ return ret; ++} ++ ++EC_KEY *o2i_ECPublicKey(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_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ret = *a; ++ if (ret->pub_key == NULL && ++ (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { ++ ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) { ++ ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); ++ return 0; ++ } ++ /* save the point conversion form */ ++ ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01); ++ *in += len; ++ return ret; ++} ++ ++int i2o_ECPublicKey(EC_KEY *a, unsigned char **out) ++{ ++ size_t buf_len = 0; ++ int new_buffer = 0; ++ ++ if (a == NULL) { ++ ECerr(EC_F_I2O_ECPUBLICKEY, 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_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ new_buffer = 1; ++ } ++ if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, ++ *out, buf_len, NULL)) { ++ ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); ++ if (new_buffer) { ++ OPENSSL_free(*out); ++ *out = NULL; ++ } ++ return 0; ++ } ++ if (!new_buffer) ++ *out += buf_len; ++ return buf_len; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_check.c b/Cryptlib/OpenSSL/crypto/ec/ec_check.c +new file mode 100644 +index 0000000..dd6f0ac +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_check.c +@@ -0,0 +1,120 @@ ++/* crypto/ec/ec_check.c */ ++/* ==================================================================== ++ * 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 ++ ++int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BIGNUM *order; ++ BN_CTX *new_ctx = NULL; ++ EC_POINT *point = NULL; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } ++ BN_CTX_start(ctx); ++ if ((order = BN_CTX_get(ctx)) == NULL) ++ goto err; ++ ++ /* check the discriminant */ ++ if (!EC_GROUP_check_discriminant(group, ctx)) { ++ ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); ++ goto err; ++ } ++ ++ /* check the generator */ ++ if (group->generator == NULL) { ++ ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); ++ goto err; ++ } ++ if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) { ++ ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE); ++ goto err; ++ } ++ ++ /* check the order of the generator */ ++ if ((point = EC_POINT_new(group)) == NULL) ++ goto err; ++ if (!EC_GROUP_get_order(group, order, ctx)) ++ goto err; ++ if (BN_is_zero(order)) { ++ ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER); ++ goto err; ++ } ++ ++ if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) ++ goto err; ++ if (!EC_POINT_is_at_infinity(group, point)) { ++ ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); ++ goto err; ++ } ++ ++ ret = 1; ++ ++ err: ++ if (ctx != NULL) ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ if (point) ++ EC_POINT_free(point); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_curve.c b/Cryptlib/OpenSSL/crypto/ec/ec_curve.c +new file mode 100644 +index 0000000..0ec05f8 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_curve.c +@@ -0,0 +1,343 @@ ++/* crypto/ec/ec_curve.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2010 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * ++ * Portions of the attached software ("Contribution") are developed by ++ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. ++ * ++ * The Contribution is licensed pursuant to the OpenSSL open source ++ * license provided above. ++ * ++ * The elliptic curve binary polynomial software is originally written by ++ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. ++ * ++ */ ++ ++#include ++#include "ec_lcl.h" ++#include ++#include ++#include ++ ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++typedef struct { ++ int field_type, /* either NID_X9_62_prime_field or ++ * NID_X9_62_characteristic_two_field */ ++ seed_len, param_len; ++ unsigned int cofactor; /* promoted to BN_ULONG */ ++} EC_CURVE_DATA; ++ ++#ifndef OPENSSL_NO_SM2 ++static const struct { ++ EC_CURVE_DATA h; ++ unsigned char data[0 + 32 * 6]; ++} _EC_sm2p256v1 = { ++ { ++ NID_X9_62_prime_field, 0, 32, 1 ++ }, ++ { ++ /* no seed */ ++ ++ /* p */ ++ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ /* a */ ++ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, ++ /* b */ ++ 0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b, ++ 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92, ++ 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93, ++ /* x */ ++ 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46, ++ 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1, ++ 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7, ++ /* y */ ++ 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3, ++ 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40, ++ 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0, ++ /* order */ ++ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b, ++ 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23, ++ } ++}; ++#endif /* OPENSSL_NO_SM2 */ ++ ++typedef struct _ec_list_element_st { ++ int nid; ++ const EC_CURVE_DATA *data; ++ const EC_METHOD *(*meth) (void); ++ const char *comment; ++} ec_list_element; ++ ++static const ec_list_element curve_list[] = { ++ /* prime field curves */ ++ /* secg curves */ ++#ifndef OPENSSL_NO_SM2 ++ {NID_sm2, &_EC_sm2p256v1.h, 0, ++ "SM2 curve over a 256 bit prime field"}, ++#endif ++}; ++ ++#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element)) ++ ++static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) ++{ ++ EC_GROUP *group = NULL; ++ EC_POINT *P = NULL; ++ BN_CTX *ctx = NULL; ++ BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = ++ NULL; ++ int ok = 0; ++ int seed_len, param_len; ++ const EC_METHOD *meth; ++ const EC_CURVE_DATA *data; ++ const unsigned char *params; ++ ++ if ((ctx = BN_CTX_new()) == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ data = curve.data; ++ seed_len = data->seed_len; ++ param_len = data->param_len; ++ params = (const unsigned char *)(data + 1); /* skip header */ ++ params += seed_len; /* skip seed */ ++ ++ if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ++ || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ++ || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (curve.meth != 0) { ++ meth = curve.meth(); ++ if (((group = EC_GROUP_new(meth)) == NULL) || ++ (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ } else if (data->field_type == NID_X9_62_prime_field) { ++ if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#ifndef OPENSSL_NO_EC2M ++ else { /* field_type == ++ * NID_X9_62_characteristic_two_field */ ++ ++ if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#endif ++ ++ if ((P = EC_POINT_new(group)) == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ++ || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) ++ || !BN_set_word(x, (BN_ULONG)data->cofactor)) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (!EC_GROUP_set_generator(group, P, order, x)) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (seed_len) { ++ if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) { ++ ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++ ok = 1; ++ err: ++ if (!ok) { ++ EC_GROUP_free(group); ++ group = NULL; ++ } ++ if (P) ++ EC_POINT_free(P); ++ if (ctx) ++ BN_CTX_free(ctx); ++ if (p) ++ BN_free(p); ++ if (a) ++ BN_free(a); ++ if (b) ++ BN_free(b); ++ if (order) ++ BN_free(order); ++ if (x) ++ BN_free(x); ++ if (y) ++ BN_free(y); ++ return group; ++} ++ ++EC_GROUP *EC_GROUP_new_by_curve_name(int nid) ++{ ++ size_t i; ++ EC_GROUP *ret = NULL; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return FIPS_ec_group_new_by_curve_name(nid); ++#endif ++ if (nid <= 0) ++ return NULL; ++ ++ for (i = 0; i < curve_list_length; i++) ++ if (curve_list[i].nid == nid) { ++ ret = ec_group_new_from_data(curve_list[i]); ++ break; ++ } ++ ++ if (ret == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP); ++ return NULL; ++ } ++ ++ EC_GROUP_set_curve_name(ret, nid); ++ ++ return ret; ++} ++ ++size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) ++{ ++ size_t i, min; ++ ++ if (r == NULL || nitems == 0) ++ return curve_list_length; ++ ++ min = nitems < curve_list_length ? nitems : curve_list_length; ++ ++ for (i = 0; i < min; i++) { ++ r[i].nid = curve_list[i].nid; ++ r[i].comment = curve_list[i].comment; ++ } ++ ++ return curve_list_length; ++} ++ ++/* Functions to translate between common NIST curve names and NIDs */ ++ ++typedef struct { ++ const char *name; /* NIST Name of curve */ ++ int nid; /* Curve NID */ ++} EC_NIST_NAME; ++ ++static EC_NIST_NAME nist_curves[] = { ++ {"B-163", NID_sect163r2}, ++ {"B-233", NID_sect233r1}, ++ {"B-283", NID_sect283r1}, ++ {"B-409", NID_sect409r1}, ++ {"B-571", NID_sect571r1}, ++ {"K-163", NID_sect163k1}, ++ {"K-233", NID_sect233k1}, ++ {"K-283", NID_sect283k1}, ++ {"K-409", NID_sect409k1}, ++ {"K-571", NID_sect571k1}, ++ {"P-192", NID_X9_62_prime192v1}, ++ {"P-224", NID_secp224r1}, ++ {"P-256", NID_X9_62_prime256v1}, ++ {"P-384", NID_secp384r1}, ++ {"P-521", NID_secp521r1} ++}; ++ ++const char *EC_curve_nid2nist(int nid) ++{ ++ size_t i; ++ for (i = 0; i < sizeof(nist_curves) / sizeof(EC_NIST_NAME); i++) { ++ if (nist_curves[i].nid == nid) ++ return nist_curves[i].name; ++ } ++ return NULL; ++} ++ ++int EC_curve_nist2nid(const char *name) ++{ ++ size_t i; ++ for (i = 0; i < sizeof(nist_curves) / sizeof(EC_NIST_NAME); i++) { ++ if (!strcmp(nist_curves[i].name, name)) ++ return nist_curves[i].nid; ++ } ++ return NID_undef; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_cvt.c b/Cryptlib/OpenSSL/crypto/ec/ec_cvt.c +new file mode 100644 +index 0000000..5fa68c2 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_cvt.c +@@ -0,0 +1,154 @@ ++/* crypto/ec/ec_cvt.c */ ++/* ++ * Originally written by Bodo Moeller 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * ++ * Portions of the attached software ("Contribution") are developed by ++ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. ++ * ++ * The Contribution is licensed pursuant to the OpenSSL open source ++ * license provided above. ++ * ++ * The elliptic curve binary polynomial software is originally written by ++ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. ++ * ++ */ ++ ++#include ++#include "ec_lcl.h" ++ ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ const EC_METHOD *meth; ++ EC_GROUP *ret; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return FIPS_ec_group_new_curve_gfp(p, a, b, ctx); ++#endif ++#if defined(OPENSSL_BN_ASM_MONT) ++ /* ++ * This might appear controversial, but the fact is that generic ++ * prime method was observed to deliver better performance even ++ * for NIST primes on a range of platforms, e.g.: 60%-15% ++ * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25% ++ * in 32-bit build and 35%--12% in 64-bit build on Core2... ++ * Coefficients are relative to optimized bn_nist.c for most ++ * intensive ECDSA verify and ECDH operations for 192- and 521- ++ * bit keys respectively. Choice of these boundary values is ++ * arguable, because the dependency of improvement coefficient ++ * from key length is not a "monotone" curve. For example while ++ * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's ++ * generally faster, sometimes "respectfully" faster, sometimes ++ * "tolerably" slower... What effectively happens is that loop ++ * with bn_mul_add_words is put against bn_mul_mont, and the ++ * latter "wins" on short vectors. Correct solution should be ++ * implementing dedicated NxN multiplication subroutines for ++ * small N. But till it materializes, let's stick to generic ++ * prime method... ++ * ++ */ ++ meth = EC_GFp_mont_method(); ++#else ++ meth = EC_GFp_nist_method(); ++#endif ++ ++ ret = EC_GROUP_new(meth); ++ if (ret == NULL) ++ return NULL; ++ ++ if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) { ++ unsigned long err; ++ ++ err = ERR_peek_last_error(); ++ ++ if (!(ERR_GET_LIB(err) == ERR_LIB_EC && ++ ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) || ++ (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) { ++ /* real error */ ++ ++ EC_GROUP_clear_free(ret); ++ return NULL; ++ } ++ ++ /* ++ * not an actual error, we just cannot use EC_GFp_nist_method ++ */ ++ ++ ERR_clear_error(); ++ ++ EC_GROUP_clear_free(ret); ++ meth = EC_GFp_mont_method(); ++ ++ ret = EC_GROUP_new(meth); ++ if (ret == NULL) ++ return NULL; ++ ++ if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) { ++ EC_GROUP_clear_free(ret); ++ return NULL; ++ } ++ } ++ ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_err.c b/Cryptlib/OpenSSL/crypto/ec/ec_err.c +new file mode 100644 +index 0000000..6fe5baa +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_err.c +@@ -0,0 +1,332 @@ ++/* crypto/ec/ec_err.c */ ++/* ==================================================================== ++ * Copyright (c) 1999-2015 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). ++ * ++ */ ++ ++/* ++ * NOTE: this file was auto generated by the mkerr.pl script: any changes ++ * made to it will be overwritten when the script next updates this file, ++ * only reason strings will be preserved. ++ */ ++ ++#include ++#include ++#include ++ ++/* BEGIN ERROR CODES */ ++#ifndef OPENSSL_NO_ERR ++ ++# define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0) ++# define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason) ++ ++static ERR_STRING_DATA EC_str_functs[] = { ++ {ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"}, ++ {ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, ++ {ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, ++ {ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, ++ {ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"}, ++ {ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "DO_EC_KEY_PRINT"}, ++ {ERR_FUNC(EC_F_ECDH_CMS_DECRYPT), "ECDH_CMS_DECRYPT"}, ++ {ERR_FUNC(EC_F_ECDH_CMS_SET_SHARED_INFO), "ECDH_CMS_SET_SHARED_INFO"}, ++ {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"}, ++ {ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "ECKEY_PRIV_ENCODE"}, ++ {ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "ECKEY_PUB_DECODE"}, ++ {ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "ECKEY_PUB_ENCODE"}, ++ {ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "ECKEY_TYPE2PARAM"}, ++ {ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"}, ++ {ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"}, ++ {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"}, ++ {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_GET_AFFINE), "ecp_nistz256_get_affine"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE), ++ "ecp_nistz256_mult_precompute"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_POINTS_MUL), "ecp_nistz256_points_mul"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_PRE_COMP_NEW), "ecp_nistz256_pre_comp_new"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_SET_WORDS), "ecp_nistz256_set_words"}, ++ {ERR_FUNC(EC_F_ECP_NISTZ256_WINDOWED_MUL), "ecp_nistz256_windowed_mul"}, ++ {ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"}, ++ {ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"}, ++ {ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"}, ++ {ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"}, ++ {ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"}, ++ {ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"}, ++ {ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"}, ++ {ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"}, ++ {ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"}, ++ {ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"}, ++ {ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"}, ++ {ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY), ++ "EC_GF2M_MONTGOMERY_POINT_MULTIPLY"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT), ++ "ec_GF2m_simple_group_check_discriminant"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE), ++ "ec_GF2m_simple_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES), ++ "ec_GF2m_simple_point_get_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES), ++ "ec_GF2m_simple_point_set_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES), ++ "ec_GF2m_simple_set_compressed_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE), ++ "ec_GFp_mont_field_set_to_one"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), ++ "ec_GFp_mont_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), ++ "EC_GFP_MONT_GROUP_SET_CURVE_GFP"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE), ++ "ec_GFp_nistp224_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES), ++ "ec_GFp_nistp224_point_get_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE), ++ "ec_GFp_nistp256_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES), ++ "ec_GFp_nistp256_point_get_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE), ++ "ec_GFp_nistp521_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"}, ++ {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES), ++ "ec_GFp_nistp521_point_get_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"}, ++ {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"}, ++ {ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), ++ "ec_GFp_nist_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT), ++ "ec_GFp_simple_group_check_discriminant"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE), ++ "ec_GFp_simple_group_set_curve"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), ++ "EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), ++ "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), ++ "ec_GFp_simple_points_make_affine"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES), ++ "ec_GFp_simple_point_get_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), ++ "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES), ++ "ec_GFp_simple_point_set_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), ++ "EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES), ++ "ec_GFp_simple_set_compressed_coordinates"}, ++ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), ++ "EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"}, ++ {ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"}, ++ {ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT), ++ "EC_GROUP_check_discriminant"}, ++ {ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS), ++ "EC_GROUP_get_pentanomial_basis"}, ++ {ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS), ++ "EC_GROUP_get_trinomial_basis"}, ++ {ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"}, ++ {ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"}, ++ {ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"}, ++ {ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"}, ++ {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"}, ++ {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"}, ++ {ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"}, ++ {ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"}, ++ {ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"}, ++ {ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"}, ++ {ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"}, ++ {ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"}, ++ {ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"}, ++ {ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"}, ++ {ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES), ++ "EC_KEY_set_public_key_affine_coordinates"}, ++ {ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, ++ {ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, ++ {ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, ++ {ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"}, ++ {ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"}, ++ {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M), ++ "EC_POINT_get_affine_coordinates_GF2m"}, ++ {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), ++ "EC_POINT_get_affine_coordinates_GFp"}, ++ {ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), ++ "EC_POINT_get_Jprojective_coordinates_GFp"}, ++ {ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"}, ++ {ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"}, ++ {ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"}, ++ {ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"}, ++ {ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"}, ++ {ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"}, ++ {ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"}, ++ {ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M), ++ "EC_POINT_set_affine_coordinates_GF2m"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), ++ "EC_POINT_set_affine_coordinates_GFp"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M), ++ "EC_POINT_set_compressed_coordinates_GF2m"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), ++ "EC_POINT_set_compressed_coordinates_GFp"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), ++ "EC_POINT_set_Jprojective_coordinates_GFp"}, ++ {ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"}, ++ {ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"}, ++ {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_ECPARAMETERS), "i2d_ECParameters"}, ++ {ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, ++ {ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, ++ {ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"}, ++ {ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"}, ++ {ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"}, ++ {ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"}, ++ {ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"}, ++ {ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"}, ++ {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} ++}; ++ ++static ERR_STRING_DATA EC_str_reasons[] = { ++ {ERR_REASON(EC_R_ASN1_ERROR), "asn1 error"}, ++ {ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD), "asn1 unknown field"}, ++ {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_COORDINATES_OUT_OF_RANGE), "coordinates out of range"}, ++ {ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE), ++ "d2i ecpkparameters failure"}, ++ {ERR_REASON(EC_R_DECODE_ERROR), "decode error"}, ++ {ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"}, ++ {ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), ++ "ec group new by name failure"}, ++ {ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"}, ++ {ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, ++ {ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE), ++ "group2pkparameters failure"}, ++ {ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE), ++ "i2d ecpkparameters failure"}, ++ {ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, ++ {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), "invalid digest"}, ++ {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_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, ++ {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"}, ++ {ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"}, ++ {ERR_REASON(EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, ++ {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"}, ++ {ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME), ++ "not a supported NIST prime"}, ++ {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_PEER_KEY_ERROR), "peer key error"}, ++ {ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE), ++ "pkparameters2group failure"}, ++ {ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"}, ++ {ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"}, ++ {ERR_REASON(EC_R_SHARED_INFO_ERROR), "shared info error"}, ++ {ERR_REASON(EC_R_SLOT_FULL), "slot full"}, ++ {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"}, ++ {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"}, ++ {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"}, ++ {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"}, ++ {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"}, ++ {ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"}, ++ {ERR_REASON(EC_R_WRONG_ORDER), "wrong order"}, ++ {0, NULL} ++}; ++ ++#endif ++ ++void ERR_load_EC_strings(void) ++{ ++#ifndef OPENSSL_NO_ERR ++ ++ if (ERR_func_error_string(EC_str_functs[0].error) == NULL) { ++ ERR_load_strings(0, EC_str_functs); ++ ERR_load_strings(0, EC_str_reasons); ++ } ++#endif ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_key.c b/Cryptlib/OpenSSL/crypto/ec/ec_key.c +new file mode 100644 +index 0000000..456080e +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_key.c +@@ -0,0 +1,564 @@ ++/* crypto/ec/ec_key.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2005 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions originally developed by SUN MICROSYSTEMS, INC., and ++ * contributed to the OpenSSL project. ++ */ ++ ++#include ++#include "ec_lcl.h" ++#include ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++EC_KEY *EC_KEY_new(void) ++{ ++ EC_KEY *ret; ++ ++ ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); ++ if (ret == NULL) { ++ ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); ++ return (NULL); ++ } ++ ++ ret->version = 1; ++ ret->flags = 0; ++ 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->method_data = NULL; ++ return (ret); ++} ++ ++EC_KEY *EC_KEY_new_by_curve_name(int nid) ++{ ++ EC_KEY *ret = EC_KEY_new(); ++ if (ret == NULL) ++ return NULL; ++ ret->group = EC_GROUP_new_by_curve_name(nid); ++ if (ret->group == NULL) { ++ EC_KEY_free(ret); ++ return 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); ++ ++ EC_EX_DATA_free_all_data(&r->method_data); ++ ++ OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); ++ ++ OPENSSL_free(r); ++} ++ ++EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) ++{ ++ EC_EXTRA_DATA *d; ++ ++ 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 method/extra data */ ++ EC_EX_DATA_free_all_data(&dest->method_data); ++ ++ for (d = src->method_data; d != NULL; d = d->next) { ++ void *t = d->dup_func(d->data); ++ ++ if (t == NULL) ++ return 0; ++ if (!EC_EX_DATA_set_data ++ (&dest->method_data, t, d->dup_func, d->free_func, ++ d->clear_free_func)) ++ return 0; ++ } ++ ++ /* copy the rest */ ++ dest->enc_flag = src->enc_flag; ++ dest->conv_form = src->conv_form; ++ dest->version = src->version; ++ dest->flags = src->flags; ++ ++ return dest; ++} ++ ++EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) ++{ ++ EC_KEY *ret = EC_KEY_new(); ++ if (ret == NULL) ++ return NULL; ++ if (EC_KEY_copy(ret, ec_key) == NULL) { ++ EC_KEY_free(ret); ++ return NULL; ++ } ++ return ret; ++} ++ ++int EC_KEY_up_ref(EC_KEY *r) ++{ ++ int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); ++#ifdef REF_PRINT ++ REF_PRINT("EC_KEY", r); ++#endif ++#ifdef REF_CHECK ++ if (i < 2) { ++ fprintf(stderr, "EC_KEY_up, bad reference count\n"); ++ abort(); ++ } ++#endif ++ return ((i > 1) ? 1 : 0); ++} ++ ++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; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return FIPS_ec_key_generate_key(eckey); ++#endif ++ ++ 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; ++ ++ if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) ++ goto err; ++ ++ eckey->priv_key = priv_key; ++ eckey->pub_key = pub_key; ++ ++ ok = 1; ++ ++ err: ++ if (order) ++ BN_free(order); ++ if (pub_key != NULL && eckey->pub_key == NULL) ++ EC_POINT_free(pub_key); ++ if (priv_key != NULL && eckey->priv_key == NULL) ++ BN_free(priv_key); ++ if (ctx != NULL) ++ BN_CTX_free(ctx); ++ return (ok); ++} ++ ++int EC_KEY_check_key(const EC_KEY *eckey) ++{ ++ int ok = 0; ++ BN_CTX *ctx = NULL; ++ const BIGNUM *order = NULL; ++ EC_POINT *point = NULL; ++ ++ if (!eckey || !eckey->group || !eckey->pub_key) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ++ if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); ++ goto err; ++ } ++ ++ if ((ctx = BN_CTX_new()) == NULL) ++ goto err; ++ if ((point = EC_POINT_new(eckey->group)) == NULL) ++ goto err; ++ ++ /* testing whether the pub_key is on the elliptic curve */ ++ if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); ++ goto err; ++ } ++ /* testing whether pub_key * order is the point at infinity */ ++ order = &eckey->group->order; ++ if (BN_is_zero(order)) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); ++ goto err; ++ } ++ if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (!EC_POINT_is_at_infinity(eckey->group, point)) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); ++ goto err; ++ } ++ /* ++ * in case the priv_key is present : check if generator * priv_key == ++ * pub_key ++ */ ++ if (eckey->priv_key) { ++ if (BN_cmp(eckey->priv_key, order) >= 0) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); ++ goto err; ++ } ++ if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, ++ NULL, NULL, ctx)) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { ++ ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); ++ goto err; ++ } ++ } ++ ok = 1; ++ err: ++ if (ctx != NULL) ++ BN_CTX_free(ctx); ++ if (point != NULL) ++ EC_POINT_free(point); ++ return (ok); ++} ++ ++int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, ++ BIGNUM *y) ++{ ++ BN_CTX *ctx = NULL; ++ BIGNUM *tx, *ty; ++ EC_POINT *point = NULL; ++ int ok = 0; ++#ifndef OPENSSL_NO_EC2M ++ int tmp_nid, is_char_two = 0; ++#endif ++ ++ if (!key || !key->group || !x || !y) { ++ ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, ++ ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ BN_CTX_start(ctx); ++ point = EC_POINT_new(key->group); ++ ++ if (!point) ++ goto err; ++ ++ tx = BN_CTX_get(ctx); ++ ty = BN_CTX_get(ctx); ++ if (ty == NULL) ++ goto err; ++ ++#ifndef OPENSSL_NO_EC2M ++ tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); ++ ++ if (tmp_nid == NID_X9_62_characteristic_two_field) ++ is_char_two = 1; ++ ++ if (is_char_two) { ++ if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, ++ x, y, ctx)) ++ goto err; ++ if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, ++ tx, ty, ctx)) ++ goto err; ++ } else ++#endif ++ { ++ if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, ++ x, y, ctx)) ++ goto err; ++ if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, ++ tx, ty, ctx)) ++ goto err; ++ } ++ /* ++ * Check if retrieved coordinates match originals: if not values are out ++ * of range. ++ */ ++ if (BN_cmp(x, tx) || BN_cmp(y, ty)) { ++ ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, ++ EC_R_COORDINATES_OUT_OF_RANGE); ++ goto err; ++ } ++ ++ if (!EC_KEY_set_public_key(key, point)) ++ goto err; ++ ++ if (EC_KEY_check_key(key) == 0) ++ goto err; ++ ++ ok = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ BN_CTX_free(ctx); ++ EC_POINT_free(point); ++ return ok; ++ ++} ++ ++const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) ++{ ++ return key->group; ++} ++ ++int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) ++{ ++ if (key->group != NULL) ++ EC_GROUP_free(key->group); ++ key->group = EC_GROUP_dup(group); ++ return (key->group == NULL) ? 0 : 1; ++} ++ ++const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) ++{ ++ return key->priv_key; ++} ++ ++int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) ++{ ++ if (key->priv_key) ++ BN_clear_free(key->priv_key); ++ key->priv_key = BN_dup(priv_key); ++ return (key->priv_key == NULL) ? 0 : 1; ++} ++ ++const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) ++{ ++ return key->pub_key; ++} ++ ++int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) ++{ ++ if (key->pub_key != NULL) ++ EC_POINT_free(key->pub_key); ++ key->pub_key = EC_POINT_dup(pub_key, key->group); ++ return (key->pub_key == NULL) ? 0 : 1; ++} ++ ++unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) ++{ ++ return key->enc_flag; ++} ++ ++void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) ++{ ++ key->enc_flag = flags; ++} ++ ++point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) ++{ ++ return key->conv_form; ++} ++ ++void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) ++{ ++ key->conv_form = cform; ++ if (key->group != NULL) ++ EC_GROUP_set_point_conversion_form(key->group, cform); ++} ++ ++void *EC_KEY_get_key_method_data(EC_KEY *key, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ void *ret; ++ ++ CRYPTO_r_lock(CRYPTO_LOCK_EC); ++ ret = ++ EC_EX_DATA_get_data(key->method_data, dup_func, free_func, ++ clear_free_func); ++ CRYPTO_r_unlock(CRYPTO_LOCK_EC); ++ ++ return ret; ++} ++ ++void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ EC_EXTRA_DATA *ex_data; ++ ++ CRYPTO_w_lock(CRYPTO_LOCK_EC); ++ ex_data = ++ EC_EX_DATA_get_data(key->method_data, dup_func, free_func, ++ clear_free_func); ++ if (ex_data == NULL) ++ EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, ++ clear_free_func); ++ CRYPTO_w_unlock(CRYPTO_LOCK_EC); ++ ++ return ex_data; ++} ++ ++void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) ++{ ++ if (key->group != NULL) ++ EC_GROUP_set_asn1_flag(key->group, flag); ++} ++ ++int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) ++{ ++ if (key->group == NULL) ++ return 0; ++ return EC_GROUP_precompute_mult(key->group, ctx); ++} ++ ++int EC_KEY_get_flags(const EC_KEY *key) ++{ ++ return key->flags; ++} ++ ++void EC_KEY_set_flags(EC_KEY *key, int flags) ++{ ++ key->flags |= flags; ++} ++ ++void EC_KEY_clear_flags(EC_KEY *key, int flags) ++{ ++ key->flags &= ~flags; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_lcl.h b/Cryptlib/OpenSSL/crypto/ec/ec_lcl.h +new file mode 100644 +index 0000000..68a1550 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_lcl.h +@@ -0,0 +1,470 @@ ++/* crypto/ec/ec_lcl.h */ ++/* ++ * Originally written by Bodo Moeller for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2010 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * ++ * Portions of the attached software ("Contribution") are developed by ++ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. ++ * ++ * The Contribution is licensed pursuant to the OpenSSL open source ++ * license provided above. ++ * ++ * The elliptic curve binary polynomial software is originally written by ++ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. ++ * ++ */ ++ ++#include ++ ++#include ++#include ++#include ++ ++#if defined(__SUNPRO_C) ++# if __SUNPRO_C >= 0x520 ++# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) ++# endif ++#endif ++ ++/* Use default functions for poin2oct, oct2point and compressed coordinates */ ++#define EC_FLAGS_DEFAULT_OCT 0x1 ++ ++/* ++ * Structure details are not part of the exported interface, so all this may ++ * change in future versions. ++ */ ++ ++struct ec_method_st { ++ /* Various method flags */ ++ int flags; ++ /* used by EC_METHOD_get_field_type: */ ++ int field_type; /* a NID */ ++ /* ++ * used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, ++ * EC_GROUP_copy: ++ */ ++ int (*group_init) (EC_GROUP *); ++ void (*group_finish) (EC_GROUP *); ++ void (*group_clear_finish) (EC_GROUP *); ++ int (*group_copy) (EC_GROUP *, const EC_GROUP *); ++ /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */ ++ /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */ ++ int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++ int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, ++ BN_CTX *); ++ /* used by EC_GROUP_get_degree: */ ++ int (*group_get_degree) (const EC_GROUP *); ++ /* used by EC_GROUP_check: */ ++ int (*group_check_discriminant) (const EC_GROUP *, BN_CTX *); ++ /* ++ * used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, ++ * EC_POINT_copy: ++ */ ++ int (*point_init) (EC_POINT *); ++ void (*point_finish) (EC_POINT *); ++ void (*point_clear_finish) (EC_POINT *); ++ int (*point_copy) (EC_POINT *, const EC_POINT *); ++ /*- ++ * used by EC_POINT_set_to_infinity, ++ * EC_POINT_set_Jprojective_coordinates_GFp, ++ * EC_POINT_get_Jprojective_coordinates_GFp, ++ * EC_POINT_set_affine_coordinates_GFp, ..._GF2m, ++ * EC_POINT_get_affine_coordinates_GFp, ..._GF2m, ++ * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m: ++ */ ++ int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *); ++ int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *, ++ EC_POINT *, const BIGNUM *x, ++ const BIGNUM *y, ++ const BIGNUM *z, BN_CTX *); ++ int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *, ++ const EC_POINT *, BIGNUM *x, ++ BIGNUM *y, BIGNUM *z, ++ BN_CTX *); ++ int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, const BIGNUM *y, ++ BN_CTX *); ++ int (*point_get_affine_coordinates) (const EC_GROUP *, const EC_POINT *, ++ BIGNUM *x, BIGNUM *y, BN_CTX *); ++ int (*point_set_compressed_coordinates) (const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, int y_bit, ++ BN_CTX *); ++ /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ ++ size_t (*point2oct) (const EC_GROUP *, const EC_POINT *, ++ point_conversion_form_t form, unsigned char *buf, ++ size_t len, BN_CTX *); ++ int (*oct2point) (const EC_GROUP *, EC_POINT *, const unsigned char *buf, ++ size_t len, BN_CTX *); ++ /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */ ++ int (*add) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *); ++ int (*dbl) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); ++ int (*invert) (const EC_GROUP *, EC_POINT *, BN_CTX *); ++ /* ++ * used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: ++ */ ++ int (*is_at_infinity) (const EC_GROUP *, const EC_POINT *); ++ int (*is_on_curve) (const EC_GROUP *, const EC_POINT *, BN_CTX *); ++ int (*point_cmp) (const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, ++ BN_CTX *); ++ /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */ ++ int (*make_affine) (const EC_GROUP *, EC_POINT *, BN_CTX *); ++ int (*points_make_affine) (const EC_GROUP *, size_t num, EC_POINT *[], ++ BN_CTX *); ++ /* ++ * used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, ++ * EC_POINT_have_precompute_mult (default implementations are used if the ++ * 'mul' pointer is 0): ++ */ ++ int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ++ size_t num, const EC_POINT *points[], const BIGNUM *scalars[], ++ BN_CTX *); ++ int (*precompute_mult) (EC_GROUP *group, BN_CTX *); ++ int (*have_precompute_mult) (const EC_GROUP *group); ++ /* internal functions */ ++ /* ++ * 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and ++ * 'dbl' so that the same implementations of point operations can be used ++ * with different optimized implementations of expensive field ++ * operations: ++ */ ++ int (*field_mul) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++ int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); ++ int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++ /* e.g. to Montgomery */ ++ int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++ /* e.g. from Montgomery */ ++ int (*field_decode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++ int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *); ++} /* EC_METHOD */ ; ++ ++typedef struct ec_extra_data_st { ++ struct ec_extra_data_st *next; ++ void *data; ++ void *(*dup_func) (void *); ++ void (*free_func) (void *); ++ void (*clear_free_func) (void *); ++} EC_EXTRA_DATA; /* used in EC_GROUP */ ++ ++struct ec_group_st { ++ const EC_METHOD *meth; ++ EC_POINT *generator; /* optional */ ++ BIGNUM order, cofactor; ++ int curve_name; /* optional NID for named curve */ ++ int asn1_flag; /* flag to control the asn1 encoding */ ++ /* ++ * Kludge: upper bit of ans1_flag is used to denote structure ++ * version. Is set, then last field is present. This is done ++ * for interoperation with FIPS code. ++ */ ++#define EC_GROUP_ASN1_FLAG_MASK 0x7fffffff ++#define EC_GROUP_VERSION(p) (p->asn1_flag&~EC_GROUP_ASN1_FLAG_MASK) ++ point_conversion_form_t asn1_form; ++ unsigned char *seed; /* optional seed for parameters (appears in ++ * ASN1) */ ++ size_t seed_len; ++ EC_EXTRA_DATA *extra_data; /* linked list */ ++ /* ++ * The following members are handled by the method functions, even if ++ * they appear generic ++ */ ++ /* ++ * Field specification. For curves over GF(p), this is the modulus; for ++ * curves over GF(2^m), this is the irreducible polynomial defining the ++ * field. ++ */ ++ BIGNUM field; ++ /* ++ * Field specification for curves over GF(2^m). The irreducible f(t) is ++ * then of the form: t^poly[0] + t^poly[1] + ... + t^poly[k] where m = ++ * poly[0] > poly[1] > ... > poly[k] = 0. The array is terminated with ++ * poly[k+1]=-1. All elliptic curve irreducibles have at most 5 non-zero ++ * terms. ++ */ ++ int poly[6]; ++ /* ++ * Curve coefficients. (Here the assumption is that BIGNUMs can be used ++ * or abused for all kinds of fields, not just GF(p).) For characteristic ++ * > 3, the curve is defined by a Weierstrass equation of the form y^2 = ++ * x^3 + a*x + b. For characteristic 2, the curve is defined by an ++ * equation of the form y^2 + x*y = x^3 + a*x^2 + b. ++ */ ++ BIGNUM a, b; ++ /* enable optimized point arithmetics for special case */ ++ int a_is_minus3; ++ /* method-specific (e.g., Montgomery structure) */ ++ void *field_data1; ++ /* method-specific */ ++ void *field_data2; ++ /* method-specific */ ++ int (*field_mod_func) (BIGNUM *, const BIGNUM *, const BIGNUM *, ++ BN_CTX *); ++ BN_MONT_CTX *mont_data; /* data for ECDSA inverse */ ++} /* EC_GROUP */ ; ++ ++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; ++ int flags; ++ EC_EXTRA_DATA *method_data; ++} /* EC_KEY */ ; ++ ++/* ++ * Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs ++ * only (with visibility limited to 'package' level for now). We use the ++ * function pointers as index for retrieval; this obviates global ++ * ex_data-style index tables. ++ */ ++int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)); ++void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *, void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)); ++void EC_EX_DATA_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)); ++void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)); ++void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **); ++void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **); ++ ++struct ec_point_st { ++ const EC_METHOD *meth; ++ /* ++ * All members except 'meth' are handled by the method functions, even if ++ * they appear generic ++ */ ++ BIGNUM X; ++ BIGNUM Y; ++ BIGNUM Z; /* Jacobian projective coordinates: (X, Y, Z) ++ * represents (X/Z^2, Y/Z^3) if Z != 0 */ ++ int Z_is_one; /* enable optimized point arithmetics for ++ * special case */ ++} /* EC_POINT */ ; ++ ++/* ++ * method functions in ec_mult.c (ec_lib.c uses these as defaults if ++ * group->method->mul is 0) ++ */ ++int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ++ size_t num, const EC_POINT *points[], const BIGNUM *scalars[], ++ BN_CTX *); ++int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *); ++int ec_wNAF_have_precompute_mult(const EC_GROUP *group); ++ ++/* method functions in ecp_smpl.c */ ++int ec_GFp_simple_group_init(EC_GROUP *); ++void ec_GFp_simple_group_finish(EC_GROUP *); ++void ec_GFp_simple_group_clear_finish(EC_GROUP *); ++int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); ++int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, ++ const BIGNUM *a, const BIGNUM *b, BN_CTX *); ++int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, ++ BIGNUM *b, BN_CTX *); ++int ec_GFp_simple_group_get_degree(const EC_GROUP *); ++int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); ++int ec_GFp_simple_point_init(EC_POINT *); ++void ec_GFp_simple_point_finish(EC_POINT *); ++void ec_GFp_simple_point_clear_finish(EC_POINT *); ++int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); ++int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); ++int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, ++ EC_POINT *, const BIGNUM *x, ++ const BIGNUM *y, ++ const BIGNUM *z, BN_CTX *); ++int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, ++ const EC_POINT *, BIGNUM *x, ++ BIGNUM *y, BIGNUM *z, ++ BN_CTX *); ++int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, ++ const BIGNUM *y, BN_CTX *); ++int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, ++ const EC_POINT *, BIGNUM *x, ++ BIGNUM *y, BN_CTX *); ++int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, int y_bit, ++ BN_CTX *); ++size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, ++ point_conversion_form_t form, ++ unsigned char *buf, size_t len, BN_CTX *); ++int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, ++ const unsigned char *buf, size_t len, BN_CTX *); ++int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *); ++int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, ++ BN_CTX *); ++int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); ++int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); ++int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); ++int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, ++ BN_CTX *); ++int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); ++int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, ++ EC_POINT *[], BN_CTX *); ++int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++ ++/* method functions in ecp_mont.c */ ++int ec_GFp_mont_group_init(EC_GROUP *); ++int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++void ec_GFp_mont_group_finish(EC_GROUP *); ++void ec_GFp_mont_group_clear_finish(EC_GROUP *); ++int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); ++int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); ++ ++/* method functions in ecp_nist.c */ ++int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); ++int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++ ++/* method functions in ec2_smpl.c */ ++int ec_GF2m_simple_group_init(EC_GROUP *); ++void ec_GF2m_simple_group_finish(EC_GROUP *); ++void ec_GF2m_simple_group_clear_finish(EC_GROUP *); ++int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *); ++int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, ++ const BIGNUM *a, const BIGNUM *b, ++ BN_CTX *); ++int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, ++ BIGNUM *b, BN_CTX *); ++int ec_GF2m_simple_group_get_degree(const EC_GROUP *); ++int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); ++int ec_GF2m_simple_point_init(EC_POINT *); ++void ec_GF2m_simple_point_finish(EC_POINT *); ++void ec_GF2m_simple_point_clear_finish(EC_POINT *); ++int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *); ++int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); ++int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, ++ const BIGNUM *y, BN_CTX *); ++int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, ++ const EC_POINT *, BIGNUM *x, ++ BIGNUM *y, BN_CTX *); ++int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, ++ const BIGNUM *x, int y_bit, ++ BN_CTX *); ++size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, ++ point_conversion_form_t form, ++ unsigned char *buf, size_t len, BN_CTX *); ++int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *, ++ const unsigned char *buf, size_t len, BN_CTX *); ++int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *); ++int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, ++ BN_CTX *); ++int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); ++int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); ++int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); ++int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, ++ BN_CTX *); ++int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); ++int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, ++ EC_POINT *[], BN_CTX *); ++int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *); ++int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *); ++ ++/* method functions in ec2_mult.c */ ++int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, ++ const BIGNUM *scalar, size_t num, ++ const EC_POINT *points[], const BIGNUM *scalars[], ++ BN_CTX *); ++int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); ++int ec_GF2m_have_precompute_mult(const EC_GROUP *group); ++ ++int ec_precompute_mont_data(EC_GROUP *); ++ ++#ifdef OPENSSL_FIPS ++EC_GROUP *FIPS_ec_group_new_curve_gfp(const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx); ++EC_GROUP *FIPS_ec_group_new_curve_gf2m(const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx); ++EC_GROUP *FIPS_ec_group_new_by_curve_name(int nid); ++#endif +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_lib.c b/Cryptlib/OpenSSL/crypto/ec/ec_lib.c +new file mode 100644 +index 0000000..4512c59 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_lib.c +@@ -0,0 +1,1077 @@ ++/* crypto/ec/ec_lib.c */ ++/* ++ * Originally written by Bodo Moeller for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Binary polynomial ECC support in OpenSSL originally developed by ++ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "ec_lcl.h" ++ ++const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; ++ ++/* functions for EC_GROUP objects */ ++ ++EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) ++{ ++ EC_GROUP *ret; ++ ++ if (meth == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); ++ return NULL; ++ } ++ if (meth->group_init == 0) { ++ ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return NULL; ++ } ++ ++ ret = OPENSSL_malloc(sizeof *ret); ++ if (ret == NULL) { ++ ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ ret->meth = meth; ++ ++ ret->extra_data = NULL; ++ ret->mont_data = NULL; ++ ++ ret->generator = NULL; ++ BN_init(&ret->order); ++ BN_init(&ret->cofactor); ++ ++ ret->curve_name = 0; ++ ret->asn1_flag = ~EC_GROUP_ASN1_FLAG_MASK; ++ ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; ++ ++ ret->seed = NULL; ++ ret->seed_len = 0; ++ ++ if (!meth->group_init(ret)) { ++ OPENSSL_free(ret); ++ return NULL; ++ } ++ ++ return ret; ++} ++ ++void EC_GROUP_free(EC_GROUP *group) ++{ ++ if (!group) ++ return; ++ ++ if (group->meth->group_finish != 0) ++ group->meth->group_finish(group); ++ ++ EC_EX_DATA_free_all_data(&group->extra_data); ++ ++ if (EC_GROUP_VERSION(group) && group->mont_data) ++ BN_MONT_CTX_free(group->mont_data); ++ ++ if (group->generator != NULL) ++ EC_POINT_free(group->generator); ++ BN_free(&group->order); ++ BN_free(&group->cofactor); ++ ++ if (group->seed) ++ OPENSSL_free(group->seed); ++ ++ OPENSSL_free(group); ++} ++ ++void EC_GROUP_clear_free(EC_GROUP *group) ++{ ++ if (!group) ++ return; ++ ++ if (group->meth->group_clear_finish != 0) ++ group->meth->group_clear_finish(group); ++ else if (group->meth->group_finish != 0) ++ group->meth->group_finish(group); ++ ++ EC_EX_DATA_clear_free_all_data(&group->extra_data); ++ ++ if (EC_GROUP_VERSION(group) && group->mont_data) ++ BN_MONT_CTX_free(group->mont_data); ++ ++ if (group->generator != NULL) ++ EC_POINT_clear_free(group->generator); ++ BN_clear_free(&group->order); ++ BN_clear_free(&group->cofactor); ++ ++ if (group->seed) { ++ OPENSSL_cleanse(group->seed, group->seed_len); ++ OPENSSL_free(group->seed); ++ } ++ ++ OPENSSL_cleanse(group, sizeof *group); ++ OPENSSL_free(group); ++} ++ ++int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) ++{ ++ EC_EXTRA_DATA *d; ++ ++ if (dest->meth->group_copy == 0) { ++ ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (dest->meth != src->meth) { ++ ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ if (dest == src) ++ return 1; ++ ++ EC_EX_DATA_free_all_data(&dest->extra_data); ++ ++ for (d = src->extra_data; d != NULL; d = d->next) { ++ void *t = d->dup_func(d->data); ++ ++ if (t == NULL) ++ return 0; ++ if (!EC_EX_DATA_set_data ++ (&dest->extra_data, t, d->dup_func, d->free_func, ++ d->clear_free_func)) ++ return 0; ++ } ++ ++ if (EC_GROUP_VERSION(src) && src->mont_data != NULL) { ++ if (dest->mont_data == NULL) { ++ dest->mont_data = BN_MONT_CTX_new(); ++ if (dest->mont_data == NULL) ++ return 0; ++ } ++ if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) ++ return 0; ++ } else { ++ /* src->generator == NULL */ ++ if (EC_GROUP_VERSION(dest) && dest->mont_data != NULL) { ++ BN_MONT_CTX_free(dest->mont_data); ++ dest->mont_data = NULL; ++ } ++ } ++ ++ if (src->generator != NULL) { ++ if (dest->generator == NULL) { ++ dest->generator = EC_POINT_new(dest); ++ if (dest->generator == NULL) ++ return 0; ++ } ++ if (!EC_POINT_copy(dest->generator, src->generator)) ++ return 0; ++ } else { ++ /* src->generator == NULL */ ++ if (dest->generator != NULL) { ++ EC_POINT_clear_free(dest->generator); ++ dest->generator = NULL; ++ } ++ } ++ ++ if (!BN_copy(&dest->order, &src->order)) ++ return 0; ++ if (!BN_copy(&dest->cofactor, &src->cofactor)) ++ return 0; ++ ++ dest->curve_name = src->curve_name; ++ dest->asn1_flag = src->asn1_flag; ++ dest->asn1_form = src->asn1_form; ++ ++ if (src->seed) { ++ if (dest->seed) ++ OPENSSL_free(dest->seed); ++ dest->seed = OPENSSL_malloc(src->seed_len); ++ if (dest->seed == NULL) ++ return 0; ++ if (!memcpy(dest->seed, src->seed, src->seed_len)) ++ return 0; ++ dest->seed_len = src->seed_len; ++ } else { ++ if (dest->seed) ++ OPENSSL_free(dest->seed); ++ dest->seed = NULL; ++ dest->seed_len = 0; ++ } ++ ++ return dest->meth->group_copy(dest, src); ++} ++ ++EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) ++{ ++ EC_GROUP *t = NULL; ++ int ok = 0; ++ ++ if (a == NULL) ++ return NULL; ++ ++ if ((t = EC_GROUP_new(a->meth)) == NULL) ++ return (NULL); ++ if (!EC_GROUP_copy(t, a)) ++ goto err; ++ ++ ok = 1; ++ ++ err: ++ if (!ok) { ++ if (t) ++ EC_GROUP_free(t); ++ return NULL; ++ } else ++ return t; ++} ++ ++const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) ++{ ++ return group->meth; ++} ++ ++int EC_METHOD_get_field_type(const EC_METHOD *meth) ++{ ++ return meth->field_type; ++} ++ ++int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, ++ const BIGNUM *order, const BIGNUM *cofactor) ++{ ++ if (generator == NULL) { ++ ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ++ if (group->generator == NULL) { ++ group->generator = EC_POINT_new(group); ++ if (group->generator == NULL) ++ return 0; ++ } ++ if (!EC_POINT_copy(group->generator, generator)) ++ return 0; ++ ++ if (order != NULL) { ++ if (!BN_copy(&group->order, order)) ++ return 0; ++ } else ++ BN_zero(&group->order); ++ ++ if (cofactor != NULL) { ++ if (!BN_copy(&group->cofactor, cofactor)) ++ return 0; ++ } else ++ BN_zero(&group->cofactor); ++ ++ /* ++ * We ignore the return value because some groups have an order with ++ * factors of two, which makes the Montgomery setup fail. ++ * |group->mont_data| will be NULL in this case. ++ */ ++ ec_precompute_mont_data(group); ++ ++ return 1; ++} ++ ++const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) ++{ ++ return group->generator; ++} ++ ++BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) ++{ ++ return EC_GROUP_VERSION(group) ? group->mont_data : NULL; ++} ++ ++int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) ++{ ++ if (!BN_copy(order, &group->order)) ++ return 0; ++ ++ return !BN_is_zero(order); ++} ++ ++const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) ++{ ++ return &group->order; ++} ++ ++int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, ++ BN_CTX *ctx) ++{ ++ if (!BN_copy(cofactor, &group->cofactor)) ++ return 0; ++ ++ return !BN_is_zero(&group->cofactor); ++} ++ ++void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) ++{ ++ group->curve_name = nid; ++} ++ ++int EC_GROUP_get_curve_name(const EC_GROUP *group) ++{ ++ return group->curve_name; ++} ++ ++void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) ++{ ++ group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK; ++ group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK; ++} ++ ++int EC_GROUP_get_asn1_flag(const EC_GROUP *group) ++{ ++ return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK; ++} ++ ++void EC_GROUP_set_point_conversion_form(EC_GROUP *group, ++ point_conversion_form_t form) ++{ ++ group->asn1_form = form; ++} ++ ++point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP ++ *group) ++{ ++ return group->asn1_form; ++} ++ ++size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) ++{ ++ if (group->seed) { ++ OPENSSL_free(group->seed); ++ group->seed = NULL; ++ group->seed_len = 0; ++ } ++ ++ if (!len || !p) ++ return 1; ++ ++ if ((group->seed = OPENSSL_malloc(len)) == NULL) ++ return 0; ++ memcpy(group->seed, p, len); ++ group->seed_len = len; ++ ++ return len; ++} ++ ++unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) ++{ ++ return group->seed; ++} ++ ++size_t EC_GROUP_get_seed_len(const EC_GROUP *group) ++{ ++ return group->seed_len; ++} ++ ++int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ if (group->meth->group_set_curve == 0) { ++ ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ return group->meth->group_set_curve(group, p, a, b, ctx); ++} ++ ++int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, ++ BIGNUM *b, BN_CTX *ctx) ++{ ++ if (group->meth->group_get_curve == 0) { ++ ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ return group->meth->group_get_curve(group, p, a, b, ctx); ++} ++ ++int EC_GROUP_get_degree(const EC_GROUP *group) ++{ ++ if (group->meth->group_get_degree == 0) { ++ ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ return group->meth->group_get_degree(group); ++} ++ ++int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) ++{ ++ if (group->meth->group_check_discriminant == 0) { ++ ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ return group->meth->group_check_discriminant(group, ctx); ++} ++ ++int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) ++{ ++ int r = 0; ++ BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; ++ BN_CTX *ctx_new = NULL; ++ ++ /* compare the field types */ ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != ++ EC_METHOD_get_field_type(EC_GROUP_method_of(b))) ++ return 1; ++ /* compare the curve name (if present in both) */ ++ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && ++ EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) ++ return 1; ++ ++ if (!ctx) ++ ctx_new = ctx = BN_CTX_new(); ++ if (!ctx) ++ return -1; ++ ++ BN_CTX_start(ctx); ++ a1 = BN_CTX_get(ctx); ++ a2 = BN_CTX_get(ctx); ++ a3 = BN_CTX_get(ctx); ++ b1 = BN_CTX_get(ctx); ++ b2 = BN_CTX_get(ctx); ++ b3 = BN_CTX_get(ctx); ++ if (!b3) { ++ BN_CTX_end(ctx); ++ if (ctx_new) ++ BN_CTX_free(ctx); ++ return -1; ++ } ++ ++ /* ++ * XXX This approach assumes that the external representation of curves ++ * over the same field type is the same. ++ */ ++ if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || ++ !b->meth->group_get_curve(b, b1, b2, b3, ctx)) ++ r = 1; ++ ++ if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) ++ r = 1; ++ ++ /* XXX EC_POINT_cmp() assumes that the methods are equal */ ++ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), ++ EC_GROUP_get0_generator(b), ctx)) ++ r = 1; ++ ++ if (!r) { ++ /* compare the order and cofactor */ ++ if (!EC_GROUP_get_order(a, a1, ctx) || ++ !EC_GROUP_get_order(b, b1, ctx) || ++ !EC_GROUP_get_cofactor(a, a2, ctx) || ++ !EC_GROUP_get_cofactor(b, b2, ctx)) { ++ BN_CTX_end(ctx); ++ if (ctx_new) ++ BN_CTX_free(ctx); ++ return -1; ++ } ++ if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) ++ r = 1; ++ } ++ ++ BN_CTX_end(ctx); ++ if (ctx_new) ++ BN_CTX_free(ctx); ++ ++ return r; ++} ++ ++/* this has 'package' visibility */ ++int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ EC_EXTRA_DATA *d; ++ ++ if (ex_data == NULL) ++ return 0; ++ ++ for (d = *ex_data; d != NULL; d = d->next) { ++ if (d->dup_func == dup_func && d->free_func == free_func ++ && d->clear_free_func == clear_free_func) { ++ ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); ++ return 0; ++ } ++ } ++ ++ if (data == NULL) ++ /* no explicit entry needed */ ++ return 1; ++ ++ d = OPENSSL_malloc(sizeof *d); ++ if (d == NULL) ++ return 0; ++ ++ d->data = data; ++ d->dup_func = dup_func; ++ d->free_func = free_func; ++ d->clear_free_func = clear_free_func; ++ ++ d->next = *ex_data; ++ *ex_data = d; ++ ++ return 1; ++} ++ ++/* this has 'package' visibility */ ++void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ const EC_EXTRA_DATA *d; ++ ++ for (d = ex_data; d != NULL; d = d->next) { ++ if (d->dup_func == dup_func && d->free_func == free_func ++ && d->clear_free_func == clear_free_func) ++ return d->data; ++ } ++ ++ return NULL; ++} ++ ++/* this has 'package' visibility */ ++void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ EC_EXTRA_DATA **p; ++ ++ if (ex_data == NULL) ++ return; ++ ++ for (p = ex_data; *p != NULL; p = &((*p)->next)) { ++ if ((*p)->dup_func == dup_func && (*p)->free_func == free_func ++ && (*p)->clear_free_func == clear_free_func) { ++ EC_EXTRA_DATA *next = (*p)->next; ++ ++ (*p)->free_func((*p)->data); ++ OPENSSL_free(*p); ++ ++ *p = next; ++ return; ++ } ++ } ++} ++ ++/* this has 'package' visibility */ ++void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, ++ void *(*dup_func) (void *), ++ void (*free_func) (void *), ++ void (*clear_free_func) (void *)) ++{ ++ EC_EXTRA_DATA **p; ++ ++ if (ex_data == NULL) ++ return; ++ ++ for (p = ex_data; *p != NULL; p = &((*p)->next)) { ++ if ((*p)->dup_func == dup_func && (*p)->free_func == free_func ++ && (*p)->clear_free_func == clear_free_func) { ++ EC_EXTRA_DATA *next = (*p)->next; ++ ++ (*p)->clear_free_func((*p)->data); ++ OPENSSL_free(*p); ++ ++ *p = next; ++ return; ++ } ++ } ++} ++ ++/* this has 'package' visibility */ ++void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) ++{ ++ EC_EXTRA_DATA *d; ++ ++ if (ex_data == NULL) ++ return; ++ ++ d = *ex_data; ++ while (d) { ++ EC_EXTRA_DATA *next = d->next; ++ ++ d->free_func(d->data); ++ OPENSSL_free(d); ++ ++ d = next; ++ } ++ *ex_data = NULL; ++} ++ ++/* this has 'package' visibility */ ++void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) ++{ ++ EC_EXTRA_DATA *d; ++ ++ if (ex_data == NULL) ++ return; ++ ++ d = *ex_data; ++ while (d) { ++ EC_EXTRA_DATA *next = d->next; ++ ++ d->clear_free_func(d->data); ++ OPENSSL_free(d); ++ ++ d = next; ++ } ++ *ex_data = NULL; ++} ++ ++/* functions for EC_POINT objects */ ++ ++EC_POINT *EC_POINT_new(const EC_GROUP *group) ++{ ++ EC_POINT *ret; ++ ++ if (group == NULL) { ++ ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); ++ return NULL; ++ } ++ if (group->meth->point_init == 0) { ++ ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return NULL; ++ } ++ ++ ret = OPENSSL_malloc(sizeof *ret); ++ if (ret == NULL) { ++ ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ ret->meth = group->meth; ++ ++ if (!ret->meth->point_init(ret)) { ++ OPENSSL_free(ret); ++ return NULL; ++ } ++ ++ return ret; ++} ++ ++void EC_POINT_free(EC_POINT *point) ++{ ++ if (!point) ++ return; ++ ++ if (point->meth->point_finish != 0) ++ point->meth->point_finish(point); ++ OPENSSL_free(point); ++} ++ ++void EC_POINT_clear_free(EC_POINT *point) ++{ ++ if (!point) ++ return; ++ ++ if (point->meth->point_clear_finish != 0) ++ point->meth->point_clear_finish(point); ++ else if (point->meth->point_finish != 0) ++ point->meth->point_finish(point); ++ OPENSSL_cleanse(point, sizeof *point); ++ OPENSSL_free(point); ++} ++ ++int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) ++{ ++ if (dest->meth->point_copy == 0) { ++ ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (dest->meth != src->meth) { ++ ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ if (dest == src) ++ return 1; ++ return dest->meth->point_copy(dest, src); ++} ++ ++EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) ++{ ++ EC_POINT *t; ++ int r; ++ ++ if (a == NULL) ++ return NULL; ++ ++ t = EC_POINT_new(group); ++ if (t == NULL) ++ return (NULL); ++ r = EC_POINT_copy(t, a); ++ if (!r) { ++ EC_POINT_free(t); ++ return NULL; ++ } else ++ return t; ++} ++ ++const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) ++{ ++ return point->meth; ++} ++ ++int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) ++{ ++ if (group->meth->point_set_to_infinity == 0) { ++ ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->point_set_to_infinity(group, point); ++} ++ ++int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, ++ EC_POINT *point, const BIGNUM *x, ++ const BIGNUM *y, const BIGNUM *z, ++ BN_CTX *ctx) ++{ ++ if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { ++ ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ++ EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, ++ y, z, ctx); ++} ++ ++int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, ++ const EC_POINT *point, BIGNUM *x, ++ BIGNUM *y, BIGNUM *z, ++ BN_CTX *ctx) ++{ ++ if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { ++ ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ++ EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, ++ y, z, ctx); ++} ++ ++int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, ++ EC_POINT *point, const BIGNUM *x, ++ const BIGNUM *y, BN_CTX *ctx) ++{ ++ if (group->meth->point_set_affine_coordinates == 0) { ++ ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ++ EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); ++} ++ ++int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, ++ const EC_POINT *point, BIGNUM *x, ++ BIGNUM *y, BN_CTX *ctx) ++{ ++ if (group->meth->point_get_affine_coordinates == 0) { ++ ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ++ EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); ++} ++ ++int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *ctx) ++{ ++ if (group->meth->add == 0) { ++ ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if ((group->meth != r->meth) || (r->meth != a->meth) ++ || (a->meth != b->meth)) { ++ ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->add(group, r, a, b, ctx); ++} ++ ++int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ++ BN_CTX *ctx) ++{ ++ if (group->meth->dbl == 0) { ++ ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if ((group->meth != r->meth) || (r->meth != a->meth)) { ++ ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->dbl(group, r, a, ctx); ++} ++ ++int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) ++{ ++ if (group->meth->invert == 0) { ++ ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != a->meth) { ++ ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->invert(group, a, ctx); ++} ++ ++int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) ++{ ++ if (group->meth->is_at_infinity == 0) { ++ ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->is_at_infinity(group, point); ++} ++ ++/* ++ * Check whether an EC_POINT is on the curve or not. Note that the return ++ * value for this function should NOT be treated as a boolean. Return values: ++ * 1: The point is on the curve ++ * 0: The point is not on the curve ++ * -1: An error occurred ++ */ ++int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, ++ BN_CTX *ctx) ++{ ++ if (group->meth->is_on_curve == 0) { ++ ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->is_on_curve(group, point, ctx); ++} ++ ++int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, ++ BN_CTX *ctx) ++{ ++ if (group->meth->point_cmp == 0) { ++ ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return -1; ++ } ++ if ((group->meth != a->meth) || (a->meth != b->meth)) { ++ ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); ++ return -1; ++ } ++ return group->meth->point_cmp(group, a, b, ctx); ++} ++ ++int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) ++{ ++ if (group->meth->make_affine == 0) { ++ ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ return group->meth->make_affine(group, point, ctx); ++} ++ ++int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, ++ EC_POINT *points[], BN_CTX *ctx) ++{ ++ size_t i; ++ ++ if (group->meth->points_make_affine == 0) { ++ ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ for (i = 0; i < num; i++) { ++ if (group->meth != points[i]->meth) { ++ ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ } ++ return group->meth->points_make_affine(group, num, points, ctx); ++} ++ ++/* ++ * Functions for point multiplication. If group->meth->mul is 0, we use the ++ * wNAF-based implementations in ec_mult.c; otherwise we dispatch through ++ * methods. ++ */ ++ ++int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ++ size_t num, const EC_POINT *points[], ++ const BIGNUM *scalars[], BN_CTX *ctx) ++{ ++ if (group->meth->mul == 0) ++ /* use default */ ++ return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); ++ ++ return group->meth->mul(group, r, scalar, num, points, scalars, ctx); ++} ++ ++int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, ++ const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) ++{ ++ /* just a convenient interface to EC_POINTs_mul() */ ++ ++ const EC_POINT *points[1]; ++ const BIGNUM *scalars[1]; ++ ++ points[0] = point; ++ scalars[0] = p_scalar; ++ ++ return EC_POINTs_mul(group, r, g_scalar, ++ (point != NULL ++ && p_scalar != NULL), points, scalars, ctx); ++} ++ ++int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) ++{ ++ if (group->meth->mul == 0) ++ /* use default */ ++ return ec_wNAF_precompute_mult(group, ctx); ++ ++ if (group->meth->precompute_mult != 0) ++ return group->meth->precompute_mult(group, ctx); ++ else ++ return 1; /* nothing to do, so report success */ ++} ++ ++int EC_GROUP_have_precompute_mult(const EC_GROUP *group) ++{ ++ if (group->meth->mul == 0) ++ /* use default */ ++ return ec_wNAF_have_precompute_mult(group); ++ ++ if (group->meth->have_precompute_mult != 0) ++ return group->meth->have_precompute_mult(group); ++ else ++ return 0; /* cannot tell whether precomputation has ++ * been performed */ ++} ++ ++/* ++ * ec_precompute_mont_data sets |group->mont_data| from |group->order| and ++ * returns one on success. On error it returns zero. ++ */ ++int ec_precompute_mont_data(EC_GROUP *group) ++{ ++ BN_CTX *ctx = BN_CTX_new(); ++ int ret = 0; ++ ++ if (!EC_GROUP_VERSION(group)) ++ goto err; ++ ++ if (group->mont_data) { ++ BN_MONT_CTX_free(group->mont_data); ++ group->mont_data = NULL; ++ } ++ ++ if (ctx == NULL) ++ goto err; ++ ++ group->mont_data = BN_MONT_CTX_new(); ++ if (!group->mont_data) ++ goto err; ++ ++ if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) { ++ BN_MONT_CTX_free(group->mont_data); ++ group->mont_data = NULL; ++ goto err; ++ } ++ ++ ret = 1; ++ ++ err: ++ ++ if (ctx) ++ BN_CTX_free(ctx); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_mult.c b/Cryptlib/OpenSSL/crypto/ec/ec_mult.c +new file mode 100644 +index 0000000..23b8c30 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_mult.c +@@ -0,0 +1,913 @@ ++/* crypto/ec/ec_mult.c */ ++/* ++ * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2007 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions of this software developed by SUN MICROSYSTEMS, INC., ++ * and contributed to the OpenSSL project. ++ */ ++ ++#include ++ ++#include ++ ++#include "ec_lcl.h" ++ ++/* ++ * This file implements the wNAF-based interleaving multi-exponentation method ++ * (); ++ * for multiplication with precomputation, we use wNAF splitting ++ * (). ++ */ ++ ++/* structure for precomputed multiples of the generator */ ++typedef struct ec_pre_comp_st { ++ const EC_GROUP *group; /* parent EC_GROUP object */ ++ size_t blocksize; /* block size for wNAF splitting */ ++ size_t numblocks; /* max. number of blocks for which we have ++ * precomputation */ ++ size_t w; /* window size */ ++ EC_POINT **points; /* array with pre-calculated multiples of ++ * generator: 'num' pointers to EC_POINT ++ * objects followed by a NULL */ ++ size_t num; /* numblocks * 2^(w-1) */ ++ int references; ++} EC_PRE_COMP; ++ ++/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */ ++static void *ec_pre_comp_dup(void *); ++static void ec_pre_comp_free(void *); ++static void ec_pre_comp_clear_free(void *); ++ ++static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) ++{ ++ EC_PRE_COMP *ret = NULL; ++ ++ if (!group) ++ return NULL; ++ ++ ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP)); ++ if (!ret) { ++ ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); ++ return ret; ++ } ++ ret->group = group; ++ ret->blocksize = 8; /* default */ ++ ret->numblocks = 0; ++ ret->w = 4; /* default */ ++ ret->points = NULL; ++ ret->num = 0; ++ ret->references = 1; ++ return ret; ++} ++ ++static void *ec_pre_comp_dup(void *src_) ++{ ++ EC_PRE_COMP *src = src_; ++ ++ /* no need to actually copy, these objects never change! */ ++ ++ CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); ++ ++ return src_; ++} ++ ++static void ec_pre_comp_free(void *pre_) ++{ ++ int i; ++ EC_PRE_COMP *pre = pre_; ++ ++ if (!pre) ++ return; ++ ++ i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); ++ if (i > 0) ++ return; ++ ++ if (pre->points) { ++ EC_POINT **p; ++ ++ for (p = pre->points; *p != NULL; p++) ++ EC_POINT_free(*p); ++ OPENSSL_free(pre->points); ++ } ++ OPENSSL_free(pre); ++} ++ ++static void ec_pre_comp_clear_free(void *pre_) ++{ ++ int i; ++ EC_PRE_COMP *pre = pre_; ++ ++ if (!pre) ++ return; ++ ++ i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); ++ if (i > 0) ++ return; ++ ++ if (pre->points) { ++ EC_POINT **p; ++ ++ for (p = pre->points; *p != NULL; p++) { ++ EC_POINT_clear_free(*p); ++ OPENSSL_cleanse(p, sizeof *p); ++ } ++ OPENSSL_free(pre->points); ++ } ++ OPENSSL_cleanse(pre, sizeof *pre); ++ OPENSSL_free(pre); ++} ++ ++/*- ++ * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. ++ * This is an array r[] of values that are either zero or odd with an ++ * absolute value less than 2^w satisfying ++ * scalar = \sum_j r[j]*2^j ++ * where at most one of any w+1 consecutive digits is non-zero ++ * with the exception that the most significant digit may be only ++ * w-1 zeros away from that next non-zero digit. ++ */ ++static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) ++{ ++ int window_val; ++ int ok = 0; ++ signed char *r = NULL; ++ int sign = 1; ++ int bit, next_bit, mask; ++ size_t len = 0, j; ++ ++ if (BN_is_zero(scalar)) { ++ r = OPENSSL_malloc(1); ++ if (!r) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ r[0] = 0; ++ *ret_len = 1; ++ return r; ++ } ++ ++ if (w <= 0 || w > 7) { /* 'signed char' can represent integers with ++ * absolute values less than 2^7 */ ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ bit = 1 << w; /* at most 128 */ ++ next_bit = bit << 1; /* at most 256 */ ++ mask = next_bit - 1; /* at most 255 */ ++ ++ if (BN_is_negative(scalar)) { ++ sign = -1; ++ } ++ ++ if (scalar->d == NULL || scalar->top == 0) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ len = BN_num_bits(scalar); ++ r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer ++ * than binary representation (*ret_len will ++ * be set to the actual length, i.e. at most ++ * BN_num_bits(scalar) + 1) */ ++ if (r == NULL) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ window_val = scalar->d[0] & mask; ++ j = 0; ++ while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len, ++ * window_val will not ++ * increase */ ++ int digit = 0; ++ ++ /* 0 <= window_val <= 2^(w+1) */ ++ ++ if (window_val & 1) { ++ /* 0 < window_val < 2^(w+1) */ ++ ++ if (window_val & bit) { ++ digit = window_val - next_bit; /* -2^w < digit < 0 */ ++ ++#if 1 /* modified wNAF */ ++ if (j + w + 1 >= len) { ++ /* ++ * special case for generating modified wNAFs: no new ++ * bits will be added into window_val, so using a ++ * positive digit here will decrease the total length of ++ * the representation ++ */ ++ ++ digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ ++ } ++#endif ++ } else { ++ digit = window_val; /* 0 < digit < 2^w */ ++ } ++ ++ if (digit <= -bit || digit >= bit || !(digit & 1)) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ window_val -= digit; ++ ++ /* ++ * now window_val is 0 or 2^(w+1) in standard wNAF generation; ++ * for modified window NAFs, it may also be 2^w ++ */ ++ if (window_val != 0 && window_val != next_bit ++ && window_val != bit) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ } ++ ++ r[j++] = sign * digit; ++ ++ window_val >>= 1; ++ window_val += bit * BN_is_bit_set(scalar, j + w); ++ ++ if (window_val > next_bit) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ } ++ ++ if (j > len + 1) { ++ ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ len = j; ++ ok = 1; ++ ++ err: ++ if (!ok) { ++ OPENSSL_free(r); ++ r = NULL; ++ } ++ if (ok) ++ *ret_len = len; ++ return r; ++} ++ ++/* ++ * TODO: table should be optimised for the wNAF-based implementation, ++ * sometimes smaller windows will give better performance (thus the ++ * boundaries should be increased) ++ */ ++#define EC_window_bits_for_scalar_size(b) \ ++ ((size_t) \ ++ ((b) >= 2000 ? 6 : \ ++ (b) >= 800 ? 5 : \ ++ (b) >= 300 ? 4 : \ ++ (b) >= 70 ? 3 : \ ++ (b) >= 20 ? 2 : \ ++ 1)) ++ ++/*- ++ * Compute ++ * \sum scalars[i]*points[i], ++ * also including ++ * scalar*generator ++ * in the addition if scalar != NULL ++ */ ++int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ++ size_t num, const EC_POINT *points[], const BIGNUM *scalars[], ++ BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ const EC_POINT *generator = NULL; ++ EC_POINT *tmp = NULL; ++ size_t totalnum; ++ size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */ ++ size_t pre_points_per_block = 0; ++ size_t i, j; ++ int k; ++ int r_is_inverted = 0; ++ int r_is_at_infinity = 1; ++ size_t *wsize = NULL; /* individual window sizes */ ++ signed char **wNAF = NULL; /* individual wNAFs */ ++ size_t *wNAF_len = NULL; ++ size_t max_len = 0; ++ size_t num_val; ++ EC_POINT **val = NULL; /* precomputation */ ++ EC_POINT **v; ++ EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or ++ * 'pre_comp->points' */ ++ const EC_PRE_COMP *pre_comp = NULL; ++ int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be ++ * treated like other scalars, i.e. ++ * precomputation is not available */ ++ int ret = 0; ++ ++ if (group->meth != r->meth) { ++ ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ ++ if ((scalar == NULL) && (num == 0)) { ++ return EC_POINT_set_to_infinity(group, r); ++ } ++ ++ for (i = 0; i < num; i++) { ++ if (group->meth != points[i]->meth) { ++ ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ goto err; ++ } ++ ++ if (scalar != NULL) { ++ generator = EC_GROUP_get0_generator(group); ++ if (generator == NULL) { ++ ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR); ++ goto err; ++ } ++ ++ /* look if we can use precomputed multiples of generator */ ++ ++ pre_comp = ++ EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ++ ec_pre_comp_free, ec_pre_comp_clear_free); ++ ++ if (pre_comp && pre_comp->numblocks ++ && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == ++ 0)) { ++ blocksize = pre_comp->blocksize; ++ ++ /* ++ * determine maximum number of blocks that wNAF splitting may ++ * yield (NB: maximum wNAF length is bit length plus one) ++ */ ++ numblocks = (BN_num_bits(scalar) / blocksize) + 1; ++ ++ /* ++ * we cannot use more blocks than we have precomputation for ++ */ ++ if (numblocks > pre_comp->numblocks) ++ numblocks = pre_comp->numblocks; ++ ++ pre_points_per_block = (size_t)1 << (pre_comp->w - 1); ++ ++ /* check that pre_comp looks sane */ ++ if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ } else { ++ /* can't use precomputation */ ++ pre_comp = NULL; ++ numblocks = 1; ++ num_scalar = 1; /* treat 'scalar' like 'num'-th element of ++ * 'scalars' */ ++ } ++ } ++ ++ totalnum = num + numblocks; ++ ++ wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]); ++ wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]); ++ wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space ++ * for pivot */ ++ val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]); ++ ++ /* Ensure wNAF is initialised in case we end up going to err */ ++ if (wNAF) ++ wNAF[0] = NULL; /* preliminary pivot */ ++ ++ if (!wsize || !wNAF_len || !wNAF || !val_sub) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /* ++ * num_val will be the total number of temporarily precomputed points ++ */ ++ num_val = 0; ++ ++ for (i = 0; i < num + num_scalar; i++) { ++ size_t bits; ++ ++ bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); ++ wsize[i] = EC_window_bits_for_scalar_size(bits); ++ num_val += (size_t)1 << (wsize[i] - 1); ++ wNAF[i + 1] = NULL; /* make sure we always have a pivot */ ++ wNAF[i] = ++ compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], ++ &wNAF_len[i]); ++ if (wNAF[i] == NULL) ++ goto err; ++ if (wNAF_len[i] > max_len) ++ max_len = wNAF_len[i]; ++ } ++ ++ if (numblocks) { ++ /* we go here iff scalar != NULL */ ++ ++ if (pre_comp == NULL) { ++ if (num_scalar != 1) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* we have already generated a wNAF for 'scalar' */ ++ } else { ++ signed char *tmp_wNAF = NULL; ++ size_t tmp_len = 0; ++ ++ if (num_scalar != 0) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ /* ++ * use the window size for which we have precomputation ++ */ ++ wsize[num] = pre_comp->w; ++ tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len); ++ if (!tmp_wNAF) ++ goto err; ++ ++ if (tmp_len <= max_len) { ++ /* ++ * One of the other wNAFs is at least as long as the wNAF ++ * belonging to the generator, so wNAF splitting will not buy ++ * us anything. ++ */ ++ ++ numblocks = 1; ++ totalnum = num + 1; /* don't use wNAF splitting */ ++ wNAF[num] = tmp_wNAF; ++ wNAF[num + 1] = NULL; ++ wNAF_len[num] = tmp_len; ++ if (tmp_len > max_len) ++ max_len = tmp_len; ++ /* ++ * pre_comp->points starts with the points that we need here: ++ */ ++ val_sub[num] = pre_comp->points; ++ } else { ++ /* ++ * don't include tmp_wNAF directly into wNAF array - use wNAF ++ * splitting and include the blocks ++ */ ++ ++ signed char *pp; ++ EC_POINT **tmp_points; ++ ++ if (tmp_len < numblocks * blocksize) { ++ /* ++ * possibly we can do with fewer blocks than estimated ++ */ ++ numblocks = (tmp_len + blocksize - 1) / blocksize; ++ if (numblocks > pre_comp->numblocks) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ totalnum = num + numblocks; ++ } ++ ++ /* split wNAF in 'numblocks' parts */ ++ pp = tmp_wNAF; ++ tmp_points = pre_comp->points; ++ ++ for (i = num; i < totalnum; i++) { ++ if (i < totalnum - 1) { ++ wNAF_len[i] = blocksize; ++ if (tmp_len < blocksize) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ tmp_len -= blocksize; ++ } else ++ /* ++ * last block gets whatever is left (this could be ++ * more or less than 'blocksize'!) ++ */ ++ wNAF_len[i] = tmp_len; ++ ++ wNAF[i + 1] = NULL; ++ wNAF[i] = OPENSSL_malloc(wNAF_len[i]); ++ if (wNAF[i] == NULL) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); ++ OPENSSL_free(tmp_wNAF); ++ goto err; ++ } ++ memcpy(wNAF[i], pp, wNAF_len[i]); ++ if (wNAF_len[i] > max_len) ++ max_len = wNAF_len[i]; ++ ++ if (*tmp_points == NULL) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ OPENSSL_free(tmp_wNAF); ++ goto err; ++ } ++ val_sub[i] = tmp_points; ++ tmp_points += pre_points_per_block; ++ pp += blocksize; ++ } ++ OPENSSL_free(tmp_wNAF); ++ } ++ } ++ } ++ ++ /* ++ * All points we precompute now go into a single array 'val'. ++ * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a ++ * subarray of 'pre_comp->points' if we already have precomputation. ++ */ ++ val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); ++ if (val == NULL) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ val[num_val] = NULL; /* pivot element */ ++ ++ /* allocate points for precomputation */ ++ v = val; ++ for (i = 0; i < num + num_scalar; i++) { ++ val_sub[i] = v; ++ for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { ++ *v = EC_POINT_new(group); ++ if (*v == NULL) ++ goto err; ++ v++; ++ } ++ } ++ if (!(v == val + num_val)) { ++ ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!(tmp = EC_POINT_new(group))) ++ goto err; ++ ++ /*- ++ * prepare precomputed values: ++ * val_sub[i][0] := points[i] ++ * val_sub[i][1] := 3 * points[i] ++ * val_sub[i][2] := 5 * points[i] ++ * ... ++ */ ++ for (i = 0; i < num + num_scalar; i++) { ++ if (i < num) { ++ if (!EC_POINT_copy(val_sub[i][0], points[i])) ++ goto err; ++ } else { ++ if (!EC_POINT_copy(val_sub[i][0], generator)) ++ goto err; ++ } ++ ++ if (wsize[i] > 1) { ++ if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) ++ goto err; ++ for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { ++ if (!EC_POINT_add ++ (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) ++ goto err; ++ } ++ } ++ } ++ ++#if 1 /* optional; EC_window_bits_for_scalar_size ++ * assumes we do this step */ ++ if (!EC_POINTs_make_affine(group, num_val, val, ctx)) ++ goto err; ++#endif ++ ++ r_is_at_infinity = 1; ++ ++ for (k = max_len - 1; k >= 0; k--) { ++ if (!r_is_at_infinity) { ++ if (!EC_POINT_dbl(group, r, r, ctx)) ++ goto err; ++ } ++ ++ for (i = 0; i < totalnum; i++) { ++ if (wNAF_len[i] > (size_t)k) { ++ int digit = wNAF[i][k]; ++ int is_neg; ++ ++ if (digit) { ++ is_neg = digit < 0; ++ ++ if (is_neg) ++ digit = -digit; ++ ++ if (is_neg != r_is_inverted) { ++ if (!r_is_at_infinity) { ++ if (!EC_POINT_invert(group, r, ctx)) ++ goto err; ++ } ++ r_is_inverted = !r_is_inverted; ++ } ++ ++ /* digit > 0 */ ++ ++ if (r_is_at_infinity) { ++ if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) ++ goto err; ++ r_is_at_infinity = 0; ++ } else { ++ if (!EC_POINT_add ++ (group, r, r, val_sub[i][digit >> 1], ctx)) ++ goto err; ++ } ++ } ++ } ++ } ++ } ++ ++ if (r_is_at_infinity) { ++ if (!EC_POINT_set_to_infinity(group, r)) ++ goto err; ++ } else { ++ if (r_is_inverted) ++ if (!EC_POINT_invert(group, r, ctx)) ++ goto err; ++ } ++ ++ ret = 1; ++ ++ err: ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ if (tmp != NULL) ++ EC_POINT_free(tmp); ++ if (wsize != NULL) ++ OPENSSL_free(wsize); ++ if (wNAF_len != NULL) ++ OPENSSL_free(wNAF_len); ++ if (wNAF != NULL) { ++ signed char **w; ++ ++ for (w = wNAF; *w != NULL; w++) ++ OPENSSL_free(*w); ++ ++ OPENSSL_free(wNAF); ++ } ++ if (val != NULL) { ++ for (v = val; *v != NULL; v++) ++ EC_POINT_clear_free(*v); ++ ++ OPENSSL_free(val); ++ } ++ if (val_sub != NULL) { ++ OPENSSL_free(val_sub); ++ } ++ return ret; ++} ++ ++/*- ++ * ec_wNAF_precompute_mult() ++ * creates an EC_PRE_COMP object with preprecomputed multiples of the generator ++ * for use with wNAF splitting as implemented in ec_wNAF_mul(). ++ * ++ * 'pre_comp->points' is an array of multiples of the generator ++ * of the following form: ++ * points[0] = generator; ++ * points[1] = 3 * generator; ++ * ... ++ * points[2^(w-1)-1] = (2^(w-1)-1) * generator; ++ * points[2^(w-1)] = 2^blocksize * generator; ++ * points[2^(w-1)+1] = 3 * 2^blocksize * generator; ++ * ... ++ * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator ++ * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator ++ * ... ++ * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator ++ * points[2^(w-1)*numblocks] = NULL ++ */ ++int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) ++{ ++ const EC_POINT *generator; ++ EC_POINT *tmp_point = NULL, *base = NULL, **var; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *order; ++ size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; ++ EC_POINT **points = NULL; ++ EC_PRE_COMP *pre_comp; ++ int ret = 0; ++ ++ /* if there is an old EC_PRE_COMP object, throw it away */ ++ EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ++ ec_pre_comp_free, ec_pre_comp_clear_free); ++ ++ if ((pre_comp = ec_pre_comp_new(group)) == NULL) ++ return 0; ++ ++ generator = EC_GROUP_get0_generator(group); ++ if (generator == NULL) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); ++ goto err; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ goto err; ++ } ++ ++ BN_CTX_start(ctx); ++ order = BN_CTX_get(ctx); ++ if (order == NULL) ++ goto err; ++ ++ if (!EC_GROUP_get_order(group, order, ctx)) ++ goto err; ++ if (BN_is_zero(order)) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); ++ goto err; ++ } ++ ++ bits = BN_num_bits(order); ++ /* ++ * The following parameters mean we precompute (approximately) one point ++ * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other ++ * bit lengths, other parameter combinations might provide better ++ * efficiency. ++ */ ++ blocksize = 8; ++ w = 4; ++ if (EC_window_bits_for_scalar_size(bits) > w) { ++ /* let's not make the window too small ... */ ++ w = EC_window_bits_for_scalar_size(bits); ++ } ++ ++ numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks ++ * to use for wNAF ++ * splitting */ ++ ++ pre_points_per_block = (size_t)1 << (w - 1); ++ num = pre_points_per_block * numblocks; /* number of points to compute ++ * and store */ ++ ++ points = OPENSSL_malloc(sizeof(EC_POINT *) * (num + 1)); ++ if (!points) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ var = points; ++ var[num] = NULL; /* pivot */ ++ for (i = 0; i < num; i++) { ++ if ((var[i] = EC_POINT_new(group)) == NULL) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } ++ ++ if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (!EC_POINT_copy(base, generator)) ++ goto err; ++ ++ /* do the precomputation */ ++ for (i = 0; i < numblocks; i++) { ++ size_t j; ++ ++ if (!EC_POINT_dbl(group, tmp_point, base, ctx)) ++ goto err; ++ ++ if (!EC_POINT_copy(*var++, base)) ++ goto err; ++ ++ for (j = 1; j < pre_points_per_block; j++, var++) { ++ /* ++ * calculate odd multiples of the current base point ++ */ ++ if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) ++ goto err; ++ } ++ ++ if (i < numblocks - 1) { ++ /* ++ * get the next base (multiply current one by 2^blocksize) ++ */ ++ size_t k; ++ ++ if (blocksize <= 2) { ++ ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!EC_POINT_dbl(group, base, tmp_point, ctx)) ++ goto err; ++ for (k = 2; k < blocksize; k++) { ++ if (!EC_POINT_dbl(group, base, base, ctx)) ++ goto err; ++ } ++ } ++ } ++ ++ if (!EC_POINTs_make_affine(group, num, points, ctx)) ++ goto err; ++ ++ pre_comp->group = group; ++ pre_comp->blocksize = blocksize; ++ pre_comp->numblocks = numblocks; ++ pre_comp->w = w; ++ pre_comp->points = points; ++ points = NULL; ++ pre_comp->num = num; ++ ++ if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp, ++ ec_pre_comp_dup, ec_pre_comp_free, ++ ec_pre_comp_clear_free)) ++ goto err; ++ pre_comp = NULL; ++ ++ ret = 1; ++ err: ++ if (ctx != NULL) ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ if (pre_comp) ++ ec_pre_comp_free(pre_comp); ++ if (points) { ++ EC_POINT **p; ++ ++ for (p = points; *p != NULL; p++) ++ EC_POINT_free(*p); ++ OPENSSL_free(points); ++ } ++ if (tmp_point) ++ EC_POINT_free(tmp_point); ++ if (base) ++ EC_POINT_free(base); ++ return ret; ++} ++ ++int ec_wNAF_have_precompute_mult(const EC_GROUP *group) ++{ ++ if (EC_EX_DATA_get_data ++ (group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ++ ec_pre_comp_clear_free) != NULL) ++ return 1; ++ else ++ return 0; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_oct.c b/Cryptlib/OpenSSL/crypto/ec/ec_oct.c +new file mode 100644 +index 0000000..4ef58f6 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_oct.c +@@ -0,0 +1,163 @@ ++/* crypto/ec/ec_lib.c */ ++/* ++ * Originally written by Bodo Moeller for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Binary polynomial ECC support in OpenSSL originally developed by ++ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "ec_lcl.h" ++ ++int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, ++ EC_POINT *point, const BIGNUM *x, ++ int y_bit, BN_CTX *ctx) ++{ ++ if (group->meth->point_set_compressed_coordinates == 0 ++ && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { ++ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ++ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ++ EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { ++ if (group->meth->field_type == NID_X9_62_prime_field) ++ return ec_GFp_simple_set_compressed_coordinates(group, point, x, ++ y_bit, ctx); ++ else ++#ifdef OPENSSL_NO_EC2M ++ { ++ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ++ EC_R_GF2M_NOT_SUPPORTED); ++ return 0; ++ } ++#else ++ return ec_GF2m_simple_set_compressed_coordinates(group, point, x, ++ y_bit, ctx); ++#endif ++ } ++ return group->meth->point_set_compressed_coordinates(group, point, x, ++ y_bit, ctx); ++} ++ ++size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, ++ point_conversion_form_t form, unsigned char *buf, ++ size_t len, BN_CTX *ctx) ++{ ++ if (group->meth->point2oct == 0 ++ && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { ++ ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { ++ if (group->meth->field_type == NID_X9_62_prime_field) ++ return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); ++ else ++#ifdef OPENSSL_NO_EC2M ++ { ++ ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED); ++ return 0; ++ } ++#else ++ return ec_GF2m_simple_point2oct(group, point, ++ form, buf, len, ctx); ++#endif ++ } ++ ++ return group->meth->point2oct(group, point, form, buf, len, ctx); ++} ++ ++int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, ++ const unsigned char *buf, size_t len, BN_CTX *ctx) ++{ ++ if (group->meth->oct2point == 0 ++ && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { ++ ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ++ return 0; ++ } ++ if (group->meth != point->meth) { ++ ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); ++ return 0; ++ } ++ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { ++ if (group->meth->field_type == NID_X9_62_prime_field) ++ return ec_GFp_simple_oct2point(group, point, buf, len, ctx); ++ else ++#ifdef OPENSSL_NO_EC2M ++ { ++ ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED); ++ return 0; ++ } ++#else ++ return ec_GF2m_simple_oct2point(group, point, buf, len, ctx); ++#endif ++ } ++ return group->meth->oct2point(group, point, buf, len, ctx); ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_pmeth.c b/Cryptlib/OpenSSL/crypto/ec/ec_pmeth.c +new file mode 100644 +index 0000000..9844857 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_pmeth.c +@@ -0,0 +1,410 @@ ++/* ++ * Written by Dr Stephen N Henson (steve@openssl.org) 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 ++#include "cryptlib.h" ++#include ++#include ++#include ++#include "ec_lcl.h" ++#include ++#include ++#include "evp_locl.h" ++#include ++ ++/* EC pkey context structure */ ++ ++typedef struct { ++ /* Key and paramgen group */ ++ EC_GROUP *gen_group; ++ /* message digest */ ++ const EVP_MD *md; ++ /* Duplicate key if custom cofactor needed */ ++ EC_KEY *co_key; ++ /* Cofactor mode */ ++ signed char cofactor_mode; ++ /* KDF (if any) to use for ECDH */ ++ char kdf_type; ++ /* Message digest to use for key derivation */ ++ const EVP_MD *kdf_md; ++ /* User key material */ ++ unsigned char *kdf_ukm; ++ size_t kdf_ukmlen; ++ /* KDF output length */ ++ size_t kdf_outlen; ++} 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; ++ ++ dctx->cofactor_mode = -1; ++ dctx->co_key = NULL; ++ dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; ++ dctx->kdf_md = NULL; ++ dctx->kdf_outlen = 0; ++ dctx->kdf_ukm = NULL; ++ dctx->kdf_ukmlen = 0; ++ ++ ctx->data = dctx; ++ ++ return 1; ++} ++ ++static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) ++{ ++ EC_PKEY_CTX *dctx, *sctx; ++ if (!pkey_ec_init(dst)) ++ return 0; ++ sctx = src->data; ++ dctx = dst->data; ++ if (sctx->gen_group) { ++ dctx->gen_group = EC_GROUP_dup(sctx->gen_group); ++ if (!dctx->gen_group) ++ return 0; ++ } ++ dctx->md = sctx->md; ++ ++ if (sctx->co_key) { ++ dctx->co_key = EC_KEY_dup(sctx->co_key); ++ if (!dctx->co_key) ++ return 0; ++ } ++ dctx->kdf_type = sctx->kdf_type; ++ dctx->kdf_md = sctx->kdf_md; ++ dctx->kdf_outlen = sctx->kdf_outlen; ++ if (sctx->kdf_ukm) { ++ dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); ++ if (!dctx->kdf_ukm) ++ return 0; ++ } else ++ dctx->kdf_ukm = NULL; ++ dctx->kdf_ukmlen = sctx->kdf_ukmlen; ++ 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); ++ if (dctx->co_key) ++ EC_KEY_free(dctx->co_key); ++ if (dctx->kdf_ukm) ++ OPENSSL_free(dctx->kdf_ukm); ++ OPENSSL_free(dctx); ++ } ++} ++ ++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_EC_PARAM_ENC: ++ if (!dctx->gen_group) { ++ ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET); ++ return 0; ++ } ++ EC_GROUP_set_asn1_flag(dctx->gen_group, p1); ++ return 1; ++ ++#ifndef OPENSSL_NO_ECDH ++ case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: ++ if (p1 == -2) { ++ if (dctx->cofactor_mode != -1) ++ return dctx->cofactor_mode; ++ else { ++ EC_KEY *ec_key = ctx->pkey->pkey.ec; ++ return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : ++ 0; ++ } ++ } else if (p1 < -1 || p1 > 1) ++ return -2; ++ dctx->cofactor_mode = p1; ++ if (p1 != -1) { ++ EC_KEY *ec_key = ctx->pkey->pkey.ec; ++ if (!ec_key->group) ++ return -2; ++ /* If cofactor is 1 cofactor mode does nothing */ ++ if (BN_is_one(&ec_key->group->cofactor)) ++ return 1; ++ if (!dctx->co_key) { ++ dctx->co_key = EC_KEY_dup(ec_key); ++ if (!dctx->co_key) ++ return 0; ++ } ++ if (p1) ++ EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); ++ else ++ EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); ++ } else if (dctx->co_key) { ++ EC_KEY_free(dctx->co_key); ++ dctx->co_key = NULL; ++ } ++ return 1; ++#endif ++ ++ case EVP_PKEY_CTRL_EC_KDF_TYPE: ++ if (p1 == -2) ++ return dctx->kdf_type; ++ if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) ++ return -2; ++ dctx->kdf_type = p1; ++ return 1; ++ ++ case EVP_PKEY_CTRL_EC_KDF_MD: ++ dctx->kdf_md = p2; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_EC_KDF_MD: ++ *(const EVP_MD **)p2 = dctx->kdf_md; ++ return 1; ++ ++ case EVP_PKEY_CTRL_EC_KDF_OUTLEN: ++ if (p1 <= 0) ++ return -2; ++ dctx->kdf_outlen = (size_t)p1; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: ++ *(int *)p2 = dctx->kdf_outlen; ++ return 1; ++ ++ case EVP_PKEY_CTRL_EC_KDF_UKM: ++ if (dctx->kdf_ukm) ++ OPENSSL_free(dctx->kdf_ukm); ++ dctx->kdf_ukm = p2; ++ if (p2) ++ dctx->kdf_ukmlen = p1; ++ else ++ dctx->kdf_ukmlen = 0; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_EC_KDF_UKM: ++ *(unsigned char **)p2 = dctx->kdf_ukm; ++ return dctx->kdf_ukmlen; ++ ++ case EVP_PKEY_CTRL_MD: ++ if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha512 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sm3) { ++ ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); ++ return 0; ++ } ++ dctx->md = p2; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_MD: ++ *(const EVP_MD **)p2 = dctx->md; ++ return 1; ++ ++ case EVP_PKEY_CTRL_PEER_KEY: ++ /* Default behaviour is OK */ ++ case EVP_PKEY_CTRL_DIGESTINIT: ++ case EVP_PKEY_CTRL_PKCS7_SIGN: ++ case EVP_PKEY_CTRL_CMS_SIGN: ++ 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 = EC_curve_nist2nid(value); ++ if (nid == NID_undef) ++ 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); ++ } else if (!strcmp(type, "ec_param_enc")) { ++ int param_enc; ++ if (!strcmp(value, "explicit")) ++ param_enc = 0; ++ else if (!strcmp(value, "named_curve")) ++ param_enc = OPENSSL_EC_NAMED_CURVE; ++ else ++ return -2; ++ return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); ++ } else if (!strcmp(type, "ecdh_kdf_md")) { ++ const EVP_MD *md; ++ if (!(md = EVP_get_digestbyname(value))) { ++ ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); ++ return 0; ++ } ++ return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); ++ } else if (!strcmp(type, "ecdh_cofactor_mode")) { ++ int co_mode; ++ co_mode = atoi(value); ++ return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); ++ } ++ ++ 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; ++ EC_PKEY_CTX *dctx = ctx->data; ++ if (ctx->pkey == NULL && dctx->gen_group == 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); ++ if (ctx->pkey) { ++ /* Note: if error return, pkey is freed by parent routine */ ++ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) ++ return 0; ++ } else { ++ if (!EC_KEY_set_group(ec, dctx->gen_group)) ++ 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_copy, ++ pkey_ec_cleanup, ++ ++ 0, ++ pkey_ec_paramgen, ++ ++ 0, ++ pkey_ec_keygen, ++ ++ 0, ++ 0, // pkey_ec_sign, ++ ++ 0, ++ 0, // pkey_ec_verify, ++ ++ 0, 0, ++ ++ 0, 0, 0, 0, ++ ++ 0, 0, ++ ++ 0, 0, ++ ++ 0, ++#ifndef OPENSSL_NO_ECDH ++ pkey_ec_kdf_derive, ++#else ++ 0, ++#endif ++ ++ pkey_ec_ctrl, ++ pkey_ec_ctrl_str ++}; +diff --git a/Cryptlib/OpenSSL/crypto/ec/ec_print.c b/Cryptlib/OpenSSL/crypto/ec/ec_print.c +new file mode 100644 +index 0000000..96b294d +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ec_print.c +@@ -0,0 +1,179 @@ ++/* crypto/ec/ec_print.c */ ++/* ==================================================================== ++ * 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 ++#include "ec_lcl.h" ++ ++BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, ++ const EC_POINT *point, ++ point_conversion_form_t form, ++ BIGNUM *ret, BN_CTX *ctx) ++{ ++ size_t buf_len = 0; ++ unsigned char *buf; ++ ++ buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); ++ if (buf_len == 0) ++ return NULL; ++ ++ if ((buf = OPENSSL_malloc(buf_len)) == NULL) ++ return NULL; ++ ++ if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) { ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ ++ ret = BN_bin2bn(buf, buf_len, ret); ++ ++ OPENSSL_free(buf); ++ ++ return ret; ++} ++ ++EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, ++ const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) ++{ ++ size_t buf_len = 0; ++ unsigned char *buf; ++ EC_POINT *ret; ++ ++ if ((buf_len = BN_num_bytes(bn)) == 0) ++ return NULL; ++ buf = OPENSSL_malloc(buf_len); ++ if (buf == NULL) ++ return NULL; ++ ++ if (!BN_bn2bin(bn, buf)) { ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ ++ if (point == NULL) { ++ if ((ret = EC_POINT_new(group)) == NULL) { ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ } else ++ ret = point; ++ ++ if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) { ++ if (point == NULL) ++ EC_POINT_clear_free(ret); ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ ++ OPENSSL_free(buf); ++ return ret; ++} ++ ++static const char *HEX_DIGITS = "0123456789ABCDEF"; ++ ++/* the return value must be freed (using OPENSSL_free()) */ ++char *EC_POINT_point2hex(const EC_GROUP *group, ++ const EC_POINT *point, ++ point_conversion_form_t form, BN_CTX *ctx) ++{ ++ char *ret, *p; ++ size_t buf_len = 0, i; ++ unsigned char *buf, *pbuf; ++ ++ buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); ++ if (buf_len == 0) ++ return NULL; ++ ++ if ((buf = OPENSSL_malloc(buf_len)) == NULL) ++ return NULL; ++ ++ if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) { ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ ++ ret = (char *)OPENSSL_malloc(buf_len * 2 + 2); ++ if (ret == NULL) { ++ OPENSSL_free(buf); ++ return NULL; ++ } ++ p = ret; ++ pbuf = buf; ++ for (i = buf_len; i > 0; i--) { ++ int v = (int)*(pbuf++); ++ *(p++) = HEX_DIGITS[v >> 4]; ++ *(p++) = HEX_DIGITS[v & 0x0F]; ++ } ++ *p = '\0'; ++ ++ OPENSSL_free(buf); ++ ++ return ret; ++} ++ ++EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, ++ const char *buf, EC_POINT *point, BN_CTX *ctx) ++{ ++ EC_POINT *ret = NULL; ++ BIGNUM *tmp_bn = NULL; ++ ++ if (!BN_hex2bn(&tmp_bn, buf)) ++ return NULL; ++ ++ ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); ++ ++ BN_clear_free(tmp_bn); ++ ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/eck_prn.c b/Cryptlib/OpenSSL/crypto/ec/eck_prn.c +new file mode 100644 +index 0000000..a3bd1db +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/eck_prn.c +@@ -0,0 +1,330 @@ ++/* crypto/ec/eck_prn.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2005 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions originally developed by SUN MICROSYSTEMS, INC., and ++ * contributed to the OpenSSL project. ++ */ ++ ++#include ++#include "cryptlib.h" ++#include ++#include ++#include ++ ++int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) ++{ ++ EVP_PKEY *pk; ++ int ret; ++ pk = EVP_PKEY_new(); ++ if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) ++ return 0; ++ ret = EVP_PKEY_print_private(bp, pk, off, NULL); ++ EVP_PKEY_free(pk); ++ return ret; ++} ++ ++int ECParameters_print(BIO *bp, const EC_KEY *x) ++{ ++ EVP_PKEY *pk; ++ int ret; ++ pk = EVP_PKEY_new(); ++ if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) ++ return 0; ++ ret = EVP_PKEY_print_params(bp, pk, 4, NULL); ++ EVP_PKEY_free(pk); ++ return ret; ++} ++ ++static int print_bin(BIO *fp, const char *str, const unsigned char *num, ++ size_t len, int off); ++ ++int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) ++{ ++ unsigned char *buffer = NULL; ++ size_t buf_len = 0, i; ++ int ret = 0, reason = ERR_R_BIO_LIB; ++ BN_CTX *ctx = NULL; ++ const EC_POINT *point = NULL; ++ BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, ++ *order = NULL, *cofactor = NULL; ++ const unsigned char *seed; ++ size_t seed_len = 0; ++ ++ static const char *gen_compressed = "Generator (compressed):"; ++ static const char *gen_uncompressed = "Generator (uncompressed):"; ++ static const char *gen_hybrid = "Generator (hybrid):"; ++ ++ if (!x) { ++ reason = ERR_R_PASSED_NULL_PARAMETER; ++ goto err; ++ } ++ ++ ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ reason = ERR_R_MALLOC_FAILURE; ++ goto err; ++ } ++ ++ if (EC_GROUP_get_asn1_flag(x)) { ++ /* the curve parameter are given by an asn1 OID */ ++ int nid; ++ const char *nname; ++ ++ if (!BIO_indent(bp, off, 128)) ++ goto err; ++ ++ nid = EC_GROUP_get_curve_name(x); ++ if (nid == 0) ++ goto err; ++ ++ if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) ++ goto err; ++ if (BIO_printf(bp, "\n") <= 0) ++ goto err; ++ nname = EC_curve_nid2nist(nid); ++ if (nname) { ++ if (!BIO_indent(bp, off, 128)) ++ goto err; ++ if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0) ++ goto err; ++ } ++ } else { ++ /* explicit parameters */ ++ int is_char_two = 0; ++ point_conversion_form_t form; ++ int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); ++ ++ if (tmp_nid == NID_X9_62_characteristic_two_field) ++ is_char_two = 1; ++ ++ if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || ++ (b = BN_new()) == NULL || (order = BN_new()) == NULL || ++ (cofactor = BN_new()) == NULL) { ++ reason = ERR_R_MALLOC_FAILURE; ++ goto err; ++ } ++#ifndef OPENSSL_NO_EC2M ++ if (is_char_two) { ++ if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ } else /* prime field */ ++#endif ++ { ++ if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ } ++ ++ if ((point = EC_GROUP_get0_generator(x)) == NULL) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ if (!EC_GROUP_get_order(x, order, NULL) || ++ !EC_GROUP_get_cofactor(x, cofactor, NULL)) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ ++ form = EC_GROUP_get_point_conversion_form(x); ++ ++ if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { ++ reason = ERR_R_EC_LIB; ++ goto err; ++ } ++ ++ buf_len = (size_t)BN_num_bytes(p); ++ if (buf_len < (i = (size_t)BN_num_bytes(a))) ++ buf_len = i; ++ if (buf_len < (i = (size_t)BN_num_bytes(b))) ++ buf_len = i; ++ if (buf_len < (i = (size_t)BN_num_bytes(gen))) ++ buf_len = i; ++ if (buf_len < (i = (size_t)BN_num_bytes(order))) ++ buf_len = i; ++ if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) ++ buf_len = i; ++ ++ if ((seed = EC_GROUP_get0_seed(x)) != NULL) ++ seed_len = EC_GROUP_get_seed_len(x); ++ ++ buf_len += 10; ++ if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { ++ reason = ERR_R_MALLOC_FAILURE; ++ goto err; ++ } ++ ++ if (!BIO_indent(bp, off, 128)) ++ goto err; ++ ++ /* print the 'short name' of the field type */ ++ if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) ++ <= 0) ++ goto err; ++ ++ if (is_char_two) { ++ /* print the 'short name' of the base type OID */ ++ int basis_type = EC_GROUP_get_basis_type(x); ++ if (basis_type == 0) ++ goto err; ++ ++ if (!BIO_indent(bp, off, 128)) ++ goto err; ++ ++ if (BIO_printf(bp, "Basis Type: %s\n", ++ OBJ_nid2sn(basis_type)) <= 0) ++ goto err; ++ ++ /* print the polynomial */ ++ if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, ++ off)) ++ goto err; ++ } else { ++ if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off)) ++ goto err; ++ } ++ if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) ++ goto err; ++ if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) ++ goto err; ++ if (form == POINT_CONVERSION_COMPRESSED) { ++ if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, ++ buffer, off)) ++ goto err; ++ } else if (form == POINT_CONVERSION_UNCOMPRESSED) { ++ if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, ++ buffer, off)) ++ goto err; ++ } else { /* form == POINT_CONVERSION_HYBRID */ ++ ++ if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, ++ buffer, off)) ++ goto err; ++ } ++ if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, ++ buffer, off)) ++ goto err; ++ if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, ++ buffer, off)) ++ goto err; ++ if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) ++ goto err; ++ } ++ ret = 1; ++ err: ++ if (!ret) ++ ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); ++ if (p) ++ BN_free(p); ++ if (a) ++ BN_free(a); ++ if (b) ++ BN_free(b); ++ if (gen) ++ BN_free(gen); ++ if (order) ++ BN_free(order); ++ if (cofactor) ++ BN_free(cofactor); ++ if (ctx) ++ BN_CTX_free(ctx); ++ if (buffer != NULL) ++ OPENSSL_free(buffer); ++ return (ret); ++} ++ ++static int print_bin(BIO *fp, const char *name, const unsigned char *buf, ++ size_t len, int off) ++{ ++ size_t i; ++ char str[128]; ++ ++ if (buf == NULL) ++ return 1; ++ if (off > 0) { ++ if (off > 128) ++ off = 128; ++ memset(str, ' ', off); ++ if (BIO_write(fp, str, off) <= 0) ++ return 0; ++ } else { ++ off = 0; ++ } ++ ++ if (BIO_printf(fp, "%s", name) <= 0) ++ return 0; ++ ++ for (i = 0; i < len; i++) { ++ if ((i % 15) == 0) { ++ str[0] = '\n'; ++ memset(&(str[1]), ' ', off + 4); ++ if (BIO_write(fp, str, off + 1 + 4) <= 0) ++ return 0; ++ } ++ if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= ++ 0) ++ return 0; ++ } ++ if (BIO_write(fp, "\n", 1) <= 0) ++ return 0; ++ ++ return 1; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ecp_mont.c b/Cryptlib/OpenSSL/crypto/ec/ecp_mont.c +new file mode 100644 +index 0000000..b2de7fa +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ecp_mont.c +@@ -0,0 +1,308 @@ ++/* crypto/ec/ecp_mont.c */ ++/* ++ * Originally written by Bodo Moeller for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2001 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions of this software developed by SUN MICROSYSTEMS, INC., ++ * and contributed to the OpenSSL project. ++ */ ++ ++#include ++ ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++#include "ec_lcl.h" ++ ++const EC_METHOD *EC_GFp_mont_method(void) ++{ ++ static const EC_METHOD ret = { ++ EC_FLAGS_DEFAULT_OCT, ++ NID_X9_62_prime_field, ++ ec_GFp_mont_group_init, ++ ec_GFp_mont_group_finish, ++ ec_GFp_mont_group_clear_finish, ++ ec_GFp_mont_group_copy, ++ ec_GFp_mont_group_set_curve, ++ ec_GFp_simple_group_get_curve, ++ ec_GFp_simple_group_get_degree, ++ ec_GFp_simple_group_check_discriminant, ++ ec_GFp_simple_point_init, ++ ec_GFp_simple_point_finish, ++ ec_GFp_simple_point_clear_finish, ++ ec_GFp_simple_point_copy, ++ ec_GFp_simple_point_set_to_infinity, ++ ec_GFp_simple_set_Jprojective_coordinates_GFp, ++ ec_GFp_simple_get_Jprojective_coordinates_GFp, ++ ec_GFp_simple_point_set_affine_coordinates, ++ ec_GFp_simple_point_get_affine_coordinates, ++ 0, 0, 0, ++ ec_GFp_simple_add, ++ ec_GFp_simple_dbl, ++ ec_GFp_simple_invert, ++ ec_GFp_simple_is_at_infinity, ++ ec_GFp_simple_is_on_curve, ++ ec_GFp_simple_cmp, ++ ec_GFp_simple_make_affine, ++ ec_GFp_simple_points_make_affine, ++ 0 /* mul */ , ++ 0 /* precompute_mult */ , ++ 0 /* have_precompute_mult */ , ++ ec_GFp_mont_field_mul, ++ ec_GFp_mont_field_sqr, ++ 0 /* field_div */ , ++ ec_GFp_mont_field_encode, ++ ec_GFp_mont_field_decode, ++ ec_GFp_mont_field_set_to_one ++ }; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return fips_ec_gfp_mont_method(); ++#endif ++ ++ return &ret; ++} ++ ++int ec_GFp_mont_group_init(EC_GROUP *group) ++{ ++ int ok; ++ ++ ok = ec_GFp_simple_group_init(group); ++ group->field_data1 = NULL; ++ group->field_data2 = NULL; ++ return ok; ++} ++ ++void ec_GFp_mont_group_finish(EC_GROUP *group) ++{ ++ if (group->field_data1 != NULL) { ++ BN_MONT_CTX_free(group->field_data1); ++ group->field_data1 = NULL; ++ } ++ if (group->field_data2 != NULL) { ++ BN_free(group->field_data2); ++ group->field_data2 = NULL; ++ } ++ ec_GFp_simple_group_finish(group); ++} ++ ++void ec_GFp_mont_group_clear_finish(EC_GROUP *group) ++{ ++ if (group->field_data1 != NULL) { ++ BN_MONT_CTX_free(group->field_data1); ++ group->field_data1 = NULL; ++ } ++ if (group->field_data2 != NULL) { ++ BN_clear_free(group->field_data2); ++ group->field_data2 = NULL; ++ } ++ ec_GFp_simple_group_clear_finish(group); ++} ++ ++int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) ++{ ++ if (dest->field_data1 != NULL) { ++ BN_MONT_CTX_free(dest->field_data1); ++ dest->field_data1 = NULL; ++ } ++ if (dest->field_data2 != NULL) { ++ BN_clear_free(dest->field_data2); ++ dest->field_data2 = NULL; ++ } ++ ++ if (!ec_GFp_simple_group_copy(dest, src)) ++ return 0; ++ ++ if (src->field_data1 != NULL) { ++ dest->field_data1 = BN_MONT_CTX_new(); ++ if (dest->field_data1 == NULL) ++ return 0; ++ if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) ++ goto err; ++ } ++ if (src->field_data2 != NULL) { ++ dest->field_data2 = BN_dup(src->field_data2); ++ if (dest->field_data2 == NULL) ++ goto err; ++ } ++ ++ return 1; ++ ++ err: ++ if (dest->field_data1 != NULL) { ++ BN_MONT_CTX_free(dest->field_data1); ++ dest->field_data1 = NULL; ++ } ++ return 0; ++} ++ ++int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, ++ const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ BN_MONT_CTX *mont = NULL; ++ BIGNUM *one = NULL; ++ int ret = 0; ++ ++ if (group->field_data1 != NULL) { ++ BN_MONT_CTX_free(group->field_data1); ++ group->field_data1 = NULL; ++ } ++ if (group->field_data2 != NULL) { ++ BN_free(group->field_data2); ++ group->field_data2 = NULL; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ mont = BN_MONT_CTX_new(); ++ if (mont == NULL) ++ goto err; ++ if (!BN_MONT_CTX_set(mont, p, ctx)) { ++ ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); ++ goto err; ++ } ++ one = BN_new(); ++ if (one == NULL) ++ goto err; ++ if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) ++ goto err; ++ ++ group->field_data1 = mont; ++ mont = NULL; ++ group->field_data2 = one; ++ one = NULL; ++ ++ ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); ++ ++ if (!ret) { ++ BN_MONT_CTX_free(group->field_data1); ++ group->field_data1 = NULL; ++ BN_free(group->field_data2); ++ group->field_data2 = NULL; ++ } ++ ++ err: ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ if (mont != NULL) ++ BN_MONT_CTX_free(mont); ++ return ret; ++} ++ ++int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ if (group->field_data1 == NULL) { ++ ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); ++ return 0; ++ } ++ ++ return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); ++} ++ ++int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *ctx) ++{ ++ if (group->field_data1 == NULL) { ++ ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); ++ return 0; ++ } ++ ++ return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); ++} ++ ++int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, ++ const BIGNUM *a, BN_CTX *ctx) ++{ ++ if (group->field_data1 == NULL) { ++ ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); ++ return 0; ++ } ++ ++ return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); ++} ++ ++int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, ++ const BIGNUM *a, BN_CTX *ctx) ++{ ++ if (group->field_data1 == NULL) { ++ ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); ++ return 0; ++ } ++ ++ return BN_from_montgomery(r, a, group->field_data1, ctx); ++} ++ ++int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, ++ BN_CTX *ctx) ++{ ++ if (group->field_data2 == NULL) { ++ ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); ++ return 0; ++ } ++ ++ if (!BN_copy(r, group->field_data2)) ++ return 0; ++ return 1; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ecp_nist.c b/Cryptlib/OpenSSL/crypto/ec/ecp_nist.c +new file mode 100644 +index 0000000..3944e24 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ecp_nist.c +@@ -0,0 +1,220 @@ ++/* crypto/ec/ecp_nist.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions of this software developed by SUN MICROSYSTEMS, INC., ++ * and contributed to the OpenSSL project. ++ */ ++ ++#include ++ ++#include ++#include ++#include "ec_lcl.h" ++ ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++const EC_METHOD *EC_GFp_nist_method(void) ++{ ++ static const EC_METHOD ret = { ++ EC_FLAGS_DEFAULT_OCT, ++ NID_X9_62_prime_field, ++ ec_GFp_simple_group_init, ++ ec_GFp_simple_group_finish, ++ ec_GFp_simple_group_clear_finish, ++ ec_GFp_nist_group_copy, ++ ec_GFp_nist_group_set_curve, ++ ec_GFp_simple_group_get_curve, ++ ec_GFp_simple_group_get_degree, ++ ec_GFp_simple_group_check_discriminant, ++ ec_GFp_simple_point_init, ++ ec_GFp_simple_point_finish, ++ ec_GFp_simple_point_clear_finish, ++ ec_GFp_simple_point_copy, ++ ec_GFp_simple_point_set_to_infinity, ++ ec_GFp_simple_set_Jprojective_coordinates_GFp, ++ ec_GFp_simple_get_Jprojective_coordinates_GFp, ++ ec_GFp_simple_point_set_affine_coordinates, ++ ec_GFp_simple_point_get_affine_coordinates, ++ 0, 0, 0, ++ ec_GFp_simple_add, ++ ec_GFp_simple_dbl, ++ ec_GFp_simple_invert, ++ ec_GFp_simple_is_at_infinity, ++ ec_GFp_simple_is_on_curve, ++ ec_GFp_simple_cmp, ++ ec_GFp_simple_make_affine, ++ ec_GFp_simple_points_make_affine, ++ 0 /* mul */ , ++ 0 /* precompute_mult */ , ++ 0 /* have_precompute_mult */ , ++ ec_GFp_nist_field_mul, ++ ec_GFp_nist_field_sqr, ++ 0 /* field_div */ , ++ 0 /* field_encode */ , ++ 0 /* field_decode */ , ++ 0 /* field_set_to_one */ ++ }; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return fips_ec_gfp_nist_method(); ++#endif ++ ++ return &ret; ++} ++ ++int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) ++{ ++ dest->field_mod_func = src->field_mod_func; ++ ++ return ec_GFp_simple_group_copy(dest, src); ++} ++ ++int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, ++ const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *tmp_bn; ++ ++ if (ctx == NULL) ++ if ((ctx = new_ctx = BN_CTX_new()) == NULL) ++ return 0; ++ ++ BN_CTX_start(ctx); ++ if ((tmp_bn = BN_CTX_get(ctx)) == NULL) ++ goto err; ++ ++ if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0) ++ group->field_mod_func = BN_nist_mod_192; ++ else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0) ++ group->field_mod_func = BN_nist_mod_224; ++ else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0) ++ group->field_mod_func = BN_nist_mod_256; ++ else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0) ++ group->field_mod_func = BN_nist_mod_384; ++ else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) ++ group->field_mod_func = BN_nist_mod_521; ++ else { ++ ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME); ++ goto err; ++ } ++ ++ ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BN_CTX *ctx_new = NULL; ++ ++ if (!group || !r || !a || !b) { ++ ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER); ++ goto err; ++ } ++ if (!ctx) ++ if ((ctx_new = ctx = BN_CTX_new()) == NULL) ++ goto err; ++ ++ if (!BN_mul(r, a, b, ctx)) ++ goto err; ++ if (!group->field_mod_func(r, r, &group->field, ctx)) ++ goto err; ++ ++ ret = 1; ++ err: ++ if (ctx_new) ++ BN_CTX_free(ctx_new); ++ return ret; ++} ++ ++int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *ctx) ++{ ++ int ret = 0; ++ BN_CTX *ctx_new = NULL; ++ ++ if (!group || !r || !a) { ++ ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); ++ goto err; ++ } ++ if (!ctx) ++ if ((ctx_new = ctx = BN_CTX_new()) == NULL) ++ goto err; ++ ++ if (!BN_sqr(r, a, ctx)) ++ goto err; ++ if (!group->field_mod_func(r, r, &group->field, ctx)) ++ goto err; ++ ++ ret = 1; ++ err: ++ if (ctx_new) ++ BN_CTX_free(ctx_new); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ecp_oct.c b/Cryptlib/OpenSSL/crypto/ec/ecp_oct.c +new file mode 100644 +index 0000000..1bc3f39 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ecp_oct.c +@@ -0,0 +1,428 @@ ++/* crypto/ec/ecp_oct.c */ ++/* ++ * Includes code written by Lenka Fibikova ++ * for the OpenSSL project. Includes code written by Bodo Moeller 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions of this software developed by SUN MICROSYSTEMS, INC., ++ * and contributed to the OpenSSL project. ++ */ ++ ++#include ++#include ++ ++#include "ec_lcl.h" ++ ++int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, ++ EC_POINT *point, ++ const BIGNUM *x_, int y_bit, ++ BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *tmp1, *tmp2, *x, *y; ++ int ret = 0; ++ ++ /* clear error queue */ ++ ERR_clear_error(); ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ y_bit = (y_bit != 0); ++ ++ BN_CTX_start(ctx); ++ tmp1 = BN_CTX_get(ctx); ++ tmp2 = BN_CTX_get(ctx); ++ x = BN_CTX_get(ctx); ++ y = BN_CTX_get(ctx); ++ if (y == NULL) ++ goto err; ++ ++ /*- ++ * Recover y. We have a Weierstrass equation ++ * y^2 = x^3 + a*x + b, ++ * so y is one of the square roots of x^3 + a*x + b. ++ */ ++ ++ /* tmp1 := x^3 */ ++ if (!BN_nnmod(x, x_, &group->field, ctx)) ++ goto err; ++ if (group->meth->field_decode == 0) { ++ /* field_{sqr,mul} work on standard representation */ ++ if (!group->meth->field_sqr(group, tmp2, x_, ctx)) ++ goto err; ++ if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) ++ goto err; ++ } else { ++ if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) ++ goto err; ++ if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) ++ goto err; ++ } ++ ++ /* tmp1 := tmp1 + a*x */ ++ if (group->a_is_minus3) { ++ if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) ++ goto err; ++ if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) ++ goto err; ++ if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) ++ goto err; ++ } else { ++ if (group->meth->field_decode) { ++ if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) ++ goto err; ++ if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) ++ goto err; ++ } else { ++ /* field_mul works on standard representation */ ++ if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) ++ goto err; ++ } ++ ++ if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) ++ goto err; ++ } ++ ++ /* tmp1 := tmp1 + b */ ++ if (group->meth->field_decode) { ++ if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) ++ goto err; ++ if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) ++ goto err; ++ } else { ++ if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) ++ goto err; ++ } ++ ++ if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { ++ unsigned long err = ERR_peek_last_error(); ++ ++ if (ERR_GET_LIB(err) == ERR_LIB_BN ++ && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { ++ ERR_clear_error(); ++ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ++ EC_R_INVALID_COMPRESSED_POINT); ++ } else ++ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ++ ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (y_bit != BN_is_odd(y)) { ++ if (BN_is_zero(y)) { ++ int kron; ++ ++ kron = BN_kronecker(x, &group->field, ctx); ++ if (kron == -2) ++ goto err; ++ ++ if (kron == 1) ++ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ++ EC_R_INVALID_COMPRESSION_BIT); ++ else ++ /* ++ * BN_mod_sqrt() should have cought this error (not a square) ++ */ ++ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ++ EC_R_INVALID_COMPRESSED_POINT); ++ goto err; ++ } ++ if (!BN_usub(y, &group->field, y)) ++ goto err; ++ } ++ if (y_bit != BN_is_odd(y)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) ++ goto err; ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, ++ point_conversion_form_t form, ++ unsigned char *buf, size_t len, BN_CTX *ctx) ++{ ++ size_t ret; ++ BN_CTX *new_ctx = NULL; ++ int used_ctx = 0; ++ BIGNUM *x, *y; ++ size_t field_len, i, skip; ++ ++ if ((form != POINT_CONVERSION_COMPRESSED) ++ && (form != POINT_CONVERSION_UNCOMPRESSED) ++ && (form != POINT_CONVERSION_HYBRID)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); ++ goto err; ++ } ++ ++ if (EC_POINT_is_at_infinity(group, point)) { ++ /* encodes to a single 0 octet */ ++ if (buf != NULL) { ++ if (len < 1) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); ++ return 0; ++ } ++ buf[0] = 0; ++ } ++ return 1; ++ } ++ ++ /* ret := required output buffer length */ ++ field_len = BN_num_bytes(&group->field); ++ ret = ++ (form == ++ POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; ++ ++ /* if 'buf' is NULL, just return required length */ ++ if (buf != NULL) { ++ if (len < ret) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); ++ goto err; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ used_ctx = 1; ++ x = BN_CTX_get(ctx); ++ y = BN_CTX_get(ctx); ++ if (y == NULL) ++ goto err; ++ ++ if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) ++ goto err; ++ ++ if ((form == POINT_CONVERSION_COMPRESSED ++ || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) ++ buf[0] = form + 1; ++ else ++ buf[0] = form; ++ ++ i = 1; ++ ++ skip = field_len - BN_num_bytes(x); ++ if (skip > field_len) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ while (skip > 0) { ++ buf[i++] = 0; ++ skip--; ++ } ++ skip = BN_bn2bin(x, buf + i); ++ i += skip; ++ if (i != 1 + field_len) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (form == POINT_CONVERSION_UNCOMPRESSED ++ || form == POINT_CONVERSION_HYBRID) { ++ skip = field_len - BN_num_bytes(y); ++ if (skip > field_len) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ while (skip > 0) { ++ buf[i++] = 0; ++ skip--; ++ } ++ skip = BN_bn2bin(y, buf + i); ++ i += skip; ++ } ++ ++ if (i != ret) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ } ++ ++ if (used_ctx) ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++ ++ err: ++ if (used_ctx) ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return 0; ++} ++ ++int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, ++ const unsigned char *buf, size_t len, BN_CTX *ctx) ++{ ++ point_conversion_form_t form; ++ int y_bit; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *x, *y; ++ size_t field_len, enc_len; ++ int ret = 0; ++ ++ if (len == 0) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); ++ return 0; ++ } ++ form = buf[0]; ++ y_bit = form & 1; ++ form = form & ~1U; ++ if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) ++ && (form != POINT_CONVERSION_UNCOMPRESSED) ++ && (form != POINT_CONVERSION_HYBRID)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ return 0; ++ } ++ if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ return 0; ++ } ++ ++ if (form == 0) { ++ if (len != 1) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ return 0; ++ } ++ ++ return EC_POINT_set_to_infinity(group, point); ++ } ++ ++ field_len = BN_num_bytes(&group->field); ++ enc_len = ++ (form == ++ POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; ++ ++ if (len != enc_len) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ return 0; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ x = BN_CTX_get(ctx); ++ y = BN_CTX_get(ctx); ++ if (y == NULL) ++ goto err; ++ ++ if (!BN_bin2bn(buf + 1, field_len, x)) ++ goto err; ++ if (BN_ucmp(x, &group->field) >= 0) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ goto err; ++ } ++ ++ if (form == POINT_CONVERSION_COMPRESSED) { ++ if (!EC_POINT_set_compressed_coordinates_GFp ++ (group, point, x, y_bit, ctx)) ++ goto err; ++ } else { ++ if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) ++ goto err; ++ if (BN_ucmp(y, &group->field) >= 0) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ goto err; ++ } ++ if (form == POINT_CONVERSION_HYBRID) { ++ if (y_bit != BN_is_odd(y)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); ++ goto err; ++ } ++ } ++ ++ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) ++ goto err; ++ } ++ ++ /* test required by X9.62 */ ++ if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { ++ ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); ++ goto err; ++ } ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ec/ecp_smpl.c b/Cryptlib/OpenSSL/crypto/ec/ecp_smpl.c +new file mode 100644 +index 0000000..2b84821 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ec/ecp_smpl.c +@@ -0,0 +1,1418 @@ ++/* crypto/ec/ecp_smpl.c */ ++/* ++ * Includes code written by Lenka Fibikova ++ * for the OpenSSL project. Includes code written by Bodo Moeller 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). ++ * ++ */ ++/* ==================================================================== ++ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. ++ * Portions of this software developed by SUN MICROSYSTEMS, INC., ++ * and contributed to the OpenSSL project. ++ */ ++ ++#include ++#include ++ ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++#include "ec_lcl.h" ++ ++const EC_METHOD *EC_GFp_simple_method(void) ++{ ++ static const EC_METHOD ret = { ++ EC_FLAGS_DEFAULT_OCT, ++ NID_X9_62_prime_field, ++ ec_GFp_simple_group_init, ++ ec_GFp_simple_group_finish, ++ ec_GFp_simple_group_clear_finish, ++ ec_GFp_simple_group_copy, ++ ec_GFp_simple_group_set_curve, ++ ec_GFp_simple_group_get_curve, ++ ec_GFp_simple_group_get_degree, ++ ec_GFp_simple_group_check_discriminant, ++ ec_GFp_simple_point_init, ++ ec_GFp_simple_point_finish, ++ ec_GFp_simple_point_clear_finish, ++ ec_GFp_simple_point_copy, ++ ec_GFp_simple_point_set_to_infinity, ++ ec_GFp_simple_set_Jprojective_coordinates_GFp, ++ ec_GFp_simple_get_Jprojective_coordinates_GFp, ++ ec_GFp_simple_point_set_affine_coordinates, ++ ec_GFp_simple_point_get_affine_coordinates, ++ 0, 0, 0, ++ ec_GFp_simple_add, ++ ec_GFp_simple_dbl, ++ ec_GFp_simple_invert, ++ ec_GFp_simple_is_at_infinity, ++ ec_GFp_simple_is_on_curve, ++ ec_GFp_simple_cmp, ++ ec_GFp_simple_make_affine, ++ ec_GFp_simple_points_make_affine, ++ 0 /* mul */ , ++ 0 /* precompute_mult */ , ++ 0 /* have_precompute_mult */ , ++ ec_GFp_simple_field_mul, ++ ec_GFp_simple_field_sqr, ++ 0 /* field_div */ , ++ 0 /* field_encode */ , ++ 0 /* field_decode */ , ++ 0 /* field_set_to_one */ ++ }; ++ ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return fips_ec_gfp_simple_method(); ++#endif ++ ++ return &ret; ++} ++ ++/* ++ * Most method functions in this file are designed to work with ++ * non-trivial representations of field elements if necessary ++ * (see ecp_mont.c): while standard modular addition and subtraction ++ * are used, the field_mul and field_sqr methods will be used for ++ * multiplication, and field_encode and field_decode (if defined) ++ * will be used for converting between representations. ++ * ++ * Functions ec_GFp_simple_points_make_affine() and ++ * ec_GFp_simple_point_get_affine_coordinates() specifically assume ++ * that if a non-trivial representation is used, it is a Montgomery ++ * representation (i.e. 'encoding' means multiplying by some factor R). ++ */ ++ ++int ec_GFp_simple_group_init(EC_GROUP *group) ++{ ++ BN_init(&group->field); ++ BN_init(&group->a); ++ BN_init(&group->b); ++ group->a_is_minus3 = 0; ++ return 1; ++} ++ ++void ec_GFp_simple_group_finish(EC_GROUP *group) ++{ ++ BN_free(&group->field); ++ BN_free(&group->a); ++ BN_free(&group->b); ++} ++ ++void ec_GFp_simple_group_clear_finish(EC_GROUP *group) ++{ ++ BN_clear_free(&group->field); ++ BN_clear_free(&group->a); ++ BN_clear_free(&group->b); ++} ++ ++int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) ++{ ++ if (!BN_copy(&dest->field, &src->field)) ++ return 0; ++ if (!BN_copy(&dest->a, &src->a)) ++ return 0; ++ if (!BN_copy(&dest->b, &src->b)) ++ return 0; ++ ++ dest->a_is_minus3 = src->a_is_minus3; ++ ++ return 1; ++} ++ ++int ec_GFp_simple_group_set_curve(EC_GROUP *group, ++ const BIGNUM *p, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *tmp_a; ++ ++ /* p must be a prime > 3 */ ++ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); ++ return 0; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ tmp_a = BN_CTX_get(ctx); ++ if (tmp_a == NULL) ++ goto err; ++ ++ /* group->field */ ++ if (!BN_copy(&group->field, p)) ++ goto err; ++ BN_set_negative(&group->field, 0); ++ ++ /* group->a */ ++ if (!BN_nnmod(tmp_a, a, p, ctx)) ++ goto err; ++ if (group->meth->field_encode) { ++ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) ++ goto err; ++ } else if (!BN_copy(&group->a, tmp_a)) ++ goto err; ++ ++ /* group->b */ ++ if (!BN_nnmod(&group->b, b, p, ctx)) ++ goto err; ++ if (group->meth->field_encode) ++ if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) ++ goto err; ++ ++ /* group->a_is_minus3 */ ++ if (!BN_add_word(tmp_a, 3)) ++ goto err; ++ group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, ++ BIGNUM *b, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BN_CTX *new_ctx = NULL; ++ ++ if (p != NULL) { ++ if (!BN_copy(p, &group->field)) ++ return 0; ++ } ++ ++ if (a != NULL || b != NULL) { ++ if (group->meth->field_decode) { ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ if (a != NULL) { ++ if (!group->meth->field_decode(group, a, &group->a, ctx)) ++ goto err; ++ } ++ if (b != NULL) { ++ if (!group->meth->field_decode(group, b, &group->b, ctx)) ++ goto err; ++ } ++ } else { ++ if (a != NULL) { ++ if (!BN_copy(a, &group->a)) ++ goto err; ++ } ++ if (b != NULL) { ++ if (!BN_copy(b, &group->b)) ++ goto err; ++ } ++ } ++ } ++ ++ ret = 1; ++ ++ err: ++ if (new_ctx) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_group_get_degree(const EC_GROUP *group) ++{ ++ return BN_num_bits(&group->field); ++} ++ ++int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) ++{ ++ int ret = 0; ++ BIGNUM *a, *b, *order, *tmp_1, *tmp_2; ++ const BIGNUM *p = &group->field; ++ BN_CTX *new_ctx = NULL; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ++ ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } ++ BN_CTX_start(ctx); ++ a = BN_CTX_get(ctx); ++ b = BN_CTX_get(ctx); ++ tmp_1 = BN_CTX_get(ctx); ++ tmp_2 = BN_CTX_get(ctx); ++ order = BN_CTX_get(ctx); ++ if (order == NULL) ++ goto err; ++ ++ if (group->meth->field_decode) { ++ if (!group->meth->field_decode(group, a, &group->a, ctx)) ++ goto err; ++ if (!group->meth->field_decode(group, b, &group->b, ctx)) ++ goto err; ++ } else { ++ if (!BN_copy(a, &group->a)) ++ goto err; ++ if (!BN_copy(b, &group->b)) ++ goto err; ++ } ++ ++ /*- ++ * check the discriminant: ++ * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) ++ * 0 =< a, b < p ++ */ ++ if (BN_is_zero(a)) { ++ if (BN_is_zero(b)) ++ goto err; ++ } else if (!BN_is_zero(b)) { ++ if (!BN_mod_sqr(tmp_1, a, p, ctx)) ++ goto err; ++ if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) ++ goto err; ++ if (!BN_lshift(tmp_1, tmp_2, 2)) ++ goto err; ++ /* tmp_1 = 4*a^3 */ ++ ++ if (!BN_mod_sqr(tmp_2, b, p, ctx)) ++ goto err; ++ if (!BN_mul_word(tmp_2, 27)) ++ goto err; ++ /* tmp_2 = 27*b^2 */ ++ ++ if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) ++ goto err; ++ if (BN_is_zero(a)) ++ goto err; ++ } ++ ret = 1; ++ ++ err: ++ if (ctx != NULL) ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_point_init(EC_POINT *point) ++{ ++ BN_init(&point->X); ++ BN_init(&point->Y); ++ BN_init(&point->Z); ++ point->Z_is_one = 0; ++ ++ return 1; ++} ++ ++void ec_GFp_simple_point_finish(EC_POINT *point) ++{ ++ BN_free(&point->X); ++ BN_free(&point->Y); ++ BN_free(&point->Z); ++} ++ ++void ec_GFp_simple_point_clear_finish(EC_POINT *point) ++{ ++ BN_clear_free(&point->X); ++ BN_clear_free(&point->Y); ++ BN_clear_free(&point->Z); ++ point->Z_is_one = 0; ++} ++ ++int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) ++{ ++ if (!BN_copy(&dest->X, &src->X)) ++ return 0; ++ if (!BN_copy(&dest->Y, &src->Y)) ++ return 0; ++ if (!BN_copy(&dest->Z, &src->Z)) ++ return 0; ++ dest->Z_is_one = src->Z_is_one; ++ ++ return 1; ++} ++ ++int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, ++ EC_POINT *point) ++{ ++ point->Z_is_one = 0; ++ BN_zero(&point->Z); ++ return 1; ++} ++ ++int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, ++ EC_POINT *point, ++ const BIGNUM *x, ++ const BIGNUM *y, ++ const BIGNUM *z, ++ BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ int ret = 0; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ if (x != NULL) { ++ if (!BN_nnmod(&point->X, x, &group->field, ctx)) ++ goto err; ++ if (group->meth->field_encode) { ++ if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) ++ goto err; ++ } ++ } ++ ++ if (y != NULL) { ++ if (!BN_nnmod(&point->Y, y, &group->field, ctx)) ++ goto err; ++ if (group->meth->field_encode) { ++ if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) ++ goto err; ++ } ++ } ++ ++ if (z != NULL) { ++ int Z_is_one; ++ ++ if (!BN_nnmod(&point->Z, z, &group->field, ctx)) ++ goto err; ++ Z_is_one = BN_is_one(&point->Z); ++ if (group->meth->field_encode) { ++ if (Z_is_one && (group->meth->field_set_to_one != 0)) { ++ if (!group->meth->field_set_to_one(group, &point->Z, ctx)) ++ goto err; ++ } else { ++ if (!group-> ++ meth->field_encode(group, &point->Z, &point->Z, ctx)) ++ goto err; ++ } ++ } ++ point->Z_is_one = Z_is_one; ++ } ++ ++ ret = 1; ++ ++ err: ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, ++ const EC_POINT *point, ++ BIGNUM *x, BIGNUM *y, ++ BIGNUM *z, BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ int ret = 0; ++ ++ if (group->meth->field_decode != 0) { ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ if (x != NULL) { ++ if (!group->meth->field_decode(group, x, &point->X, ctx)) ++ goto err; ++ } ++ if (y != NULL) { ++ if (!group->meth->field_decode(group, y, &point->Y, ctx)) ++ goto err; ++ } ++ if (z != NULL) { ++ if (!group->meth->field_decode(group, z, &point->Z, ctx)) ++ goto err; ++ } ++ } else { ++ if (x != NULL) { ++ if (!BN_copy(x, &point->X)) ++ goto err; ++ } ++ if (y != NULL) { ++ if (!BN_copy(y, &point->Y)) ++ goto err; ++ } ++ if (z != NULL) { ++ if (!BN_copy(z, &point->Z)) ++ goto err; ++ } ++ } ++ ++ ret = 1; ++ ++ err: ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, ++ EC_POINT *point, ++ const BIGNUM *x, ++ const BIGNUM *y, BN_CTX *ctx) ++{ ++ if (x == NULL || y == NULL) { ++ /* ++ * unlike for projective coordinates, we do not tolerate this ++ */ ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ++ ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ++ return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, ++ BN_value_one(), ctx); ++} ++ ++int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, ++ const EC_POINT *point, ++ BIGNUM *x, BIGNUM *y, ++ BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *Z, *Z_1, *Z_2, *Z_3; ++ const BIGNUM *Z_; ++ int ret = 0; ++ ++ if (EC_POINT_is_at_infinity(group, point)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ++ EC_R_POINT_AT_INFINITY); ++ return 0; ++ } ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ Z = BN_CTX_get(ctx); ++ Z_1 = BN_CTX_get(ctx); ++ Z_2 = BN_CTX_get(ctx); ++ Z_3 = BN_CTX_get(ctx); ++ if (Z_3 == NULL) ++ goto err; ++ ++ /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ ++ ++ if (group->meth->field_decode) { ++ if (!group->meth->field_decode(group, Z, &point->Z, ctx)) ++ goto err; ++ Z_ = Z; ++ } else { ++ Z_ = &point->Z; ++ } ++ ++ if (BN_is_one(Z_)) { ++ if (group->meth->field_decode) { ++ if (x != NULL) { ++ if (!group->meth->field_decode(group, x, &point->X, ctx)) ++ goto err; ++ } ++ if (y != NULL) { ++ if (!group->meth->field_decode(group, y, &point->Y, ctx)) ++ goto err; ++ } ++ } else { ++ if (x != NULL) { ++ if (!BN_copy(x, &point->X)) ++ goto err; ++ } ++ if (y != NULL) { ++ if (!BN_copy(y, &point->Y)) ++ goto err; ++ } ++ } ++ } else { ++ if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ++ ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (group->meth->field_encode == 0) { ++ /* field_sqr works on standard representation */ ++ if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) ++ goto err; ++ } else { ++ if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) ++ goto err; ++ } ++ ++ if (x != NULL) { ++ /* ++ * in the Montgomery case, field_mul will cancel out Montgomery ++ * factor in X: ++ */ ++ if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) ++ goto err; ++ } ++ ++ if (y != NULL) { ++ if (group->meth->field_encode == 0) { ++ /* ++ * field_mul works on standard representation ++ */ ++ if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) ++ goto err; ++ } else { ++ if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) ++ goto err; ++ } ++ ++ /* ++ * in the Montgomery case, field_mul will cancel out Montgomery ++ * factor in Y: ++ */ ++ if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) ++ goto err; ++ } ++ } ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *ctx) ++{ ++ int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, ++ const BIGNUM *, BN_CTX *); ++ int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); ++ const BIGNUM *p; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; ++ int ret = 0; ++ ++ if (a == b) ++ return EC_POINT_dbl(group, r, a, ctx); ++ if (EC_POINT_is_at_infinity(group, a)) ++ return EC_POINT_copy(r, b); ++ if (EC_POINT_is_at_infinity(group, b)) ++ return EC_POINT_copy(r, a); ++ ++ field_mul = group->meth->field_mul; ++ field_sqr = group->meth->field_sqr; ++ p = &group->field; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ n0 = BN_CTX_get(ctx); ++ n1 = BN_CTX_get(ctx); ++ n2 = BN_CTX_get(ctx); ++ n3 = BN_CTX_get(ctx); ++ n4 = BN_CTX_get(ctx); ++ n5 = BN_CTX_get(ctx); ++ n6 = BN_CTX_get(ctx); ++ if (n6 == NULL) ++ goto end; ++ ++ /* ++ * Note that in this function we must not read components of 'a' or 'b' ++ * once we have written the corresponding components of 'r'. ('r' might ++ * be one of 'a' or 'b'.) ++ */ ++ ++ /* n1, n2 */ ++ if (b->Z_is_one) { ++ if (!BN_copy(n1, &a->X)) ++ goto end; ++ if (!BN_copy(n2, &a->Y)) ++ goto end; ++ /* n1 = X_a */ ++ /* n2 = Y_a */ ++ } else { ++ if (!field_sqr(group, n0, &b->Z, ctx)) ++ goto end; ++ if (!field_mul(group, n1, &a->X, n0, ctx)) ++ goto end; ++ /* n1 = X_a * Z_b^2 */ ++ ++ if (!field_mul(group, n0, n0, &b->Z, ctx)) ++ goto end; ++ if (!field_mul(group, n2, &a->Y, n0, ctx)) ++ goto end; ++ /* n2 = Y_a * Z_b^3 */ ++ } ++ ++ /* n3, n4 */ ++ if (a->Z_is_one) { ++ if (!BN_copy(n3, &b->X)) ++ goto end; ++ if (!BN_copy(n4, &b->Y)) ++ goto end; ++ /* n3 = X_b */ ++ /* n4 = Y_b */ ++ } else { ++ if (!field_sqr(group, n0, &a->Z, ctx)) ++ goto end; ++ if (!field_mul(group, n3, &b->X, n0, ctx)) ++ goto end; ++ /* n3 = X_b * Z_a^2 */ ++ ++ if (!field_mul(group, n0, n0, &a->Z, ctx)) ++ goto end; ++ if (!field_mul(group, n4, &b->Y, n0, ctx)) ++ goto end; ++ /* n4 = Y_b * Z_a^3 */ ++ } ++ ++ /* n5, n6 */ ++ if (!BN_mod_sub_quick(n5, n1, n3, p)) ++ goto end; ++ if (!BN_mod_sub_quick(n6, n2, n4, p)) ++ goto end; ++ /* n5 = n1 - n3 */ ++ /* n6 = n2 - n4 */ ++ ++ if (BN_is_zero(n5)) { ++ if (BN_is_zero(n6)) { ++ /* a is the same point as b */ ++ BN_CTX_end(ctx); ++ ret = EC_POINT_dbl(group, r, a, ctx); ++ ctx = NULL; ++ goto end; ++ } else { ++ /* a is the inverse of b */ ++ BN_zero(&r->Z); ++ r->Z_is_one = 0; ++ ret = 1; ++ goto end; ++ } ++ } ++ ++ /* 'n7', 'n8' */ ++ if (!BN_mod_add_quick(n1, n1, n3, p)) ++ goto end; ++ if (!BN_mod_add_quick(n2, n2, n4, p)) ++ goto end; ++ /* 'n7' = n1 + n3 */ ++ /* 'n8' = n2 + n4 */ ++ ++ /* Z_r */ ++ if (a->Z_is_one && b->Z_is_one) { ++ if (!BN_copy(&r->Z, n5)) ++ goto end; ++ } else { ++ if (a->Z_is_one) { ++ if (!BN_copy(n0, &b->Z)) ++ goto end; ++ } else if (b->Z_is_one) { ++ if (!BN_copy(n0, &a->Z)) ++ goto end; ++ } else { ++ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) ++ goto end; ++ } ++ if (!field_mul(group, &r->Z, n0, n5, ctx)) ++ goto end; ++ } ++ r->Z_is_one = 0; ++ /* Z_r = Z_a * Z_b * n5 */ ++ ++ /* X_r */ ++ if (!field_sqr(group, n0, n6, ctx)) ++ goto end; ++ if (!field_sqr(group, n4, n5, ctx)) ++ goto end; ++ if (!field_mul(group, n3, n1, n4, ctx)) ++ goto end; ++ if (!BN_mod_sub_quick(&r->X, n0, n3, p)) ++ goto end; ++ /* X_r = n6^2 - n5^2 * 'n7' */ ++ ++ /* 'n9' */ ++ if (!BN_mod_lshift1_quick(n0, &r->X, p)) ++ goto end; ++ if (!BN_mod_sub_quick(n0, n3, n0, p)) ++ goto end; ++ /* n9 = n5^2 * 'n7' - 2 * X_r */ ++ ++ /* Y_r */ ++ if (!field_mul(group, n0, n0, n6, ctx)) ++ goto end; ++ if (!field_mul(group, n5, n4, n5, ctx)) ++ goto end; /* now n5 is n5^3 */ ++ if (!field_mul(group, n1, n2, n5, ctx)) ++ goto end; ++ if (!BN_mod_sub_quick(n0, n0, n1, p)) ++ goto end; ++ if (BN_is_odd(n0)) ++ if (!BN_add(n0, n0, p)) ++ goto end; ++ /* now 0 <= n0 < 2*p, and n0 is even */ ++ if (!BN_rshift1(&r->Y, n0)) ++ goto end; ++ /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ ++ ++ ret = 1; ++ ++ end: ++ if (ctx) /* otherwise we already called BN_CTX_end */ ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ++ BN_CTX *ctx) ++{ ++ int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, ++ const BIGNUM *, BN_CTX *); ++ int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); ++ const BIGNUM *p; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *n0, *n1, *n2, *n3; ++ int ret = 0; ++ ++ if (EC_POINT_is_at_infinity(group, a)) { ++ BN_zero(&r->Z); ++ r->Z_is_one = 0; ++ return 1; ++ } ++ ++ field_mul = group->meth->field_mul; ++ field_sqr = group->meth->field_sqr; ++ p = &group->field; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ n0 = BN_CTX_get(ctx); ++ n1 = BN_CTX_get(ctx); ++ n2 = BN_CTX_get(ctx); ++ n3 = BN_CTX_get(ctx); ++ if (n3 == NULL) ++ goto err; ++ ++ /* ++ * Note that in this function we must not read components of 'a' once we ++ * have written the corresponding components of 'r'. ('r' might the same ++ * as 'a'.) ++ */ ++ ++ /* n1 */ ++ if (a->Z_is_one) { ++ if (!field_sqr(group, n0, &a->X, ctx)) ++ goto err; ++ if (!BN_mod_lshift1_quick(n1, n0, p)) ++ goto err; ++ if (!BN_mod_add_quick(n0, n0, n1, p)) ++ goto err; ++ if (!BN_mod_add_quick(n1, n0, &group->a, p)) ++ goto err; ++ /* n1 = 3 * X_a^2 + a_curve */ ++ } else if (group->a_is_minus3) { ++ if (!field_sqr(group, n1, &a->Z, ctx)) ++ goto err; ++ if (!BN_mod_add_quick(n0, &a->X, n1, p)) ++ goto err; ++ if (!BN_mod_sub_quick(n2, &a->X, n1, p)) ++ goto err; ++ if (!field_mul(group, n1, n0, n2, ctx)) ++ goto err; ++ if (!BN_mod_lshift1_quick(n0, n1, p)) ++ goto err; ++ if (!BN_mod_add_quick(n1, n0, n1, p)) ++ goto err; ++ /*- ++ * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) ++ * = 3 * X_a^2 - 3 * Z_a^4 ++ */ ++ } else { ++ if (!field_sqr(group, n0, &a->X, ctx)) ++ goto err; ++ if (!BN_mod_lshift1_quick(n1, n0, p)) ++ goto err; ++ if (!BN_mod_add_quick(n0, n0, n1, p)) ++ goto err; ++ if (!field_sqr(group, n1, &a->Z, ctx)) ++ goto err; ++ if (!field_sqr(group, n1, n1, ctx)) ++ goto err; ++ if (!field_mul(group, n1, n1, &group->a, ctx)) ++ goto err; ++ if (!BN_mod_add_quick(n1, n1, n0, p)) ++ goto err; ++ /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ ++ } ++ ++ /* Z_r */ ++ if (a->Z_is_one) { ++ if (!BN_copy(n0, &a->Y)) ++ goto err; ++ } else { ++ if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) ++ goto err; ++ } ++ if (!BN_mod_lshift1_quick(&r->Z, n0, p)) ++ goto err; ++ r->Z_is_one = 0; ++ /* Z_r = 2 * Y_a * Z_a */ ++ ++ /* n2 */ ++ if (!field_sqr(group, n3, &a->Y, ctx)) ++ goto err; ++ if (!field_mul(group, n2, &a->X, n3, ctx)) ++ goto err; ++ if (!BN_mod_lshift_quick(n2, n2, 2, p)) ++ goto err; ++ /* n2 = 4 * X_a * Y_a^2 */ ++ ++ /* X_r */ ++ if (!BN_mod_lshift1_quick(n0, n2, p)) ++ goto err; ++ if (!field_sqr(group, &r->X, n1, ctx)) ++ goto err; ++ if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) ++ goto err; ++ /* X_r = n1^2 - 2 * n2 */ ++ ++ /* n3 */ ++ if (!field_sqr(group, n0, n3, ctx)) ++ goto err; ++ if (!BN_mod_lshift_quick(n3, n0, 3, p)) ++ goto err; ++ /* n3 = 8 * Y_a^4 */ ++ ++ /* Y_r */ ++ if (!BN_mod_sub_quick(n0, n2, &r->X, p)) ++ goto err; ++ if (!field_mul(group, n0, n1, n0, ctx)) ++ goto err; ++ if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) ++ goto err; ++ /* Y_r = n1 * (n2 - X_r) - n3 */ ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) ++{ ++ if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) ++ /* point is its own inverse */ ++ return 1; ++ ++ return BN_usub(&point->Y, &group->field, &point->Y); ++} ++ ++int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) ++{ ++ return BN_is_zero(&point->Z); ++} ++ ++int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, ++ BN_CTX *ctx) ++{ ++ int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, ++ const BIGNUM *, BN_CTX *); ++ int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); ++ const BIGNUM *p; ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *rh, *tmp, *Z4, *Z6; ++ int ret = -1; ++ ++ if (EC_POINT_is_at_infinity(group, point)) ++ return 1; ++ ++ field_mul = group->meth->field_mul; ++ field_sqr = group->meth->field_sqr; ++ p = &group->field; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return -1; ++ } ++ ++ BN_CTX_start(ctx); ++ rh = BN_CTX_get(ctx); ++ tmp = BN_CTX_get(ctx); ++ Z4 = BN_CTX_get(ctx); ++ Z6 = BN_CTX_get(ctx); ++ if (Z6 == NULL) ++ goto err; ++ ++ /*- ++ * We have a curve defined by a Weierstrass equation ++ * y^2 = x^3 + a*x + b. ++ * The point to consider is given in Jacobian projective coordinates ++ * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). ++ * Substituting this and multiplying by Z^6 transforms the above equation into ++ * Y^2 = X^3 + a*X*Z^4 + b*Z^6. ++ * To test this, we add up the right-hand side in 'rh'. ++ */ ++ ++ /* rh := X^2 */ ++ if (!field_sqr(group, rh, &point->X, ctx)) ++ goto err; ++ ++ if (!point->Z_is_one) { ++ if (!field_sqr(group, tmp, &point->Z, ctx)) ++ goto err; ++ if (!field_sqr(group, Z4, tmp, ctx)) ++ goto err; ++ if (!field_mul(group, Z6, Z4, tmp, ctx)) ++ goto err; ++ ++ /* rh := (rh + a*Z^4)*X */ ++ if (group->a_is_minus3) { ++ if (!BN_mod_lshift1_quick(tmp, Z4, p)) ++ goto err; ++ if (!BN_mod_add_quick(tmp, tmp, Z4, p)) ++ goto err; ++ if (!BN_mod_sub_quick(rh, rh, tmp, p)) ++ goto err; ++ if (!field_mul(group, rh, rh, &point->X, ctx)) ++ goto err; ++ } else { ++ if (!field_mul(group, tmp, Z4, &group->a, ctx)) ++ goto err; ++ if (!BN_mod_add_quick(rh, rh, tmp, p)) ++ goto err; ++ if (!field_mul(group, rh, rh, &point->X, ctx)) ++ goto err; ++ } ++ ++ /* rh := rh + b*Z^6 */ ++ if (!field_mul(group, tmp, &group->b, Z6, ctx)) ++ goto err; ++ if (!BN_mod_add_quick(rh, rh, tmp, p)) ++ goto err; ++ } else { ++ /* point->Z_is_one */ ++ ++ /* rh := (rh + a)*X */ ++ if (!BN_mod_add_quick(rh, rh, &group->a, p)) ++ goto err; ++ if (!field_mul(group, rh, rh, &point->X, ctx)) ++ goto err; ++ /* rh := rh + b */ ++ if (!BN_mod_add_quick(rh, rh, &group->b, p)) ++ goto err; ++ } ++ ++ /* 'lh' := Y^2 */ ++ if (!field_sqr(group, tmp, &point->Y, ctx)) ++ goto err; ++ ++ ret = (0 == BN_ucmp(tmp, rh)); ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, ++ const EC_POINT *b, BN_CTX *ctx) ++{ ++ /*- ++ * return values: ++ * -1 error ++ * 0 equal (in affine coordinates) ++ * 1 not equal ++ */ ++ ++ int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, ++ const BIGNUM *, BN_CTX *); ++ int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *tmp1, *tmp2, *Za23, *Zb23; ++ const BIGNUM *tmp1_, *tmp2_; ++ int ret = -1; ++ ++ if (EC_POINT_is_at_infinity(group, a)) { ++ return EC_POINT_is_at_infinity(group, b) ? 0 : 1; ++ } ++ ++ if (EC_POINT_is_at_infinity(group, b)) ++ return 1; ++ ++ if (a->Z_is_one && b->Z_is_one) { ++ return ((BN_cmp(&a->X, &b->X) == 0) ++ && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; ++ } ++ ++ field_mul = group->meth->field_mul; ++ field_sqr = group->meth->field_sqr; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return -1; ++ } ++ ++ BN_CTX_start(ctx); ++ tmp1 = BN_CTX_get(ctx); ++ tmp2 = BN_CTX_get(ctx); ++ Za23 = BN_CTX_get(ctx); ++ Zb23 = BN_CTX_get(ctx); ++ if (Zb23 == NULL) ++ goto end; ++ ++ /*- ++ * We have to decide whether ++ * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), ++ * or equivalently, whether ++ * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). ++ */ ++ ++ if (!b->Z_is_one) { ++ if (!field_sqr(group, Zb23, &b->Z, ctx)) ++ goto end; ++ if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) ++ goto end; ++ tmp1_ = tmp1; ++ } else ++ tmp1_ = &a->X; ++ if (!a->Z_is_one) { ++ if (!field_sqr(group, Za23, &a->Z, ctx)) ++ goto end; ++ if (!field_mul(group, tmp2, &b->X, Za23, ctx)) ++ goto end; ++ tmp2_ = tmp2; ++ } else ++ tmp2_ = &b->X; ++ ++ /* compare X_a*Z_b^2 with X_b*Z_a^2 */ ++ if (BN_cmp(tmp1_, tmp2_) != 0) { ++ ret = 1; /* points differ */ ++ goto end; ++ } ++ ++ if (!b->Z_is_one) { ++ if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) ++ goto end; ++ if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) ++ goto end; ++ /* tmp1_ = tmp1 */ ++ } else ++ tmp1_ = &a->Y; ++ if (!a->Z_is_one) { ++ if (!field_mul(group, Za23, Za23, &a->Z, ctx)) ++ goto end; ++ if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) ++ goto end; ++ /* tmp2_ = tmp2 */ ++ } else ++ tmp2_ = &b->Y; ++ ++ /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ ++ if (BN_cmp(tmp1_, tmp2_) != 0) { ++ ret = 1; /* points differ */ ++ goto end; ++ } ++ ++ /* points are equal */ ++ ret = 0; ++ ++ end: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, ++ BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *x, *y; ++ int ret = 0; ++ ++ if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) ++ return 1; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ x = BN_CTX_get(ctx); ++ y = BN_CTX_get(ctx); ++ if (y == NULL) ++ goto err; ++ ++ if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) ++ goto err; ++ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) ++ goto err; ++ if (!point->Z_is_one) { ++ ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ return ret; ++} ++ ++int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, ++ EC_POINT *points[], BN_CTX *ctx) ++{ ++ BN_CTX *new_ctx = NULL; ++ BIGNUM *tmp, *tmp_Z; ++ BIGNUM **prod_Z = NULL; ++ size_t i; ++ int ret = 0; ++ ++ if (num == 0) ++ return 1; ++ ++ if (ctx == NULL) { ++ ctx = new_ctx = BN_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ } ++ ++ BN_CTX_start(ctx); ++ tmp = BN_CTX_get(ctx); ++ tmp_Z = BN_CTX_get(ctx); ++ if (tmp == NULL || tmp_Z == NULL) ++ goto err; ++ ++ prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]); ++ if (prod_Z == NULL) ++ goto err; ++ for (i = 0; i < num; i++) { ++ prod_Z[i] = BN_new(); ++ if (prod_Z[i] == NULL) ++ goto err; ++ } ++ ++ /* ++ * Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, ++ * skipping any zero-valued inputs (pretend that they're 1). ++ */ ++ ++ if (!BN_is_zero(&points[0]->Z)) { ++ if (!BN_copy(prod_Z[0], &points[0]->Z)) ++ goto err; ++ } else { ++ if (group->meth->field_set_to_one != 0) { ++ if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) ++ goto err; ++ } else { ++ if (!BN_one(prod_Z[0])) ++ goto err; ++ } ++ } ++ ++ for (i = 1; i < num; i++) { ++ if (!BN_is_zero(&points[i]->Z)) { ++ if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], ++ &points[i]->Z, ctx)) ++ goto err; ++ } else { ++ if (!BN_copy(prod_Z[i], prod_Z[i - 1])) ++ goto err; ++ } ++ } ++ ++ /* ++ * Now use a single explicit inversion to replace every non-zero ++ * points[i]->Z by its inverse. ++ */ ++ ++ if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { ++ ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (group->meth->field_encode != 0) { ++ /* ++ * In the Montgomery case, we just turned R*H (representing H) into ++ * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to ++ * multiply by the Montgomery factor twice. ++ */ ++ if (!group->meth->field_encode(group, tmp, tmp, ctx)) ++ goto err; ++ if (!group->meth->field_encode(group, tmp, tmp, ctx)) ++ goto err; ++ } ++ ++ for (i = num - 1; i > 0; --i) { ++ /* ++ * Loop invariant: tmp is the product of the inverses of points[0]->Z ++ * .. points[i]->Z (zero-valued inputs skipped). ++ */ ++ if (!BN_is_zero(&points[i]->Z)) { ++ /* ++ * Set tmp_Z to the inverse of points[i]->Z (as product of Z ++ * inverses 0 .. i, Z values 0 .. i - 1). ++ */ ++ if (!group-> ++ meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) ++ goto err; ++ /* ++ * Update tmp to satisfy the loop invariant for i - 1. ++ */ ++ if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) ++ goto err; ++ /* Replace points[i]->Z by its inverse. */ ++ if (!BN_copy(&points[i]->Z, tmp_Z)) ++ goto err; ++ } ++ } ++ ++ if (!BN_is_zero(&points[0]->Z)) { ++ /* Replace points[0]->Z by its inverse. */ ++ if (!BN_copy(&points[0]->Z, tmp)) ++ goto err; ++ } ++ ++ /* Finally, fix up the X and Y coordinates for all points. */ ++ ++ for (i = 0; i < num; i++) { ++ EC_POINT *p = points[i]; ++ ++ if (!BN_is_zero(&p->Z)) { ++ /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ ++ ++ if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) ++ goto err; ++ if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) ++ goto err; ++ ++ if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) ++ goto err; ++ if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) ++ goto err; ++ ++ if (group->meth->field_set_to_one != 0) { ++ if (!group->meth->field_set_to_one(group, &p->Z, ctx)) ++ goto err; ++ } else { ++ if (!BN_one(&p->Z)) ++ goto err; ++ } ++ p->Z_is_one = 1; ++ } ++ } ++ ++ ret = 1; ++ ++ err: ++ BN_CTX_end(ctx); ++ if (new_ctx != NULL) ++ BN_CTX_free(new_ctx); ++ if (prod_Z != NULL) { ++ for (i = 0; i < num; i++) { ++ if (prod_Z[i] == NULL) ++ break; ++ BN_clear_free(prod_Z[i]); ++ } ++ OPENSSL_free(prod_Z); ++ } ++ return ret; ++} ++ ++int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *b, BN_CTX *ctx) ++{ ++ return BN_mod_mul(r, a, b, &group->field, ctx); ++} ++ ++int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, ++ BN_CTX *ctx) ++{ ++ return BN_mod_sqr(r, a, &group->field, ctx); ++} +-- +2.33.0 + diff --git a/Feature-shim-openssl-add-ecdsa-support.patch b/Feature-shim-openssl-add-ecdsa-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d0c4bf64a6ccb16b54a18d4219df3fbc4660879 --- /dev/null +++ b/Feature-shim-openssl-add-ecdsa-support.patch @@ -0,0 +1,1408 @@ +From 9c23c5fc4ec7ca4d58d1d4f8d7de307fae421310 Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Mon, 7 Nov 2022 11:43:45 +0800 +Subject: [PATCH 2/5] shim openssl add ecdsa support + +Co-authored-by: Yusong Gao +Signed-off-by: Yusong Gao +Signed-off-by: Huaxin Lu +--- + Cryptlib/OpenSSL/crypto/ecdsa/ecs_asn1.c | 75 ++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_err.c | 107 ++++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_lib.c | 354 +++++++++++++++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_locl.h | 120 ++++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_ossl.c | 464 +++++++++++++++++++++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_sign.c | 106 ++++++ + Cryptlib/OpenSSL/crypto/ecdsa/ecs_vrf.c | 112 ++++++ + 7 files changed, 1338 insertions(+) + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_asn1.c + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_err.c + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_lib.c + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_locl.h + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_ossl.c + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_sign.c + create mode 100644 Cryptlib/OpenSSL/crypto/ecdsa/ecs_vrf.c + +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_asn1.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_asn1.c +new file mode 100644 +index 0000000..77a290d +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_asn1.c +@@ -0,0 +1,75 @@ ++/* crypto/ecdsa/ecs_asn1.c */ ++/* ==================================================================== ++ * Copyright (c) 2000-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 ++ * 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 "ecs_locl.h" ++#include ++#include ++ ++ASN1_SEQUENCE(ECDSA_SIG) = { ++ ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM), ++ ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM) ++} ASN1_SEQUENCE_END(ECDSA_SIG) ++ ++DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG) ++DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG) ++IMPLEMENT_ASN1_FUNCTIONS_const(ECDSA_SIG) ++ ++void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) ++{ ++ if (pr != NULL) ++ *pr = sig->r; ++ if (ps != NULL) ++ *ps = sig->s; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_err.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_err.c +new file mode 100644 +index 0000000..f1fa7b5 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_err.c +@@ -0,0 +1,107 @@ ++/* crypto/ecdsa/ecs_err.c */ ++/* ==================================================================== ++ * Copyright (c) 1999-2011 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). ++ * ++ */ ++ ++/* ++ * NOTE: this file was auto generated by the mkerr.pl script: any changes ++ * made to it will be overwritten when the script next updates this file, ++ * only reason strings will be preserved. ++ */ ++ ++#include ++#include ++#include ++ ++/* BEGIN ERROR CODES */ ++#ifndef OPENSSL_NO_ERR ++ ++# define ERR_FUNC(func) ERR_PACK(ERR_LIB_ECDSA,func,0) ++# define ERR_REASON(reason) ERR_PACK(ERR_LIB_ECDSA,0,reason) ++ ++static ERR_STRING_DATA ECDSA_str_functs[] = { ++ {ERR_FUNC(ECDSA_F_ECDSA_CHECK), "ECDSA_CHECK"}, ++ {ERR_FUNC(ECDSA_F_ECDSA_DATA_NEW_METHOD), "ECDSA_DATA_NEW_METHOD"}, ++ {ERR_FUNC(ECDSA_F_ECDSA_DO_SIGN), "ECDSA_do_sign"}, ++ {ERR_FUNC(ECDSA_F_ECDSA_DO_VERIFY), "ECDSA_do_verify"}, ++ {ERR_FUNC(ECDSA_F_ECDSA_METHOD_NEW), "ECDSA_METHOD_new"}, ++ {ERR_FUNC(ECDSA_F_ECDSA_SIGN_SETUP), "ECDSA_sign_setup"}, ++ {0, NULL} ++}; ++ ++static ERR_STRING_DATA ECDSA_str_reasons[] = { ++ {ERR_REASON(ECDSA_R_BAD_SIGNATURE), "bad signature"}, ++ {ERR_REASON(ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), ++ "data too large for key size"}, ++ {ERR_REASON(ECDSA_R_ERR_EC_LIB), "err ec lib"}, ++ {ERR_REASON(ECDSA_R_MISSING_PARAMETERS), "missing parameters"}, ++ {ERR_REASON(ECDSA_R_NEED_NEW_SETUP_VALUES), "need new setup values"}, ++ {ERR_REASON(ECDSA_R_NON_FIPS_METHOD), "non fips method"}, ++ {ERR_REASON(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED), ++ "random number generation failed"}, ++ {ERR_REASON(ECDSA_R_SIGNATURE_MALLOC_FAILED), "signature malloc failed"}, ++ {0, NULL} ++}; ++ ++#endif ++ ++void ERR_load_ECDSA_strings(void) ++{ ++#ifndef OPENSSL_NO_ERR ++ ++ if (ERR_func_error_string(ECDSA_str_functs[0].error) == NULL) { ++ ERR_load_strings(0, ECDSA_str_functs); ++ ERR_load_strings(0, ECDSA_str_reasons); ++ } ++#endif ++} +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_lib.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_lib.c +new file mode 100644 +index 0000000..8dc1dda +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_lib.c +@@ -0,0 +1,354 @@ ++/* crypto/ecdsa/ecs_lib.c */ ++/* ==================================================================== ++ * Copyright (c) 1998-2005 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 ++#include "ecs_locl.h" ++#ifndef OPENSSL_NO_ENGINE ++# include ++#endif ++#include ++#include ++#ifdef OPENSSL_FIPS ++# include ++#endif ++ ++const char ECDSA_version[] = "ECDSA" OPENSSL_VERSION_PTEXT; ++ ++static const ECDSA_METHOD *default_ECDSA_method = NULL; ++ ++static void *ecdsa_data_new(void); ++static void *ecdsa_data_dup(void *); ++static void ecdsa_data_free(void *); ++ ++void ECDSA_set_default_method(const ECDSA_METHOD *meth) ++{ ++ default_ECDSA_method = meth; ++} ++ ++const ECDSA_METHOD *ECDSA_get_default_method(void) ++{ ++ if (!default_ECDSA_method) { ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode()) ++ return FIPS_ecdsa_openssl(); ++ else ++ return ECDSA_OpenSSL(); ++#else ++ default_ECDSA_method = ECDSA_OpenSSL(); ++#endif ++ } ++ return default_ECDSA_method; ++} ++ ++int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth) ++{ ++ ECDSA_DATA *ecdsa; ++ ++ ecdsa = ecdsa_check(eckey); ++ ++ if (ecdsa == NULL) ++ return 0; ++ ++#ifndef OPENSSL_NO_ENGINE ++ if (ecdsa->engine) { ++ ENGINE_finish(ecdsa->engine); ++ ecdsa->engine = NULL; ++ } ++#endif ++ ecdsa->meth = meth; ++ ++ return 1; ++} ++ ++static ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine) ++{ ++ ECDSA_DATA *ret; ++ ++ ret = (ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA)); ++ if (ret == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE); ++ return (NULL); ++ } ++ ++ ret->init = NULL; ++ ++ ret->meth = ECDSA_get_default_method(); ++ ret->engine = engine; ++#ifndef OPENSSL_NO_ENGINE ++ if (!ret->engine) ++ ret->engine = ENGINE_get_default_ECDSA(); ++ if (ret->engine) { ++ ret->meth = ENGINE_get_ECDSA(ret->engine); ++ if (!ret->meth) { ++ ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); ++ ENGINE_finish(ret->engine); ++ OPENSSL_free(ret); ++ return NULL; ++ } ++ } ++#endif ++ ++ ret->flags = ret->meth->flags; ++ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); ++#if 0 ++ if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { ++ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); ++ OPENSSL_free(ret); ++ ret = NULL; ++ } ++#endif ++ return (ret); ++} ++ ++static void *ecdsa_data_new(void) ++{ ++ return (void *)ECDSA_DATA_new_method(NULL); ++} ++ ++static void *ecdsa_data_dup(void *data) ++{ ++ ECDSA_DATA *r = (ECDSA_DATA *)data; ++ ++ /* XXX: dummy operation */ ++ if (r == NULL) ++ return NULL; ++ ++ return ecdsa_data_new(); ++} ++ ++static void ecdsa_data_free(void *data) ++{ ++ ECDSA_DATA *r = (ECDSA_DATA *)data; ++ ++#ifndef OPENSSL_NO_ENGINE ++ if (r->engine) ++ ENGINE_finish(r->engine); ++#endif ++ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data); ++ ++ OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA)); ++ ++ OPENSSL_free(r); ++} ++ ++ECDSA_DATA *ecdsa_check(EC_KEY *key) ++{ ++ ECDSA_DATA *ecdsa_data; ++ ++ void *data = EC_KEY_get_key_method_data(key, ecdsa_data_dup, ++ ecdsa_data_free, ecdsa_data_free); ++ if (data == NULL) { ++ ecdsa_data = (ECDSA_DATA *)ecdsa_data_new(); ++ if (ecdsa_data == NULL) ++ return NULL; ++ data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, ++ ecdsa_data_dup, ecdsa_data_free, ++ ecdsa_data_free); ++ if (data != NULL) { ++ /* ++ * Another thread raced us to install the key_method data and ++ * won. ++ */ ++ ecdsa_data_free(ecdsa_data); ++ ecdsa_data = (ECDSA_DATA *)data; ++ } ++ } else ++ ecdsa_data = (ECDSA_DATA *)data; ++#ifdef OPENSSL_FIPS ++ if (FIPS_mode() && !(ecdsa_data->flags & ECDSA_FLAG_FIPS_METHOD) ++ && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW)) { ++ ECDSAerr(ECDSA_F_ECDSA_CHECK, ECDSA_R_NON_FIPS_METHOD); ++ return NULL; ++ } ++#endif ++ ++ return ecdsa_data; ++} ++ ++int ECDSA_size(const EC_KEY *r) ++{ ++ int ret, i; ++ ASN1_INTEGER bs; ++ BIGNUM *order = NULL; ++ unsigned char buf[4]; ++ const EC_GROUP *group; ++ ++ if (r == NULL) ++ return 0; ++ group = EC_KEY_get0_group(r); ++ if (group == NULL) ++ return 0; ++ ++ if ((order = BN_new()) == NULL) ++ return 0; ++ if (!EC_GROUP_get_order(group, order, NULL)) { ++ BN_clear_free(order); ++ return 0; ++ } ++ i = BN_num_bits(order); ++ bs.length = (i + 7) / 8; ++ bs.data = buf; ++ bs.type = V_ASN1_INTEGER; ++ /* If the top bit is set the asn1 encoding is 1 larger. */ ++ buf[0] = 0xff; ++ ++ i = i2d_ASN1_INTEGER(&bs, NULL); ++ i += i; /* r and s */ ++ ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); ++ BN_clear_free(order); ++ return (ret); ++} ++ ++int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, ++ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) ++{ ++ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDSA, argl, argp, ++ new_func, dup_func, free_func); ++} ++ ++int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg) ++{ ++ ECDSA_DATA *ecdsa; ++ ecdsa = ecdsa_check(d); ++ if (ecdsa == NULL) ++ return 0; ++ return (CRYPTO_set_ex_data(&ecdsa->ex_data, idx, arg)); ++} ++ ++void *ECDSA_get_ex_data(EC_KEY *d, int idx) ++{ ++ ECDSA_DATA *ecdsa; ++ ecdsa = ecdsa_check(d); ++ if (ecdsa == NULL) ++ return NULL; ++ return (CRYPTO_get_ex_data(&ecdsa->ex_data, idx)); ++} ++ ++ECDSA_METHOD *ECDSA_METHOD_new(const ECDSA_METHOD *ecdsa_meth) ++{ ++ ECDSA_METHOD *ret; ++ ++ ret = OPENSSL_malloc(sizeof(ECDSA_METHOD)); ++ if (ret == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ if (ecdsa_meth) ++ *ret = *ecdsa_meth; ++ else { ++ ret->ecdsa_sign_setup = 0; ++ ret->ecdsa_do_sign = 0; ++ ret->ecdsa_do_verify = 0; ++ ret->name = NULL; ++ ret->flags = 0; ++ } ++ ret->flags |= ECDSA_METHOD_FLAG_ALLOCATED; ++ return ret; ++} ++ ++void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, ++ ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char ++ *dgst, int dgst_len, ++ const BIGNUM *inv, ++ const BIGNUM *rp, ++ EC_KEY *eckey)) ++{ ++ ecdsa_method->ecdsa_do_sign = ecdsa_do_sign; ++} ++ ++void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, ++ int (*ecdsa_sign_setup) (EC_KEY *eckey, ++ BN_CTX *ctx, ++ BIGNUM **kinv, ++ BIGNUM **r)) ++{ ++ ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup; ++} ++ ++void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, ++ int (*ecdsa_do_verify) (const unsigned char ++ *dgst, int dgst_len, ++ const ECDSA_SIG *sig, ++ EC_KEY *eckey)) ++{ ++ ecdsa_method->ecdsa_do_verify = ecdsa_do_verify; ++} ++ ++void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags) ++{ ++ ecdsa_method->flags = flags | ECDSA_METHOD_FLAG_ALLOCATED; ++} ++ ++void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name) ++{ ++ ecdsa_method->name = name; ++} ++ ++void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method) ++{ ++ if (ecdsa_method->flags & ECDSA_METHOD_FLAG_ALLOCATED) ++ OPENSSL_free(ecdsa_method); ++} ++ ++void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app) ++{ ++ ecdsa_method->app_data = app; ++} ++ ++void *ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method) ++{ ++ return ecdsa_method->app_data; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_locl.h b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_locl.h +new file mode 100644 +index 0000000..4e9bd44 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_locl.h +@@ -0,0 +1,120 @@ ++/* crypto/ecdsa/ecs_locl.h */ ++/* ++ * Written by Nils Larsch for the OpenSSL project ++ */ ++/* ==================================================================== ++ * Copyright (c) 2000-2005 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). ++ * ++ */ ++ ++#ifndef HEADER_ECS_LOCL_H ++# define HEADER_ECS_LOCL_H ++ ++# include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct ecdsa_method { ++ const char *name; ++ ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char *dgst, int dgst_len, ++ const BIGNUM *inv, const BIGNUM *rp, ++ EC_KEY *eckey); ++ int (*ecdsa_sign_setup) (EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, ++ BIGNUM **r); ++ int (*ecdsa_do_verify) (const unsigned char *dgst, int dgst_len, ++ const ECDSA_SIG *sig, EC_KEY *eckey); ++# if 0 ++ int (*init) (EC_KEY *eckey); ++ int (*finish) (EC_KEY *eckey); ++# endif ++ int flags; ++ void *app_data; ++}; ++ ++/* The ECDSA_METHOD was allocated and can be freed */ ++ ++# define ECDSA_METHOD_FLAG_ALLOCATED 0x2 ++ ++/* ++ * If this flag is set the ECDSA method is FIPS compliant and can be used in ++ * FIPS mode. This is set in the validated module method. If an application ++ * sets this flag in its own methods it is its responsibility to ensure the ++ * result is compliant. ++ */ ++ ++# define ECDSA_FLAG_FIPS_METHOD 0x1 ++ ++typedef struct ecdsa_data_st { ++ /* EC_KEY_METH_DATA part */ ++ int (*init) (EC_KEY *); ++ /* method (ECDSA) specific part */ ++ ENGINE *engine; ++ int flags; ++ const ECDSA_METHOD *meth; ++ CRYPTO_EX_DATA ex_data; ++} ECDSA_DATA; ++ ++/** ecdsa_check ++ * checks whether ECKEY->meth_data is a pointer to a ECDSA_DATA structure ++ * and if not it removes the old meth_data and creates a ECDSA_DATA structure. ++ * \param eckey pointer to a EC_KEY object ++ * \return pointer to a ECDSA_DATA structure ++ */ ++ECDSA_DATA *ecdsa_check(EC_KEY *eckey); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HEADER_ECS_LOCL_H */ +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_ossl.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_ossl.c +new file mode 100644 +index 0000000..dd76960 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_ossl.c +@@ -0,0 +1,464 @@ ++/* crypto/ecdsa/ecs_ossl.c */ ++/* ++ * Written by Nils Larsch for the OpenSSL project ++ */ ++/* ==================================================================== ++ * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * 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 "ecs_locl.h" ++#include ++#include ++#include ++ ++static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen, ++ const BIGNUM *, const BIGNUM *, ++ EC_KEY *eckey); ++static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, ++ BIGNUM **rp); ++static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ++ const ECDSA_SIG *sig, EC_KEY *eckey); ++ ++static ECDSA_METHOD openssl_ecdsa_meth = { ++ "OpenSSL ECDSA method", ++ ecdsa_do_sign, ++ ecdsa_sign_setup, ++ ecdsa_do_verify, ++#if 0 ++ NULL, /* init */ ++ NULL, /* finish */ ++#endif ++ 0, /* flags */ ++ NULL /* app_data */ ++}; ++ ++const ECDSA_METHOD *ECDSA_OpenSSL(void) ++{ ++ return &openssl_ecdsa_meth; ++} ++ ++static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, ++ BIGNUM **rp) ++{ ++ BN_CTX *ctx = NULL; ++ BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; ++ EC_POINT *tmp_point = NULL; ++ const EC_GROUP *group; ++ int ret = 0; ++ ++ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ ++ if (ctx_in == NULL) { ++ if ((ctx = BN_CTX_new()) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ } else ++ ctx = ctx_in; ++ ++ k = BN_new(); /* this value is later returned in *kinvp */ ++ r = BN_new(); /* this value is later returned in *rp */ ++ order = BN_new(); ++ X = BN_new(); ++ if (!k || !r || !order || !X) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if ((tmp_point = EC_POINT_new(group)) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (!EC_GROUP_get_order(group, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ do { ++ /* get random k */ ++ do ++ if (!BN_rand_range(k, order)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ++ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); ++ goto err; ++ } ++ while (BN_is_zero(k)) ; ++ ++ /* ++ * We do not want timing information to leak the length of k, so we ++ * compute G*k using an equivalent scalar of fixed bit-length. ++ */ ++ ++ if (!BN_add(k, k, order)) ++ goto err; ++ if (BN_num_bits(k) <= BN_num_bits(order)) ++ if (!BN_add(k, k, order)) ++ goto err; ++ ++ /* compute r the x-coordinate of generator * k */ ++ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == ++ NID_X9_62_prime_field) { ++ if (!EC_POINT_get_affine_coordinates_GFp ++ (group, tmp_point, X, NULL, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#ifndef OPENSSL_NO_EC2M ++ else { /* NID_X9_62_characteristic_two_field */ ++ ++ if (!EC_POINT_get_affine_coordinates_GF2m(group, ++ tmp_point, X, NULL, ++ ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#endif ++ if (!BN_nnmod(r, X, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ } ++ while (BN_is_zero(r)); ++ ++ /* compute the inverse of k */ ++ if (EC_GROUP_get_mont_data(group) != NULL) { ++ /* ++ * We want inverse in constant time, therefore we utilize the fact ++ * order must be prime and use Fermats Little Theorem instead. ++ */ ++ if (!BN_set_word(X, 2)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (!BN_mod_sub(X, order, X, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ BN_set_flags(X, BN_FLG_CONSTTIME); ++ if (!BN_mod_exp_mont_consttime ++ (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ } else { ++ if (!BN_mod_inverse(k, k, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); ++ goto err; ++ } ++ } ++ ++ /* clear old values if necessary */ ++ if (*rp != NULL) ++ BN_clear_free(*rp); ++ if (*kinvp != NULL) ++ BN_clear_free(*kinvp); ++ /* save the pre-computed values */ ++ *rp = r; ++ *kinvp = k; ++ ret = 1; ++ err: ++ if (!ret) { ++ if (k != NULL) ++ BN_clear_free(k); ++ if (r != NULL) ++ BN_clear_free(r); ++ } ++ if (ctx_in == NULL) ++ BN_CTX_free(ctx); ++ if (order != NULL) ++ BN_free(order); ++ if (tmp_point != NULL) ++ EC_POINT_free(tmp_point); ++ if (X) ++ BN_clear_free(X); ++ return (ret); ++} ++ ++static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, ++ const BIGNUM *in_kinv, const BIGNUM *in_r, ++ EC_KEY *eckey) ++{ ++ int ok = 0, i; ++ BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; ++ const BIGNUM *ckinv; ++ BN_CTX *ctx = NULL; ++ const EC_GROUP *group; ++ ECDSA_SIG *ret; ++ ECDSA_DATA *ecdsa; ++ const BIGNUM *priv_key; ++ ++ ecdsa = ecdsa_check(eckey); ++ group = EC_KEY_get0_group(eckey); ++ priv_key = EC_KEY_get0_private_key(eckey); ++ ++ if (group == NULL || priv_key == NULL || ecdsa == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); ++ return NULL; ++ } ++ ++ ret = ECDSA_SIG_new(); ++ if (!ret) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ s = ret->s; ++ ++ if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || ++ (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (!EC_GROUP_get_order(group, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); ++ goto err; ++ } ++ i = BN_num_bits(order); ++ /* ++ * Need to truncate digest if it is too long: first truncate whole bytes. ++ */ ++ if (8 * dgst_len > i) ++ dgst_len = (i + 7) / 8; ++ if (!BN_bin2bn(dgst, dgst_len, m)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* If still too long truncate remaining bits with a shift */ ++ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); ++ goto err; ++ } ++ do { ++ if (in_kinv == NULL || in_r == NULL) { ++ if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_ECDSA_LIB); ++ goto err; ++ } ++ ckinv = kinv; ++ } else { ++ ckinv = in_kinv; ++ if (BN_copy(ret->r, in_r) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ } ++ ++ if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (!BN_mod_add_quick(s, tmp, m, order)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (!BN_mod_mul(s, s, ckinv, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); ++ goto err; ++ } ++ if (BN_is_zero(s)) { ++ /* ++ * if kinv and r have been supplied by the caller don't to ++ * generate new kinv and r values ++ */ ++ if (in_kinv != NULL && in_r != NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ++ ECDSA_R_NEED_NEW_SETUP_VALUES); ++ goto err; ++ } ++ } else ++ /* s != 0 => we have a valid signature */ ++ break; ++ } ++ while (1); ++ ++ ok = 1; ++ err: ++ if (!ok) { ++ ECDSA_SIG_free(ret); ++ ret = NULL; ++ } ++ if (ctx) ++ BN_CTX_free(ctx); ++ if (m) ++ BN_clear_free(m); ++ if (tmp) ++ BN_clear_free(tmp); ++ if (order) ++ BN_free(order); ++ if (kinv) ++ BN_clear_free(kinv); ++ return ret; ++} ++ ++static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, ++ const ECDSA_SIG *sig, EC_KEY *eckey) ++{ ++ int ret = -1, i; ++ BN_CTX *ctx; ++ BIGNUM *order, *u1, *u2, *m, *X; ++ EC_POINT *point = NULL; ++ const EC_GROUP *group; ++ const EC_POINT *pub_key; ++ ++ /* check input values */ ++ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || ++ (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); ++ return -1; ++ } ++ ++ ctx = BN_CTX_new(); ++ if (!ctx) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); ++ return -1; ++ } ++ BN_CTX_start(ctx); ++ order = BN_CTX_get(ctx); ++ u1 = BN_CTX_get(ctx); ++ u2 = BN_CTX_get(ctx); ++ m = BN_CTX_get(ctx); ++ X = BN_CTX_get(ctx); ++ if (!X) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (!EC_GROUP_get_order(group, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || ++ BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || ++ BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ++ ret = 0; /* signature is invalid */ ++ goto err; ++ } ++ /* calculate tmp1 = inv(S) mod order */ ++ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* digest -> m */ ++ i = BN_num_bits(order); ++ /* ++ * Need to truncate digest if it is too long: first truncate whole bytes. ++ */ ++ if (8 * dgst_len > i) ++ dgst_len = (i + 7) / 8; ++ if (!BN_bin2bn(dgst, dgst_len, m)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* If still too long truncate remaining bits with a shift */ ++ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* u1 = m * tmp mod order */ ++ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* u2 = r * w mod q */ ++ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if ((point = EC_POINT_new(group)) == NULL) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); ++ goto err; ++ } ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == ++ NID_X9_62_prime_field) { ++ if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#ifndef OPENSSL_NO_EC2M ++ else { /* NID_X9_62_characteristic_two_field */ ++ ++ if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++#endif ++ if (!BN_nnmod(u1, X, order, ctx)) { ++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); ++ goto err; ++ } ++ /* if the signature is correct u1 is equal to sig->r */ ++ ret = (BN_ucmp(u1, sig->r) == 0); ++ err: ++ BN_CTX_end(ctx); ++ BN_CTX_free(ctx); ++ if (point) ++ EC_POINT_free(point); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_sign.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_sign.c +new file mode 100644 +index 0000000..28652d4 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_sign.c +@@ -0,0 +1,106 @@ ++/* crypto/ecdsa/ecdsa_sign.c */ ++/* ==================================================================== ++ * 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 "ecs_locl.h" ++#ifndef OPENSSL_NO_ENGINE ++# include ++#endif ++#include ++ ++ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) ++{ ++ return ECDSA_do_sign_ex(dgst, dlen, NULL, NULL, eckey); ++} ++ ++ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dlen, ++ const BIGNUM *kinv, const BIGNUM *rp, ++ EC_KEY *eckey) ++{ ++ ECDSA_DATA *ecdsa = ecdsa_check(eckey); ++ if (ecdsa == NULL) ++ return NULL; ++ return ecdsa->meth->ecdsa_do_sign(dgst, dlen, kinv, rp, eckey); ++} ++ ++int ECDSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char ++ *sig, unsigned int *siglen, EC_KEY *eckey) ++{ ++ return ECDSA_sign_ex(type, dgst, dlen, sig, siglen, NULL, NULL, eckey); ++} ++ ++int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char ++ *sig, unsigned int *siglen, const BIGNUM *kinv, ++ const BIGNUM *r, EC_KEY *eckey) ++{ ++ ECDSA_SIG *s; ++ RAND_seed(dgst, dlen); ++ s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); ++ if (s == NULL) { ++ *siglen = 0; ++ return 0; ++ } ++ *siglen = i2d_ECDSA_SIG(s, &sig); ++ ECDSA_SIG_free(s); ++ return 1; ++} ++ ++int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, ++ BIGNUM **rp) ++{ ++ ECDSA_DATA *ecdsa = ecdsa_check(eckey); ++ if (ecdsa == NULL) ++ return 0; ++ return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp); ++} +diff --git a/Cryptlib/OpenSSL/crypto/ecdsa/ecs_vrf.c b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_vrf.c +new file mode 100644 +index 0000000..e909aeb +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/ecdsa/ecs_vrf.c +@@ -0,0 +1,112 @@ ++/* crypto/ecdsa/ecdsa_vrf.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 "ecs_locl.h" ++#include ++#ifndef OPENSSL_NO_ENGINE ++# include ++#endif ++ ++/*- ++ * returns ++ * 1: correct signature ++ * 0: incorrect signature ++ * -1: error ++ */ ++int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, ++ const ECDSA_SIG *sig, EC_KEY *eckey) ++{ ++ ECDSA_DATA *ecdsa = ecdsa_check(eckey); ++ if (ecdsa == NULL) ++ return 0; ++ return ecdsa->meth->ecdsa_do_verify(dgst, dgst_len, sig, eckey); ++} ++ ++/*- ++ * returns ++ * 1: correct signature ++ * 0: incorrect signature ++ * -1: error ++ */ ++int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, ++ const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) ++{ ++ ECDSA_SIG *s; ++ const unsigned char *p = sigbuf; ++ unsigned char *der = NULL; ++ int derlen = -1; ++ int ret = -1; ++ ++ s = ECDSA_SIG_new(); ++ if (s == NULL) ++ return (ret); ++ if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) ++ goto err; ++ /* Ensure signature uses DER and doesn't have trailing garbage */ ++ derlen = i2d_ECDSA_SIG(s, &der); ++ if (derlen != sig_len || memcmp(sigbuf, der, derlen)) ++ goto err; ++ ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); ++ err: ++ if (derlen > 0) { ++ OPENSSL_cleanse(der, derlen); ++ OPENSSL_free(der); ++ } ++ ECDSA_SIG_free(s); ++ return (ret); ++} +-- +2.33.0 + diff --git a/Feature-shim-openssl-add-sm2-and-sm3-support.patch b/Feature-shim-openssl-add-sm2-and-sm3-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d41619c547969ae62e3d6a2f8a07712b47b9dc1 --- /dev/null +++ b/Feature-shim-openssl-add-sm2-and-sm3-support.patch @@ -0,0 +1,1284 @@ +From 62d73c2dd0cc4b2a80186d55de5ffd4298462a83 Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Mon, 7 Nov 2022 11:44:18 +0800 +Subject: [PATCH 3/5] shim openssl add sm2 and sm3 support + +Co-authored-by: Yusong Gao +Signed-off-by: Yusong Gao +Signed-off-by: Huaxin Lu +--- + Cryptlib/Include/openssl/sm2.h | 79 ++++++ + Cryptlib/Include/openssl/sm2err.h | 65 +++++ + Cryptlib/Include/openssl/sm3.h | 39 +++ + Cryptlib/OpenSSL/crypto/sm2/sm2_err.c | 71 ++++++ + Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c | 292 +++++++++++++++++++++ + Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c | 325 ++++++++++++++++++++++++ + Cryptlib/OpenSSL/crypto/sm3/m_sm3.c | 52 ++++ + Cryptlib/OpenSSL/crypto/sm3/sm3.c | 196 ++++++++++++++ + Cryptlib/OpenSSL/crypto/sm3/sm3_local.h | 79 ++++++ + 9 files changed, 1198 insertions(+) + create mode 100644 Cryptlib/Include/openssl/sm2.h + create mode 100644 Cryptlib/Include/openssl/sm2err.h + create mode 100644 Cryptlib/Include/openssl/sm3.h + create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_err.c + create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c + create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c + create mode 100644 Cryptlib/OpenSSL/crypto/sm3/m_sm3.c + create mode 100644 Cryptlib/OpenSSL/crypto/sm3/sm3.c + create mode 100644 Cryptlib/OpenSSL/crypto/sm3/sm3_local.h + +diff --git a/Cryptlib/Include/openssl/sm2.h b/Cryptlib/Include/openssl/sm2.h +new file mode 100644 +index 0000000..37c67a3 +--- /dev/null ++++ b/Cryptlib/Include/openssl/sm2.h +@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. All Rights Reserved. ++ * Ported from Ribose contributions from Botan. ++ * ++ * 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 ++ */ ++ ++#ifndef OSSL_CRYPTO_SM2_H ++# define OSSL_CRYPTO_SM2_H ++# include ++ ++# ifndef OPENSSL_NO_SM2 ++ ++# include ++# include ++ ++/* The default user id as specified in GM/T 0009-2012 */ ++# define SM2_DEFAULT_USERID "1234567812345678" ++# define SM2_DEFAULT_USERID_LEN 16 ++ ++int sm2_compute_z_digest(uint8_t *out, ++ const EVP_MD *digest, ++ const uint8_t *id, ++ const size_t id_len, ++ const EC_KEY *key); ++ ++/* ++ * SM2 signature operation. Computes Z and then signs H(Z || msg) using SM2 ++ */ ++ECDSA_SIG *sm2_do_sign(const EC_KEY *key, ++ const EVP_MD *digest, ++ const uint8_t *id, ++ const size_t id_len, ++ const uint8_t *msg, size_t msg_len); ++ ++int sm2_do_verify(const EC_KEY *key, ++ const EVP_MD *digest, ++ const ECDSA_SIG *signature, ++ const uint8_t *id, ++ const size_t id_len, ++ const uint8_t *msg, size_t msg_len); ++ ++/* ++ * SM2 signature generation. ++ */ ++int sm2_sign(const unsigned char *dgst, int dgstlen, ++ unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); ++ ++/* ++ * SM2 signature verification. ++ */ ++int sm2_verify(const unsigned char *dgst, int dgstlen, ++ const unsigned char *sig, int siglen, EC_KEY *eckey); ++ ++/* ++ * SM2 encryption ++ */ ++int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, ++ size_t *ct_size); ++ ++int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size); ++ ++int sm2_encrypt(const EC_KEY *key, ++ const EVP_MD *digest, ++ const uint8_t *msg, ++ size_t msg_len, ++ uint8_t *ciphertext_buf, size_t *ciphertext_len); ++ ++int sm2_decrypt(const EC_KEY *key, ++ const EVP_MD *digest, ++ const uint8_t *ciphertext, ++ size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len); ++ ++# endif /* OPENSSL_NO_SM2 */ ++#endif +diff --git a/Cryptlib/Include/openssl/sm2err.h b/Cryptlib/Include/openssl/sm2err.h +new file mode 100644 +index 0000000..251c4f9 +--- /dev/null ++++ b/Cryptlib/Include/openssl/sm2err.h +@@ -0,0 +1,65 @@ ++/* ++ * Generated by util/mkerr.pl DO NOT EDIT ++ * Copyright 1995-2022 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 ++ */ ++ ++#ifndef HEADER_SM2ERR_H ++# define HEADER_SM2ERR_H ++ ++# include ++ ++# include ++ ++# ifndef OPENSSL_NO_SM2 ++ ++# ifdef __cplusplus ++extern "C" ++# endif ++int ERR_load_SM2_strings(void); ++ ++/* ++ * SM2 function codes. ++ */ ++# define SM2_F_PKEY_SM2_COPY 115 ++# define SM2_F_PKEY_SM2_CTRL 109 ++# define SM2_F_PKEY_SM2_CTRL_STR 110 ++# define SM2_F_PKEY_SM2_DIGEST_CUSTOM 114 ++# define SM2_F_PKEY_SM2_INIT 111 ++# define SM2_F_PKEY_SM2_SIGN 112 ++# define SM2_F_SM2_COMPUTE_KEY 116 ++# define SM2_F_SM2_COMPUTE_MSG_HASH 100 ++# define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 ++# define SM2_F_SM2_COMPUTE_Z_DIGEST 113 ++# define SM2_F_SM2_DECRYPT 102 ++# define SM2_F_SM2_ENCRYPT 103 ++# define SM2_F_SM2_PLAINTEXT_SIZE 104 ++# define SM2_F_SM2_SIGN 105 ++# define SM2_F_SM2_SIG_GEN 106 ++# define SM2_F_SM2_SIG_VERIFY 107 ++# define SM2_F_SM2_VERIFY 108 ++ ++/* ++ * SM2 reason codes. ++ */ ++# define SM2_R_ASN1_ERROR 100 ++# define SM2_R_BAD_SIGNATURE 101 ++# define SM2_R_BUFFER_TOO_SMALL 107 ++# define SM2_R_DIST_ID_TOO_LARGE 110 ++# define SM2_R_ID_NOT_SET 112 ++# define SM2_R_ID_TOO_LARGE 111 ++# define SM2_R_INVALID_CURVE 108 ++# define SM2_R_INVALID_DIGEST 102 ++# define SM2_R_INVALID_DIGEST_TYPE 103 ++# define SM2_R_INVALID_ENCODING 104 ++# define SM2_R_INVALID_FIELD 105 ++# define SM2_R_NO_PARAMETERS_SET 109 ++# define SM2_R_NO_PRIVATE_VALUE 113 ++# define SM2_R_USER_ID_TOO_LARGE 106 ++ ++# endif ++#endif +diff --git a/Cryptlib/Include/openssl/sm3.h b/Cryptlib/Include/openssl/sm3.h +new file mode 100644 +index 0000000..97e7460 +--- /dev/null ++++ b/Cryptlib/Include/openssl/sm3.h +@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. 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 ++ */ ++ ++#ifndef OSSL_CRYPTO_SM3_H ++# define OSSL_CRYPTO_SM3_H ++ ++# include ++ ++# ifdef OPENSSL_NO_SM3 ++# error SM3 is disabled. ++# endif ++ ++# define SM3_DIGEST_LENGTH 32 ++# define SM3_WORD unsigned int ++ ++# define SM3_CBLOCK 64 ++# define SM3_LBLOCK (SM3_CBLOCK/4) ++ ++typedef struct SM3state_st { ++ SM3_WORD A, B, C, D, E, F, G, H; ++ SM3_WORD Nl, Nh; ++ SM3_WORD data[SM3_LBLOCK]; ++ unsigned int num; ++} SM3_CTX; ++ ++int sm3_init(SM3_CTX *c); ++int sm3_update(SM3_CTX *c, const void *data, size_t len); ++int sm3_final(unsigned char *md, SM3_CTX *c); ++ ++void sm3_block_data_order(SM3_CTX *c, const void *p, size_t num); ++ ++#endif +diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c +new file mode 100644 +index 0000000..6e06f6a +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c +@@ -0,0 +1,71 @@ ++/* ++ * Generated by util/mkerr.pl DO NOT EDIT ++ * Copyright 1995-2022 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 ++ */ ++ ++#include ++#include ++ ++#ifndef OPENSSL_NO_ERR ++ ++static const ERR_STRING_DATA SM2_str_functs[] = { ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_COPY, 0), "pkey_sm2_copy"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_DIGEST_CUSTOM, 0), ++ "pkey_sm2_digest_custom"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_KEY, 0), "SM2_compute_key"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0), ++ "sm2_compute_msg_hash"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0), ++ "sm2_compute_userid_digest"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0), ++ "sm2_compute_z_digest"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_ENCRYPT, 0), "sm2_encrypt"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_PLAINTEXT_SIZE, 0), "sm2_plaintext_size"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIGN, 0), "sm2_sign"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_GEN, 0), "sm2_sig_gen"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_VERIFY, 0), "sm2_sig_verify"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_VERIFY, 0), "sm2_verify"}, ++ {0, NULL} ++}; ++ ++static const ERR_STRING_DATA SM2_str_reasons[] = { ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_DIST_ID_TOO_LARGE), "dist id too large"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_NOT_SET), "id not set"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_TOO_LARGE), "id too large"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST_TYPE), ++ "invalid digest type"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PRIVATE_VALUE), "no private value"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"}, ++ {0, NULL} ++}; ++ ++#endif ++ ++int ERR_load_SM2_strings(void) ++{ ++#ifndef OPENSSL_NO_ERR ++ if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) { ++ ERR_load_strings_const(SM2_str_functs); ++ ERR_load_strings_const(SM2_str_reasons); ++ } ++#endif ++ return 1; ++} +diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c +new file mode 100644 +index 0000000..b0d9519 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c +@@ -0,0 +1,292 @@ ++/* ++ * Copyright 2006-2021 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 ++ */ ++ ++#include "crypto/cryptlib.h" ++#include ++#include ++#include ++#include ++#include "crypto/evp/evp_locl.h" ++#include ++#include ++ ++/* EC pkey context structure */ ++ ++typedef struct { ++ /* Key and paramgen group */ ++ EC_GROUP *gen_group; ++ /* message digest */ ++ const EVP_MD *md; ++ /* Distinguishing Identifier, ISO/IEC 15946-3 */ ++ uint8_t *id; ++ size_t id_len; ++ /* id_set indicates if the 'id' field is set (1) or not (0) */ ++ int id_set; ++} SM2_PKEY_CTX; ++ ++static int pkey_sm2_init(EVP_PKEY_CTX *ctx) ++{ ++ SM2_PKEY_CTX *smctx; ++ ++ if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) { ++ SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ ctx->data = smctx; ++ return 1; ++} ++ ++static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) ++{ ++ SM2_PKEY_CTX *smctx = ctx->data; ++ ++ if (smctx != NULL) { ++ EC_GROUP_free(smctx->gen_group); ++ OPENSSL_free(smctx->id); ++ OPENSSL_free(smctx); ++ ctx->data = NULL; ++ } ++} ++ ++static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) ++{ ++ SM2_PKEY_CTX *dctx, *sctx; ++ ++ if (!pkey_sm2_init(dst)) ++ return 0; ++ sctx = src->data; ++ dctx = dst->data; ++ if (sctx->gen_group != NULL) { ++ dctx->gen_group = EC_GROUP_dup(sctx->gen_group); ++ if (dctx->gen_group == NULL) { ++ pkey_sm2_cleanup(dst); ++ return 0; ++ } ++ } ++ if (sctx->id != NULL) { ++ dctx->id = OPENSSL_malloc(sctx->id_len); ++ if (dctx->id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE); ++ pkey_sm2_cleanup(dst); ++ return 0; ++ } ++ memcpy(dctx->id, sctx->id, sctx->id_len); ++ } ++ dctx->id_len = sctx->id_len; ++ dctx->id_set = sctx->id_set; ++ dctx->md = sctx->md; ++ ++ return 1; ++} ++ ++static int pkey_sm2_verify(EVP_PKEY_CTX *ctx, ++ const unsigned char *sig, size_t siglen, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ ++ return sm2_verify(tbs, tbslen, sig, siglen, ec); ++} ++ ++static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ++{ ++ SM2_PKEY_CTX *smctx = ctx->data; ++ EC_GROUP *group; ++ uint8_t *tmp_id; ++ ++ switch (type) { ++ case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: ++ group = EC_GROUP_new_by_curve_name(p1); ++ if (group == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE); ++ return 0; ++ } ++ EC_GROUP_free(smctx->gen_group); ++ smctx->gen_group = group; ++ return 1; ++ ++ case EVP_PKEY_CTRL_EC_PARAM_ENC: ++ if (smctx->gen_group == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET); ++ return 0; ++ } ++ EC_GROUP_set_asn1_flag(smctx->gen_group, p1); ++ return 1; ++ ++ case EVP_PKEY_CTRL_MD: ++ smctx->md = p2; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_MD: ++ *(const EVP_MD **)p2 = smctx->md; ++ return 1; ++ ++ case EVP_PKEY_CTRL_SET1_ID: ++ if (p1 > 0) { ++ tmp_id = OPENSSL_malloc(p1); ++ if (tmp_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ memcpy(tmp_id, p2, p1); ++ OPENSSL_free(smctx->id); ++ smctx->id = tmp_id; ++ } else { ++ /* set null-ID */ ++ OPENSSL_free(smctx->id); ++ smctx->id = NULL; ++ } ++ smctx->id_len = (size_t)p1; ++ smctx->id_set = 1; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET1_ID: ++ memcpy(p2, smctx->id, smctx->id_len); ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET1_ID_LEN: ++ *(size_t *)p2 = smctx->id_len; ++ return 1; ++ ++ case EVP_PKEY_CTRL_PKCS7_SIGN: ++ case EVP_PKEY_CTRL_DIGESTINIT: ++ /* nothing to be inited, this is to suppress the error... */ ++ return 1; ++ ++ default: ++ return -2; ++ } ++} ++ ++static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, ++ const char *type, const char *value) ++{ ++ uint8_t *hex_id; ++ long hex_len = 0; ++ int ret = 0; ++ ++ if (strcmp(type, "ec_paramgen_curve") == 0) { ++ int nid = NID_undef; ++ ++ if (((nid = EC_curve_nist2nid(value)) == NID_undef) ++ && ((nid = OBJ_sn2nid(value)) == NID_undef) ++ && ((nid = OBJ_ln2nid(value)) == NID_undef)) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE); ++ return 0; ++ } ++ return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); ++ } else if (strcmp(type, "ec_param_enc") == 0) { ++ int param_enc; ++ ++ if (strcmp(value, "explicit") == 0) ++ param_enc = 0; ++ else if (strcmp(value, "named_curve") == 0) ++ param_enc = OPENSSL_EC_NAMED_CURVE; ++ else ++ return -2; ++ return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); ++ } else if (strcmp(type, "sm2_id") == 0) { ++ return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, ++ (int)strlen(value), (void *)value); ++ } else if (strcmp(type, "sm2_hex_id") == 0) { ++ /* ++ * TODO(3.0): reconsider the name "sm2_hex_id", OR change ++ * OSSL_PARAM_construct_from_text() / OSSL_PARAM_allocate_from_text() ++ * to handle infix "_hex_" ++ */ ++ hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); ++ if (hex_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++ ret = pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len, ++ (void *)hex_id); ++ OPENSSL_free(hex_id); ++ return ret; ++ } ++ ++ return -2; ++} ++ ++static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) ++{ ++ uint8_t z[EVP_MAX_MD_SIZE]; ++ SM2_PKEY_CTX *smctx = ctx->data; ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ const EVP_MD *md = EVP_MD_CTX_md(mctx); ++ int mdlen = EVP_MD_size(md); ++ ++#ifndef OPENSSL_NO_SM2 ++ if (!smctx->id_set) ++ (void)pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, SM2_DEFAULT_USERID_LEN ++ , (void *)SM2_DEFAULT_USERID); ++#endif ++ if (!smctx->id_set) { ++ /* ++ * An ID value must be set. The specifications are not clear whether a ++ * NULL is allowed. We only allow it if set explicitly for maximum ++ * flexibility. ++ */ ++ SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET); ++ return 0; ++ } ++ ++ if (mdlen < 0) { ++ SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST); ++ return 0; ++ } ++ ++ /* get hashed prefix 'z' of tbs message */ ++ if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec)) ++ return 0; ++ ++ return EVP_DigestUpdate(mctx, z, (size_t)mdlen); ++} ++ ++const EVP_PKEY_METHOD sm2_pkey_meth = { ++ EVP_PKEY_SM2, ++ 0, ++ pkey_sm2_init, ++ pkey_sm2_copy, ++ pkey_sm2_cleanup, ++ ++ 0, ++ 0, ++ ++ 0, ++ 0, ++ ++ 0, ++ 0, // pkey_sm2_sign, ++ ++ 0, ++ pkey_sm2_verify, ++ ++ 0, 0, ++ ++ 0, 0, 0, 0, ++ ++ 0, ++ 0, // pkey_sm2_encrypt, ++ ++ 0, ++ 0, // pkey_sm2_decrypt, ++ ++ 0, ++ 0, ++ pkey_sm2_ctrl, ++ pkey_sm2_ctrl_str, ++ ++ 0, 0, ++ ++ 0, 0, 0, ++ ++ pkey_sm2_digest_custom ++}; +diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c +new file mode 100644 +index 0000000..d206f33 +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c +@@ -0,0 +1,325 @@ ++/* ++ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. All Rights Reserved. ++ * Ported from Ribose contributions from Botan. ++ * ++ * 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 ++ */ ++ ++#include ++#include ++#include /* ec_group_do_inverse_ord() */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++int sm2_compute_z_digest(uint8_t *out, ++ const EVP_MD *digest, ++ const uint8_t *id, ++ const size_t id_len, ++ const EC_KEY *key) ++{ ++ int rc = 0; ++ const EC_GROUP *group = EC_KEY_get0_group(key); ++ BN_CTX *ctx = NULL; ++ EVP_MD_CTX *hash = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *a = NULL; ++ BIGNUM *b = NULL; ++ BIGNUM *xG = NULL; ++ BIGNUM *yG = NULL; ++ BIGNUM *xA = NULL; ++ BIGNUM *yA = NULL; ++ int p_bytes = 0; ++ uint8_t *buf = NULL; ++ uint16_t entl = 0; ++ uint8_t e_byte = 0; ++ ++ hash = EVP_MD_CTX_new(); ++ ctx = BN_CTX_new(); ++ if (hash == NULL || ctx == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ p = BN_CTX_get(ctx); ++ a = BN_CTX_get(ctx); ++ b = BN_CTX_get(ctx); ++ xG = BN_CTX_get(ctx); ++ yG = BN_CTX_get(ctx); ++ xA = BN_CTX_get(ctx); ++ yA = BN_CTX_get(ctx); ++ ++ if (yA == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ if (!EVP_DigestInit(hash, digest)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); ++ goto done; ++ } ++ ++ /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ ++ ++ if (id_len >= (UINT16_MAX / 8)) { ++ /* too large */ ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE); ++ goto done; ++ } ++ ++ entl = (uint16_t)(8 * id_len); ++ ++ e_byte = entl >> 8; ++ if (!EVP_DigestUpdate(hash, &e_byte, 1)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); ++ goto done; ++ } ++ e_byte = entl & 0xFF; ++ if (!EVP_DigestUpdate(hash, &e_byte, 1)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); ++ goto done; ++ } ++ ++ if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); ++ goto done; ++ } ++ ++ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB); ++ goto done; ++ } ++ ++ p_bytes = BN_num_bytes(p); ++ buf = OPENSSL_zalloc(p_bytes); ++ if (buf == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ if (BN_bn2bin(a, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2bin(b, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EC_POINT_get_affine_coordinates_GFp(group, ++ EC_GROUP_get0_generator(group), ++ xG, yG, ctx) ++ || BN_bn2bin(xG, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2bin(yG, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EC_POINT_get_affine_coordinates_GFp(group, ++ EC_KEY_get0_public_key(key), ++ xA, yA, ctx) ++ || BN_bn2bin(xA, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2bin(yA, buf) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EVP_DigestFinal(hash, out, NULL)) { ++ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR); ++ goto done; ++ } ++ ++ rc = 1; ++ ++ done: ++ OPENSSL_free(buf); ++ BN_CTX_free(ctx); ++ EVP_MD_CTX_free(hash); ++ return rc; ++} ++ ++static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest, ++ const EC_KEY *key, ++ const uint8_t *id, ++ const size_t id_len, ++ const uint8_t *msg, size_t msg_len) ++{ ++ EVP_MD_CTX *hash = EVP_MD_CTX_new(); ++ const int md_size = EVP_MD_size(digest); ++ uint8_t *z = NULL; ++ BIGNUM *e = NULL; ++ ++ if (md_size < 0) { ++ SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST); ++ goto done; ++ } ++ ++ z = OPENSSL_zalloc(md_size); ++ if (hash == NULL || z == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ if (!sm2_compute_z_digest(z, digest, id, id_len, key)) { ++ /* SM2err already called */ ++ goto done; ++ } ++ ++ if (!EVP_DigestInit(hash, digest) ++ || !EVP_DigestUpdate(hash, z, md_size) ++ || !EVP_DigestUpdate(hash, msg, msg_len) ++ /* reuse z buffer to hold H(Z || M) */ ++ || !EVP_DigestFinal(hash, z, NULL)) { ++ SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB); ++ goto done; ++ } ++ ++ e = BN_bin2bn(z, md_size, NULL); ++ if (e == NULL) ++ SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR); ++ ++ done: ++ OPENSSL_free(z); ++ EVP_MD_CTX_free(hash); ++ return e; ++} ++ ++static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, ++ const BIGNUM *e) ++{ ++ int ret = 0; ++ const EC_GROUP *group = EC_KEY_get0_group(key); ++ const BIGNUM *order = EC_GROUP_get0_order(group); ++ BN_CTX *ctx = NULL; ++ EC_POINT *pt = NULL; ++ BIGNUM *t = NULL; ++ BIGNUM *x1 = NULL; ++ const BIGNUM *r = NULL; ++ const BIGNUM *s = NULL; ++ ++ ctx = BN_CTX_new(); ++ pt = EC_POINT_new(group); ++ if (ctx == NULL || pt == NULL) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ BN_CTX_start(ctx); ++ t = BN_CTX_get(ctx); ++ x1 = BN_CTX_get(ctx); ++ if (x1 == NULL) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ ++ /* ++ * B1: verify whether r' in [1,n-1], verification failed if not ++ * B2: verify whether s' in [1,n-1], verification failed if not ++ * B3: set M'~=ZA || M' ++ * B4: calculate e'=Hv(M'~) ++ * B5: calculate t = (r' + s') modn, verification failed if t=0 ++ * B6: calculate the point (x1', y1')=[s']G + [t]PA ++ * B7: calculate R=(e'+x1') modn, verification pass if yes, otherwise failed ++ */ ++ ++ ECDSA_SIG_get0(sig, &r, &s); ++ ++ if (BN_cmp(r, BN_value_one()) < 0 ++ || BN_cmp(s, BN_value_one()) < 0 ++ || BN_cmp(order, r) <= 0 ++ || BN_cmp(order, s) <= 0) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE); ++ goto done; ++ } ++ ++ if (!BN_mod_add(t, r, s, order, ctx)) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB); ++ goto done; ++ } ++ ++ if (BN_is_zero(t)) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE); ++ goto done; ++ } ++ ++ if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx) ++ || !EC_POINT_get_affine_coordinates_GFp(group, pt, x1, NULL, ctx)) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_EC_LIB); ++ goto done; ++ } ++ ++ if (!BN_mod_add(t, e, x1, order, ctx)) { ++ SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB); ++ goto done; ++ } ++ ++ if (BN_cmp(r, t) == 0) ++ ret = 1; ++ ++ done: ++ EC_POINT_free(pt); ++ BN_CTX_free(ctx); ++ return ret; ++} ++ ++int sm2_do_verify(const EC_KEY *key, ++ const EVP_MD *digest, ++ const ECDSA_SIG *sig, ++ const uint8_t *id, ++ const size_t id_len, ++ const uint8_t *msg, size_t msg_len) ++{ ++ BIGNUM *e = NULL; ++ int ret = 0; ++ ++ e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); ++ if (e == NULL) { ++ /* SM2err already called */ ++ goto done; ++ } ++ ++ ret = sm2_sig_verify(key, sig, e); ++ ++ done: ++ BN_free(e); ++ return ret; ++} ++ ++int sm2_verify(const unsigned char *dgst, int dgstlen, ++ const unsigned char *sig, int sig_len, EC_KEY *eckey) ++{ ++ ECDSA_SIG *s = NULL; ++ BIGNUM *e = NULL; ++ const unsigned char *p = sig; ++ unsigned char *der = NULL; ++ int derlen = -1; ++ int ret = -1; ++ ++ s = ECDSA_SIG_new(); ++ if (s == NULL) { ++ SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE); ++ goto done; ++ } ++ if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { ++ SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING); ++ goto done; ++ } ++ /* Ensure signature uses DER and doesn't have trailing garbage */ ++ derlen = i2d_ECDSA_SIG(s, &der); ++ if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { ++ SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING); ++ goto done; ++ } ++ ++ e = BN_bin2bn(dgst, dgstlen, NULL); ++ if (e == NULL) { ++ SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB); ++ goto done; ++ } ++ ++ ret = sm2_sig_verify(eckey, s, e); ++ ++ done: ++ OPENSSL_free(der); ++ BN_free(e); ++ ECDSA_SIG_free(s); ++ return ret; ++} +diff --git a/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c b/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c +new file mode 100644 +index 0000000..d429b8c +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c +@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. 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 ++ */ ++ ++#include "cryptlib.h" ++ ++#ifndef OPENSSL_NO_SM3 ++# include ++# include ++ ++static int init(EVP_MD_CTX *ctx) ++{ ++ return sm3_init(EVP_MD_CTX_md_data(ctx)); ++} ++ ++static int update(EVP_MD_CTX *ctx, const void *data, size_t count) ++{ ++ return sm3_update(EVP_MD_CTX_md_data(ctx), data, count); ++} ++ ++static int final(EVP_MD_CTX *ctx, unsigned char *md) ++{ ++ return sm3_final(md, EVP_MD_CTX_md_data(ctx)); ++} ++ ++static const EVP_MD sm3_md = { ++ NID_sm3, ++ NID_sm3WithRSAEncryption, ++ SM3_DIGEST_LENGTH, ++ 0, ++ init, ++ update, ++ final, ++ NULL, ++ NULL, ++ EVP_PKEY_NULL_method, ++ SM3_CBLOCK, ++ sizeof(EVP_MD *) + sizeof(SM3_CTX), ++}; ++ ++const EVP_MD *EVP_sm3(void) ++{ ++ return &sm3_md; ++} ++ ++#endif +diff --git a/Cryptlib/OpenSSL/crypto/sm3/sm3.c b/Cryptlib/OpenSSL/crypto/sm3/sm3.c +new file mode 100644 +index 0000000..d78292b +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm3/sm3.c +@@ -0,0 +1,196 @@ ++/* ++ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. All Rights Reserved. ++ * Ported from Ribose contributions from Botan. ++ * ++ * 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 ++ */ ++ ++#include ++#include "sm3_local.h" ++ ++int sm3_init(SM3_CTX *c) ++{ ++ memset(c, 0, sizeof(*c)); ++ c->A = SM3_A; ++ c->B = SM3_B; ++ c->C = SM3_C; ++ c->D = SM3_D; ++ c->E = SM3_E; ++ c->F = SM3_F; ++ c->G = SM3_G; ++ c->H = SM3_H; ++ return 1; ++} ++ ++void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) ++{ ++ const unsigned char *data = p; ++ register unsigned MD32_REG_T A, B, C, D, E, F, G, H; ++ ++ unsigned MD32_REG_T W00, W01, W02, W03, W04, W05, W06, W07, ++ W08, W09, W10, W11, W12, W13, W14, W15; ++ ++ for (; num--;) { ++ ++ A = ctx->A; ++ B = ctx->B; ++ C = ctx->C; ++ D = ctx->D; ++ E = ctx->E; ++ F = ctx->F; ++ G = ctx->G; ++ H = ctx->H; ++ ++ /* ++ * We have to load all message bytes immediately since SM3 reads ++ * them slightly out of order. ++ */ ++ (void)HOST_c2l(data, W00); ++ (void)HOST_c2l(data, W01); ++ (void)HOST_c2l(data, W02); ++ (void)HOST_c2l(data, W03); ++ (void)HOST_c2l(data, W04); ++ (void)HOST_c2l(data, W05); ++ (void)HOST_c2l(data, W06); ++ (void)HOST_c2l(data, W07); ++ (void)HOST_c2l(data, W08); ++ (void)HOST_c2l(data, W09); ++ (void)HOST_c2l(data, W10); ++ (void)HOST_c2l(data, W11); ++ (void)HOST_c2l(data, W12); ++ (void)HOST_c2l(data, W13); ++ (void)HOST_c2l(data, W14); ++ (void)HOST_c2l(data, W15); ++ ++ R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04); ++ W00 = EXPAND(W00, W07, W13, W03, W10); ++ R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05); ++ W01 = EXPAND(W01, W08, W14, W04, W11); ++ R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06); ++ W02 = EXPAND(W02, W09, W15, W05, W12); ++ R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07); ++ W03 = EXPAND(W03, W10, W00, W06, W13); ++ R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08); ++ W04 = EXPAND(W04, W11, W01, W07, W14); ++ R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09); ++ W05 = EXPAND(W05, W12, W02, W08, W15); ++ R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10); ++ W06 = EXPAND(W06, W13, W03, W09, W00); ++ R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11); ++ W07 = EXPAND(W07, W14, W04, W10, W01); ++ R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12); ++ W08 = EXPAND(W08, W15, W05, W11, W02); ++ R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13); ++ W09 = EXPAND(W09, W00, W06, W12, W03); ++ R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14); ++ W10 = EXPAND(W10, W01, W07, W13, W04); ++ R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15); ++ W11 = EXPAND(W11, W02, W08, W14, W05); ++ R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00); ++ W12 = EXPAND(W12, W03, W09, W15, W06); ++ R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01); ++ W13 = EXPAND(W13, W04, W10, W00, W07); ++ R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02); ++ W14 = EXPAND(W14, W05, W11, W01, W08); ++ R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03); ++ W15 = EXPAND(W15, W06, W12, W02, W09); ++ R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); ++ W00 = EXPAND(W00, W07, W13, W03, W10); ++ R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); ++ W01 = EXPAND(W01, W08, W14, W04, W11); ++ R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); ++ W02 = EXPAND(W02, W09, W15, W05, W12); ++ R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); ++ W03 = EXPAND(W03, W10, W00, W06, W13); ++ R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); ++ W04 = EXPAND(W04, W11, W01, W07, W14); ++ R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); ++ W05 = EXPAND(W05, W12, W02, W08, W15); ++ R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); ++ W06 = EXPAND(W06, W13, W03, W09, W00); ++ R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); ++ W07 = EXPAND(W07, W14, W04, W10, W01); ++ R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); ++ W08 = EXPAND(W08, W15, W05, W11, W02); ++ R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); ++ W09 = EXPAND(W09, W00, W06, W12, W03); ++ R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); ++ W10 = EXPAND(W10, W01, W07, W13, W04); ++ R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); ++ W11 = EXPAND(W11, W02, W08, W14, W05); ++ R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); ++ W12 = EXPAND(W12, W03, W09, W15, W06); ++ R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); ++ W13 = EXPAND(W13, W04, W10, W00, W07); ++ R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); ++ W14 = EXPAND(W14, W05, W11, W01, W08); ++ R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); ++ W15 = EXPAND(W15, W06, W12, W02, W09); ++ R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04); ++ W00 = EXPAND(W00, W07, W13, W03, W10); ++ R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05); ++ W01 = EXPAND(W01, W08, W14, W04, W11); ++ R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06); ++ W02 = EXPAND(W02, W09, W15, W05, W12); ++ R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07); ++ W03 = EXPAND(W03, W10, W00, W06, W13); ++ R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08); ++ W04 = EXPAND(W04, W11, W01, W07, W14); ++ R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09); ++ W05 = EXPAND(W05, W12, W02, W08, W15); ++ R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10); ++ W06 = EXPAND(W06, W13, W03, W09, W00); ++ R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11); ++ W07 = EXPAND(W07, W14, W04, W10, W01); ++ R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12); ++ W08 = EXPAND(W08, W15, W05, W11, W02); ++ R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13); ++ W09 = EXPAND(W09, W00, W06, W12, W03); ++ R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14); ++ W10 = EXPAND(W10, W01, W07, W13, W04); ++ R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15); ++ W11 = EXPAND(W11, W02, W08, W14, W05); ++ R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00); ++ W12 = EXPAND(W12, W03, W09, W15, W06); ++ R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01); ++ W13 = EXPAND(W13, W04, W10, W00, W07); ++ R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02); ++ W14 = EXPAND(W14, W05, W11, W01, W08); ++ R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03); ++ W15 = EXPAND(W15, W06, W12, W02, W09); ++ R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); ++ W00 = EXPAND(W00, W07, W13, W03, W10); ++ R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); ++ W01 = EXPAND(W01, W08, W14, W04, W11); ++ R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); ++ W02 = EXPAND(W02, W09, W15, W05, W12); ++ R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); ++ W03 = EXPAND(W03, W10, W00, W06, W13); ++ R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); ++ R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); ++ R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); ++ R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); ++ R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); ++ R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); ++ R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); ++ R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); ++ R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); ++ R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); ++ R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); ++ R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); ++ ++ ctx->A ^= A; ++ ctx->B ^= B; ++ ctx->C ^= C; ++ ctx->D ^= D; ++ ctx->E ^= E; ++ ctx->F ^= F; ++ ctx->G ^= G; ++ ctx->H ^= H; ++ } ++} ++ +diff --git a/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h b/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h +new file mode 100644 +index 0000000..dfb7bfb +--- /dev/null ++++ b/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h +@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2017 Ribose Inc. All Rights Reserved. ++ * Ported from Ribose contributions from Botan. ++ * ++ * 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 ++ */ ++ ++#include ++#include ++ ++#define DATA_ORDER_IS_BIG_ENDIAN ++ ++#define HASH_LONG SM3_WORD ++#define HASH_CTX SM3_CTX ++#define HASH_CBLOCK SM3_CBLOCK ++#define HASH_UPDATE sm3_update ++#define HASH_TRANSFORM sm3_transform ++#define HASH_FINAL sm3_final ++#define HASH_MAKE_STRING(c, s) \ ++ do { \ ++ unsigned long ll; \ ++ ll=(c)->A; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->B; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->C; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->D; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->E; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->F; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->G; (void)HOST_l2c(ll, (s)); \ ++ ll=(c)->H; (void)HOST_l2c(ll, (s)); \ ++ } while (0) ++#define HASH_BLOCK_DATA_ORDER sm3_block_data_order ++ ++void sm3_transform(SM3_CTX *c, const unsigned char *data); ++ ++#include "crypto/md32_common.h" ++ ++#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) ++#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) ++ ++#define FF0(X,Y,Z) (X ^ Y ^ Z) ++#define GG0(X,Y,Z) (X ^ Y ^ Z) ++ ++#define FF1(X,Y,Z) ((X & Y) | ((X | Y) & Z)) ++#define GG1(X,Y,Z) ((Z ^ (X & (Y ^ Z)))) ++ ++#define EXPAND(W0,W7,W13,W3,W10) \ ++ (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10) ++ ++#define RND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG) \ ++ do { \ ++ const SM3_WORD A12 = ROTATE(A, 12); \ ++ const SM3_WORD A12_SM = A12 + E + TJ; \ ++ const SM3_WORD SS1 = ROTATE(A12_SM, 7); \ ++ const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj); \ ++ const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi; \ ++ B = ROTATE(B, 9); \ ++ D = TT1; \ ++ F = ROTATE(F, 19); \ ++ H = P0(TT2); \ ++ } while(0) ++ ++#define R1(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \ ++ RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF0,GG0) ++ ++#define R2(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \ ++ RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF1,GG1) ++ ++#define SM3_A 0x7380166fUL ++#define SM3_B 0x4914b2b9UL ++#define SM3_C 0x172442d7UL ++#define SM3_D 0xda8a0600UL ++#define SM3_E 0xa96f30bcUL ++#define SM3_F 0x163138aaUL ++#define SM3_G 0xe38dee4dUL ++#define SM3_H 0xb0fb0e4eUL +-- +2.33.0 + diff --git a/Feature-shim-support-sm2-and-sm3-algorithm.patch b/Feature-shim-support-sm2-and-sm3-algorithm.patch new file mode 100644 index 0000000000000000000000000000000000000000..d43769accdfa2885ac836ddac7d3e9d9e65c788d --- /dev/null +++ b/Feature-shim-support-sm2-and-sm3-algorithm.patch @@ -0,0 +1,589 @@ +From b56474e6f7d0ddece0f5dd87e410f8f482f66a58 Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Mon, 7 Nov 2022 11:47:42 +0800 +Subject: [PATCH 5/5] shim support sm2 and sm3 algorithm + +Co-authored-by: Yusong Gao +Signed-off-by: Yusong Gao +Signed-off-by: Huaxin Lu +--- + Makefile | 2 +- + MokManager.c | 8 ++++ + include/pe.h | 7 ++++ + include/peimage.h | 3 ++ + pe.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ + shim.c | 73 +++++++++++++++++++++++++++++++-- + shim.h | 20 ++++++++++ + 7 files changed, 208 insertions(+), 5 deletions(-) + +diff --git a/Makefile b/Makefile +index 24ac314..8876f9f 100644 +--- a/Makefile ++++ b/Makefile +@@ -163,7 +163,7 @@ Cryptlib/libcryptlib.a: + $(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile + + Cryptlib/OpenSSL/libopenssl.a: +- for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done ++ for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes ec sm3 sm2 ecdsa; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done + $(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile + + lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch]) +diff --git a/MokManager.c b/MokManager.c +index ffcd6a6..8b7fd4b 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1910,6 +1910,9 @@ static EFI_STATUS enroll_file(void *data, UINTN datasize, BOOLEAN hash) + if (hash) { + UINT8 sha256[SHA256_DIGEST_SIZE]; + UINT8 sha1[SHA1_DIGEST_SIZE]; ++#ifdef ENABLE_SHIM_SM ++ UINT8 sm3[SM3_DIGEST_SIZE]; ++#endif + SHIM_LOCK *shim_lock; + PE_COFF_LOADER_IMAGE_CONTEXT context; + +@@ -1929,8 +1932,13 @@ static EFI_STATUS enroll_file(void *data, UINTN datasize, BOOLEAN hash) + if (EFI_ERROR(efi_status)) + goto out; + ++#ifdef ENABLE_SHIM_SM ++ efi_status = shim_lock->Hash(data, datasize, &context, sha256, ++ sha1, sm3); ++#else + efi_status = shim_lock->Hash(data, datasize, &context, sha256, + sha1); ++#endif + if (EFI_ERROR(efi_status)) + goto out; + +diff --git a/include/pe.h b/include/pe.h +index ccc8798..93af091 100644 +--- a/include/pe.h ++++ b/include/pe.h +@@ -28,10 +28,17 @@ handle_image (void *data, unsigned int datasize, + EFI_PHYSICAL_ADDRESS *alloc_address, + UINTN *alloc_pages); + ++#ifdef ENABLE_SHIM_SM ++EFI_STATUS ++generate_hash (char *data, unsigned int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash); ++#else + EFI_STATUS + generate_hash (char *data, unsigned int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash); ++#endif + + EFI_STATUS + relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, +diff --git a/include/peimage.h b/include/peimage.h +index e97b29c..7a4f356 100644 +--- a/include/peimage.h ++++ b/include/peimage.h +@@ -807,6 +807,9 @@ typedef struct { + + #define SHA1_DIGEST_SIZE 20 + #define SHA256_DIGEST_SIZE 32 ++#ifdef ENABLE_SHIM_SM ++#define SM3_DIGEST_SIZE 32 ++#endif + #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 + + typedef struct { +diff --git a/pe.c b/pe.c +index ba3e2bb..37b08a3 100644 +--- a/pe.c ++++ b/pe.c +@@ -297,13 +297,24 @@ get_section_vma_by_name (char *name, size_t namesz, + * Calculate the SHA1 and SHA256 hashes of a binary + */ + ++#ifdef ENABLE_SHIM_SM ++EFI_STATUS ++generate_hash(char *data, unsigned int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash, ++ UINT8 *sha1hash, UINT8 *sm3hash) ++#else + EFI_STATUS + generate_hash(char *data, unsigned int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash, + UINT8 *sha1hash) ++#endif + { + unsigned int sha256ctxsize, sha1ctxsize; + void *sha256ctx = NULL, *sha1ctx = NULL; ++#ifdef ENABLE_SHIM_SM ++ unsigned int sm3ctxsize; ++ void *sm3ctx = NULL; ++#endif + char *hashbase; + unsigned int hashsize; + unsigned int SumOfBytesHashed, SumOfSectionBytes; +@@ -327,12 +338,25 @@ generate_hash(char *data, unsigned int datasize, + sha1ctxsize = Sha1GetContextSize(); + sha1ctx = AllocatePool(sha1ctxsize); + ++#ifdef SHIM_ENABLE_SM ++ sm3ctxsize = Sm3GetContextSize(); ++ sm3ctx = AllocatePool(sm3ctxsize); ++#endif ++ ++#ifdef SHIM_ENABLE_SM ++ if (!sha256ctx || !sha1ctx || !sm3ctx) { ++#else + if (!sha256ctx || !sha1ctx) { ++#endif + perror(L"Unable to allocate memory for hash context\n"); + return EFI_OUT_OF_RESOURCES; + } + ++#ifdef SHIM_ENABLE_SM ++ if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx) || !Sm3Init(sm3ctx)) { ++#else + if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) { ++#endif + perror(L"Unable to initialise hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -344,8 +368,14 @@ generate_hash(char *data, unsigned int datasize, + hashbase; + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -357,8 +387,14 @@ generate_hash(char *data, unsigned int datasize, + hashsize = (char *)context->SecDir - hashbase; + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -375,8 +411,14 @@ generate_hash(char *data, unsigned int datasize, + } + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -505,8 +547,14 @@ generate_hash(char *data, unsigned int datasize, + hashsize = (unsigned int) Section->SizeOfRawData; + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -531,8 +579,14 @@ generate_hash(char *data, unsigned int datasize, + } + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -551,8 +605,14 @@ generate_hash(char *data, unsigned int datasize, + + check_size(data, datasize, hashbase, hashsize); + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || ++ !(Sha1Update(sha1ctx, hashbase, hashsize)) || ++ !(Sm3Update(sm3ctx, hashbase, hashsize))) { ++#else + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { ++#endif + perror(L"Unable to generate hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -562,8 +622,14 @@ generate_hash(char *data, unsigned int datasize, + } + #endif + ++#ifdef SHIM_ENABLE_SM ++ if (!(Sha256Final(sha256ctx, sha256hash)) || ++ !(Sha1Final(sha1ctx, sha1hash)) || ++ !(Sm3Final(sm3ctx, sm3hash))) { ++#else + if (!(Sha256Final(sha256ctx, sha256hash)) || + !(Sha1Final(sha1ctx, sha1hash))) { ++#endif + perror(L"Unable to finalise hash\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto done; +@@ -573,6 +639,10 @@ generate_hash(char *data, unsigned int datasize, + dhexdumpat(sha1hash, SHA1_DIGEST_SIZE, 0); + dprint(L"sha256 authenticode hash:\n"); + dhexdumpat(sha256hash, SHA256_DIGEST_SIZE, 0); ++#ifdef SHIM_ENABLE_SM ++ dprint(L"sm3 authenticode hash:\n"); ++ dhexdumpat(sm3hash, SM3_DIGEST_SIZE, 0); ++#endif + + done: + if (SectionHeader) +@@ -581,6 +651,10 @@ done: + FreePool(sha1ctx); + if (sha256ctx) + FreePool(sha256ctx); ++#ifdef SHIM_ENABLE_SM ++ if (sm3ctx) ++ FreePool(sm3ctx); ++#endif + + return efi_status; + } +@@ -1027,6 +1101,9 @@ EFI_STATUS verify_image(void *data, unsigned int datasize, + EFI_STATUS efi_status; + UINT8 sha1hash[SHA1_DIGEST_SIZE]; + UINT8 sha256hash[SHA256_DIGEST_SIZE]; ++#ifdef SHIM_ENABLE_SM ++ UINT8 sm3hash[SHA256_DIGEST_SIZE]; ++#endif + + /* + * The binary header contains relevant context and section pointers +@@ -1042,8 +1119,13 @@ EFI_STATUS verify_image(void *data, unsigned int datasize, + * in order to load it. + */ + if (secure_mode()) { ++#ifdef SHIM_ENABLE_SM ++ efi_status = verify_buffer(data, datasize, ++ context, sha256hash, sha1hash, sm3hash); ++#else + efi_status = verify_buffer(data, datasize, + context, sha256hash, sha1hash); ++#endif + if (EFI_ERROR(efi_status)) { + if (verbose) + console_print(L"Verification failed: %r\n", efi_status); +@@ -1061,8 +1143,13 @@ EFI_STATUS verify_image(void *data, unsigned int datasize, + * this is only useful for the TPM1.2 case. We should try to fix + * this in a follow-up. + */ ++#ifdef SHIM_ENABLE_SM ++ efi_status = generate_hash(data, datasize, context, sha256hash, ++ sha1hash, sm3hash); ++#else + efi_status = generate_hash(data, datasize, context, sha256hash, + sha1hash); ++#endif + if (EFI_ERROR(efi_status)) + return efi_status; + +@@ -1103,6 +1190,9 @@ handle_image (void *data, unsigned int datasize, + int found_entry_point = 0; + UINT8 sha1hash[SHA1_DIGEST_SIZE]; + UINT8 sha256hash[SHA256_DIGEST_SIZE]; ++#ifdef SHIM_ENABLE_SM ++ UINT8 sm3hash[SM3_DIGEST_SIZE]; ++#endif + + /* + * The binary header contains relevant context and section pointers +@@ -1118,8 +1208,13 @@ handle_image (void *data, unsigned int datasize, + * in order to load it. + */ + if (secure_mode ()) { ++#ifdef SHIM_ENABLE_SM ++ efi_status = verify_buffer(data, datasize, &context, sha256hash, ++ sha1hash, sm3hash); ++#else + efi_status = verify_buffer(data, datasize, &context, sha256hash, + sha1hash); ++#endif + + if (EFI_ERROR(efi_status)) { + if (verbose) +@@ -1140,8 +1235,13 @@ handle_image (void *data, unsigned int datasize, + * this is only useful for the TPM1.2 case. We should try to fix + * this in a follow-up. + */ ++#ifdef SHIM_ENABLE_SM ++ efi_status = generate_hash(data, datasize, &context, sha256hash, ++ sha1hash, sm3hash); ++#else + efi_status = generate_hash(data, datasize, &context, sha256hash, + sha1hash); ++#endif + if (EFI_ERROR(efi_status)) + return efi_status; + +diff --git a/shim.c b/shim.c +index fdd205e..5662ca8 100644 +--- a/shim.c ++++ b/shim.c +@@ -458,11 +458,20 @@ BOOLEAN secure_mode (void) + return TRUE; + } + ++#ifdef ENABLE_SHIM_SM ++static EFI_STATUS ++verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash) ++#else + static EFI_STATUS + verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig, + UINT8 *sha256hash, UINT8 *sha1hash) ++#endif + { + EFI_STATUS efi_status; ++#ifdef ENABLE_SHIM_SM ++ sm3hash = sm3hash; ++#endif + + /* + * Ensure that the binary isn't forbidden +@@ -533,10 +542,15 @@ verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig, + dprint("verifying against vendor_cert\n"); + } + if (vendor_cert_size && +- AuthenticodeVerify(sig->CertData, +- sig->Hdr.dwLength - sizeof(sig->Hdr), +- vendor_cert, vendor_cert_size, +- sha256hash, SHA256_DIGEST_SIZE)) { ++#ifdef ENABLE_SHIM_SM ++ (AuthenticodeVerify(sig->CertData, sig->Hdr.dwLength - sizeof(sig->Hdr), ++ vendor_cert, vendor_cert_size, sha256hash, SHA256_DIGEST_SIZE) || ++ AuthenticodeVerify(sig->CertData, sig->Hdr.dwLength - sizeof(sig->Hdr), ++ vendor_cert, vendor_cert_size, sm3hash, SM3_DIGEST_SIZE))) { ++#else ++ (AuthenticodeVerify(sig->CertData, sig->Hdr.dwLength - sizeof(sig->Hdr), ++ vendor_cert, vendor_cert_size, sha256hash, SHA256_DIGEST_SIZE)) { ++#endif + dprint(L"AuthenticodeVerify(vendor_cert) succeeded\n"); + update_verification_method(VERIFIED_BY_CERT); + tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, +@@ -558,10 +572,17 @@ verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig, + /* + * Check that the signature is valid and matches the binary + */ ++#ifdef ENABLE_SHIM_SM ++EFI_STATUS ++verify_buffer_authenticode (char *data, int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash) ++#else + EFI_STATUS + verify_buffer_authenticode (char *data, int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash) ++#endif + { + EFI_STATUS ret_efi_status; + size_t size = datasize; +@@ -578,7 +599,12 @@ verify_buffer_authenticode (char *data, int datasize, + */ + drain_openssl_errors(); + ++#ifdef ENABLE_SHIM_SM ++ ret_efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash, sm3hash); ++#else + ret_efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash); ++#endif ++ + if (EFI_ERROR(ret_efi_status)) { + dprint(L"generate_hash: %r\n", ret_efi_status); + PrintErrors(); +@@ -665,7 +691,11 @@ verify_buffer_authenticode (char *data, int datasize, + + dprint(L"Attempting to verify signature %d:\n", i++); + ++#ifdef ENABLE_SHIM_SM ++ efi_status = verify_one_signature(sig, sha256hash, sha1hash, sm3hash); ++#else + efi_status = verify_one_signature(sig, sha256hash, sha1hash); ++#endif + + /* + * If we didn't get EFI_SECURITY_VIOLATION from +@@ -746,10 +776,17 @@ verify_buffer_sbat (char *data, int datasize, + * Check that the signature is valid and matches the binary and that + * the binary is permitted to load by SBAT. + */ ++#ifdef ENABLE_SHIM_SM ++EFI_STATUS ++verify_buffer (char *data, int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash) ++#else + EFI_STATUS + verify_buffer (char *data, int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash) ++#endif + { + EFI_STATUS efi_status; + +@@ -757,7 +794,11 @@ verify_buffer (char *data, int datasize, + if (EFI_ERROR(efi_status)) + return efi_status; + ++#ifdef ENABLE_SHIM_SM ++ return verify_buffer_authenticode(data, datasize, context, sha256hash, sha1hash, sm3hash); ++#else + return verify_buffer_authenticode(data, datasize, context, sha256hash, sha1hash); ++#endif + } + + static int +@@ -970,6 +1011,9 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) + PE_COFF_LOADER_IMAGE_CONTEXT context; + UINT8 sha1hash[SHA1_DIGEST_SIZE]; + UINT8 sha256hash[SHA256_DIGEST_SIZE]; ++#ifdef ENABLE_SHIM_SM ++ UINT8 sm3hash[SM3_DIGEST_SIZE]; ++#endif + + if ((INT32)size < 0) + return EFI_INVALID_PARAMETER; +@@ -981,8 +1025,13 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) + if (EFI_ERROR(efi_status)) + goto done; + ++#ifdef ENABLE_SHIM_SM ++ efi_status = generate_hash(buffer, size, &context, ++ sha256hash, sha1hash, sm3hash); ++#else + efi_status = generate_hash(buffer, size, &context, + sha256hash, sha1hash); ++#endif + if (EFI_ERROR(efi_status)) + goto done; + +@@ -1002,16 +1051,27 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) + goto done; + } + ++#ifdef ENABLE_SHIM_SM ++ efi_status = verify_buffer(buffer, size, ++ &context, sha256hash, sha1hash, sm3hash); ++#else + efi_status = verify_buffer(buffer, size, + &context, sha256hash, sha1hash); ++#endif + done: + in_protocol = 0; + return efi_status; + } + ++#ifdef ENABLE_SHIM_SM ++static EFI_STATUS shim_hash (char *data, int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash) ++#else + static EFI_STATUS shim_hash (char *data, int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash) ++#endif + { + EFI_STATUS efi_status; + +@@ -1019,8 +1079,13 @@ static EFI_STATUS shim_hash (char *data, int datasize, + return EFI_INVALID_PARAMETER; + + in_protocol = 1; ++#ifdef ENABLE_SHIM_SM ++ efi_status = generate_hash(data, datasize, context, ++ sha256hash, sha1hash, sm3hash); ++#else + efi_status = generate_hash(data, datasize, context, + sha256hash, sha1hash); ++#endif + in_protocol = 0; + + return efi_status; +diff --git a/shim.h b/shim.h +index b5272b9..b9aa982 100644 +--- a/shim.h ++++ b/shim.h +@@ -208,6 +208,18 @@ EFI_STATUS + IN UINT32 size + ); + ++#ifdef ENABLE_SHIM_SM ++typedef ++EFI_STATUS ++(*EFI_SHIM_LOCK_HASH) ( ++ IN char *data, ++ IN int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, ++ UINT8 *sha1hash, ++ UINT8 *sm3hash ++ ); ++#else + typedef + EFI_STATUS + (*EFI_SHIM_LOCK_HASH) ( +@@ -217,6 +229,7 @@ EFI_STATUS + UINT8 *sha256hash, + UINT8 *sha1hash + ); ++#endif + + typedef + EFI_STATUS +@@ -271,10 +284,17 @@ extern UINT32 load_options_size; + + BOOLEAN secure_mode (void); + ++#ifdef ENABLE_SHIM_SM ++EFI_STATUS ++verify_buffer (char *data, int datasize, ++ PE_COFF_LOADER_IMAGE_CONTEXT *context, ++ UINT8 *sha256hash, UINT8 *sha1hash, UINT8 *sm3hash); ++#else + EFI_STATUS + verify_buffer (char *data, int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash); ++#endif + + #ifndef SHIM_UNIT_TEST + #define perror_(file, line, func, fmt, ...) ({ \ +-- +2.33.0 + diff --git a/shim.spec b/shim.spec index 73523dec33c724fbdf4cb029ccf88445ba8f7ec3..ef474bd780c203cebe38c131f86440f7633e6ac1 100644 --- a/shim.spec +++ b/shim.spec @@ -22,7 +22,7 @@ Name: shim Version: 15.6 -Release: 2 +Release: 3 Summary: First-stage UEFI bootloader ExclusiveArch: x86_64 aarch64 License: BSD @@ -31,7 +31,12 @@ Source0: https://github.com/rhboot/shim/releases/download/%{version}/shim-%{v Source1: BOOTAA64.CSV Source2: BOOTX64.CSV -Patch9000: Feature-shim-support-SMx-verify.patch +# Feature for shim SMx support +Patch9000:Feature-shim-openssl-add-ec-support.patch +Patch9001:Feature-shim-openssl-add-ecdsa-support.patch +Patch9002:Feature-shim-openssl-add-sm2-and-sm3-support.patch +Patch9003:Feature-shim-cryptlib-support-sm2-signature-verify.patch +Patch9004:Feature-shim-support-sm2-and-sm3-algorithm.patch BuildRequires: elfutils-libelf-devel openssl-devel openssl git pesign gnu-efi gnu-efi-devel gcc Requires: dbxtool efi-filesystem mokutil @@ -136,6 +141,9 @@ cd .. /usr/src/debug/%{name}-%{version}-%{release}/* %changelog +* Tue Nov 8 2022 luhuaxin - 15.6-3 +- Optimize patches for SMx feature + * Mon Oct 31 2022 luhuaxin - 15.6-2 - Feature: shim support SM2 and SM3