00001 /* 00002 --------------------------------------------------------------------------- 00003 Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK. 00004 All rights reserved. 00005 00006 LICENSE TERMS 00007 00008 The free distribution and use of this software in both source and binary 00009 form is allowed (with or without changes) provided that: 00010 00011 1. distributions of this source code include the above copyright 00012 notice, this list of conditions and the following disclaimer; 00013 00014 2. distributions in binary form include the above copyright 00015 notice, this list of conditions and the following disclaimer 00016 in the documentation and/or other associated materials; 00017 00018 3. the copyright holder's name is not used to endorse products 00019 built using this software without specific written permission. 00020 00021 ALTERNATIVELY, provided that this notice is retained in full, this product 00022 may be distributed under the terms of the GNU General Public License (GPL), 00023 in which case the provisions of the GPL apply INSTEAD OF those given above. 00024 00025 DISCLAIMER 00026 00027 This software is provided 'as is' with no explicit or implied warranties 00028 in respect of its properties, including, but not limited to, correctness 00029 and/or fitness for purpose. 00030 --------------------------------------------------------------------------- 00031 Issue Date: 1/05/2003 00032 00033 This code implements the CCM combined encryption and authentication mode 00034 specified by Doug Whiting, Russ Housley and Niels Ferguson. 00035 00036 The additonal authenicated data in this version is memory resident in a 00037 single block and is limited to less than 65280 bytes. The length of the 00038 mesaage data must be less than 2^32 bytes unless LONG_MESSAGES has been 00039 defined. This can be input in multiple blocks. 00040 */ 00041 00042 #ifdef __cplusplus 00043 00044 extern "C" { 00045 00046 #endif 00047 00048 00049 00050 #include <memory.h> 00051 00052 #include "aes.h" 00053 00054 #define BLOCK_MASK (AES_BLOCK_SIZE - 1) 00055 00056 #ifndef LONG_MESSAGES 00057 typedef aes_32t mlen_type; 00058 typedef long ret_type; 00059 #else 00060 #ifdef _MSC_VER 00061 typedef __int64 ret_type; 00062 typedef unsigned __int64 mlen_type; 00063 #else 00064 typedef long long ret_type; 00065 typedef unsigned long long mlen_type; 00066 #endif 00067 #endif 00068 00069 /* CCM error codes */ 00070 00071 #define CCM_ok 0 00072 #define CCM_bad_key -1 00073 #define CCM_bad_auth_field_length -2 00074 #define CCM_bad_auth_data_length -3 00075 #define CCM_auth_failure -4 00076 #define CCM_msg_length_error -5 00077 00078 /* The CCM context */ 00079 00080 typedef struct 00081 { aes_08t blk[AES_BLOCK_SIZE]; /* counter block */ 00082 aes_08t cbc[AES_BLOCK_SIZE]; /* running CBC value */ 00083 aes_08t sii[AES_BLOCK_SIZE]; /* encrypted counter block */ 00084 aes_32t af_len; /* authentication field length (bytes) */ 00085 mlen_type md_len; /* message length (bytes) */ 00086 mlen_type cnt; /* message position counter */ 00087 aes_encrypt_ctx aes[1]; /* AES context */ 00088 } CCM_ctx; 00089 00090 /* This call initialises the CCM context by setting the encryption key 00091 and setting up and calculating the the CBC value for the additional 00092 authenication data. 00093 00094 This call is then followed by calls to CCM_encrypt() or CCM_decrypt() 00095 to encrypt or decrypt the message bytes. Length values are in bytes. 00096 00097 The message length value for CCM_init() is the actual number of bytes 00098 in the message without the authentication data. This is also true for 00099 CCM_encrypt() but the length for CCM_decrypt() is the message length 00100 plus the length in bytes of the added authentication data field that 00101 is stored at the end of the message. 00102 00103 CCM_encrypt() and CCM_decrypt() can be called more than once in order 00104 to process long messages but the overall sum of the data lengths for 00105 the set of calls must match the message length (encrypt) or the sum 00106 of the message length and the authentication field length (decrypt). 00107 00108 The number of bytes required in the nonce[] array depends on how many 00109 bytes are needed to represent the message length in bytes. If 2, 3 or 00110 4 bytes are needed to store the message length, then the number of 00111 nonce bytes needed is 13, 12 or 11 respectively. 00112 */ 00113 00114 ret_type CCM_init( 00115 const unsigned char key[], unsigned long key_len,/* the key value to be used */ 00116 const unsigned char nonce[], /* the nonce value */ 00117 const unsigned char auth[], unsigned long ad_len,/* the additional authenticated data */ 00118 const mlen_type msg_len, /* message data length */ 00119 const unsigned long auth_field_len, /* the authentication field length */ 00120 CCM_ctx ctx[1]); /* the CCM context */ 00121 00122 /* Encrypt 'len' bytes data from imsg[] to omsg[]. This call can be repeated 00123 for multiple blocks provided that the sum of the individual block lengths 00124 is equal to the overall message length set by the call to CCM_init(). The 00125 last (omsg) block for which this routine is called must have space for the 00126 authentication field bytes in addition to the message bytes (i.e. omsg[] 00127 for the last call must have a length of 'len' + 'auth_field_len' bytes). 00128 If the return value is negative an error has occurred, otherwise the number 00129 of bytes written to omsg[] is returned. 00130 */ 00131 00132 ret_type CCM_encrypt(unsigned char mbuf[], /* the plaintext input message */ 00133 mlen_type len, /* the length of this block (bytes) */ 00134 CCM_ctx ctx[1]); /* the CCM context */ 00135 00136 /* Decrypt 'len' bytes data from imsg[] to omsg[]. This call can be repeated 00137 for multiple blocks provided that the sum of the individual block lengths 00138 is equal to the sum of the message length and the authentication field 00139 length set in the call to CCM_init(). The last block for which this routine 00140 is called must include the _complete_ authentication field (i.e. imsg[] for 00141 the last call must have a length of 'len' + 'auth_field_len' bytes). If the 00142 return value is negative an error has occurred, otherwise the number of 00143 bytes written to omsg[] is returned. 00144 */ 00145 00146 ret_type CCM_decrypt(unsigned char mbuf[], /* the plaintext input message */ 00147 mlen_type len, /* the length of this block (bytes) */ 00148 CCM_ctx ctx[1]); /* the CCM context */ 00149 00150 /* Perform an encryption or decryption in one call. The message length is the 00151 plaintext message length without the authentication field for both the 00152 encryption and decryption calls. If the return value is negative an error 00153 has occurred, otherwise the number of bytes written to omsg[] is returned. 00154 */ 00155 00156 ret_type CCM_mode( 00157 const unsigned char key[], unsigned long key_len,/* the key value to be used */ 00158 const unsigned char nonce[], /* the nonce value */ 00159 const unsigned char auth[], unsigned long ad_len,/* the additional authenticated data */ 00160 unsigned char msg[], mlen_type msg_len, /* the message data */ 00161 unsigned long auth_field_len, /* the authentication field length */ 00162 int ed_flag); /* 0 = encrypt, 1 = decrypt */ 00163 00164 #ifdef __cplusplus 00165 00166 } 00167 00168 #endif