]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_omac_acpkm.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_omac_acpkm.c
index 9bdb05f0e510ae2be0957531bfa777e329e79788..8a3c841ad269feb43b297ae38c7123c7bf630eb5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved.
+ * Copyright (C) 2018,2020 Vitaly Chikunov <vt@altlinux.org>. All Rights Reserved.
  * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
  *
  * Contents licensed under the terms of the OpenSSL license
@@ -58,7 +58,7 @@ static void make_kn(unsigned char *k1, unsigned char *l, int bl)
 static CMAC_ACPKM_CTX *CMAC_ACPKM_CTX_new(void)
 {
     CMAC_ACPKM_CTX *ctx;
-    ctx = OPENSSL_malloc(sizeof(CMAC_ACPKM_CTX));
+    ctx = OPENSSL_zalloc(sizeof(CMAC_ACPKM_CTX));
     if (!ctx)
         return NULL;
     ctx->cctx = EVP_CIPHER_CTX_new();
@@ -68,6 +68,7 @@ static CMAC_ACPKM_CTX *CMAC_ACPKM_CTX_new(void)
     }
     ctx->actx = EVP_CIPHER_CTX_new();
     if (ctx->actx == NULL) {
+        EVP_CIPHER_CTX_free(ctx->cctx);
         OPENSSL_free(ctx);
         return NULL;
     }
@@ -97,7 +98,7 @@ static void CMAC_ACPKM_CTX_free(CMAC_ACPKM_CTX *ctx)
     OPENSSL_free(ctx);
 }
 
-int CMAC_ACPKM_CTX_copy(CMAC_ACPKM_CTX *out, const CMAC_ACPKM_CTX *in)
+static int CMAC_ACPKM_CTX_copy(CMAC_ACPKM_CTX *out, const CMAC_ACPKM_CTX *in)
 {
     int bl;
     if (in->nlast_block == -1)
@@ -137,26 +138,23 @@ static int CMAC_ACPKM_Init(CMAC_ACPKM_CTX *ctx, const void *key, size_t keylen,
 
         if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL))
             return 0;
-        switch (EVP_CIPHER_nid(cipher)) {
-            case NID_grasshopper_cbc:
-                acpkm = cipher_gost_grasshopper_ctracpkm();
-                break;
-            default:
-                return 0;
-        }
+        if (!EVP_CIPHER_is_a(cipher, SN_grasshopper_cbc))
+            return 0;
+        acpkm = cipher_gost_grasshopper_ctracpkm();
         if (!EVP_EncryptInit_ex(ctx->actx, acpkm, impl, NULL, NULL))
             return 0;
     }
     /* Non-NULL key means initialisation is complete */
     if (key) {
         unsigned char acpkm_iv[EVP_MAX_BLOCK_LENGTH];
+        int block_size, key_len;
 
         /* Initialize CTR for ACPKM-Master */
         if (!EVP_CIPHER_CTX_cipher(ctx->actx))
             return 0;
         /* block size of ACPKM cipher could be 1, but,
          * cbc cipher is same with correct block_size */
-        const int block_size = EVP_CIPHER_CTX_block_size(ctx->cctx);
+        block_size = EVP_CIPHER_CTX_block_size(ctx->cctx);
         /* Wide IV = 1^{n/2} || 0,
          * where a^r denotes the string that consists of r 'a' bits */
         memset(acpkm_iv, 0xff, block_size / 2);
@@ -164,7 +162,7 @@ static int CMAC_ACPKM_Init(CMAC_ACPKM_CTX *ctx, const void *key, size_t keylen,
         if (!EVP_EncryptInit_ex(ctx->actx, NULL, NULL, key, acpkm_iv))
             return 0;
         /* EVP_CIPHER key_len may be different from EVP_CIPHER_CTX key_len */
-        int key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
+        key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
 
         /* Generate first key material (K^1 || K^1_1) */
         if (!EVP_Cipher(ctx->actx, ctx->km, zero_iv, key_len + block_size))
@@ -251,13 +249,19 @@ static int CMAC_ACPKM_Update(CMAC_ACPKM_CTX *ctx, const void *in, size_t dlen)
 
 }
 
+/* Return value is propagated to EVP_DigestFinal_ex */
 static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out,
                             size_t *poutlen)
 {
-    int i, bl, lb;
+    int i, bl, lb, key_len;
+    unsigned char *k1, k2[EVP_MAX_BLOCK_LENGTH];
     if (ctx->nlast_block == -1)
         return 0;
     bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
+    if (bl != 8 && bl != 16) {
+        GOSTerr(GOST_F_OMAC_ACPKM_IMIT_FINAL, GOST_R_INVALID_MAC_PARAMS);
+        return 0;
+    }
     *poutlen = (size_t) bl;
     if (!out)
         return 1;
@@ -265,10 +269,9 @@ static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out,
 
     if (!CMAC_ACPKM_Mesh(ctx))
         return 0;
-    int key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
+    key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
     /* Keys k1 and k2 */
-    unsigned char *k1 = ctx->km + key_len;
-    unsigned char k2[EVP_MAX_BLOCK_LENGTH];
+    k1 = ctx->km + key_len;
     make_kn(k2, ctx->km + key_len, bl);
 
     /* Is last block complete? */
@@ -299,20 +302,20 @@ static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out,
 typedef struct omac_acpkm_ctx {
     CMAC_ACPKM_CTX *cmac_ctx;
     size_t dgst_size;
-    int cipher_nid;
+    const char *cipher_name;
     int key_set;
 } OMAC_ACPKM_CTX;
 
 #define MAX_GOST_OMAC_ACPKM_SIZE 16
 
-static int omac_acpkm_init(EVP_MD_CTX *ctx, int cipher_nid)
+static int omac_acpkm_init(EVP_MD_CTX *ctx, const char *cipher_name)
 {
     OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
     memset(c, 0, sizeof(OMAC_ACPKM_CTX));
-    c->cipher_nid = cipher_nid;
+    c->cipher_name = cipher_name;
     c->key_set = 0;
 
-    switch (cipher_nid) {
+    switch (OBJ_txt2nid(cipher_name)) {
     case NID_grasshopper_cbc:
         c->dgst_size = 16;
         break;
@@ -323,7 +326,7 @@ static int omac_acpkm_init(EVP_MD_CTX *ctx, int cipher_nid)
 
 static int grasshopper_omac_acpkm_init(EVP_MD_CTX *ctx)
 {
-    return omac_acpkm_init(ctx, NID_grasshopper_cbc);
+    return omac_acpkm_init(ctx, SN_grasshopper_cbc);
 }
 
 static int omac_acpkm_imit_update(EVP_MD_CTX *ctx, const void *data,
@@ -343,26 +346,27 @@ int omac_acpkm_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
     OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
     unsigned char mac[MAX_GOST_OMAC_ACPKM_SIZE];
     size_t mac_size = sizeof(mac);
+    int ret;
 
     if (!c->key_set) {
         GOSTerr(GOST_F_OMAC_ACPKM_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
         return 0;
     }
 
-    CMAC_ACPKM_Final(c->cmac_ctx, mac, &mac_size);
+    ret = CMAC_ACPKM_Final(c->cmac_ctx, mac, &mac_size);
 
     memcpy(md, mac, c->dgst_size);
-    return 1;
+    return ret;
 }
 
-int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
+static int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
 {
     OMAC_ACPKM_CTX *c_to = EVP_MD_CTX_md_data(to);
     const OMAC_ACPKM_CTX *c_from = EVP_MD_CTX_md_data(from);
 
     if (c_from && c_to) {
         c_to->dgst_size = c_from->dgst_size;
-        c_to->cipher_nid = c_from->cipher_nid;
+        c_to->cipher_name = c_from->cipher_name;
         c_to->key_set = c_from->key_set;
     } else {
         return 0;
@@ -374,14 +378,15 @@ int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
         }
         return 1;
     }
-    if (c_to->cmac_ctx == c_from->cmac_ctx) {
+    if ((c_to->cmac_ctx == c_from->cmac_ctx) || (c_to->cmac_ctx == NULL))  {
         c_to->cmac_ctx = CMAC_ACPKM_CTX_new();
     }
-    return CMAC_ACPKM_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
+
+    return (c_to->cmac_ctx) ? CMAC_ACPKM_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx) : 0;
 }
 
 /* Clean up imit ctx */
-int omac_acpkm_imit_cleanup(EVP_MD_CTX *ctx)
+static int omac_acpkm_imit_cleanup(EVP_MD_CTX *ctx)
 {
     OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
 
@@ -420,36 +425,41 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
         {
             OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
             const EVP_MD *md = EVP_MD_CTX_md(ctx);
-            const EVP_CIPHER *cipher = NULL;
+            EVP_CIPHER *cipher = NULL;
+            int ret = 0;
 
-            if (c->cipher_nid == NID_undef) {
-                switch (EVP_MD_nid(md)) {
-                case NID_grasshopper_mac:
-                    c->cipher_nid = NID_grasshopper_cbc;
-                    break;
-                }
+            if (c->cipher_name == NULL) {
+                if (EVP_MD_is_a(md, SN_grasshopper_mac)
+                    || EVP_MD_is_a(md, SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac))
+                    c->cipher_name = SN_grasshopper_cbc;
             }
-            cipher = EVP_get_cipherbynid(c->cipher_nid);
-            if (cipher == NULL) {
+            if ((cipher =
+                 (EVP_CIPHER *)EVP_get_cipherbyname(c->cipher_name)) == NULL
+                && (cipher =
+                    EVP_CIPHER_fetch(NULL, c->cipher_name, NULL)) == NULL) {
                 GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
             }
             if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
                 GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
-                return 0;
+                goto set_key_end;
             }
             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
             if (c->key_set) {
                 GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_BAD_ORDER);
-                return 0;
+                goto set_key_end;
             }
             if (arg == 0) {
                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
-                return omac_acpkm_key(c, cipher, key->key, 32);
+                ret = omac_acpkm_key(c, cipher, key->key, 32);
+                goto set_key_end;
             } else if (arg == 32) {
-                return omac_acpkm_key(c, cipher, ptr, 32);
+                ret = omac_acpkm_key(c, cipher, ptr, 32);
+                goto set_key_end;
             }
             GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
-            return 0;
+          set_key_end:
+            EVP_CIPHER_free(cipher);
+            return ret;
         }
     case EVP_CTRL_KEY_MESH:
         {
@@ -459,15 +469,26 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
             c->cmac_ctx->section_size = arg;
             if (ptr && *(int *)ptr) {
                 /* Set parameter T */
-                if (!EVP_CIPHER_CTX_ctrl(c->cmac_ctx->actx, EVP_CTRL_KEY_MESH, *(int *)ptr, NULL))
-                    return 0;
+                if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_cipher(c->cmac_ctx->actx))
+                    == NULL) {
+                    if (!EVP_CIPHER_CTX_ctrl(c->cmac_ctx->actx, EVP_CTRL_KEY_MESH,
+                                             *(int *)ptr, NULL))
+                        return 0;
+                } else {
+                    size_t cipher_key_mesh = (size_t)*(int *)ptr;
+                    OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+                    params[0] = OSSL_PARAM_construct_size_t("key-mesh",
+                                                            &cipher_key_mesh);
+                    if (!EVP_CIPHER_CTX_set_params(c->cmac_ctx->actx, params))
+                        return 0;
+                }
             }
             return 1;
         }
-    case EVP_MD_CTRL_MAC_LEN:
+    case EVP_MD_CTRL_XOF_LEN:   /* Supported in OpenSSL */
         {
             OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
-            switch (c->cipher_nid) {
+            switch (OBJ_txt2nid(c->cipher_name)) {
             case NID_grasshopper_cbc:
                 if (arg < 1 || arg > 16) {
                     GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
@@ -475,6 +496,13 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
                 }
                 c->dgst_size = arg;
                 break;
+            case NID_magma_cbc:
+                if (arg < 1 || arg > 8) {
+                    GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
+                    return 0;
+                }
+                c->dgst_size = arg;
+                break;
             default:
                 return 0;
             }
@@ -486,36 +514,16 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
     }
 }
 
-static EVP_MD *_hidden_grasshopper_omac_acpkm_md = NULL;
-
-EVP_MD *grasshopper_omac_acpkm(void)
-{
-    if (_hidden_grasshopper_omac_acpkm_md == NULL) {
-        EVP_MD *md;
-
-        if ((md =
-             EVP_MD_meth_new(NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
-              NID_undef)) == NULL
-            || !EVP_MD_meth_set_result_size(md, MAX_GOST_OMAC_ACPKM_SIZE)
-            || !EVP_MD_meth_set_input_blocksize(md, GRASSHOPPER_BLOCK_SIZE)
-            || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_ACPKM_CTX))
-            || !EVP_MD_meth_set_flags(md, 0)
-            || !EVP_MD_meth_set_init(md, grasshopper_omac_acpkm_init)
-            || !EVP_MD_meth_set_update(md, omac_acpkm_imit_update)
-            || !EVP_MD_meth_set_final(md, omac_acpkm_imit_final)
-            || !EVP_MD_meth_set_copy(md, omac_acpkm_imit_copy)
-            || !EVP_MD_meth_set_cleanup(md, omac_acpkm_imit_cleanup)
-            || !EVP_MD_meth_set_ctrl(md, omac_acpkm_imit_ctrl)) {
-            EVP_MD_meth_free(md);
-            md = NULL;
-        }
-        _hidden_grasshopper_omac_acpkm_md = md;
-    }
-    return _hidden_grasshopper_omac_acpkm_md;
-}
-
-void grasshopper_omac_acpkm_destroy(void)
-{
-    EVP_MD_meth_free(_hidden_grasshopper_omac_acpkm_md);
-    _hidden_grasshopper_omac_acpkm_md = NULL;
-}
+GOST_digest kuznyechik_ctracpkm_omac_digest = {
+    .nid = NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
+    .result_size = MAX_GOST_OMAC_ACPKM_SIZE,
+    .input_blocksize = GRASSHOPPER_BLOCK_SIZE,
+    .app_datasize = sizeof(OMAC_ACPKM_CTX),
+    .flags = EVP_MD_FLAG_XOF,
+    .init = grasshopper_omac_acpkm_init,
+    .update = omac_acpkm_imit_update,
+    .final = omac_acpkm_imit_final,
+    .copy = omac_acpkm_imit_copy,
+    .cleanup = omac_acpkm_imit_cleanup,
+    .ctrl = omac_acpkm_imit_ctrl,
+};