Network Working Group                                           JH. Song
Request for Comments: 4493                                 R. Poovendran
Category: Informational                         University of Washington
                                                                  J. Lee
                                                     Samsung Electronics
                                                                T. Iwata
                                                       Nagoya University
                                                               June 2006
        
Network Working Group                                           JH. Song
Request for Comments: 4493                                 R. Poovendran
Category: Informational                         University of Washington
                                                                  J. Lee
                                                     Samsung Electronics
                                                                T. Iwata
                                                       Nagoya University
                                                               June 2006
        

The AES-CMAC Algorithm

AES-CMAC算法

Status of This Memo

关于下段备忘

This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.

本备忘录为互联网社区提供信息。它没有规定任何类型的互联网标准。本备忘录的分发不受限制。

Copyright Notice

版权公告

Copyright (C) The Internet Society (2006).

版权所有(C)互联网协会(2006年)。

Abstract

摘要

The National Institute of Standards and Technology (NIST) has recently specified the Cipher-based Message Authentication Code (CMAC), which is equivalent to the One-Key CBC MAC1 (OMAC1) submitted by Iwata and Kurosawa. This memo specifies an authentication algorithm based on CMAC with the 128-bit Advanced Encryption Standard (AES). This new authentication algorithm is named AES-CMAC. The purpose of this document is to make the AES-CMAC algorithm conveniently available to the Internet Community.

国家标准与技术研究所(NIST)最近指定了基于密码的消息认证码(CMAC),它相当于岩田和黑泽东彦提交的一键CBC MAC1(OMAC1)。本备忘录规定了一种基于CMAC和128位高级加密标准(AES)的认证算法。这种新的认证算法称为AES-CMAC。本文档的目的是使AES-CMAC算法方便地提供给互联网社区。

Table of Contents

目录

   1. Introduction ....................................................2
   2. Specification of AES-CMAC .......................................3
      2.1. Basic Definitions ..........................................3
      2.2. Overview ...................................................4
      2.3. Subkey Generation Algorithm ................................5
      2.4. MAC Generation Algorithm ...................................7
      2.5. MAC Verification Algorithm .................................9
   3. Security Considerations ........................................10
   4. Test Vectors ...................................................11
   5. Acknowledgement ................................................12
   6. References .....................................................12
      6.1. Normative References ......................................12
      6.2. Informative References ....................................12
   Appendix A. Test Code .............................................14
        
   1. Introduction ....................................................2
   2. Specification of AES-CMAC .......................................3
      2.1. Basic Definitions ..........................................3
      2.2. Overview ...................................................4
      2.3. Subkey Generation Algorithm ................................5
      2.4. MAC Generation Algorithm ...................................7
      2.5. MAC Verification Algorithm .................................9
   3. Security Considerations ........................................10
   4. Test Vectors ...................................................11
   5. Acknowledgement ................................................12
   6. References .....................................................12
      6.1. Normative References ......................................12
      6.2. Informative References ....................................12
   Appendix A. Test Code .............................................14
        
1. Introduction
1. 介绍

The National Institute of Standards and Technology (NIST) has recently specified the Cipher-based Message Authentication Code (CMAC). CMAC [NIST-CMAC] is a keyed hash function that is based on a symmetric key block cipher, such as the Advanced Encryption Standard [NIST-AES]. CMAC is equivalent to the One-Key CBC MAC1 (OMAC1) submitted by Iwata and Kurosawa [OMAC1a, OMAC1b]. OMAC1 is an improvement of the eXtended Cipher Block Chaining mode (XCBC) submitted by Black and Rogaway [XCBCa, XCBCb], which itself is an improvement of the basic Cipher Block Chaining-Message Authentication Code (CBC-MAC). XCBC efficiently addresses the security deficiencies of CBC-MAC, and OMAC1 efficiently reduces the key size of XCBC.

国家标准与技术研究所(NIST)最近指定了基于密码的消息认证码(CMAC)。CMAC[NIST-CMAC]是一种基于对称密钥分组密码的密钥散列函数,如高级加密标准[NIST-AES]。CMAC相当于岩田和黑泽东彦提交的一个关键CBC MAC1(OMAC1)[OMAC1a,OMAC1b]。OMAC1是Black和Rogaway[XCBCa,XCBCb]提交的扩展密码块链接模式(XCBC)的改进,其本身是基本密码块链接消息认证码(CBC-MAC)的改进。XCBC有效地解决了CBC-MAC的安全缺陷,OMAC1有效地减少了XCBC的密钥大小。

AES-CMAC provides stronger assurance of data integrity than a checksum or an error-detecting code. The verification of a checksum or an error-detecting code detects only accidental modifications of the data, while CMAC is designed to detect intentional, unauthorized modifications of the data, as well as accidental modifications.

AES-CMAC提供了比校验和或错误检测代码更强的数据完整性保证。校验和或错误检测代码的验证仅检测数据的意外修改,而CMAC旨在检测数据的有意、未经授权的修改以及意外修改。

AES-CMAC achieves a security goal similar to that of HMAC [RFC-HMAC]. Since AES-CMAC is based on a symmetric key block cipher, AES, and HMAC is based on a hash function, such as SHA-1, AES-CMAC is appropriate for information systems in which AES is more readily available than a hash function.

AES-CMAC实现了与HMAC[RFC-HMAC]类似的安全目标。由于AES-CMAC基于对称密钥分组密码AES,而HMAC基于散列函数(如SHA-1),因此AES-CMAC适用于AES比散列函数更容易获得的信息系统。

This memo specifies the authentication algorithm based on CMAC with AES-128. This new authentication algorithm is named AES-CMAC.

本备忘录规定了基于CMAC和AES-128的认证算法。这种新的认证算法称为AES-CMAC。

2. Specification of AES-CMAC
2. AES-CMAC规范
2.1. Basic Definitions
2.1. 基本定义

The following table describes the basic definitions necessary to explain the specification of AES-CMAC.

下表描述了解释AES-CMAC规范所需的基本定义。

x || y Concatenation. x || y is the string x concatenated with the string y. 0000 || 1111 is 00001111.

x | | y串联。x | | y是与字符串y连接的字符串x。0000 | | 1111是00001111。

x XOR y Exclusive-OR operation. For two equal length strings, x and y, x XOR y is their bit-wise exclusive-OR.

x或y异或运算。对于两个等长字符串x和y,x或y是它们的位异或。

ceil(x) Ceiling function. The smallest integer no smaller than x. ceil(3.5) is 4. ceil(5) is 5.

天花板(x)天花板功能。不小于x的最小整数。ceil(3.5)为4。ceil(5)是5。

x << 1 Left-shift of the string x by 1 bit. The most significant bit disappears, and a zero comes into the least significant bit. 10010001 << 1 is 00100010.

x<<字符串x左移1位。最高有效位消失,零进入最低有效位。10010001<<1是00100010。

0^n The string that consists of n zero-bits. 0^3 means 000 in binary format. 10^4 means 10000 in binary format. 10^i means 1 followed by i-times repeated zeros.

0^n由n个零位组成的字符串。0^3表示二进制格式的000。10^4表示二进制格式的10000。10^ i表示1后跟i乘以重复的零。

MSB(x) The most-significant bit of the string x. MSB(10010000) means 1.

MSB(x)字符串x的最高有效位。MSB(10010000)表示1。

padding(x) 10^i padded output of input x. It is described in detail in section 2.4.

填充(x)10^i输入x的填充输出。第2.4节对其进行了详细描述。

Key 128-bit (16-octet) long key for AES-128. Denoted by K.

AES-128的128位(16八位)长密钥。用K表示。

First subkey 128-bit (16-octet) long first subkey, derived through the subkey generation algorithm from the key K. Denoted by K1.

第一子密钥128位(16八位字节)长的第一子密钥,通过子密钥生成算法从密钥K中导出。由K1表示。

Second subkey 128-bit (16-octet) long second subkey, derived through the subkey generation algorithm from the key K. Denoted by K2.

第二子密钥128位(16个八位组)长的第二子密钥,通过子密钥生成算法从密钥K中导出。由K2表示。

Message A message to be authenticated. Denoted by M. The message can be null, which means that the length of M is 0.

消息要进行身份验证的消息。由M表示。消息可以为null,这意味着M的长度为0。

Message length The length of the message M in octets. Denoted by len. The minimum value of the length can be 0. The maximum value of the length is not specified in this document.

消息长度消息的长度M,以八位字节为单位。以len表示。长度的最小值可以是0。本文档中未指定长度的最大值。

AES-128(K,M) AES-128(K,M) is the 128-bit ciphertext of AES-128 for a 128-bit key, K, and a 128-bit message, M.

AES-128(K,M)AES-128(K,M)是AES-128的128位密文,用于128位密钥K和128位消息M。

MAC A 128-bit string that is the output of AES-CMAC. Denoted by T. Validating the MAC provides assurance of the integrity and authenticity of the message from the source.

MAC是AES-CMAC输出的128位字符串。由T表示。验证MAC可确保来自源的消息的完整性和真实性。

MAC length By default, the length of the output of AES-CMAC is 128 bits. It is possible to truncate the MAC. The result of the truncation should be taken in most significant bits first order. The MAC length must be specified before the communication starts, and it must not be changed during the lifetime of the key.

MAC长度默认情况下,AES-CMAC的输出长度为128位。可以截断MAC。截断的结果应按最高有效位的一阶进行。MAC长度必须在通信开始前指定,并且在密钥的生命周期内不得更改。

2.2. Overview
2.2. 概述

AES-CMAC uses the Advanced Encryption Standard [NIST-AES] as a building block. To generate a MAC, AES-CMAC takes a secret key, a message of variable length, and the length of the message in octets as inputs and returns a fixed-bit string called a MAC.

AES-CMAC使用高级加密标准[NIST-AES]作为构建块。为了生成MAC,AES-CMAC将密钥、可变长度消息和消息长度(以八位字节为单位)作为输入,并返回一个称为MAC的固定位字符串。

The core of AES-CMAC is the basic CBC-MAC. For a message, M, to be authenticated, the CBC-MAC is applied to M. There are two cases of operation in CMAC. Figure 2.1 illustrates the operation of CBC-MAC in both cases. If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits), the last block shall be exclusive-OR'ed with K1 before processing. Otherwise, the last block shall be padded with 10^i (notation is described in section 2.1) and exclusive-OR'ed with K2. The result of the previous

AES-CMAC的核心是基本的CBC-MAC。对于要认证的消息M,CBC-MAC应用于M。CMAC中有两种操作情况。图2.1说明了两种情况下CBC-MAC的操作。如果输入消息块的大小等于块大小的正倍数(即128位),则在处理前,最后一个块应与K1异或。否则,最后一块应填充10^i(符号在第2.1节中描述)和K2。上一次调查的结果

process will be the input of the last encryption. The output of AES-CMAC provides data integrity of the whole input message.

进程将是最后一次加密的输入。AES-CMAC的输出提供了整个输入消息的数据完整性。

 +-----+     +-----+     +-----+     +-----+     +-----+     +---+----+
 | M_1 |     | M_2 |     | M_n |     | M_1 |     | M_2 |     |M_n|10^i|
 +-----+     +-----+     +-----+     +-----+     +-----+     +---+----+
    |           |           |   +--+    |           |           |   +--+
    |     +--->(+)    +--->(+)<-|K1|    |     +--->(+)    +--->(+)<-|K2|
    |     |     |     |     |   +--+    |     |     |     |     |   +--+
 +-----+  |  +-----+  |  +-----+     +-----+  |  +-----+  |  +-----+
 |AES_K|  |  |AES_K|  |  |AES_K|     |AES_K|  |  |AES_K|  |  |AES_K|
 +-----+  |  +-----+  |  +-----+     +-----+  |  +-----+  |  +-----+
    |     |     |     |     |           |     |     |     |     |
    +-----+     +-----+     |           +-----+     +-----+     |
                            |                                   |
                         +-----+                              +-----+
                         |  T  |                              |  T  |
                         +-----+                              +-----+
        
 +-----+     +-----+     +-----+     +-----+     +-----+     +---+----+
 | M_1 |     | M_2 |     | M_n |     | M_1 |     | M_2 |     |M_n|10^i|
 +-----+     +-----+     +-----+     +-----+     +-----+     +---+----+
    |           |           |   +--+    |           |           |   +--+
    |     +--->(+)    +--->(+)<-|K1|    |     +--->(+)    +--->(+)<-|K2|
    |     |     |     |     |   +--+    |     |     |     |     |   +--+
 +-----+  |  +-----+  |  +-----+     +-----+  |  +-----+  |  +-----+
 |AES_K|  |  |AES_K|  |  |AES_K|     |AES_K|  |  |AES_K|  |  |AES_K|
 +-----+  |  +-----+  |  +-----+     +-----+  |  +-----+  |  +-----+
    |     |     |     |     |           |     |     |     |     |
    +-----+     +-----+     |           +-----+     +-----+     |
                            |                                   |
                         +-----+                              +-----+
                         |  T  |                              |  T  |
                         +-----+                              +-----+
        

(a) positive multiple block length (b) otherwise

(a) 正多块长度(b),否则

Figure 2.1. Illustration of the two cases of AES-CMAC

图2.1。AES-CMAC的两个案例说明

AES_K is AES-128 with key K. The message M is divided into blocks M_1,...,M_n, where M_i is the i-th message block. The length of M_i is 128 bits for i = 1,...,n-1, and the length of the last block, M_n, is less than or equal to 128 bits. K1 is the subkey for the case (a), and K2 is the subkey for the case (b). K1 and K2 are generated by the subkey generation algorithm described in section 2.3.

AES_K是具有密钥K的AES-128。消息M被划分为块M_1,…,M_n,其中M_i是第i个消息块。对于i=1,…,n-1,M_i的长度为128位,最后一个块的长度M_n小于或等于128位。K1是案例(a)的子键,K2是案例(b)的子键。K1和K2由第2.3节所述的子密钥生成算法生成。

2.3. Subkey Generation Algorithm
2.3. 子密钥生成算法

The subkey generation algorithm, Generate_Subkey(), takes a secret key, K, which is just the key for AES-128.

子密钥生成算法Generate_subkey(),采用一个密钥K,该密钥正是AES-128的密钥。

The outputs of the subkey generation algorithm are two subkeys, K1 and K2. We write (K1,K2) := Generate_Subkey(K).

子密钥生成算法的输出是两个子密钥K1和K2。我们写(K1,K2):=Generate_子键(K)。

Subkeys K1 and K2 are used in both MAC generation and MAC verification algorithms. K1 is used for the case where the length of the last block is equal to the block length. K2 is used for the case where the length of the last block is less than the block length.

子密钥K1和K2用于MAC生成和MAC验证算法。K1用于最后一个块的长度等于块长度的情况。K2用于最后一个块的长度小于块长度的情况。

Figure 2.2 specifies the subkey generation algorithm.

图2.2指定了子密钥生成算法。

   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                    Algorithm Generate_Subkey                      +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K (128-bit key)                                      +
   +   Output   : K1 (128-bit first subkey)                            +
   +              K2 (128-bit second subkey)                           +
   +-------------------------------------------------------------------+
   +                                                                   +
   +   Constants: const_Zero is 0x00000000000000000000000000000000     +
   +              const_Rb   is 0x00000000000000000000000000000087     +
   +   Variables: L          for output of AES-128 applied to 0^128    +
   +                                                                   +
   +   Step 1.  L := AES-128(K, const_Zero);                           +
   +   Step 2.  if MSB(L) is equal to 0                                +
   +            then    K1 := L << 1;                                  +
   +            else    K1 := (L << 1) XOR const_Rb;                   +
   +   Step 3.  if MSB(K1) is equal to 0                               +
   +            then    K2 := K1 << 1;                                 +
   +            else    K2 := (K1 << 1) XOR const_Rb;                  +
   +   Step 4.  return K1, K2;                                         +
   +                                                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                    Algorithm Generate_Subkey                      +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K (128-bit key)                                      +
   +   Output   : K1 (128-bit first subkey)                            +
   +              K2 (128-bit second subkey)                           +
   +-------------------------------------------------------------------+
   +                                                                   +
   +   Constants: const_Zero is 0x00000000000000000000000000000000     +
   +              const_Rb   is 0x00000000000000000000000000000087     +
   +   Variables: L          for output of AES-128 applied to 0^128    +
   +                                                                   +
   +   Step 1.  L := AES-128(K, const_Zero);                           +
   +   Step 2.  if MSB(L) is equal to 0                                +
   +            then    K1 := L << 1;                                  +
   +            else    K1 := (L << 1) XOR const_Rb;                   +
   +   Step 3.  if MSB(K1) is equal to 0                               +
   +            then    K2 := K1 << 1;                                 +
   +            else    K2 := (K1 << 1) XOR const_Rb;                  +
   +   Step 4.  return K1, K2;                                         +
   +                                                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        

Figure 2.2. Algorithm Generate_Subkey

图2.2。生成子密钥的算法

In step 1, AES-128 with key K is applied to an all-zero input block.

在步骤1中,将带有密钥K的AES-128应用于全零输入块。

In step 2, K1 is derived through the following operation:

在步骤2中,通过以下操作导出K1:

If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit.

如果L的最高有效位等于0,则K1是L的左移1位。

Otherwise, K1 is the exclusive-OR of const_Rb and the left-shift of L by 1 bit.

否则,K1是常量Rb的异或,L左移1位。

In step 3, K2 is derived through the following operation:

在步骤3中,通过以下操作导出K2:

If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit.

如果K1的最高有效位等于0,则K2为K1的左移1位。

Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of K1 by 1 bit.

否则,K2是常量Rb的异或,K1左移1位。

In step 4, (K1,K2) := Generate_Subkey(K) is returned.

在步骤4中,返回(K1,K2):=Generate_子键(K)。

The mathematical meaning of the procedures in steps 2 and 3, including const_Rb, can be found in [OMAC1a].

步骤2和步骤3中程序的数学含义,包括常数Rb,可在[OMAC1a]中找到。

2.4. MAC Generation Algorithm
2.4. MAC生成算法

The MAC generation algorithm, AES-CMAC(), takes three inputs, a secret key, a message, and the length of the message in octets. The secret key, denoted by K, is just the key for AES-128. The message and its length in octets are denoted by M and len, respectively. The message M is denoted by the sequence of M_i, where M_i is the i-th message block. That is, if M consists of n blocks, then M is written as

MAC生成算法AES-CMAC()接受三个输入:一个密钥、一条消息和消息长度(以八位字节为单位)。用K表示的密钥就是AES-128的密钥。消息及其长度(以八位字节为单位)分别用M和len表示。消息M由M_i的序列表示,其中M_i是第i个消息块。也就是说,如果M由n个块组成,那么M被写为

- M = M_1 || M_2 || ... || M_{n-1} || M_n

- M=M|u 1 | M|u 2 | |……|M{n-1}|M|n

The length of M_i is 128 bits for i = 1,...,n-1, and the length of the last block M_n is less than or equal to 128 bits.

如果i-M等于128位,则i-M的长度小于128位。

The output of the MAC generation algorithm is a 128-bit string, called a MAC, which is used to validate the input message. The MAC is denoted by T, and we write T := AES-CMAC(K,M,len). Validating the MAC provides assurance of the integrity and authenticity of the message from the source.

MAC生成算法的输出是一个128位字符串,称为MAC,用于验证输入消息。MAC用T表示,我们写T:=AES-CMAC(K,M,len)。验证MAC可确保来自源的消息的完整性和真实性。

It is possible to truncate the MAC. According to [NIST-CMAC], at least a 64-bit MAC should be used as protection against guessing attacks. The result of truncation should be taken in most significant bits first order.

可以截断MAC。根据[NIST-CMAC],至少应该使用64位MAC来防止猜测攻击。截断的结果应按最高有效位的一阶进行。

The block length of AES-128 is 128 bits (16 octets). There is a special treatment if the length of the message is not a positive multiple of the block length. The special treatment is to pad M with the bit-string 10^i to adjust the length of the last block up to the block length.

AES-128的块长度为128位(16个八位字节)。如果消息长度不是块长度的正倍数,则需要进行特殊处理。特殊处理是用位串10^i填充M,以将最后一个块的长度调整到块长度。

For an input string x of r-octets, where 0 <= r < 16, the padding function, padding(x), is defined as follows:

对于r八位字节的输入字符串x,其中0<=r<16,填充函数padding(x)定义如下:

- padding(x) = x || 10^i where i is 128-8*r-1

- 填充(x)=x | | 10^i,其中i为128-8*r-1

That is, padding(x) is the concatenation of x and a single '1', followed by the minimum number of '0's, so that the total length is equal to 128 bits.

也就是说,填充(x)是x和单个“1”的串联,后跟最小数量的“0”,因此总长度等于128位。

Figure 2.3 describes the MAC generation algorithm.

图2.3描述了MAC生成算法。

   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                   Algorithm AES-CMAC                              +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K    ( 128-bit key )                                 +
   +            : M    ( message to be authenticated )                 +
   +            : len  ( length of the message in octets )             +
   +   Output   : T    ( message authentication code )                 +
   +                                                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +   Constants: const_Zero is 0x00000000000000000000000000000000     +
   +              const_Bsize is 16                                    +
   +                                                                   +
   +   Variables: K1, K2 for 128-bit subkeys                           +
   +              M_i is the i-th block (i=1..ceil(len/const_Bsize))   +
   +              M_last is the last block xor-ed with K1 or K2        +
   +              n      for number of blocks to be processed          +
   +              r      for number of octets of last block            +
   +              flag   for denoting if last block is complete or not +
   +                                                                   +
   +   Step 1.  (K1,K2) := Generate_Subkey(K);                         +
   +   Step 2.  n := ceil(len/const_Bsize);                            +
   +   Step 3.  if n = 0                                               +
   +            then                                                   +
   +                 n := 1;                                           +
   +                 flag := false;                                    +
   +            else                                                   +
   +                 if len mod const_Bsize is 0                       +
   +                 then flag := true;                                +
   +                 else flag := false;                               +
   +                                                                   +
   +   Step 4.  if flag is true                                        +
   +            then M_last := M_n XOR K1;                             +
   +            else M_last := padding(M_n) XOR K2;                    +
   +   Step 5.  X := const_Zero;                                       +
   +   Step 6.  for i := 1 to n-1 do                                   +
   +                begin                                              +
   +                  Y := X XOR M_i;                                  +
   +                  X := AES-128(K,Y);                               +
   +                end                                                +
   +            Y := M_last XOR X;                                     +
   +            T := AES-128(K,Y);                                     +
   +   Step 7.  return T;                                              +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                   Algorithm AES-CMAC                              +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K    ( 128-bit key )                                 +
   +            : M    ( message to be authenticated )                 +
   +            : len  ( length of the message in octets )             +
   +   Output   : T    ( message authentication code )                 +
   +                                                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +   Constants: const_Zero is 0x00000000000000000000000000000000     +
   +              const_Bsize is 16                                    +
   +                                                                   +
   +   Variables: K1, K2 for 128-bit subkeys                           +
   +              M_i is the i-th block (i=1..ceil(len/const_Bsize))   +
   +              M_last is the last block xor-ed with K1 or K2        +
   +              n      for number of blocks to be processed          +
   +              r      for number of octets of last block            +
   +              flag   for denoting if last block is complete or not +
   +                                                                   +
   +   Step 1.  (K1,K2) := Generate_Subkey(K);                         +
   +   Step 2.  n := ceil(len/const_Bsize);                            +
   +   Step 3.  if n = 0                                               +
   +            then                                                   +
   +                 n := 1;                                           +
   +                 flag := false;                                    +
   +            else                                                   +
   +                 if len mod const_Bsize is 0                       +
   +                 then flag := true;                                +
   +                 else flag := false;                               +
   +                                                                   +
   +   Step 4.  if flag is true                                        +
   +            then M_last := M_n XOR K1;                             +
   +            else M_last := padding(M_n) XOR K2;                    +
   +   Step 5.  X := const_Zero;                                       +
   +   Step 6.  for i := 1 to n-1 do                                   +
   +                begin                                              +
   +                  Y := X XOR M_i;                                  +
   +                  X := AES-128(K,Y);                               +
   +                end                                                +
   +            Y := M_last XOR X;                                     +
   +            T := AES-128(K,Y);                                     +
   +   Step 7.  return T;                                              +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        

Figure 2.3. Algorithm AES-CMAC

图2.3。AES-CMAC算法

In step 1, subkeys K1 and K2 are derived from K through the subkey generation algorithm.

在步骤1中,通过子密钥生成算法从K导出子密钥K1和K2。

In step 2, the number of blocks, n, is calculated. The number of blocks is the smallest integer value greater than or equal to the quotient determined by dividing the length parameter by the block length, 16 octets.

在步骤2中,计算块的数量n。块数是大于或等于长度参数除以块长度16个八位字节所得商的最小整数值。

In step 3, the length of the input message is checked. If the input length is 0 (null), the number of blocks to be processed shall be 1, and the flag shall be marked as not-complete-block (false). Otherwise, if the last block length is 128 bits, the flag is marked as complete-block (true); else mark the flag as not-complete-block (false).

在步骤3中,检查输入消息的长度。如果输入长度为0(null),则要处理的块数应为1,且标志应标记为不完整块(false)。否则,如果最后一个块长度为128位,则标记为完整块(true);否则,将标志标记为不完整块(false)。

In step 4, M_last is calculated by exclusive-OR'ing M_n and one of the previously calculated subkeys. If the last block is a complete block (true), then M_last is the exclusive-OR of M_n and K1. Otherwise, M_last is the exclusive-OR of padding(M_n) and K2.

在步骤4中,通过对M_n和先前计算的子键之一进行异或运算来计算M_last。如果最后一个块是完整块(true),那么M_last是M_n和K1的异或。否则,M_last是padding(M_n)和K2的异或。

In step 5, the variable X is initialized.

在步骤5中,初始化变量X。

In step 6, the basic CBC-MAC is applied to M_1,...,M_{n-1},M_last.

在步骤6中,基本CBC-MAC应用于M_1,…,M_{n-1},M_last。

In step 7, the 128-bit MAC, T := AES-CMAC(K,M,len), is returned.

在步骤7中,返回128位MAC,T:=AES-CMAC(K,M,len)。

If necessary, the MAC is truncated before it is returned.

如有必要,MAC将在返回之前被截断。

2.5. MAC Verification Algorithm
2.5. MAC验证算法

The verification of the MAC is simply done by a MAC recomputation. We use the MAC generation algorithm, which is described in section 2.4.

MAC的验证只需通过MAC重新计算即可完成。我们使用MAC生成算法,如第2.4节所述。

The MAC verification algorithm, Verify_MAC(), takes four inputs, a secret key, a message, the length of the message in octets, and the received MAC. These are denoted by K, M, len, and T', respectively.

MAC验证算法Verify_MAC(),接受四个输入:一个密钥、一条消息、消息长度(以八位字节为单位)和接收到的MAC。它们分别用K、M、len和T'表示。

The output of the MAC verification algorithm is either INVALID or VALID.

MAC验证算法的输出无效或有效。

Figure 2.4 describes the MAC verification algorithm.

图2.4描述了MAC验证算法。

   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                      Algorithm Verify_MAC                         +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K    ( 128-bit Key )                                 +
   +            : M    ( message to be verified )                      +
   +            : len  ( length of the message in octets )             +
   +            : T'   ( the received MAC to be verified )             +
   +   Output   : INVALID or VALID                                     +
   +                                                                   +
   +-------------------------------------------------------------------+
   +                                                                   +
   +   Step 1.  T* := AES-CMAC(K,M,len);                               +
   +   Step 2.  if T* is equal to T'                                   +
   +            then                                                   +
   +                 return VALID;                                     +
   +            else                                                   +
   +                 return INVALID;                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                      Algorithm Verify_MAC                         +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                                   +
   +   Input    : K    ( 128-bit Key )                                 +
   +            : M    ( message to be verified )                      +
   +            : len  ( length of the message in octets )             +
   +            : T'   ( the received MAC to be verified )             +
   +   Output   : INVALID or VALID                                     +
   +                                                                   +
   +-------------------------------------------------------------------+
   +                                                                   +
   +   Step 1.  T* := AES-CMAC(K,M,len);                               +
   +   Step 2.  if T* is equal to T'                                   +
   +            then                                                   +
   +                 return VALID;                                     +
   +            else                                                   +
   +                 return INVALID;                                   +
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        

Figure 2.4. Algorithm Verify_MAC

图2.4。算法验证

In step 1, T* is derived from K, M, and len through the MAC generation algorithm.

在步骤1中,通过MAC生成算法从K、M和len导出T*。

In step 2, T* and T' are compared. If T* is equal to T', then return VALID; otherwise return INVALID.

在步骤2中,比较T*和T′。如果T*等于T',则返回有效值;否则返回无效。

If the output is INVALID, then the message is definitely not authentic, i.e., it did not originate from a source that executed the generation process on the message to produce the purported MAC.

如果输出无效,则消息肯定是不真实的,即,它不是来自对消息执行生成过程以产生声称的MAC的源。

If the output is VALID, then the design of the AES-CMAC provides assurance that the message is authentic and, hence, was not corrupted in transit; however, this assurance, as for any MAC algorithm, is not absolute.

如果输出有效,则AES-CMAC的设计可确保消息是真实的,因此不会在传输过程中损坏;然而,与任何MAC算法一样,这种保证不是绝对的。

3. Security Considerations
3. 安全考虑

The security provided by AES-CMAC is built on the strong cryptographic algorithm AES. However, as is true with any cryptographic algorithm, part of its strength lies in the secret key, K, and the correctness of the implementation in all of the participating systems. If the secret key is compromised or inappropriately shared, it guarantees neither authentication nor integrity of message at all. The secret key shall be generated in a way that meets the pseudo randomness requirement of RFC 4086 [RFC4086] and should be kept safe. If and only if AES-CMAC is used

AES-CMAC提供的安全性建立在强密码算法AES的基础上。然而,与任何加密算法一样,它的一部分优势在于密钥K和所有参与系统中实现的正确性。如果密钥被泄露或不适当地共享,则它根本不能保证消息的身份验证或完整性。密钥应以满足RFC 4086[RFC4086]的伪随机性要求的方式生成,并应保持安全。当且仅当使用AES-CMAC时

properly it provides the authentication and integrity that meet the best current practice of message authentication.

正确地说,它提供了符合当前消息身份验证最佳实践的身份验证和完整性。

4. Test Vectors
4. 测试向量

The following test vectors are the same as those of [NIST-CMAC]. The following vectors are also the output of the test program in Appendix A.

以下测试向量与[NIST-CMAC]的测试向量相同。以下向量也是附录A中测试程序的输出。

   --------------------------------------------------
   Subkey Generation
   K              2b7e1516 28aed2a6 abf71588 09cf4f3c
   AES-128(key,0) 7df76b0c 1ab899b3 3e42f047 b91b546f
   K1             fbeed618 35713366 7c85e08f 7236a8de
   K2             f7ddac30 6ae266cc f90bc11e e46d513b
   --------------------------------------------------
        
   --------------------------------------------------
   Subkey Generation
   K              2b7e1516 28aed2a6 abf71588 09cf4f3c
   AES-128(key,0) 7df76b0c 1ab899b3 3e42f047 b91b546f
   K1             fbeed618 35713366 7c85e08f 7236a8de
   K2             f7ddac30 6ae266cc f90bc11e e46d513b
   --------------------------------------------------
        
   --------------------------------------------------
   Example 1: len = 0
   M              <empty string>
   AES-CMAC       bb1d6929 e9593728 7fa37d12 9b756746
   --------------------------------------------------
        
   --------------------------------------------------
   Example 1: len = 0
   M              <empty string>
   AES-CMAC       bb1d6929 e9593728 7fa37d12 9b756746
   --------------------------------------------------
        
   Example 2: len = 16
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
   AES-CMAC       070a16b4 6b4d4144 f79bdd9d d04a287c
   --------------------------------------------------
        
   Example 2: len = 16
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
   AES-CMAC       070a16b4 6b4d4144 f79bdd9d d04a287c
   --------------------------------------------------
        
   Example 3: len = 40
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
                  ae2d8a57 1e03ac9c 9eb76fac 45af8e51
                  30c81c46 a35ce411
   AES-CMAC       dfa66747 de9ae630 30ca3261 1497c827
   --------------------------------------------------
        
   Example 3: len = 40
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
                  ae2d8a57 1e03ac9c 9eb76fac 45af8e51
                  30c81c46 a35ce411
   AES-CMAC       dfa66747 de9ae630 30ca3261 1497c827
   --------------------------------------------------
        
   Example 4: len = 64
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
                  ae2d8a57 1e03ac9c 9eb76fac 45af8e51
                  30c81c46 a35ce411 e5fbc119 1a0a52ef
                  f69f2445 df4f9b17 ad2b417b e66c3710
   AES-CMAC       51f0bebf 7e3b9d92 fc497417 79363cfe
   --------------------------------------------------
        
   Example 4: len = 64
   M              6bc1bee2 2e409f96 e93d7e11 7393172a
                  ae2d8a57 1e03ac9c 9eb76fac 45af8e51
                  30c81c46 a35ce411 e5fbc119 1a0a52ef
                  f69f2445 df4f9b17 ad2b417b e66c3710
   AES-CMAC       51f0bebf 7e3b9d92 fc497417 79363cfe
   --------------------------------------------------
        
5. Acknowledgement
5. 确认

Portions of the text herein are borrowed from [NIST-CMAC]. We appreciate the OMAC1 authors, the SP 800-38B author, and Russ Housley for his useful comments and guidance, which have been incorporated herein. We also thank Alfred Hoenes for many useful comments. This memo was prepared while Tetsu Iwata was at Ibaraki University, Japan.

本文部分内容借用自[NIST-CMAC]。我们感谢OMAC1作者、SP 800-38B作者和Russ Housley的有用意见和指导,这些意见和指导已纳入本文。我们还感谢阿尔弗雷德·霍恩斯提出的许多有益的意见。这份备忘录是岩田德洙在日本茨城大学时编写的。

We acknowledge the support from the following grants: Collaborative Technology Alliance (CTA) from US Army Research Laboratory, DAAD19- 01-2-0011; Presidential Award from Army Research Office, W911NF-05- 1-0491; NSF CAREER ANI-0093187. Results do not reflect any position of the funding agencies.

我们感谢以下赠款的支持:美国陆军研究实验室合作技术联盟(CTA),DAAD19-01-2-0011;陆军研究办公室颁发的总统奖,W911NF-05-1-0491;NSF职业ANI-0093187。结果并不反映资助机构的任何立场。

6. References
6. 工具书类
6.1. Normative References
6.1. 规范性引用文件

[NIST-CMAC] NIST, Special Publication 800-38B, "Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication", May 2005.

[NIST-CMAC]NIST,特别出版物800-38B,“分组密码操作模式建议:认证CMAC模式”,2005年5月。

   [NIST-AES]  NIST, FIPS 197, "Advanced Encryption Standard (AES)",
               November 2001.
               http://csrc.nist.gov/publications/fips/fips197/fips-
               197.pdf
        
   [NIST-AES]  NIST, FIPS 197, "Advanced Encryption Standard (AES)",
               November 2001.
               http://csrc.nist.gov/publications/fips/fips197/fips-
               197.pdf
        

[RFC4086] Eastlake, D., 3rd, Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.

[RFC4086]伊斯特莱克,D.,3,席勒,J.和S.克罗克,“安全的随机性要求”,BCP 106,RFC 4086,2005年6月。

6.2. Informative References
6.2. 资料性引用

[RFC-HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997.

[RFC-HMAC]Krawczyk,H.,Bellare,M.和R.Canetti,“HMAC:用于消息身份验证的键控哈希”,RFC 2104,1997年2月。

[OMAC1a] Tetsu Iwata and Kaoru Kurosawa, "OMAC: One-Key CBC MAC", Fast Software Encryption, FSE 2003, LNCS 2887, pp. 129- 153, Springer-Verlag, 2003.

[OMAC1a]岩田铁洙和黑泽薰,“OMAC:一个密钥CBC MAC”,快速软件加密,FSE 2003,LNCS 2887,第129-153页,Springer Verlag,2003年。

   [OMAC1b]    Tetsu Iwata and Kaoru Kurosawa, "OMAC: One-Key CBC MAC",
               Submission to NIST, December 2002.  Available from the
               NIST modes of operation web site at
               http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/
               omac/omac-spec.pdf
        
   [OMAC1b]    Tetsu Iwata and Kaoru Kurosawa, "OMAC: One-Key CBC MAC",
               Submission to NIST, December 2002.  Available from the
               NIST modes of operation web site at
               http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/
               omac/omac-spec.pdf
        
   [XCBCa]     John Black and Phillip Rogaway, "A Suggestion for
               Handling Arbitrary-Length Messages with the CBC MAC",
               NIST Second Modes of Operation Workshop, August 2001.
               Available from the NIST modes of operation web site at
               http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/
               xcbc-mac/xcbc-mac-spec.pdf
        
   [XCBCa]     John Black and Phillip Rogaway, "A Suggestion for
               Handling Arbitrary-Length Messages with the CBC MAC",
               NIST Second Modes of Operation Workshop, August 2001.
               Available from the NIST modes of operation web site at
               http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/
               xcbc-mac/xcbc-mac-spec.pdf
        

[XCBCb] John Black and Phillip Rogaway, "CBC MACs for Arbitrary-Length Messages: The Three-Key Constructions", Journal of Cryptology, Vol. 18, No. 2, pp. 111-132, Springer-Verlag, Spring 2005.

[XCBCb]John Black和Phillip Rogaway,“任意长度消息的CBC MAC:三种关键结构”,《密码学杂志》,第18卷,第2期,第111-132页,Springer Verlag,2005年春季。

Appendix A. Test Code
附录A.测试代码

This C source is designed to generate the test vectors that appear in this memo to verify correctness of the algorithm. The source code is not intended for use in commercial products.

此C源用于生成此备忘录中出现的测试向量,以验证算法的正确性。源代码不适用于商业产品。

  /****************************************************************/
  /* AES-CMAC with AES-128 bit                                    */
  /* CMAC     Algorithm described in SP800-38B                    */
  /* Author: Junhyuk Song (junhyuk.song@samsung.com)              */
  /*         Jicheol Lee  (jicheol.lee@samsung.com)               */
  /****************************************************************/
        
  /****************************************************************/
  /* AES-CMAC with AES-128 bit                                    */
  /* CMAC     Algorithm described in SP800-38B                    */
  /* Author: Junhyuk Song (junhyuk.song@samsung.com)              */
  /*         Jicheol Lee  (jicheol.lee@samsung.com)               */
  /****************************************************************/
        
  #include <stdio.h>
        
  #include <stdio.h>
        
  /* For CMAC Calculation */
  unsigned char const_Rb[16] = {
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
  };
  unsigned char const_Zero[16] = {
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
        
  /* For CMAC Calculation */
  unsigned char const_Rb[16] = {
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
  };
  unsigned char const_Zero[16] = {
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
        
  /* Basic Functions */
        
  /* Basic Functions */
        
  void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
  {
      int i;
      for (i=0;i<16; i++)
      {
          out[i] = a[i] ^ b[i];
      }
  }
        
  void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
  {
      int i;
      for (i=0;i<16; i++)
      {
          out[i] = a[i] ^ b[i];
      }
  }
        
  void print_hex(char *str, unsigned char *buf, int len)
  {
      int     i;
        
  void print_hex(char *str, unsigned char *buf, int len)
  {
      int     i;
        
      for ( i=0; i<len; i++ ) {
          if ( (i % 16) == 0 && i != 0 ) printf(str);
          printf("%02x", buf[i]);
          if ( (i % 4) == 3 ) printf(" ");
          if ( (i % 16) == 15 ) printf("\n");
      }
      if ( (i % 16) != 0 ) printf("\n");
  }
        
      for ( i=0; i<len; i++ ) {
          if ( (i % 16) == 0 && i != 0 ) printf(str);
          printf("%02x", buf[i]);
          if ( (i % 4) == 3 ) printf(" ");
          if ( (i % 16) == 15 ) printf("\n");
      }
      if ( (i % 16) != 0 ) printf("\n");
  }
        
  void print128(unsigned char *bytes)
  {
      int         j;
      for (j=0; j<16;j++) {
          printf("%02x",bytes[j]);
          if ( (j%4) == 3 ) printf(" ");
      }
  }
        
  void print128(unsigned char *bytes)
  {
      int         j;
      for (j=0; j<16;j++) {
          printf("%02x",bytes[j]);
          if ( (j%4) == 3 ) printf(" ");
      }
  }
        
  void print96(unsigned char *bytes)
  {
      int         j;
      for (j=0; j<12;j++) {
          printf("%02x",bytes[j]);
          if ( (j%4) == 3 ) printf(" ");
      }
  }
        
  void print96(unsigned char *bytes)
  {
      int         j;
      for (j=0; j<12;j++) {
          printf("%02x",bytes[j]);
          if ( (j%4) == 3 ) printf(" ");
      }
  }
        
  /* AES-CMAC Generation Function */
        
  /* AES-CMAC Generation Function */
        
  void leftshift_onebit(unsigned char *input,unsigned char *output)
  {
      int         i;
      unsigned char overflow = 0;
        
  void leftshift_onebit(unsigned char *input,unsigned char *output)
  {
      int         i;
      unsigned char overflow = 0;
        
      for ( i=15; i>=0; i-- ) {
          output[i] = input[i] << 1;
          output[i] |= overflow;
          overflow = (input[i] & 0x80)?1:0;
      }
      return;
  }
        
      for ( i=15; i>=0; i-- ) {
          output[i] = input[i] << 1;
          output[i] |= overflow;
          overflow = (input[i] & 0x80)?1:0;
      }
      return;
  }
        
  void generate_subkey(unsigned char *key, unsigned char *K1, unsigned
                       char *K2)
  {
      unsigned char L[16];
      unsigned char Z[16];
      unsigned char tmp[16];
      int i;
        
  void generate_subkey(unsigned char *key, unsigned char *K1, unsigned
                       char *K2)
  {
      unsigned char L[16];
      unsigned char Z[16];
      unsigned char tmp[16];
      int i;
        
      for ( i=0; i<16; i++ ) Z[i] = 0;
        
      for ( i=0; i<16; i++ ) Z[i] = 0;
        

AES_128(key,Z,L);

AES_128(键,Z,L);

      if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */
          leftshift_onebit(L,K1);
      } else {    /* Else K1 = ( L << 1 ) (+) Rb */
        
      if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */
          leftshift_onebit(L,K1);
      } else {    /* Else K1 = ( L << 1 ) (+) Rb */
        
          leftshift_onebit(L,tmp);
          xor_128(tmp,const_Rb,K1);
      }
        
          leftshift_onebit(L,tmp);
          xor_128(tmp,const_Rb,K1);
      }
        
      if ( (K1[0] & 0x80) == 0 ) {
          leftshift_onebit(K1,K2);
      } else {
          leftshift_onebit(K1,tmp);
          xor_128(tmp,const_Rb,K2);
      }
      return;
  }
        
      if ( (K1[0] & 0x80) == 0 ) {
          leftshift_onebit(K1,K2);
      } else {
          leftshift_onebit(K1,tmp);
          xor_128(tmp,const_Rb,K2);
      }
      return;
  }
        
  void padding ( unsigned char *lastb, unsigned char *pad, int length )
  {
      int         j;
        
  void padding ( unsigned char *lastb, unsigned char *pad, int length )
  {
      int         j;
        
      /* original last block */
      for ( j=0; j<16; j++ ) {
          if ( j < length ) {
              pad[j] = lastb[j];
          } else if ( j == length ) {
              pad[j] = 0x80;
          } else {
              pad[j] = 0x00;
          }
      }
  }
        
      /* original last block */
      for ( j=0; j<16; j++ ) {
          if ( j < length ) {
              pad[j] = lastb[j];
          } else if ( j == length ) {
              pad[j] = 0x80;
          } else {
              pad[j] = 0x00;
          }
      }
  }
        
  void AES_CMAC ( unsigned char *key, unsigned char *input, int length,
                  unsigned char *mac )
  {
      unsigned char       X[16],Y[16], M_last[16], padded[16];
      unsigned char       K1[16], K2[16];
      int         n, i, flag;
      generate_subkey(key,K1,K2);
        
  void AES_CMAC ( unsigned char *key, unsigned char *input, int length,
                  unsigned char *mac )
  {
      unsigned char       X[16],Y[16], M_last[16], padded[16];
      unsigned char       K1[16], K2[16];
      int         n, i, flag;
      generate_subkey(key,K1,K2);
        
      n = (length+15) / 16;       /* n is number of rounds */
        
      n = (length+15) / 16;       /* n is number of rounds */
        
      if ( n == 0 ) {
          n = 1;
          flag = 0;
      } else {
          if ( (length%16) == 0 ) { /* last block is a complete block */
              flag = 1;
          } else { /* last block is not complete block */
              flag = 0;
          }
        
      if ( n == 0 ) {
          n = 1;
          flag = 0;
      } else {
          if ( (length%16) == 0 ) { /* last block is a complete block */
              flag = 1;
          } else { /* last block is not complete block */
              flag = 0;
          }
        

}

}

      if ( flag ) { /* last block is complete block */
          xor_128(&input[16*(n-1)],K1,M_last);
      } else {
          padding(&input[16*(n-1)],padded,length%16);
          xor_128(padded,K2,M_last);
      }
        
      if ( flag ) { /* last block is complete block */
          xor_128(&input[16*(n-1)],K1,M_last);
      } else {
          padding(&input[16*(n-1)],padded,length%16);
          xor_128(padded,K2,M_last);
      }
        
      for ( i=0; i<16; i++ ) X[i] = 0;
      for ( i=0; i<n-1; i++ ) {
          xor_128(X,&input[16*i],Y); /* Y := Mi (+) X  */
          AES_128(key,Y,X);      /* X := AES-128(KEY, Y); */
      }
        
      for ( i=0; i<16; i++ ) X[i] = 0;
      for ( i=0; i<n-1; i++ ) {
          xor_128(X,&input[16*i],Y); /* Y := Mi (+) X  */
          AES_128(key,Y,X);      /* X := AES-128(KEY, Y); */
      }
        
      xor_128(X,M_last,Y);
      AES_128(key,Y,X);
        
      xor_128(X,M_last,Y);
      AES_128(key,Y,X);
        
      for ( i=0; i<16; i++ ) {
          mac[i] = X[i];
      }
  }
        
      for ( i=0; i<16; i++ ) {
          mac[i] = X[i];
      }
  }
        
  int main()
  {
      unsigned char L[16], K1[16], K2[16], T[16], TT[12];
      unsigned char M[64] = {
          0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
          0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
          0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
          0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
          0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
          0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
          0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
          0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
      };
      unsigned char key[16] = {
          0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
          0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
      };
        
  int main()
  {
      unsigned char L[16], K1[16], K2[16], T[16], TT[12];
      unsigned char M[64] = {
          0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
          0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
          0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
          0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
          0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
          0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
          0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
          0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
      };
      unsigned char key[16] = {
          0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
          0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
      };
        
      printf("--------------------------------------------------\n");
      printf("K              "); print128(key); printf("\n");
        
      printf("--------------------------------------------------\n");
      printf("K              "); print128(key); printf("\n");
        
      printf("\nSubkey Generation\n");
      AES_128(key,const_Zero,L);
      printf("AES_128(key,0) "); print128(L); printf("\n");
      generate_subkey(key,K1,K2);
        
      printf("\nSubkey Generation\n");
      AES_128(key,const_Zero,L);
      printf("AES_128(key,0) "); print128(L); printf("\n");
      generate_subkey(key,K1,K2);
        
      printf("K1             "); print128(K1); printf("\n");
      printf("K2             "); print128(K2); printf("\n");
        
      printf("K1             "); print128(K1); printf("\n");
      printf("K2             "); print128(K2); printf("\n");
        
      printf("\nExample 1: len = 0\n");
      printf("M              "); printf("<empty string>\n");
        
      printf("\nExample 1: len = 0\n");
      printf("M              "); printf("<empty string>\n");
        
      AES_CMAC(key,M,0,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      AES_CMAC(key,M,0,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      printf("\nExample 2: len = 16\n");
      printf("M              "); print_hex("                ",M,16);
      AES_CMAC(key,M,16,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
      printf("\nExample 3: len = 40\n");
      printf("M              "); print_hex("               ",M,40);
      AES_CMAC(key,M,40,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      printf("\nExample 2: len = 16\n");
      printf("M              "); print_hex("                ",M,16);
      AES_CMAC(key,M,16,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
      printf("\nExample 3: len = 40\n");
      printf("M              "); print_hex("               ",M,40);
      AES_CMAC(key,M,40,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      printf("\nExample 4: len = 64\n");
      printf("M              "); print_hex("               ",M,64);
      AES_CMAC(key,M,64,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      printf("\nExample 4: len = 64\n");
      printf("M              "); print_hex("               ",M,64);
      AES_CMAC(key,M,64,T);
      printf("AES_CMAC       "); print128(T); printf("\n");
        
      printf("--------------------------------------------------\n");
        
      printf("--------------------------------------------------\n");
        
      return 0;
  }
        
      return 0;
  }
        

Authors' Addresses

作者地址

Junhyuk Song University of Washington Samsung Electronics

华盛顿大学音乐学院三星电子

  Phone: (206) 853-5843
  EMail: songlee@ee.washington.edu, junhyuk.song@samsung.com
        
  Phone: (206) 853-5843
  EMail: songlee@ee.washington.edu, junhyuk.song@samsung.com
        

Jicheol Lee Samsung Electronics

三星电子

  Phone: +82-31-279-3605
  EMail: jicheol.lee@samsung.com
        
  Phone: +82-31-279-3605
  EMail: jicheol.lee@samsung.com
        

Radha Poovendran Network Security Lab University of Washington

华盛顿大学网络安全实验室

Phone: (206) 221-6512 EMail: radha@ee.washington.edu

电话:(206)221-6512电子邮件:radha@ee.washington.edu

Tetsu Iwata Nagoya University

岩田德洙名古屋大学

  EMail: iwata@cse.nagoya-u.ac.jp
        
  EMail: iwata@cse.nagoya-u.ac.jp
        

Full Copyright Statement

完整版权声明

Copyright (C) The Internet Society (2006).

版权所有(C)互联网协会(2006年)。

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

本文件受BCP 78中包含的权利、许可和限制的约束,除其中规定外,作者保留其所有权利。

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

本文件及其包含的信息是按“原样”提供的,贡献者、他/她所代表或赞助的组织(如有)、互联网协会和互联网工程任务组不承担任何明示或暗示的担保,包括但不限于任何保证,即使用本文中的信息不会侵犯任何权利,或对适销性或特定用途适用性的任何默示保证。

Intellectual Property

知识产权

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

IETF对可能声称与本文件所述技术的实施或使用有关的任何知识产权或其他权利的有效性或范围,或此类权利下的任何许可可能或可能不可用的程度,不采取任何立场;它也不表示它已作出任何独立努力来确定任何此类权利。有关RFC文件中权利的程序信息,请参见BCP 78和BCP 79。

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

向IETF秘书处披露的知识产权副本和任何许可证保证,或本规范实施者或用户试图获得使用此类专有权利的一般许可证或许可的结果,可从IETF在线知识产权存储库获取,网址为http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.

IETF邀请任何相关方提请其注意任何版权、专利或专利申请,或其他可能涵盖实施本标准所需技术的专有权利。请将信息发送至IETF的IETF-ipr@ietf.org.

Acknowledgement

确认

Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA).

RFC编辑器功能的资金由IETF行政支持活动(IASA)提供。