├── test ├── pytest.ini ├── requirements.txt ├── dev-requirements.txt ├── test_asn1.py ├── test_oscore.py ├── test_minisuo.py ├── conftest.py ├── test_hmac_data │ └── hmac_sm3.txt ├── test_sm4.py ├── test_sm3.py ├── test_ascon_hash.py ├── tf.py ├── test_hmac_ascon.py ├── test_ascon_aead.py ├── test_hmac_sm3.py ├── test_sm3.c ├── test_ascon_hash.c ├── test_hmac_sm3.c ├── test_hmac_ascon.c ├── test_sm4_api.c ├── test_sm3_data │ └── sm3.txt ├── test_ascon_aead.c ├── test.h └── ascon_gen_kat.c ├── .gitignore ├── include ├── internal │ ├── pool.h │ ├── sm3.h │ ├── meth.h │ ├── sm4.h │ ├── ascon.h │ ├── log.h │ ├── oscore_crypto.h │ └── asn1.h └── tongsuo │ ├── sm3.h │ ├── hmac.h │ ├── mem.h │ ├── sm4.h │ ├── minisuo.h │ ├── ascon.h │ ├── oscore.h │ ├── oscore_cbor.h │ ├── oscore_context.h │ └── oscore_cose.h ├── examples ├── sm3_oneshot.c ├── ascon_hash_oneshot.c ├── ascon_hash.c ├── sm3_demo.c ├── hmac_sm3.c ├── hmac_ascon.c ├── sm4_oneshot.c ├── ascon_aead_oneshot.c ├── sm4_cbc_enc.c └── ascon_aead_enc.c ├── doc └── build.md ├── src ├── version.c ├── log.c ├── error.c ├── meth.c ├── pool.c ├── mem.c ├── hmac.c ├── oscore_crypto.c └── asn1.c ├── README.cn.md ├── NOTICE ├── README.md ├── .github └── workflows │ ├── ci.yml │ └── compiler-zoo.yml ├── .clang-format ├── perf └── perf.c ├── CMakeLists.txt └── LICENSE /test/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] -------------------------------------------------------------------------------- /test/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pytest-subtests 3 | pytest-xdist -------------------------------------------------------------------------------- /test/dev-requirements.txt: -------------------------------------------------------------------------------- 1 | black 2 | pytest 3 | pytest-subtests 4 | pytest-xdist -------------------------------------------------------------------------------- /test/test_asn1.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | 8 | 9 | def test_asn1_api(): 10 | tf.ok("test_asn1") 11 | -------------------------------------------------------------------------------- /test/test_oscore.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | 8 | 9 | def test_oscore(): 10 | tf.ok("test_oscore") 11 | -------------------------------------------------------------------------------- /test/test_minisuo.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | 8 | 9 | def test_minisuo_version(): 10 | tf.ok("minisuo -v") 11 | tf.ok("minisuo --version") 12 | -------------------------------------------------------------------------------- /test/conftest.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import os 7 | import tempfile 8 | import pytest 9 | 10 | 11 | @pytest.fixture 12 | def setup_temp1(): 13 | _, tmp = tempfile.mkstemp(text=True) 14 | 15 | yield tmp 16 | 17 | os.remove(tmp) 18 | 19 | 20 | @pytest.fixture 21 | def setup_temp2(): 22 | _, tmp1 = tempfile.mkstemp(text=True) 23 | _, tmp2 = tempfile.mkstemp(text=True) 24 | 25 | yield tmp1, tmp2 26 | 27 | os.remove(tmp1) 28 | os.remove(tmp2) 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | 3 | __pycache__/ 4 | .venv/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # Prerequisites 9 | *.d 10 | 11 | # Object files 12 | *.o 13 | *.ko 14 | *.obj 15 | *.elf 16 | 17 | # Linker output 18 | *.ilk 19 | *.map 20 | *.exp 21 | 22 | # Precompiled Headers 23 | *.gch 24 | *.pch 25 | 26 | # Libraries 27 | *.lib 28 | *.a 29 | *.la 30 | *.lo 31 | 32 | # Shared objects (inc. Windows DLLs) 33 | *.dll 34 | *.so 35 | *.so.* 36 | *.dylib 37 | 38 | # Executables 39 | *.exe 40 | *.out 41 | *.app 42 | *.i*86 43 | *.x86_64 44 | *.hex 45 | 46 | # Debug files 47 | *.dSYM/ 48 | *.su 49 | *.idb 50 | *.pdb 51 | 52 | # Kernel Module Compile Results 53 | *.mod* 54 | *.cmd 55 | .tmp_versions/ 56 | modules.order 57 | Module.symvers 58 | Mkfile.old 59 | dkms.conf 60 | -------------------------------------------------------------------------------- /include/internal/pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_POOL_H) 11 | # define TSM_INTERNAL_POOL_H 12 | # pragma once 13 | 14 | # include 15 | 16 | typedef struct tsm_pool_s tsm_pool_t; 17 | 18 | tsm_pool_t *ngx_create_pool(size_t size); 19 | void tsm_destroy_pool(tsm_pool_t *pool); 20 | void *tsm_palloc(tsm_pool_t *pool, size_t size); 21 | void *tsm_pcalloc(tsm_pool_t *pool, size_t size); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/internal/sm3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_SM3_H) 11 | # define TSM_INTERNAL_SM3_H 12 | # pragma once 13 | 14 | # define TSM_SM3_CBLOCK 64 15 | # define TSM_SM3_LBLOCK 16 16 | 17 | # pragma pack(1) 18 | typedef struct tsm_sm3_ctx_s { 19 | unsigned int A, B, C, D, E, F, G, H; 20 | unsigned int Nl, Nh; 21 | unsigned int data[TSM_SM3_LBLOCK]; 22 | unsigned int num; 23 | } TSM_SM3_CTX; 24 | # pragma pack() 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /examples/sm3_oneshot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(void) 15 | { 16 | const char *data = "hello world"; 17 | unsigned char md[TSM_SM3_DIGEST_LEN]; 18 | 19 | if (tsm_sm3_oneshot((const unsigned char *)data, strlen(data), md) != TSM_OK) { 20 | return 1; 21 | } 22 | 23 | printf("SM3(%s)=", data); 24 | 25 | for (int i = 0; i < TSM_SM3_DIGEST_LEN; i++) { 26 | printf("%02x", md[i]); 27 | } 28 | 29 | printf("\n"); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /doc/build.md: -------------------------------------------------------------------------------- 1 | ## Build 2 | 3 | The build depends on cmake, make and C compiler (gcc or clang). 4 | Build tongsuo-mini from the source code as follows: 5 | 6 | ```bash 7 | # Download source code 8 | git clone https://github.com/Tongsuo-Project/tongsuo-mini 9 | cd tongsuo-mini 10 | 11 | mkdir build 12 | cd build 13 | 14 | # Compile all modules with -DWITH_ALL=ON, compile specific module with -DWITH_=ON, e.g. -DWITH_ASCON=ON 15 | cmake -DWITH_ALL=ON .. 16 | make -j 17 | 18 | # If you need to install 19 | make install 20 | ``` 21 | 22 | ## Test 23 | 24 | To test with Python3, create a virtual environment in the test directory and install the dependencies: 25 | 26 | ```bash 27 | cd test 28 | python3 -m venv .venv 29 | source .venv/bin/activate 30 | pip3 install -r test/requirements.txt 31 | ``` 32 | 33 | Then run the command in the build directory: 34 | 35 | ```bash 36 | ctest 37 | ``` 38 | 39 | Or run the command in the test directory: 40 | 41 | ```bash 42 | pytest . 43 | ``` 44 | -------------------------------------------------------------------------------- /include/internal/meth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_METH_H) 11 | # define TSM_INTERNAL_METH_H 12 | # pragma once 13 | 14 | # include 15 | # include 16 | 17 | typedef struct { 18 | const char *name; 19 | uint8_t alg; 20 | uint8_t hashsize; 21 | uint8_t blocksize; 22 | void *(*newctx)(void); 23 | void (*freectx)(void *ctx); 24 | int (*init)(void *ctx); 25 | int (*update)(void *ctx, const unsigned char *data, size_t len); 26 | int (*final)(void *ctx, unsigned char *out, size_t *outl); 27 | } TSM_HASH_METH; 28 | 29 | void *tsm_get_hash_meth(int alg); 30 | #endif 31 | -------------------------------------------------------------------------------- /test/test_hmac_data/hmac_sm3.txt: -------------------------------------------------------------------------------- 1 | #HMAC-SM3 from GM/T 0042-2015 Appendix D.3 2 | 3 | Count = 1 4 | Input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 5 | Key = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 6 | Output = ca05e144ed05d1857840d1f318a4a8669e559fc8391f414485bfdf7bb408963a 7 | 8 | Count = 2 9 | Input = cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd 10 | Key = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425 11 | Output = 220bf579ded555393f0159f66c99877822a3ecf610d1552154b41d44b94db3ae 12 | 13 | Count = 3 14 | Input = "Hi There" 15 | Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 16 | Output = c0ba18c68b90c88bc07de794bfc7d2c8d19ec31ed8773bc2b390c9604e0be11e 17 | 18 | Count = 4 19 | Input = "what do ya want for nothing?" 20 | Key = "Jefe" 21 | Output = 2e87f1d16862e6d964b50a5200bf2b10b764faa9680a296a2405f24bec39f882 22 | -------------------------------------------------------------------------------- /examples/ascon_hash_oneshot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(void) 15 | { 16 | const char *data = "hello world"; 17 | unsigned char md[TSM_ASCON_HASH_LEN]; 18 | size_t outl; 19 | 20 | if (tsm_ascon_hash_oneshot(TSM_HASH_ASCON_HASH, (const unsigned char *)data, strlen(data), md, 21 | &outl) 22 | != TSM_OK) { 23 | return 1; 24 | } 25 | 26 | printf("ASCON_HASH(%s)=", data); 27 | 28 | for (size_t i = 0; i < outl; i++) { 29 | printf("%02x", md[i]); 30 | } 31 | 32 | printf("\n"); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/test_sm4.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import binascii 8 | 9 | 10 | def test_sm4_api(): 11 | tf.ok("test_sm4_api") 12 | 13 | 14 | def test_minisuo_sm4_cbc(setup_temp2): 15 | infile, outfile = setup_temp2 16 | key = "0123456789ABCDEFFEDCBA9876543210" 17 | iv = "0123456789ABCDEFFEDCBA9876543210" 18 | plaintext = "0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210" 19 | ciphertext = "2677F46B09C122CC975533105BD4A22AF6125F7275CE552C3A2BBCF533DE8A3B" 20 | 21 | tf.writef(infile, binascii.unhexlify(plaintext)) 22 | 23 | tf.ok( 24 | "minisuo sm4 -enc -mode cbc -key {key} -iv {iv} -in {infile} -out {outfile} -nopad".format( 25 | key=key, iv=iv, infile=infile, outfile=outfile 26 | ) 27 | ) 28 | 29 | res = tf.readf(outfile) 30 | assert res == binascii.unhexlify(ciphertext) 31 | -------------------------------------------------------------------------------- /include/internal/sm4.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_SM4_H) 11 | # define TSM_INTERNAL_SM4_H 12 | # pragma once 13 | 14 | # include 15 | # include 16 | 17 | # define SM4_KEY_SCHEDULE 32 18 | 19 | # pragma pack(1) 20 | typedef struct tsm_sm4_ctx_s { 21 | uint32_t rk[SM4_KEY_SCHEDULE]; 22 | unsigned char mode; 23 | unsigned char flags; 24 | unsigned char block_size; 25 | unsigned char iv_len; 26 | unsigned char iv[TSM_MAX_IV_LENGTH]; 27 | int buf_len; /* number we have left */ 28 | unsigned char buf[TSM_MAX_BLOCK_LENGTH]; /* saved partial block */ 29 | int final_used; 30 | unsigned char final[TSM_MAX_BLOCK_LENGTH]; /* possible final block */ 31 | } TSM_SM4_CTX; 32 | # pragma pack() 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /* Tongsuo Mini xxx.yyy.zzz-pre255 */ 15 | static char version[32]; 16 | 17 | const char *tsm_version_text(void) 18 | { 19 | char *p = version; 20 | char *end = version + sizeof(version); 21 | char tag[8]; 22 | 23 | switch (TSM_VERSION_TAG & 0xff) { 24 | case 0: 25 | strcpy(tag, "-dev"); 26 | break; 27 | case 0xff: 28 | tag[0] = '\0'; 29 | break; 30 | default: 31 | snprintf(tag, sizeof(tag), "-pre%u", TSM_VERSION_TAG & 0xff); 32 | break; 33 | } 34 | 35 | p += snprintf(p, end - p, "Tongsuo Mini %d.%d.%d%s", TSM_VERSION_MAJOR, TSM_VERSION_MINOR, 36 | TSM_VERSION_PATCH, tag); 37 | 38 | return version; 39 | } 40 | -------------------------------------------------------------------------------- /test/test_sm3.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import pytest 8 | 9 | 10 | @pytest.mark.parametrize( 11 | "kat_file", 12 | [ 13 | "test_sm3_data/sm3.txt", 14 | ], 15 | ) 16 | def test_sm3(kat_file, subtests): 17 | with open(kat_file) as f: 18 | tb = {} 19 | 20 | for line in f: 21 | if line.startswith("#"): 22 | continue 23 | line = line.strip() 24 | if not line: 25 | continue 26 | 27 | name, value = line.partition("=")[::2] 28 | tb[name.strip()] = value.strip() 29 | 30 | if "Count" in tb and "Input" in tb and "Output" in tb: 31 | with subtests.test(i=tb["Count"]): 32 | tf.ok( 33 | "test_sm3 -input {} -output {}".format( 34 | tb["Input"], tb["Output"] 35 | ) 36 | ) 37 | 38 | tb.clear() 39 | -------------------------------------------------------------------------------- /README.cn.md: -------------------------------------------------------------------------------- 1 | 语言: 简体中文 | [English](README.md) 2 | 3 | # 铜锁迷你版 4 | 5 | 铜锁迷你版(tongsuo-mini),中文名称“迷你锁”,是一个轻量级的密码学算法库,专为嵌入式系统和物联网设备等资源受限场景提供常用的密码学算法和安全传输协议,并可以适应超低内存和存储的极限要求。“迷你锁”通过高度模块化,允许用户在编译时只开启需要的功能,不浪费存储空间。 6 | 同时,通过紧凑的内存对齐等方式,压缩运行时内存。 7 | 8 | ## 特性 9 | 10 | 迷你锁(tongsuo-mini)提供如下特性: 11 | 12 | * 高度可定制的模块化编译 13 | * 轻量级密码学算法 14 | * ASCON AEAD 15 | * ASCON HASH 16 | * 轻量级安全通信协议 17 | * OSCORE 18 | * EDHOC\* 19 | * 基于可预测逻辑的动态二进制加载能力\* 20 | * 传统密码学算法 21 | * 商用密码算法:SM2\*,SM3,SM4 22 | * 国际密码学算法\*:AES,SHA系列,RSA,ECDSA,EdDSA 23 | * 传统安全通信协议 24 | * TLS协议\* 25 | * TLCP协议\* 26 | 27 | 注:\*号表示待开发 28 | 29 | ## 构建 30 | 31 | 构建依赖cmake,make和C编译器(gcc或者clang),基于源代码构建迷你锁如下: 32 | 33 | ```bash 34 | # 下载源代码 35 | git clone https://github.com/Tongsuo-Project/tongsuo-mini 36 | cd tongsuo-mini 37 | 38 | mkdir build 39 | cd build 40 | 41 | # 编译所有模块使用-DWITH_ALL=ON, 编译指定模块-DWITH_=ON,例如-DWITH_ASCON=ON 42 | # 查看所有可用的编译选项, cmake -LH .. 43 | cmake -DWITH_ALL=ON .. 44 | make -j 45 | 46 | # 安装 47 | make install 48 | ``` 49 | 50 | ## 测试 51 | 52 | 测试使用Python3,在test目录下创建虚拟环境并安装依赖: 53 | 54 | ```bash 55 | cd test 56 | python3 -m venv .venv 57 | source .venv/bin/activate 58 | pip3 install -r requirements.txt 59 | ``` 60 | 61 | 然后在build目录下执行: 62 | ```bash 63 | ctest 64 | ``` 65 | 或者在test目录下执行: 66 | ```bash 67 | pytest . 68 | ``` 69 | -------------------------------------------------------------------------------- /examples/ascon_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | void *ctx = NULL; 18 | const char *data = "hello world"; 19 | unsigned char md[TSM_ASCON_HASH_LEN]; 20 | size_t outl; 21 | 22 | ctx = tsm_ascon_hash_ctx_new(); 23 | if (ctx == NULL) { 24 | return 1; 25 | } 26 | 27 | if (tsm_ascon_hash_init(ctx) != TSM_OK 28 | || tsm_ascon_hash_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK 29 | || tsm_ascon_hash_final(ctx, md, &outl) != TSM_OK) { 30 | tsm_ascon_hash_ctx_free(ctx); 31 | return 1; 32 | } 33 | 34 | tsm_ascon_hash_ctx_free(ctx); 35 | 36 | printf("ASCON_HASH(%s)=", data); 37 | 38 | for (size_t i = 0; i < outl; i++) { 39 | printf("%02x", md[i]); 40 | } 41 | 42 | printf("\n"); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test/test_ascon_hash.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import pytest 8 | 9 | 10 | @pytest.mark.parametrize( 11 | "scheme, kat_file", 12 | [ 13 | ("hash", "test_ascon_data/ascon_hash.txt"), 14 | ("hasha", "test_ascon_data/ascon_hasha.txt"), 15 | ], 16 | ) 17 | def test_ascon_hash(scheme, kat_file, subtests): 18 | with open(kat_file) as f: 19 | tb = {} 20 | 21 | for line in f: 22 | if line.startswith("#"): 23 | continue 24 | line = line.strip() 25 | if not line: 26 | continue 27 | 28 | name, value = line.partition("=")[::2] 29 | tb[name.strip()] = value.strip() 30 | 31 | if "Count" in tb and "Msg" in tb and "MD" in tb: 32 | with subtests.test(i=tb["Count"]): 33 | tf.ok( 34 | "test_ascon_hash -scheme {} -msg {} -md {}".format( 35 | scheme, tb["Msg"], tb["MD"] 36 | ) 37 | ) 38 | tb.clear() 39 | -------------------------------------------------------------------------------- /test/tf.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import os 7 | import sys 8 | import subprocess 9 | 10 | current_dir = os.path.split(os.path.realpath(__file__))[0] 11 | 12 | 13 | def ok(cmd, input=None): 14 | """ 15 | input should be bytes or None 16 | """ 17 | print("$ " + cmd) 18 | 19 | child = subprocess.Popen( 20 | cmd, 21 | stdout=subprocess.PIPE, 22 | stdin=subprocess.PIPE, 23 | shell=True, 24 | env=dict(PATH=os.path.join(os.path.dirname(current_dir), "build")), 25 | ) 26 | 27 | if input is not None: 28 | print(">") 29 | sys.stdout.buffer.write(input) 30 | 31 | output = child.communicate(input)[0] 32 | else: 33 | output = child.communicate()[0] 34 | 35 | child.stdin.close() 36 | 37 | assert child.returncode == 0 38 | 39 | print(output.decode("utf-8")) 40 | return output 41 | 42 | 43 | def writef(file, data): 44 | with open(file, "wb") as f: 45 | return f.write(data) 46 | 47 | 48 | def readf(file): 49 | with open(file, "rb") as f: 50 | return f.read() 51 | -------------------------------------------------------------------------------- /examples/sm3_demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(void) 15 | { 16 | void *ctx = NULL; 17 | const char *data1 = "hello "; 18 | const char *data2 = "world"; 19 | unsigned char md[TSM_SM3_DIGEST_LEN]; 20 | 21 | ctx = tsm_sm3_ctx_new(); 22 | if (ctx == NULL) { 23 | return 1; 24 | } 25 | 26 | if (tsm_sm3_init(ctx) != TSM_OK 27 | || tsm_sm3_update(ctx, (const unsigned char *)data1, strlen(data1)) != TSM_OK 28 | || tsm_sm3_update(ctx, (const unsigned char *)data2, strlen(data2)) != TSM_OK 29 | || tsm_sm3_final(ctx, md, NULL) != TSM_OK) { 30 | tsm_sm3_ctx_free(ctx); 31 | return 1; 32 | } 33 | 34 | tsm_sm3_ctx_free(ctx); 35 | 36 | printf("SM3(%s%s)=", data1, data2); 37 | 38 | for (int i = 0; i < TSM_SM3_DIGEST_LEN; i++) { 39 | printf("%02x", md[i]); 40 | } 41 | 42 | printf("\n"); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test/test_hmac_ascon.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import pytest 8 | 9 | 10 | @pytest.mark.parametrize( 11 | "algo, kat_file", 12 | [ 13 | ("ascon-hmac", "test_hmac_data/ascon_hmac.txt"), 14 | ("ascon-hmaca", "test_hmac_data/ascon_hmaca.txt"), 15 | ], 16 | ) 17 | def test_hmac_ascon(algo, kat_file, subtests): 18 | with open(kat_file) as f: 19 | tb = {} 20 | 21 | for line in f: 22 | if line.startswith("#"): 23 | continue 24 | line = line.strip() 25 | if not line: 26 | continue 27 | 28 | name, value = line.partition("=")[::2] 29 | tb[name.strip()] = value.strip() 30 | 31 | if "Count" in tb and "Msg" in tb and "Key" in tb and "Tag" in tb: 32 | with subtests.test(i=tb["Count"]): 33 | tf.ok( 34 | "test_hmac_ascon -algo {} -key {} -msg {} -tag {}".format( 35 | algo, tb["Key"], tb["Msg"], tb["Tag"] 36 | ) 37 | ) 38 | tb.clear() 39 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "internal/log.h" 14 | 15 | #define TSM_MAX_LOG_STRLEN 2048 16 | 17 | static int default_log_level = TSM_LOG_ERROR; 18 | 19 | const char *log_level[] = { 20 | "DEBUG", 21 | "INFO", 22 | "WARN", 23 | "ERROR", 24 | }; 25 | 26 | void tsm_log_impl(const char *file, int line, int level, const char *fmt, ...) 27 | { 28 | char *p, *end; 29 | va_list args; 30 | char msg[TSM_MAX_LOG_STRLEN]; 31 | 32 | if (level < default_log_level) 33 | return; 34 | 35 | p = msg; 36 | end = p + sizeof(msg) - 1; 37 | 38 | if (file != NULL) { 39 | p += snprintf(p, end - p, "[%s]|[%s:%d]|", log_level[level], file, line); 40 | if (p > end) 41 | return; 42 | } 43 | 44 | va_start(args, fmt); 45 | p += vsnprintf(p, end - p, fmt, args); 46 | va_end(args); 47 | 48 | if (p > end) { 49 | memcpy(end - 5, "[...]", 5); 50 | p = end; 51 | } 52 | 53 | *p++ = '\n'; 54 | 55 | fprintf(stderr, "%.*s", (int)(p - msg), msg); 56 | } 57 | -------------------------------------------------------------------------------- /include/internal/ascon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_ASCON_H) 11 | # define TSM_INTERNAL_ASCON_H 12 | # pragma once 13 | 14 | # include 15 | # include 16 | # include 17 | 18 | # define ASCON_PHASE_INIT 1 19 | # define ASCON_PHASE_AD 2 20 | # define ASCON_PHASE_TEXT 3 21 | # define ASCON_PHASE_FINAL 4 22 | 23 | # pragma pack(1) 24 | typedef struct tsm_ascon_state_st { 25 | uint64_t x[5]; 26 | } TSM_ASCON_STATE; 27 | 28 | typedef struct tsm_ascon_aead_ctx_st { 29 | TSM_ASCON_STATE s; 30 | uint64_t K[2]; 31 | uint64_t N[2]; 32 | uint8_t mode; 33 | uint8_t flags; 34 | uint8_t block_size; 35 | uint8_t a; 36 | uint8_t b; 37 | uint8_t phase; 38 | uint8_t buf_len; 39 | unsigned char buf[16]; /* saved partial block */ 40 | unsigned char tag[TSM_ASCON_AEAD_TAG_LEN]; 41 | } TSM_ASCON_AEAD_CTX; 42 | 43 | typedef struct tsm_ascon_hash_ctx_st { 44 | TSM_ASCON_STATE s; 45 | uint8_t alg; 46 | uint8_t buf_len; 47 | unsigned char buf[8]; /* saved partial block */ 48 | } TSM_ASCON_HASH_CTX; 49 | # pragma pack() 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /examples/hmac_sm3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | int main(void) 18 | { 19 | int ret = 1; 20 | void *ctx = NULL; 21 | const char *data = "hello world"; 22 | unsigned char *key = 23 | tsm_hex2buf("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); 24 | unsigned char hmac[TSM_ASCON_HMAC_LEN]; 25 | size_t outl; 26 | 27 | if (key == NULL) 28 | goto err; 29 | 30 | ctx = tsm_hmac_ctx_new(); 31 | if (ctx == NULL) { 32 | goto err; 33 | } 34 | 35 | if (tsm_hmac_init(ctx, key, 32, TSM_HASH_ASCON_HASH) != TSM_OK 36 | || tsm_hmac_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK 37 | || tsm_hmac_final(ctx, hmac, &outl) != TSM_OK) { 38 | goto err; 39 | } 40 | 41 | printf("HMAC_ASCON(%s)=", data); 42 | 43 | for (size_t i = 0; i < outl; i++) { 44 | printf("%02x", hmac[i]); 45 | } 46 | 47 | printf("\n"); 48 | 49 | ret = 0; 50 | err: 51 | tsm_free(key); 52 | tsm_hmac_ctx_free(ctx); 53 | return ret; 54 | } 55 | -------------------------------------------------------------------------------- /examples/hmac_ascon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | int main(void) 18 | { 19 | int ret = 1; 20 | void *ctx = NULL; 21 | const char *data = "hello world"; 22 | unsigned char *key = 23 | tsm_hex2buf("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); 24 | unsigned char hmac[TSM_ASCON_HMAC_LEN]; 25 | size_t outl; 26 | 27 | if (key == NULL) 28 | goto err; 29 | 30 | ctx = tsm_hmac_ctx_new(); 31 | if (ctx == NULL) { 32 | goto err; 33 | } 34 | 35 | if (tsm_hmac_init(ctx, key, 32, TSM_HASH_ASCON_HASH) != TSM_OK 36 | || tsm_hmac_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK 37 | || tsm_hmac_final(ctx, hmac, &outl) != TSM_OK) { 38 | goto err; 39 | } 40 | 41 | printf("HMAC_ASCON(%s)=", data); 42 | 43 | for (size_t i = 0; i < outl; i++) { 44 | printf("%02x", hmac[i]); 45 | } 46 | 47 | printf("\n"); 48 | 49 | ret = 0; 50 | err: 51 | tsm_free(key); 52 | tsm_hmac_ctx_free(ctx); 53 | return ret; 54 | } 55 | -------------------------------------------------------------------------------- /test/test_ascon_aead.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import pytest 8 | 9 | 10 | @pytest.mark.parametrize( 11 | "scheme, kat_file", 12 | [ 13 | ("ascon128", "test_ascon_data/ascon_aead128.txt"), 14 | ("ascon128a", "test_ascon_data/ascon_aead128a.txt"), 15 | ], 16 | ) 17 | def test_ascon_aead(scheme, kat_file, subtests): 18 | with open(kat_file) as f: 19 | tb = {} 20 | 21 | for line in f: 22 | if line.startswith("#"): 23 | continue 24 | line = line.strip() 25 | if not line: 26 | continue 27 | 28 | name, value = line.partition("=")[::2] 29 | tb[name.strip()] = value.strip() 30 | 31 | if ( 32 | "Count" in tb 33 | and "Key" in tb 34 | and "Nonce" in tb 35 | and "AD" in tb 36 | and "PT" in tb 37 | and "CT" in tb 38 | ): 39 | with subtests.test(i=tb["Count"]): 40 | tf.ok( 41 | "test_ascon_aead -scheme {} -key {} -nonce {} -ad {} -pt {} -ct {}".format( 42 | scheme, tb["Key"], tb["Nonce"], tb["AD"], tb["PT"], tb["CT"] 43 | ) 44 | ) 45 | tb.clear() 46 | -------------------------------------------------------------------------------- /include/internal/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_LOG_H) 11 | # define TSM_INTERNAL_LOG_H 12 | # pragma once 13 | 14 | # include 15 | # include 16 | 17 | enum { 18 | TSM_LOG_DEBUG = 0, 19 | TSM_LOG_INFO, 20 | TSM_LOG_WARN, 21 | TSM_LOG_ERROR, 22 | }; 23 | # ifdef TSM_LOG 24 | void tsm_log_impl(const char *file, int line, int level, const char *fmt, ...); 25 | # else 26 | static inline void tsm_log_impl(const char *file, int line, int level, const char *fmt, ...) 27 | { 28 | (void)file; 29 | (void)line; 30 | (void)level; 31 | (void)fmt; 32 | } 33 | # endif 34 | 35 | # define tsm_log(level, ...) tsm_log_impl(NULL, 0, level, __VA_ARGS__) 36 | # define LOGD(...) tsm_log_impl(__FILE__, __LINE__, TSM_LOG_DEBUG, __VA_ARGS__) 37 | # define LOGI(...) tsm_log_impl(__FILE__, __LINE__, TSM_LOG_INFO, __VA_ARGS__) 38 | # define LOGW(...) tsm_log_impl(NULL, 0, TSM_LOG_WARN, __VA_ARGS__) 39 | # define LOGE(...) tsm_log_impl(NULL, 0, TSM_LOG_ERROR, __VA_ARGS__) 40 | # define LOGERR(e) tsm_log_impl(NULL, 0, TSM_LOG_ERROR, "%s", tsm_err2str(e)) 41 | # define eLOG(e) tsm_log_impl(NULL, 0, TSM_LOG_ERROR, "%s", tsm_err2str(e)), e 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /examples/sm4_oneshot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | int ret = 1; 18 | const char *plaintext = "hello world"; 19 | unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 20 | unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 21 | unsigned char ciphertext[1024]; 22 | size_t outl; 23 | 24 | if (key == NULL || iv == NULL) { 25 | goto err; 26 | } 27 | 28 | if (tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, 29 | key, 30 | iv, 31 | (const unsigned char *)plaintext, 32 | strlen(plaintext), 33 | ciphertext, 34 | &outl, 35 | TSM_CIPH_FLAG_ENCRYPT) 36 | != TSM_OK) { 37 | goto err; 38 | } 39 | 40 | printf("SM4_CBC_Encrypt(%s)=", plaintext); 41 | 42 | for (size_t i = 0; i < outl; i++) { 43 | printf("%02x", ciphertext[i]); 44 | } 45 | 46 | printf("\n"); 47 | 48 | ret = 0; 49 | err: 50 | tsm_free(key); 51 | tsm_free(iv); 52 | return ret; 53 | } 54 | -------------------------------------------------------------------------------- /test/test_hmac_sm3.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License 2.0 (the "License"). You may not use 2 | # this file except in compliance with the License. You can obtain a copy 3 | # in the file LICENSE in the source distribution or at 4 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 5 | 6 | import tf 7 | import pytest 8 | import binascii 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "kat_file", 13 | [ 14 | "test_hmac_data/hmac_sm3.txt", 15 | ], 16 | ) 17 | def test_hmac_sm3(kat_file, subtests): 18 | with open(kat_file) as f: 19 | tb = {} 20 | 21 | for line in f: 22 | if line.startswith("#"): 23 | continue 24 | line = line.strip() 25 | if not line: 26 | continue 27 | 28 | name, value = line.partition("=")[::2] 29 | tb[name.strip()] = value.strip() 30 | 31 | if "Count" in tb and "Input" in tb and "Key" in tb and "Output" in tb: 32 | if tb["Input"][0] == '"': 33 | tb["Input"] = binascii.hexlify( 34 | tb["Input"].strip('"').encode() 35 | ).decode() 36 | 37 | if tb["Key"][0] == '"': 38 | tb["Key"] = binascii.hexlify(tb["Key"].strip('"').encode()).decode() 39 | 40 | with subtests.test(i=tb["Count"]): 41 | tf.ok( 42 | "test_hmac_sm3 -key {} -msg {} -tag {}".format( 43 | tb["Key"], tb["Input"], tb["Output"] 44 | ) 45 | ) 46 | 47 | tb.clear() 48 | -------------------------------------------------------------------------------- /test/test_sm3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include "test.h" 12 | #include 13 | #include 14 | #include 15 | 16 | int test_sm3_hash(const char *hex_input, const char *hex_output) 17 | { 18 | unsigned char *input = tsm_hex2buf(hex_input); 19 | unsigned char *output = tsm_hex2buf(hex_output); 20 | unsigned char md[TSM_SM3_DIGEST_LEN]; 21 | 22 | ASSERT_OK(tsm_sm3_oneshot(input, strlen(hex_input) / 2, md)); 23 | ASSERT(memcmp(md, output, TSM_SM3_DIGEST_LEN) == 0); 24 | 25 | tsm_free(input); 26 | tsm_free(output); 27 | 28 | return TSM_OK; 29 | } 30 | 31 | int main(int argc, char **argv) 32 | { 33 | int i; 34 | const char *input = NULL; 35 | const char *output = NULL; 36 | 37 | for (i = 1; i < argc; i++) { 38 | if (argv[i][0] == '-') { 39 | if (i + 1 >= argc) 40 | break; 41 | 42 | if (argv[i + 1][0] == '-') 43 | continue; 44 | 45 | if (strcmp(argv[i], "-input") == 0) 46 | input = argv[++i]; 47 | else if (strcmp(argv[i], "-output") == 0) 48 | output = argv[++i]; 49 | else 50 | return 1; 51 | } 52 | } 53 | 54 | TEST_EX(test_sm3_hash, input, output); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /examples/ascon_aead_oneshot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | int ret = 1; 19 | const char *plaintext = "hello world"; 20 | const char *ad = "0123456789abcdef"; 21 | unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 22 | unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 23 | unsigned char out[1024]; 24 | size_t outl; 25 | 26 | if (key == NULL || iv == NULL) { 27 | goto err; 28 | } 29 | 30 | if (tsm_ascon_aead_oneshot(TSM_ASCON_AEAD_128, 31 | key, 32 | iv, 33 | (const unsigned char *)ad, 34 | strlen(ad), 35 | (const unsigned char *)plaintext, 36 | strlen(plaintext), 37 | out, 38 | &outl, 39 | TSM_CIPH_FLAG_ENCRYPT) 40 | != TSM_OK) { 41 | goto err; 42 | } 43 | 44 | printf("ASCON_AEAD_Encrypt(%s)=", plaintext); 45 | 46 | for (size_t i = 0; i < outl; i++) { 47 | printf("%02x", out[i]); 48 | } 49 | 50 | printf("\n"); 51 | 52 | ret = 0; 53 | err: 54 | tsm_free(key); 55 | tsm_free(iv); 56 | return ret; 57 | } 58 | -------------------------------------------------------------------------------- /examples/sm4_cbc_enc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | int ret = 1; 18 | void *ctx = NULL; 19 | const char *plaintext = "hello world"; 20 | unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 21 | unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 22 | unsigned char ciphertext[1024]; 23 | size_t outl, tmplen; 24 | 25 | if (key == NULL || iv == NULL) { 26 | goto err; 27 | } 28 | 29 | ctx = tsm_sm4_ctx_new(); 30 | if (ctx == NULL) { 31 | goto err; 32 | } 33 | 34 | if (tsm_sm4_init(ctx, TSM_CIPH_MODE_CBC, key, iv, TSM_CIPH_FLAG_ENCRYPT) != TSM_OK 35 | || tsm_sm4_update(ctx, 36 | (const unsigned char *)plaintext, 37 | strlen(plaintext), 38 | ciphertext, 39 | &outl) 40 | != TSM_OK 41 | || tsm_sm4_final(ctx, ciphertext + outl, &tmplen) != TSM_OK) { 42 | goto err; 43 | } 44 | outl += tmplen; 45 | 46 | printf("SM4_CBC_Encrypt(%s)=", plaintext); 47 | 48 | for (size_t i = 0; i < outl; i++) { 49 | printf("%02x", ciphertext[i]); 50 | } 51 | 52 | printf("\n"); 53 | 54 | ret = 0; 55 | err: 56 | tsm_sm4_ctx_free(ctx); 57 | tsm_free(key); 58 | tsm_free(iv); 59 | return ret; 60 | } 61 | -------------------------------------------------------------------------------- /include/tongsuo/sm3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_SM3_H) 11 | # define TSM_SM3_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | 20 | # define TSM_SM3_DIGEST_LEN 32 21 | 22 | /* Create a new context of sm3. The context should be freed by calling tsm_sm3_ctx_free() after use. 23 | */ 24 | void *tsm_sm3_ctx_new(void); 25 | /* Frees up the context of sm3. */ 26 | void tsm_sm3_ctx_free(void *ctx); 27 | /* Initialize the sm3 context. Returns TSM_OK on success, error code on failure. */ 28 | int tsm_sm3_init(void *ctx); 29 | /* Updates the sm3 context with the given data in and data length len. Returns TSM_OK on success, 30 | * error code on failure. */ 31 | int tsm_sm3_update(void *ctx, const unsigned char *data, size_t len); 32 | /* Finalizes the sm3 context and writes the result to md. The buffer md must hold TSM_SM3_DIGEST_LEN 33 | * bytes. The length of md is written to mdlen if mdlen is not NULL. Returns TSM_OK on success, 34 | * error code on failure. */ 35 | int tsm_sm3_final(void *ctx, unsigned char *md, size_t *mdlen); 36 | /* Perform SM3 transformation with the given data data and data length num. */ 37 | void tsm_sm3_transform(void *ctx, const unsigned char *data, size_t num); 38 | /* Computes the SM3 hash of the given data data and data length len. The result is written to md. 39 | * The buffer md must hold TSM_SM3_DIGEST_LEN bytes. Returns TSM_OK on success, error code on 40 | * failure. */ 41 | int tsm_sm3_oneshot(const unsigned char *data, size_t len, unsigned char *md); 42 | 43 | # ifdef __cplusplus 44 | } 45 | # endif 46 | #endif 47 | -------------------------------------------------------------------------------- /test/test_ascon_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "test.h" 15 | 16 | static char *schemestr; 17 | static char *hex_msg; 18 | static char *hex_md; 19 | 20 | int test_ascon_hash(void) 21 | { 22 | unsigned char *msg = tsm_hex2buf(hex_msg); 23 | unsigned char *md = tsm_hex2buf(hex_md); 24 | unsigned char buf[TSM_ASCON_HASH_LEN]; 25 | int scheme; 26 | size_t outlen; 27 | 28 | if (strcmp(schemestr, "hash") == 0) 29 | scheme = TSM_HASH_ASCON_HASH; 30 | else 31 | scheme = TSM_HASH_ASCON_HASHA; 32 | 33 | ASSERT_OK( 34 | tsm_ascon_hash_oneshot(scheme, msg, msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); 35 | 36 | ASSERT(outlen == TSM_ASCON_HASH_LEN); 37 | ASSERT(memcmp(buf, md, outlen) == 0); 38 | 39 | if (msg) 40 | tsm_free(msg); 41 | if (md) 42 | tsm_free(md); 43 | 44 | return 0; 45 | } 46 | 47 | int main(int argc, char **argv) 48 | { 49 | int i; 50 | 51 | for (i = 1; i < argc; i++) { 52 | if (argv[i][0] == '-') { 53 | if (i + 1 >= argc) 54 | break; 55 | 56 | if (argv[i + 1][0] == '-') 57 | continue; 58 | 59 | if (strcmp(argv[i], "-msg") == 0) 60 | hex_msg = argv[++i]; 61 | else if (strcmp(argv[i], "-md") == 0) 62 | hex_md = argv[++i]; 63 | else if (strcmp(argv[i], "-scheme") == 0) 64 | schemestr = argv[++i]; 65 | } 66 | } 67 | 68 | TEST(test_ascon_hash); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /include/tongsuo/hmac.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_HMAC_H) 11 | # define TSM_HMAC_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | 20 | /* Create a new context of HMAC. Should be freed by calling tsm_hmac_ctx_free() after use. */ 21 | void *tsm_hmac_ctx_new(void); 22 | /* Frees up the context ctx of HMAC. */ 23 | void tsm_hmac_ctx_free(void *ctx); 24 | /* Initialize the HMAC context with the given key and key length. The hash_alg sets the used hash 25 | * algorith. 26 | * Returns TSM_OK on success, error code on failure. */ 27 | int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, int hash_alg); 28 | /* Updates the HMAC context with the given data in and data length inlen. Returns TSM_OK for success 29 | * and others for failure. */ 30 | int tsm_hmac_update(void *ctx, const unsigned char *in, size_t inlen); 31 | /* Finalizes the HMAC context and writes the result to out. The length of the result is written to 32 | * outlen. Returns TSM_OK for success and others for failure. */ 33 | int tsm_hmac_final(void *ctx, unsigned char *out, size_t *outlen); 34 | /* Computes the HMAC of the given data in and data length inlen with the given key and key length 35 | * keylen. The result is written to out. The length of the result is written to outl. The hash_alg 36 | * sets the used hash algorithm, maybe TSM_HASH_SM3, TSM_HASH_ASCON_HASH or others. Returns 37 | * TSM_OK for success and others for failure. */ 38 | int tsm_hmac_oneshot(int hash_alg, const unsigned char *key, size_t keylen, const unsigned char *in, 39 | size_t inlen, unsigned char *out, size_t *outl); 40 | 41 | # ifdef __cplusplus 42 | } 43 | # endif 44 | #endif 45 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This product includes the OSCORE related code from libcoap 2 | (https://libcoap.net). The original author(s) and the original license of the 3 | OSCORE code are as follows: 4 | 5 | Martin Gunnarsson 6 | adapted to libcoap and major rewrite 7 | Peter van der Stok 8 | on request of Fairhair alliance 9 | adapted for libcoap integration 10 | Jon Shallow 11 | 12 | Copyright (c) 2018, SICS, RISE AB 13 | All rights reserved. 14 | 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions 17 | are met: 18 | 1. Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 2. Redistributions in binary form must reproduce the above copyright 21 | notice, this list of conditions and the following disclaimer in the 22 | documentation and/or other materials provided with the distribution. 23 | 3. Neither the name of the Institute nor the names of its contributors 24 | may be used to endorse or promote products derived from this software 25 | without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 31 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 | SUCH DAMAGE. 38 | 39 | ======================================================================== -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Language: English | [简体中文](README.cn.md) 2 | 3 | # Tongsuo-mini 4 | 5 | This project, tongsuo-mini (stands for 'mini copper lock' in Chinese, or 'minisuo' for its Chinese pronunciation), is a lightweight cryptography library that provides cryptographic primitives and secure network protocol for embbeded systems and IoT devices. 6 | 7 | Tongsuo-mini can be used in constrained environment while requiring small memory and storage usage. 8 | 9 | Tongsuo-mini is a member project of the Tongsuo open source community. 10 | 11 | ## Feature 12 | 13 | Tongsuo-mini has the following features: 14 | 15 | * Highly configurable modular build system 16 | * Lightweight cryptographic algorithm 17 | * ASCON AEAD 18 | * ASCON HASH 19 | * Lightweight secure network protocol 20 | * OSCORE 21 | * EDHOC\* 22 | * Dynamic binary loading based on predication logic\* 23 | * Oridnary cryptography algorithm 24 | * Chinese Shangmi: SM2\*,SM3,SM4 25 | * others\*: AES, SHA, RSA, ECDSA, EdDSA 26 | * Ordinary secure network protocol 27 | * TLS\* 28 | * TLCP\* 29 | 30 | Note: \* means the feature is under development 31 | 32 | ## Build 33 | 34 | The build depends on cmake, make and C compiler (gcc or clang). 35 | Build tongsuo-mini from the source code as follows: 36 | 37 | ```bash 38 | # Download source code 39 | git clone https://github.com/Tongsuo-Project/tongsuo-mini 40 | cd tongsuo-mini 41 | 42 | mkdir build 43 | cd build 44 | 45 | # Compile all modules with -DWITH_ALL=ON, compile specific module with -DWITH_=ON, e.g. -DWITH_ASCON=ON 46 | # View all available compilation options, cmake -LH .. 47 | cmake -DWITH_ALL=ON .. 48 | make -j 49 | 50 | # If you need to install 51 | make install 52 | ``` 53 | 54 | ## Test 55 | 56 | To test with Python3, create a virtual environment in the test directory and install the dependencies: 57 | 58 | ```bash 59 | cd test 60 | python3 -m venv .venv 61 | source .venv/bin/activate 62 | pip3 install -r requirements.txt 63 | ``` 64 | 65 | Then run the command in the build directory: 66 | 67 | ```bash 68 | ctest 69 | ``` 70 | 71 | Or run the command in the test directory: 72 | 73 | ```bash 74 | pytest . 75 | ``` 76 | -------------------------------------------------------------------------------- /test/test_hmac_sm3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "test.h" 14 | #include 15 | 16 | int test_hmac_sm3(const char *hex_key, const char *hex_msg, const char *hex_tag) 17 | { 18 | unsigned char *key = tsm_hex2buf(hex_key); 19 | unsigned char *msg = tsm_hex2buf(hex_msg); 20 | unsigned char *tag = tsm_hex2buf(hex_tag); 21 | unsigned char buf[TSM_SM3_DIGEST_LEN]; 22 | size_t outlen; 23 | 24 | ASSERT_OK(tsm_hmac_oneshot(TSM_HASH_SM3, key, strlen(hex_key) / 2, msg, 25 | msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); 26 | 27 | ASSERT(outlen == TSM_SM3_DIGEST_LEN); 28 | ASSERT(memcmp(buf, tag, outlen) == 0); 29 | 30 | if (key) 31 | tsm_free(key); 32 | if (msg) 33 | tsm_free(msg); 34 | if (tag) 35 | tsm_free(tag); 36 | 37 | return 0; 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | int i; 43 | const char *hex_key = NULL; 44 | const char *hex_msg = NULL; 45 | const char *hex_tag = NULL; 46 | 47 | for (i = 1; i < argc; i++) { 48 | if (argv[i][0] == '-') { 49 | if (i + 1 >= argc) 50 | break; 51 | 52 | if (argv[i + 1][0] == '-') 53 | continue; 54 | 55 | if (strcmp(argv[i], "-key") == 0) 56 | hex_key = argv[++i]; 57 | else if (strcmp(argv[i], "-msg") == 0) 58 | hex_msg = argv[++i]; 59 | else if (strcmp(argv[i], "-tag") == 0) 60 | hex_tag = argv[++i]; 61 | else 62 | return 1; 63 | } 64 | } 65 | 66 | TEST_EX(test_hmac_sm3, hex_key, hex_msg, hex_tag); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /include/tongsuo/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_MEM_H) 11 | # define TSM_MEM_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | # include 20 | 21 | # pragma pack(1) 22 | typedef struct tsm_str_s { 23 | size_t length; 24 | const uint8_t *s; 25 | } TSM_STR; 26 | # pragma pack() 27 | 28 | /* Create a new TSM_STR object with the given data and length. Should be freed by calling 29 | * tsm_str_free() after use. */ 30 | TSM_STR *tsm_str_new(const uint8_t *data, size_t len); 31 | /* Frees up the TSM_STR object. */ 32 | void tsm_str_free(TSM_STR *buf); 33 | /* Duplicates the TSM_STR object. Should be freed by calling tsm_str_free() after use. */ 34 | TSM_STR *tsm_str_dup(TSM_STR *buf); 35 | /* Creates a temp TSM_STR object with the given string. Must not be freed by calling tsm_str_free(). 36 | */ 37 | TSM_STR *tsm_str(const char *string); 38 | /* Creates a temp TSM_STR object with the given data and length. Must not be freed by calling 39 | * tsm_str_free(). */ 40 | TSM_STR *tsm_str_const(const uint8_t *data, size_t len); 41 | /* Compares two TSM_STR. Return non-zero means equal, 0 means not equal. */ 42 | int tsm_str_equal(TSM_STR *a, TSM_STR *b); 43 | /* Allocate a new buffer with size length. */ 44 | void *tsm_alloc(size_t size); 45 | /* Allocate a new buffer with size length and zero it. */ 46 | void *tsm_calloc(size_t size); 47 | /* Free the buffer. */ 48 | void tsm_free(void *ptr); 49 | /* Zero the buffer. */ 50 | void tsm_memzero(void *ptr, size_t size); 51 | /* Convert a hex buf with length buflen to binary. Return TSM_OK for success and others for failure. 52 | */ 53 | int tsm_hex2bin(const char *str, unsigned char *buf, size_t *buflen); 54 | /* Convert a hex string with NUL(\0) as ending to buffer. The return pointer shoud be freed by 55 | * calling tsm_free() after use. */ 56 | unsigned char *tsm_hex2buf(const char *str); 57 | 58 | # ifdef __cplusplus 59 | } 60 | # endif 61 | #endif 62 | -------------------------------------------------------------------------------- /examples/ascon_aead_enc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | int ret = 1; 19 | void *ctx = NULL; 20 | const char *plaintext = "hello world"; 21 | const char *ad = "0123456789abcdef"; 22 | unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 23 | unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); 24 | unsigned char out[1024]; 25 | unsigned char tag[TSM_ASCON_AEAD_TAG_LEN]; 26 | size_t outl, tmplen; 27 | 28 | if (key == NULL || iv == NULL) { 29 | goto err; 30 | } 31 | 32 | ctx = tsm_ascon_aead_ctx_new(); 33 | if (ctx == NULL) { 34 | goto err; 35 | } 36 | 37 | if (tsm_ascon_aead_init(ctx, TSM_ASCON_AEAD_128, key, iv, TSM_CIPH_FLAG_ENCRYPT) != TSM_OK 38 | || tsm_ascon_aead_update(ctx, (const unsigned char *)ad, strlen(ad), NULL, NULL) != TSM_OK 39 | || tsm_ascon_aead_update(ctx, 40 | (const unsigned char *)plaintext, 41 | strlen(plaintext), 42 | out, 43 | &outl) 44 | != TSM_OK 45 | || tsm_ascon_aead_final(ctx, out + outl, &tmplen) != TSM_OK) { 46 | goto err; 47 | } 48 | 49 | outl += tmplen; 50 | 51 | if (tsm_ascon_aead_get_tag(ctx, tag) != TSM_OK) { 52 | goto err; 53 | } 54 | 55 | printf("ASCON_AEAD_Encrypt(%s)=", plaintext); 56 | 57 | for (size_t i = 0; i < outl; i++) { 58 | printf("%02x", out[i]); 59 | } 60 | 61 | for (size_t i = 0; i < TSM_ASCON_AEAD_TAG_LEN; i++) { 62 | printf("%02x", tag[i]); 63 | } 64 | 65 | printf("\n"); 66 | 67 | ret = 0; 68 | err: 69 | tsm_ascon_aead_ctx_free(ctx); 70 | tsm_free(key); 71 | tsm_free(iv); 72 | return ret; 73 | } 74 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #ifdef TSM_ERRSTR 14 | static const char *errstr[] = { 15 | [TSM_OK] = "Success", 16 | [TSM_ERR_INTERNAL_ERROR] = "Internal error", 17 | [TSM_ERR_PASS_NULL_PARAM] = "Pass null param", 18 | [TSM_ERR_MALLOC_FAILED] = "Malloc failed", 19 | [TSM_ERR_OUT_OF_DATA] = "Out of data", 20 | [TSM_ERR_BUFFER_OVERFLOW] = "Buffer overflow", 21 | [TSM_ERR_BUFFER_TOO_SMALL] = "Buffer too small", 22 | [TSM_ERR_UNEXPECTED_ASN1_TAG] = "Unexpected ASN1 tag", 23 | [TSM_ERR_INVALID_ASN1_LENGTH] = "Invalid ASN1 length", 24 | [TSM_ERR_INVALID_ASN1_VALUE] = "Invalid ASN1 value", 25 | [TSM_ERR_WRONG_FINAL_BLOCK_LENGTH] = "Wrong length of final block", 26 | [TSM_ERR_BAD_DECRYPT] = "Bad decrypt", 27 | [TSM_ERR_WRONG_CIPH_MODE] = "Wrong cipher mode", 28 | [TSM_ERR_INVALID_HEX_STR] = "Invalid hex string", 29 | [TSM_ERR_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH] = "Data length not multiple of block length", 30 | [TSM_ERR_INVALID_AEAD_TAG_LENGTH] = "Invalid AEAD tag length", 31 | [TSM_ERR_INVALID_OPERATION] = "Invalid operation", 32 | [TSM_ERR_INVALID_ASCON_SCHEME] = "Invalid Ascon scheme", 33 | [TSM_ERR_AEAD_VERIFY_FAILED] = "AEAD verify failed", 34 | [TSM_ERR_INVALID_HASH_SIZE] = "Invalid hash size", 35 | [TSM_ERR_INVALID_HASH_ALGORITHM] = "Invalid hash algorithm", 36 | [TSM_ERR_NOT_FOUND] = "Not found", 37 | [TSM_ERR_INVALID_SEQ] = "Invalid sequence num", 38 | [TSM_ERR_REPLAYED_SEQ] = "Replayed sequence num", 39 | [TSM_ERR_ALGORITHM_NOT_SUPPORTED] = "Algorithm not supported", 40 | }; 41 | #endif 42 | 43 | const char *tsm_err2str(int err) 44 | { 45 | if (err == TSM_FAILED) 46 | return "Failed"; 47 | 48 | if (err < TSM_OK) 49 | return NULL; 50 | 51 | #ifdef TSM_ERRSTR 52 | return errstr[err]; 53 | #else 54 | if (err == TSM_OK) 55 | return "Success"; 56 | else 57 | return "Error"; 58 | #endif 59 | } 60 | -------------------------------------------------------------------------------- /src/meth.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "internal/sm3.h" 14 | #include "internal/meth.h" 15 | 16 | #ifdef TSM_HAVE_ASCON 17 | static TSM_HASH_METH tsm_ascon_hash_meth = { 18 | .name = "ascon_hash", 19 | .alg = TSM_HASH_ASCON_HASH, 20 | .hashsize = TSM_ASCON_HASH_LEN, 21 | /* The ASCON-HASH block absorption rate of 8 bytes is too short so we use the HMAC-SHA-256 22 | block size of 64 instead. */ 23 | .blocksize = 64, 24 | .newctx = tsm_ascon_hash_ctx_new, 25 | .freectx = tsm_ascon_hash_ctx_free, 26 | .init = tsm_ascon_hash_init, 27 | .update = tsm_ascon_hash_update, 28 | .final = tsm_ascon_hash_final, 29 | }; 30 | 31 | static TSM_HASH_METH tsm_ascon_hasha_meth = { 32 | .name = "ascon_hasha", 33 | .alg = TSM_HASH_ASCON_HASHA, 34 | .hashsize = TSM_ASCON_HASH_LEN, 35 | /* The ASCON-HASHA block absorption rate of 8 bytes is too short so we use the HMAC-SHA-256 36 | block size of 64 instead.*/ 37 | .blocksize = 64, 38 | .newctx = tsm_ascon_hash_ctx_new, 39 | .freectx = tsm_ascon_hash_ctx_free, 40 | .init = tsm_ascon_hasha_init, 41 | .update = tsm_ascon_hasha_update, 42 | .final = tsm_ascon_hasha_final, 43 | }; 44 | #endif 45 | 46 | #ifdef TSM_HAVE_SM3 47 | static TSM_HASH_METH tsm_sm3_meth = { 48 | .name = "sm3", 49 | .alg = TSM_HASH_SM3, 50 | .hashsize = TSM_SM3_DIGEST_LEN, 51 | .blocksize = TSM_SM3_CBLOCK, 52 | .newctx = tsm_sm3_ctx_new, 53 | .freectx = tsm_sm3_ctx_free, 54 | .init = tsm_sm3_init, 55 | .update = tsm_sm3_update, 56 | .final = tsm_sm3_final, 57 | }; 58 | #endif 59 | 60 | void *tsm_get_hash_meth(int alg) 61 | { 62 | (void)alg; 63 | #ifdef TSM_HAVE_SM3 64 | if (alg == TSM_HASH_SM3) 65 | return &tsm_sm3_meth; 66 | #endif 67 | 68 | #ifdef TSM_HAVE_ASCON 69 | if (alg == TSM_HASH_ASCON_HASH) 70 | return &tsm_ascon_hash_meth; 71 | 72 | if (alg == TSM_HASH_ASCON_HASHA) 73 | return &tsm_ascon_hasha_meth; 74 | #endif 75 | 76 | return NULL; 77 | } 78 | -------------------------------------------------------------------------------- /test/test_hmac_ascon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "test.h" 14 | #include 15 | 16 | int test_ascon_hmac(int hash, const char *hex_key, const char *hex_msg, const char *hex_tag) 17 | { 18 | unsigned char *key = tsm_hex2buf(hex_key); 19 | unsigned char *msg = tsm_hex2buf(hex_msg); 20 | unsigned char *tag = tsm_hex2buf(hex_tag); 21 | unsigned char buf[TSM_ASCON_HMAC_LEN]; 22 | size_t outlen; 23 | 24 | ASSERT_OK(tsm_hmac_oneshot(hash, key, strlen(hex_key) / 2, msg, 25 | msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); 26 | 27 | ASSERT(outlen == TSM_ASCON_HMAC_LEN); 28 | ASSERT(memcmp(buf, tag, outlen) == 0); 29 | 30 | if (key) 31 | tsm_free(key); 32 | if (msg) 33 | tsm_free(msg); 34 | if (tag) 35 | tsm_free(tag); 36 | 37 | return 0; 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | int i; 43 | int hash; 44 | const char *hex_key = NULL; 45 | const char *hex_msg = NULL; 46 | const char *hex_tag = NULL; 47 | const char *algo = NULL; 48 | 49 | for (i = 1; i < argc; i++) { 50 | if (argv[i][0] == '-') { 51 | if (i + 1 >= argc) 52 | break; 53 | 54 | if (argv[i + 1][0] == '-') 55 | continue; 56 | 57 | if (strcmp(argv[i], "-algo") == 0) 58 | algo = argv[++i]; 59 | else if (strcmp(argv[i], "-key") == 0) 60 | hex_key = argv[++i]; 61 | else if (strcmp(argv[i], "-msg") == 0) 62 | hex_msg = argv[++i]; 63 | else if (strcmp(argv[i], "-tag") == 0) 64 | hex_tag = argv[++i]; 65 | else 66 | return 1; 67 | } 68 | } 69 | 70 | if (strcmp(algo, "ascon-hmac") == 0) 71 | hash = TSM_HASH_ASCON_HASH; 72 | else if (strcmp(algo, "ascon-hmaca") == 0) 73 | hash = TSM_HASH_ASCON_HASHA; 74 | else 75 | return 1; 76 | 77 | TEST_EX(test_ascon_hmac, hash, hex_key, hex_msg, hex_tag); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /include/tongsuo/sm4.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_SM4_H) 11 | # define TSM_SM4_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | 20 | /* Create a new context of sm4. The context should be freed by calling tsm_sm4_ctx_free() after use. 21 | */ 22 | void *tsm_sm4_ctx_new(void); 23 | /* Frees up the context of sm4. */ 24 | void tsm_sm4_ctx_free(void *ctx); 25 | /* Initialize the sm4 context. Note: only mode TSM_CIPH_MODE_CBC is supported now. The length of key 26 | * should be 128 bits(16 bytes). iv is set on demand. flags can contain multiple flags bitwise XOR; 27 | * TSM_CIPH_FLAG_ENCRYPT means performing encryption, TSM_CIPH_FLAG_DECRYPT means performing 28 | * decryption, TSM_CIPH_FLAG_NO_PAD means no padding. Returns TSM_OK on success, error code on 29 | * error. */ 30 | int tsm_sm4_init(void *ctx, int mode, const unsigned char *key, const unsigned char *iv, int flags); 31 | /* Updates the sm4 context with the given data in and data length inl. The result is written to out 32 | * with the actual length to outl. Returns TSM_OK on success, error code on error. */ 33 | int tsm_sm4_update(void *ctx, const unsigned char *in, size_t inl, unsigned char *out, 34 | size_t *outl); 35 | /* Finalizes the sm4 encryption or decryption and writes the "final" data to out with the actual 36 | * length to outl. Returns TSM_OK on success, error code on error. */ 37 | int tsm_sm4_final(void *ctx, unsigned char *out, size_t *outl); 38 | /* Encrypts or decrypts the given data in with the length inl. The result is written to out with the 39 | * actual length to outl. The length of key should be 128 bits(16 bytes). iv is set on demand. flags 40 | * can contain multiple flags bitwise XOR; TSM_CIPH_FLAG_ENCRYPT means performing encryption, 41 | * TSM_CIPH_FLAG_DECRYPT means performing decryption, TSM_CIPH_FLAG_NO_PAD means no padding. 42 | * Returns TSM_OK on success, error code on error. */ 43 | int tsm_sm4_oneshot(int mode, const unsigned char *key, const unsigned char *iv, 44 | const unsigned char *in, size_t inl, unsigned char *out, size_t *outl, 45 | int flags); 46 | 47 | # ifdef __cplusplus 48 | } 49 | # endif 50 | #endif 51 | -------------------------------------------------------------------------------- /include/internal/oscore_crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore_crypto.h 33 | * @brief An implementation of the Hash Based Key Derivation Function (RFC) and 34 | * wrappers for AES-CCM*. 35 | * 36 | * \author 37 | * Martin Gunnarsson 38 | * 39 | * adapted to libcoap 40 | * Peter van der Stok 41 | * on request of Fairhair alliance 42 | * adapted for libcoap integration 43 | * Jon Shallow 44 | * adapted for Tongsuo-mini integration 45 | * K1 46 | */ 47 | 48 | #if !defined(TSM_INTERNAL_OSCORE_CRYPTO_H) 49 | # define TSM_INTERNAL_OSCORE_CRYPTO_H 50 | # pragma once 51 | 52 | # include 53 | 54 | int oscore_hkdf(cose_hkdf_alg_t hkdf_alg, 55 | TSM_STR *salt, 56 | TSM_STR *ikm, 57 | uint8_t *info, 58 | size_t info_len, 59 | uint8_t *okm, 60 | size_t okm_len); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/tongsuo/minisuo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_MINISUO_H) 11 | # define TSM_MINISUO_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | 20 | # define TONGSUO_IS_MINI 1 21 | 22 | # define TSM_VERSION_MAJOR 0 23 | # define TSM_VERSION_MINOR 9 24 | # define TSM_VERSION_PATCH 0 25 | /* 0x00, dev 26 | * 0x1~0xfe, pre1~pre254 27 | * 0xff, release */ 28 | # define TSM_VERSION_TAG 0 29 | # define TONGSUO_MINI_VERSION \ 30 | ((TSM_VERSION_MAJOR << 24) | (TSM_VERSION_MINOR << 16) | (TSM_VERSION_PATCH << 8) \ 31 | | TSM_VERSION_TAG) 32 | 33 | /* Supported cipher modes. */ 34 | # define TSM_CIPH_MODE_STREAM 0x0 35 | # define TSM_CIPH_MODE_ECB 0x1 36 | # define TSM_CIPH_MODE_CBC 0x2 37 | # define TSM_CIPH_MODE_CFB 0x3 38 | # define TSM_CIPH_MODE_OFB 0x4 39 | # define TSM_CIPH_MODE_CTR 0x5 40 | # define TSM_CIPH_MODE_GCM 0x6 41 | # define TSM_CIPH_MODE_CCM 0x7 42 | 43 | /* Supported cipher flags. */ 44 | # define TSM_CIPH_FLAG_ENCRYPT 0x1 45 | # define TSM_CIPH_FLAG_DECRYPT 0x2 46 | # define TSM_CIPH_FLAG_NO_PAD 0x4 47 | 48 | # define TSM_MAX_IV_LENGTH 16 49 | # define TSM_MAX_BLOCK_LENGTH 32 50 | 51 | /* Supported hash algorithms. */ 52 | enum { 53 | TSM_HASH_SM3 = 1, 54 | TSM_HASH_ASCON_HASH, 55 | TSM_HASH_ASCON_HASHA, 56 | }; 57 | 58 | /* All error codes are defined here. 59 | * Most of APIs return TSM_OK on success, specific error code on failure. */ 60 | enum { 61 | TSM_FAILED = -1, 62 | TSM_OK = 0, 63 | TSM_ERR_INTERNAL_ERROR, 64 | TSM_ERR_PASS_NULL_PARAM, 65 | TSM_ERR_MALLOC_FAILED, 66 | TSM_ERR_OUT_OF_DATA, 67 | TSM_ERR_BUFFER_OVERFLOW, 68 | TSM_ERR_BUFFER_TOO_SMALL, 69 | TSM_ERR_UNEXPECTED_ASN1_TAG, 70 | TSM_ERR_INVALID_ASN1_LENGTH, 71 | TSM_ERR_INVALID_ASN1_VALUE, 72 | TSM_ERR_WRONG_FINAL_BLOCK_LENGTH, 73 | TSM_ERR_BAD_DECRYPT, 74 | TSM_ERR_WRONG_CIPH_MODE, 75 | TSM_ERR_INVALID_HEX_STR, 76 | TSM_ERR_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH, 77 | TSM_ERR_INVALID_AEAD_TAG_LENGTH, 78 | TSM_ERR_INVALID_OPERATION, 79 | TSM_ERR_INVALID_ASCON_SCHEME, 80 | TSM_ERR_AEAD_VERIFY_FAILED, 81 | TSM_ERR_INVALID_HASH_SIZE, 82 | TSM_ERR_INVALID_HASH_ALGORITHM, 83 | TSM_ERR_NOT_FOUND, 84 | TSM_ERR_INVALID_SEQ, 85 | TSM_ERR_REPLAYED_SEQ, 86 | TSM_ERR_ALGORITHM_NOT_SUPPORTED, 87 | }; 88 | 89 | /* Converts error code to error string. */ 90 | const char *tsm_err2str(int err); 91 | /* Returns version text of tongsuo-mini. */ 92 | const char *tsm_version_text(void); 93 | 94 | # ifdef __cplusplus 95 | } 96 | # endif 97 | #endif 98 | -------------------------------------------------------------------------------- /test/test_sm4_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include "test.h" 12 | #include 13 | 14 | static int test_sm4_crypt(int idx) 15 | { 16 | void *ctx = NULL; 17 | unsigned char key[16] = { 18 | 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 19 | 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 20 | }; 21 | unsigned char iv[16] = { 22 | 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 23 | 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 24 | }; 25 | unsigned char plain[32] = { 26 | 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 27 | 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 28 | 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 29 | }; 30 | unsigned char out[32]; 31 | unsigned char cipher[32] = { 32 | 0x26, 0x77, 0xF4, 0x6B, 0x09, 0xC1, 0x22, 0xCC, 0x97, 0x55, 0x33, 33 | 0x10, 0x5B, 0xD4, 0xA2, 0x2A, 0xF6, 0x12, 0x5F, 0x72, 0x75, 0xCE, 34 | 0x55, 0x2C, 0x3A, 0x2B, 0xBC, 0xF5, 0x33, 0xDE, 0x8A, 0x3B, 35 | }; 36 | size_t outlen, tmplen; 37 | 38 | if (idx == 0) { 39 | ctx = tsm_sm4_ctx_new(); 40 | ASSERT(ctx != NULL); 41 | 42 | ASSERT_OK(tsm_sm4_init(ctx, TSM_CIPH_MODE_CBC, key, iv, 43 | TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD)); 44 | ASSERT_OK(tsm_sm4_update(ctx, plain, sizeof(plain), out, &outlen)); 45 | ASSERT_OK(tsm_sm4_final(ctx, out + outlen, &tmplen)); 46 | 47 | ASSERT(memcmp(out, cipher, sizeof(cipher)) == 0); 48 | 49 | tsm_sm4_ctx_free(ctx); 50 | } else if (idx == 1) { 51 | ctx = tsm_sm4_ctx_new(); 52 | ASSERT(ctx != NULL); 53 | 54 | ASSERT_OK(tsm_sm4_init(ctx, TSM_CIPH_MODE_CBC, key, iv, 55 | TSM_CIPH_FLAG_DECRYPT | TSM_CIPH_FLAG_NO_PAD)); 56 | ASSERT_OK(tsm_sm4_update(ctx, cipher, sizeof(cipher), out, &outlen)); 57 | ASSERT_OK(tsm_sm4_final(ctx, out + outlen, &tmplen)); 58 | 59 | ASSERT(memcmp(out, plain, sizeof(plain)) == 0); 60 | 61 | tsm_sm4_ctx_free(ctx); 62 | } else if (idx == 2) { 63 | ASSERT_OK(tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, key, iv, plain, sizeof(plain), out, &outlen, 64 | TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD)); 65 | ASSERT(memcmp(out, cipher, sizeof(cipher)) == 0); 66 | } else if (idx == 3) { 67 | ASSERT_OK(tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, key, iv, cipher, sizeof(cipher), out, &outlen, 68 | TSM_CIPH_FLAG_DECRYPT | TSM_CIPH_FLAG_NO_PAD)); 69 | ASSERT(memcmp(out, plain, sizeof(plain)) == 0); 70 | } 71 | 72 | return TSM_OK; 73 | } 74 | 75 | int main(void) 76 | { 77 | TESTS(test_sm4_crypt, 4); 78 | 79 | return TSM_OK; 80 | } 81 | -------------------------------------------------------------------------------- /src/pool.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include "internal/log.h" 11 | #include "internal/pool.h" 12 | #include 13 | #include 14 | 15 | typedef struct { 16 | unsigned char *last; 17 | unsigned char *end; 18 | tsm_pool_t *next; 19 | int failed; 20 | } tsm_pool_data_t; 21 | 22 | struct tsm_pool_s { 23 | tsm_pool_data_t d; 24 | tsm_pool_t *current; 25 | }; 26 | 27 | static void *tsm_palloc_block(tsm_pool_t *pool, size_t size); 28 | 29 | tsm_pool_t *ngx_create_pool(size_t size) 30 | { 31 | tsm_pool_t *p; 32 | 33 | p = tsm_alloc(size); 34 | if (p == NULL) { 35 | return NULL; 36 | } 37 | 38 | p->d.last = (unsigned char *)p + sizeof(tsm_pool_t); 39 | p->d.end = (unsigned char *)p + size; 40 | p->d.next = NULL; 41 | p->d.failed = 0; 42 | 43 | size = size - sizeof(tsm_pool_t); 44 | p->current = p; 45 | 46 | LOGD("create pool %p:%z", p, size); 47 | return p; 48 | } 49 | 50 | void tsm_destroy_pool(tsm_pool_t *pool) 51 | { 52 | tsm_pool_t *p, *n; 53 | LOGD("destroy pool %p", pool); 54 | 55 | for (p = pool, n = pool->d.next;; p = n, n = n->d.next) { 56 | tsm_free(p); 57 | 58 | if (n == NULL) { 59 | break; 60 | } 61 | } 62 | } 63 | 64 | void *tsm_palloc(tsm_pool_t *pool, size_t size) 65 | { 66 | unsigned char *m; 67 | tsm_pool_t *p; 68 | 69 | LOGD("palloc %p:%z", pool, size); 70 | 71 | p = pool->current; 72 | 73 | do { 74 | m = p->d.last; 75 | 76 | if ((size_t)(p->d.end - m) >= size) { 77 | p->d.last = m + size; 78 | 79 | return m; 80 | } 81 | 82 | p = p->d.next; 83 | 84 | } while (p); 85 | 86 | return tsm_palloc_block(pool, size); 87 | } 88 | 89 | static void *tsm_palloc_block(tsm_pool_t *pool, size_t size) 90 | { 91 | unsigned char *m; 92 | size_t psize; 93 | tsm_pool_t *p, *new; 94 | 95 | psize = (size_t)(pool->d.end - (unsigned char *)pool); 96 | 97 | m = tsm_alloc(psize); 98 | if (m == NULL) { 99 | return NULL; 100 | } 101 | 102 | new = (tsm_pool_t *)m; 103 | 104 | new->d.end = m + psize; 105 | new->d.next = NULL; 106 | new->d.failed = 0; 107 | 108 | m += sizeof(tsm_pool_data_t); 109 | new->d.last = m + size; 110 | 111 | for (p = pool->current; p->d.next; p = p->d.next) { 112 | if (p->d.failed++ > 4) { 113 | pool->current = p->d.next; 114 | } 115 | } 116 | 117 | p->d.next = new; 118 | 119 | return m; 120 | } 121 | 122 | void *tsm_pcalloc(tsm_pool_t *pool, size_t size) 123 | { 124 | void *p; 125 | 126 | p = tsm_palloc(pool, size); 127 | if (p) { 128 | tsm_memzero(p, size); 129 | } 130 | 131 | LOGD("pcalloc %p:%p:%z", pool, p, size); 132 | return p; 133 | } 134 | -------------------------------------------------------------------------------- /include/internal/asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_INTERNAL_ASN1_H) 11 | # define TSM_INTERNAL_ASN1_H 12 | # pragma once 13 | 14 | # include 15 | 16 | # define TONGSUO_ASN1_BOOLEAN 0x01 17 | # define TONGSUO_ASN1_INTEGER 0x02 18 | # define TONGSUO_ASN1_BIT_STRING 0x03 19 | # define TONGSUO_ASN1_OCTET_STRING 0x04 20 | # define TONGSUO_ASN1_NULL 0x05 21 | # define TONGSUO_ASN1_OBJECT_IDENTIFIER 0x06 22 | # define TONGSUO_ASN1_ENUMERATED 0x0A 23 | # define TONGSUO_ASN1_UTF8_STRING 0x0C 24 | # define TONGSUO_ASN1_SEQUENCE 0x10 25 | # define TONGSUO_ASN1_SET 0x11 26 | # define TONGSUO_ASN1_PRINTABLE_STRING 0x13 27 | # define TONGSUO_ASN1_T61_STRING 0x14 28 | # define TONGSUO_ASN1_IA5_STRING 0x16 29 | # define TONGSUO_ASN1_UTC_TIME 0x17 30 | # define TONGSUO_ASN1_GENERALIZED_TIME 0x18 31 | # define TONGSUO_ASN1_UNIVERSAL_STRING 0x1C 32 | # define TONGSUO_ASN1_BMP_STRING 0x1E 33 | 34 | # define TONGSUO_ASN1_PRIMITIVE 0x00 35 | # define TONGSUO_ASN1_CONSTRUCTED 0x20 36 | # define TONGSUO_ASN1_CONTEXT_SPECIFIC 0x80 37 | 38 | typedef struct { 39 | unsigned char *p; 40 | size_t len; 41 | unsigned char padding; 42 | } ts_asn1_bitstring; 43 | 44 | int asn1_encode_header_tag(unsigned char **out, size_t *outl, int tag); 45 | int asn1_decode_header_tag(unsigned char **in, size_t inlen, int *tag); 46 | int asn1_encode_header_len(unsigned char **out, size_t *outl, size_t len); 47 | int asn1_decode_header_len(unsigned char **in, size_t inlen, size_t *len); 48 | int asn1_encode_header(unsigned char **out, size_t *outl, int tag, size_t len); 49 | int asn1_decode_header(unsigned char **in, size_t inlen, int tag, size_t *len); 50 | 51 | int asn1_encode_bool(unsigned char **out, size_t *outl, int val); 52 | int asn1_decode_bool(unsigned char **in, size_t inlen, int *val); 53 | 54 | int asn1_encode_int(unsigned char **out, size_t *outl, int val); 55 | int asn1_decode_int(unsigned char **in, size_t inlen, int *val); 56 | 57 | int asn1_encode_bit_string(unsigned char **out, size_t *outl, const unsigned char *bs, 58 | size_t nbits); 59 | int asn1_decode_bit_string(unsigned char **in, size_t inlen, unsigned char *bs, size_t *nbits); 60 | 61 | int asn1_encode_octet_string(unsigned char **out, size_t *outl, const unsigned char *buf, 62 | size_t buflen); 63 | 64 | int asn1_encode_null(unsigned char **out, size_t *outl); 65 | int asn1_decode_null(unsigned char **in, size_t inlen); 66 | 67 | int asn1_encode_oid(unsigned char **out, size_t *outl, const unsigned char *oid, size_t oidlen); 68 | 69 | int asn1_encode_enum(unsigned char **out, size_t *outl, int val); 70 | int asn1_decode_enum(unsigned char **in, size_t inlen, int *val); 71 | 72 | int asn1_encode_printable_string(unsigned char **out, size_t *outl, const unsigned char *buf, 73 | size_t buflen); 74 | 75 | int asn1_encode_ia5_string(unsigned char **out, size_t *outl, const unsigned char *buf, 76 | size_t buflen); 77 | #endif 78 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License 2.0 (the "License"). You may not use 4 | # this file except in compliance with the License. You can obtain a copy 5 | # in the file LICENSE in the source distribution or at 6 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 7 | 8 | name: GitHub CI 9 | 10 | on: [pull_request, push] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | check-format: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: clang-format check 21 | uses: jidicula/clang-format-action@v4.11.0 22 | with: 23 | clang-format-version: '17' 24 | include-regex: '^\./(app|examples|include|perf|src|test)/.*\.(c|h)$' 25 | minimal: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: install packages 30 | run: | 31 | sudo apt-get update 32 | sudo apt-get -y install cmake python3 python3-pip 33 | - name: Configure CMake 34 | run: cmake -B ${{github.workspace}}/build 35 | - name: Build 36 | run: cmake --build ${{github.workspace}}/build 37 | - name: Test 38 | working-directory: ${{github.workspace}}/build 39 | run: | 40 | python3 -m venv ${{github.workspace}}/.venv 41 | source ${{github.workspace}}/.venv/bin/activate 42 | pip3 install -r ${{github.workspace}}/test/requirements.txt 43 | ctest -C ${{env.BUILD_TYPE}} 44 | - name: debug 45 | if: ${{ failure() }} 46 | run: | 47 | cat ${{github.workspace}}/build/Testing/Temporary/LastTest.log 48 | 49 | with_single_module: 50 | runs-on: ubuntu-latest 51 | strategy: 52 | fail-fast: false 53 | matrix: 54 | module: [ascon, asn1, hmac, oscore, sm3, sm4] 55 | steps: 56 | - uses: actions/checkout@v3 57 | - name: install packages 58 | run: | 59 | sudo apt-get update 60 | sudo apt-get -y install cmake python3 python3-pip 61 | - name: Configure CMake 62 | run: cmake -B ${{github.workspace}}/build -DWITH_${{matrix.module}}=ON 63 | - name: Build 64 | run: cmake --build ${{github.workspace}}/build 65 | - name: Test 66 | working-directory: ${{github.workspace}}/build 67 | run: | 68 | python3 -m venv ${{github.workspace}}/.venv 69 | source ${{github.workspace}}/.venv/bin/activate 70 | pip3 install -r ${{github.workspace}}/test/requirements.txt 71 | ctest -C ${{env.BUILD_TYPE}} 72 | - name: debug 73 | if: ${{ failure() }} 74 | run: | 75 | cat ${{github.workspace}}/build/Testing/Temporary/LastTest.log 76 | 77 | all: 78 | runs-on: ubuntu-latest 79 | steps: 80 | - uses: actions/checkout@v3 81 | - name: install packages 82 | run: | 83 | sudo apt-get update 84 | sudo apt-get -y install cmake python3 python3-pip 85 | - name: Configure CMake 86 | run: cmake -B ${{github.workspace}}/build -DWITH_ALL=ON 87 | - name: Build 88 | run: cmake --build ${{github.workspace}}/build 89 | - name: Test 90 | working-directory: ${{github.workspace}}/build 91 | run: | 92 | python3 -m venv ${{github.workspace}}/.venv 93 | source ${{github.workspace}}/.venv/bin/activate 94 | pip3 install -r ${{github.workspace}}/test/requirements.txt 95 | ctest -C ${{env.BUILD_TYPE}} 96 | - name: debug 97 | if: ${{ failure() }} 98 | run: | 99 | cat ${{github.workspace}}/build/Testing/Temporary/LastTest.log 100 | 101 | -------------------------------------------------------------------------------- /test/test_sm3_data/sm3.txt: -------------------------------------------------------------------------------- 1 | Count = 1 2 | Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857 3 | Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A 4 | 5 | Count = 2 6 | Input = 616263 7 | Output = 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0 8 | 9 | Count = 3 10 | Input = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364 11 | Output = DEBE9FF92275B8A138604889C18E5A4D6FDB70E5387E5765293dCbA39C0C5732 12 | 13 | Count = 4 14 | Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857 15 | Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A 16 | 17 | Count = 5 18 | Input = 0090414C494345313233405941484F4F2E434F4D00000000000000000000000000000000000000000000000000000000000000000000E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B201686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612 19 | Output = 26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD5 20 | 21 | Count = 6 22 | Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A23099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE16553DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B 23 | Output = E4D1D0C3CA4C7F11BC8FF8CB3F4C02A78F108FA098E51A668487240F75E20F31 24 | 25 | Count = 7 26 | Input = 008842494C4C343536405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F4353C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C 27 | Output = 6B4B6D0E276691BD4A11BF72F4FB501AE309FDACB72FA6CC336E6656119ABD67 28 | 29 | Count = 8 30 | Input = 4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D03082020CA003020102020900AF28725D98D33143300C06082A811CCF550183750500307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E301E170D3132303632343037353433395A170D3332303632303037353433395A307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E3059301306072A8648CE3D020106082A811CCF5501822D03420004D69C2F1EEC3BFB6B95B30C28085C77B125D77A9C39525D8190768F37D6B205B589DCD316BBE7D89A9DC21917F17799E698531F5E6E3E10BD31370B259C3F81C3A3733071300F0603551D130101FF040530030101FF301D0603551D0E041604148E5D90347858BAAAD870D8BDFBA6A85E7B563B64301F0603551D230418301680148E5D90347858BAAAD870D8BDFBA6A85E7B563B64300B0603551D0F040403020106301106096086480186F8420101040403020057 31 | Output = C3B02E500A8B60B77DEDCF6F4C11BEF8D56E5CDE708C72065654FD7B2167915A -------------------------------------------------------------------------------- /src/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | #include 10 | #include "internal/log.h" 11 | #include 12 | #include 13 | 14 | void *tsm_alloc(size_t size) 15 | { 16 | void *ptr = malloc(size); 17 | LOGD("malloc %p:%u", ptr, size); 18 | return ptr; 19 | } 20 | 21 | void *tsm_calloc(size_t size) 22 | { 23 | void *ptr; 24 | 25 | ptr = tsm_alloc(size); 26 | if (ptr) 27 | tsm_memzero(ptr, size); 28 | 29 | return ptr; 30 | } 31 | 32 | void tsm_free(void *ptr) 33 | { 34 | LOGD("free %p", ptr); 35 | if (ptr == NULL) 36 | return; 37 | free(ptr); 38 | } 39 | 40 | void tsm_memzero(void *ptr, size_t size) 41 | { 42 | (void)memset(ptr, 0, size); 43 | } 44 | 45 | static int tsm_hexchar2int(char c) 46 | { 47 | if (c >= '0' && c <= '9') { 48 | return c - '0'; 49 | } else if (c >= 'A' && c <= 'F') { 50 | return c - 'A' + 10; 51 | } else if (c >= 'a' && c <= 'f') { 52 | return c - 'a' + 10; 53 | } 54 | return -1; 55 | } 56 | 57 | int tsm_hex2bin(const char *str, unsigned char *buf, size_t *buflen) 58 | { 59 | size_t i, j; 60 | size_t len; 61 | 62 | len = strlen(str); 63 | if (len & 1) { 64 | return TSM_ERR_INVALID_HEX_STR; 65 | } 66 | len /= 2; 67 | 68 | if (buf == NULL) { 69 | *buflen = len; 70 | return TSM_OK; 71 | } 72 | 73 | if (*buflen < len) { 74 | *buflen = len; 75 | return TSM_ERR_BUFFER_TOO_SMALL; 76 | } 77 | 78 | memset(buf, 0, *buflen); 79 | 80 | for (i = 0, j = 0; i < len; i++) { 81 | int k; 82 | 83 | k = tsm_hexchar2int(str[i * 2]); 84 | if (k < 0) 85 | return TSM_ERR_INVALID_HEX_STR; 86 | 87 | buf[j] = k << 4; 88 | 89 | k = tsm_hexchar2int(str[i * 2 + 1]); 90 | if (k < 0) 91 | return TSM_ERR_INVALID_HEX_STR; 92 | 93 | buf[j] |= k; 94 | j++; 95 | } 96 | 97 | *buflen = len; 98 | 99 | return TSM_OK; 100 | } 101 | 102 | unsigned char *tsm_hex2buf(const char *str) 103 | { 104 | size_t len; 105 | unsigned char *buf; 106 | 107 | if (str == NULL) 108 | return NULL; 109 | 110 | len = strlen(str); 111 | if (len & 1) 112 | return NULL; 113 | 114 | len /= 2; 115 | buf = tsm_alloc(len); 116 | if (buf == NULL) 117 | return NULL; 118 | 119 | if (tsm_hex2bin(str, buf, &len) != TSM_OK) { 120 | tsm_free(buf); 121 | return NULL; 122 | } 123 | 124 | return buf; 125 | } 126 | 127 | TSM_STR *tsm_str_new(const uint8_t *data, size_t len) 128 | { 129 | TSM_STR *buf; 130 | uint8_t *tmp; 131 | 132 | buf = tsm_calloc(sizeof(*buf)); 133 | if (buf == NULL) 134 | return NULL; 135 | 136 | tmp = tsm_alloc(len); 137 | if (tmp == NULL) { 138 | tsm_free(tmp); 139 | return NULL; 140 | } 141 | 142 | memcpy(tmp, data, len); 143 | buf->length = len; 144 | buf->s = tmp; 145 | 146 | return buf; 147 | } 148 | 149 | TSM_STR *tsm_str_dup(TSM_STR *buf) 150 | { 151 | if (buf == NULL) 152 | return NULL; 153 | 154 | return tsm_str_new(buf->s, buf->length); 155 | } 156 | 157 | int tsm_str_equal(TSM_STR *a, TSM_STR *b) 158 | { 159 | if (a == NULL || b == NULL) 160 | return 0; 161 | 162 | if (a->length == b->length && memcmp(a->s, b->s, a->length) == 0) 163 | return 1; 164 | 165 | return 0; 166 | } 167 | 168 | void tsm_str_free(TSM_STR *buf) 169 | { 170 | if (buf == NULL) 171 | return; 172 | 173 | tsm_free((void *)buf->s); 174 | tsm_free(buf); 175 | } 176 | 177 | TSM_STR *tsm_str_const(const uint8_t *data, size_t len) 178 | { 179 | static int pos = 0; 180 | static TSM_STR tb[10]; 181 | if (pos == 10) 182 | pos = 0; 183 | tb[pos].length = len; 184 | tb[pos].s = data; 185 | return &tb[pos++]; 186 | } 187 | 188 | TSM_STR *tsm_str(const char *string) 189 | { 190 | return tsm_str_const((const uint8_t *)string, strlen(string)); 191 | } 192 | -------------------------------------------------------------------------------- /.github/workflows/compiler-zoo.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License 2.0 (the "License"). You may not use 4 | # this file except in compliance with the License. You can obtain a copy 5 | # in the file LICENSE in the source distribution or at 6 | # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 7 | 8 | name: Compiler Zoo CI 9 | 10 | on: [pull_request, push] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | compiler: 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | zoo: [ 21 | { 22 | cc: gcc-7, 23 | distro: ubuntu-20.04 24 | }, { 25 | cc: gcc-8, 26 | distro: ubuntu-20.04 27 | }, { 28 | cc: gcc-9, 29 | distro: ubuntu-20.04 30 | }, { 31 | cc: gcc-10, 32 | distro: ubuntu-20.04 33 | }, { 34 | cc: gcc-11, 35 | distro: ubuntu-22.04 36 | }, { 37 | cc: gcc-12, 38 | distro: ubuntu-22.04 39 | }, { 40 | cc: clang-6.0, 41 | distro: ubuntu-20.04 42 | }, { 43 | cc: clang-7, 44 | distro: ubuntu-20.04 45 | }, { 46 | cc: clang-8, 47 | distro: ubuntu-20.04 48 | }, { 49 | cc: clang-9, 50 | distro: ubuntu-20.04 51 | }, { 52 | cc: clang-10, 53 | distro: ubuntu-20.04 54 | }, { 55 | cc: clang-11, 56 | distro: ubuntu-20.04 57 | }, { 58 | cc: clang-12, 59 | distro: ubuntu-20.04 60 | }, { 61 | cc: clang-13, 62 | distro: ubuntu-22.04 63 | }, { 64 | cc: clang-14, 65 | distro: ubuntu-22.04 66 | }, { 67 | cc: clang-15, 68 | distro: ubuntu-22.04, 69 | llvm-ppa-name: jammy 70 | }, { 71 | cc: clang-16, 72 | distro: ubuntu-22.04, 73 | llvm-ppa-name: jammy 74 | } 75 | ] 76 | # We set per-compiler now to allow testing with both older and newer sets 77 | # Often, the full range of oldest->newest compilers we want aren't available 78 | # in a single version of Ubuntu. 79 | 80 | runs-on: ${{ matrix.zoo.distro }} 81 | steps: 82 | - uses: actions/checkout@v3 83 | - name: install packages 84 | run: | 85 | llvm_ppa_name="${{ matrix.zoo.llvm-ppa-name }}" 86 | 87 | # In the Matrix above, we set llvm-ppa-name if an LLVM version isn't 88 | # part of the Ubuntu version we're using. See https://apt.llvm.org/. 89 | 90 | if [[ -n ${llvm_ppa_name} ]] ; then 91 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key |\ 92 | gpg --dearmor |\ 93 | sudo tee /usr/share/keyrings/llvm-snapshot.gpg.key > /dev/null 94 | 95 | clang_version="${{ matrix.zoo.cc }}" 96 | clang_version="${clang_version/clang-}" 97 | 98 | echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg.key] http://apt.llvm.org/${{ matrix.zoo.llvm-ppa-name }}/ llvm-toolchain-${{ matrix.zoo.llvm-ppa-name }}-${clang_version} main" \ 99 | | sudo tee /etc/apt/sources.list.d/llvm.list 100 | echo "deb-src [signed-by=/usr/share/keyrings/llvm-snapshot.gpg.key] http://apt.llvm.org/${{ matrix.zoo.llvm-ppa-name }}/ llvm-toolchain-${{ matrix.zoo.llvm-ppa-name }}-${clang_version} main" \ 101 | | sudo tee -a /etc/apt/sources.list.d/llvm.list 102 | 103 | cat /etc/apt/sources.list.d/llvm.list 104 | fi 105 | 106 | sudo apt-get update 107 | sudo apt-get -y install ${{ matrix.zoo.cc }} 108 | sudo apt-get -y install cmake python3 python3-pip 109 | - name: Configure CMake 110 | run: cmake -B ${{github.workspace}}/build -D CMAKE_C_COMPILER=${{ matrix.zoo.cc }} -DWITH_ALL=ON 111 | - name: Build 112 | run: cmake --build ${{github.workspace}}/build 113 | - name: Test 114 | working-directory: ${{github.workspace}}/build 115 | run: | 116 | python3 -m venv ${{github.workspace}}/.venv 117 | source ${{github.workspace}}/.venv/bin/activate 118 | pip3 install -r ${{github.workspace}}/test/requirements.txt 119 | ctest -C ${{env.BUILD_TYPE}} 120 | - name: debug 121 | if: ${{ failure() }} 122 | run: | 123 | cat ${{github.workspace}}/build/Testing/Temporary/LastTest.log 124 | -------------------------------------------------------------------------------- /test/test_ascon_aead.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "test.h" 15 | 16 | static int scheme; 17 | static char *hex_key; 18 | static char *hex_nonce; 19 | static char *hex_ad; 20 | static char *hex_plaintext; 21 | static char *hex_ciphertext; 22 | 23 | int test_ascon_aead_encrypt(void) 24 | { 25 | unsigned char *key = tsm_hex2buf(hex_key); 26 | unsigned char *nonce = tsm_hex2buf(hex_nonce); 27 | unsigned char *ad = tsm_hex2buf(hex_ad); 28 | unsigned char *plaintext = tsm_hex2buf(hex_plaintext); 29 | unsigned char *ciphertext = tsm_hex2buf(hex_ciphertext); 30 | unsigned char *buf = NULL; 31 | size_t buflen; 32 | size_t plaintext_len = 0; 33 | 34 | if (plaintext != NULL) 35 | plaintext_len = strlen(hex_plaintext) / 2; 36 | 37 | buflen = plaintext_len + TSM_ASCON_AEAD_TAG_LEN; 38 | buf = tsm_alloc(buflen); 39 | ASSERT_OK(tsm_ascon_aead_oneshot(scheme, key, nonce, ad, ad == NULL ? 0 : strlen(hex_ad) / 2, 40 | plaintext, plaintext_len, buf, &buflen, 41 | TSM_CIPH_FLAG_ENCRYPT)); 42 | 43 | ASSERT(buflen == plaintext_len + TSM_ASCON_AEAD_TAG_LEN); 44 | ASSERT(memcmp(buf, ciphertext, buflen) == 0); 45 | 46 | if (buf) 47 | tsm_free(buf); 48 | if (key) 49 | tsm_free(key); 50 | if (nonce) 51 | tsm_free(nonce); 52 | if (ad) 53 | tsm_free(ad); 54 | if (plaintext) 55 | tsm_free(plaintext); 56 | if (ciphertext) 57 | tsm_free(ciphertext); 58 | 59 | return 0; 60 | } 61 | 62 | int test_ascon_aead_decrypt(void) 63 | { 64 | unsigned char *key = tsm_hex2buf(hex_key); 65 | unsigned char *nonce = tsm_hex2buf(hex_nonce); 66 | unsigned char *ad = tsm_hex2buf(hex_ad); 67 | unsigned char *plaintext = tsm_hex2buf(hex_plaintext); 68 | unsigned char *ciphertext = tsm_hex2buf(hex_ciphertext); 69 | unsigned char *buf = NULL; 70 | size_t buflen; 71 | size_t plaintext_len = 0; 72 | 73 | if (plaintext != NULL) 74 | plaintext_len = strlen(hex_plaintext) / 2; 75 | 76 | buflen = plaintext_len; 77 | buf = tsm_alloc(buflen); 78 | 79 | ASSERT_OK(tsm_ascon_aead_oneshot(scheme, key, nonce, ad, ad == NULL ? 0 : strlen(hex_ad) / 2, 80 | ciphertext, strlen(hex_ciphertext) / 2, buf, &buflen, 81 | TSM_CIPH_FLAG_DECRYPT)); 82 | 83 | ASSERT(buflen == plaintext_len); 84 | ASSERT(memcmp(buf, plaintext, buflen) == 0); 85 | 86 | if (buf) 87 | tsm_free(buf); 88 | if (key) 89 | tsm_free(key); 90 | if (nonce) 91 | tsm_free(nonce); 92 | if (ad) 93 | tsm_free(ad); 94 | if (plaintext) 95 | tsm_free(plaintext); 96 | if (ciphertext) 97 | tsm_free(ciphertext); 98 | 99 | return 0; 100 | } 101 | 102 | int main(int argc, char **argv) 103 | { 104 | int i; 105 | 106 | for (i = 1; i < argc; i++) { 107 | if (argv[i][0] == '-') { 108 | if (i + 1 >= argc) 109 | break; 110 | 111 | if (argv[i + 1][0] == '-') 112 | continue; 113 | 114 | if (strcmp(argv[i], "-scheme") == 0) { 115 | if (strcmp(argv[i + 1], "ascon128") == 0) { 116 | scheme = TSM_ASCON_AEAD_128; 117 | } else if (strcmp(argv[i + 1], "ascon128a") == 0) { 118 | scheme = TSM_ASCON_AEAD_128A; 119 | } else { 120 | fprintf(stderr, "unknown scheme\n"); 121 | return 1; 122 | } 123 | i++; 124 | } else if (strcmp(argv[i], "-key") == 0) { 125 | hex_key = argv[++i]; 126 | } else if (strcmp(argv[i], "-nonce") == 0) { 127 | hex_nonce = argv[++i]; 128 | } else if (strcmp(argv[i], "-ad") == 0) { 129 | hex_ad = argv[++i]; 130 | } else if (strcmp(argv[i], "-pt") == 0) { 131 | hex_plaintext = argv[++i]; 132 | } else if (strcmp(argv[i], "-ct") == 0) { 133 | hex_ciphertext = argv[++i]; 134 | } 135 | } 136 | } 137 | 138 | TEST(test_ascon_aead_encrypt); 139 | TEST(test_ascon_aead_decrypt); 140 | return 0; 141 | } 142 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TONGSUOMINI_TEST_H) 11 | # define TONGSUOMINI_TEST_H 12 | # pragma once 13 | 14 | # include "internal/asn1.h" 15 | # include 16 | # include 17 | # include 18 | 19 | # define TEST(func) RUN_TEST(__FILE__, __LINE__, func) 20 | # define RUN_TEST(file, line, func) \ 21 | do { \ 22 | int ret = func(); \ 23 | if (ret) { \ 24 | fprintf(stderr, "Failed\t%s\t%s:%d\n", #func, file, line); \ 25 | return ret; \ 26 | } else { \ 27 | fprintf(stderr, "Passed\t%s\t%s:%d\n", #func, file, line); \ 28 | } \ 29 | } while (0) 30 | # define TEST_EX(func, ...) RUN_TEST_WITH_ARGS(__FILE__, __LINE__, func, __VA_ARGS__) 31 | # define RUN_TEST_WITH_ARGS(file, line, func, ...) \ 32 | do { \ 33 | int ret = func(__VA_ARGS__); \ 34 | if (ret) { \ 35 | fprintf(stderr, "Failed\t%s\t%s:%d\n", #func, file, line); \ 36 | return ret; \ 37 | } else { \ 38 | fprintf(stderr, "Passed\t%s\t%s:%d\n", #func, file, line); \ 39 | } \ 40 | } while (0) 41 | 42 | # define TESTS(...) RUN_TESTS(__VA_ARGS__, __FILE__, __LINE__) 43 | # define RUN_TESTS(func, n, file, line) \ 44 | for (int i = 0; i < n; i++) { \ 45 | int ret = func(i); \ 46 | if (ret) { \ 47 | fprintf(stderr, "Failed\t%s(%d)\t%s:%d\n", #func, i, file, line); \ 48 | return ret; \ 49 | } else { \ 50 | fprintf(stderr, "Passed\t%s(%d)\t%s:%d\n", #func, i, file, line); \ 51 | } \ 52 | } 53 | 54 | # define ASSERT(exp) TEST_ASSERT((exp), __FILE__, __LINE__) 55 | # define ASSERT_0(ret) TEST_ASSERT(((ret) == 0), __FILE__, __LINE__) 56 | # define ASSERT_OK(ret) TEST_ASSERT(((ret) == TSM_OK), __FILE__, __LINE__) 57 | # define ASSERT_ERR(ret) TEST_ASSERT(((ret) != TSM_OK), __FILE__, __LINE__) 58 | 59 | # define TEST_ASSERT(exp, func, line) \ 60 | do { \ 61 | if (exp) { \ 62 | ; \ 63 | } else { \ 64 | TEST_FAIL((func), (line)); \ 65 | } \ 66 | } while (0) 67 | 68 | static inline void TEST_FAIL(const char *func, int line) 69 | { 70 | fprintf(stderr, "Assert Failed\t%s:%d\n", func, line); 71 | exit(1); 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/hmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include "internal/meth.h" 11 | #include "internal/log.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define HMAC_IPAD 0x36 18 | #define HMAC_OPAD 0x5C 19 | 20 | /* The current largest case is for SHA3-224 */ 21 | #define HMAC_MAX_MD_CBLOCK_SIZE 144 22 | 23 | typedef struct { 24 | void *algctx; 25 | TSM_HASH_METH *meth; 26 | unsigned char *key; 27 | size_t keylen; 28 | } TSM_HMAC_CTX; 29 | 30 | void *tsm_hmac_ctx_new(void) 31 | { 32 | return tsm_calloc(sizeof(TSM_HMAC_CTX)); 33 | } 34 | 35 | void tsm_hmac_ctx_free(void *ctx) 36 | { 37 | if (ctx == NULL) 38 | return; 39 | 40 | TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; 41 | if (c->algctx != NULL) { 42 | c->meth->freectx(c->algctx); 43 | c->algctx = NULL; 44 | } 45 | 46 | tsm_free(c->key); 47 | tsm_free(c); 48 | } 49 | 50 | int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, int hash_alg) 51 | { 52 | TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; 53 | void *meth = tsm_get_hash_meth(hash_alg); 54 | unsigned char *temp = NULL; 55 | unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; 56 | size_t temp_len; 57 | int ret, i; 58 | 59 | if (meth == NULL) 60 | return eLOG(TSM_ERR_INVALID_HASH_ALGORITHM); 61 | 62 | c->meth = meth; 63 | 64 | if (c->algctx == NULL) { 65 | c->algctx = c->meth->newctx(); 66 | if (c->algctx == NULL) 67 | return eLOG(TSM_ERR_MALLOC_FAILED); 68 | } 69 | 70 | temp = tsm_alloc(c->meth->blocksize); 71 | if (temp == NULL) 72 | return eLOG(TSM_ERR_MALLOC_FAILED); 73 | 74 | if (keylen > c->meth->blocksize) { 75 | if (c->meth->blocksize < c->meth->hashsize) { 76 | ret = TSM_ERR_INVALID_HASH_SIZE; 77 | goto err; 78 | } 79 | 80 | if ((ret = c->meth->init(c->algctx)) != TSM_OK 81 | || (ret = c->meth->update(c->algctx, key, keylen)) != TSM_OK 82 | || (ret = c->meth->final(c->algctx, temp, &temp_len)) != TSM_OK) 83 | goto err; 84 | } else { 85 | memcpy(temp, key, keylen); 86 | temp_len = keylen; 87 | } 88 | 89 | c->key = temp; 90 | c->keylen = temp_len; 91 | temp = NULL; 92 | 93 | if (c->keylen < c->meth->blocksize) 94 | memset(c->key + c->keylen, 0, c->meth->blocksize - c->keylen); 95 | 96 | for (i = 0; i < c->meth->blocksize; i++) 97 | pad[i] = c->key[i] ^ HMAC_IPAD; 98 | 99 | if ((ret = c->meth->init(c->algctx)) != TSM_OK 100 | || (ret = c->meth->update(c->algctx, pad, c->meth->blocksize)) != TSM_OK) 101 | goto err; 102 | 103 | ret = TSM_OK; 104 | err: 105 | tsm_free(temp); 106 | return ret; 107 | } 108 | 109 | int tsm_hmac_update(void *ctx, const unsigned char *in, size_t inlen) 110 | { 111 | TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; 112 | int ret; 113 | 114 | if ((ret = c->meth->update(c->algctx, in, inlen)) != TSM_OK) 115 | return ret; 116 | 117 | return TSM_OK; 118 | } 119 | 120 | int tsm_hmac_final(void *ctx, unsigned char *out, size_t *outl) 121 | { 122 | TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; 123 | unsigned char *temp = NULL; 124 | unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; 125 | size_t temp_len; 126 | int ret, i; 127 | 128 | temp = tsm_alloc(c->meth->hashsize); 129 | if (temp == NULL) 130 | return eLOG(TSM_ERR_MALLOC_FAILED); 131 | 132 | if ((ret = c->meth->final(c->algctx, temp, &temp_len)) != TSM_OK) 133 | goto err; 134 | 135 | for (i = 0; i < c->meth->blocksize; i++) 136 | pad[i] = c->key[i] ^ HMAC_OPAD; 137 | 138 | if ((ret = c->meth->init(c->algctx) != TSM_OK) 139 | || (ret = c->meth->update(c->algctx, pad, c->meth->blocksize)) != TSM_OK 140 | || (ret = c->meth->update(c->algctx, temp, temp_len)) != TSM_OK 141 | || (ret = c->meth->final(c->algctx, out, outl)) != TSM_OK) { 142 | goto err; 143 | } 144 | 145 | ret = TSM_OK; 146 | err: 147 | tsm_free(temp); 148 | return ret; 149 | } 150 | 151 | int tsm_hmac_oneshot(int hash_alg, const unsigned char *key, size_t keylen, const unsigned char *in, 152 | size_t inlen, unsigned char *out, size_t *outl) 153 | { 154 | TSM_HMAC_CTX *ctx; 155 | int ret; 156 | 157 | ctx = tsm_hmac_ctx_new(); 158 | if (ctx == NULL) 159 | return eLOG(TSM_ERR_MALLOC_FAILED); 160 | 161 | if ((ret = tsm_hmac_init(ctx, key, keylen, hash_alg)) != TSM_OK 162 | || (ret = tsm_hmac_update(ctx, in, inlen)) != TSM_OK 163 | || (ret = tsm_hmac_final(ctx, out, outl)) != TSM_OK) { 164 | tsm_hmac_ctx_free(ctx); 165 | return ret; 166 | } 167 | 168 | tsm_hmac_ctx_free(ctx); 169 | return TSM_OK; 170 | } 171 | -------------------------------------------------------------------------------- /include/tongsuo/ascon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #if !defined(TSM_ASCON_H) 11 | # define TSM_ASCON_H 12 | # pragma once 13 | 14 | # ifdef __cplusplus 15 | extern "C" { 16 | # endif 17 | 18 | # include 19 | 20 | # define TSM_ASCON_AEAD_128 0x1 21 | # define TSM_ASCON_AEAD_128A 0x2 22 | 23 | # define TSM_ASCON_AEAD_TAG_LEN 16 24 | # define TSM_ASCON_AEAD_KEY_LEN 16 25 | # define TSM_ASCON_AEAD_IV_LEN 16 26 | 27 | # define TSM_ASCON_HASH_LEN 32 28 | # define TSM_ASCON_HMAC_LEN TSM_ASCON_HASH_LEN 29 | 30 | /* Create a new context of ascon aead, should be freed by tsm_ascon_aead_ctx_free() after use. */ 31 | void *tsm_ascon_aead_ctx_new(void); 32 | /* Frees up the context ctx of ascon aead. */ 33 | void tsm_ascon_aead_ctx_free(void *ctx); 34 | /* Initializes the context ctx with type, key, iv and flags. type should be TSM_ASCON_AEAD_128 or 35 | * TSM_ASCON_AEAD_128A. The length of key and iv should be 16 bytes. flags may be 36 | * TSM_CIPH_FLAG_ENCRYPT or TSM_CIPH_FLAG_DECRYPT. If you want to encrypt data without padding, 37 | * flags should be TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD. Returns TSM_OK for success and 38 | * others for failure. */ 39 | int tsm_ascon_aead_init(void *ctx, int type, const unsigned char *key, const unsigned char *iv, 40 | int flags); 41 | /* Encrypts or decrypts data at in with the length inl, and retrives the result at out. The number 42 | * of bytes of result written will be written to the integer at outl. Returns TSM_OK for success and 43 | * others for failure. */ 44 | int tsm_ascon_aead_update(void *ctx, const unsigned char *in, size_t inl, unsigned char *out, 45 | size_t *outl); 46 | /* Encrypts or decrypts the "final" data, that is any data that remains in a partial block. The 47 | * encrypted or decrypted final data is written to out which should have sufficient space for one 48 | * cipher block, 16 bytes for aead. The number of bytes written is placed in outl. After this 49 | * function is called the encryption operation is finished and no further calls to 50 | * tsm_ascon_aead_update() should be made. Returns TSM_OK for success and others for failure. */ 51 | int tsm_ascon_aead_final(void *ctx, unsigned char *out, size_t *outl); 52 | /* Set tag before ascon AEAD decryption. Returns TSM_OK on success, error code on failure. */ 53 | int tsm_ascon_aead_set_tag(void *ctx, const unsigned char *tag); 54 | /* Get tag after ascon AEAD encryption. Returns TSM_OK on success, error code on failure. */ 55 | int tsm_ascon_aead_get_tag(void *ctx, unsigned char *tag); 56 | /* Encrypts or decrypts data at in with length inl, and retrives the result at out. The number of 57 | * bytes of result written will be written to the integer at outl. The length of key and iv 58 | * should be 16 bytes. type should be TSM_ASCON_AEAD_128 or TSM_ASCON_AEAD_128A. flags may be 59 | * TSM_CIPH_FLAG_ENCRYPT or TSM_CIPH_FLAG_DECRYPT. If you want to encrypt data without padding, 60 | * flags should be TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD. 61 | * When encryption, the tag is appended to the ciphertext, so the length of out should be inl + 62 | * TSM_ASCON_AEAD_TAG_LEN. When decryption, the tag should be located at the end of plaintext with 63 | * the length TSM_ASCON_AEAD_TAG_LEN. 64 | * Returns TSM_OK on success, error code on failure. */ 65 | int tsm_ascon_aead_oneshot(int type, const unsigned char *key, const unsigned char *iv, 66 | const unsigned char *ad, size_t adl, const unsigned char *in, size_t inl, 67 | unsigned char *out, size_t *outl, int flags); 68 | /* Create ctx of ascon hash. */ 69 | void *tsm_ascon_hash_ctx_new(void); 70 | /* Destroy ctx of ascon hash. */ 71 | void tsm_ascon_hash_ctx_free(void *ctx); 72 | /* Initialize ascon hash ctx. Returns TSM_OK on success, error code on failure. */ 73 | int tsm_ascon_hash_init(void *ctx); 74 | /* Identical to tsm_ascon_hash_init(), but used by ascon hasha only. */ 75 | int tsm_ascon_hasha_init(void *ctx); 76 | /* Hashes inl bytes of data at in into the hash context ctx. This function can be called serveral 77 | * times on the same ctx to hash more data. Returns TSM_OK for success and others for failure. */ 78 | int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl); 79 | /* Identical to tsm_ascon_hash_update(), but used by ascon hasha only. */ 80 | int tsm_ascon_hasha_update(void *ctx, const unsigned char *in, size_t inl); 81 | /* Retrieves the hash value from ctx and place it in out. The number of bytes of data written will 82 | * be written to the integer at outl. If successful, the length of digest should be 83 | * TSM_ASCON_HASH_LEN. After calling tsm_ascon_hash_final() no additional calls to 84 | * tsm_ascon_hash_update() can be made. Returns TSM_OK for success and others for failure. */ 85 | int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl); 86 | /* Identical to tsm_ascon_hasha_final(), but used by ascon hasha only. */ 87 | int tsm_ascon_hasha_final(void *ctx, unsigned char *out, size_t *outl); 88 | /* Hashes inl bytes of data at in, and retrieves the hash value at out. hash should be either 89 | * TSM_HASH_ASCON_HASH or TSM_HASH_ASCON_HASHA. The number of bytes of data written will be written 90 | * to the integer at outl. If successful, the length of digest should be TSM_ASCON_HASH_LEN. Returns 91 | * TSM_OK on success, error code on failure. */ 92 | int tsm_ascon_hash_oneshot(int hash, const unsigned char *in, size_t inl, unsigned char *out, 93 | size_t *outl); 94 | # ifdef __cplusplus 95 | } 96 | # endif 97 | #endif 98 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignArrayOfStructures: None 7 | AlignConsecutiveMacros: AcrossEmptyLines 8 | AlignConsecutiveAssignments: None 9 | AlignConsecutiveBitFields: AcrossEmptyLines 10 | AlignConsecutiveDeclarations: None 11 | AlignEscapedNewlines: Right 12 | AlignOperands: Align 13 | AlignTrailingComments: true 14 | AllowAllArgumentsOnNextLine: false 15 | AllowAllParametersOfDeclarationOnNextLine: false 16 | AllowShortEnumsOnASingleLine: true 17 | AllowShortBlocksOnASingleLine: Never 18 | AllowShortCaseLabelsOnASingleLine: false 19 | AllowShortFunctionsOnASingleLine: None 20 | AllowShortLambdasOnASingleLine: All 21 | AllowShortIfStatementsOnASingleLine: Never 22 | AllowShortLoopsOnASingleLine: false 23 | AlwaysBreakAfterDefinitionReturnType: None 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: false 26 | AlwaysBreakTemplateDeclarations: MultiLine 27 | AttributeMacros: 28 | - __capability 29 | BinPackArguments: true 30 | BinPackParameters: true 31 | BraceWrapping: 32 | AfterCaseLabel: false 33 | AfterClass: false 34 | AfterControlStatement: Never 35 | AfterEnum: false 36 | AfterFunction: false 37 | AfterNamespace: false 38 | AfterObjCDeclaration: false 39 | AfterStruct: false 40 | AfterUnion: false 41 | AfterExternBlock: false 42 | BeforeCatch: false 43 | BeforeElse: false 44 | BeforeLambdaBody: false 45 | BeforeWhile: false 46 | IndentBraces: false 47 | SplitEmptyFunction: true 48 | SplitEmptyRecord: true 49 | SplitEmptyNamespace: true 50 | BreakBeforeBinaryOperators: NonAssignment 51 | BreakBeforeConceptDeclarations: true 52 | BreakBeforeBraces: Linux 53 | BreakBeforeInheritanceComma: false 54 | BreakInheritanceList: BeforeColon 55 | BreakBeforeTernaryOperators: true 56 | BreakConstructorInitializersBeforeComma: false 57 | BreakConstructorInitializers: BeforeColon 58 | BreakAfterJavaFieldAnnotations: false 59 | BreakStringLiterals: false 60 | ColumnLimit: 100 61 | CommentPragmas: '^ IWYU pragma:' 62 | QualifierAlignment: Leave 63 | CompactNamespaces: false 64 | ConstructorInitializerIndentWidth: 4 65 | ContinuationIndentWidth: 4 66 | Cpp11BracedListStyle: true 67 | DeriveLineEnding: true 68 | DerivePointerAlignment: false 69 | DisableFormat: false 70 | EmptyLineAfterAccessModifier: Never 71 | EmptyLineBeforeAccessModifier: LogicalBlock 72 | ExperimentalAutoDetectBinPacking: true 73 | PackConstructorInitializers: BinPack 74 | BasedOnStyle: '' 75 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 76 | AllowAllConstructorInitializersOnNextLine: true 77 | FixNamespaceComments: true 78 | ForEachMacros: 79 | - foreach 80 | - Q_FOREACH 81 | - BOOST_FOREACH 82 | IfMacros: 83 | - KJ_IF_MAYBE 84 | IncludeBlocks: Preserve 85 | IncludeCategories: 86 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 87 | Priority: 2 88 | SortPriority: 0 89 | CaseSensitive: false 90 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 91 | Priority: 3 92 | SortPriority: 0 93 | CaseSensitive: false 94 | - Regex: '.*' 95 | Priority: 1 96 | SortPriority: 0 97 | CaseSensitive: false 98 | IncludeIsMainRegex: '(Test)?$' 99 | IncludeIsMainSourceRegex: '' 100 | IndentAccessModifiers: false 101 | IndentCaseLabels: false 102 | IndentCaseBlocks: false 103 | IndentGotoLabels: true 104 | IndentPPDirectives: AfterHash 105 | IndentExternBlock: AfterExternBlock 106 | IndentRequires: false 107 | IndentWidth: 4 108 | IndentWrappedFunctionNames: false 109 | InsertTrailingCommas: None 110 | JavaScriptQuotes: Leave 111 | JavaScriptWrapImports: true 112 | KeepEmptyLinesAtTheStartOfBlocks: false 113 | LambdaBodyIndentation: Signature 114 | MacroBlockBegin: '' 115 | MacroBlockEnd: '' 116 | MaxEmptyLinesToKeep: 1 117 | NamespaceIndentation: None 118 | ObjCBinPackProtocolList: Auto 119 | ObjCBlockIndentWidth: 2 120 | ObjCBreakBeforeNestedBlockParam: true 121 | ObjCSpaceAfterProperty: false 122 | ObjCSpaceBeforeProtocolList: true 123 | PenaltyBreakAssignment: 2 124 | PenaltyBreakBeforeFirstCallParameter: 30 125 | PenaltyBreakComment: 10 126 | PenaltyBreakFirstLessLess: 0 127 | PenaltyBreakOpenParenthesis: 0 128 | PenaltyBreakString: 10 129 | PenaltyBreakTemplateDeclaration: 10 130 | PenaltyExcessCharacter: 100 131 | PenaltyReturnTypeOnItsOwnLine: 60 132 | PenaltyIndentedWhitespace: 0 133 | PointerAlignment: Right 134 | PPIndentWidth: 1 135 | ReferenceAlignment: Pointer 136 | ReflowComments: true 137 | RemoveBracesLLVM: false 138 | SeparateDefinitionBlocks: Leave 139 | ShortNamespaceLines: 1 140 | SortIncludes: Never 141 | SortJavaStaticImport: Before 142 | SortUsingDeclarations: true 143 | SpaceAfterCStyleCast: false 144 | SpaceAfterLogicalNot: false 145 | SpaceAfterTemplateKeyword: true 146 | SpaceBeforeAssignmentOperators: true 147 | SpaceBeforeCaseColon: false 148 | SpaceBeforeCpp11BracedList: false 149 | SpaceBeforeCtorInitializerColon: true 150 | SpaceBeforeInheritanceColon: true 151 | SpaceBeforeParens: ControlStatements 152 | SpaceBeforeParensOptions: 153 | AfterControlStatements: true 154 | AfterForeachMacros: true 155 | AfterFunctionDefinitionName: false 156 | AfterFunctionDeclarationName: false 157 | AfterIfMacros: true 158 | AfterOverloadedOperator: false 159 | BeforeNonEmptyParentheses: false 160 | SpaceAroundPointerQualifiers: Default 161 | SpaceBeforeRangeBasedForLoopColon: true 162 | SpaceInEmptyBlock: false 163 | SpaceInEmptyParentheses: false 164 | SpacesBeforeTrailingComments: 1 165 | SpacesInAngles: Never 166 | SpacesInConditionalStatement: false 167 | SpacesInContainerLiterals: false 168 | SpacesInCStyleCastParentheses: false 169 | SpacesInLineCommentPrefix: 170 | Minimum: 1 171 | Maximum: -1 172 | SpacesInParentheses: false 173 | SpacesInSquareBrackets: false 174 | SpaceBeforeSquareBrackets: false 175 | BitFieldColonSpacing: Both 176 | Standard: Latest 177 | UseTab: Never 178 | UseCRLF: false 179 | #LineEnding: LF 180 | -------------------------------------------------------------------------------- /test/ascon_gen_kat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static int gen_aead(FILE *fp, int scheme) 18 | { 19 | unsigned char key[TSM_ASCON_AEAD_KEY_LEN]; 20 | unsigned char iv[TSM_ASCON_AEAD_IV_LEN]; 21 | unsigned char pt[32]; 22 | unsigned char ad[32]; 23 | unsigned char ct[1024]; 24 | unsigned char tag[TSM_ASCON_AEAD_TAG_LEN]; 25 | size_t outl; 26 | int i, j, k, cnt = 0; 27 | 28 | for (i = 0; i < sizeof(key); i++) { 29 | key[i] = i; 30 | } 31 | for (i = 0; i < sizeof(iv); i++) { 32 | iv[i] = i; 33 | } 34 | for (i = 0; i < sizeof(pt); i++) { 35 | pt[i] = i; 36 | } 37 | for (i = 0; i < sizeof(ad); i++) { 38 | ad[i] = i; 39 | } 40 | 41 | fprintf(fp, "# Generated by ascon_gen_kat\n"); 42 | 43 | for (i = 0; i <= sizeof(pt); i++) { 44 | for (j = 0; j <= sizeof(ad); j++) { 45 | fprintf(fp, "Count = %d\n", ++cnt); 46 | 47 | fprintf(fp, "Key = "); 48 | for (k = 0; k < sizeof(key); k++) { 49 | fprintf(fp, "%02X", key[k]); 50 | } 51 | 52 | fprintf(fp, "\nNonce = "); 53 | for (k = 0; k < sizeof(iv); k++) { 54 | fprintf(fp, "%02X", iv[k]); 55 | } 56 | 57 | fprintf(fp, "\nPT = "); 58 | for (k = 0; k < i; k++) { 59 | fprintf(fp, "%02X", pt[k]); 60 | } 61 | 62 | fprintf(fp, "\nAD = "); 63 | for (k = 0; k < j; k++) { 64 | fprintf(fp, "%02X", ad[k]); 65 | } 66 | 67 | fprintf(fp, "\nCT = "); 68 | if (tsm_ascon_aead_oneshot(scheme, key, iv, ad, j, pt, i, ct, &outl, 69 | TSM_CIPH_FLAG_ENCRYPT) 70 | != TSM_OK) { 71 | fprintf(stderr, "Error: could not encrypt\n"); 72 | return 0; 73 | } 74 | for (k = 0; k < outl; k++) { 75 | fprintf(fp, "%02X", ct[k]); 76 | } 77 | 78 | fprintf(fp, "\n\n"); 79 | } 80 | } 81 | 82 | return 1; 83 | } 84 | 85 | static int gen_hash(FILE *fp, int scheme) 86 | { 87 | unsigned int i, j, cnt = 0; 88 | unsigned char buf[1024]; 89 | unsigned char hash[TSM_ASCON_HASH_LEN]; 90 | size_t outl; 91 | 92 | for (i = 0; i < sizeof(buf); i++) { 93 | buf[i] = i & 0xff; 94 | } 95 | 96 | fprintf(fp, "# Generated by ascon_gen_kat\n"); 97 | for (i = 0; i <= sizeof(buf); i++) { 98 | fprintf(fp, "Count = %u\n", i + 1); 99 | 100 | fprintf(fp, "Msg = "); 101 | for (j = 0; j < i; j++) { 102 | fprintf(fp, "%02X", buf[j]); 103 | } 104 | fprintf(fp, "\n"); 105 | 106 | if (tsm_ascon_hash_oneshot(scheme, buf, i, hash, &outl) != TSM_OK) { 107 | fprintf(stderr, "Error: could not generate hash\n"); 108 | return 0; 109 | } 110 | 111 | fprintf(fp, "MD = "); 112 | for (j = 0; j < TSM_ASCON_HASH_LEN; j++) { 113 | fprintf(fp, "%02X", hash[j]); 114 | } 115 | 116 | fprintf(fp, "\n\n"); 117 | } 118 | 119 | return 1; 120 | } 121 | 122 | static int gen_hmac(FILE *fp, int hash) 123 | { 124 | unsigned char msg[1024]; 125 | unsigned char key[32]; 126 | unsigned char buf[TSM_ASCON_HMAC_LEN]; 127 | size_t outlen; 128 | int i; 129 | 130 | fprintf(fp, "# Generated by ascon_gen_kat\n"); 131 | 132 | for (i = 0; i < sizeof(key); i++) { 133 | key[i] = i; 134 | } 135 | 136 | for (i = 0; i < sizeof(msg); i++) { 137 | msg[i] = i & 0xff; 138 | } 139 | 140 | for (i = 0; i <= sizeof(msg); i++) { 141 | fprintf(fp, "Count = %d\n", i + 1); 142 | 143 | fprintf(fp, "Key = "); 144 | for (int j = 0; j < sizeof(key); j++) { 145 | fprintf(fp, "%02X", key[j]); 146 | } 147 | 148 | fprintf(fp, "\nMsg = "); 149 | for (int j = 0; j < i; j++) { 150 | fprintf(fp, "%02X", msg[j]); 151 | } 152 | 153 | fprintf(fp, "\nTag = "); 154 | if (tsm_hmac_oneshot(hash, key, sizeof(key), msg, i, buf, &outlen) != TSM_OK) { 155 | fprintf(stderr, "Error: could not generate HMAC\n"); 156 | return 0; 157 | } 158 | for (int j = 0; j < outlen; j++) { 159 | fprintf(fp, "%02X", buf[j]); 160 | } 161 | 162 | fprintf(fp, "\n\n"); 163 | } 164 | 165 | return 1; 166 | } 167 | 168 | int main(int argc, char **argv) 169 | { 170 | int ret = 0; 171 | 172 | if (argc != 2) { 173 | fprintf(stderr, "Usage: %s [-hash|-hasha|-aead128|-aead128a|-hmac|-hmaca]\n", argv[0]); 174 | exit(EXIT_FAILURE); 175 | } 176 | 177 | if (strcmp(argv[1], "-hash") == 0) { 178 | ret = gen_hash(stdout, TSM_HASH_ASCON_HASH); 179 | } else if (strcmp(argv[1], "-hasha") == 0) { 180 | ret = gen_hash(stdout, TSM_HASH_ASCON_HASHA); 181 | } else if (strcmp(argv[1], "-aead128") == 0) { 182 | ret = gen_aead(stdout, TSM_ASCON_AEAD_128); 183 | } else if (strcmp(argv[1], "-aead128a") == 0) { 184 | ret = gen_aead(stdout, TSM_ASCON_AEAD_128A); 185 | } else if (strcmp(argv[1], "-hmac") == 0) { 186 | ret = gen_hmac(stdout, TSM_HASH_ASCON_HASH); 187 | } else if (strcmp(argv[1], "-hmaca") == 0) { 188 | ret = gen_hmac(stdout, TSM_HASH_ASCON_HASHA); 189 | } else { 190 | fprintf(stderr, "Error: invalid argument %s\n", argv[1]); 191 | exit(EXIT_FAILURE); 192 | } 193 | 194 | if (ret == 0) { 195 | fprintf(stderr, "Error: could not generate KAT\n"); 196 | exit(EXIT_FAILURE); 197 | } 198 | 199 | return 0; 200 | } 201 | 202 | // cc ascon_gen_kat.c ../build/libtongsuo-mini.a -o ascon_gen_kat -I ../include 203 | // ./ascon_gen_kat -hash > ascon_hash.txt 204 | -------------------------------------------------------------------------------- /include/tongsuo/oscore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore.h 33 | * @brief An implementation of the Object Security for Constrained RESTful 34 | * Environments (RFC 8613). 35 | * 36 | * \author Martin Gunnarsson 37 | * major rewrite for libcoap 38 | * Peter van der Stok 39 | * on request of Fairhair alliance 40 | * adapted for libcoap integration 41 | * Jon Shallow 42 | * adapted for Tongsuo-mini integration 43 | * K1 44 | */ 45 | 46 | #if !defined(TSM_OSCORE_H) 47 | # define TSM_OSCORE_H 48 | # pragma once 49 | 50 | # ifdef __cplusplus 51 | extern "C" { 52 | # endif 53 | 54 | # include 55 | # include 56 | # include 57 | 58 | # define TSM_OSCORE_DEFAULT_REPLAY_WINDOW 32 59 | 60 | /* Estimate your header size, especially when using Proxy-Uri. */ 61 | # define COAP_MAX_HEADER_SIZE 70 62 | 63 | /* OSCORE error messages (to be moved elsewhere */ 64 | # define OSCORE_DECRYPTION_ERROR 100 65 | # define PACKET_SERIALIZATION_ERROR 102 66 | 67 | /* Encodes the OSCORE option value to option_buffer with length option_buf_len. Returns the written 68 | * length. */ 69 | size_t tsm_oscore_encode_option_value(uint8_t *option_buffer, 70 | size_t option_buf_len, 71 | cose_encrypt0_t *cose, 72 | uint8_t group, 73 | uint8_t appendix_b_2); 74 | 75 | /* Decodes the OSCORE option value and places decoded values into the provided 76 | * cose structure. Returns TSM_OK if successful, error code otherwise. */ 77 | int tsm_oscore_decode_option_value(const uint8_t *option_value, 78 | size_t option_len, 79 | cose_encrypt0_t *cose); 80 | 81 | /* Creates AAD, creates External AAD and serializes it into the complete AAD 82 | * structure. Returns serialized size. */ 83 | size_t tsm_oscore_prepare_aad(const uint8_t *external_aad_buffer, 84 | size_t external_aad_len, 85 | uint8_t *aad_buffer, 86 | size_t aad_size); 87 | /* 88 | * Build the CBOR for external_aad 89 | * 90 | * external_aad = bstr .cbor aad_array 91 | * 92 | * No group mode 93 | * aad_array = [ 94 | * oscore_version : uint, 95 | * algorithms : [ alg_aead : int / tstr ], 96 | * request_kid : bstr, 97 | * request_piv : bstr, 98 | * options : bstr, 99 | * ] 100 | * 101 | * Group mode 102 | * aad_array = [ 103 | * oscore_version : uint, 104 | * algorithms : [alg_aead : int / tstr / null, 105 | * alg_signature_enc : int / tstr / null, 106 | * alg_signature : int / tstr / null, 107 | * alg_pairwise_key_agreement : int / tstr / null], 108 | * request_kid : bstr, 109 | * request_piv : bstr, 110 | * options : bstr, 111 | * request_kid_context : bstr, 112 | * OSCORE_option: bstr, 113 | * sender_public_key: bstr, (initiator's key) 114 | * gm_public_key: bstr / null 115 | * ] 116 | */ 117 | size_t tsm_oscore_prepare_e_aad(oscore_ctx_t *ctx, 118 | cose_encrypt0_t *cose, 119 | const uint8_t *oscore_option, 120 | size_t oscore_option_len, 121 | TSM_STR *sender_public_key, 122 | uint8_t *external_aad_ptr, 123 | size_t external_aad_size); 124 | 125 | /* Creates nonce and writes to buffer with length size. */ 126 | void tsm_oscore_generate_nonce(cose_encrypt0_t *ptr, 127 | oscore_ctx_t *ctx, 128 | uint8_t *buffer, 129 | uint8_t size); 130 | 131 | /* Validate the sequence of sender. Returns TSM_OK if OK, error code otherwise. */ 132 | int tsm_oscore_validate_sender_seq(oscore_recipient_ctx_t *ctx, cose_encrypt0_t *cose); 133 | 134 | /* Increases the sequence of sender. Returns TSM_OK on succes, error code on error. */ 135 | int tsm_oscore_increment_sender_seq(oscore_ctx_t *ctx); 136 | /* Restore the sequence number and replay-window to the previous state. This is 137 | * to be used when decryption fail. */ 138 | void tsm_oscore_roll_back_seq(oscore_recipient_ctx_t *ctx); 139 | /* Create a OSCORE conf object which should be freed by calling tsm_oscore_conf_free() after use. */ 140 | TSM_OSCORE_CONF *tsm_oscore_conf_new(void); 141 | /* Frees up the OSCORE conf object. */ 142 | void tsm_oscore_conf_free(TSM_OSCORE_CONF *oscf); 143 | 144 | # ifdef __cplusplus 145 | } 146 | # endif 147 | #endif 148 | -------------------------------------------------------------------------------- /src/oscore_crypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore_crypto.c 33 | * @brief An implementation of the Hash Based Key Derivation Function (RFC) and 34 | * wrappers for AES-CCM*. 35 | * 36 | * \author 37 | * Martin Gunnarsson 38 | * extended for libcoap 39 | * Peter van der Stok 40 | * on request of Fairhair alliance 41 | * adapted for libcoap integration 42 | * Jon Shallow 43 | * adapted for Tongsuo-mini integration 44 | * K1 45 | */ 46 | 47 | #include "internal/log.h" 48 | #include "internal/meth.h" 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | static int oscore_hmac_hash(int hmac_alg, TSM_STR *key, TSM_STR *data, TSM_STR **hmac) 57 | { 58 | int ret; 59 | unsigned char *out = NULL; 60 | size_t outl; 61 | TSM_HASH_METH *meth = tsm_get_hash_meth(hmac_alg); 62 | 63 | if (meth == NULL) 64 | return eLOG(TSM_ERR_INVALID_HASH_ALGORITHM); 65 | 66 | out = tsm_alloc(meth->hashsize); 67 | if (out == NULL) 68 | return eLOG(TSM_ERR_MALLOC_FAILED); 69 | 70 | if ((ret = tsm_hmac_oneshot(hmac_alg, key->s, key->length, data->s, data->length, out, &outl)) 71 | != TSM_OK) { 72 | tsm_free(out); 73 | LOGE("oscore_hmac_hash: Failed hmac\n"); 74 | return ret; 75 | } 76 | 77 | *hmac = tsm_str_new(out, outl); 78 | tsm_free(out); 79 | 80 | return TSM_OK; 81 | } 82 | 83 | static int 84 | oscore_hkdf_extract(cose_hkdf_alg_t hkdf_alg, TSM_STR *salt, TSM_STR *ikm, TSM_STR **hkdf_extract) 85 | { 86 | int hmac_alg; 87 | int ret; 88 | 89 | assert(ikm); 90 | if ((ret = tsm_cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg)) != TSM_OK) 91 | return ret; 92 | if (salt == NULL || salt->s == NULL) { 93 | uint8_t zeroes_data[32]; 94 | TSM_STR zeroes; 95 | 96 | memset(zeroes_data, 0, sizeof(zeroes_data)); 97 | zeroes.s = zeroes_data; 98 | zeroes.length = sizeof(zeroes_data); 99 | 100 | return oscore_hmac_hash(hmac_alg, &zeroes, ikm, hkdf_extract); 101 | } else { 102 | return oscore_hmac_hash(hmac_alg, salt, ikm, hkdf_extract); 103 | } 104 | } 105 | 106 | static int oscore_hkdf_expand(cose_hkdf_alg_t hkdf_alg, 107 | TSM_STR *prk, 108 | uint8_t *info, 109 | size_t info_len, 110 | uint8_t *okm, 111 | size_t okm_len) 112 | { 113 | int ret; 114 | size_t N = (okm_len + 32 - 1) / 32; /* ceil(okm_len/32) */ 115 | uint8_t *aggregate_buffer = tsm_alloc(32 + info_len + 1); 116 | uint8_t *out_buffer = tsm_alloc((N + 1) * 32); /* 32 extra bytes to fit the last block */ 117 | size_t i; 118 | TSM_STR data; 119 | TSM_STR *hkdf = NULL; 120 | int hmac_alg; 121 | 122 | if ((ret = tsm_cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg)) != TSM_OK) 123 | goto fail; 124 | /* Compose T(1) */ 125 | memcpy(aggregate_buffer, info, info_len); 126 | aggregate_buffer[info_len] = 0x01; 127 | 128 | data.s = aggregate_buffer; 129 | data.length = info_len + 1; 130 | if ((ret = oscore_hmac_hash(hmac_alg, prk, &data, &hkdf)) != TSM_OK) 131 | goto fail; 132 | memcpy(&out_buffer[0], hkdf->s, hkdf->length); 133 | tsm_str_free(hkdf); 134 | 135 | /* Compose T(2) -> T(N) */ 136 | memcpy(aggregate_buffer, &(out_buffer[0]), 32); 137 | for (i = 1; i < N; i++) { 138 | memcpy(&(aggregate_buffer[32]), info, info_len); 139 | aggregate_buffer[32 + info_len] = (uint8_t)(i + 1); 140 | data.s = aggregate_buffer; 141 | data.length = 32 + info_len + 1; 142 | if ((ret = oscore_hmac_hash(hmac_alg, prk, &data, &hkdf)) != TSM_OK) 143 | goto fail; 144 | memcpy(&out_buffer[i * 32], hkdf->s, hkdf->length); 145 | tsm_str_free(hkdf); 146 | memcpy(aggregate_buffer, &(out_buffer[i * 32]), 32); 147 | } 148 | memcpy(okm, out_buffer, okm_len); 149 | tsm_free(out_buffer); 150 | tsm_free(aggregate_buffer); 151 | return TSM_OK; 152 | 153 | fail: 154 | tsm_free(out_buffer); 155 | tsm_free(aggregate_buffer); 156 | return ret; 157 | } 158 | 159 | int oscore_hkdf(cose_hkdf_alg_t hkdf_alg, 160 | TSM_STR *salt, 161 | TSM_STR *ikm, 162 | uint8_t *info, 163 | size_t info_len, 164 | uint8_t *okm, 165 | size_t okm_len) 166 | { 167 | int ret; 168 | TSM_STR *hkdf_extract = NULL; 169 | if ((ret = oscore_hkdf_extract(hkdf_alg, salt, ikm, &hkdf_extract)) != TSM_OK) 170 | return ret; 171 | ret = oscore_hkdf_expand(hkdf_alg, hkdf_extract, info, info_len, okm, okm_len); 172 | tsm_str_free(hkdf_extract); 173 | return ret; 174 | } 175 | -------------------------------------------------------------------------------- /include/tongsuo/oscore_cbor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore_cbor.h 33 | * @brief An implementation of the Concise Binary Object Representation (RFC). 34 | * 35 | * \author 36 | * Martin Gunnarsson 37 | * extended for libcoap by: 38 | * Peter van der Stok 39 | * on request of Fairhair alliance 40 | * adapted for libcoap integration 41 | * Jon Shallow 42 | * adapted for Tongsuo-mini integration 43 | * K1 44 | */ 45 | 46 | #if !defined(TSM_OSCORE_CBOR_H) 47 | # define TSM_OSCORE_CBOR_H 48 | # pragma once 49 | 50 | # ifdef __cplusplus 51 | extern "C" { 52 | # endif 53 | 54 | # include 55 | # include 56 | 57 | /* CBOR major types */ 58 | # define CBOR_UNSIGNED_INTEGER 0 59 | # define CBOR_NEGATIVE_INTEGER 1 60 | # define CBOR_BYTE_STRING 2 61 | # define CBOR_TEXT_STRING 3 62 | # define CBOR_ARRAY 4 63 | # define CBOR_MAP 5 64 | # define CBOR_TAG 6 65 | # define CBOR_SIMPLE_VALUE 7 66 | # define CBOR_FLOATING_POINT 7 67 | 68 | # define CBOR_FALSE 20 69 | # define CBOR_TRUE 21 70 | # define CBOR_NULL 22 71 | 72 | /* Write a CBOR nil to the buffer. Returns the number of bytes written. */ 73 | size_t tsm_oscore_cbor_put_nil(uint8_t **buffer, size_t *buf_size); 74 | /* Write a CBOR true to the buffer. Returns the number of bytes written. */ 75 | size_t tsm_oscore_cbor_put_true(uint8_t **buffer, size_t *buf_size); 76 | /* Write a CBOR false to the buffer. Returns the number of bytes written. */ 77 | size_t tsm_oscore_cbor_put_false(uint8_t **buffer, size_t *buf_size); 78 | /* Write CBOR text with length text_len to the buffer. Returns the number of bytes written. */ 79 | size_t tsm_oscore_cbor_put_text(uint8_t **buffer, size_t *buf_size, const char *text, 80 | size_t text_len); 81 | /* Write CBOR array with elements size to the buffer. Returns the number of bytes written. */ 82 | size_t tsm_oscore_cbor_put_array(uint8_t **buffer, size_t *buf_size, size_t elements); 83 | /* Write CBOR bytes with length bytes_len to the buffer. Returns the number of bytes written. */ 84 | size_t tsm_oscore_cbor_put_bytes(uint8_t **buffer, size_t *buf_size, const uint8_t *bytes, 85 | size_t bytes_len); 86 | /* Write CBOR map with elements size to the buffer. Returns the number of bytes written. */ 87 | size_t tsm_oscore_cbor_put_map(uint8_t **buffer, size_t *buf_size, size_t elements); 88 | /* Write CBOR integer to the buffer. Returns the number of bytes written. 89 | */ 90 | size_t tsm_oscore_cbor_put_number(uint8_t **buffer, size_t *buf_size, int64_t value); 91 | /* Write CBOR simple value to the buffer. Returns the number of bytes written. */ 92 | size_t tsm_oscore_cbor_put_simple_value(uint8_t **buffer, size_t *buf_size, uint8_t value); 93 | /* Write CBOR unsigned integer to the buffer. Returns the number of bytes written. */ 94 | size_t tsm_oscore_cbor_put_unsigned(uint8_t **buffer, size_t *buf_size, uint64_t value); 95 | /* Write CBOR tag to the buffer. Returns the number of bytes written. */ 96 | size_t tsm_oscore_cbor_put_tag(uint8_t **buffer, size_t *buf_size, uint64_t value); 97 | /* Write CBOR negative integer to the buffer. Returns the number of bytes written. */ 98 | size_t tsm_oscore_cbor_put_negative(uint8_t **buffer, size_t *buf_size, int64_t value); 99 | /* Get the type of the next CBOR element in the buffer. */ 100 | uint8_t tsm_oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_size); 101 | /* Get the size of the next CBOR element in the buffer. */ 102 | size_t tsm_oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size); 103 | /* Test if the data buffer contaions a complete element. */ 104 | uint8_t tsm_oscore_cbor_elem_contained(const uint8_t *data, size_t *buf_size, uint8_t *end); 105 | /* Gets a negative or positive number from data. Returns TSM_OK means success, otherwise returns 106 | * a specific error code. */ 107 | int tsm_oscore_cbor_get_number(const uint8_t **data, size_t *buf_size, int64_t *value); 108 | /* Gets a simple value from data; returns TSM_OK means success, otherwise returns a specific error 109 | * code.otherwise returns a specific error code. */ 110 | int tsm_oscore_cbor_get_simple_value(const uint8_t **data, size_t *buf_size, uint8_t *value); 111 | /* Gets a negative integer from buffer. */ 112 | int64_t tsm_oscore_cbor_get_negative_integer(const uint8_t **buffer, size_t *buf_size); 113 | /* Gets an unsigned integer from buffer. */ 114 | uint64_t tsm_oscore_cbor_get_unsigned_integer(const uint8_t **buffer, size_t *buf_size); 115 | /* Gets a CBOR string with length size from buffer. */ 116 | void tsm_oscore_cbor_get_string(const uint8_t **buffer, size_t *buf_size, char *str, size_t size); 117 | /* Gets a CBOR array with length size from buffer. */ 118 | void tsm_oscore_cbor_get_array(const uint8_t **buffer, size_t *buf_size, uint8_t *arr, size_t size); 119 | 120 | /* Gets a string array and fills the result. The length of result is written to len. result is 121 | * allocated by tsm_alloc(), should be freed by calling tsm_free() after use. Returns TSM_OK for 122 | * success and others for failure. */ 123 | int tsm_oscore_cbor_get_string_array(const uint8_t **data, size_t *buf_size, uint8_t **result, 124 | size_t *len); 125 | /* Strips the value of the cbor element into result and writes size in len. result is allocated by 126 | * tsm_alloc(), should be freed by calling tsm_free() after use. Returns TSM_OK for success and 127 | * others for failure. */ 128 | int tsm_oscore_cbor_strip_value(const uint8_t **data, size_t *buf_size, uint8_t **result, 129 | size_t *len); 130 | # ifdef __cplusplus 131 | } 132 | # endif 133 | #endif 134 | -------------------------------------------------------------------------------- /perf/perf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt 8 | */ 9 | 10 | /* 11 | * Performance test for various algorithms on xxx times 1MB random data, in avg. 12 | * Detailed performance indices: 13 | * SM3: hash(Mbps) 14 | * ASCON-Hash: Hash (in Mbps) 15 | * SM4: CBC Encrypt, CBC Decrypt (in Mbps) 16 | * ASCON-AEAD: Encrypt, Decrypt (in Mbps) 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | static long long get_time(void); 31 | 32 | /* iteration number, could be adjusted as required */ 33 | #define ITR_NUM 1000 * 1000 34 | #define RND_DATA_SIZE 1024 35 | 36 | /* time difference on each index */ 37 | struct perf_index { 38 | int sm3_hash; 39 | int ascon_hash; 40 | int sm4_cbc_enc; 41 | int sm4_cbc_dec; 42 | int ascon_aead_enc; 43 | int ascon_aead_dec; 44 | }; 45 | 46 | /* final result in Mbps */ 47 | struct perf_result { 48 | long long sm3_hash_avg; 49 | long long ascon_hash_avg; 50 | long long sm4_cbc_enc_avg; 51 | long long sm4_cbc_dec_avg; 52 | long long ascon_aead_enc_avg; 53 | long long ascon_aead_dec_avg; 54 | }; 55 | 56 | static long long get_time(void) 57 | { 58 | /* just using gettimeofday() is adequate for our case */ 59 | struct timeval tp; 60 | 61 | if (gettimeofday(&tp, NULL) != 0) 62 | return 0; 63 | else 64 | return (long long)(tp.tv_sec * 1000 * 1000 + tp.tv_usec); 65 | } 66 | 67 | int main(void) 68 | { 69 | int ret = 1; 70 | struct perf_index *indices = NULL; 71 | struct perf_result result; 72 | int i = 0; 73 | unsigned char *rnd_data = NULL; 74 | long long start = 0, end = 0; 75 | unsigned char *out = NULL, *out2 = NULL; 76 | size_t outlen = 0, out2len = 0, inlen = RND_DATA_SIZE; 77 | unsigned char sm3_md[TSM_SM3_DIGEST_LEN]; 78 | unsigned char ascon_md[TSM_ASCON_HASH_LEN]; 79 | size_t mdlen = 0; 80 | unsigned char key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 81 | 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; 82 | unsigned char iv[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 83 | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; 84 | unsigned char ad[] = "performance test program"; 85 | 86 | memset(&result, 0, sizeof(result)); 87 | indices = tsm_alloc(sizeof(struct perf_index) * ITR_NUM); 88 | if (indices == NULL) { 89 | fprintf(stderr, "malloc error - indices\n"); 90 | return -1; 91 | } 92 | memset(indices, 0, sizeof(struct perf_index) * ITR_NUM); 93 | 94 | out = tsm_alloc(inlen * 2); 95 | if (out == NULL) { 96 | goto err; 97 | } 98 | 99 | out2 = tsm_alloc(inlen * 2); 100 | if (out2 == NULL) { 101 | goto err; 102 | } 103 | 104 | for (; i < ITR_NUM; i++) { 105 | rnd_data = tsm_alloc(inlen); 106 | if (rnd_data == NULL) { 107 | goto err; 108 | } 109 | 110 | /* SM3 hash */ 111 | start = get_time(); 112 | if (tsm_sm3_oneshot(rnd_data, inlen, sm3_md) != TSM_OK) { 113 | goto err; 114 | } 115 | end = get_time(); 116 | indices[i].sm3_hash = 1000 * 1000 * 8 / (end - start); 117 | 118 | /* ASCON hash */ 119 | start = get_time(); 120 | if (tsm_ascon_hash_oneshot(TSM_HASH_ASCON_HASH, rnd_data, inlen, ascon_md, &mdlen) 121 | != TSM_OK) { 122 | goto err; 123 | } 124 | end = get_time(); 125 | indices[i].ascon_hash = 1000 * 1000 * 8 / (end - start); 126 | 127 | /* SM4 CBC encrypt */ 128 | start = get_time(); 129 | if (tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, key, iv, rnd_data, inlen, out, &outlen, 130 | TSM_CIPH_FLAG_ENCRYPT) 131 | != TSM_OK) { 132 | goto err; 133 | } 134 | end = get_time(); 135 | indices[i].sm4_cbc_enc = 1000 * 1000 * 8 / (end - start); 136 | 137 | /* SM4 CBC decrypt */ 138 | start = get_time(); 139 | if (tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, key, iv, out, outlen, out2, &out2len, 140 | TSM_CIPH_FLAG_DECRYPT) 141 | != TSM_OK) { 142 | goto err; 143 | } 144 | end = get_time(); 145 | indices[i].sm4_cbc_dec = 1000 * 1000 * 8 / (end - start); 146 | 147 | /* ASCON aead encrypt */ 148 | start = get_time(); 149 | if (tsm_ascon_aead_oneshot(TSM_ASCON_AEAD_128, key, iv, ad, sizeof(ad), rnd_data, inlen, 150 | out, &outlen, TSM_CIPH_FLAG_ENCRYPT) 151 | != TSM_OK) { 152 | goto err; 153 | } 154 | end = get_time(); 155 | indices[i].ascon_aead_enc = 1000 * 1000 * 8 / (end - start); 156 | 157 | /* ASCON aead decrypt */ 158 | start = get_time(); 159 | if (tsm_ascon_aead_oneshot(TSM_ASCON_AEAD_128, key, iv, ad, sizeof(ad), out, outlen, out2, 160 | &out2len, TSM_CIPH_FLAG_DECRYPT) 161 | != TSM_OK) { 162 | goto err; 163 | } 164 | end = get_time(); 165 | indices[i].ascon_aead_dec = 1000 * 1000 * 8 / (end - start); 166 | #if 0 167 | fprintf(stdout, "sm3-hash: %d, " 168 | "ascon-hash: %d, " 169 | "sm4-cbc-enc: %d, " 170 | "sm4-cbc-dec: %d, " 171 | "ascon-aead-enc: %d, " 172 | "ascon-aead-dec: %d\n", 173 | indices[i].sm3_hash, indices[i].ascon_hash, 174 | indices[i].sm4_cbc_enc, indices[i].sm4_cbc_dec, 175 | indices[i].ascon_aead_enc, indices[i].ascon_aead_dec); 176 | #endif 177 | } 178 | 179 | /* calculate the final average result */ 180 | for (i = 0; i < ITR_NUM; i++) { 181 | result.sm3_hash_avg += indices[i].sm3_hash; 182 | result.ascon_hash_avg += indices[i].ascon_hash; 183 | result.sm4_cbc_enc_avg += indices[i].sm4_cbc_enc; 184 | result.sm4_cbc_dec_avg += indices[i].sm4_cbc_dec; 185 | result.ascon_aead_enc_avg += indices[i].ascon_aead_enc; 186 | result.ascon_aead_dec_avg += indices[i].ascon_aead_dec; 187 | } 188 | 189 | result.sm3_hash_avg /= ITR_NUM; 190 | result.ascon_hash_avg /= ITR_NUM; 191 | result.sm4_cbc_dec_avg /= ITR_NUM; 192 | result.sm4_cbc_enc_avg /= ITR_NUM; 193 | result.ascon_aead_enc_avg /= ITR_NUM; 194 | result.ascon_aead_dec_avg /= ITR_NUM; 195 | 196 | fprintf(stdout, 197 | "Final result:\n" 198 | "sm3-hash: %lld kbps\n" 199 | "ascon-hash: %lld kbps\n" 200 | "sm4-cbc-enc: %lld kbps\n" 201 | "sm4-cbc-dec: %lld kbps\n" 202 | "ascon-aead-enc: %lld kbps\n" 203 | "ascon-aead-dec: %lld kbps\n", 204 | result.sm3_hash_avg, result.ascon_hash_avg, result.sm4_cbc_enc_avg, 205 | result.sm4_cbc_dec_avg, result.ascon_aead_enc_avg, result.ascon_aead_dec_avg); 206 | 207 | ret = 0; 208 | err: 209 | 210 | tsm_free(out); 211 | tsm_free(out2); 212 | tsm_free(indices); 213 | tsm_free(rnd_data); 214 | 215 | return ret; 216 | } 217 | -------------------------------------------------------------------------------- /include/tongsuo/oscore_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore_context.h 33 | * @brief An implementation of the Object Security for Constrained RESTful 34 | * Enviornments (RFC 8613). 35 | * 36 | * \author 37 | * Martin Gunnarsson 38 | * adapted to libcoap; added group communication 39 | * Peter van der Stok 40 | * on request of Fairhair alliance 41 | * adapted for libcoap integration 42 | * Jon Shallow 43 | * adapted for Tongsuo-mini integration 44 | * K1 45 | */ 46 | 47 | #if !defined(TSM_OSCORE_CONTEXT_H) 48 | # define TSM_OSCORE_CONTEXT_H 49 | # pragma once 50 | 51 | # ifdef __cplusplus 52 | extern "C" { 53 | # endif 54 | 55 | # include 56 | # include 57 | # include 58 | 59 | /* AES-256 */ 60 | # define CONTEXT_MAX_KEY_LEN 32 61 | 62 | # define OSCORE_SEQ_MAX (((uint64_t)1 << 40) - 1) 63 | 64 | typedef enum oscore_mode_e { 65 | OSCORE_MODE_SINGLE = 0, /* Vanilla RFC8613 support */ 66 | OSCORE_MODE_GROUP, /* TODO draft-ietf-core-oscore-groupcomm */ 67 | OSCORE_MODE_PAIRWISE /* TODO draft-ietf-core-oscore-groupcomm */ 68 | } oscore_mode_t; 69 | 70 | typedef struct oscore_ctx_s oscore_ctx_t; 71 | typedef struct oscore_sender_ctx_s oscore_sender_ctx_t; 72 | typedef struct oscore_recipient_ctx_s oscore_recipient_ctx_t; 73 | typedef struct oscore_association_s oscore_association_t; 74 | typedef struct tsm_oscore_conf_s TSM_OSCORE_CONF; 75 | 76 | typedef int (*tsm_oscore_save_seq_num_t)(uint64_t sender_seq_num, void *param); 77 | 78 | struct tsm_oscore_conf_s { 79 | TSM_STR *master_secret; /* Common Master Secret */ 80 | TSM_STR *master_salt; /* Common Master Salt */ 81 | TSM_STR *sender_id; /* Sender ID (i.e. local our id) */ 82 | TSM_STR *id_context; /* Common ID context */ 83 | TSM_STR **recipient_id; /* Recipient ID (i.e. remote peer id) 84 | Array of recipient_id */ 85 | uint32_t recipient_id_count; /* Number of recipient_id entries */ 86 | uint32_t replay_window; /* Replay window size 87 | Use COAP_OSCORE_DEFAULT_REPLAY_WINDOW */ 88 | uint32_t ssn_freq; /* Sender Seq Num update frequency */ 89 | cose_alg_t aead_alg; /* Set to one of COSE_ALGORITHM_AES* */ 90 | cose_hkdf_alg_t hkdf_alg; /* Set to one of COSE_HKDF_ALG_* */ 91 | uint32_t rfc8613_b_1_2; /* 1 if rfc8613 B.1.2 enabled else 0 */ 92 | uint32_t rfc8613_b_2; /* 1 if rfc8613 B.2 protocol else 0 */ 93 | /* General Testing */ 94 | uint32_t break_sender_key; /* 1 if sender key to be broken, else 0 */ 95 | uint32_t break_recipient_key; /* 1 if recipient key to be broken, else 0 */ 96 | /* SSN handling (not in oscore_config[]) */ 97 | tsm_oscore_save_seq_num_t save_seq_num_func; /* Called every seq num 98 | change */ 99 | void *save_seq_num_func_param; /* Passed to save_seq_num_func() */ 100 | uint64_t start_seq_num; /* Used for ssn_freq updating */ 101 | }; 102 | 103 | struct oscore_ctx_s { 104 | struct oscore_ctx_s *next; 105 | TSM_STR *master_secret; 106 | TSM_STR *master_salt; 107 | TSM_STR *common_iv; /* Derived from Master Secret, 108 | Master Salt, and ID Context */ 109 | TSM_STR *id_context; /* contains GID in case of group */ 110 | oscore_sender_ctx_t *sender_context; 111 | oscore_recipient_ctx_t *recipient_chain; 112 | cose_alg_t aead_alg; 113 | cose_hkdf_alg_t hkdf_alg; 114 | oscore_mode_t mode; 115 | uint8_t rfc8613_b_1_2; /* 1 if rfc8613 B.1.2 enabled else 0 */ 116 | uint8_t rfc8613_b_2; /* 1 if rfc8613 B.2 protocol else 0 */ 117 | uint32_t ssn_freq; /* Sender Seq Num update frequency */ 118 | uint32_t replay_window_size; 119 | tsm_oscore_save_seq_num_t save_seq_num_func; /* Called every seq num 120 | change */ 121 | void *save_seq_num_func_param; /* Passed to save_seq_num_func() */ 122 | }; 123 | 124 | struct oscore_sender_ctx_s { 125 | uint64_t seq; 126 | uint64_t next_seq; /* Used for ssn_freq updating */ 127 | TSM_STR *sender_key; 128 | TSM_STR *sender_id; 129 | }; 130 | 131 | struct oscore_recipient_ctx_s { 132 | oscore_recipient_ctx_t *next_recipient; /* This field allows recipient chaining */ 133 | oscore_ctx_t *osc_ctx; 134 | uint64_t last_seq; 135 | uint64_t sliding_window; 136 | uint64_t rollback_sliding_window; 137 | uint64_t rollback_last_seq; 138 | TSM_STR *recipient_key; 139 | TSM_STR *recipient_id; 140 | uint8_t echo_value[8]; 141 | uint8_t initial_state; 142 | }; 143 | 144 | struct oscore_association_s { 145 | /* FIXME: change link list to hash table */ 146 | struct oscore_association_s *next; 147 | oscore_recipient_ctx_t *recipient_ctx; 148 | void *sent_pdu; 149 | TSM_STR *token; 150 | TSM_STR *aad; 151 | TSM_STR *nonce; 152 | TSM_STR *partial_iv; 153 | uint64_t last_seen; 154 | uint8_t is_observe; 155 | }; 156 | 157 | /* Create a new context of oscore, based on oscore_conf. The context should be freed by calling 158 | * tsm_oscore_ctx_free() after use. */ 159 | oscore_ctx_t *tsm_oscore_ctx_new(TSM_OSCORE_CONF *oscore_conf); 160 | /* Frees up the context osc_ctx of oscore. */ 161 | void tsm_oscore_ctx_free(oscore_ctx_t *osc_ctx); 162 | /* Duplicates the context o_osc_ctx of oscore with sender_id, recipient_id and id_context. The 163 | * context should be freed by calling tsm_oscore_ctx_free() after use. */ 164 | oscore_ctx_t *tsm_oscore_ctx_dup(oscore_ctx_t *o_osc_ctx, 165 | TSM_STR *sender_id, 166 | TSM_STR *recipient_id, 167 | TSM_STR *id_context); 168 | /* Updates the id context within osc_ctx with id_context. */ 169 | void tsm_oscore_ctx_update(oscore_ctx_t *osc_ctx, TSM_STR *id_context); 170 | /* Adds a new recipient to osc_ctx with recipient id rid. break_key is intended for testing. Returns 171 | * recipient context on success, otherwise returns NULL. */ 172 | oscore_recipient_ctx_t *tsm_oscore_add_recipient(oscore_ctx_t *osc_ctx, TSM_STR *rid, 173 | uint32_t break_key); 174 | /* Deletes the recipient with recipient id rid within osc_ctx. If found and deleted successfully, 175 | * TSM_OK is returned. */ 176 | int tsm_oscore_delete_recipient(oscore_ctx_t *osc_ctx, TSM_STR *rid); 177 | /* Log tsm_str in hex format. */ 178 | void tsm_oscore_log_hex_value(int level, const char *name, TSM_STR *value); 179 | /* Log C str. */ 180 | void tsm_oscore_log_char_value(int level, const char *name, const char *value); 181 | /* Finds recipient within osc_ctc. If recipient id in rcpkey_id is not empty, the id is used as a 182 | * key. If oscore_r2 is not NULL, oscore_r2 is compared to id context within osc_ctx. If ctxkey_id 183 | * is not NULL, ctxkey_id is compared to id context within osc_ctx. If found, the recipient context 184 | * is returned, otherwise NULL is returned. */ 185 | oscore_recipient_ctx_t *tsm_oscore_find_recipient(const oscore_ctx_t *osc_ctx, 186 | const TSM_STR *rcpkey_id, 187 | const TSM_STR *ctxkey_id, 188 | uint8_t *oscore_r2); 189 | /* Create new association with token, recipient context, aad, nonce, partial iv. The returned 190 | * association should be freed by calling tsm_oscore_association_free() after use. */ 191 | oscore_association_t *tsm_oscore_association_new(TSM_STR *token, 192 | oscore_recipient_ctx_t *recipient_ctx, 193 | TSM_STR *aad, 194 | TSM_STR *nonce, 195 | TSM_STR *partial_iv, 196 | int is_observe); 197 | /* Frees up the association association. */ 198 | void tsm_oscore_association_free(oscore_association_t *association); 199 | /* Finds a association within chain with token. If found, the association is returned, otherwise 200 | * NULL is returned. */ 201 | oscore_association_t *tsm_oscore_association_find(oscore_association_t *chain, TSM_STR *token); 202 | /* Deletes the association on chain. */ 203 | void tsm_oscore_association_delete(oscore_association_t **chain, oscore_association_t *association); 204 | /* Deletes all associations on chain by calling free_func. */ 205 | void tsm_oscore_association_free_all(oscore_association_t *chain, 206 | void (*free_func)(oscore_association_t *)); 207 | # ifdef __cplusplus 208 | } 209 | # endif 210 | #endif 211 | -------------------------------------------------------------------------------- /src/asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE 8 | */ 9 | 10 | /* 11 | * ASN.1 DER编解码函数, Tag || Length || Value 12 | * 返回0表示成功,非0表示失败 13 | * 输出参数:outl,追加输出缓存区写入的长度 14 | */ 15 | 16 | #include "internal/asn1.h" 17 | #include "internal/log.h" 18 | #include 19 | #include 20 | #include 21 | 22 | int asn1_encode_header_tag(unsigned char **out, size_t *outl, int tag) 23 | { 24 | if (out && *out) { 25 | **out = tag; 26 | (*out)++; 27 | } 28 | 29 | *outl += 1; 30 | 31 | return 0; 32 | } 33 | 34 | int asn1_decode_header_tag(unsigned char **in, size_t inlen, int *tag) 35 | { 36 | if (inlen < 1) 37 | return TSM_ERR_OUT_OF_DATA; 38 | 39 | *tag = **in; 40 | (*in)++; 41 | 42 | return 0; 43 | } 44 | 45 | int asn1_encode_header_len(unsigned char **out, size_t *outl, size_t len) 46 | { 47 | int n = 0; 48 | 49 | if (len < 0x80) { 50 | if (out && *out) { 51 | **out = len; 52 | (*out)++; 53 | } 54 | 55 | *outl += 1; 56 | return 0; 57 | } 58 | 59 | while (len) { 60 | n++; 61 | len >>= 8; 62 | } 63 | 64 | if (n > 4) 65 | return TSM_ERR_INTERNAL_ERROR; 66 | 67 | *outl += n + 1; 68 | 69 | if (out && *out) { 70 | **out = 0x80 | n; 71 | (*out)++; 72 | while (n--) { 73 | **out = len >> (n * 8); 74 | (*out)++; 75 | } 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | int asn1_decode_header_len(unsigned char **in, size_t inlen, size_t *len) 82 | { 83 | unsigned char *end = *in + inlen; 84 | 85 | if (inlen < 1) 86 | return TSM_ERR_OUT_OF_DATA; 87 | 88 | if ((**in & 0x80) == 0) { 89 | *len = *(*in)++; 90 | } else { 91 | switch (**in & 0x7F) { 92 | case 1: 93 | if (inlen < 2) 94 | return TSM_ERR_OUT_OF_DATA; 95 | 96 | *len = (*in)[1]; 97 | (*in) += 2; 98 | break; 99 | 100 | case 2: 101 | if (inlen < 3) 102 | return TSM_ERR_OUT_OF_DATA; 103 | 104 | *len = ((size_t)(*in)[1] << 8) | (*in)[2]; 105 | (*in) += 3; 106 | break; 107 | 108 | case 3: 109 | if (inlen < 4) 110 | return TSM_ERR_OUT_OF_DATA; 111 | 112 | *len = ((size_t)(*in)[1] << 16) | ((size_t)(*in)[2] << 8) | (*in)[3]; 113 | (*in) += 4; 114 | break; 115 | 116 | case 4: 117 | if (inlen < 5) 118 | return TSM_ERR_OUT_OF_DATA; 119 | 120 | *len = ((size_t)(*in)[1] << 24) | ((size_t)(*in)[2] << 16) | ((size_t)(*in)[3] << 8) 121 | | (*in)[4]; 122 | (*in) += 5; 123 | break; 124 | 125 | default: 126 | return TSM_ERR_INVALID_ASN1_LENGTH; 127 | } 128 | } 129 | 130 | if (*len > (size_t)(end - *in)) 131 | return TSM_ERR_OUT_OF_DATA; 132 | 133 | return 0; 134 | } 135 | 136 | int asn1_encode_header(unsigned char **out, size_t *outl, int tag, size_t len) 137 | { 138 | int err; 139 | 140 | if ((err = asn1_encode_header_tag(out, outl, tag)) != 0 141 | || (err = asn1_encode_header_len(out, outl, len)) != 0) 142 | return err; 143 | 144 | return 0; 145 | } 146 | 147 | int asn1_decode_header(unsigned char **in, size_t inlen, int tag, size_t *len) 148 | { 149 | int t; 150 | 151 | if (asn1_decode_header_tag(in, inlen, &t) || t != tag) 152 | return TSM_ERR_UNEXPECTED_ASN1_TAG; 153 | 154 | if (len) 155 | return asn1_decode_header_len(in, inlen - 1, len); 156 | 157 | return 0; 158 | } 159 | 160 | int asn1_encode_bool(unsigned char **out, size_t *outl, int val) 161 | { 162 | int err; 163 | 164 | if ((err = asn1_encode_header(out, outl, TONGSUO_ASN1_BOOLEAN, 1)) != 0) 165 | return err; 166 | 167 | if (out && *out) { 168 | **out = (val == 0) ? 0x00 : 0xFF; 169 | (*out)++; 170 | } 171 | 172 | *outl += 1; 173 | return 0; 174 | } 175 | 176 | int asn1_decode_bool(unsigned char **in, size_t inlen, int *val) 177 | { 178 | size_t len; 179 | 180 | if (asn1_decode_header(in, inlen, TONGSUO_ASN1_BOOLEAN, &len) || len != 1) 181 | return TSM_ERR_INVALID_ASN1_LENGTH; 182 | 183 | *val = (**in == 0xFF) ? 1 : 0; 184 | (*in)++; 185 | 186 | return 0; 187 | } 188 | 189 | static int asn1_encode_tag_int(unsigned char **out, size_t *outl, int tag, int val) 190 | { 191 | unsigned char buf[sizeof(int) + 1]; 192 | int err, len; 193 | 194 | if (val < 0) 195 | return TSM_ERR_INVALID_ASN1_VALUE; 196 | 197 | len = 0; 198 | do { 199 | buf[len++] = val & 0xFF; 200 | val >>= 8; 201 | } while (val > 0); 202 | 203 | if (buf[len - 1] & 0x80) 204 | buf[len++] = 0; 205 | 206 | if ((err = asn1_encode_header(out, outl, tag, len)) != 0) 207 | return err; 208 | 209 | *outl += len; 210 | 211 | if (out && *out) { 212 | while (len--) 213 | *(*out)++ = buf[len]; 214 | } 215 | 216 | return 0; 217 | } 218 | 219 | int asn1_encode_int(unsigned char **out, size_t *outl, int val) 220 | { 221 | return asn1_encode_tag_int(out, outl, TONGSUO_ASN1_INTEGER, val); 222 | } 223 | 224 | int asn1_encode_enum(unsigned char **out, size_t *outl, int val) 225 | { 226 | return asn1_encode_tag_int(out, outl, TONGSUO_ASN1_ENUMERATED, val); 227 | } 228 | 229 | int asn1_decode_tag_int(unsigned char **in, size_t inlen, int tag, int *val) 230 | { 231 | if (in == NULL || *in == NULL || val == NULL) 232 | return eLOG(TSM_ERR_PASS_NULL_PARAM); 233 | 234 | int err; 235 | size_t len; 236 | 237 | if ((err = asn1_decode_header(in, inlen, tag, &len)) != 0) 238 | return err; 239 | 240 | /* 241 | * len==0 is malformed (0 must be represented as 020100 for INTEGER, 242 | * or 0A0100 for ENUMERATED tags 243 | */ 244 | if (len == 0) 245 | return TSM_ERR_INVALID_ASN1_LENGTH; 246 | 247 | /* Reject negative integer */ 248 | if ((**in & 0x80) != 0) 249 | return TSM_ERR_INVALID_ASN1_LENGTH; 250 | 251 | /* Skip leading zeros. */ 252 | while (len > 0 && **in == 0) { 253 | ++(*in); 254 | --len; 255 | } 256 | 257 | /* Reject integers that don't fit in an int. This code assumes that 258 | * the int type has no padding bit. */ 259 | if (len > sizeof(int)) 260 | return TSM_ERR_INVALID_ASN1_LENGTH; 261 | 262 | if (len == sizeof(int) && (**in & 0x80) != 0) 263 | return TSM_ERR_INVALID_ASN1_LENGTH; 264 | 265 | *val = 0; 266 | while (len-- > 0) { 267 | *val = (*val << 8) | **in; 268 | (*in)++; 269 | } 270 | 271 | return 0; 272 | } 273 | 274 | int asn1_decode_int(unsigned char **in, size_t inlen, int *val) 275 | { 276 | return asn1_decode_tag_int(in, inlen, TONGSUO_ASN1_INTEGER, val); 277 | } 278 | 279 | int asn1_decode_enum(unsigned char **in, size_t inlen, int *val) 280 | { 281 | return asn1_decode_tag_int(in, inlen, TONGSUO_ASN1_ENUMERATED, val); 282 | } 283 | 284 | int asn1_encode_bit_string(unsigned char **out, size_t *outl, const unsigned char *bs, size_t nbits) 285 | { 286 | size_t len, padding; 287 | int err; 288 | 289 | len = 1 + (nbits + 7) / 8; 290 | padding = nbits % 8; 291 | 292 | if ((err = asn1_encode_header(out, outl, TONGSUO_ASN1_BIT_STRING, len)) != 0) 293 | return err; 294 | 295 | *outl += len; 296 | 297 | if (out && *out) { 298 | *(*out)++ = padding; 299 | memcpy(*out, bs, len - 1); 300 | *out += len - 1; 301 | } 302 | 303 | return 0; 304 | } 305 | 306 | int asn1_decode_bit_string(unsigned char **in, size_t inlen, unsigned char *bs, size_t *nbits) 307 | { 308 | size_t len, padding; 309 | int err; 310 | 311 | if ((err = asn1_decode_header(in, inlen, TONGSUO_ASN1_BIT_STRING, &len)) != 0) 312 | return err; 313 | 314 | if (len < 1) 315 | return TSM_ERR_INVALID_ASN1_LENGTH; 316 | 317 | padding = **in; 318 | if (padding > 7) 319 | return TSM_ERR_INVALID_ASN1_VALUE; 320 | 321 | len -= 1; 322 | (*in)++; 323 | 324 | *in += len; 325 | if (bs) 326 | memcpy(bs, *in, len); 327 | 328 | *nbits = len * 8 - padding; 329 | 330 | return 0; 331 | } 332 | 333 | int asn1_encode_null(unsigned char **out, size_t *outl) 334 | { 335 | int err; 336 | 337 | if ((err = asn1_encode_header(out, outl, TONGSUO_ASN1_NULL, 0)) != 0) 338 | return err; 339 | 340 | return 0; 341 | } 342 | 343 | int asn1_decode_null(unsigned char **in, size_t inlen) 344 | { 345 | size_t len; 346 | 347 | if (asn1_decode_header(in, inlen, TONGSUO_ASN1_NULL, &len) || len != 0) 348 | return TSM_ERR_INVALID_ASN1_LENGTH; 349 | 350 | return 0; 351 | } 352 | 353 | static int asn1_encode_tag_string(unsigned char **out, size_t *outl, int tag, 354 | const unsigned char *buf, size_t buflen) 355 | { 356 | int err; 357 | 358 | if ((err = asn1_encode_header(out, outl, tag, buflen)) != 0) 359 | return err; 360 | 361 | *outl += buflen; 362 | 363 | if (out && *out) { 364 | memcpy(*out, buf, buflen); 365 | *out += buflen; 366 | } 367 | 368 | return 0; 369 | } 370 | 371 | int asn1_encode_octet_string(unsigned char **out, size_t *outl, const unsigned char *buf, 372 | size_t buflen) 373 | { 374 | return asn1_encode_tag_string(out, outl, TONGSUO_ASN1_OCTET_STRING, buf, buflen); 375 | } 376 | 377 | int asn1_encode_printable_string(unsigned char **out, size_t *outl, const unsigned char *buf, 378 | size_t buflen) 379 | { 380 | return asn1_encode_tag_string(out, outl, TONGSUO_ASN1_PRINTABLE_STRING, buf, buflen); 381 | } 382 | 383 | int asn1_encode_ia5_string(unsigned char **out, size_t *outl, const unsigned char *buf, 384 | size_t buflen) 385 | { 386 | return asn1_encode_tag_string(out, outl, TONGSUO_ASN1_IA5_STRING, buf, buflen); 387 | } 388 | 389 | int asn1_encode_oid(unsigned char **out, size_t *outl, const unsigned char *oid, size_t oidlen) 390 | { 391 | return asn1_encode_tag_string(out, outl, TONGSUO_ASN1_OBJECT_IDENTIFIER, oid, oidlen); 392 | } 393 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) 2 | 3 | PROJECT(tongsuo-mini LANGUAGES C) 4 | 5 | if (MSVC) 6 | # warning level 4 and all warnings as errors 7 | add_compile_options(/W4 /WX) 8 | else() 9 | # lots of warnings and all warnings as errors 10 | add_compile_options(-Wall -Wextra -pedantic -Werror) 11 | endif() 12 | 13 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 14 | 15 | if(MSVC) 16 | set(CMAKE_INSTALL_PREFIX C:/tongsuo-mini) 17 | else() 18 | set(CMAKE_INSTALL_PREFIX /opt/tongsuo-mini) 19 | endif() 20 | 21 | set(CMAKE_MACOSX_RPATH 1) 22 | set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") 23 | 24 | include_directories(include) 25 | 26 | set(libsrc 27 | src/error.c 28 | src/mem.c 29 | src/meth.c 30 | src/pool.c 31 | src/version.c 32 | ) 33 | 34 | # All options, in alphabetic order 35 | OPTION(WITH_ALL "Build with all modules" OFF) 36 | OPTION(WITH_ASCON "Build with ASCON module" OFF) 37 | OPTION(WITH_ASN1 "Build with asn1 module" OFF) 38 | OPTION(WITH_DEBUG "Enable debug" OFF) 39 | OPTION(WITH_ERRSTR "Build with error string" OFF) 40 | OPTION(WITH_EXAMPLE "Build example program" OFF) 41 | OPTION(WITH_HMAC "Build with HMAC module" OFF) 42 | OPTION(WITH_LOG "Build with log module" OFF) 43 | OPTION(WITH_OSCORE "Build with OSCORE module" OFF) 44 | OPTION(WITH_PERF "Build performance test program" OFF) 45 | OPTION(WITH_SM3 "Build with SM3 module" OFF) 46 | OPTION(WITH_SM4 "Build with SM4 module" OFF) 47 | 48 | if(WITH_ALL) 49 | set(WITH_ASCON ON) 50 | set(WITH_ASN1 ON) 51 | set(WITH_DEBUG ON) 52 | set(WITH_ERRSTR ON) 53 | set(WITH_EXAMPLE ON) 54 | set(WITH_HMAC ON) 55 | set(WITH_LOG ON) 56 | set(WITH_OSCORE ON) 57 | set(WITH_PERF ON) 58 | set(WITH_SM3 ON) 59 | set(WITH_SM4 ON) 60 | endif() 61 | 62 | if(WITH_DEBUG) 63 | add_definitions(-DDEBUG) 64 | set(CMAKE_BUILD_TYPE "Debug") 65 | else() 66 | add_definitions(-DNDEBUG) 67 | set(CMAKE_BUILD_TYPE "Release") 68 | endif() 69 | 70 | if(WITH_LOG) 71 | add_definitions(-DTSM_LOG) 72 | list(APPEND libsrc src/log.c) 73 | endif() 74 | 75 | if(WITH_ERRSTR) 76 | add_definitions(-DTSM_ERRSTR) 77 | endif() 78 | 79 | if(WITH_ASN1) 80 | list(APPEND libsrc src/asn1.c) 81 | 82 | add_executable(test_asn1 test/test_asn1.c) 83 | target_include_directories(test_asn1 PUBLIC test) 84 | target_link_libraries(test_asn1 LINK_PUBLIC tongsuo-mini) 85 | add_test(NAME test_asn1 86 | COMMAND python3 -m pytest test_asn1.py 87 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 88 | ) 89 | endif() 90 | 91 | if(WITH_SM3 OR WITH_PERF) 92 | list(APPEND libsrc src/sm3.c) 93 | add_definitions(-DTSM_HAVE_SM3) 94 | 95 | add_executable(test_sm3 test/test_sm3.c) 96 | target_include_directories(test_sm3 PUBLIC test) 97 | target_link_libraries(test_sm3 LINK_PUBLIC tongsuo-mini) 98 | add_test(NAME test_sm3 99 | COMMAND python3 -m pytest test_sm3.py 100 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 101 | ) 102 | endif() 103 | 104 | if(WITH_SM4 OR WITH_PERF) 105 | list(APPEND libsrc src/sm4.c) 106 | add_definitions(-DTSM_HAVE_SM4) 107 | 108 | add_executable(test_sm4_api test/test_sm4_api.c) 109 | target_include_directories(test_sm4_api PUBLIC test) 110 | target_link_libraries(test_sm4_api LINK_PUBLIC tongsuo-mini) 111 | add_test(NAME test_sm4 112 | COMMAND python3 -m pytest test_sm4.py 113 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 114 | ) 115 | endif() 116 | 117 | if(WITH_OSCORE) 118 | set(WITH_ASCON ON) 119 | set(WITH_HMAC ON) 120 | 121 | list(APPEND libsrc src/oscore_cbor.c src/oscore_context.c src/oscore_cose.c src/oscore_crypto.c src/oscore.c) 122 | add_executable(test_oscore test/test_oscore.c) 123 | target_include_directories(test_oscore PUBLIC test) 124 | target_link_libraries(test_oscore LINK_PUBLIC tongsuo-mini) 125 | add_test(NAME test_oscore 126 | COMMAND python3 -m pytest test_oscore.py 127 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 128 | ) 129 | endif() 130 | 131 | if(WITH_ASCON OR WITH_PERF) 132 | list(APPEND libsrc src/ascon.c) 133 | add_definitions(-DTSM_HAVE_ASCON) 134 | 135 | add_executable(test_ascon_aead test/test_ascon_aead.c) 136 | add_executable(test_ascon_hash test/test_ascon_hash.c) 137 | target_include_directories(test_ascon_aead PUBLIC test) 138 | target_include_directories(test_ascon_hash PUBLIC test) 139 | target_link_libraries(test_ascon_aead LINK_PUBLIC tongsuo-mini) 140 | target_link_libraries(test_ascon_hash LINK_PUBLIC tongsuo-mini) 141 | add_test(NAME test_ascon_aead 142 | COMMAND python3 -m pytest test_ascon_aead.py 143 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 144 | ) 145 | add_test(NAME test_ascon_hash 146 | COMMAND python3 -m pytest test_ascon_hash.py 147 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 148 | ) 149 | endif() 150 | 151 | if(WITH_HMAC) 152 | list(APPEND libsrc src/hmac.c) 153 | 154 | if(WITH_SM3) 155 | add_executable(test_hmac_sm3 test/test_hmac_sm3.c) 156 | target_include_directories(test_hmac_sm3 PUBLIC test) 157 | target_link_libraries(test_hmac_sm3 LINK_PUBLIC tongsuo-mini) 158 | add_test(NAME test_hmac_sm3 159 | COMMAND python3 -m pytest test_hmac_sm3.py 160 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 161 | ) 162 | endif(WITH_SM3) 163 | 164 | if(WITH_ASCON) 165 | add_executable(test_hmac_ascon test/test_hmac_ascon.c) 166 | target_include_directories(test_hmac_ascon PUBLIC test) 167 | target_link_libraries(test_hmac_ascon LINK_PUBLIC tongsuo-mini) 168 | add_test(NAME test_hmac_ascon 169 | COMMAND python3 -m pytest test_hmac_ascon.py 170 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 171 | ) 172 | endif(WITH_ASCON) 173 | endif() 174 | 175 | add_library(tongsuo-mini-obj OBJECT ${libsrc}) 176 | # static library does not need to be a PIC... 177 | set_property(TARGET tongsuo-mini-obj PROPERTY POSITION_INDEPENDENT_CODE 1) 178 | add_library(tongsuo-mini SHARED $) 179 | add_library(tongsuo-mini-static STATIC $) 180 | set_target_properties(tongsuo-mini-static PROPERTIES OUTPUT_NAME tongsuo-mini) 181 | 182 | add_executable(minisuo app/minisuo.c) 183 | target_link_libraries(minisuo LINK_PUBLIC tongsuo-mini) 184 | 185 | if(WITH_PERF) 186 | add_executable(minisuo-perf perf/perf.c) 187 | target_link_libraries(minisuo-perf LINK_PUBLIC tongsuo-mini) 188 | endif() 189 | 190 | if(WITH_EXAMPLE) 191 | if(WITH_SM3) 192 | add_executable(sm3_demo examples/sm3_demo.c) 193 | target_link_libraries(sm3_demo LINK_PUBLIC tongsuo-mini) 194 | set_property(TARGET sm3_demo 195 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 196 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 197 | 198 | add_executable(sm3_oneshot examples/sm3_oneshot.c) 199 | target_link_libraries(sm3_oneshot LINK_PUBLIC tongsuo-mini) 200 | set_property(TARGET sm3_oneshot 201 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 202 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 203 | endif(WITH_SM3) 204 | 205 | if(WITH_SM4) 206 | add_executable(sm4_cbc_enc examples/sm4_cbc_enc.c) 207 | target_link_libraries(sm4_cbc_enc LINK_PUBLIC tongsuo-mini) 208 | set_property(TARGET sm4_cbc_enc 209 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 210 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 211 | 212 | add_executable(sm4_oneshot examples/sm4_oneshot.c) 213 | target_link_libraries(sm4_oneshot LINK_PUBLIC tongsuo-mini) 214 | set_property(TARGET sm4_oneshot 215 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 216 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 217 | endif(WITH_SM4) 218 | 219 | if(WITH_ASCON) 220 | add_executable(ascon_aead_enc examples/ascon_aead_enc.c) 221 | target_link_libraries(ascon_aead_enc LINK_PUBLIC tongsuo-mini) 222 | set_property(TARGET ascon_aead_enc 223 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 224 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 225 | 226 | add_executable(ascon_aead_oneshot examples/ascon_aead_oneshot.c) 227 | target_link_libraries(ascon_aead_oneshot LINK_PUBLIC tongsuo-mini) 228 | set_property(TARGET ascon_aead_oneshot 229 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 230 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 231 | 232 | add_executable(ascon_hash examples/ascon_hash.c) 233 | target_link_libraries(ascon_hash LINK_PUBLIC tongsuo-mini) 234 | set_property(TARGET ascon_hash 235 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 236 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 237 | 238 | add_executable(ascon_hash_oneshot examples/ascon_hash_oneshot.c) 239 | target_link_libraries(ascon_hash_oneshot LINK_PUBLIC tongsuo-mini) 240 | set_property(TARGET ascon_hash_oneshot 241 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 242 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 243 | endif(WITH_ASCON) 244 | 245 | if(WITH_HMAC) 246 | if(WITH_ASCON) 247 | add_executable(hmac_ascon examples/hmac_ascon.c) 248 | target_link_libraries(hmac_ascon LINK_PUBLIC tongsuo-mini) 249 | set_property(TARGET hmac_ascon 250 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 251 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 252 | endif(WITH_ASCON) 253 | 254 | if(WITH_SM3) 255 | add_executable(hmac_sm3 examples/hmac_sm3.c) 256 | target_link_libraries(hmac_sm3 LINK_PUBLIC tongsuo-mini) 257 | set_property(TARGET hmac_sm3 258 | PROPERTY RUNTIME_OUTPUT_DIRECTORY 259 | ${CMAKE_CURRENT_BINARY_DIR}/examples) 260 | endif(WITH_SM3) 261 | endif(WITH_HMAC) 262 | endif() 263 | 264 | enable_testing() 265 | add_test(NAME test_minisuo 266 | COMMAND python3 -m pytest test_minisuo.py 267 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test 268 | ) 269 | 270 | # show options 271 | message(STATUS "") 272 | message(STATUS "Tongsuo Mini Configuration Summary:") 273 | message(STATUS "") 274 | message(STATUS "WITH_ALL...................${WITH_ALL}") 275 | message(STATUS "WITH_ASCON.................${WITH_ASCON}") 276 | message(STATUS "WITH_ASN1..................${WITH_ASN1}") 277 | message(STATUS "WITH_DEBUG.................${WITH_DEBUG}") 278 | message(STATUS "WITH_ERRSTR................${WITH_ERRSTR}") 279 | message(STATUS "WITH_EXAMPLE...............${WITH_EXAMPLE}") 280 | message(STATUS "WITH_HMAC..................${WITH_HMAC}") 281 | message(STATUS "WITH_LOG...................${WITH_LOG}") 282 | message(STATUS "WITH_OSCORE................${WITH_OSCORE}") 283 | message(STATUS "WITH_PERF..................${WITH_PERF}") 284 | message(STATUS "WITH_SM3...................${WITH_SM3}") 285 | message(STATUS "WITH_SM4...................${WITH_SM4}") 286 | 287 | # 288 | # install 289 | # 290 | install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/tongsuo 291 | DESTINATION ${CMAKE_INSTALL_PREFIX}/include 292 | COMPONENT dev) 293 | 294 | install(TARGETS tongsuo-mini tongsuo-mini-static 295 | LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib COMPONENT lib 296 | ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib COMPONENT lib) 297 | 298 | install(TARGETS minisuo 299 | DESTINATION ${CMAKE_INSTALL_PREFIX}/bin 300 | COMPONENT dev) 301 | 302 | if(WITH_PERF) 303 | install(TARGETS minisuo-perf 304 | DESTINATION ${CMAKE_INSTALL_PREFIX}/bin 305 | COMPONENT dev) 306 | endif() 307 | -------------------------------------------------------------------------------- /include/tongsuo/oscore_cose.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, SICS, RISE AB 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /** 32 | * @file oscore_cose.h 33 | * @brief An implementation of the CBOR Object Signing and Encryption (RFC). 34 | * 35 | * \author 36 | * Martin Gunnarsson 37 | * adapted with sign1 function for libcoap 38 | * Peter van der Stok 39 | * on request of Fairhair alliance 40 | * adapted for libcoap integration 41 | * Jon Shallow 42 | * adapted for Tongsuo-mini integration 43 | * K1 44 | */ 45 | 46 | #if !defined(TSM_OSCORE_COSE_H) 47 | # define TSM_OSCORE_COSE_H 48 | # pragma once 49 | 50 | # ifdef __cplusplus 51 | extern "C" { 52 | # endif 53 | 54 | # include 55 | # include 56 | 57 | # define AES_CCM_TAG 16 58 | 59 | # define COSE_ALGORITHM_ED25519_SIG_LEN 64 60 | # define COSE_ALGORITHM_ED25519_PRIV_KEY_LEN 32 61 | # define COSE_ALGORITHM_ED25519_PUB_KEY_LEN 32 62 | 63 | # define COSE_ALGORITHM_ASCON_AEAD_16_128_128_KEY_LEN 16 64 | # define COSE_ALGORITHM_ASCON_AEAD_16_128_128_NONCE_LEN 16 65 | # define COSE_ALGORITHM_ASCON_AEAD_16_128_128_TAG_LEN 16 66 | 67 | # define COSE_ALGORITHM_ASCON_AEAD_64_128_128_KEY_LEN 16 68 | # define COSE_ALGORITHM_ASCON_AEAD_64_128_128_NONCE_LEN 16 69 | # define COSE_ALGORITHM_ASCON_AEAD_64_128_128_TAG_LEN 16 70 | 71 | # define COSE_ALGORITHM_AES_CCM_64_64_128_KEY_LEN 16 72 | # define COSE_ALGORITHM_AES_CCM_64_64_128_NONCE_LEN 7 73 | # define COSE_ALGORITHM_AES_CCM_64_64_128_TAG_LEN 8 74 | 75 | # define COSE_ALGORITHM_AES_CCM_16_64_128_KEY_LEN 16 76 | # define COSE_ALGORITHM_AES_CCM_16_64_128_NONCE_LEN 13 77 | # define COSE_ALGORITHM_AES_CCM_16_64_128_TAG_LEN 8 78 | 79 | # define COSE_ALGORITHM_AES_CCM_64_128_128_KEY_LEN 16 80 | # define COSE_ALGORITHM_AES_CCM_64_128_128_NONCE_LEN 7 81 | # define COSE_ALGORITHM_AES_CCM_64_128_128_TAG_LEN 16 82 | 83 | # define COSE_ALGORITHM_AES_CCM_16_128_128_KEY_LEN 16 84 | # define COSE_ALGORITHM_AES_CCM_16_128_128_NONCE_LEN 13 85 | # define COSE_ALGORITHM_AES_CCM_16_128_128_TAG_LEN 16 86 | 87 | # define COSE_ALGORITHM_ES256_PRIV_KEY_LEN 24 88 | # define COSE_ALGORITHM_ES256_PUB_KEY_LEN 32 89 | # define COSE_ALGORITHM_ES256_SIGNATURE_LEN 64 90 | # define COSE_ALGORITHM_ES256_HASH_LEN 32 91 | 92 | # define COSE_ALGORITHM_ES384_PRIV_KEY_LEN 24 93 | # define COSE_ALGORITHM_ES384_PUB_KEY_LEN 32 94 | # define COSE_ALGORITHM_ES384_SIGNATURE_LEN 64 95 | # define COSE_ALGORITHM_ES384_HASH_LEN 48 96 | 97 | # define COSE_ALGORITHM_ES512_PRIV_KEY_LEN 24 98 | # define COSE_ALGORITHM_ES512_PUB_KEY_LEN 32 99 | # define COSE_ALGORITHM_ES512_SIGNATURE_LEN 64 100 | # define COSE_ALGORITHM_ES512_HASH_LEN 64 101 | 102 | # define COSE_ALGORITHM_ECDH_PRIV_KEY_LEN 32 103 | # define COSE_ALGORITHM_ECDH_PUB_KEY_LEN 32 104 | 105 | # define COSE_ALGORITHM_SHA_512_LEN 64 106 | # define COSE_ALGORITHM_SHA_512_256_LEN 32 107 | # define COSE_ALGORITHM_SHA_256_256_LEN 32 108 | # define COSE_ALGORITHM_SHA_256_64_LEN 8 109 | 110 | # define COSE_ALGORITHM_HMAC256_64_HASH_LEN 16 111 | # define COSE_ALGORITHM_HMAC256_256_HASH_LEN 32 112 | # define COSE_ALGORITHM_HMAC384_384_HASH_LEN 48 113 | # define COSE_ALGORITHM_HMAC512_512_HASH_LEN 64 114 | 115 | /* cose algorithms */ 116 | typedef enum { 117 | COSE_ALGORITHM_HKDF_ASCON_HASHA = -101, 118 | COSE_ALGORITHM_HKDF_ASCON_HASH = -100, 119 | COSE_ALGORITHM_ES256K = -47, /* with ECC known as secp256k1 */ 120 | COSE_ALGORITHM_SHA_512 = -44, 121 | COSE_ALGORITHM_SHA_384 = -43, 122 | COSE_ALGORITHM_ES512 = -36, /* with ECDSA */ 123 | COSE_ALGORITHM_ES384 = -35, /* with ECDSA */ 124 | COSE_ALGORITHM_ECDH_SS_HKDF_256 = -27, 125 | COSE_ALGORITHM_SHA_512_256 = -17, 126 | COSE_ALGORITHM_SHA_256_256 = -16, 127 | COSE_ALGORITHM_SHA_256_64 = -15, 128 | COSE_ALGORITHM_SHA_1 = -14, 129 | COSE_ALGORITHM_HKDF_SHA_512 = -11, 130 | COSE_ALGORITHM_HKDF_SHA_256 = -10, 131 | COSE_ALGORITHM_EDDSA = -8, 132 | COSE_ALGORITHM_ES256 = -7, /* with ECC known as secp256r1 */ 133 | COSE_ALGORITHM_HMAC256_64 = 4, /* truncated to 64 bits */ 134 | COSE_ALGORITHM_HMAC256_256 = 5, 135 | COSE_ALGORITHM_HMAC384_384 = 6, 136 | COSE_ALGORITHM_HMAC512_512 = 7, 137 | COSE_ALGORITHM_AES_CCM_16_64_128 = 10, 138 | COSE_ALGORITHM_AES_CCM_16_64_256 = 11, 139 | COSE_ALGORITHM_AES_CCM_64_64_128 = 12, 140 | COSE_ALGORITHM_AES_CCM_64_64_256 = 13, 141 | COSE_ALGORITHM_CHACHA20_P1035 = 24, 142 | COSE_ALGORITHM_AES_CCM_16_128_128 = 30, 143 | COSE_ALGORITHM_AES_CCM_16_128_256 = 31, 144 | COSE_ALGORITHM_AES_CCM_64_128_128 = 32, 145 | COSE_ALGORITHM_AES_CCM_64_128_256 = 33, 146 | COSE_ALGORITHM_ASCON_AEAD_16_128_128 = 40, 147 | COSE_ALGORITHM_ASCON_AEAD_64_128_128 = 41, 148 | COSE_ALGORITHM_HMAC_ASCON_HMAC = 100, 149 | COSE_ALGORITHM_HMAC_ASCON_HMACA = 100, 150 | } cose_alg_t; 151 | 152 | /* cose HKDF specific algorithms */ 153 | typedef enum { 154 | COSE_HKDF_ALG_HKDF_ASCON_HASHA = -101, 155 | COSE_HKDF_ALG_HKDF_ASCON_HASH = -100, 156 | COSE_HKDF_ALG_HKDF_SHA_512 = -11, 157 | COSE_HKDF_ALG_HKDF_SHA_256 = -10, 158 | } cose_hkdf_alg_t; 159 | 160 | /* Get algorithm name by id. The name is written to buffer with the max length buflen. The buffer is 161 | * returned. */ 162 | const char *tsm_cose_get_alg_name(cose_alg_t id, char *buffer, size_t buflen); 163 | /* Returns the algorithm id of name. */ 164 | cose_alg_t tsm_cose_get_alg_id(const char *name); 165 | /* Get hkdf algorithm name by id. The name is written to buffer with the max length buflen. The 166 | * buffer is returned. */ 167 | const char *tsm_cose_get_hkdf_alg_name(cose_hkdf_alg_t id, char *buffer, size_t buflen); 168 | /* Retrives HMAC algorithm from HKDF. Returns TSM_OK means success, others mean failure. */ 169 | int tsm_cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, int *hmac_alg); 170 | /* Returns tag length belonging to cose algorithm. */ 171 | size_t tsm_cose_tag_len(cose_alg_t cose_alg); 172 | /* Returns hash length belonging to cose algorithm. */ 173 | size_t tsm_cose_hash_len(cose_alg_t cose_alg); 174 | /* Returns nonce length belonging to cose algorithm. */ 175 | size_t tsm_cose_nonce_len(cose_alg_t cose_alg); 176 | /* Returns key length belonging to cose algorithm */ 177 | size_t tsm_cose_key_len(cose_alg_t cose_alg); 178 | 179 | /* COSE Encrypt0 Struct */ 180 | typedef struct cose_encrypt0_s { 181 | cose_alg_t alg; 182 | TSM_STR key; 183 | uint8_t partial_iv_data[8]; 184 | /* partial_iv.s will point back to partial_iv_data if set */ 185 | TSM_STR partial_iv; 186 | TSM_STR key_id; 187 | TSM_STR kid_context; 188 | TSM_STR oscore_option; 189 | TSM_STR nonce; 190 | TSM_STR external_aad; 191 | TSM_STR aad; 192 | TSM_STR plaintext; 193 | TSM_STR ciphertext; 194 | } cose_encrypt0_t; 195 | 196 | /* Initiate a new COSE Encrypt0 object. */ 197 | void tsm_cose_encrypt0_init(cose_encrypt0_t *ptr); 198 | /* Sets algorithm to COSE Encrypt0 object. */ 199 | void tsm_cose_encrypt0_set_alg(cose_encrypt0_t *ptr, uint8_t alg); 200 | /* Sets plain text at buffer with length size to COSE Encrypt0 object. */ 201 | void tsm_cose_encrypt0_set_plaintext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size); 202 | /* Sets cipher text at buffer with length size to COSE Encrypt0 object. */ 203 | void tsm_cose_encrypt0_set_ciphertext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size); 204 | /* Sets partial iv with length length to COSE Encrypt0 object. */ 205 | void tsm_cose_encrypt0_set_partial_iv(cose_encrypt0_t *ptr, const uint8_t *partial_iv, 206 | size_t length); 207 | /* Sets key id with length length to COSE Encrypt0 object. */ 208 | void tsm_cose_encrypt0_set_key_id(cose_encrypt0_t *ptr, const uint8_t *key_id, size_t length); 209 | /* Gets key id of COSE Encrypt0 object. Return length of key id. */ 210 | size_t tsm_cose_encrypt0_get_key_id(cose_encrypt0_t *ptr, const uint8_t **buffer); 211 | /* Sets external aad with length length to COSE Encrypt0 object. */ 212 | void tsm_cose_encrypt0_set_external_aad(cose_encrypt0_t *ptr, const uint8_t *external_aad, 213 | size_t length); 214 | /* Sets aad with length length to COSE Encrypt0 object. */ 215 | void tsm_cose_encrypt0_set_aad(cose_encrypt0_t *ptr, const uint8_t *aad, size_t length); 216 | /* Gets key id context of COSE Encrypt0 object. Return length of key id context. */ 217 | size_t tsm_cose_encrypt0_get_kid_context(cose_encrypt0_t *ptr, const uint8_t **buffer); 218 | /* Sets key id context with length length to COSE Encrypt0 object. */ 219 | void tsm_cose_encrypt0_set_kid_context(cose_encrypt0_t *ptr, const uint8_t *kid_context, 220 | size_t length); 221 | /* Sets key with length length to COSE Encrypt0 object. Returns TSM_OK if successfull, other error 222 | * code if key is of incorrect length. */ 223 | int tsm_cose_encrypt0_set_key(cose_encrypt0_t *ptr, const uint8_t *key, size_t length); 224 | /* Sets nonce with length length to COSE Encrypt0 object. */ 225 | void tsm_cose_encrypt0_set_nonce(cose_encrypt0_t *ptr, const uint8_t *nonce, size_t length); 226 | /* Encrypts COSE Encrypt0 object and writes to ciphertext_buffer with the max length ciphertext_len. 227 | * Returns actual length of cipher text if successful, otherwise returns a negative integer. */ 228 | int tsm_cose_encrypt0_encrypt(cose_encrypt0_t *ptr, uint8_t *ciphertext_buffer, 229 | size_t ciphertext_len); 230 | /* Decrypts COSE Encrypt0 object and writes to plaintext_buffer with the max length plaintext_len. 231 | * Returns actual length of plain text if successful, otherwise returns a negative integer. */ 232 | int tsm_cose_encrypt0_decrypt(cose_encrypt0_t *ptr, uint8_t *plaintext_buffer, 233 | size_t plaintext_len); 234 | 235 | # ifdef __cplusplus 236 | } 237 | # endif 238 | #endif 239 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------