]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_pmeth.c
Make it possible to re-define OPENSSL_ENGINES_INSTALL_DIR
[openssl-gost/engine.git] / gost_pmeth.c
index 896dabb1a1146155ed88500b86db77ce63f636ff..69080bdc52f689907ea240c1003e9ead0b1538b1 100644 (file)
@@ -146,8 +146,10 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
     case EVP_PKEY_CTRL_SET_IV:
         OPENSSL_assert(p2 != NULL);
         pctx->shared_ukm = OPENSSL_malloc((int)p1);
-        if (!pctx->shared_ukm)
+        if (pctx->shared_ukm == NULL) {
+            GOSTerr(GOST_F_PKEY_GOST_CTRL, ERR_R_MALLOC_FAILURE);
             return 0;
+        }
         memcpy(pctx->shared_ukm, p2, (int)p1);
         return 1;
     case EVP_PKEY_CTRL_PEER_KEY:
@@ -281,7 +283,7 @@ static int pkey_gost2001_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
     EC_KEY *ec = NULL;
 
     if (!data || data->sign_param_nid == NID_undef) {
-        GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
+        GOSTerr(GOST_F_PKEY_GOST2001_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
         return 0;
     }
 
@@ -301,7 +303,7 @@ static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
     int result = 0;
 
     if (!data || data->sign_param_nid == NID_undef) {
-        GOSTerr(GOST_F_PKEY_GOST12_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
+        GOSTerr(GOST_F_PKEY_GOST2012_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
         return 0;
     }
 
@@ -367,10 +369,12 @@ static int pkey_gost2012cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
  */
 int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
 {
+    const BIGNUM *sig_r = NULL, *sig_s = NULL;
+    DSA_SIG_get0(s, &sig_r, &sig_s);
     *siglen = 2 * order;
     memset(sig, 0, *siglen);
-    store_bignum(s->s, sig, order);
-    store_bignum(s->r, sig + order, order);
+    store_bignum(sig_s, sig, order);
+    store_bignum(sig_r, sig + order, order);
     DSA_SIG_free(s);
     return 1;
 }
@@ -413,18 +417,20 @@ static int pkey_gost_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
 
 /* ------------------- verify callbacks ---------------------------*/
 /* Unpack signature according to cryptopro rules  */
-DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen)
+DSA_SIG *unpack_cp_signature(const unsigned char *sigbuf, size_t siglen)
 {
-    DSA_SIG *s;
+    DSA_SIG *sig;
+    BIGNUM *r = NULL, *s = NULL;
 
-    s = DSA_SIG_new();
-    if (s == NULL) {
+    sig = DSA_SIG_new();
+    if (sig == NULL) {
         GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
-    s->s = BN_bin2bn(sig, siglen / 2, NULL);
-    s->r = BN_bin2bn(sig + siglen / 2, siglen / 2, NULL);
-    return s;
+    s = BN_bin2bn(sigbuf, siglen / 2, NULL);
+    r = BN_bin2bn(sigbuf + siglen / 2, siglen / 2, NULL);
+               DSA_SIG_set0(sig, r, s);
+    return sig;
 }
 
 static int pkey_gost_ec_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
@@ -466,15 +472,59 @@ static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
 {
     struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
+    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+
+    if (!data)
+        return 0;
+    memset(data, 0, sizeof(*data));
+    data->mac_size = 4;
+    data->mac_param_nid = NID_undef;
+
+    if (pkey) {
+        struct gost_mac_key *key = EVP_PKEY_get0(pkey);
+        if (key) {
+            data->mac_param_nid = key->mac_param_nid;
+            data->mac_size = key->mac_size;
+        }
+    }
+
+    EVP_PKEY_CTX_set_data(ctx, data);
+    return 1;
+}
+
+static int pkey_gost_omac_init(EVP_PKEY_CTX *ctx, size_t mac_size)
+{
+    struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
+    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
 
     if (!data)
         return 0;
     memset(data, 0, sizeof(*data));
-       data->mac_size = 4;
+    data->mac_size = mac_size;
+    data->mac_param_nid = NID_undef;
+
+    if (pkey) {
+        struct gost_mac_key *key = EVP_PKEY_get0(pkey);
+        if (key) {
+            data->mac_param_nid = key->mac_param_nid;
+            data->mac_size = key->mac_size;
+        }
+    }
+
     EVP_PKEY_CTX_set_data(ctx, data);
     return 1;
 }
 
+static int pkey_gost_magma_mac_init(EVP_PKEY_CTX *ctx)
+{
+       return pkey_gost_omac_init(ctx, 4);
+}
+
+static int pkey_gost_grasshopper_mac_init(EVP_PKEY_CTX *ctx)
+{
+       return pkey_gost_omac_init(ctx, 8);
+}
+
 static void pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
 {
     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
@@ -532,10 +582,16 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
         memcpy(data->key, p2, 32);
         data->key_set = 1;
         return 1;
+    case EVP_PKEY_CTRL_GOST_PARAMSET:
+        {
+            struct gost_cipher_info *param = p2;
+            data->mac_param_nid = param->nid;
+            return 1;
+        }
     case EVP_PKEY_CTRL_DIGESTINIT:
         {
             EVP_MD_CTX *mctx = p2;
-            void *key;
+            struct gost_mac_key *key;
             if (!data->key_set) {
                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
                 if (!pkey) {
@@ -549,22 +605,23 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                             GOST_R_MAC_KEY_NOT_SET);
                     return 0;
                 }
+                return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
+                    (mctx, EVP_MD_CTRL_SET_KEY, 0, key);
             } else {
-                key = &(data->key);
+                return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
+                    (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key));
+            }
+        }
+    case EVP_PKEY_CTRL_MAC_LEN:
+        {
+            if (p1 < 1 || p1 > 8) {
+
+                GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_SIZE);
+                return 0;
             }
-            return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key);
+            data->mac_size = p1;
+            return 1;
         }
-       case EVP_PKEY_CTRL_MAC_LEN:     
-               {
-                       if (p1<1 || p1>8)
-                               {
-                                       
-                                       GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_INVALID_MAC_SIZE);
-                                       return 0;
-                               }
-                               data->mac_size = p1;
-                               return 1;
-               }
     }
     return -2;
 }
@@ -596,32 +653,186 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
         return ret;
 
     }
-       if (!strcmp(type,maclen_ctrl_string)) {
-               char *endptr;
-               long size=strtol(value,&endptr,10);
-               if (*endptr!='\0') {
-                       GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
-                                  GOST_R_INVALID_MAC_SIZE);
-                       return 0;
-               }
-               return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN,size,NULL);
-       }
+    if (!strcmp(type, maclen_ctrl_string)) {
+        char *endptr;
+        long size = strtol(value, &endptr, 10);
+        if (*endptr != '\0') {
+            GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE);
+            return 0;
+        }
+        return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL);
+    }
+    if (strcmp(type, param_ctrl_string) == 0) {
+        ASN1_OBJECT *obj = OBJ_txt2obj(value, 0);
+        const struct gost_cipher_info *param = NULL;
+        if (obj == NULL) {
+            GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS);
+            return 0;
+        }
+
+        param = get_encryption_params(obj);
+                               ASN1_OBJECT_free(obj);
+        if (param == NULL) {
+            GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS);
+            return 0;
+        }
+
+
+        return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, 0,
+                                  (void *)param);
+    }
+    return -2;
+}
+
+static int pkey_gost_omac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2, size_t max_size)
+{
+    struct gost_mac_pmeth_data *data =
+        (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
+
+    switch (type) {
+    case EVP_PKEY_CTRL_MD:
+        {
+            int nid = EVP_MD_type((const EVP_MD *)p2);
+            if (nid != NID_magma_mac && nid != NID_grasshopper_mac) {
+                GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
+                        GOST_R_INVALID_DIGEST_TYPE);
+                return 0;
+            }
+            data->md = (EVP_MD *)p2;
+            return 1;
+        }
+
+    case EVP_PKEY_CTRL_GET_MD:
+        *(const EVP_MD **)p2 = data->md;
+        return 1;
+
+    case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
+    case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+    case EVP_PKEY_CTRL_PKCS7_SIGN:
+        return 1;
+    case EVP_PKEY_CTRL_SET_MAC_KEY:
+        if (p1 != 32) {
+            GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
+            return 0;
+        }
+
+        memcpy(data->key, p2, 32);
+        data->key_set = 1;
+        return 1;
+    case EVP_PKEY_CTRL_DIGESTINIT:
+        {
+            EVP_MD_CTX *mctx = p2;
+            struct gost_mac_key *key;
+            if (!data->key_set) {
+                EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+                if (!pkey) {
+                    GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
+                            GOST_R_MAC_KEY_NOT_SET);
+                    return 0;
+                }
+                key = EVP_PKEY_get0(pkey);
+                if (!key) {
+                    GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
+                            GOST_R_MAC_KEY_NOT_SET);
+                    return 0;
+                }
+                return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
+                    (mctx, EVP_MD_CTRL_SET_KEY, 0, key);
+            } else {
+                return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
+                    (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key));
+            }
+        }
+    case EVP_PKEY_CTRL_MAC_LEN:
+        {
+            if (p1 < 1 || p1 > max_size) {
+
+                GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_SIZE);
+                return 0;
+            }
+            data->mac_size = p1;
+            return 1;
+        }
+    }
+    return -2;
+}
+
+static int pkey_gost_magma_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+       return pkey_gost_omac_ctrl(ctx, type, p1, p2, 8);
+}
+
+static int pkey_gost_grasshopper_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+       return pkey_gost_omac_ctrl(ctx, type, p1, p2, 16);
+}
+
+static int pkey_gost_omac_ctrl_str(EVP_PKEY_CTX *ctx,
+                                  const char *type, const char *value, size_t max_size)
+{
+    if (strcmp(type, key_ctrl_string) == 0) {
+        if (strlen(value) != 32) {
+            GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
+                    GOST_R_INVALID_MAC_KEY_LENGTH);
+            return 0;
+        }
+        return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
+                                  32, (char *)value);
+    }
+    if (strcmp(type, hexkey_ctrl_string) == 0) {
+        long keylen;
+        int ret;
+        unsigned char *keybuf = string_to_hex(value, &keylen);
+        if (!keybuf || keylen != 32) {
+            GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
+                    GOST_R_INVALID_MAC_KEY_LENGTH);
+            OPENSSL_free(keybuf);
+            return 0;
+        }
+        ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
+        OPENSSL_free(keybuf);
+        return ret;
+
+    }
+    if (!strcmp(type, maclen_ctrl_string)) {
+        char *endptr;
+        long size = strtol(value, &endptr, 10);
+        if (*endptr != '\0') {
+            GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE);
+            return 0;
+        }
+        return pkey_gost_omac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL, max_size);
+    }
     return -2;
 }
 
+static int pkey_gost_magma_mac_ctrl_str(EVP_PKEY_CTX *ctx,
+                                  const char *type, const char *value)
+{
+       return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
+}
+
+static int pkey_gost_grasshopper_mac_ctrl_str(EVP_PKEY_CTX *ctx,
+                                  const char *type, const char *value)
+{
+       return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
+}
+
 static int pkey_gost_mac_keygen_base(EVP_PKEY_CTX *ctx,
                                      EVP_PKEY *pkey, int mac_nid)
 {
     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
-    unsigned char *keydata;
+    struct gost_mac_key *keydata;
     if (!data || !data->key_set) {
-        GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET);
+        GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN_BASE, GOST_R_MAC_KEY_NOT_SET);
         return 0;
     }
-    keydata = OPENSSL_malloc(32);
+    keydata = OPENSSL_malloc(sizeof(struct gost_mac_key));
     if (keydata == NULL)
         return 0;
-    memcpy(keydata, data->key, 32);
+    memcpy(keydata->key, data->key, 32);
+    keydata->mac_param_nid = data->mac_param_nid;
+    keydata->mac_size = data->mac_size;
     EVP_PKEY_assign(pkey, mac_nid, keydata);
     return 1;
 }
@@ -636,8 +847,64 @@ static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
     return pkey_gost_mac_keygen_base(ctx, pkey, NID_id_Gost28147_89_MAC);
 }
 
+static int pkey_gost_magma_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    return pkey_gost_mac_keygen_base(ctx, pkey, NID_magma_mac);
+}
+
+static int pkey_gost_grasshopper_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    return pkey_gost_mac_keygen_base(ctx, pkey, NID_grasshopper_mac);
+}
+
 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
 {
+    struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+
+    if (data == NULL) {
+        pkey_gost_mac_init(ctx);
+    }
+
+    data = EVP_PKEY_CTX_get_data(ctx);
+    if (!data) {
+        GOSTerr(GOST_F_PKEY_GOST_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int pkey_gost_magma_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+    struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+
+    if (data == NULL) {
+        pkey_gost_omac_init(ctx, 4);
+    }
+
+    data = EVP_PKEY_CTX_get_data(ctx);
+    if (!data) {
+        GOSTerr(GOST_F_PKEY_GOST_MAGMA_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int pkey_gost_grasshopper_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+    struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+
+    if (data == NULL) {
+        pkey_gost_omac_init(ctx, 8);
+    }
+
+    data = EVP_PKEY_CTX_get_data(ctx);
+    if (!data) {
+        GOSTerr(GOST_F_PKEY_GOST_GRASSHOPPER_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
+        return 0;
+    }
+
     return 1;
 }
 
@@ -646,7 +913,7 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
 {
     unsigned int tmpsiglen;
     int ret;
-       struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+    struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
 
     if (!siglen)
         return 0;
@@ -658,7 +925,8 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
         return 1;
     }
 
-       mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
+    EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
+        (mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
     *siglen = data->mac_size;
     return ret;
@@ -745,6 +1013,26 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags)
         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
         return 1;
+    case NID_magma_mac:
+        EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_magma_mac_ctrl,
+                               pkey_gost_magma_mac_ctrl_str);
+        EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_magma_mac_signctx_init,
+                                  pkey_gost_mac_signctx);
+        EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_magma_mac_keygen);
+        EVP_PKEY_meth_set_init(*pmeth, pkey_gost_magma_mac_init);
+        EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
+        EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
+        return 1;
+    case NID_grasshopper_mac:
+        EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_grasshopper_mac_ctrl,
+                               pkey_gost_grasshopper_mac_ctrl_str);
+        EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_grasshopper_mac_signctx_init,
+                                  pkey_gost_mac_signctx);
+        EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_grasshopper_mac_keygen);
+        EVP_PKEY_meth_set_init(*pmeth, pkey_gost_grasshopper_mac_init);
+        EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
+        EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
+        return 1;
     default:                   /* Unsupported method */
         return 0;
     }