Roy Want / Mbed OS beaconCompileReadyFork
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aes_eax.cpp Source File

aes_eax.cpp

00001 /*
00002  * Copyright (c) 2016, Google Inc, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017  
00018 #include <string.h>
00019 
00020 // #include "aes_eax.h"
00021 // set defines before loading aes.h
00022 #define MBEDTLS_CIPHER_MODE_CBC
00023 #define MBEDTLS_CIPHER_MODE_CTR
00024 #include "aes.h"
00025 
00026 #define EDDY_ERR_EAX_AUTH_FAILED    -0x000F /**< Authenticated decryption failed. */
00027 
00028 void gf128_double_( unsigned char val[16] )
00029 {
00030     int i;
00031     int carry = val[0] >> 7;
00032     int xv = (-carry) & 0x87;
00033     for (i = 15; i >= 0; i--) {
00034         carry = val[i] >> 7;
00035         val[i] = (val[i] << 1) ^ xv;
00036         xv = carry;
00037     }
00038 }
00039 
00040 int compute_cmac_( mbedtls_aes_context *ctx,
00041                   const unsigned char *input,
00042                   size_t length,
00043                   unsigned char param,
00044                   unsigned char mac[16] )
00045 {
00046     unsigned char buf[16], iv[16];
00047     memset(buf, 0, sizeof(buf));
00048     buf[15] = param;
00049     memset(iv, 0, sizeof(iv));
00050     length += 16;
00051 
00052     unsigned char pad[16];
00053     memset(pad, 0, sizeof(pad));
00054     mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, pad, pad);
00055     gf128_double_(pad);
00056     if (length & 15) {
00057         gf128_double_(pad);
00058         pad[length & 15] ^= 0x80;
00059     }
00060 
00061     const unsigned char *tmp_input = buf;
00062     while (length > 16) {
00063         mbedtls_aes_crypt_cbc(ctx, MBEDTLS_AES_ENCRYPT, 16, iv, tmp_input, buf);
00064         if (tmp_input == buf) {
00065             tmp_input = input;
00066         } else {
00067             tmp_input += 16;
00068         }
00069         length -= 16;
00070     }
00071 
00072     size_t i;
00073     for (i = 0; i < length; i++)
00074         pad[i] ^= tmp_input[i];
00075 
00076     mbedtls_aes_crypt_cbc(ctx, MBEDTLS_AES_ENCRYPT, 16, iv, pad, mac);
00077     return 0;
00078 }
00079 
00080 int eddy_aes_authcrypt_eax( mbedtls_aes_context *ctx,
00081                             int mode,                   
00082                             const unsigned char *nonce, 
00083                             size_t nonce_length,        
00084                             const unsigned char *header,
00085                             size_t header_length, 
00086                             size_t message_length,
00087                             const unsigned char *input,
00088                             unsigned char *output,
00089                             unsigned char *tag,
00090                             size_t tag_length )
00091 {
00092     unsigned char header_mac[16];
00093     unsigned char nonce_mac[16];
00094     unsigned char ciphertext_mac[16];
00095     uint8_t i;
00096     compute_cmac_(ctx, header, header_length, 1, header_mac);
00097     compute_cmac_(ctx, nonce, nonce_length, 0, nonce_mac);
00098     if (mode == MBEDTLS_AES_DECRYPT) {
00099         compute_cmac_(ctx, input, message_length, 2, ciphertext_mac);
00100         unsigned char n_ok = 0;
00101         for (i = 0; i < tag_length; i++) {
00102             ciphertext_mac[i] ^= header_mac[i];
00103             ciphertext_mac[i] ^= nonce_mac[i];
00104             ciphertext_mac[i] ^= tag[i];
00105             n_ok |= ciphertext_mac[i];
00106         }
00107         if (n_ok)
00108             return EDDY_ERR_EAX_AUTH_FAILED;
00109     }
00110     size_t nc_off = 0;
00111     unsigned char nonce_copy[16];
00112     memcpy(nonce_copy, nonce_mac, sizeof(nonce_mac));
00113     unsigned char sb[16];
00114     mbedtls_aes_crypt_ctr(ctx, message_length, &nc_off, nonce_copy, sb, input, output);
00115     if (mode == MBEDTLS_AES_ENCRYPT) {
00116         compute_cmac_(ctx, output, message_length, 2, ciphertext_mac); 
00117         for (i = 0; i < tag_length; i++)
00118             tag[i] = header_mac[i] ^ nonce_mac[i] ^ ciphertext_mac[i];
00119     }
00120     return 0;
00121 }