]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bcal-cmac.c
7d774e6ecead9834183f5506ec1c6df2b61c5f94
[avr-crypto-lib.git] / bcal-cmac.c
1 /* bcal-omac.c */
2 /*
3  This file is part of the AVR-Crypto-Lib.
4  Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
5
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdint.h>
21 #include <string.h>
22 #include "bcal-basic.h"
23 #include "bcal-cmac.h"
24 #include "memxor.h"
25
26 static uint8_t left_shift_be_block(void *block, uint8_t blocksize_B)
27 {
28     uint8_t c1 = 0, c2;
29     do {
30         --blocksize_B;
31         c2 = (((uint8_t*) block)[blocksize_B]) >> 7;
32         (((uint8_t*) block)[blocksize_B]) <<= 1;
33         (((uint8_t*) block)[blocksize_B]) |= c1;
34         c1 = c2;
35     } while (blocksize_B);
36     return c1;
37 }
38
39 static const uint8_t const_128 = 0x87;
40 static const uint8_t const_64 = 0x1b;
41
42 uint8_t bcal_cmac_init(const bcdesc_t *desc, const void *key,
43         uint16_t keysize_b, bcal_cmac_ctx_t *ctx)
44 {
45     uint8_t r;
46     ctx->desc = (bcdesc_t*) desc;
47     ctx->blocksize_B = bcal_cipher_getBlocksize_b(desc) / 8;
48     if (ctx->blocksize_B != 128 / 8 && ctx->blocksize_B != 64 / 8) {
49         return 0x13;
50     }
51     ctx->accu = malloc(ctx->blocksize_B);
52     if (ctx->accu == NULL) {
53         return 0x14;
54     }
55     ctx->k1 = malloc(ctx->blocksize_B);
56     if (ctx->k1 == NULL) {
57         return 0x15;
58     }
59     ctx->k2 = malloc(ctx->blocksize_B);
60     if (ctx->k2 == NULL) {
61         return 0x16;
62     }
63     ctx->lastblock = malloc(ctx->blocksize_B);
64     if (ctx->lastblock == NULL) {
65         return 0x17;
66     }
67     r = bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
68     if (r) {
69         return r;
70     }
71     if (ctx->blocksize_B == 128 / 8) {
72         r = const_128;
73     } else {
74         r = const_64;
75     }
76     /* subkey computation */
77     memset(ctx->accu, 0x00, ctx->blocksize_B);
78     memset(ctx->k1, 0x00, ctx->blocksize_B);
79     bcal_cipher_enc(ctx->k1, &(ctx->cctx));
80     if (left_shift_be_block(ctx->k1, ctx->blocksize_B)) {
81         ctx->k1[ctx->blocksize_B - 1] ^= r;
82     }
83     memcpy(ctx->k2, ctx->k1, ctx->blocksize_B);
84     if (left_shift_be_block(ctx->k2, ctx->blocksize_B)) {
85         ctx->k2[ctx->blocksize_B - 1] ^= r;
86     }
87     ctx->last_set = 0;
88     return 0;
89 }
90
91 void bcal_cmac_free(bcal_cmac_ctx_t *ctx)
92 {
93     free(ctx->accu);
94     free(ctx->k1);
95     free(ctx->k2);
96     bcal_cipher_free(&(ctx->cctx));
97 }
98
99 void bcal_cmac_nextBlock(bcal_cmac_ctx_t *ctx, const void *block)
100 {
101     if (ctx->last_set) {
102         memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
103         bcal_cipher_enc(ctx->accu, &(ctx->cctx));
104     }
105     memcpy(ctx->lastblock, block, ctx->blocksize_B);
106     ctx->last_set = 1;
107 }
108
109 void bcal_cmac_lastBlock(bcal_cmac_ctx_t *ctx, const void *block,
110         uint16_t length_b)
111 {
112     uint16_t blocksize_b;
113     blocksize_b = ctx->blocksize_B * 8;
114     while (length_b >= blocksize_b) {
115         bcal_cmac_nextBlock(ctx, block);
116         block = (uint8_t*) block + ctx->blocksize_B;
117         length_b -= blocksize_b;
118     }
119     if (ctx->last_set == 0) {
120         memxor(ctx->accu, block, (length_b + 7) / 8);
121         memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
122         ctx->accu[length_b / 8] ^= 0x80 >> (length_b & 7);
123     } else {
124         if (length_b == 0) {
125             memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
126             memxor(ctx->accu, ctx->k1, ctx->blocksize_B);
127         } else {
128             memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
129             bcal_cipher_enc(ctx->accu, &(ctx->cctx));
130             memxor(ctx->accu, block, (length_b + 7) / 8);
131             memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
132             ctx->accu[length_b / 8] ^= 0x80 >> (length_b & 7);
133         }
134     }
135     bcal_cipher_enc(ctx->accu, &(ctx->cctx));
136 }
137
138 void bcal_cmac_ctx2mac(void *dest, uint16_t length_b,
139         const bcal_cmac_ctx_t *ctx)
140 {
141     memcpy(dest, ctx->accu, length_b / 8);
142     if (length_b & 7) {
143         ((uint8_t*) dest)[length_b / 8] &= 0xff >> (length_b & 7);
144         ((uint8_t*) dest)[length_b / 8] |= (0xff00 >> (length_b & 7))
145                 & (ctx->accu[length_b / 8]);
146     }
147 }
148
149 void bcal_cmac(void *dest, uint16_t out_length_b, const void *block,
150         uint32_t length_b, bcal_cmac_ctx_t *ctx)
151 {
152     uint16_t blocksize_b;
153     blocksize_b = ctx->blocksize_B * 8;
154     while (length_b > blocksize_b) {
155         bcal_cmac_nextBlock(ctx, block);
156         block = (uint8_t*) block + ctx->blocksize_B;
157         length_b -= blocksize_b;
158     }
159     bcal_cmac_lastBlock(ctx, block, length_b);
160     bcal_cmac_ctx2mac(dest, out_length_b, ctx);
161 }