Home | History | Annotate | Download | only in cmac
      1 /* Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL
      2  * project 2010.
      3  */
      4 /* ====================================================================
      5  * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in
     16  *    the documentation and/or other materials provided with the
     17  *    distribution.
     18  *
     19  * 3. All advertising materials mentioning features or use of this
     20  *    software must display the following acknowledgment:
     21  *    "This product includes software developed by the OpenSSL Project
     22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     23  *
     24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     25  *    endorse or promote products derived from this software without
     26  *    prior written permission. For written permission, please contact
     27  *    licensing (at) OpenSSL.org.
     28  *
     29  * 5. Products derived from this software may not be called "OpenSSL"
     30  *    nor may "OpenSSL" appear in their names without prior written
     31  *    permission of the OpenSSL Project.
     32  *
     33  * 6. Redistributions of any form whatsoever must retain the following
     34  *    acknowledgment:
     35  *    "This product includes software developed by the OpenSSL Project
     36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     37  *
     38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     49  * OF THE POSSIBILITY OF SUCH DAMAGE.
     50  * ====================================================================
     51  */
     52 
     53 #include <stdio.h>
     54 #include "cryptlib.h"
     55 #include <openssl/x509.h>
     56 #include <openssl/x509v3.h>
     57 #include <openssl/evp.h>
     58 #include <openssl/cmac.h>
     59 #include "evp_locl.h"
     60 
     61 /* The context structure and "key" is simply a CMAC_CTX */
     62 
     63 static int pkey_cmac_init(EVP_PKEY_CTX *ctx)
     64 	{
     65 	ctx->data = CMAC_CTX_new();
     66 	if (!ctx->data)
     67 		return 0;
     68 	ctx->keygen_info_count = 0;
     69 	return 1;
     70 	}
     71 
     72 static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
     73 	{
     74 	if (!pkey_cmac_init(dst))
     75 		return 0;
     76 	if (!CMAC_CTX_copy(dst->data, src->data))
     77 		return 0;
     78 	return 1;
     79 	}
     80 
     81 static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx)
     82 	{
     83 	CMAC_CTX_free(ctx->data);
     84 	}
     85 
     86 static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
     87 	{
     88 	CMAC_CTX *cmkey = CMAC_CTX_new();
     89 	CMAC_CTX *cmctx = ctx->data;
     90 	if (!cmkey)
     91 		return 0;
     92 	if (!CMAC_CTX_copy(cmkey, cmctx))
     93 		{
     94 		CMAC_CTX_free(cmkey);
     95 		return 0;
     96 		}
     97 	EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey);
     98 
     99 	return 1;
    100 	}
    101 
    102 static int int_update(EVP_MD_CTX *ctx,const void *data,size_t count)
    103 	{
    104 	if (!CMAC_Update(ctx->pctx->data, data, count))
    105 		return 0;
    106 	return 1;
    107 	}
    108 
    109 static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
    110 	{
    111 	EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
    112 	mctx->update = int_update;
    113 	return 1;
    114 	}
    115 
    116 static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
    117 					EVP_MD_CTX *mctx)
    118 	{
    119 	return CMAC_Final(ctx->data, sig, siglen);
    120 	}
    121 
    122 static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
    123 	{
    124 	CMAC_CTX *cmctx = ctx->data;
    125 	switch (type)
    126 		{
    127 
    128 		case EVP_PKEY_CTRL_SET_MAC_KEY:
    129 		if (!p2 || p1 < 0)
    130 			return 0;
    131 		if (!CMAC_Init(cmctx, p2, p1, NULL, NULL))
    132 			return 0;
    133 		break;
    134 
    135 		case EVP_PKEY_CTRL_CIPHER:
    136 		if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine))
    137 			return 0;
    138 		break;
    139 
    140 		case EVP_PKEY_CTRL_MD:
    141 		if (ctx->pkey && !CMAC_CTX_copy(ctx->data,
    142 					(CMAC_CTX *)ctx->pkey->pkey.ptr))
    143 			return 0;
    144 		if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL))
    145 			return 0;
    146 		break;
    147 
    148 		default:
    149 		return -2;
    150 
    151 		}
    152 	return 1;
    153 	}
    154 
    155 static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx,
    156 			const char *type, const char *value)
    157 	{
    158 	if (!value)
    159 		{
    160 		return 0;
    161 		}
    162 	if (!strcmp(type, "key"))
    163 		{
    164 		void *p = (void *)value;
    165 		return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
    166 								strlen(p), p);
    167 		}
    168 	if (!strcmp(type, "cipher"))
    169 		{
    170 		const EVP_CIPHER *c;
    171 		c = EVP_get_cipherbyname(value);
    172 		if (!c)
    173 			return 0;
    174 		return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c);
    175 		}
    176 	if (!strcmp(type, "hexkey"))
    177 		{
    178 		unsigned char *key;
    179 		int r;
    180 		long keylen;
    181 		key = string_to_hex(value, &keylen);
    182 		if (!key)
    183 			return 0;
    184 		r = pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key);
    185 		OPENSSL_free(key);
    186 		return r;
    187 		}
    188 	return -2;
    189 	}
    190 
    191 const EVP_PKEY_METHOD cmac_pkey_meth =
    192 	{
    193 	EVP_PKEY_CMAC,
    194 	EVP_PKEY_FLAG_SIGCTX_CUSTOM,
    195 	pkey_cmac_init,
    196 	pkey_cmac_copy,
    197 	pkey_cmac_cleanup,
    198 
    199 	0, 0,
    200 
    201 	0,
    202 	pkey_cmac_keygen,
    203 
    204 	0, 0,
    205 
    206 	0, 0,
    207 
    208 	0,0,
    209 
    210 	cmac_signctx_init,
    211 	cmac_signctx,
    212 
    213 	0,0,
    214 
    215 	0,0,
    216 
    217 	0,0,
    218 
    219 	0,0,
    220 
    221 	pkey_cmac_ctrl,
    222 	pkey_cmac_ctrl_str
    223 
    224 	};
    225