Support SM2 ECIES scheme via EVP
authorJack Lloyd <jack.lloyd@ribose.com>
Wed, 24 Jan 2018 21:45:48 +0000 (16:45 -0500)
committerRichard Levitte <levitte@openssl.org>
Mon, 19 Mar 2018 13:33:25 +0000 (14:33 +0100)
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4793)

crypto/ec/ec_pmeth.c
crypto/sm2/sm2_crypt.c
test/recipes/30-test_evp_data/evppkey.txt

index 82a4ffa..5f3f56c 100644 (file)
@@ -17,7 +17,7 @@
 #include "internal/evp_int.h"
 
 #if !defined(OPENSSL_NO_SM2)
-  #include <openssl/sm2.h>
+include <openssl/sm2.h>
 #endif
 
 /* EC pkey context structure */
@@ -123,13 +123,12 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
 
     if (ec_nid == NID_sm2) {
 #if defined(OPENSSL_NO_SM2)
-       ret = -1;
+        ret = -1;
 #else
-       ret = SM2_sign(type, tbs, tbslen, sig, &sltmp, ec);
+        ret = SM2_sign(type, tbs, tbslen, sig, &sltmp, ec);
 #endif
-    }
-    else {
-       ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
+    } else {
+        ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
     }
 
     if (ret <= 0)
@@ -154,22 +153,19 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
 
     if (ec_nid == NID_sm2) {
 #if defined(OPENSSL_NO_SM2)
-       ret = -1;
+        ret = -1;
 #else
-       ret = SM2_verify(type, tbs, tbslen, sig, siglen, ec);
+        ret = SM2_verify(type, tbs, tbslen, sig, siglen, ec);
 #endif
+    } else {
+        ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
     }
-    else {
-       ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
-    }
-
 
     return ret;
 }
 
 #ifndef OPENSSL_NO_EC
-static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
-                          size_t *keylen)
+static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
 {
     int ret;
     size_t outlen;
@@ -205,6 +201,68 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
     return 1;
 }
 
+static int pkey_ecies_encrypt(EVP_PKEY_CTX *ctx,
+                              unsigned char *out, size_t *outlen,
+                              const unsigned char *in, size_t inlen)
+{
+    int ret, md_type;
+    EC_PKEY_CTX *dctx = ctx->data;
+    EC_KEY *ec = ctx->pkey->pkey.ec;
+    const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+
+    if (dctx->md)
+        md_type = EVP_MD_type(dctx->md);
+    else if (ec_nid == NID_sm2)
+        md_type = NID_sm3;
+    else
+        md_type = NID_sha256;
+
+    if (ec_nid == NID_sm2) {
+# if defined(OPENSSL_NO_SM2)
+        ret = -1;
+# else
+        ret = SM2_encrypt(ec, EVP_get_digestbynid(md_type),
+                          in, inlen, out, outlen);
+# endif
+    } else {
+        /* standard ECIES not implemented */
+        ret = -1;
+    }
+
+    return ret;
+}
+
+static int pkey_ecies_decrypt(EVP_PKEY_CTX *ctx,
+                              unsigned char *out, size_t *outlen,
+                              const unsigned char *in, size_t inlen)
+{
+    int ret, md_type;
+    EC_PKEY_CTX *dctx = ctx->data;
+    EC_KEY *ec = ctx->pkey->pkey.ec;
+    const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+
+    if (dctx->md)
+        md_type = EVP_MD_type(dctx->md);
+    else if (ec_nid == NID_sm2)
+        md_type = NID_sm3;
+    else
+        md_type = NID_sha256;
+
+    if (ec_nid == NID_sm2) {
+# if defined(OPENSSL_NO_SM2)
+        ret = -1;
+# else
+        ret = SM2_decrypt(ec, EVP_get_digestbynid(md_type),
+                          in, inlen, out, outlen);
+# endif
+    } else {
+        /* standard ECIES not implemented */
+        ret = -1;
+    }
+
+    return ret;
+}
+
 static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
                               unsigned char *key, size_t *keylen)
 {
@@ -269,8 +327,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                 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;
+                return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
             }
         } else if (p1 < -1 || p1 > 1)
             return -2;
@@ -453,7 +510,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 
 const EVP_PKEY_METHOD ec_pkey_meth = {
     EVP_PKEY_EC,
-    0,
+    EVP_PKEY_FLAG_AUTOARGLEN,
     pkey_ec_init,
     pkey_ec_copy,
     pkey_ec_cleanup,
@@ -474,9 +531,11 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
 
     0, 0, 0, 0,
 
-    0, 0,
+    0,
+    pkey_ecies_encrypt,
 
-    0, 0,
+    0,
+    pkey_ecies_decrypt,
 
     0,
 #ifndef OPENSSL_NO_EC
index a450146..7e7be9d 100644 (file)
@@ -303,6 +303,7 @@ int SM2_decrypt(const EC_KEY *key,
         goto done;
 
     rc = 1;
+    *ptext_len = msg_len;
 
  done:
 
index d29fbbe..b2bbcbc 100644 (file)
@@ -18383,3 +18383,8 @@ Verify = SM2_key1
 Ctrl = digest:SM3
 Input = D7AD397F6FFA5D4F7F11E7217F241607DC30618C236D2C09C1B9EA8FDADEE2E8
 Output = 3046022100AB1DB64DE7C40EDBDE6651C9B8EBDB804673DB836E5D5C7FE15DCF9ED2725037022100EBA714451FF69B0BB930B379E192E7CD5FA6E3C41C7FBD8303B799AB54A54621
+
+Decrypt = SM2_key1
+Input = 30818A0220466BE2EF5C11782EC77864A0055417F407A5AFC11D653C6BCE69E417BB1D05B6022062B572E21FF0DDF5C726BD3F9FF2EAE56E6294713A607E9B9525628965F62CC804203C1B5713B5DB2728EB7BF775E44F4689FC32668BDC564F52EA45B09E8DF2A5F40422084A9D0CC2997092B7D3C404FCE95956EB604D732B2307A8E5B8900ED6608CA5B197
+Output = "The floofy bunnies hop at midnight"
+