Branch data Line data Source code
1 : : /* crypto/cmac/cmac.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 2010 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : */
53 : :
54 : : #define OPENSSL_FIPSAPI
55 : :
56 : : #include <stdio.h>
57 : : #include <stdlib.h>
58 : : #include <string.h>
59 : : #include "cryptlib.h"
60 : : #include <openssl/cmac.h>
61 : :
62 : : struct CMAC_CTX_st
63 : : {
64 : : /* Cipher context to use */
65 : : EVP_CIPHER_CTX cctx;
66 : : /* Keys k1 and k2 */
67 : : unsigned char k1[EVP_MAX_BLOCK_LENGTH];
68 : : unsigned char k2[EVP_MAX_BLOCK_LENGTH];
69 : : /* Temporary block */
70 : : unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
71 : : /* Last (possibly partial) block */
72 : : unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
73 : : /* Number of bytes in last block: -1 means context not initialised */
74 : : int nlast_block;
75 : : };
76 : :
77 : :
78 : : /* Make temporary keys K1 and K2 */
79 : :
80 : 0 : static void make_kn(unsigned char *k1, const unsigned char *l, int bl)
81 : : {
82 : : int i;
83 : 0 : unsigned char c = l[0], carry = c>>7, cnext;
84 : :
85 : : /* Shift block to left, including carry */
86 [ # # ]: 0 : for (i = 0; i < bl-1; i++, c = cnext)
87 : 0 : k1[i] = (c << 1) | ((cnext=l[i+1]) >> 7);
88 : :
89 : : /* If MSB set fixup with R */
90 [ # # ]: 0 : k1[i] = (c << 1) ^ ((0-carry)&(bl==16?0x87:0x1b));
91 : 0 : }
92 : :
93 : 0 : CMAC_CTX *CMAC_CTX_new(void)
94 : : {
95 : : CMAC_CTX *ctx;
96 : 0 : ctx = OPENSSL_malloc(sizeof(CMAC_CTX));
97 [ # # ]: 0 : if (!ctx)
98 : : return NULL;
99 : 0 : EVP_CIPHER_CTX_init(&ctx->cctx);
100 : 0 : ctx->nlast_block = -1;
101 : 0 : return ctx;
102 : : }
103 : :
104 : 0 : void CMAC_CTX_cleanup(CMAC_CTX *ctx)
105 : : {
106 : 0 : EVP_CIPHER_CTX_cleanup(&ctx->cctx);
107 : 0 : OPENSSL_cleanse(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
108 : 0 : OPENSSL_cleanse(ctx->k1, EVP_MAX_BLOCK_LENGTH);
109 : 0 : OPENSSL_cleanse(ctx->k2, EVP_MAX_BLOCK_LENGTH);
110 : 0 : OPENSSL_cleanse(ctx->last_block, EVP_MAX_BLOCK_LENGTH);
111 : 0 : ctx->nlast_block = -1;
112 : 0 : }
113 : :
114 : 0 : EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
115 : : {
116 : 0 : return &ctx->cctx;
117 : : }
118 : :
119 : 0 : void CMAC_CTX_free(CMAC_CTX *ctx)
120 : : {
121 : 0 : CMAC_CTX_cleanup(ctx);
122 : 0 : OPENSSL_free(ctx);
123 : 0 : }
124 : :
125 : 0 : int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
126 : : {
127 : : int bl;
128 [ # # ]: 0 : if (in->nlast_block == -1)
129 : : return 0;
130 [ # # ]: 0 : if (!EVP_CIPHER_CTX_copy(&out->cctx, &in->cctx))
131 : : return 0;
132 : 0 : bl = M_EVP_CIPHER_CTX_block_size(&in->cctx);
133 : 0 : memcpy(out->k1, in->k1, bl);
134 : 0 : memcpy(out->k2, in->k2, bl);
135 : 0 : memcpy(out->tbl, in->tbl, bl);
136 : 0 : memcpy(out->last_block, in->last_block, bl);
137 : 0 : out->nlast_block = in->nlast_block;
138 : 0 : return 1;
139 : : }
140 : :
141 : 0 : int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
142 : : const EVP_CIPHER *cipher, ENGINE *impl)
143 : : {
144 : : __fips_constseg
145 : : static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = {0};
146 : : /* All zeros means restart */
147 [ # # ][ # # ]: 0 : if (!key && !cipher && !impl && keylen == 0)
148 : : {
149 : : /* Not initialised */
150 [ # # ]: 0 : if (ctx->nlast_block == -1)
151 : : return 0;
152 [ # # ]: 0 : if (!M_EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
153 : : return 0;
154 : 0 : memset(ctx->tbl, 0, M_EVP_CIPHER_CTX_block_size(&ctx->cctx));
155 : 0 : ctx->nlast_block = 0;
156 : 0 : return 1;
157 : : }
158 : : /* Initialiase context */
159 [ # # ][ # # ]: 0 : if (cipher && !M_EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
160 : : return 0;
161 : : /* Non-NULL key means initialisation complete */
162 [ # # ]: 0 : if (key)
163 : : {
164 : : int bl;
165 [ # # ]: 0 : if (!M_EVP_CIPHER_CTX_cipher(&ctx->cctx))
166 : : return 0;
167 [ # # ]: 0 : if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen))
168 : : return 0;
169 [ # # ]: 0 : if (!M_EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv))
170 : : return 0;
171 : 0 : bl = M_EVP_CIPHER_CTX_block_size(&ctx->cctx);
172 [ # # ]: 0 : if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl))
173 : : return 0;
174 : 0 : make_kn(ctx->k1, ctx->tbl, bl);
175 : 0 : make_kn(ctx->k2, ctx->k1, bl);
176 : 0 : OPENSSL_cleanse(ctx->tbl, bl);
177 : : /* Reset context again ready for first data block */
178 [ # # ]: 0 : if (!M_EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
179 : : return 0;
180 : : /* Zero tbl so resume works */
181 : 0 : memset(ctx->tbl, 0, bl);
182 : 0 : ctx->nlast_block = 0;
183 : : }
184 : : return 1;
185 : : }
186 : :
187 : 0 : int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
188 : : {
189 : 0 : const unsigned char *data = in;
190 : : size_t bl;
191 [ # # ]: 0 : if (ctx->nlast_block == -1)
192 : : return 0;
193 [ # # ]: 0 : if (dlen == 0)
194 : : return 1;
195 : 0 : bl = M_EVP_CIPHER_CTX_block_size(&ctx->cctx);
196 : : /* Copy into partial block if we need to */
197 [ # # ]: 0 : if (ctx->nlast_block > 0)
198 : : {
199 : : size_t nleft;
200 : 0 : nleft = bl - ctx->nlast_block;
201 [ # # ]: 0 : if (dlen < nleft)
202 : 0 : nleft = dlen;
203 : 0 : memcpy(ctx->last_block + ctx->nlast_block, data, nleft);
204 : 0 : dlen -= nleft;
205 : 0 : ctx->nlast_block += nleft;
206 : : /* If no more to process return */
207 [ # # ]: 0 : if (dlen == 0)
208 : : return 1;
209 : 0 : data += nleft;
210 : : /* Else not final block so encrypt it */
211 [ # # ]: 0 : if (!EVP_Cipher(&ctx->cctx, ctx->tbl, ctx->last_block,bl))
212 : : return 0;
213 : : }
214 : : /* Encrypt all but one of the complete blocks left */
215 [ # # ]: 0 : while(dlen > bl)
216 : : {
217 [ # # ]: 0 : if (!EVP_Cipher(&ctx->cctx, ctx->tbl, data, bl))
218 : : return 0;
219 : 0 : dlen -= bl;
220 : 0 : data += bl;
221 : : }
222 : : /* Copy any data left to last block buffer */
223 : 0 : memcpy(ctx->last_block, data, dlen);
224 : 0 : ctx->nlast_block = dlen;
225 : 0 : return 1;
226 : :
227 : : }
228 : :
229 : 0 : int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
230 : : {
231 : : int i, bl, lb;
232 [ # # ]: 0 : if (ctx->nlast_block == -1)
233 : : return 0;
234 : 0 : bl = M_EVP_CIPHER_CTX_block_size(&ctx->cctx);
235 : 0 : *poutlen = (size_t)bl;
236 [ # # ]: 0 : if (!out)
237 : : return 1;
238 : 0 : lb = ctx->nlast_block;
239 : : /* Is last block complete? */
240 [ # # ]: 0 : if (lb == bl)
241 : : {
242 [ # # ]: 0 : for (i = 0; i < bl; i++)
243 : 0 : out[i] = ctx->last_block[i] ^ ctx->k1[i];
244 : : }
245 : : else
246 : : {
247 : 0 : ctx->last_block[lb] = 0x80;
248 [ # # ]: 0 : if (bl - lb > 1)
249 : 0 : memset(ctx->last_block + lb + 1, 0, bl - lb - 1);
250 [ # # ]: 0 : for (i = 0; i < bl; i++)
251 : 0 : out[i] = ctx->last_block[i] ^ ctx->k2[i];
252 : : }
253 [ # # ]: 0 : if (!EVP_Cipher(&ctx->cctx, out, out, bl))
254 : : {
255 : 0 : OPENSSL_cleanse(out, bl);
256 : 0 : return 0;
257 : : }
258 : : return 1;
259 : : }
260 : :
261 : 0 : int CMAC_resume(CMAC_CTX *ctx)
262 : : {
263 [ # # ]: 0 : if (ctx->nlast_block == -1)
264 : : return 0;
265 : : /* The buffer "tbl" containes the last fully encrypted block
266 : : * which is the last IV (or all zeroes if no last encrypted block).
267 : : * The last block has not been modified since CMAC_final().
268 : : * So reinitliasing using the last decrypted block will allow
269 : : * CMAC to continue after calling CMAC_Final().
270 : : */
271 : 0 : return M_EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, ctx->tbl);
272 : : }
|