Skip to content

Commit abf0fd9

Browse files
authored
Merge pull request #2579 from ssievert42/crypto_aes_ccm
crypto: add support for AES CCM
2 parents ff3ae01 + dc31001 commit abf0fd9

File tree

8 files changed

+162
-0
lines changed

8 files changed

+162
-0
lines changed

ChangeLog

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
ESP32: add setIP and setAPIP
7070
Graphics.wrapString fix issue with missing final char if immediately after a '.' or other char we can split after (#2572)
7171
Graphics: g.dump/asBMP can now output 16 bit images
72+
Crypto: Add support for AES CCM
7273

7374
2v24 : Bangle.js2: Add 'Bangle.touchRd()', 'Bangle.touchWr()'
7475
Bangle.js2: After Bangle.showTestScreen, put Bangle.js into a hard off state (not soft off)

boards/BANGLEJS2.py

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
'TERMINAL',
3737
'GRAPHICS',
3838
'CRYPTO','SHA256','SHA512',
39+
'AES_CCM',
3940
'LCD_MEMLCD',
4041
'TENSORFLOW',
4142
'JIT' # JIT compiler enabled

boards/EMSCRIPTEN2.py

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
'LCD_MEMLCD',
2929
# 'FILESYSTEM',
3030
'CRYPTO','SHA256','SHA512',
31+
'AES_CCM',
3132
# 'TLS',
3233
# 'TELNET',
3334
],

boards/LINUX.py

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
'GRAPHICS',
2727
'FILESYSTEM',
2828
'CRYPTO','SHA256','SHA512',
29+
'AES_CCM',
2930
'TLS',
3031
'TELNET',
3132
],

libs/crypto/jswrap_crypto.c

+134
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#ifdef USE_AES
2222
#include "mbedtls/aes.h"
2323
#endif
24+
#ifdef USE_AES_CCM
25+
#include "mbedtls/ccm.h"
26+
#endif
2427
#ifndef USE_SHA1_JS
2528
#include "mbedtls/sha1.h"
2629
#endif
@@ -92,6 +95,9 @@ const char *jswrap_crypto_error_to_str(int err) {
9295
case MBEDTLS_ERR_MD_BAD_INPUT_DATA: return "Bad input data";
9396
#ifdef USE_AES
9497
case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: return "Invalid input length";
98+
#endif
99+
#ifdef USE_AES_CCM
100+
case MBEDTLS_ERR_CCM_AUTH_FAILED: return "Authenticated decryption failed";
95101
#endif
96102
}
97103
return 0;
@@ -485,3 +491,131 @@ JsVar *jswrap_crypto_AES_decrypt(JsVar *message, JsVar *key, JsVar *options) {
485491
return jswrap_crypto_AEScrypt(message, key, options, false);
486492
}
487493
#endif
494+
495+
#ifdef USE_AES_CCM
496+
// if encrypting, tagArg is tag length
497+
// if decrypting, tagArg is tag that came with the message
498+
JsVar *jswrap_crypto_AES_ccmCrypt(JsVar *message, JsVar *key, JsVar *iv, JsVar *tagArg, bool encrypt) {
499+
unsigned char ivVal[13];
500+
memset(ivVal, 0, sizeof(ivVal));
501+
int ivLenVal = 0;
502+
if (jsvIsArray(iv) || jsvIsArrayBuffer(iv)){
503+
jsvIterateCallbackToBytes(iv, ivVal, sizeof(ivVal));
504+
ivLenVal = jsvGetLength(iv);
505+
if (ivLenVal < 2 || ivLenVal > sizeof(ivVal)) {
506+
jswrap_crypto_error(MBEDTLS_ERR_MD_BAD_INPUT_DATA);
507+
return NULL;
508+
}
509+
} else {
510+
jswrap_crypto_error(MBEDTLS_ERR_MD_BAD_INPUT_DATA);
511+
return NULL;
512+
}
513+
514+
JSV_GET_AS_CHAR_ARRAY(messagePtr, messageLen, message);
515+
if (!messagePtr) return NULL;
516+
517+
JSV_GET_AS_CHAR_ARRAY(keyPtr, keyLen, key);
518+
if (!keyPtr) return NULL;
519+
520+
char *outMessagePtr = NULL;
521+
JsVar *outVar = jsvNewArrayBufferWithPtr(messageLen, &outMessagePtr);
522+
if (!outMessagePtr) return NULL;
523+
524+
int err = 0;
525+
mbedtls_ccm_context ctx;
526+
mbedtls_ccm_init(&ctx);
527+
err = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, (unsigned char*)keyPtr, (unsigned int)keyLen*8);
528+
if (err == 0) {
529+
if (encrypt) {
530+
// encrypt and generate tag
531+
int tagLenVal = 0;
532+
if (jsvIsNumeric(tagArg)) {
533+
tagLenVal = jsvGetInteger(tagArg);
534+
} else {
535+
err = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
536+
}
537+
if (err == 0) {
538+
if (tagLenVal < 4 || tagLenVal > 16 || tagLenVal % 2 != 0) {
539+
// invalid tag length; must be one of 4, 6, 8, 10, 12, 14 or 16
540+
err = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
541+
}
542+
}
543+
if (err == 0) {
544+
unsigned char tag[tagLenVal];
545+
memset(tag, 0, sizeof(tag));
546+
err = mbedtls_ccm_encrypt_and_tag(&ctx, messageLen, ivVal, ivLenVal, NULL, 0, (unsigned char*)messagePtr, (unsigned char*)outMessagePtr, tag, sizeof(tag));
547+
if (err == 0) {
548+
JsVar *outMessageVar = outVar;
549+
outVar = jsvNewObject();
550+
jsvObjectSetChildAndUnLock(outVar, "data", outMessageVar);
551+
jsvObjectSetChildAndUnLock(outVar, "tag", jsvNewArrayBufferWithData(tagLenVal, tag));
552+
}
553+
}
554+
} else {
555+
// decrypt and check tag
556+
JSV_GET_AS_CHAR_ARRAY(tagPtr, tagLen, tagArg);
557+
if (!tagPtr) {
558+
err = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
559+
}
560+
if (err == 0) {
561+
err = mbedtls_ccm_auth_decrypt(&ctx, messageLen, ivVal, ivLenVal, NULL, 0, (unsigned char*)messagePtr, (unsigned char*)outMessagePtr, (unsigned char*)tagPtr, tagLen);
562+
}
563+
}
564+
}
565+
mbedtls_ccm_free(&ctx);
566+
567+
if (err == 0) {
568+
return outVar;
569+
} else {
570+
jswrap_crypto_error(err);
571+
jsvUnLock(outVar);
572+
return NULL;
573+
}
574+
}
575+
576+
/*TYPESCRIPT
577+
type AES_CCM_EncryptResult = {
578+
data: ArrayBuffer,
579+
tag: ArrayBuffer,
580+
};
581+
*/
582+
583+
/*JSON{
584+
"type" : "staticmethod",
585+
"class" : "AES",
586+
"name" : "ccmEncrypt",
587+
"generate" : "jswrap_crypto_AES_ccmEncrypt",
588+
"params" : [
589+
["message","JsVar","Message to encrypt"],
590+
["key","JsVar","Key to encrypt message - must be an `ArrayBuffer` of 128, 192, or 256 BITS"],
591+
["iv","JsVar","nonce (initialization vector) - must be an `ArrayBuffer` of 2 to 13 bytes"],
592+
["tagLen","JsVar","Length of tag to generate in bytes - must be one of 4, 6, 8, 10, 12, 14 or 16"]
593+
],
594+
"return" : ["JsVar","An object"],
595+
"return_object" : "AES_CCM_EncryptResult",
596+
"ifdef" : "USE_AES_CCM"
597+
}
598+
*/
599+
JsVar *jswrap_crypto_AES_ccmEncrypt(JsVar *message, JsVar *key, JsVar *iv, JsVar *tagLen) {
600+
return jswrap_crypto_AES_ccmCrypt(message, key, iv, tagLen, true);
601+
}
602+
603+
/*JSON{
604+
"type" : "staticmethod",
605+
"class" : "AES",
606+
"name" : "ccmDecrypt",
607+
"generate" : "jswrap_crypto_AES_ccmDecrypt",
608+
"params" : [
609+
["message","JsVar","Message to decrypt"],
610+
["key","JsVar","Key to decrypt message - must be an `ArrayBuffer` of 128, 192, or 256 BITS"],
611+
["iv","JsVar","Nonce (initialization vector) - must be an `ArrayBuffer` of 2 to 13 bytes"],
612+
["tag","JsVar","Tag that came with the message - must be an `ArrayBuffer`"]
613+
],
614+
"return" : ["JsVar","Decrypted message, or null on error (for example if the tag doesn't match)"],
615+
"ifdef" : "USE_AES_CCM"
616+
}
617+
*/
618+
JsVar *jswrap_crypto_AES_ccmDecrypt(JsVar *message, JsVar *key, JsVar *iv, JsVar *tag) {
619+
return jswrap_crypto_AES_ccmCrypt(message, key, iv, tag, false);
620+
}
621+
#endif

libs/crypto/jswrap_crypto.h

+4
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ JsVar *jswrap_crypto_PBKDF2(JsVar *passphrase, JsVar *salt, JsVar *options);
2323
JsVar *jswrap_crypto_AES_encrypt(JsVar *message, JsVar *key, JsVar *options);
2424
JsVar *jswrap_crypto_AES_decrypt(JsVar *message, JsVar *key, JsVar *options);
2525
#endif
26+
#ifdef USE_AES_CCM
27+
JsVar *jswrap_crypto_AES_ccmEncrypt(JsVar *message, JsVar *key, JsVar *iv, JsVar *tagLen);
28+
JsVar *jswrap_crypto_AES_ccmDecrypt(JsVar *message, JsVar *key, JsVar *iv, JsVar *tag);
29+
#endif

libs/crypto/mbedtls/config.h

+9
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787

8888
#endif
8989

90+
#ifdef USE_AES
9091
/* common mbed TLS feature support */
9192
#define MBEDTLS_CIPHER_MODE_CBC
9293
#define MBEDTLS_CIPHER_MODE_CFB
@@ -98,6 +99,7 @@
9899
#define MBEDTLS_MD_C
99100
#define MBEDTLS_OID_C
100101
#define MBEDTLS_PKCS5_C
102+
#endif
101103
#ifndef USE_SHA1_JS
102104
#define MBEDTLS_SHA1_C
103105
#endif
@@ -107,6 +109,13 @@
107109
#ifdef USE_SHA512
108110
#define MBEDTLS_SHA512_C
109111
#endif
112+
#ifdef USE_AES_CCM
113+
#define MBEDTLS_CCM_C
114+
#ifndef USE_AES
115+
#define MBEDTLS_AES_C
116+
#define MBEDTLS_CIPHER_C
117+
#endif
118+
#endif
110119

111120
#include "jsvar.h"
112121

make/crypto/default.make

+11
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ libs/crypto/mbedtls/library/md_wrap.c \
5050
libs/crypto/mbedtls/library/oid.c \
5151
libs/crypto/mbedtls/library/pkcs5.c
5252
endif
53+
ifdef USE_AES_CCM
54+
DEFINES += -DUSE_AES_CCM
55+
SOURCES += \
56+
libs/crypto/mbedtls/library/ccm.c
57+
ifndef USE_AES
58+
SOURCES += \
59+
libs/crypto/mbedtls/library/aes.c \
60+
libs/crypto/mbedtls/library/cipher.c \
61+
libs/crypto/mbedtls/library/cipher_wrap.c
62+
endif
63+
endif

0 commit comments

Comments
 (0)