1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/krb/cmac.c */
4 * Copyright 2010 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 #include "crypto_int.h"
31 static unsigned char const_Rb[BLOCK_SIZE] = {
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
37 xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
41 for (z = 0; z < BLOCK_SIZE / 4; z++) {
42 unsigned char *aptr = &a[z * 4];
43 unsigned char *bptr = &b[z * 4];
44 unsigned char *outptr = &out[z * 4];
46 store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr);
51 leftshift_onebit(unsigned char *input, unsigned char *output)
54 unsigned char overflow = 0;
56 for (i = BLOCK_SIZE - 1; i >= 0; i--) {
57 output[i] = input[i] << 1;
58 output[i] |= overflow;
59 overflow = (input[i] & 0x80) ? 1 : 0;
63 /* Generate subkeys K1 and K2 as described in RFC 4493 figure 2.2. */
64 static krb5_error_code
65 generate_subkey(const struct krb5_enc_provider *enc,
70 unsigned char L[BLOCK_SIZE];
71 unsigned char tmp[BLOCK_SIZE];
75 /* L := encrypt(K, const_Zero) */
76 memset(L, 0, sizeof(L));
77 d = make_data(L, BLOCK_SIZE);
78 ret = encrypt_block(enc, key, &d);
82 /* K1 := (MSB(L) == 0) ? L << 1 : (L << 1) XOR const_Rb */
83 if ((L[0] & 0x80) == 0) {
84 leftshift_onebit(L, K1);
86 leftshift_onebit(L, tmp);
87 xor_128(tmp, const_Rb, K1);
90 /* K2 := (MSB(K1) == 0) ? K1 << 1 : (K1 << 1) XOR const_Rb */
91 if ((K1[0] & 0x80) == 0) {
92 leftshift_onebit(K1, K2);
94 leftshift_onebit(K1, tmp);
95 xor_128(tmp, const_Rb, K2);
101 /* Pad out lastb with a 1 bit followed by 0 bits, placing the result in pad. */
103 padding(unsigned char *lastb, unsigned char *pad, int length)
107 /* original last block */
108 for (j = 0; j < BLOCK_SIZE; j++) {
111 } else if (j == length) {
120 * Implementation of CMAC algorithm. When used with AES, this function
121 * is compatible with RFC 4493 figure 2.3.
124 krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
125 const krb5_crypto_iov *data, size_t num_data,
128 unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE];
129 unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE];
130 unsigned char input[BLOCK_SIZE];
131 unsigned int n, i, flag;
133 struct iov_cursor cursor;
135 krb5_crypto_iov iov[1];
138 assert(enc->cbc_mac != NULL);
140 if (enc->block_size != BLOCK_SIZE)
141 return KRB5_BAD_MSIZE;
143 length = iov_total_length(data, num_data, TRUE);
146 ret = generate_subkey(enc, key, K1, K2);
151 n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
158 flag = ((length % BLOCK_SIZE) == 0);
161 iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
162 iov[0].data = make_data(input, BLOCK_SIZE);
164 /* Step 5 (we'll do step 4 in a bit). */
165 memset(Y, 0, BLOCK_SIZE);
166 d = make_data(Y, BLOCK_SIZE);
168 /* Step 6 (all but last block). */
169 k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, TRUE);
170 for (i = 0; i < n - 1; i++) {
171 k5_iov_cursor_get(&cursor, input);
173 ret = enc->cbc_mac(key, iov, 1, &d, &d);
179 k5_iov_cursor_get(&cursor, input);
181 /* last block is complete block */
182 xor_128(input, K1, M_last);
184 padding(input, padded, length % BLOCK_SIZE);
185 xor_128(padded, K2, M_last);
188 /* Step 6 (last block). */
189 iov[0].data = make_data(M_last, BLOCK_SIZE);
190 ret = enc->cbc_mac(key, iov, 1, &d, &d);
194 assert(output->length >= d.length);
196 output->length = d.length;
197 memcpy(output->data, d.data, d.length);