1238384Sjkim/* crypto/cmac/cmac.c */
2296341Sdelphij/*
3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4238384Sjkim * project.
5238384Sjkim */
6238384Sjkim/* ====================================================================
7238384Sjkim * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
8238384Sjkim *
9238384Sjkim * Redistribution and use in source and binary forms, with or without
10238384Sjkim * modification, are permitted provided that the following conditions
11238384Sjkim * are met:
12238384Sjkim *
13238384Sjkim * 1. Redistributions of source code must retain the above copyright
14296341Sdelphij *    notice, this list of conditions and the following disclaimer.
15238384Sjkim *
16238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
17238384Sjkim *    notice, this list of conditions and the following disclaimer in
18238384Sjkim *    the documentation and/or other materials provided with the
19238384Sjkim *    distribution.
20238384Sjkim *
21238384Sjkim * 3. All advertising materials mentioning features or use of this
22238384Sjkim *    software must display the following acknowledgment:
23238384Sjkim *    "This product includes software developed by the OpenSSL Project
24238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25238384Sjkim *
26238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27238384Sjkim *    endorse or promote products derived from this software without
28238384Sjkim *    prior written permission. For written permission, please contact
29238384Sjkim *    licensing@OpenSSL.org.
30238384Sjkim *
31238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
32238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
33238384Sjkim *    permission of the OpenSSL Project.
34238384Sjkim *
35238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
36238384Sjkim *    acknowledgment:
37238384Sjkim *    "This product includes software developed by the OpenSSL Project
38238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39238384Sjkim *
40238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
52238384Sjkim * ====================================================================
53238384Sjkim */
54238384Sjkim
55238384Sjkim#include <stdio.h>
56238384Sjkim#include <stdlib.h>
57238384Sjkim#include <string.h>
58238384Sjkim#include "cryptlib.h"
59238384Sjkim#include <openssl/cmac.h>
60238384Sjkim
61238384Sjkim#ifdef OPENSSL_FIPS
62296341Sdelphij# include <openssl/fips.h>
63238384Sjkim#endif
64238384Sjkim
65296341Sdelphijstruct CMAC_CTX_st {
66296341Sdelphij    /* Cipher context to use */
67296341Sdelphij    EVP_CIPHER_CTX cctx;
68296341Sdelphij    /* Keys k1 and k2 */
69296341Sdelphij    unsigned char k1[EVP_MAX_BLOCK_LENGTH];
70296341Sdelphij    unsigned char k2[EVP_MAX_BLOCK_LENGTH];
71296341Sdelphij    /* Temporary block */
72296341Sdelphij    unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
73296341Sdelphij    /* Last (possibly partial) block */
74296341Sdelphij    unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
75296341Sdelphij    /* Number of bytes in last block: -1 means context not initialised */
76296341Sdelphij    int nlast_block;
77296341Sdelphij};
78238384Sjkim
79238384Sjkim/* Make temporary keys K1 and K2 */
80238384Sjkim
81238384Sjkimstatic void make_kn(unsigned char *k1, unsigned char *l, int bl)
82296341Sdelphij{
83296341Sdelphij    int i;
84296341Sdelphij    /* Shift block to left, including carry */
85296341Sdelphij    for (i = 0; i < bl; i++) {
86296341Sdelphij        k1[i] = l[i] << 1;
87296341Sdelphij        if (i < bl - 1 && l[i + 1] & 0x80)
88296341Sdelphij            k1[i] |= 1;
89296341Sdelphij    }
90296341Sdelphij    /* If MSB set fixup with R */
91296341Sdelphij    if (l[0] & 0x80)
92296341Sdelphij        k1[bl - 1] ^= bl == 16 ? 0x87 : 0x1b;
93296341Sdelphij}
94238384Sjkim
95238384SjkimCMAC_CTX *CMAC_CTX_new(void)
96296341Sdelphij{
97296341Sdelphij    CMAC_CTX *ctx;
98296341Sdelphij    ctx = OPENSSL_malloc(sizeof(CMAC_CTX));
99296341Sdelphij    if (!ctx)
100296341Sdelphij        return NULL;
101296341Sdelphij    EVP_CIPHER_CTX_init(&ctx->cctx);
102296341Sdelphij    ctx->nlast_block = -1;
103296341Sdelphij    return ctx;
104296341Sdelphij}
105238384Sjkim
106238384Sjkimvoid CMAC_CTX_cleanup(CMAC_CTX *ctx)
107296341Sdelphij{
108238384Sjkim#ifdef OPENSSL_FIPS
109296341Sdelphij    if (FIPS_mode() && !ctx->cctx.engine) {
110296341Sdelphij        FIPS_cmac_ctx_cleanup(ctx);
111296341Sdelphij        return;
112296341Sdelphij    }
113238384Sjkim#endif
114296341Sdelphij    EVP_CIPHER_CTX_cleanup(&ctx->cctx);
115296341Sdelphij    OPENSSL_cleanse(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
116296341Sdelphij    OPENSSL_cleanse(ctx->k1, EVP_MAX_BLOCK_LENGTH);
117296341Sdelphij    OPENSSL_cleanse(ctx->k2, EVP_MAX_BLOCK_LENGTH);
118296341Sdelphij    OPENSSL_cleanse(ctx->last_block, EVP_MAX_BLOCK_LENGTH);
119296341Sdelphij    ctx->nlast_block = -1;
120296341Sdelphij}
121238384Sjkim
122238384SjkimEVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
123296341Sdelphij{
124296341Sdelphij    return &ctx->cctx;
125296341Sdelphij}
126238384Sjkim
127238384Sjkimvoid CMAC_CTX_free(CMAC_CTX *ctx)
128296341Sdelphij{
129296341Sdelphij    if (!ctx)
130296341Sdelphij        return;
131296341Sdelphij    CMAC_CTX_cleanup(ctx);
132296341Sdelphij    OPENSSL_free(ctx);
133296341Sdelphij}
134238384Sjkim
135238384Sjkimint CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
136296341Sdelphij{
137296341Sdelphij    int bl;
138296341Sdelphij    if (in->nlast_block == -1)
139296341Sdelphij        return 0;
140296341Sdelphij    if (!EVP_CIPHER_CTX_copy(&out->cctx, &in->cctx))
141296341Sdelphij        return 0;
142296341Sdelphij    bl = EVP_CIPHER_CTX_block_size(&in->cctx);
143296341Sdelphij    memcpy(out->k1, in->k1, bl);
144296341Sdelphij    memcpy(out->k2, in->k2, bl);
145296341Sdelphij    memcpy(out->tbl, in->tbl, bl);
146296341Sdelphij    memcpy(out->last_block, in->last_block, bl);
147296341Sdelphij    out->nlast_block = in->nlast_block;
148296341Sdelphij    return 1;
149296341Sdelphij}
150238384Sjkim
151296341Sdelphijint CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
152296341Sdelphij              const EVP_CIPHER *cipher, ENGINE *impl)
153296341Sdelphij{
154296341Sdelphij    static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
155238384Sjkim#ifdef OPENSSL_FIPS
156296341Sdelphij    if (FIPS_mode()) {
157296341Sdelphij        /* If we have an ENGINE need to allow non FIPS */
158296341Sdelphij        if ((impl || ctx->cctx.engine)
159296341Sdelphij            && !(ctx->cctx.flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) {
160296341Sdelphij            EVPerr(EVP_F_CMAC_INIT, EVP_R_DISABLED_FOR_FIPS);
161296341Sdelphij            return 0;
162296341Sdelphij        }
163296341Sdelphij        /*
164296341Sdelphij         * Other algorithm blocking will be done in FIPS_cmac_init, via
165296341Sdelphij         * FIPS_cipherinit().
166296341Sdelphij         */
167296341Sdelphij        if (!impl && !ctx->cctx.engine)
168296341Sdelphij            return FIPS_cmac_init(ctx, key, keylen, cipher, NULL);
169296341Sdelphij    }
170238384Sjkim#endif
171296341Sdelphij    /* All zeros means restart */
172296341Sdelphij    if (!key && !cipher && !impl && keylen == 0) {
173296341Sdelphij        /* Not initialised */
174296341Sdelphij        if (ctx->nlast_block == -1)
175296341Sdelphij            return 0;
176296341Sdelphij        if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
177296341Sdelphij            return 0;
178296341Sdelphij        memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(&ctx->cctx));
179296341Sdelphij        ctx->nlast_block = 0;
180296341Sdelphij        return 1;
181296341Sdelphij    }
182296341Sdelphij    /* Initialiase context */
183296341Sdelphij    if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
184296341Sdelphij        return 0;
185296341Sdelphij    /* Non-NULL key means initialisation complete */
186296341Sdelphij    if (key) {
187296341Sdelphij        int bl;
188296341Sdelphij        if (!EVP_CIPHER_CTX_cipher(&ctx->cctx))
189296341Sdelphij            return 0;
190296341Sdelphij        if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen))
191296341Sdelphij            return 0;
192296341Sdelphij        if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv))
193296341Sdelphij            return 0;
194296341Sdelphij        bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
195296341Sdelphij        if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl))
196296341Sdelphij            return 0;
197296341Sdelphij        make_kn(ctx->k1, ctx->tbl, bl);
198296341Sdelphij        make_kn(ctx->k2, ctx->k1, bl);
199296341Sdelphij        OPENSSL_cleanse(ctx->tbl, bl);
200296341Sdelphij        /* Reset context again ready for first data block */
201296341Sdelphij        if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
202296341Sdelphij            return 0;
203296341Sdelphij        /* Zero tbl so resume works */
204296341Sdelphij        memset(ctx->tbl, 0, bl);
205296341Sdelphij        ctx->nlast_block = 0;
206296341Sdelphij    }
207296341Sdelphij    return 1;
208296341Sdelphij}
209238384Sjkim
210238384Sjkimint CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
211296341Sdelphij{
212296341Sdelphij    const unsigned char *data = in;
213296341Sdelphij    size_t bl;
214238384Sjkim#ifdef OPENSSL_FIPS
215296341Sdelphij    if (FIPS_mode() && !ctx->cctx.engine)
216296341Sdelphij        return FIPS_cmac_update(ctx, in, dlen);
217238384Sjkim#endif
218296341Sdelphij    if (ctx->nlast_block == -1)
219296341Sdelphij        return 0;
220296341Sdelphij    if (dlen == 0)
221296341Sdelphij        return 1;
222296341Sdelphij    bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
223296341Sdelphij    /* Copy into partial block if we need to */
224296341Sdelphij    if (ctx->nlast_block > 0) {
225296341Sdelphij        size_t nleft;
226296341Sdelphij        nleft = bl - ctx->nlast_block;
227296341Sdelphij        if (dlen < nleft)
228296341Sdelphij            nleft = dlen;
229296341Sdelphij        memcpy(ctx->last_block + ctx->nlast_block, data, nleft);
230296341Sdelphij        dlen -= nleft;
231296341Sdelphij        ctx->nlast_block += nleft;
232296341Sdelphij        /* If no more to process return */
233296341Sdelphij        if (dlen == 0)
234296341Sdelphij            return 1;
235296341Sdelphij        data += nleft;
236296341Sdelphij        /* Else not final block so encrypt it */
237296341Sdelphij        if (!EVP_Cipher(&ctx->cctx, ctx->tbl, ctx->last_block, bl))
238296341Sdelphij            return 0;
239296341Sdelphij    }
240296341Sdelphij    /* Encrypt all but one of the complete blocks left */
241296341Sdelphij    while (dlen > bl) {
242296341Sdelphij        if (!EVP_Cipher(&ctx->cctx, ctx->tbl, data, bl))
243296341Sdelphij            return 0;
244296341Sdelphij        dlen -= bl;
245296341Sdelphij        data += bl;
246296341Sdelphij    }
247296341Sdelphij    /* Copy any data left to last block buffer */
248296341Sdelphij    memcpy(ctx->last_block, data, dlen);
249296341Sdelphij    ctx->nlast_block = dlen;
250296341Sdelphij    return 1;
251238384Sjkim
252296341Sdelphij}
253238384Sjkim
254238384Sjkimint CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
255296341Sdelphij{
256296341Sdelphij    int i, bl, lb;
257238384Sjkim#ifdef OPENSSL_FIPS
258296341Sdelphij    if (FIPS_mode() && !ctx->cctx.engine)
259296341Sdelphij        return FIPS_cmac_final(ctx, out, poutlen);
260238384Sjkim#endif
261296341Sdelphij    if (ctx->nlast_block == -1)
262296341Sdelphij        return 0;
263296341Sdelphij    bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
264296341Sdelphij    *poutlen = (size_t)bl;
265296341Sdelphij    if (!out)
266296341Sdelphij        return 1;
267296341Sdelphij    lb = ctx->nlast_block;
268296341Sdelphij    /* Is last block complete? */
269296341Sdelphij    if (lb == bl) {
270296341Sdelphij        for (i = 0; i < bl; i++)
271296341Sdelphij            out[i] = ctx->last_block[i] ^ ctx->k1[i];
272296341Sdelphij    } else {
273296341Sdelphij        ctx->last_block[lb] = 0x80;
274296341Sdelphij        if (bl - lb > 1)
275296341Sdelphij            memset(ctx->last_block + lb + 1, 0, bl - lb - 1);
276296341Sdelphij        for (i = 0; i < bl; i++)
277296341Sdelphij            out[i] = ctx->last_block[i] ^ ctx->k2[i];
278296341Sdelphij    }
279296341Sdelphij    if (!EVP_Cipher(&ctx->cctx, out, out, bl)) {
280296341Sdelphij        OPENSSL_cleanse(out, bl);
281296341Sdelphij        return 0;
282296341Sdelphij    }
283296341Sdelphij    return 1;
284296341Sdelphij}
285238384Sjkim
286238384Sjkimint CMAC_resume(CMAC_CTX *ctx)
287296341Sdelphij{
288296341Sdelphij    if (ctx->nlast_block == -1)
289296341Sdelphij        return 0;
290296341Sdelphij    /*
291296341Sdelphij     * The buffer "tbl" containes the last fully encrypted block which is the
292296341Sdelphij     * last IV (or all zeroes if no last encrypted block). The last block has
293296341Sdelphij     * not been modified since CMAC_final(). So reinitliasing using the last
294296341Sdelphij     * decrypted block will allow CMAC to continue after calling
295296341Sdelphij     * CMAC_Final().
296296341Sdelphij     */
297296341Sdelphij    return EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, ctx->tbl);
298296341Sdelphij}
299