CMAC implementation 49/70149/11
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 18 May 2016 07:33:14 +0000 (09:33 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 23 May 2016 08:03:11 +0000 (10:03 +0200)
Change-Id: Ie6c0f5a83db902cddcb029d9140c12351b17d4e6

src/sign.c

index 8cff08c..4e119be 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
+#include <openssl/cmac.h>
 
 #include <yaca/crypto.h>
 #include <yaca/error.h>
@@ -331,6 +332,97 @@ free_key:
        return ret;
 }
 
+API int yaca_sign_cmac_init(yaca_ctx_h *ctx,
+                            yaca_enc_algo_e algo,
+                            const yaca_key_h key)
+{
+       struct yaca_sign_ctx_s *nc = NULL;
+       CMAC_CTX* cmac_ctx = NULL;
+       const EVP_CIPHER* cipher = NULL;
+       EVP_PKEY *pkey = NULL;
+       int ret;
+
+       if (ctx == NULL || key == NULL ||
+          (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES))
+               return YACA_ERROR_INVALID_ARGUMENT;
+
+       const struct yaca_key_simple_s *simple_key = key_get_simple(key);
+
+        // the type is ok so we should be able to extract simple key
+       assert(simple_key != NULL);
+
+       nc = yaca_zalloc(sizeof(struct yaca_sign_ctx_s));
+       if (nc == NULL) {
+               return YACA_ERROR_OUT_OF_MEMORY;
+       }
+
+       nc->op_type = OP_SIGN;
+       nc->ctx.type = YACA_CTX_SIGN;
+       nc->ctx.ctx_destroy = destroy_sign_context;
+       nc->ctx.get_output_length = get_sign_output_length;
+
+       ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bits, &cipher);
+       if (ret != 0) {
+               goto free_ctx;
+       }
+
+       // create and initialize low level CMAC context
+       cmac_ctx = CMAC_CTX_new();
+       if (cmac_ctx == NULL) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto free_ctx;
+       }
+
+       if (CMAC_Init(cmac_ctx, simple_key->d, simple_key->bits/8, cipher, NULL) != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               // TODO refactor error handling: use single cleanup label
+               goto free_cmac_ctx;
+       }
+
+       // create key and assign CMAC context to it
+       pkey = EVP_PKEY_new();
+       if (!pkey) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto free_cmac_ctx;
+       }
+
+       if (EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmac_ctx) != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto free_pkey;
+       }
+       // TODO refactor error handling: set cmac_ctx to NULL
+
+       nc->mdctx = EVP_MD_CTX_create();
+       if (nc->mdctx == NULL) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto free_pkey;
+       }
+
+       if (EVP_DigestSignInit(nc->mdctx, NULL, NULL, NULL, pkey) != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto free_pkey;
+       }
+       // TODO refactor error handling: set mdctx to NULL, set pkey to NULL
+
+       *ctx = (yaca_ctx_h)nc;
+       return 0;
+
+free_pkey:
+       EVP_PKEY_free(pkey);
+free_cmac_ctx:
+       CMAC_CTX_free(cmac_ctx);
+free_ctx:
+       yaca_ctx_free((yaca_ctx_h)nc);
+
+       return ret;
+}
+
 API int yaca_sign_update(yaca_ctx_h ctx,
                         const char *data,
                         size_t data_len)