Skip to content

Commit 6cf0cdd

Browse files
committed
AES decrypt function
1 parent 12bb471 commit 6cf0cdd

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

examples/ECCX08AES/ECCX08AES.ino

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ void setup() {
5555
Serial.print("tag: ");
5656
printHex(tag, 16);
5757
}
58+
59+
byte ptDecrypted[40];
60+
if (!ECCX08.AESDecrypt(IV, ad, ptDecrypted, ct, tag, adLength, ptLength)){
61+
Serial.println("Failed to decrypt.");
62+
} else {
63+
Serial.print("PT: ");
64+
printHex(ptDecrypted, ptLength);
65+
}
5866
}
5967

6068
void loop() {

src/ECCX08.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,71 @@ int ECCX08Class::AESEncrypt(byte IV[], byte ad[], byte pt[], byte ct[], byte tag
413413
return 1;
414414
}
415415

416+
int ECCX08Class::AESDecrypt(byte IV[], byte ad[], byte pt[], byte ct[], byte tag[], const uint64_t adLength, const uint64_t ctLength)
417+
{
418+
uint64_t maxLength = 1ull << 36;
419+
if (adLength >= maxLength || ctLength >= maxLength){
420+
return 0;
421+
}
422+
423+
byte H[16] = {0x00};
424+
if (!AESBlockEncrypt(H)){
425+
return 0;
426+
}
427+
428+
byte J0[16] = {0x00};
429+
memcpy(J0, IV, 12);
430+
J0[15] = 0x01;
431+
432+
int adPad = (-adLength) % 16;
433+
int ctPad = (-ctLength) % 16;
434+
435+
byte S[16];
436+
uint64_t inputLength = adLength+adPad+ctLength+ctPad+16;
437+
byte input[inputLength];
438+
memcpy(input, ad, adLength);
439+
memset(input+adLength, 0, adPad);
440+
memcpy(input+adLength+adPad, ct, ctLength);
441+
memset(input+adLength+adPad+ctLength, 0, ctPad);
442+
// Device is little endian
443+
// GCM specification requires big endian length representation
444+
// Hence we reverse the byte order of adLength and ctLength
445+
for (int i=0; i<8; i++){
446+
input[adLength+adPad+ctLength+ctPad+i] = (adLength >> (56-8*i)) & 0xFF;
447+
input[adLength+adPad+ctLength+ctPad+8+i] = (ctLength >> (56-8*i)) & 0xFF;
448+
}
449+
450+
if (!AESGHASH(H, input, S, inputLength)){
451+
return 0;
452+
}
453+
454+
byte tagComputed[16];
455+
if (!AESGCTR(J0, S, tagComputed, 16)){
456+
return 0;
457+
}
458+
459+
uint8_t equalBytes=0;
460+
for (int i=0; i<16; i++){
461+
equalBytes += (tag[i]==tagComputed[i]);
462+
}
463+
if (equalBytes!=16){
464+
// tag mismatch
465+
return 0;
466+
}
467+
468+
byte counterBlock[16];
469+
memcpy(counterBlock, J0, 16);
470+
if (!AESIncrementBlock(counterBlock)){
471+
return 0;
472+
}
473+
474+
if (!AESGCTR(counterBlock, ct, pt, ctLength)){
475+
return 0;
476+
}
477+
478+
return 1;
479+
}
480+
416481

417482
/** \brief GCTR function, see
418483
* NIST Special Publication 800-38D

src/ECCX08.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class ECCX08Class
5555
#define ECDH_MODE_OUTPUT ((uint8_t)0x0c) //!< ECDH mode: write to buffer
5656

5757
int AESEncrypt(byte IV[], byte ad[], byte pt[], byte ct[], byte tag[], const uint64_t adLength, const uint64_t ptLength);
58-
int AESDecrypt(byte IV[], byte ad[], byte pt[], byte ct[], byte tag[]);
58+
int AESDecrypt(byte IV[], byte ad[], byte pt[], byte ct[], byte tag[], const uint64_t adLength, const uint64_t ctLength);
5959

6060
int AESGCTR(byte counterBlock[], byte input[], byte output[], const uint64_t inputLength);
6161
int AESGHASH(byte counterBlock[], byte input[], byte output[], const uint64_t inputLength);

0 commit comments

Comments
 (0)