14561 lines
474 KiB
Diff
14561 lines
474 KiB
Diff
From 5589c21862f49f682d55c321389cd6f631972564 Mon Sep 17 00:00:00 2001
|
|
From: Huaxin Lu <luhuaxin1@huawei.com>
|
|
Date: Tue, 18 Oct 2022 12:50:09 +0800
|
|
Subject: [PATCH] shim support sm verify
|
|
|
|
Co-authored-by: Yusong Gao <gaoyusong2@huawei.com>
|
|
Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
|
|
---
|
|
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/sm2.h | 79 ++
|
|
Cryptlib/Include/openssl/sm2err.h | 65 +
|
|
Cryptlib/Include/openssl/sm3.h | 39 +
|
|
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/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 ++++++++++++++++++++
|
|
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 ++
|
|
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/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 ++
|
|
Cryptlib/OpenSSL/crypto/x509/x_all.c | 142 ++
|
|
Cryptlib/Pk/CryptPkcs7Verify.c | 5 +
|
|
Makefile | 2 +-
|
|
MokManager.c | 8 +
|
|
include/pe.h | 7 +
|
|
include/peimage.h | 3 +
|
|
pe.c | 100 ++
|
|
shim.c | 73 +-
|
|
shim.h | 20 +
|
|
73 files changed, 13094 insertions(+), 43 deletions(-)
|
|
create mode 100644 Cryptlib/Hash/CryptSm3.c
|
|
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/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
|
|
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
|
|
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/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.<BR>
|
|
+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 <openssl/sm3.h>
|
|
+
|
|
+/**
|
|
+ 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/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 <openssl/opensslconf.h>
|
|
+
|
|
+# ifndef OPENSSL_NO_SM2
|
|
+
|
|
+# include <openssl/ec.h>
|
|
+# include <openssl/ecdsa.h>
|
|
+
|
|
+/* 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 <openssl/symhacks.h>
|
|
+
|
|
+# include <openssl/opensslconf.h>
|
|
+
|
|
+# 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 <openssl/opensslconf.h>
|
|
+
|
|
+# 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/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 <openssl/engine.h>
|
|
#endif
|
|
#include "asn1_locl.h"
|
|
+#include <openssl/evp.h>
|
|
|
|
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/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 <stdio.h>
|
|
+#include "cryptlib.h"
|
|
+#include <openssl/x509.h>
|
|
+#include <openssl/ec.h>
|
|
+#include <openssl/bn.h>
|
|
+#include <openssl/asn1t.h>
|
|
+#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 <string.h>
|
|
+#include "ec_lcl.h"
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/asn1t.h>
|
|
+#include <openssl/objects.h>
|
|
+
|
|
+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 <openssl/err.h>
|
|
+
|
|
+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 <string.h>
|
|
+#include "ec_lcl.h"
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/obj_mac.h>
|
|
+#include <openssl/opensslconf.h>
|
|
+
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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 <openssl/err.h>
|
|
+#include "ec_lcl.h"
|
|
+
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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...
|
|
+ * <appro>
|
|
+ */
|
|
+ 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 <stdio.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/ec.h>
|
|
+
|
|
+/* 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 <string.h>
|
|
+#include "ec_lcl.h"
|
|
+#include <openssl/err.h>
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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 <stdlib.h>
|
|
+
|
|
+#include <openssl/obj_mac.h>
|
|
+#include <openssl/ec.h>
|
|
+#include <openssl/bn.h>
|
|
+
|
|
+#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 <string.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/opensslv.h>
|
|
+
|
|
+#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 <string.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+
|
|
+#include "ec_lcl.h"
|
|
+
|
|
+/*
|
|
+ * This file implements the wNAF-based interleaving multi-exponentation method
|
|
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
|
|
+ * for multiplication with precomputation, we use wNAF splitting
|
|
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
|
|
+ */
|
|
+
|
|
+/* 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 <string.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/opensslv.h>
|
|
+
|
|
+#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 <stdio.h>
|
|
+#include "cryptlib.h"
|
|
+#include <openssl/asn1t.h>
|
|
+#include <openssl/x509.h>
|
|
+#include <openssl/ec.h>
|
|
+#include "ec_lcl.h"
|
|
+#include <openssl/ecdsa.h>
|
|
+#include <openssl/evp.h>
|
|
+#include "evp_locl.h"
|
|
+#include <openssl/sm2.h>
|
|
+
|
|
+/* 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 <openssl/crypto.h>
|
|
+#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 <stdio.h>
|
|
+#include "cryptlib.h"
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/ec.h>
|
|
+#include <openssl/bn.h>
|
|
+
|
|
+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 <openssl/err.h>
|
|
+
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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 <limits.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/obj_mac.h>
|
|
+#include "ec_lcl.h"
|
|
+
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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 <fibikova@exp-math.uni-essen.de>
|
|
+ * 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 <openssl/err.h>
|
|
+#include <openssl/symhacks.h>
|
|
+
|
|
+#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 <fibikova@exp-math.uni-essen.de>
|
|
+ * 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 <openssl/err.h>
|
|
+#include <openssl/symhacks.h>
|
|
+
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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);
|
|
+}
|
|
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 <openssl/err.h>
|
|
+#include <openssl/asn1t.h>
|
|
+
|
|
+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 <stdio.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/ecdsa.h>
|
|
+
|
|
+/* 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 <string.h>
|
|
+#include "ecs_locl.h"
|
|
+#ifndef OPENSSL_NO_ENGINE
|
|
+# include <openssl/engine.h>
|
|
+#endif
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/bn.h>
|
|
+#ifdef OPENSSL_FIPS
|
|
+# include <openssl/fips.h>
|
|
+#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 <openssl/ecdsa.h>
|
|
+
|
|
+#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 <openssl/err.h>
|
|
+#include <openssl/obj_mac.h>
|
|
+#include <openssl/bn.h>
|
|
+
|
|
+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 <openssl/engine.h>
|
|
+#endif
|
|
+#include <openssl/rand.h>
|
|
+
|
|
+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 <string.h>
|
|
+#ifndef OPENSSL_NO_ENGINE
|
|
+# include <openssl/engine.h>
|
|
+#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);
|
|
+}
|
|
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 <ctype.h>
|
|
#include <e_os.h>
|
|
#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 e6a44f4..2acd0c2 100644
|
|
--- a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c
|
|
+++ b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c
|
|
@@ -1032,10 +1032,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);
|
|
|
|
@@ -1070,6 +1070,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
|
|
@@ -1110,7 +1122,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,
|
|
@@ -1127,14 +1144,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;
|
|
@@ -1142,6 +1153,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/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 <openssl/err.h>
|
|
+#include <openssl/sm2err.h>
|
|
+
|
|
+#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 <openssl/asn1t.h>
|
|
+#include <openssl/ec.h>
|
|
+#include <openssl/ecdsa.h>
|
|
+#include <openssl/evp.h>
|
|
+#include "crypto/evp/evp_locl.h"
|
|
+#include <openssl/sm2.h>
|
|
+#include <openssl/sm2err.h>
|
|
+
|
|
+/* 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 <openssl/sm2.h>
|
|
+#include <openssl/sm2err.h>
|
|
+#include <openssl/ec.h> /* ec_group_do_inverse_ord() */
|
|
+#include <openssl/ecdsa.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/bn.h>
|
|
+#include <string.h>
|
|
+
|
|
+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 <openssl/evp.h>
|
|
+# include <openssl/sm3.h>
|
|
+
|
|
+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 <openssl/e_os2.h>
|
|
+#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 <string.h>
|
|
+#include <openssl/sm3.h>
|
|
+
|
|
+#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
|
|
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 <openssl/dsa.h>
|
|
#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;
|
|
}
|
|
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
|
|
|