Add 3DES CMAC for ARM

This commit is contained in:
Aaron Tulino (Aaronjamt)
2025-12-21 00:34:11 -07:00
parent fee7f02320
commit 63fc2b415d
3 changed files with 157 additions and 1 deletions
+2 -1
View File
@@ -153,7 +153,8 @@ THUMBSRC = start.c \
clocks.c \
hfsnoop.c \
generator.c \
cmac_calc.c
cmac_calc.c \
cmac_3des.c
# These are to be compiled in ARM mode
+126
View File
@@ -0,0 +1,126 @@
//-----------------------------------------------------------------------------
// Copyright (C) Aaron Tulino - December 2025
// Copyright (C) Christian Herrmman, Iceman - October 2025
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// Calculate CMAC 3DES
//-----------------------------------------------------------------------------
#include "cmac_3des.h"
#include <string.h>
#include "commonutil.h"
#include "dbprint.h"
#include "mbedtls/des.h"
// XOR two 64-bit blocks
static void xor_64(const uint8_t *a, const uint8_t *b, uint8_t *out) {
for (int i = 0; i < 8; i++) {
out[i] = a[i] ^ b[i];
}
}
// Left shift one bit in a 64-bit block
static void left_shift_64(const uint8_t *input, uint8_t *output) {
uint8_t overflow = 0;
for (int i = 7; i >= 0; i--) {
output[i] = (input[i] << 1) | overflow;
overflow = (input[i] & 0x80) ? 1 : 0;
}
}
// Generate Subkeys K1 and K2
static void generate_subkeys(mbedtls_des3_context *ctx, uint8_t *K1, uint8_t *K2) {
uint8_t L[8] = {0};
// Step 1: L = 3DES-ENC(0^64)
mbedtls_des3_crypt_ecb(ctx, L, L);
// Step 2: K1 = L << 1 (with conditional XOR with 0x1B)
left_shift_64(L, K1);
if (L[0] & 0x80) {
// If MSB is 1
K1[7] ^= 0x1B;
}
// Step 3: K2 = K1 << 1 (with conditional XOR with 0x1B)
left_shift_64(K1, K2);
if (K1[0] & 0x80) {
K2[7] ^= 0x1B;
}
}
// Pad the last block (adds 0x80 followed by zeros)
static void padding(const uint8_t *lastb, uint8_t *pad, size_t len) {
memcpy(pad, lastb, len);
pad[len] = 0x80;
for (size_t i = len + 1; i < 16; i++) {
pad[i] = 0x00;
}
}
// CMAC implementation
void des3_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[8]) {
uint8_t last[8] = {0};
uint8_t X[8] = {0};
uint8_t Y[8] = {0};
uint8_t buffer[8] = {0};
uint8_t K1[8] = {0};
uint8_t K2[8] = {0};
int last_block_complete = (ilen % 8 == 0 && ilen != 0);
mbedtls_des3_context ctx;
mbedtls_des3_init(&ctx);
if (key_len == 16) {
mbedtls_des3_set2key_enc(&ctx, key);
} else if (key_len == 24) {
mbedtls_des3_set3key_enc(&ctx, key);
}
generate_subkeys(&ctx, K1, K2);
size_t n_blocks = (ilen + 7) / 8;
// prepare last block
if (n_blocks == 0) {
// if message is empty, CMAC is just MAC of padded block XOR K2
// since buffer is all zeros here.
n_blocks = 1;
buffer[0] = 0x80;
xor_64(buffer, K2, last);
} else {
const uint8_t *last_block = input + 8 * (n_blocks - 1);
if (last_block_complete) {
xor_64(last_block, K1, last);
} else {
padding(last_block, buffer, ilen % 8);
xor_64(buffer, K2, last);
}
}
// main loop
for (size_t i = 0; i < n_blocks - 1; i++) {
xor_64(X, input + 8 * i, Y);
mbedtls_des3_crypt_ecb(&ctx, Y, X);
}
// last block
xor_64(X, last, Y);
mbedtls_des3_crypt_ecb(&ctx, Y, output);
mbedtls_des3_free(&ctx);
}
+29
View File
@@ -0,0 +1,29 @@
//-----------------------------------------------------------------------------
// Copyright (C) Aaron Tulino - December 2025
// Copyright (C) Christian Herrmman, Iceman - October 2025
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// Calculate CMAC 3DES
//-----------------------------------------------------------------------------
#ifndef __CMAC_3DES_H
#define __CMAC_3DES_H
#include "common.h"
void des3_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[8]);
#endif