BeRTOS
omac.c
Go to the documentation of this file.
00001 
00037 #include "omac.h"
00038 #include <cfg/macros.h>
00039 #include <sec/util.h>
00040 
00041 static void omac_set_key(Mac *ctx_, const void* key, size_t len)
00042 {
00043     OmacContext *ctx = (OmacContext *)ctx_;
00044     cipher_set_vkey(ctx->c, key, len);
00045 }
00046 
00047 static void omac_begin(Mac *ctx_)
00048 {
00049     OmacContext *ctx = (OmacContext *)ctx_;
00050 
00051     ctx->acc = 0;
00052 
00053     memset(ctx->Y, 0, cipher_block_len(ctx->c));
00054     cipher_cbc_begin(ctx->c, ctx->Y);
00055 }
00056 
00057 static void omac_update(Mac *ctx_, const void *data_, size_t len)
00058 {
00059     OmacContext *ctx = (OmacContext *)ctx_;
00060     size_t blen = cipher_block_len(ctx->c);
00061     const uint8_t *data = (const uint8_t *)data_;
00062 
00063     while (len)
00064     {
00065         ASSERT(ctx->acc <= blen);
00066         if (ctx->acc == blen)
00067         {
00068             cipher_cbc_encrypt(ctx->c, ctx->accum);
00069             ctx->acc = 0;
00070         }
00071 
00072         size_t L = MIN(len, blen - ctx->acc);
00073         memcpy(ctx->accum + ctx->acc, data, L);
00074         data += L;
00075         len -= L;
00076         ctx->acc += L;
00077     }
00078 }
00079 
00080 static void omac_shift_left(uint8_t *L, size_t len)
00081 {
00082     int firstbit = L[0] >> 7;
00083     size_t i;
00084 
00085     for (i=0; i<len-1; ++i)
00086         L[i] = (L[i] << 1) | (L[i+1] >> 7);
00087     L[i] <<= 1;
00088 
00089     if (firstbit)
00090     {
00091         if (len == 16)
00092             L[i] ^= 0x87;
00093         else if (len == 8)
00094             L[i] ^= 0x1B;
00095         else
00096             ASSERT(0);
00097     }
00098 }
00099 
00100 static void omac_shift_right(uint8_t *L, size_t len)
00101 {
00102     int firstbit = L[len-1] & 1;
00103     size_t i;
00104 
00105     for (i=len-1; i>0; --i)
00106         L[i] = (L[i] >> 1) | (L[i-1] << 7);
00107     L[i] >>= 1;
00108 
00109     if (firstbit)
00110     {
00111         L[i] |= 0x80;
00112         if (len == 16)
00113             L[len-1] ^= 0x43;
00114         else if (len == 8)
00115             L[len-1] ^= 0x0D;
00116         else
00117             ASSERT(0);
00118     }
00119 }
00120 
00121 static uint8_t *omac1_final(Mac *ctx_)
00122 {
00123     OmacContext *ctx = (OmacContext *)ctx_;
00124     size_t blen = cipher_block_len(ctx->c);
00125 
00126     uint8_t L[blen];
00127     memset(L, 0, blen);
00128     cipher_ecb_encrypt(ctx->c, L);
00129 
00130     omac_shift_left(L, blen);
00131     if (ctx->acc < blen)
00132     {
00133         ctx->accum[ctx->acc++] = 0x80;
00134         memset(ctx->accum + ctx->acc, 0, blen - ctx->acc);
00135         omac_shift_left(L, blen);
00136     }
00137 
00138     xor_block(ctx->accum, ctx->accum, L, blen);
00139     cipher_cbc_encrypt(ctx->c, ctx->accum);
00140     return ctx->accum;
00141 }
00142 
00143 static uint8_t *omac2_final(Mac *ctx_)
00144 {
00145     OmacContext *ctx = (OmacContext *)ctx_;
00146     size_t blen = cipher_block_len(ctx->c);
00147 
00148     uint8_t L[blen];
00149     memset(L, 0, blen);
00150     cipher_ecb_encrypt(ctx->c, L);
00151 
00152     if (ctx->acc < blen)
00153     {
00154         ctx->accum[ctx->acc++] = 0x80;
00155         memset(ctx->accum + ctx->acc, 0, blen - ctx->acc);
00156         omac_shift_right(L, blen);
00157     }
00158     else
00159         omac_shift_left(L, blen);
00160 
00161     xor_block(ctx->accum, ctx->accum, L, blen);
00162     cipher_cbc_encrypt(ctx->c, ctx->accum);
00163     return ctx->accum;
00164 }
00165 
00166 
00167 /****************************************************************************/
00168 
00169 static void omac_init(OmacContext *ctx, BlockCipher *c)
00170 {
00171     ctx->mac.set_key = omac_set_key;
00172     ctx->mac.begin = omac_begin;
00173     ctx->mac.update = omac_update;
00174     ctx->mac.key_len = cipher_key_len(c);
00175     ctx->mac.digest_len = cipher_block_len(c);
00176     ctx->c = c;
00177 
00178     ASSERT(cipher_block_len(c) == 8 || cipher_block_len(c) == 16);
00179     ASSERT(sizeof(ctx->Y) >= cipher_block_len(c));
00180     ASSERT(sizeof(ctx->accum) >= cipher_block_len(c));
00181 }
00182 
00183 void omac1_init(OmacContext *ctx, BlockCipher *c)
00184 {
00185     omac_init(ctx, c);
00186     ctx->mac.final = omac1_final;
00187 }
00188 
00189 void omac2_init(OmacContext *ctx, BlockCipher *c)
00190 {
00191     omac_init(ctx, c);
00192     ctx->mac.final = omac2_final;
00193 }