* Implement AES CCM+CBC-MAC decryption and authentication. * Returns 0 on failure, 1 on success. * * The primary difference here is that each encrypted block * needs to be hashed&encrypted after it is decrypted (since * the CBC-MAC is based on the plain text). This means that * we do the decryption twice -- first to verify the tag, * and second to decrypt and copy it out. * * To avoid an
| 307 | * checksum. |
| 308 | */ |
| 309 | static void |
| 310 | decrypt_loop(const unsigned char *in, unsigned char *out, size_t nbytes, |
| 311 | __m128i s0, size_t nonce_length, __m128i *macp, |
| 312 | const unsigned char *key, int nr) |
| 313 | { |
| 314 | size_t total = 0; |
| 315 | __m128i s_x = s0, mac_block; |
| 316 | int counter = 1; |
| 317 | const size_t L = sizeof(__m128i) - 1 - nonce_length; |
| 318 | __m128i pad_block, staging_block; |
| 319 | |
| 320 | /* |
| 321 | * The starting mac (post AAD, if any). |
| 322 | */ |
| 323 | if (macp != NULL) |
| 324 | mac_block = *macp; |
| 325 | |
| 326 | while (total < nbytes) { |
| 327 | size_t copy_amt = MIN(nbytes - total, sizeof(staging_block)); |
| 328 | |
| 329 | if (copy_amt < sizeof(staging_block)) { |
| 330 | staging_block = _mm_setzero_si128(); |
| 331 | } |
| 332 | bcopy(in+total, &staging_block, copy_amt); |
| 333 | |
| 334 | /* |
| 335 | * staging_block has the current block of input data, |
| 336 | * zero-padded if necessary. This is used in computing |
| 337 | * both the decrypted data, and the authentication tag. |
| 338 | */ |
| 339 | append_int(counter++, &s_x, L+1); |
| 340 | /* |
| 341 | * The tag is computed based on the decrypted data. |
| 342 | */ |
| 343 | pad_block = AESNI_ENC(s_x, key, nr); |
| 344 | if (copy_amt < sizeof(staging_block)) { |
| 345 | /* |
| 346 | * Need to pad out pad_block with 0. |
| 347 | * (staging_block was set to 0's above.) |
| 348 | */ |
| 349 | uint8_t *end_of_buffer = (uint8_t*)&pad_block; |
| 350 | bzero(end_of_buffer + copy_amt, |
| 351 | sizeof(pad_block) - copy_amt); |
| 352 | } |
| 353 | staging_block = _mm_xor_si128(staging_block, pad_block); |
| 354 | |
| 355 | if (out) |
| 356 | bcopy(&staging_block, out+total, copy_amt); |
| 357 | |
| 358 | if (macp) |
| 359 | mac_block = xor_and_encrypt(mac_block, staging_block, |
| 360 | key, nr); |
| 361 | total += copy_amt; |
| 362 | } |
| 363 | |
| 364 | if (macp) |
| 365 | *macp = mac_block; |
| 366 |
no test coverage detected