Skip to content

Commit 8f6dd60

Browse files
authored
Merge pull request #3054 from aaronjamt/patch-3des-cmac
Add 3DES CMAC for ARM
2 parents fee7f02 + 63fc2b4 commit 8f6dd60

File tree

3 files changed

+157
-1
lines changed

3 files changed

+157
-1
lines changed

armsrc/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ THUMBSRC = start.c \
153153
clocks.c \
154154
hfsnoop.c \
155155
generator.c \
156-
cmac_calc.c
156+
cmac_calc.c \
157+
cmac_3des.c
157158

158159

159160
# These are to be compiled in ARM mode

armsrc/cmac_3des.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//-----------------------------------------------------------------------------
2+
// Copyright (C) Aaron Tulino - December 2025
3+
// Copyright (C) Christian Herrmman, Iceman - October 2025
4+
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU General Public License for more details.
15+
//
16+
// See LICENSE.txt for the text of the license.
17+
//-----------------------------------------------------------------------------
18+
// Calculate CMAC 3DES
19+
//-----------------------------------------------------------------------------
20+
#include "cmac_3des.h"
21+
22+
#include <string.h>
23+
#include "commonutil.h"
24+
#include "dbprint.h"
25+
#include "mbedtls/des.h"
26+
27+
// XOR two 64-bit blocks
28+
static void xor_64(const uint8_t *a, const uint8_t *b, uint8_t *out) {
29+
for (int i = 0; i < 8; i++) {
30+
out[i] = a[i] ^ b[i];
31+
}
32+
}
33+
34+
// Left shift one bit in a 64-bit block
35+
static void left_shift_64(const uint8_t *input, uint8_t *output) {
36+
uint8_t overflow = 0;
37+
for (int i = 7; i >= 0; i--) {
38+
output[i] = (input[i] << 1) | overflow;
39+
overflow = (input[i] & 0x80) ? 1 : 0;
40+
}
41+
}
42+
43+
// Generate Subkeys K1 and K2
44+
static void generate_subkeys(mbedtls_des3_context *ctx, uint8_t *K1, uint8_t *K2) {
45+
uint8_t L[8] = {0};
46+
47+
// Step 1: L = 3DES-ENC(0^64)
48+
mbedtls_des3_crypt_ecb(ctx, L, L);
49+
50+
// Step 2: K1 = L << 1 (with conditional XOR with 0x1B)
51+
left_shift_64(L, K1);
52+
if (L[0] & 0x80) {
53+
// If MSB is 1
54+
K1[7] ^= 0x1B;
55+
}
56+
57+
// Step 3: K2 = K1 << 1 (with conditional XOR with 0x1B)
58+
left_shift_64(K1, K2);
59+
if (K1[0] & 0x80) {
60+
K2[7] ^= 0x1B;
61+
}
62+
}
63+
64+
// Pad the last block (adds 0x80 followed by zeros)
65+
static void padding(const uint8_t *lastb, uint8_t *pad, size_t len) {
66+
memcpy(pad, lastb, len);
67+
pad[len] = 0x80;
68+
for (size_t i = len + 1; i < 16; i++) {
69+
pad[i] = 0x00;
70+
}
71+
}
72+
73+
// CMAC implementation
74+
void des3_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[8]) {
75+
uint8_t last[8] = {0};
76+
uint8_t X[8] = {0};
77+
uint8_t Y[8] = {0};
78+
uint8_t buffer[8] = {0};
79+
uint8_t K1[8] = {0};
80+
uint8_t K2[8] = {0};
81+
82+
int last_block_complete = (ilen % 8 == 0 && ilen != 0);
83+
84+
mbedtls_des3_context ctx;
85+
mbedtls_des3_init(&ctx);
86+
if (key_len == 16) {
87+
mbedtls_des3_set2key_enc(&ctx, key);
88+
} else if (key_len == 24) {
89+
mbedtls_des3_set3key_enc(&ctx, key);
90+
}
91+
92+
generate_subkeys(&ctx, K1, K2);
93+
94+
size_t n_blocks = (ilen + 7) / 8;
95+
96+
// prepare last block
97+
if (n_blocks == 0) {
98+
// if message is empty, CMAC is just MAC of padded block XOR K2
99+
// since buffer is all zeros here.
100+
n_blocks = 1;
101+
buffer[0] = 0x80;
102+
xor_64(buffer, K2, last);
103+
} else {
104+
105+
const uint8_t *last_block = input + 8 * (n_blocks - 1);
106+
107+
if (last_block_complete) {
108+
xor_64(last_block, K1, last);
109+
} else {
110+
padding(last_block, buffer, ilen % 8);
111+
xor_64(buffer, K2, last);
112+
}
113+
}
114+
115+
// main loop
116+
for (size_t i = 0; i < n_blocks - 1; i++) {
117+
xor_64(X, input + 8 * i, Y);
118+
mbedtls_des3_crypt_ecb(&ctx, Y, X);
119+
}
120+
121+
// last block
122+
xor_64(X, last, Y);
123+
mbedtls_des3_crypt_ecb(&ctx, Y, output);
124+
mbedtls_des3_free(&ctx);
125+
126+
}

armsrc/cmac_3des.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//-----------------------------------------------------------------------------
2+
// Copyright (C) Aaron Tulino - December 2025
3+
// Copyright (C) Christian Herrmman, Iceman - October 2025
4+
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU General Public License for more details.
15+
//
16+
// See LICENSE.txt for the text of the license.
17+
//-----------------------------------------------------------------------------
18+
// Calculate CMAC 3DES
19+
//-----------------------------------------------------------------------------
20+
21+
#ifndef __CMAC_3DES_H
22+
#define __CMAC_3DES_H
23+
24+
25+
#include "common.h"
26+
27+
void des3_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[8]);
28+
29+
#endif

0 commit comments

Comments
 (0)