]> www.wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_omac_acpkm.c
Merge pull request #455 from arx11/magma_ctracpkm_omac
[openssl-gost/engine.git] / gost_omac_acpkm.c
index 507ca53532d5684be92117679908bcfd6b9047b0..f10b11865580aaa8d3a9a00bad7211855f06ef27 100644 (file)
@@ -98,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)
@@ -134,13 +134,29 @@ static int CMAC_ACPKM_Init(CMAC_ACPKM_CTX *ctx, const void *key, size_t keylen,
     }
     /* Initialise context */
     if (cipher) {
-        const EVP_CIPHER *acpkm;
+        const EVP_CIPHER *acpkm = NULL;
 
         if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL))
             return 0;
-        if (!EVP_CIPHER_is_a(cipher, SN_grasshopper_cbc))
+        /* Unfortunately, EVP_CIPHER_is_a is bugged for an engine, EVP_CIPHER_nid is bugged for a provider. */
+        if (EVP_CIPHER_nid(cipher) == NID_undef) {
+            /* Looks like a provider */
+            if (EVP_CIPHER_is_a(cipher, SN_magma_cbc))
+                acpkm = cipher_gost_magma_ctracpkm();
+            else if (EVP_CIPHER_is_a(cipher, SN_grasshopper_cbc))
+                acpkm = cipher_gost_grasshopper_ctracpkm();
+        }
+        else {
+            /* Looks like an engine */
+            if (EVP_CIPHER_nid(cipher) == NID_magma_cbc)
+                acpkm = cipher_gost_magma_ctracpkm();
+            else if (EVP_CIPHER_nid(cipher) == NID_grasshopper_cbc)
+                acpkm = cipher_gost_grasshopper_ctracpkm();
+        }
+
+        if (acpkm == NULL)
             return 0;
-        acpkm = cipher_gost_grasshopper_ctracpkm();
+
         if (!EVP_EncryptInit_ex(ctx->actx, acpkm, impl, NULL, NULL))
             return 0;
     }
@@ -249,6 +265,7 @@ 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)
 {
@@ -257,6 +274,10 @@ static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out,
     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;
@@ -314,6 +335,9 @@ static int omac_acpkm_init(EVP_MD_CTX *ctx, const char *cipher_name)
     case NID_grasshopper_cbc:
         c->dgst_size = 16;
         break;
+    case NID_magma_cbc:
+        c->dgst_size = 8;
+        break;
     }
 
     return 1;
@@ -324,6 +348,11 @@ static int grasshopper_omac_acpkm_init(EVP_MD_CTX *ctx)
     return omac_acpkm_init(ctx, SN_grasshopper_cbc);
 }
 
+static int magma_omac_acpkm_init(EVP_MD_CTX *ctx)
+{
+    return omac_acpkm_init(ctx, SN_magma_cbc);
+}
+
 static int omac_acpkm_imit_update(EVP_MD_CTX *ctx, const void *data,
                                   size_t count)
 {
@@ -341,16 +370,17 @@ 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;
 }
 
 static int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
@@ -375,7 +405,8 @@ static int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
     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 */
@@ -425,6 +456,9 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
                 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;
+                else if (EVP_MD_is_a(md, SN_magma_mac)
+                    || EVP_MD_is_a(md, SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac))
+                    c->cipher_name = SN_magma_cbc;
             }
             if ((cipher =
                  (EVP_CIPHER *)EVP_get_cipherbyname(c->cipher_name)) == NULL
@@ -461,9 +495,13 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
                 return -1;
             c->cmac_ctx->section_size = arg;
             if (ptr && *(int *)ptr) {
+                const EVP_CIPHER *cipher;
+                if ((cipher = EVP_CIPHER_CTX_cipher(c->cmac_ctx->actx)) == NULL) {
+                    return 0;
+                }
+
                 /* Set parameter T */
-                if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_cipher(c->cmac_ctx->actx))
-                    == NULL) {
+                if (EVP_CIPHER_get0_provider(cipher) == NULL) {
                     if (!EVP_CIPHER_CTX_ctrl(c->cmac_ctx->actx, EVP_CTRL_KEY_MESH,
                                              *(int *)ptr, NULL))
                         return 0;
@@ -520,3 +558,17 @@ GOST_digest kuznyechik_ctracpkm_omac_digest = {
     .cleanup = omac_acpkm_imit_cleanup,
     .ctrl = omac_acpkm_imit_ctrl,
 };
+
+GOST_digest magma_ctracpkm_omac_digest = {
+    .nid = NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac,
+    .result_size = 8,
+    .input_blocksize = 8,
+    .app_datasize = sizeof(OMAC_ACPKM_CTX),
+    .flags = EVP_MD_FLAG_XOF,
+    .init = magma_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,
+};