Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 44 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
44
Dung lượng
208,18 KB
Nội dung
As we recall from Chapter 4, CTR mode is as secure as the underlying block cipher (assuming it has been keyed and implemented properly) only if the IVs are unique. In this case, they would not be unique and an attacker could exploit the overlap. This places upper bounds on implementation. With CTRLEN set to 4, we can have only 2 32 packets, but each could be 2 100 bytes long. With CTRLEN set to 8, we can have 2 64 packets, each limited to 2 68 bytes. However, the longer the CTRLEN setting, the larger the overhead. Longer packet counters do not always help; on the other hand, short packet coun- ters can be ineffective if there is a lot of traffic. 129 /* Store counter */ 130 for (x = 0; x < CTRLEN; x++) { 131 out[x] = IV[x]; 132 } 133 134 /* encrypt message */ 135 if ((err = ctr_encrypt(in, out+CTRLEN, inlen, 136 &stream->channels[0].skey)) != CRYPT_OK) { 137 return err; 138 } At this point, we have stored the packet counter and the ciphertext in the output buffer. The first CTRLEN bytes are the counter, followed by the ciphertext. 140 /* HMAC the ctr+ciphertext */ 141 maclen = MACLEN; 142 if ((err = hmac_memory(find_hash(“sha256”), 143 stream->channels[0].mackey, MACKEYLEN, 144 out, inlen + CTRLEN, 145 out + inlen + CTRLEN, &maclen)) != CRYPT_OK) { 146 return err; 147 } Our ordering of the data is not haphazard. One might wonder why we did not place the HMAC tag after the packet counter.This function call answers this question. In one fell swoop, we can HMAC both the counter and the ciphertext. LibTomCrypt does provide a hmac_memory_multi() function, which is similar to hmac_memory() except that it uses a va_list to HMAC multiple regions of memory in a single function call (very similar to scattergather lists).That function has a higher caller over- head, as it uses va_list functions to retrieve the parameters. 149 /* packet out[0 inlen+CTRLEN+MACLEN-1] now 150 contains the authenticated ciphertext */ 151 return 0; 152 } www.syngress.com Message - Authentication Code Algorithms • Chapter 6 287 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 287 At this point, we have the entire packet ready to be transmitted. All packets that come in as inlen bytes in length come out as inlen+OVERHEAD bytes in length. 154 int decode_frame(const unsigned char *in, 155 unsigned inlen, 156 unsigned char *out, 157 encauth_stream *stream) 158 { This function decodes and authenticates an encoded frame. Note that inlen is the size of the packet created by encode_frame() and not the original plaintext length. 159 int err; 160 unsigned char IV[16], tag[MACLEN]; 161 unsigned long maclen; 162 163 /* restore our original inlen */ 164 if (inlen < MACLEN+CTRLEN) { return -1; } 165 inlen -= MACLEN+CTRLEN; We restore the plaintext length to make the rest of the function comparable with the encoding.The first check is to ensure that the input length is actually valid. We return –1 if it is not. 167 /* first compute the mactag */ 168 maclen = MACLEN; 169 if ((err = hmac_memory(find_hash(“sha256”), 170 stream->channels[1].mackey, MACKEYLEN, 171 in, inlen + CTRLEN, 172 tag, &maclen)) != CRYPT_OK) { 173 return err; 174 } 175 176 /* compare */ 177 if (memcmp(tag, in+inlen+CTRLEN, MACLEN)) { 178 return MAC_FAILED; 179 } At this point, we have verified the HMAC tag and it is valid. We are not out of the woods yet, however.The packet could be a replay or out of order. There is a choice of how the caller can handle a MAC failure. Very likely, if the medium is something as robust as Ethernet, or the underlying transport protocol guarantees delivery such as TCP, then a MAC failure is a sign of tampering.The caller should look at this as an active attack. On the other hand, if the medium is not robust, such as a radio link or water- mark, a MAC failure could just be the result of noise overpowering the signal. www.syngress.com 288 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 288 The caller must determine how to proceed based on the context of the application. 181 /* compare CTR */ 182 if (memcmp(in, stream->channels[1].PktCTR, CTRLEN) <= 0) { 183 return PKTCTR_FAILED; 184 } This memcmp() operation performs our nice big endian packet counter comparison. It will return a value <= 0 if the packet counter in the packet is not larger than the packet counter in our stream structure. We allow out of order packets, but only in the forward direction. For instance, receiving packets 0, 3, 4, 7, and 8 (in that order) would be valid; how- ever, the packets 0, 3, 4, 1, 2 (in that order) would not be. Unlike MAC failures, a counter failure can occur for various legitimate reasons. It is valid for UDP packets, for instance, to arrive in any order. While they will most likely arrive in order (especially over traditional IPv4 links), unordered packets are not always a sign of attack. Replayed packets, on the other hand, are usually not part of a transmission protocol. The reader may wish to augment this function to distinguish between replay and out of order packets (such as using the sliding window trick). 186 /* good to go, decrypt and copy the CTR */ 187 memset(IV, 0, 16); 188 memcpy(IV, in, CTRLEN); 189 memcpy(stream->channels[1].PktCTR, in, CTRLEN); 190 191 /* set IV */ 192 if ((err = ctr_setiv(IV, 16, 193 &stream->channels[1].skey)) != CRYPT_OK) { 194 return err; 195 } 196 197 /* encrypt message */ 198 if ((err = ctr_decrypt(in+CTRLEN, out, inlen, &stream->channels[1].skey)) != CRYPT_OK) { 199 return err; 200 } 201 return 0; 202 } Our test program will initialize two streams (one in either direction) and proceed to try to decrypt the same packet three times. It should work the first time, and fail the second and third times. On the second attempt, it should fail with a PKTCTR_FAILED error as we replayed the packet. On the third attempt, we have modified a byte of the payload and it should fail with a MAC_FAILED error. www.syngress.com Message - Authentication Code Algorithms • Chapter 6 289 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 289 204 int main(void) 205 { 206 unsigned char masterkey[16], salt[8]; 207 unsigned char inbuf[32], outbuf[32+OVERHEAD]; 208 encauth_stream incoming, outgoing; 209 int err; 210 211 /* setup lib */ 212 register_algorithms(); This sets up LibTomCrypt for use by our demonstration. 214 /* pick master key */ 215 rng_get_bytes(masterkey, 16, NULL); 216 rng_get_bytes(salt, 8, NULL); Here we are using the system RNG for our key and salt. In a real application, we need to get our master key from somewhere a bit more useful.The salt should be generated in this manner. Two possible methods of deriving a master key could be by hashing a user’s password, or sharing a random key by using a public key encryption scheme. 218 /* setup two streams */ 219 if ((err = init_stream(masterkey, 16, 220 salt, 8, 221 &incoming, 0)) != CRYPT_OK) { 222 printf(“init_stream error: %d\n”, err); 223 return EXIT_FAILURE; 224 } This initializes our incoming stream. Note that we used the value 0 for the node parameter. 226 /* other side of channel would use this one */ 227 if ((err = init_stream(masterkey, 16, 228 salt, 8, 229 &outgoing, 1)) != CRYPT_OK) { 230 printf(“init_stream error: %d\n”, err); 231 return EXIT_FAILURE; 232 } This initializes our outgoing stream. Note that we used the value 1 for the node param- eter. In fact, it does not matter which order we pick the node values in; as long as we are consistent, it will work fine. www.syngress.com 290 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 290 Note also that each side of the communication has to generate only one stream structure to both encode and decode. In our example, we generate two because we are both encoding and decoding data we generate. 234 /* make a sample message */ 235 memset(inbuf, 0, sizeof(inbuf)); 236 strcpy((char*)inbuf, “hello world”); Our traditional sample message. 238 if ((err = encode_frame(inbuf, sizeof(inbuf), 239 outbuf, &outgoing)) != CRYPT_OK) { 240 printf(“encode_frame error: %d\n”, err); 241 return EXIT_FAILURE; 242 } At this point, outbuf[0 sizeof(inbuf )+OVERHEAD-1] contains the packet. By trans- mitting the entire buffer to the other party, they can authenticate and decrypt it. 244 /* now let’s try to decode it */ 245 memset(inbuf, 0, sizeof(inbuf)); 246 if ((err = decode_frame(outbuf, sizeof(outbuf), 247 inbuf, &incoming)) != CRYPT_OK) { 248 printf(“decode_frame error: %d\n”, err); 249 return EXIT_FAILURE; 250 } 251 printf(“Decoded data: [%s]\n”, inbuf); We first clear the inbuf array to show that the routine did indeed decode the data. We decode the buffer using the incoming stream structure. At this point we should see the string Decoded data: [hello world] on the terminal. 253 /* now let’s try to decode it again (should fail) */ 254 memset(inbuf, 0, sizeof(inbuf)); 255 if ((err = decode_frame(outbuf, sizeof(outbuf), 256 inbuf, &incoming)) != CRYPT_OK) { 257 printf(“decode_frame error: %d\n”, err); 258 if (err != PKTCTR_FAILED) { 259 printf(“We got the wrong error!\n”); 260 return EXIT_FAILURE; 261 } 262 } www.syngress.com Message - Authentication Code Algorithms • Chapter 6 291 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 291 This represents a replayed packet. It should fail with PKTCTR_FAILED, and we should see decode_frame error: -4 on the terminal. 264 /* let’s modify a byte and try again */ 265 memset(inbuf, 0, sizeof(inbuf)); 266 outbuf[CTRLEN] ^= 0x01; 267 if ((err = decode_frame(outbuf, sizeof(outbuf), 268 inbuf, &incoming)) != CRYPT_OK) { 269 printf(“decode_frame error: %d\n”, err); 270 if (err != MAC_FAILED) { 271 printf(“We got the wrong error!\n”); 272 return EXIT_FAILURE; 273 } 274 } This represents both a replayed and forged message. It should fail the MAC test before getting to the packet counter check. We should see decode_frame error: -3 on the terminal. 276 return EXIT_SUCCESS; 277 } This demonstration represents code that is not entirely optimal.There are several methods of improving it based on the context it will be used. The first useful optimization ensures the ciphertext is aligned on a 16-byte boundary. This allows the LibTomCrypt routines to safely use word-aligned XOR operations to per- form the CTR encryption.A simple way to accomplish this is to pad the message with zero bytes between the packet counter and the ciphertext (include it as part of the MAC input). The second optimization involves knowledge of how LibTomCrypt works; the CTR structure exposes the IV nicely, which means we can directly set the IV instead of using ctr_setiv() to update it. The third optimization is also a security optimization. By making the code thread safe, we can decode or encode multiple packets at once.This combined with a sliding window for the packet counter can ensure that even if the threads are executed out of order, we are reasonable assured that the decoder will accept them. www.syngress.com 292 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 292 Q: What is a MAC function? A: A MAC or message authentication code function is a function that accepts a secret key and message and reduces it to a MAC tag. Q: What is a MAC tag? A: A tag is a short string of bits that is used to prove that the secret key and message were processed together through the MAC function. Q: What does that mean? What does authentication mean? A: Being able to prove that the message and secret key were combined to produce the tag can directly imply one thing: that the holder of the key produced vouches for or simply wishes to convey an unaltered original message. A forger not possessing the secret key should have no significant advantage in producing verifiable MAC tags for messages. In short, the goal of a MAC function is to be able to conclude that if the MAC tag is cor- rect, the message is intact and was not modified during transit. Since only a limited number of parties (typically only one or two) have the secret key, the ownership of the message is rather obvious. Q: What standards are there? A: There are two NIST standards for MAC functions currently worth considering.The CMAC standard is SP 800-38B and specifies a method of turning a block cipher into a MAC function.The HMAC standard is FIPS-198 and specifies a method of turning a hash function into a MAC. An older standard, FIPS-113, specifies CBC-MAC (a pre- cursor to CMAC) using DES, and should be considered insecure. Q: Should I use CMAC or HMAC? A: Both CMAC and HMAC are secure when keyed and implemented safely. CMAC is typically more efficient for very short messages. It is also ideal for instances where a cipher is already deployed and space is limited. HMAC is more efficient for larger mes- www.syngress.com Message - Authentication Code Algorithms • Chapter 6 293 Frequently Asked Questions The following Frequently Asked Questions, answered by the authors of this book, are designed to both measure your understanding of the concepts presented in this chapter and to assist you with real-life implementation of these concepts. To have your questions about this chapter answered by the author, browse to www.syngress.com/solutions and click on the “Ask the Author” form. 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 293 sages, and ideal when a hash is already deployed. Of course, you should pick whichever matches the standard you are trying to adhere to. Q: What is advantage? A: We have seen the term advantage several times in our discussion already. Essentially, the advantage of an attacker refers to the probability of forgery gained by a forger through analysis of previously authenticated messages. In the case of CMAC, for instance, the advantage is roughly approximate to (mq) 2 /2 126 for CMAC-AES—where m is the number of messages authenticated, and q is the number of AES blocks per message. As the ratio approaches one, the probability of a successful forgery approaches one as well. Advantage is a little different in this context than in the symmetric encryption con- text. An advantage of 2 –40 is not the same as using a 40-bit encryption key.An attack on the MAC must take place online.This means, an attacker has but one chance to guess the correct MAC tag. In the latter context, an attacker can guess encryption keys offline and does not run the risk of exposure. Q: How do key lengths play into the security of MAC functions? A: Key lengths matter for MAC functions in much the same way they matter in symmetric cryptography.The longer the key, the longer a brute force key determination will take. If an attacker can guess a message, he can forge messages. Q: How does the length of the MAC tag play into the security of MAC functions? A: The length of the MAC tag is often variable (at least it is in HMAC and CMAC) and can limit the security of the MAC function.The shorter the tag, the more likely a forger is to guess it correctly. Unlike hash functions, the birthday paradox attack does not apply. Therefore, short MAC tags are often ideally secure for particular applications. Q: How do I match up key length, MAC tag length, and advantage? A: Your key length should ideally be as large as possible.There is often little practical value to using shorter keys. For instance, padding an AES-128 key with 88 bits of zeroes, effectively reducing it to a 40-bit key, may seem like it requires fewer resources. In fact, it saves no time or space and weakens the system. Ideally, for a MAC tag length of w- bits, you wish to give your attacker an advantage of no more than 2 -w . For instance, if you are going to send 2 40 blocks of message data with CMAC-AES, the attacker’s advan- tage is no less than 2 –46 . In this case, a tag longer than 46 bits is actually wasteful as you approach the 2 40 th block of message data. On the other hand, if you are sending a trivial amount of message blocks, the advantage is very small and the tag length can be cus- tomized to suit bandwidth needs. www.syngress.com 294 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 294 Q: Why can I not use hash(key || message) as a MAC function? A: Such a construction is not resistant to offline attacks and is also vulnerable to message extension attacks. Forging messages is trivial with this scheme. Q: What is a replay attack? A: A replay attack can occur when you break a larger message into smaller independent pieces (e.g., packets).The attacker exploits the fact that unless you correlate the order of the packets, the attacker can change the meaning of the message simply by re-arranging the order of the packets. While each individual packet may be authenticated, it is not being modified.Thus, the attack goes unnoticed. Q: Why do I care? A: Without replay protection, an attacker can change the meaning of the overall message. Often, this implies the attacker can re-issue statements or commands. An attacker could, for instance, re-issue shell commands sent by a remote login shell. Q: How do I defeat replay attacks? A: The most obvious solution is to have a method of correlating the packets to their overall (relative) order within the larger stream of packets that make up the message.The most obvious solutions are timestamp counters and simple incremental counters. In both cases, the counter is included as part of the message authenticated. Filtering based on previously authenticated counters prevents an attacker from re-issuing an old packet or issuing them out of stream order. Q: How do I deal with packet loss or re-ordering? A: Occasionally, packet loss and re-ordering are part of the communication medium. For example, UDP is a lossy protocol that tolerates packet loss. Even when packets are not lost, they are not guaranteed to arrive in any particular order (this is often a warning that does not arise in most networks). Out of order UDP is fairly rare on non-congested IPv4 networks.The meaning of the error depends on the context of the application. If you are working with UDP (or another lossy medium), packet loss and re-ordering are usually not malicious acts.The best practice is to reject the packet, possibly issue a syn- chronization message, and resume the protocol. Note that an attacker may exploit the resynchronization step to have a victim generate authenticated messages. On a relatively stable medium such as TCP, packet loss and reordering are usually a sign of malicious interference and should be treated as hostile.The usual action here is to drop the con- nection. (Commonly, this is argued to be a denial of service (DoS) attack vector. However, anyone with the ability to modify packets between you and another host can also simply filter all packets anyways.) There is no added threat by taking this precaution. www.syngress.com Message - Authentication Code Algorithms • Chapter 6 295 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 295 In both cases, whether the error is treated as hostile or benign, the packet should be dropped and not interpreted further up the protocol stack. Q: What libraries provide MAC functionality? A: LibTomCrypt provides a highly modular HMAC function for C developers. Crypto++ provides similar functionality for C++ developers. Limited HMAC support is also found in OpenSSL. LibTomCrypt also provides modular support for CMAC. At the time of this writing, neither Crypto++ or OpenSSL provide support for CMAC. By “modular,” we mean that the HMAC and CMAC implementations are not tied to underlying algo- rithms. For instance, the HMAC code in LibTomCrypt can use any hash function that LibTomCrypt supports without changes to the API.This allows future upgrades to be performed in a more timely and streamlined fashion. Q: What patents cover MAC functions? A: Both HMAC and CMAC are patent free and can be used for any purpose. Various other MAC functions such as PMAC are covered by patents but are also not standard. www.syngress.com 296 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 296 [...]... int x; for (x = 15; x > 0; x ) { a[x] = (a[x]>>1) | ((a[x-1]= 1; } This function performs the right shift (multiplication by x) using GCM conventions 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 0 98 099 100 101 102 /* c = b*a */ static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x 08, 0x04, 0x02, 0x01 }; static const unsigned char poly[] = { 0x00,... fully unrolled and turned into simple load and XOR operations 075 076 077 /* GMAC it */ gcm->pttotlen += 1 28; gcm_mult_h(gcm, gcm->X); Since we are processing 16-byte blocks, we always perform the multiplication by H on the accumulated data 0 78 079 080 081 082 083 084 085 086 /* increment counter */ for (y = 15; y >= 12; y ) { if (++gcm->Y[y] & 255) { break; } } if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(... slower multiplier, since at this point we do not have tables to work with 072 073 074 075 076 077 0 78 079 080 081 082 083 084 /* now generate the rest of the tables * based the previous table */ for (x = 1; x < 16; x++) { for (y = 0; y < 256; y++) { /* now shift it right by 8 bits */ t = gcm->PC[x-1][y][15]; for (z = 15; z > 0; z ) { gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; } gcm->PC[x][y][0] = gcm_shift_table[tbuflen = 0; gcm->totlen = 0; gcm->mode = GCM_MODE_AAD; } if (gcm->mode != GCM_MODE_AAD || gcm->buflen >= 16) { return CRYPT_INVALID_ARG; } At this point, we check that we are indeed in AAD mode and that our buflen is a legal value 072 073 074 075 076 077 0 78 079 080 081 082 083 084 x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { for. .. B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i]; B[M(9)][i] = B[M(1)][i] ^ B[M (8) ][i]; B[M(10)][i] = B[M(2)][i] ^ B[M (8) ][i]; B[M(12)][i] = B[M (8) ][i] ^ B[M(4)][i]; /* now all 3 bit values and the only 4 bit value: www.syngress.com 309 404_CRYPTO_07.qxd 310 10/30/06 11:51 AM Page 310 Chapter 7 • Encrypt and Authenticate Modes 177 1 78 179 180 181 182 183 * 7, 11, 13, 14, 15 */ B[M(7)][i] = B[M(3)][i] B[M(11)][i] =... Destination for a * b */ void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) { unsigned char Z[16], V[16]; unsigned x, y, z; zeromem(Z, 16); XMEMCPY(V, a, 16); www.syngress.com 307 404_CRYPTO_07.qxd 3 08 10/30/06 11:51 AM Page 3 08 Chapter 7 • Encrypt and Authenticate Modes 103 104 105 106 107 1 08 109 110 111 112 113 114 for (x = 0; x < 1 28; x++) { if (b[x>>3] & mask[x&7]) { for. .. use the tables approach.The PC table contains 16 8x1 28 tables, one for each byte of the input and for each of their respective possible values.The first thing we must do is copy the 0th entry to T (our accumulator).The rest of the lookups will be XORed into this value 012 013 014 015 016 017 0 18 019 020 021 022 for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) . signal. www.syngress.com 288 Chapter 6 • Message - Authentication Code Algorithms 404_CRYPTO_06.qxd 10/30/06 10:20 AM Page 288 The caller must determine how to proceed based on the context of the application. 181 /*. packets (such as using the sliding window trick). 186 /* good to go, decrypt and copy the CTR */ 187 memset(IV, 0, 16); 188 memcpy(IV, in, CTRLEN); 189 memcpy(stream->channels[1].PktCTR, in, CTRLEN); 190. HMAC function for C developers. Crypto++ provides similar functionality for C++ developers. Limited HMAC support is also found in OpenSSL. LibTomCrypt also provides modular support for CMAC. At