├── extra_vecs ├── .gitignore ├── README.md ├── salsa20-extra.py ├── Makefile ├── libsodium-extra.py ├── python-hash.py └── openssl-hash.c ├── src ├── arm │ ├── .gitignore │ ├── openocd.efm32.cfg │ ├── openocd.stm32f0.cfg │ ├── openocd.stm32f1.cfg │ ├── openocd.stm32f3.cfg │ ├── linkscript.efm32.ld │ ├── linkscript.lm3s6965evb.ld │ ├── linkscript.stm32f1.ld │ ├── linkscript.stm32f3.ld │ ├── linkscript.qemucm3.ld │ ├── linkscript.stm32f0.ld │ ├── semihost.s │ ├── curve25519-results.txt │ ├── memcpy.s │ ├── memset.s │ ├── merge.py │ ├── semihost.h │ ├── ext │ │ └── cutest.h │ ├── boot.c │ ├── semihost.c │ ├── unacl │ │ ├── cortex_m0_reduce25519.s │ │ └── cortex_m0_mpy121666.s │ └── linkscript.std.ld ├── .gitignore ├── chash.c ├── tassert.h ├── curve25519.c ├── curve25519.h ├── testutil.h ├── pbkdf2.h ├── Makefile ├── prp.h ├── gf128.h ├── testcurve25519.c ├── cf_config.h ├── ext │ └── handy.h ├── hmac.h ├── pbkdf2.c ├── testsha1.c ├── cbcmac.c ├── poly1305.h ├── sha1.h ├── sha3_shake.c ├── chacha20poly1305.h ├── modes.c ├── hmac.c ├── norx.h ├── gf128.c ├── poly1305.py ├── testnorx.c ├── eax.c ├── testshake.h ├── sha3_shake.h ├── testpoly1305.c ├── sha1.c ├── chash.h ├── cmac.c ├── salsa20.c ├── salsa20.h ├── aes.h ├── chacha20.c ├── chacha20poly1305.c ├── curve25519.tweetnacl.c ├── poly1305.c ├── ccm.c ├── blockwise.c ├── sha3.h ├── blockwise.h ├── gcm.c ├── testsha.h └── drbg.h ├── doc ├── Makefile └── index.rst ├── .travis.yml ├── curve25519-shootout.md └── COPYING /extra_vecs/.gitignore: -------------------------------------------------------------------------------- 1 | openssl-hash 2 | -------------------------------------------------------------------------------- /src/arm/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.elf 3 | *.bin 4 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | default: all 2 | all: 3 | sphinx-build -b html . _build 4 | -------------------------------------------------------------------------------- /src/arm/openocd.efm32.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/jlink.cfg] 2 | transport select swd 3 | source [find target/efm32.cfg] 4 | -------------------------------------------------------------------------------- /src/arm/openocd.stm32f0.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/stlink-v2.cfg] 2 | transport select hla_swd 3 | source [find target/stm32f0x.cfg] 4 | -------------------------------------------------------------------------------- /src/arm/openocd.stm32f1.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/stlink-v2.cfg] 2 | transport select hla_swd 3 | source [find target/stm32f1x.cfg] 4 | -------------------------------------------------------------------------------- /src/arm/openocd.stm32f3.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/stlink-v2.cfg] 2 | transport select hla_swd 3 | source [find target/stm32f3x.cfg] 4 | -------------------------------------------------------------------------------- /extra_vecs/README.md: -------------------------------------------------------------------------------- 1 | This directory contains assorted programs for generating test vectors 2 | from other crypto libraries, like OpenSSL. 3 | -------------------------------------------------------------------------------- /src/arm/linkscript.efm32.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | 9 | -------------------------------------------------------------------------------- /src/arm/linkscript.lm3s6965evb.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | -------------------------------------------------------------------------------- /src/arm/linkscript.stm32f1.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | 9 | -------------------------------------------------------------------------------- /src/arm/linkscript.stm32f3.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 12K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | 9 | -------------------------------------------------------------------------------- /src/arm/linkscript.qemucm3.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | 9 | -------------------------------------------------------------------------------- /src/arm/linkscript.stm32f0.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K 4 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K 5 | } 6 | 7 | INCLUDE linkscript.std.ld 8 | 9 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.gcov 3 | *.gcno 4 | *.gcda 5 | testaes 6 | testmodes 7 | testsha1 8 | testsha2 9 | testsha3 10 | testsalsa20 11 | testcurve25519 12 | testpoly1305 13 | testnorx 14 | testchacha20poly1305 15 | testdrbg 16 | testshake 17 | -------------------------------------------------------------------------------- /src/arm/semihost.s: -------------------------------------------------------------------------------- 1 | .text 2 | .syntax unified 3 | .global semihost 4 | .func semihost 5 | .thumb_func 6 | 7 | semihost: 8 | /* on entry 9 | * r0 = op 10 | * r1 = arg */ 11 | push {r7, lr} 12 | bkpt 0xab 13 | pop {r7, pc} 14 | 15 | .endfunc 16 | -------------------------------------------------------------------------------- /extra_vecs/salsa20-extra.py: -------------------------------------------------------------------------------- 1 | import salsa20 2 | 3 | key = ('secretkey'*4)[:32] 4 | nonce = ('nonce'*2)[:8] 5 | keystream = salsa20.Salsa20_keystream(128, nonce, key) 6 | 7 | print """vector("%s", "%s", "%s");""" % (key.encode('hex'), nonce.encode('hex'), keystream.encode('hex')) 8 | -------------------------------------------------------------------------------- /extra_vecs/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -std=gnu99 -O0 -g -Wall -Werror 2 | 3 | all: run 4 | 5 | openssl-hash: openssl-hash.c 6 | $(CC) $(CFLAGS) -o $@ $^ -lcrypto 7 | 8 | run: openssl-hash 9 | ./openssl-hash 10 | python python-hash.py 11 | 12 | clean: 13 | rm -rf *.o openssl-hash 14 | -------------------------------------------------------------------------------- /src/arm/curve25519-results.txt: -------------------------------------------------------------------------------- 1 | STM32F0 2 | donna-before-opt: 12907000c 3 | donna-after-opt: 17294000c 4 | donna-reset-opt: 12947000c 5 | ~20k 6 | 7 | donna -O2 -Os: 15268000c 8 | donna -O2 -Os noasm: 20453000c 9 | donna -Os: 15748000c 10 | 7.4k 11 | 12 | donna -O3: 12907000c 16KB 3380b 13 | donna -Os: 15748000c 7.4KB 3148b 14 | donna -O2: 15218000c 7.9KB 3148b 15 | 16 | tweetnacl -O2: 68876000c 3.0KB 2268b 17 | tweetnacl -Os: 75979000c 2.8KB 2244b 18 | tweetnacl -O3: 69622000c 8.9KB 2900b 19 | 20 | naclref -Os: 47813000c 3.2KB 4012b 21 | naclref -O3: 35059000c 4.1KB 4044b 22 | naclref -O2: 34309000c 3.5KB 4036b 23 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Cifra documentation master file, created by 2 | sphinx-quickstart on Sat Feb 21 18:02:37 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Cifra's documentation! 7 | ================================= 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | cf_config 15 | prp 16 | chash 17 | aes 18 | norx 19 | salsa20 20 | modes 21 | hmac 22 | poly1305 23 | chacha20poly1305 24 | pbkdf2 25 | sha1 26 | sha2 27 | sha3 28 | sha3_shake 29 | drbg 30 | 31 | Index 32 | ----- 33 | * :ref:`genindex` 34 | 35 | -------------------------------------------------------------------------------- /extra_vecs/libsodium-extra.py: -------------------------------------------------------------------------------- 1 | import pysodium 2 | 3 | def test(msg, aad, nonce, key): 4 | ct = pysodium.crypto_aead_chacha20poly1305_ietf_encrypt(msg, aad, nonce, key) 5 | ct, tag = ct[:len(msg)], ct[len(msg):] 6 | 7 | print """ 8 | vector("%s", 9 | "%s", 10 | "%s", 11 | "%s", 12 | "%s", 13 | "%s");""" % (key.encode('hex'), nonce.encode('hex'), aad.encode('hex'), msg.encode('hex'), ct.encode('hex'), tag.encode('hex')) 14 | 15 | key = 'key.' * 8 16 | nonce = 'nonce.' * 2 17 | msg = 'message' * 5 18 | aad = 'aad' * 12 19 | 20 | for msgl in range(32): 21 | test(msg[:msgl], aad, nonce, key) 22 | 23 | for aadl in range(32): 24 | test(msg, aad[:aadl], nonce, key) 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | before_install: 4 | - sudo pip install cpp-coveralls 5 | 6 | script: 7 | - cd src 8 | - make clean 9 | - make test 10 | 11 | after_success: 12 | - coveralls --exclude src/ext --gcov-options '\-lp' 13 | 14 | compiler: 15 | - gcc 16 | 17 | env: 18 | global: 19 | - secure: "W9IUnUWNc03gIBGLPOxXCVJUOb3RY2fS4lgOo+wIsCSk0rsJAB6gruAZDoz1sMxCJyBhCv0dKV5WPkAxkZ0y55wiuUcCepgR0qis6S6rJxldPdEWc3RQaeU9LbVRKRBYUBqSsFlXr5pdOvl0CBDWmx8lhcRxAw8z+JVDrAGVsTQ=" 20 | 21 | addons: 22 | coverity_scan: 23 | project: 24 | name: "ctz/cifra" 25 | description: "Cifra is a collection of cryptographic primitives targeted at embedded use." 26 | notification_email: jpixton@gmail.com 27 | build_command_prepend: "cd src ; make clean" 28 | build_command: "make" 29 | branch_pattern: coverity-scan 30 | -------------------------------------------------------------------------------- /src/arm/memcpy.s: -------------------------------------------------------------------------------- 1 | .text 2 | .syntax unified 3 | .global memcpy 4 | .func memcpy 5 | .thumb_func 6 | 7 | memcpy: 8 | /* on entry 9 | * r0 = targ 10 | * r1 = src 11 | * r2 = len (bytes) 12 | * on exit 13 | * r0 = targ (unchanged) 14 | */ 15 | push {r0, r4, lr} 16 | 17 | /* If targ or src are unaligned, drop to byte 18 | * processing. */ 19 | mov r3, r0 20 | movs r4, #3 21 | orrs r3, r1 22 | ands r3, r4 23 | bne L_bytewise 24 | 25 | /* Process words */ 26 | L_wordwise: 27 | cmp r2, #4 28 | blo L_bytewise 29 | ldr r4, [r1] 30 | adds r1, #4 31 | str r4, [r0] 32 | adds r0, #4 33 | subs r2, #4 34 | b L_wordwise 35 | 36 | /* Process bytes */ 37 | L_bytewise: 38 | cmp r2, #0 39 | beq L_fin 40 | ldrb r4, [r1] 41 | adds r1, #1 42 | strb r4, [r0] 43 | adds r0, #1 44 | subs r2, #1 45 | b L_bytewise 46 | 47 | L_fin: 48 | pop {r0, r4, pc} 49 | .endfunc 50 | -------------------------------------------------------------------------------- /src/chash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "chash.h" 16 | #include "handy.h" 17 | #include "tassert.h" 18 | 19 | void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out) 20 | { 21 | cf_chash_ctx ctx; 22 | assert(h); 23 | h->init(&ctx); 24 | h->update(&ctx, m, nm); 25 | h->digest(&ctx, out); 26 | mem_clean(&ctx, sizeof ctx); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /curve25519-shootout.md: -------------------------------------------------------------------------------- 1 | ## Curve25519 on Cortex-M0 shootout 2 | Implementation | Optimisation | Cycles | Code size | Stack usage 3 | -------------- | ------------ | --------- | --------- | ----------- 4 | donna | `-Os` | 15748K | 7.4KB | 3148B 5 | donna | `-O2` | 15218K | 7.9KB | 3148B 6 | donna | `-O3` | 12907K | 16KB | 3380B 7 | naclref | `-Os` | 47813K | 3.2KB | 4012B 8 | naclref | `-O2` | 34309K | 3.5KB | 4036B 9 | naclref | `-O3` | 35059K | 4.1KB | 4044B 10 | tweetnacl | `-Os` | 75979K | 2.8KB | 2244B 11 | tweetnacl | `-O2` | 68876K | 3.0KB | 2268B 12 | tweetnacl | `-O3` | 69622K | 8.9KB | 2900B 13 | 14 | naclref at -O2 seems to give a good balance. If you can spare the flash, 15 | donna is quite significantly quicker. 16 | 17 | -------------------------------------------------------------------------------- /src/arm/memset.s: -------------------------------------------------------------------------------- 1 | .text 2 | .syntax unified 3 | .global memset 4 | .func memset 5 | .thumb_func 6 | 7 | memset: 8 | /* on entry 9 | * r0 = targ 10 | * r1 = value 11 | * r2 = len (bytes) 12 | * on exit 13 | * r0 = targ (unchanged) 14 | */ 15 | push {r0, r4, lr} 16 | 17 | /* If targ is unaligned, drop to byte 18 | * processing. */ 19 | movs r3, #3 20 | ands r3, r0 21 | bne L_bytewise 22 | 23 | /* Process words */ 24 | /* Build r4 by repeating r1. */ 25 | uxtb r4, r1 26 | lsls r3, r4, #8 27 | orrs r4, r3 28 | lsls r3, r4, #16 29 | orrs r4, r3 30 | 31 | L_wordwise: 32 | cmp r2, #4 33 | blo L_bytewise 34 | str r4, [r0] 35 | adds r0, #4 36 | subs r2, #4 37 | b L_wordwise 38 | 39 | /* Process bytes */ 40 | L_bytewise: 41 | cmp r2, #0 42 | beq L_fin 43 | strb r1, [r0] 44 | adds r0, #1 45 | subs r2, #1 46 | b L_bytewise 47 | 48 | L_fin: 49 | pop {r0, r4, pc} 50 | .endfunc 51 | -------------------------------------------------------------------------------- /src/arm/merge.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def extract_results(results): 4 | index = 0 5 | while index < len(results): 6 | if results[index].startswith('## '): 7 | end = results.index('\n', index) 8 | yield results[index:end] 9 | index += 1 10 | 11 | def merge(readme, res): 12 | title, table = res[0], res[1:] 13 | assert title in readme, 'Section ' + title + ' missing from README.md' 14 | secindex = readme.index(title) 15 | hdrindex = [i for i in range(secindex, len(readme)) if readme[i].startswith('---------- | ')][0] 16 | start = hdrindex - 1 17 | end = readme.index('\n', start) 18 | table = [t.rstrip() + '\n' for t in table] 19 | return readme[:start] + table + readme[end:] 20 | 21 | results = sys.stdin.readlines() 22 | readme = open('../../README.md').readlines() 23 | 24 | for res in extract_results(results): 25 | readme = merge(readme, res) 26 | print ''.join(readme).rstrip() 27 | -------------------------------------------------------------------------------- /src/tassert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef TASSERT_H 16 | #define TASSERT_H 17 | 18 | /* Tiny assert 19 | * ----------- 20 | * 21 | * This is an assert(3) definition which doesn't include any 22 | * strings, but just branches to abort(3) on failure. 23 | */ 24 | 25 | #ifndef FULL_FAT_ASSERT 26 | # include 27 | # define assert(expr) do { if (!(expr)) abort(); } while (0) 28 | #else 29 | # include 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/curve25519.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #if defined(CORTEX_M0) || defined(CORTEX_M3) || defined(CORTEX_M4) 16 | #include "arm/unacl/scalarmult.c" 17 | 18 | void cf_curve25519_mul(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]) 19 | { 20 | crypto_scalarmult_curve25519(out, scalar, point); 21 | } 22 | 23 | void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]) 24 | { 25 | crypto_scalarmult_curve25519_base(out, scalar); 26 | } 27 | #else 28 | #include "curve25519.tweetnacl.c" 29 | #endif 30 | -------------------------------------------------------------------------------- /src/arm/semihost.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMIHOST_H 2 | #define SEMIHOST_H 3 | 4 | #include 5 | #include 6 | 7 | /* Exits emulator with success (or merely hangs). */ 8 | __attribute__((noreturn)) 9 | void quit_success(void); 10 | 11 | /* Exits emulator with failure (or merely hangs). */ 12 | __attribute__((noreturn)) 13 | void quit_failure(void); 14 | 15 | /* Writes zero terminated string to debug output */ 16 | void emit(const char *buf); 17 | 18 | /* Writes a formatting string to debug output. 19 | * 20 | * Supported: 21 | * %u - uint32_t argument, same as emit_uint32 22 | * %s - const char * argument, same as emit 23 | */ 24 | void emitf(const char *fmt, ...); 25 | 26 | /* Writes hex dump of len bytes at ptr to debug output. */ 27 | void emit_hex(const void *ptr, size_t len); 28 | 29 | /* Writes value v in hex to debug output, in format: 30 | * 0xHHHHHHHH (equivalent to printf 0x%08x). */ 31 | void emit_uint32(uint32_t v); 32 | 33 | /* Reset cycle counter to 0. Returns the current value 34 | * (just after resetting it). */ 35 | uint32_t reset_cycles(void); 36 | 37 | /* Return the value of the cycle counter. */ 38 | uint32_t get_cycles(void); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/arm/ext/cutest.h: -------------------------------------------------------------------------------- 1 | /* cutest, for embedded targets. */ 2 | 3 | #ifndef CUTEST_H 4 | #define CUTEST_H 5 | 6 | /* Main interface. */ 7 | #define TEST_LIST const struct test__ test_list__[] 8 | #define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, #cond) 9 | /* no TEST_CHECK_ -- we don't have a good enough printf */ 10 | 11 | /* Implementation */ 12 | #include "../semihost.h" 13 | 14 | struct test__ 15 | { 16 | const char *name; 17 | void (*func)(void); 18 | }; 19 | 20 | extern const struct test__ test_list__[]; 21 | 22 | static void test_check__(int cond, const char *file, int line, const char *expr) 23 | { 24 | if (cond) 25 | return; /* pass */ 26 | 27 | emit("Failed!\n"); 28 | emit("File: "); emit(file); emit("\n"); 29 | emit("Line: "); emit_uint32(line); emit("\n"); 30 | emit("Expr: "); emit(expr); emit("\n"); 31 | quit_failure(); 32 | } 33 | 34 | static void run_test__(const struct test__ *t) 35 | { 36 | emit(" "); emit(t->name); emit(": "); 37 | t->func(); 38 | emit("OK\n"); 39 | } 40 | 41 | int main(void) 42 | { 43 | emit("Running tests:\n"); 44 | 45 | for (const struct test__ *t = test_list__; 46 | t->name; 47 | t++) 48 | { 49 | run_test__(t); 50 | } 51 | emit("Success\n"); 52 | quit_success(); 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /extra_vecs/python-hash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | # 4 | # see openssl-hash for details of what this is computing 5 | # you'll need python-sha3 from https://github.com/bjornedstrom/python-sha3 6 | # 7 | 8 | import hashlib 9 | import sha3 10 | 11 | # check sha3 at least works; pysha3 *DOES NOT* (it is keccak, not sha3) 12 | assert '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532' == hashlib.sha3_256('abc').hexdigest() 13 | 14 | def hh(x): 15 | return ''.join(['\\x' + x[y:y+2] for y in range(0, len(x), 2)]) 16 | 17 | def len_test(name, H, max): 18 | outer = H() 19 | 20 | for n in range(max): 21 | inner = H() 22 | inner.update(chr(n & 0xff) * n) 23 | outer.update(inner.digest()) 24 | 25 | result = outer.hexdigest() 26 | print '%s(%d) = %s or %s' % (name, max, result, hh(result)) 27 | 28 | if __name__ == '__main__': 29 | MAX = 1024 30 | len_test('SHA1', hashlib.sha1, MAX) 31 | len_test('SHA224', hashlib.sha224, MAX) 32 | len_test('SHA256', hashlib.sha256, MAX) 33 | len_test('SHA384', hashlib.sha384, MAX) 34 | len_test('SHA512', hashlib.sha512, MAX) 35 | len_test('SHA3-224', hashlib.sha3_224, MAX) 36 | len_test('SHA3-256', hashlib.sha3_256, MAX) 37 | len_test('SHA3-384', hashlib.sha3_384, MAX) 38 | len_test('SHA3-512', hashlib.sha3_512, MAX) 39 | -------------------------------------------------------------------------------- /src/curve25519.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef CURVE25519_H 16 | #define CURVE25519_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * Curve25519 23 | * ========== 24 | * This is `curve25519 `_ with switchable 25 | * implementations underneath. 26 | * 27 | * By default tweetnacl is used on hosts, and the implementation 28 | * from μNaCl for Cortex-M0, M3 and M4. 29 | */ 30 | 31 | /* .. c:function:: $DECL 32 | * Multiplies `point` by `scalar`, putting the resulting point into `out`. */ 33 | void cf_curve25519_mul(uint8_t out[32], 34 | const uint8_t scalar[32], 35 | const uint8_t point[32]); 36 | 37 | /* .. c:function:: $DECL 38 | * Multiplies `scalar` by the curve25519 base point, putting the resulting 39 | * point into `out`. */ 40 | void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/testutil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef TESTUTIL_H 16 | #define TESTUTIL_H 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | static inline uint8_t unhex_chr(char a) 23 | { 24 | if (a >= '0' && a <= '9') 25 | return a - '0'; 26 | else if (a >= 'a' && a <= 'f') 27 | return a - 'a' + 10; 28 | else if (a >= 'A' && a <= 'F') 29 | return a - 'A' + 10; 30 | return 0; 31 | } 32 | 33 | static inline size_t unhex(uint8_t *buf, size_t len, const char *str) 34 | { 35 | size_t used = 0; 36 | 37 | assert(strlen(str) % 2 == 0); 38 | assert(strlen(str) / 2 <= len); 39 | 40 | while (*str) 41 | { 42 | assert(len); 43 | *buf = unhex_chr(str[0]) << 4 | unhex_chr(str[1]); 44 | buf++; 45 | used++; 46 | str += 2; 47 | len--; 48 | } 49 | 50 | return used; 51 | } 52 | 53 | static inline void dump(const char *label, const uint8_t *buf, size_t len) 54 | { 55 | printf("%s: ", label); 56 | for (size_t i = 0; i < len; i++) 57 | printf("%02x", buf[i]); 58 | printf("\n"); 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/pbkdf2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef PBKDF2_H 16 | #define PBKDF2_H 17 | 18 | #include 19 | #include 20 | 21 | #include "chash.h" 22 | 23 | /** 24 | * PBKDF2-HMAC 25 | * =========== 26 | * This is PBKDF2 as described by PKCS#5/RFC2898 with HMAC as the PRF. 27 | */ 28 | 29 | /* .. c:function:: $DECL 30 | * This computes PBKDF2-HMAC with the given hash functon. 31 | * 32 | * :param pw: password input buffer. 33 | * :param npw: password length. 34 | * :param salt: salt input buffer. 35 | * :param nsalt: salt length. 36 | * :param iterations: non-zero iteration count. Tune this for performance/security tradeoff. 37 | * :param out: key material output buffer. `nout` bytes are written here. 38 | * :param nout: key material length. 39 | * :param hash: hash function description. 40 | */ 41 | void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw, 42 | const uint8_t *salt, size_t nsalt, 43 | uint32_t iterations, 44 | uint8_t *out, size_t nout, 45 | const cf_chash *hash); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /extra_vecs/openssl-hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #define MAX_LENGTH 1024 7 | 8 | static void printhex(const uint8_t *buf, size_t len) 9 | { 10 | for (size_t i = 0; i < len; i++) 11 | printf("%02x", buf[i]); 12 | } 13 | 14 | /* This test produces a single hash value which depends on 15 | * hashes with all preimage lengths up to max. 16 | * 17 | * It emits 18 | * H(H(t(0)) || H(t(1)) || ... || H(t(max-1)))) 19 | * where 20 | * t(n) = (n % 256) ^ n 21 | * (informally, t(n) is a n-length octet string of octets with value n mod 256) 22 | */ 23 | static void emit_length_test(const char *name, const EVP_MD *h, size_t max) 24 | { 25 | EVP_MD_CTX outer, inner; 26 | EVP_DigestInit(&outer, h); 27 | uint8_t digest[EVP_MAX_MD_SIZE]; 28 | unsigned int digestlen; 29 | 30 | for (size_t n = 0; n < max; n++) 31 | { 32 | EVP_DigestInit(&inner, h); 33 | for (size_t i = 0; i < n; i++) 34 | { 35 | uint8_t byte = n & 0xff; 36 | EVP_DigestUpdate(&inner, &byte, 1); 37 | } 38 | digestlen = sizeof digest; 39 | EVP_DigestFinal(&inner, digest, &digestlen); 40 | 41 | EVP_DigestUpdate(&outer, digest, digestlen); 42 | } 43 | 44 | digestlen = sizeof digest; 45 | EVP_DigestFinal(&outer, digest, &digestlen); 46 | 47 | printf("%s(%zu) = ", name, max); 48 | printhex(digest, (size_t) digestlen); 49 | printf("\n"); 50 | } 51 | 52 | int main(void) 53 | { 54 | emit_length_test("SHA1", EVP_sha1(), MAX_LENGTH); 55 | emit_length_test("SHA224", EVP_sha224(), MAX_LENGTH); 56 | emit_length_test("SHA256", EVP_sha256(), MAX_LENGTH); 57 | emit_length_test("SHA384", EVP_sha384(), MAX_LENGTH); 58 | emit_length_test("SHA512", EVP_sha512(), MAX_LENGTH); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -g -O0 -std=gnu99 -fPIC -Wall -Wextra -Werror \ 2 | -Wno-unused-parameter -Wno-missing-field-initializers 3 | CPPFLAGS += -I./ext 4 | 5 | ifdef WITH_ASAN 6 | LDFLAGS += -fsanitize=address 7 | CFLAGS += -fsanitize=address 8 | endif 9 | 10 | ifdef WITH_COVERAGE 11 | LDFLAGS += -coverage 12 | CFLAGS += -coverage 13 | endif 14 | 15 | ifdef WITH_VALGRIND 16 | VALGRIND := valgrind --leak-check=full --show-reachable=yes --track-origins=yes 17 | TEST_OPT := --no-exec 18 | endif 19 | 20 | TARGETS = testaes testmodes testsha1 testsha2 testsha3 testsalsa20 \ 21 | testcurve25519 testpoly1305 testnorx testchacha20poly1305 \ 22 | testdrbg testshake 23 | all: $(TARGETS) 24 | 25 | SOURCES = aes.o sha256.o sha512.o chash.o hmac.o pbkdf2.o modes.o eax.o \ 26 | gf128.o blockwise.o cmac.o salsa20.o chacha20.o curve25519.o \ 27 | gcm.o cbcmac.o ccm.o sha3.o sha1.o poly1305.o \ 28 | norx.o chacha20poly1305.o drbg.o ocb.o sha3_shake.o 29 | 30 | testaes: $(SOURCES) testaes.o 31 | testmodes: $(SOURCES) testmodes.o 32 | testsha1: $(SOURCES) testsha1.o 33 | testsha2: $(SOURCES) testsha2.o 34 | testsha3: $(SOURCES) testsha3.o 35 | testshake: $(SOURCES) testshake.o 36 | testsalsa20: $(SOURCES) testsalsa20.o 37 | testcurve25519: $(SOURCES) testcurve25519.o 38 | testpoly1305: $(SOURCES) testpoly1305.o 39 | testnorx: $(SOURCES) testnorx.o 40 | testchacha20poly1305: $(SOURCES) testchacha20poly1305.o 41 | testdrbg: $(SOURCES) testdrbg.o 42 | 43 | clean: 44 | rm -f *.o *.pyc $(TARGETS) *.gcov *.gcda *.gcno 45 | 46 | test: $(TARGETS) 47 | for x in $(TARGETS) ; do \ 48 | echo "Running $$x" ; \ 49 | $(VALGRIND) ./$$x $(TEST_OPT) ; \ 50 | done 51 | 52 | cover: test 53 | gcov *.c 54 | echo 'Lines with missing coverage:' 55 | grep '#####' *.gcov | grep -vE '(cutest|testutil).h.gcov' 56 | -------------------------------------------------------------------------------- /src/prp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef PRP_H 16 | #define PRP_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * General block cipher description 23 | * ================================ 24 | * This allows us to implement block cipher modes which can work 25 | * with different block ciphers. 26 | */ 27 | 28 | /* .. c:type:: cf_prp_block 29 | * Block processing function type. 30 | * 31 | * The `in` and `out` blocks may alias. 32 | * 33 | * :rtype: void 34 | * :param ctx: block cipher-specific context object. 35 | * :param in: input block. 36 | * :param out: output block. 37 | */ 38 | typedef void (*cf_prp_block)(void *ctx, const uint8_t *in, uint8_t *out); 39 | 40 | /* .. c:type:: cf_prp 41 | * Describes an PRP in a general way. 42 | * 43 | * .. c:member:: cf_prp.blocksz 44 | * Block size in bytes. Must be no more than :c:macro:`CF_MAXBLOCK`. 45 | * 46 | * .. c:member:: cf_prp.encrypt 47 | * Block encryption function. 48 | * 49 | * .. c:member:: cf_prp.decrypt 50 | * Block decryption function. 51 | */ 52 | typedef struct 53 | { 54 | size_t blocksz; 55 | cf_prp_block encrypt; 56 | cf_prp_block decrypt; 57 | } cf_prp; 58 | 59 | /* .. c:macro:: CF_MAXBLOCK 60 | * The maximum block cipher blocksize we support, in bytes. 61 | */ 62 | #define CF_MAXBLOCK 16 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/gf128.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef GF128_H 16 | #define GF128_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * @brief Operations in GF(2^128). 23 | * 24 | * These implementations are constant time, but relatively slow. 25 | */ 26 | 27 | typedef uint32_t cf_gf128[4]; 28 | 29 | /* Unpack from big-endian bytes into out. */ 30 | void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out); 31 | 32 | /* Pack in big-endian order into out. */ 33 | void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]); 34 | 35 | /* out = 2 * in. Arguments may not alias. */ 36 | void cf_gf128_double(const cf_gf128 in, cf_gf128 out); 37 | 38 | /* out = 2 * in. Arguments may not alias. 39 | * This differs from cf_gf128_double because it interprets the 40 | * block in little endian: the lsb is the msb of the 41 | * first element, the msb is the lsb of the last element. 42 | * 43 | * GCM uses this convention. */ 44 | void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out); 45 | 46 | /* out = x + y. Arguments may alias. */ 47 | void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out); 48 | 49 | /* out = xy. Arguments may alias. 50 | * 51 | * This uses cf_gf128_double_le internally, and is suitable for 52 | * GCM. */ 53 | void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/testcurve25519.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "curve25519.h" 16 | #include "handy.h" 17 | #include "cutest.h" 18 | #include "testutil.h" 19 | 20 | static void test_base_mul(void) 21 | { 22 | uint8_t secret[32]; 23 | uint8_t public[32]; 24 | uint8_t expect[32]; 25 | 26 | unhex(secret, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"); 27 | unhex(expect, 32, "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"); 28 | cf_curve25519_mul_base(public, secret); 29 | TEST_CHECK(memcmp(expect, public, 32) == 0); 30 | 31 | unhex(secret, 32, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"); 32 | unhex(expect, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"); 33 | cf_curve25519_mul_base(public, secret); 34 | TEST_CHECK(memcmp(expect, public, 32) == 0); 35 | } 36 | 37 | static void test_mul(void) 38 | { 39 | uint8_t scalar[32]; 40 | uint8_t public[32]; 41 | uint8_t shared[32]; 42 | uint8_t expect[32]; 43 | 44 | unhex(scalar, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"); 45 | unhex(public, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"); 46 | unhex(expect, 32, "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); 47 | cf_curve25519_mul(shared, scalar, public); 48 | TEST_CHECK(memcmp(expect, shared, 32) == 0); 49 | } 50 | 51 | TEST_LIST = { 52 | { "base-mul", test_base_mul }, 53 | { "mul", test_mul }, 54 | { 0 } 55 | }; 56 | 57 | -------------------------------------------------------------------------------- /src/cf_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef CF_CONFIG_H 16 | #define CF_CONFIG_H 17 | 18 | /** 19 | * Library configuration 20 | * ===================== 21 | */ 22 | 23 | /* .. c:macro:: CF_SIDE_CHANNEL_PROTECTION 24 | * Define this as 1 if you need all available side channel protections. 25 | * **This option may alter the ABI**. 26 | * 27 | * This has a non-trivial performance penalty. Where a 28 | * side-channel free option is cheap or free (like checking 29 | * a MAC) this is always done in a side-channel free way. 30 | * 31 | * The default is **on** for all available protections. 32 | */ 33 | #ifndef CF_SIDE_CHANNEL_PROTECTION 34 | # define CF_SIDE_CHANNEL_PROTECTION 1 35 | #endif 36 | 37 | /* .. c:macro:: CF_TIME_SIDE_CHANNEL_PROTECTION 38 | * Define this as 1 if you need timing/branch prediction side channel 39 | * protection. 40 | * 41 | * You probably want this. The default is on. */ 42 | #ifndef CF_TIME_SIDE_CHANNEL_PROTECTION 43 | # define CF_TIME_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION 44 | #endif 45 | 46 | /* .. c:macro:: CF_CACHE_SIDE_CHANNEL_PROTECTION 47 | * Define this as 1 if you need cache side channel protection. 48 | * 49 | * If you have a microcontroller with no cache, you can turn this off 50 | * without negative effects. 51 | * 52 | * The default is on. This will have some performance impact, 53 | * especially on AES. 54 | */ 55 | #ifndef CF_CACHE_SIDE_CHANNEL_PROTECTION 56 | # define CF_CACHE_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/ext/handy.h: -------------------------------------------------------------------------------- 1 | #ifndef HANDY_H 2 | #define HANDY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | * Handy CPP defines and C inline functions. 10 | */ 11 | 12 | /* Evaluates to the number of items in array-type variable arr. */ 13 | #define ARRAYCOUNT(arr) (sizeof arr / sizeof arr[0]) 14 | 15 | /* Normal MIN/MAX macros. Evaluate argument expressions only once. */ 16 | #ifndef MIN 17 | #define MIN(x, y) \ 18 | ({ typeof (x) __x = (x); \ 19 | typeof (y) __y = (y); \ 20 | __x < __y ? __x : __y; }) 21 | #endif 22 | #ifndef MAX 23 | #define MAX(x, y) \ 24 | ({ typeof (x) __x = (x); \ 25 | typeof (y) __y = (y); \ 26 | __x > __y ? __x : __y; }) 27 | #endif 28 | 29 | /* Swap two values. Uses GCC type inference magic. */ 30 | #ifndef SWAP 31 | #define SWAP(x, y) \ 32 | do { \ 33 | typeof (x) __tmp = (x); \ 34 | (x) = (y); \ 35 | (y) = __tmp; \ 36 | } while (0) 37 | #endif 38 | 39 | /** Stringify its argument. */ 40 | #define STRINGIFY(x) STRINGIFY_(x) 41 | #define STRINGIFY_(x) #x 42 | 43 | /* Error handling macros. 44 | * 45 | * These expect a zero = success, non-zero = error convention. 46 | */ 47 | 48 | /** Error: return. 49 | * 50 | * If the expression fails, return the error from this function. */ 51 | #define ER(expr) do { typeof (expr) err_ = (expr); if (err_) return err_; } while (0) 52 | 53 | /** Error: goto. 54 | * 55 | * If the expression fails, goto x_err. Assumes defn of label 56 | * x_err and 'error_type err'. */ 57 | #define EG(expr) do { err = (expr); if (err) goto x_err; } while (0) 58 | 59 | /** Like memset(ptr, 0, len), but not allowed to be removed by 60 | * compilers. */ 61 | static inline void mem_clean(volatile void *v, size_t len) 62 | { 63 | if (len) 64 | { 65 | memset((void *) v, 0, len); 66 | (void) *((volatile uint8_t *) v); 67 | } 68 | } 69 | 70 | /** Returns 1 if len bytes at va equal len bytes at vb, 0 if they do not. 71 | * Does not leak length of common prefix through timing. */ 72 | static inline unsigned mem_eq(const void *va, const void *vb, size_t len) 73 | { 74 | const volatile uint8_t *a = va; 75 | const volatile uint8_t *b = vb; 76 | uint8_t diff = 0; 77 | 78 | while (len--) 79 | { 80 | diff |= *a++ ^ *b++; 81 | } 82 | 83 | return !diff; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/hmac.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef HMAC_H 16 | #define HMAC_H 17 | 18 | #include 19 | #include 20 | 21 | #include "chash.h" 22 | 23 | /** 24 | * HMAC 25 | * ==== 26 | * This is a one-shot and incremental interface to computing 27 | * HMAC with any hash function. 28 | * 29 | * (Note: HMAC with SHA3 is possible, but is probably not a 30 | * sensible thing to want.) 31 | */ 32 | 33 | /* .. c:type:: cf_hmac_ctx 34 | * HMAC incremental interface context. 35 | * 36 | * .. c:member:: cf_hmac_ctx.hash 37 | * Hash function description. 38 | * 39 | * .. c:member:: cf_hmac_ctx.inner 40 | * Inner hash computation. 41 | * 42 | * .. c:member:: cf_hmac_ctx.outer 43 | * Outer hash computation. 44 | */ 45 | typedef struct 46 | { 47 | const cf_chash *hash; 48 | cf_chash_ctx inner; 49 | cf_chash_ctx outer; 50 | } cf_hmac_ctx; 51 | 52 | /* .. c:function:: $DECL 53 | * Set up ctx for computing a HMAC using the given hash and key. */ 54 | void cf_hmac_init(cf_hmac_ctx *ctx, 55 | const cf_chash *hash, 56 | const uint8_t *key, size_t nkey); 57 | 58 | /* .. c:function:: $DECL 59 | * Input data. */ 60 | void cf_hmac_update(cf_hmac_ctx *ctx, 61 | const void *data, size_t ndata); 62 | 63 | /* .. c:function:: $DECL 64 | * Finish and compute HMAC. 65 | * `ctx->hash->hashsz` bytes are written to `out`. */ 66 | void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out); 67 | 68 | /* .. c:function:: $DECL 69 | * One shot interface: compute `HMAC_hash(key, msg)`, writing the 70 | * answer (which is `hash->hashsz` long) to `out`. 71 | * 72 | * This function does not fail. */ 73 | void cf_hmac(const uint8_t *key, size_t nkey, 74 | const uint8_t *msg, size_t nmsg, 75 | uint8_t *out, 76 | const cf_chash *hash); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/pbkdf2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "pbkdf2.h" 16 | #include "hmac.h" 17 | #include "bitops.h" 18 | #include "handy.h" 19 | #include "tassert.h" 20 | 21 | #include 22 | 23 | static void F(const cf_hmac_ctx *startctx, 24 | uint32_t counter, 25 | const uint8_t *salt, size_t nsalt, 26 | uint32_t iterations, 27 | uint8_t *out) 28 | { 29 | uint8_t U[CF_MAXHASH]; 30 | size_t hashsz = startctx->hash->hashsz; 31 | 32 | uint8_t countbuf[4]; 33 | write32_be(counter, countbuf); 34 | 35 | /* First iteration: 36 | * U_1 = PRF(P, S || INT_32_BE(i)) 37 | */ 38 | cf_hmac_ctx ctx = *startctx; 39 | cf_hmac_update(&ctx, salt, nsalt); 40 | cf_hmac_update(&ctx, countbuf, sizeof countbuf); 41 | cf_hmac_finish(&ctx, U); 42 | memcpy(out, U, hashsz); 43 | 44 | /* Subsequent iterations: 45 | * U_c = PRF(P, U_{c-1}) 46 | */ 47 | for (uint32_t i = 1; i < iterations; i++) 48 | { 49 | ctx = *startctx; 50 | cf_hmac_update(&ctx, U, hashsz); 51 | cf_hmac_finish(&ctx, U); 52 | xor_bb(out, out, U, hashsz); 53 | } 54 | } 55 | 56 | void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw, 57 | const uint8_t *salt, size_t nsalt, 58 | uint32_t iterations, 59 | uint8_t *out, size_t nout, 60 | const cf_chash *hash) 61 | { 62 | uint32_t counter = 1; 63 | uint8_t block[CF_MAXHASH]; 64 | 65 | assert(iterations); 66 | assert(out && nout); 67 | assert(hash); 68 | 69 | /* Starting point for inner loop. */ 70 | cf_hmac_ctx ctx; 71 | cf_hmac_init(&ctx, hash, pw, npw); 72 | 73 | while (nout) 74 | { 75 | F(&ctx, counter, salt, nsalt, iterations, block); 76 | 77 | size_t taken = MIN(nout, hash->hashsz); 78 | memcpy(out, block, taken); 79 | out += taken; 80 | nout -= taken; 81 | counter++; 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/testsha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "sha1.h" 16 | #include "hmac.h" 17 | #include "handy.h" 18 | #include "cutest.h" 19 | #include "testutil.h" 20 | 21 | #include "testsha.h" 22 | 23 | static void test_sha1(void) 24 | { 25 | const cf_chash *h = &cf_sha1; 26 | vector(h, "", 0, "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09", 20); 27 | vector(h, "abc", 3, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20); 28 | vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, 29 | "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", 20); 30 | vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, 31 | "\xa4\x9b\x24\x46\xa0\x2c\x64\x5b\xf4\x19\xf9\x95\xb6\x70\x91\x25\x3a\x04\xa2\x59", 20); 32 | 33 | vector_abc_final(h, cf_sha1_digest_final, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20); 34 | 35 | vector_length(h, 1024, "\x15\x53\x65\xcf\x77\xee\xd4\x8f\x46\xe2\x55\xc7\xdd\xdf\xfd\x0a\xf6\x99\x88\xbe", 20); 36 | } 37 | 38 | static void test_hmac_sha1(void) 39 | { 40 | hmac_test(&cf_sha1, 41 | "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00", 42 | "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", 43 | "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3", 44 | "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"); 45 | hmac_test_sha1(&cf_sha1, 46 | "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12", 47 | "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"); 48 | } 49 | 50 | TEST_LIST = { 51 | { "sha1", test_sha1}, 52 | { "hmac-sha1", test_hmac_sha1}, 53 | { 0 } 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /src/cbcmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "handy.h" 16 | #include "prp.h" 17 | #include "modes.h" 18 | #include "bitops.h" 19 | #include "blockwise.h" 20 | #include "gf128.h" 21 | #include "tassert.h" 22 | 23 | #include 24 | 25 | void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx) 26 | { 27 | memset(ctx, 0, sizeof *ctx); 28 | ctx->prp = prp; 29 | ctx->prpctx = prpctx; 30 | cf_cbcmac_stream_reset(ctx); 31 | } 32 | 33 | void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx) 34 | { 35 | uint8_t iv_zero[CF_MAXBLOCK] = { 0 }; 36 | cf_cbc_init(&ctx->cbc, ctx->prp, ctx->prpctx, iv_zero); 37 | mem_clean(ctx->buffer, sizeof ctx->buffer); 38 | ctx->used = 0; 39 | } 40 | 41 | static void cbcmac_process(void *vctx, const uint8_t *block) 42 | { 43 | cf_cbcmac_stream *ctx = vctx; 44 | uint8_t output[CF_MAXBLOCK]; 45 | cf_cbc_encrypt(&ctx->cbc, block, output, 1); 46 | } 47 | 48 | void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t len) 49 | { 50 | cf_blockwise_accumulate(ctx->buffer, &ctx->used, ctx->prp->blocksz, 51 | data, len, 52 | cbcmac_process, 53 | ctx); 54 | } 55 | 56 | void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx) 57 | { 58 | if (ctx->used == 0) 59 | return; 60 | 61 | memset(ctx->buffer + ctx->used, 0, ctx->prp->blocksz - ctx->used); 62 | cbcmac_process(ctx, ctx->buffer); 63 | ctx->used = 0; 64 | } 65 | 66 | void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) 67 | { 68 | assert(ctx->used == 0); 69 | memcpy(out, ctx->cbc.block, ctx->prp->blocksz); 70 | } 71 | 72 | void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) 73 | { 74 | uint8_t npad = ctx->prp->blocksz - ctx->used; 75 | cf_blockwise_acc_byte(ctx->buffer, &ctx->used, ctx->prp->blocksz, 76 | npad, npad, 77 | cbcmac_process, ctx); 78 | cf_cbcmac_stream_nopad_final(ctx, out); 79 | } 80 | -------------------------------------------------------------------------------- /src/poly1305.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef POLY1305_H 16 | #define POLY1305_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * Poly1305 23 | * ======== 24 | * This is an incremental interface to computing the poly1305 25 | * single shot MAC. 26 | * 27 | * Note: construct Poly1305-AES with this by taking a 16 byte 28 | * nonce and encrypting it, and then using the result as an 29 | * input to this function. 30 | */ 31 | 32 | /* .. c:type:: cf_poly1305 33 | * Poly1305 incremental interface context. 34 | * 35 | * .. c:member:: cf_poly1305.h 36 | * Current accumulator. 37 | * 38 | * .. c:member:: cf_poly1305.r 39 | * Block multiplier. 40 | * 41 | * .. c:member:: cf_poly1305.s 42 | * Final XOR offset. 43 | * 44 | * .. c:member:: cf_poly1305.partial 45 | * Unprocessed input. 46 | * 47 | * .. c:member:: cf_poly1305.npartial 48 | * Number of bytes of unprocessed input. 49 | * 50 | */ 51 | typedef struct 52 | { 53 | uint32_t h[17]; 54 | uint32_t r[17]; 55 | uint8_t s[16]; 56 | uint8_t partial[16]; 57 | size_t npartial; 58 | } cf_poly1305; 59 | 60 | /* .. c:function:: $DECL 61 | * Sets up `ctx` ready to compute a new MAC. 62 | * 63 | * In Poly1305-AES, `r` is the second half of the 32-byte key. 64 | * `s` is a nonce encrypted under the first half of the key. 65 | * 66 | * :param ctx: context (written) 67 | * :param r: MAC key. 68 | * :param s: preprocessed nonce. 69 | * 70 | */ 71 | void cf_poly1305_init(cf_poly1305 *ctx, 72 | const uint8_t r[static 16], 73 | const uint8_t s[static 16]); 74 | 75 | /* .. c:function:: $DECL 76 | * Processes `nbytes` at `data`. Copies the data if there isn't enough to make 77 | * a full block. 78 | */ 79 | void cf_poly1305_update(cf_poly1305 *ctx, 80 | const uint8_t *data, 81 | size_t nbytes); 82 | 83 | /* .. c:function:: $DECL 84 | * Finishes the operation, writing 16 bytes to `out`. 85 | * 86 | * This destroys `ctx`. 87 | */ 88 | void cf_poly1305_finish(cf_poly1305 *ctx, 89 | uint8_t out[static 16]); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef SHA1_H 16 | #define SHA1_H 17 | 18 | #include 19 | #include 20 | 21 | #include "chash.h" 22 | 23 | /** 24 | * SHA1 25 | * ==== 26 | * 27 | * You shouldn't use this for anything new. 28 | */ 29 | 30 | /* .. c:macro:: CF_SHA1_HASHSZ 31 | * The output size of SHA1: 20 bytes. */ 32 | #define CF_SHA1_HASHSZ 20 33 | 34 | /* .. c:macro:: CF_SHA1_BLOCKSZ 35 | * The block size of SHA1: 64 bytes. */ 36 | #define CF_SHA1_BLOCKSZ 64 37 | 38 | /* .. c:type:: cf_sha1_context 39 | * Incremental SHA1 hashing context. 40 | * 41 | * .. c:member:: cf_sha1_context.H 42 | * Intermediate values. 43 | * 44 | * .. c:member:: cf_sha1_context.partial 45 | * Unprocessed input. 46 | * 47 | * .. c:member:: cf_sha1_context.npartial 48 | * Number of bytes of unprocessed input. 49 | * 50 | * .. c:member:: cf_sha1_context.blocks 51 | * Number of full blocks processed. 52 | */ 53 | typedef struct 54 | { 55 | uint32_t H[5]; /* State. */ 56 | uint8_t partial[CF_SHA1_BLOCKSZ]; /* Partial block of input. */ 57 | uint32_t blocks; /* Number of full blocks processed into H. */ 58 | size_t npartial; /* Number of bytes in prefix of partial. */ 59 | } cf_sha1_context; 60 | 61 | /* .. c:function:: $DECL 62 | * Sets up `ctx` ready to hash a new message. 63 | */ 64 | extern void cf_sha1_init(cf_sha1_context *ctx); 65 | 66 | /* .. c:function:: $DECL 67 | * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make 68 | * a full block. 69 | */ 70 | extern void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes); 71 | 72 | /* .. c:function:: $DECL 73 | * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`. 74 | * 75 | * This leaves `ctx` unchanged. 76 | */ 77 | extern void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]); 78 | 79 | /* .. c:function:: $DECL 80 | * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`. 81 | * 82 | * This destroys `ctx`, but uses less stack than :c:func:`cf_sha1_digest`. 83 | */ 84 | extern void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]); 85 | 86 | /* .. c:var:: cf_sha1 87 | * Abstract interface to SHA1. See :c:type:`cf_chash` for more information. 88 | */ 89 | extern const cf_chash cf_sha1; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/sha3_shake.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2020 by Silex Insight. 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "sha3_shake.h" 16 | #include "handy.h" 17 | #include "tassert.h" 18 | 19 | /* function prototypes */ 20 | extern void sha3_init(cf_sha3_context *, uint16_t, uint16_t); 21 | extern void sha3_update(cf_sha3_context *, const void *, size_t); 22 | extern void pad_and_squeeze(cf_sha3_context *, uint8_t *, size_t); 23 | 24 | /* SHAKE 128 */ 25 | void cf_shake_128_init(cf_sha3_context *ctx) 26 | { 27 | sha3_init(ctx, 1344, 256); 28 | ctx->domain_pad = DOMAIN_SHAKE_PAD; 29 | } 30 | 31 | void cf_shake_128_update(cf_sha3_context *ctx, const void *data, size_t nbytes) 32 | { 33 | sha3_update(ctx, data, nbytes); 34 | } 35 | 36 | void cf_shake_128_digest(const cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes) 37 | { 38 | cf_sha3_context ours = *ctx; 39 | cf_shake_128_digest_final(&ours, hash, noutbytes); 40 | } 41 | 42 | void cf_shake_128_digest_final(cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes) 43 | { 44 | pad_and_squeeze(ctx, hash, noutbytes); 45 | } 46 | 47 | const cf_cshake cf_shake_128 = { 48 | .blocksz = CF_SHAKE_128_BLOCKSZ, 49 | .init = (cf_cshake_init) cf_shake_128_init, 50 | .update = (cf_cshake_update) cf_shake_128_update, 51 | .digest = (cf_cshake_digest) cf_shake_128_digest 52 | }; 53 | 54 | /* SHAKE 256 */ 55 | void cf_shake_256_init(cf_sha3_context *ctx) 56 | { 57 | sha3_init(ctx, 1088, 512); 58 | ctx->domain_pad = DOMAIN_SHAKE_PAD; 59 | } 60 | 61 | void cf_shake_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes) 62 | { 63 | sha3_update(ctx, data, nbytes); 64 | } 65 | 66 | void cf_shake_256_digest(const cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes) 67 | { 68 | cf_sha3_context ours = *ctx; 69 | cf_shake_256_digest_final(&ours, hash, noutbytes); 70 | } 71 | 72 | void cf_shake_256_digest_final(cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes) 73 | { 74 | pad_and_squeeze(ctx, hash, noutbytes); 75 | } 76 | 77 | const cf_cshake cf_shake_256 = { 78 | .blocksz = CF_SHAKE_256_BLOCKSZ, 79 | .init = (cf_cshake_init) cf_shake_256_init, 80 | .update = (cf_cshake_update) cf_shake_256_update, 81 | .digest = (cf_cshake_digest) cf_shake_256_digest 82 | }; 83 | 84 | /* one-shot shake function */ 85 | void cf_shake(const cf_cshake *h, const void *m, size_t nm, uint8_t *out, size_t nout) 86 | { 87 | cf_sha3_context ctx; 88 | assert(h); 89 | h->init(&ctx); 90 | h->update(&ctx, m, nm); 91 | h->digest(&ctx, out, nout); 92 | mem_clean(&ctx, sizeof ctx); 93 | } 94 | -------------------------------------------------------------------------------- /src/chacha20poly1305.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef CHACHA20POLY1305_H 16 | #define CHACHA20POLY1305_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * The ChaCha20-Poly1305 AEAD construction 23 | * ======================================= 24 | * This is a composition of the ChaCha20 stream cipher and 25 | * the Poly1305 polynomial MAC to form an AEAD. 26 | * It's specified for use in TLS in the form of RFC7539. 27 | * 28 | * It uses a 256-bit key and a 96-bit nonce. 29 | * 30 | * This is a one-shot interface. 31 | */ 32 | 33 | /* .. c:function:: $DECL 34 | * ChaCha20-Poly1305 authenticated encryption. 35 | * 36 | * :param key: key material. 37 | * :param nonce: per-message nonce. 38 | * :param header: header buffer. 39 | * :param nheader: number of header bytes. 40 | * :param plaintext: plaintext bytes to be encrypted. 41 | * :param nbytes: number of plaintext/ciphertext bytes. 42 | * :param ciphertext: ciphertext output buffer, nbytes in length. 43 | * :param tag: authentication tag output buffer. 44 | */ 45 | void cf_chacha20poly1305_encrypt(const uint8_t key[static 32], 46 | const uint8_t nonce[static 12], 47 | const uint8_t *header, size_t nheader, 48 | const uint8_t *plaintext, size_t nbytes, 49 | uint8_t *ciphertext, 50 | uint8_t tag[static 16]); 51 | 52 | /* .. c:function:: $DECL 53 | * ChaCha20-Poly1305 authenticated decryption. 54 | * 55 | * :return: 0 on success, non-zero on error. Plaintext is zeroed on error. 56 | * 57 | * :param key: key material. 58 | * :param nonce: per-message nonce. 59 | * :param header: header buffer. 60 | * :param nheader: number of header bytes. 61 | * :param ciphertext: ciphertext bytes to be decrypted. 62 | * :param nbytes: number of plaintext/ciphertext bytes. 63 | * :param plaintext: plaintext output buffer, nbytes in length. 64 | * :param tag: authentication tag output buffer. 65 | */ 66 | int cf_chacha20poly1305_decrypt(const uint8_t key[static 32], 67 | const uint8_t nonce[static 12], 68 | const uint8_t *header, size_t nheader, 69 | const uint8_t *ciphertext, size_t nbytes, 70 | const uint8_t tag[static 16], 71 | uint8_t *plaintext); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/modes.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "prp.h" 16 | #include "modes.h" 17 | #include "bitops.h" 18 | #include "blockwise.h" 19 | 20 | #include 21 | #include "tassert.h" 22 | 23 | /* CBC */ 24 | void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]) 25 | { 26 | ctx->prp = prp; 27 | ctx->prpctx = prpctx; 28 | memcpy(ctx->block, iv, prp->blocksz); 29 | } 30 | 31 | void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks) 32 | { 33 | uint8_t buf[CF_MAXBLOCK]; 34 | size_t nblk = ctx->prp->blocksz; 35 | 36 | while (blocks--) 37 | { 38 | xor_bb(buf, input, ctx->block, nblk); 39 | ctx->prp->encrypt(ctx->prpctx, buf, ctx->block); 40 | memcpy(output, ctx->block, nblk); 41 | input += nblk; 42 | output += nblk; 43 | } 44 | } 45 | 46 | void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks) 47 | { 48 | uint8_t buf[CF_MAXBLOCK]; 49 | size_t nblk = ctx->prp->blocksz; 50 | 51 | while (blocks--) 52 | { 53 | ctx->prp->decrypt(ctx->prpctx, input, buf); 54 | xor_bb(output, buf, ctx->block, nblk); 55 | memcpy(ctx->block, input, nblk); 56 | input += nblk; 57 | output += nblk; 58 | } 59 | } 60 | 61 | /* CTR */ 62 | void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]) 63 | { 64 | memset(ctx, 0, sizeof *ctx); 65 | ctx->counter_offset = 0; 66 | ctx->counter_width = prp->blocksz; 67 | ctx->prp = prp; 68 | ctx->prpctx = prpctx; 69 | ctx->nkeymat = 0; 70 | memcpy(ctx->nonce, nonce, prp->blocksz); 71 | } 72 | 73 | void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width) 74 | { 75 | assert(ctx->prp->blocksz <= offset + width); 76 | ctx->counter_offset = offset; 77 | ctx->counter_width = width; 78 | } 79 | 80 | static void ctr_next_block(void *vctx, uint8_t *out) 81 | { 82 | cf_ctr *ctx = vctx; 83 | ctx->prp->encrypt(ctx->prpctx, ctx->nonce, out); 84 | incr_be(ctx->nonce + ctx->counter_offset, ctx->counter_width); 85 | } 86 | 87 | void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes) 88 | { 89 | cf_blockwise_xor(ctx->keymat, &ctx->nkeymat, 90 | ctx->prp->blocksz, 91 | input, output, bytes, 92 | ctr_next_block, 93 | ctx); 94 | } 95 | 96 | void cf_ctr_discard_block(cf_ctr *ctx) 97 | { 98 | ctx->nkeymat = 0; 99 | } 100 | -------------------------------------------------------------------------------- /src/hmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "hmac.h" 16 | #include "chash.h" 17 | #include "bitops.h" 18 | #include "handy.h" 19 | #include "tassert.h" 20 | 21 | #include 22 | 23 | void cf_hmac_init(cf_hmac_ctx *ctx, 24 | const cf_chash *hash, 25 | const uint8_t *key, size_t nkey) 26 | { 27 | assert(ctx); 28 | assert(hash); 29 | 30 | mem_clean(ctx, sizeof *ctx); 31 | ctx->hash = hash; 32 | 33 | /* Prepare key: */ 34 | uint8_t k[CF_CHASH_MAXBLK]; 35 | 36 | /* Shorten long keys. */ 37 | if (nkey > hash->blocksz) 38 | { 39 | /* Standard doesn't cover case where blocksz < hashsz. 40 | * FIPS186-1 seems to want to append a negative number of zero bytes. 41 | * In any case, we only have a k buffer of CF_CHASH_MAXBLK! */ 42 | assert(hash->hashsz <= hash->blocksz); 43 | 44 | cf_hash(hash, key, nkey, k); 45 | key = k; 46 | nkey = hash->hashsz; 47 | } 48 | 49 | /* Right zero-pad short keys. */ 50 | if (k != key) 51 | memcpy(k, key, nkey); 52 | if (hash->blocksz > nkey) 53 | memset(k + nkey, 0, hash->blocksz - nkey); 54 | 55 | /* Start inner hash computation */ 56 | uint8_t blk[CF_CHASH_MAXBLK]; 57 | 58 | xor_b8(blk, k, 0x36, hash->blocksz); 59 | hash->init(&ctx->inner); 60 | hash->update(&ctx->inner, blk, hash->blocksz); 61 | 62 | /* And outer. */ 63 | xor_b8(blk, k, 0x5c, hash->blocksz); 64 | hash->init(&ctx->outer); 65 | hash->update(&ctx->outer, blk, hash->blocksz); 66 | 67 | mem_clean(blk, sizeof blk); 68 | mem_clean(k, sizeof k); 69 | } 70 | 71 | void cf_hmac_update(cf_hmac_ctx *ctx, const void *data, size_t ndata) 72 | { 73 | assert(ctx && ctx->hash); 74 | 75 | ctx->hash->update(&ctx->inner, data, ndata); 76 | } 77 | 78 | void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out) 79 | { 80 | assert(ctx && ctx->hash); 81 | assert(out); 82 | 83 | uint8_t innerh[CF_MAXHASH]; 84 | ctx->hash->digest(&ctx->inner, innerh); 85 | 86 | ctx->hash->update(&ctx->outer, innerh, ctx->hash->hashsz); 87 | ctx->hash->digest(&ctx->outer, out); 88 | 89 | mem_clean(ctx, sizeof *ctx); 90 | } 91 | 92 | void cf_hmac(const uint8_t *key, size_t nkey, 93 | const uint8_t *msg, size_t nmsg, 94 | uint8_t *out, 95 | const cf_chash *hash) 96 | { 97 | cf_hmac_ctx ctx; 98 | 99 | assert(out); 100 | assert(hash); 101 | 102 | cf_hmac_init(&ctx, hash, key, nkey); 103 | cf_hmac_update(&ctx, msg, nmsg); 104 | cf_hmac_finish(&ctx, out); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/norx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef NORX_H 16 | #define NORX_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * The NORX AEAD cipher 23 | * ==================== 24 | * This is an implementation of NORX32-4-1 with a one-shot 25 | * interface. NORX is a CAESAR candidate with a core similar 26 | * to ChaCha20 and a sponge structure like Keccak. 27 | * 28 | * This is NORX v2.0. It is not compatible with earlier 29 | * versions. 30 | * 31 | * NORX32 uses a 128-bit key. Each encryption requires a 32 | * 64-bit nonce. An encryption processes one sequence of 33 | * additional data ('header'), followed by encryption of 34 | * the plaintext, followed by processing a second sequence 35 | * of additional data ('trailer'). It outputs a 128-bit 36 | * tag. 37 | */ 38 | 39 | /* .. c:function:: $DECL 40 | * NORX32-4-1 one-shot encryption interface. 41 | * 42 | * :param key: key material. 43 | * :param nonce: per-message nonce. 44 | * :param header: header buffer. 45 | * :param nheader: number of header bytes. 46 | * :param plaintext: plaintext bytes to be encrypted. 47 | * :param nbytes: number of plaintext/ciphertext bytes. 48 | * :param trailer: trailer buffer. 49 | * :param ntrailer: number of trailer bytes. 50 | * :param ciphertext: ciphertext output buffer, nbytes in length. 51 | * :param tag: authentication tag output buffer. 52 | */ 53 | void cf_norx32_encrypt(const uint8_t key[static 16], 54 | const uint8_t nonce[static 8], 55 | const uint8_t *header, size_t nheader, 56 | const uint8_t *plaintext, size_t nbytes, 57 | const uint8_t *trailer, size_t ntrailer, 58 | uint8_t *ciphertext, 59 | uint8_t tag[static 16]); 60 | 61 | /* .. c:function:: $DECL 62 | * NORX32-4-1 one-shot decryption interface. 63 | * 64 | * :return: 0 on success, non-zero on error. Plaintext is zeroed on error. 65 | * 66 | * :param key: key material. 67 | * :param nonce: per-message nonce. 68 | * :param header: header buffer. 69 | * :param nheader: number of header bytes. 70 | * :param ciphertext: ciphertext bytes to be decrypted. 71 | * :param nbytes: number of plaintext/ciphertext bytes. 72 | * :param trailer: trailer buffer. 73 | * :param ntrailer: number of trailer bytes. 74 | * :param plaintext: plaintext output buffer, nbytes in length. 75 | * :param tag: authentication tag output buffer. 76 | */ 77 | int cf_norx32_decrypt(const uint8_t key[static 16], 78 | const uint8_t nonce[static 8], 79 | const uint8_t *header, size_t nheader, 80 | const uint8_t *ciphertext, size_t nbytes, 81 | const uint8_t *trailer, size_t ntrailer, 82 | const uint8_t tag[static 16], 83 | uint8_t *plaintext); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/arm/boot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern int main(void); 6 | 7 | /* --- Defined by link script --- */ 8 | extern uint32_t __etext; /* End of text/start of data. */ 9 | extern uint32_t __data_start__, __data_end__; /* Data addresses in RAM */ 10 | extern uint32_t __bss_start__, __bss_end__; /* BSS addresses in RAM */ 11 | extern uint32_t __StackTop; /* End of stack in RAM */ 12 | 13 | #define ATTR_SECTION(sec) __attribute__ ((section (sec))) 14 | 15 | /* --- Interrupt vector table. --- */ 16 | void Reset_Handler(void); 17 | void SysTick_Handler(void); 18 | void infinite_loop(void); 19 | void do_nothing(void); 20 | 21 | typedef void (*vector_fn)(void); 22 | 23 | typedef struct { 24 | uint32_t *stack_top; 25 | vector_fn reset, nmi, hard_fault, mmu_fault, bus_fault, usage_fault; 26 | vector_fn reserved0[4]; 27 | vector_fn svc, debug_monitor; 28 | vector_fn reserved1; 29 | vector_fn pendsv, systick; 30 | vector_fn irq[128]; 31 | } vectors_t; 32 | 33 | #define COPY2(v) v, v 34 | #define COPY4(v) COPY2(v), COPY2(v) 35 | #define COPY8(v) COPY4(v), COPY4(v) 36 | #define COPY16(v) COPY8(v), COPY8(v) 37 | #define COPY32(v) COPY16(v), COPY16(v) 38 | #define COPY64(v) COPY32(v), COPY32(v) 39 | #define COPY128(v) COPY64(v), COPY64(v) 40 | 41 | vectors_t vectors ATTR_SECTION(".isr_vector") = { 42 | .stack_top = &__StackTop, 43 | .reset = Reset_Handler, 44 | .nmi = do_nothing, 45 | .hard_fault = infinite_loop, 46 | .mmu_fault = infinite_loop, 47 | .bus_fault = infinite_loop, 48 | .usage_fault = infinite_loop, 49 | .svc = do_nothing, 50 | .debug_monitor = do_nothing, 51 | .pendsv = do_nothing, 52 | .systick = SysTick_Handler, 53 | .irq = { COPY128(do_nothing) } 54 | }; 55 | 56 | /* --- ISRs --- */ 57 | void Reset_Handler(void) 58 | { 59 | /* Copy data segment contents from flash to RAM. */ 60 | uint32_t data_bytes = (&__data_end__ - &__data_start__) * 4; 61 | memcpy(&__etext, &__data_start__, data_bytes); 62 | 63 | /* Zero BSS. */ 64 | uint32_t bss_bytes = (&__bss_end__ - &__bss_start__) * 4; 65 | memset(&__bss_start__, 0, bss_bytes); 66 | 67 | main(); 68 | while (1) 69 | ; 70 | } 71 | 72 | void __assert_func(const char *file, int line, const char *func, const char *expr) 73 | { 74 | while (1) 75 | ; 76 | } 77 | 78 | void infinite_loop(void) 79 | { 80 | while (1) 81 | ; 82 | } 83 | 84 | void do_nothing(void) 85 | { 86 | } 87 | 88 | uint32_t ticks = 0; 89 | 90 | void SysTick_Handler(void) 91 | { 92 | ticks++; 93 | } 94 | 95 | uint32_t get_ticks(void) 96 | { 97 | return ticks; 98 | } 99 | 100 | void reset_ticks(void) 101 | { 102 | ticks = 0; 103 | } 104 | 105 | void *memmove(void *vtarg, const void *vsrc, size_t len) 106 | { 107 | if (vsrc > vtarg) 108 | return memcpy(vtarg, vsrc, len); 109 | else if (vsrc == vtarg) 110 | return vtarg; 111 | 112 | uint8_t *targ = vtarg; 113 | const uint8_t *src = vsrc; 114 | 115 | for (size_t i = len; i != 0; i++) 116 | targ[i - 1] = src[i - 1]; 117 | return vtarg; 118 | } 119 | 120 | int memcmp(const void *va, const void *vb, size_t len) 121 | { 122 | const uint8_t *a = va, *b = vb; 123 | 124 | for (size_t i = 0; i < len; i++) 125 | { 126 | if (a[i] != b[i]) 127 | return a[i] < b[i] ? -1 : 1; 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | size_t strlen(const char *c) 134 | { 135 | size_t r = 0; 136 | while (*c++) r++; 137 | return r; 138 | } 139 | 140 | void abort(void) 141 | { 142 | while (1) 143 | ; 144 | } 145 | -------------------------------------------------------------------------------- /src/gf128.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "cf_config.h" 16 | #include "gf128.h" 17 | #include "bitops.h" 18 | 19 | #include 20 | 21 | void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]) 22 | { 23 | write32_be(in[0], out + 0); 24 | write32_be(in[1], out + 4); 25 | write32_be(in[2], out + 8); 26 | write32_be(in[3], out + 12); 27 | } 28 | 29 | void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out) 30 | { 31 | out[0] = read32_be(in + 0); 32 | out[1] = read32_be(in + 4); 33 | out[2] = read32_be(in + 8); 34 | out[3] = read32_be(in + 12); 35 | } 36 | 37 | /* out = 2 * in. Arguments may alias. */ 38 | void cf_gf128_double(const cf_gf128 in, cf_gf128 out) 39 | { 40 | uint8_t table[2] = { 0x00, 0x87 }; 41 | uint32_t borrow = 0; 42 | uint32_t inword; 43 | 44 | inword = in[3]; out[3] = (inword << 1) | borrow; borrow = inword >> 31; 45 | inword = in[2]; out[2] = (inword << 1) | borrow; borrow = inword >> 31; 46 | inword = in[1]; out[1] = (inword << 1) | borrow; borrow = inword >> 31; 47 | inword = in[0]; out[0] = (inword << 1) | borrow; borrow = inword >> 31; 48 | 49 | #if CF_CACHE_SIDE_CHANNEL_PROTECTION 50 | out[3] ^= select_u8(borrow, table, 2); 51 | #else 52 | out[3] ^= table[borrow]; 53 | #endif 54 | } 55 | 56 | /* out = 2 * in. Arguments may alias. */ 57 | void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out) 58 | { 59 | uint8_t table[2] = { 0x00, 0xe1 }; 60 | uint32_t borrow = 0; 61 | uint32_t inword; 62 | 63 | inword = in[0]; out[0] = (inword >> 1) | (borrow << 31); borrow = inword & 1; 64 | inword = in[1]; out[1] = (inword >> 1) | (borrow << 31); borrow = inword & 1; 65 | inword = in[2]; out[2] = (inword >> 1) | (borrow << 31); borrow = inword & 1; 66 | inword = in[3]; out[3] = (inword >> 1) | (borrow << 31); borrow = inword & 1; 67 | 68 | #if CF_CACHE_SIDE_CHANNEL_PROTECTION 69 | out[0] ^= select_u8(borrow, table, 2) << 24; 70 | #else 71 | out[0] ^= table[borrow] << 24; 72 | #endif 73 | } 74 | 75 | /* out = x + y. Arguments may alias. */ 76 | void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out) 77 | { 78 | out[0] = x[0] ^ y[0]; 79 | out[1] = x[1] ^ y[1]; 80 | out[2] = x[2] ^ y[2]; 81 | out[3] = x[3] ^ y[3]; 82 | } 83 | 84 | /* out = xy. Arguments may alias. */ 85 | void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out) 86 | { 87 | #if CF_TIME_SIDE_CHANNEL_PROTECTION 88 | cf_gf128 zero = { 0 }; 89 | #endif 90 | 91 | /* Z_0 = 0^128 92 | * V_0 = Y */ 93 | cf_gf128 Z, V; 94 | memset(Z, 0, sizeof Z); 95 | memcpy(V, y, sizeof V); 96 | 97 | for (int i = 0; i < 128; i++) 98 | { 99 | uint32_t word = x[i >> 5]; 100 | uint8_t bit = (word >> (31 - (i & 31))) & 1; 101 | 102 | #if CF_TIME_SIDE_CHANNEL_PROTECTION 103 | select_xor128(Z, zero, V, bit); 104 | #else 105 | if (bit) 106 | xor_words(Z, V, 4); 107 | #endif 108 | 109 | cf_gf128_double_le(V, V); 110 | } 111 | 112 | memcpy(out, Z, sizeof Z); 113 | } 114 | -------------------------------------------------------------------------------- /src/poly1305.py: -------------------------------------------------------------------------------- 1 | rs = (0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91 2 | ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25 3 | ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65 4 | ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80) 5 | 6 | msg = (0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73 7 | ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce 8 | ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4 9 | ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a 10 | ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b 11 | ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72 12 | ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2 13 | ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38 14 | ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a 15 | ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae 16 | ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea 17 | ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda 18 | ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde 19 | ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3 20 | ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 21 | ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74 22 | ,0xe3,0x55,0xa5) 23 | 24 | tag = (0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5 25 | ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9) 26 | 27 | print len(msg) 28 | 29 | WORD = 0xffffffff 30 | 31 | def add(x, y): 32 | u = 0 33 | r = [0] * 17 34 | for i in range(17): 35 | u += (x[i] + y[i]) & WORD 36 | r[i] = u & 0xff 37 | u >>= 8 38 | return r 39 | 40 | def reduce(x): 41 | r = list(x) 42 | u = 0 43 | 44 | for i in range(16): 45 | u += r[i] 46 | r[i] = u & 0xff 47 | u >>= 8 48 | u += r[16] 49 | r[16] = u & 3 50 | u = 5 * (u >> 2) 51 | 52 | for i in range(16): 53 | u += r[i] 54 | r[i] = u & 0xff 55 | u >>= 8 56 | u += r[16] 57 | r[16] = u 58 | 59 | return r 60 | 61 | def modmul(x, y): 62 | r = [0] * 17 63 | for i in range(17): 64 | u = 0 65 | for j in range(i + 1): 66 | u += (x[j] * y[i - j]) & WORD 67 | for j in range(i + 1, 17): 68 | u += (320 * x[j] * y[i + 17 - j]) & WORD 69 | r[i] = u 70 | return reduce(r) 71 | 72 | def dump(why, v): 73 | print '%s = %s' % (why, ' '.join('%08x' % x for x in v)) 74 | 75 | def freeze(x): 76 | # -2^130 - 5 in twos complement 77 | negative_130_5 = (5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252) 78 | 79 | r = add(x, negative_130_5) 80 | dump('minusp', r) 81 | negative = bool(x[16] >> 7) 82 | if negative: 83 | return r 84 | else: 85 | return x 86 | 87 | def poly1305(msg, rs): 88 | r, s = list(rs[:16]), list(rs[16:]) 89 | 90 | r[3] &= 15 91 | r[4] &= 252 92 | r[7] &= 15 93 | r[8] &= 252 94 | r[11] &= 15 95 | r[12] &= 252 96 | r[15] &= 15 97 | r.append(0) 98 | 99 | h = [0] * 17 100 | dump('r-init', r) 101 | dump('h-init', h) 102 | 103 | block = 0 104 | 105 | for offs in range(0, len(msg), 16): 106 | print '--- block %d ---' % block 107 | block += 1 108 | c = list(msg[offs:offs+16]) 109 | c.append(1) 110 | while len(c) != 17: c.append(0) 111 | dump('c', c) 112 | 113 | h = add(h, c) 114 | dump('after-add', h) 115 | h = modmul(h, r) 116 | dump('after-mul', h) 117 | 118 | dump('end-block', h) 119 | h = freeze(h) 120 | dump('h', h) 121 | s.append(0) 122 | h = add(h, s) 123 | dump('final', h) 124 | return h[:16] 125 | 126 | r = poly1305(msg, rs) 127 | print repr([hex(x) for x in r]) 128 | -------------------------------------------------------------------------------- /src/testnorx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "norx.h" 16 | #include "handy.h" 17 | #include "cutest.h" 18 | #include "testutil.h" 19 | 20 | static void test_vector(void) 21 | { 22 | uint8_t K[16], N[8], A[128], M[128], Z[128], C[128], T[16]; 23 | 24 | /* This is from the v2.0 paper, section A.2. */ 25 | 26 | unhex(K, sizeof K, "000102030405060708090a0b0c0d0e0f"); 27 | unhex(N, sizeof N, "f0e0d0c0b0a09080"); 28 | 29 | for (unsigned i = 0; i < 128; i++) 30 | { 31 | A[i] = M[i] = Z[i] = i; 32 | } 33 | 34 | cf_norx32_encrypt(K, N, 35 | A, sizeof A, 36 | M, sizeof M, 37 | Z, sizeof Z, 38 | C, T); 39 | 40 | uint8_t expect_C[128], expect_T[16]; 41 | 42 | unhex(expect_C, sizeof expect_C, "f4afc8e66d2d80de0a7f719c899624c9ad896ec7c61739d5376d0648c7bcb204e57db05c6f83b3ff4315e8a4ef2f2c855f21ea4c51ac6de575773ba548f36e636a13b979d953bb91298ea4a6e2aa27402991e0da541997825407b2f12441de3ae6c5dbfe41b12f1480d234832765111e4c09deef9fe3971618d2217c4b77921e"); 43 | unhex(expect_T, sizeof expect_T, "7810131eea2eab1e5da05d23d4e3cb99"); 44 | 45 | TEST_CHECK(memcmp(C, expect_C, sizeof C) == 0); 46 | TEST_CHECK(memcmp(T, expect_T, sizeof T) == 0); 47 | 48 | uint8_t M2[128]; 49 | TEST_CHECK(0 == 50 | cf_norx32_decrypt(K, N, 51 | A, sizeof A, 52 | C, sizeof C, 53 | Z, sizeof Z, 54 | T, 55 | M2)); 56 | 57 | TEST_CHECK(memcmp(M, M2, sizeof M) == 0); 58 | T[0] ^= 0xff; 59 | 60 | TEST_CHECK(cf_norx32_decrypt(K, N, 61 | A, sizeof A, 62 | C, sizeof C, 63 | Z, sizeof Z, 64 | T, 65 | M2)); 66 | } 67 | 68 | #include "testnorx.katdata.inc" 69 | 70 | static void test_kat(void) 71 | { 72 | uint8_t K[16], N[16], H[256], W[256]; 73 | const uint8_t *kats = kat_data; 74 | 75 | #define FILL(arr, c) \ 76 | do { \ 77 | for (size_t i = 0; i < sizeof arr; i++) \ 78 | arr[i] = (i * c + 123) & 0xff; \ 79 | } while (0) 80 | FILL(N, 181); 81 | FILL(K, 191); 82 | FILL(H, 193); 83 | FILL(W, 197); 84 | #undef FILL 85 | 86 | for (size_t i = 0; i < sizeof W; i++) 87 | { 88 | uint8_t C[256]; 89 | uint8_t A[16]; 90 | 91 | cf_norx32_encrypt(K, N, 92 | H, i, 93 | W, i, 94 | NULL, 0, 95 | C, A); 96 | 97 | TEST_CHECK(memcmp(kats, C, i) == 0); 98 | kats += i; 99 | TEST_CHECK(memcmp(kats, A, sizeof A) == 0); 100 | kats += sizeof A; 101 | 102 | uint8_t M[256] = { 0 }; 103 | TEST_CHECK(0 == cf_norx32_decrypt(K, N, 104 | H, i, 105 | C, i, 106 | NULL, 0, 107 | A, M)); 108 | 109 | TEST_CHECK(0 == memcmp(M, W, i)); 110 | } 111 | } 112 | 113 | TEST_LIST = { 114 | { "vector", test_vector }, 115 | { "kat", test_kat }, 116 | { 0 } 117 | }; 118 | 119 | -------------------------------------------------------------------------------- /src/eax.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "handy.h" 16 | #include "prp.h" 17 | #include "modes.h" 18 | #include "tassert.h" 19 | 20 | #include 21 | 22 | static void cmac_compute_n(cf_cmac_stream *ctx, 23 | uint8_t t, 24 | const uint8_t *input, size_t ninput, 25 | uint8_t out[CF_MAXBLOCK]) 26 | { 27 | size_t blocksz = ctx->cmac.prp->blocksz; 28 | assert(blocksz > 0); 29 | 30 | uint8_t firstblock[CF_MAXBLOCK]; 31 | memset(firstblock, 0, blocksz); 32 | firstblock[blocksz - 1] = t; 33 | 34 | cf_cmac_stream_reset(ctx); 35 | if (ninput) 36 | { 37 | cf_cmac_stream_update(ctx, firstblock, blocksz, 0); 38 | cf_cmac_stream_update(ctx, input, ninput, 1); 39 | } else { 40 | cf_cmac_stream_update(ctx, firstblock, blocksz, 1); 41 | } 42 | 43 | cf_cmac_stream_final(ctx, out); 44 | } 45 | 46 | void cf_eax_encrypt(const cf_prp *prp, void *prpctx, 47 | const uint8_t *plain, size_t nplain, 48 | const uint8_t *header, size_t nheader, 49 | const uint8_t *nonce, size_t nnonce, 50 | uint8_t *cipher, /* the same size as nplain */ 51 | uint8_t *tag, size_t ntag) 52 | { 53 | uint8_t NN[CF_MAXBLOCK], 54 | HH[CF_MAXBLOCK], 55 | CC[CF_MAXBLOCK]; 56 | 57 | cf_cmac_stream cmac; 58 | cf_cmac_stream_init(&cmac, prp, prpctx); 59 | 60 | /* NN = OMAC_K^0(N) */ 61 | cmac_compute_n(&cmac, 0, nonce, nnonce, NN); 62 | 63 | /* HH = OMAC_K^1(H) */ 64 | cmac_compute_n(&cmac, 1, header, nheader, HH); 65 | 66 | /* C = CTR_K^NN(M) */ 67 | cf_ctr ctr; 68 | cf_ctr_init(&ctr, prp, prpctx, NN); 69 | cf_ctr_cipher(&ctr, plain, cipher, nplain); 70 | 71 | /* CC = OMAC_K^2(C) */ 72 | cmac_compute_n(&cmac, 2, cipher, nplain, CC); 73 | 74 | /* Tag = NN ^ CC ^ HH 75 | * T = Tag [ first tau bits ] */ 76 | assert(ntag <= prp->blocksz); 77 | for (size_t i = 0; i < ntag; i++) 78 | tag[i] = NN[i] ^ CC[i] ^ HH[i]; 79 | } 80 | 81 | int cf_eax_decrypt(const cf_prp *prp, void *prpctx, 82 | const uint8_t *cipher, size_t ncipher, 83 | const uint8_t *header, size_t nheader, 84 | const uint8_t *nonce, size_t nnonce, 85 | const uint8_t *tag, size_t ntag, 86 | uint8_t *plain) /* the same size as ncipher */ 87 | { 88 | uint8_t NN[CF_MAXBLOCK], 89 | HH[CF_MAXBLOCK], 90 | CC[CF_MAXBLOCK]; 91 | 92 | cf_cmac_stream cmac; 93 | cf_cmac_stream_init(&cmac, prp, prpctx); 94 | 95 | /* NN = OMAC_K^0(N) */ 96 | cmac_compute_n(&cmac, 0, nonce, nnonce, NN); 97 | 98 | /* HH = OMAC_K^1(H) */ 99 | cmac_compute_n(&cmac, 1, header, nheader, HH); 100 | 101 | /* CC = OMAC_K^2(C) */ 102 | cmac_compute_n(&cmac, 2, cipher, ncipher, CC); 103 | 104 | uint8_t tt[CF_MAXBLOCK]; 105 | assert(ntag && ntag <= prp->blocksz); 106 | for (size_t i = 0; i < ntag; i++) 107 | tt[i] = NN[i] ^ CC[i] ^ HH[i]; 108 | 109 | if (!mem_eq(tt, tag, ntag)) 110 | return 1; 111 | 112 | cf_ctr ctr; 113 | cf_ctr_init(&ctr, prp, prpctx, NN); 114 | cf_ctr_cipher(&ctr, cipher, plain, ncipher); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /src/arm/semihost.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "semihost.h" 7 | 8 | #define OP_WRITE0 0x04 9 | #define OP_EXIT 0x18 10 | #define OP_EXIT_ARG_FAILURE 0x0 11 | #define OP_EXIT_ARG_SUCCESS 0x20026 12 | 13 | extern uint32_t semihost(uint32_t, volatile void *); 14 | 15 | __attribute__((noreturn)) 16 | void quit_success(void) 17 | { 18 | semihost(OP_EXIT, (void *) OP_EXIT_ARG_SUCCESS); 19 | while (1) 20 | ; 21 | } 22 | 23 | __attribute__((noreturn)) 24 | void quit_failure(void) 25 | { 26 | semihost(OP_EXIT, (void *) OP_EXIT_ARG_FAILURE); 27 | while (1) 28 | ; 29 | } 30 | 31 | void emit(const char *buf) 32 | { 33 | semihost(OP_WRITE0, (volatile void *) buf); 34 | } 35 | 36 | static void emit_extent(const char *start, const char *end) 37 | { 38 | char buf[32+1]; 39 | size_t bufmax = sizeof(buf) - 1; 40 | buf[32] = 0; 41 | 42 | size_t bytes = end - start + 1; 43 | 44 | while (bytes >= bufmax) 45 | { 46 | memcpy(buf, start, bufmax); 47 | emit(buf); 48 | bytes -= bufmax; 49 | start += bufmax; 50 | } 51 | 52 | if (bytes == 0) 53 | return; 54 | 55 | memcpy(buf, start, bytes); 56 | buf[bytes] = 0; 57 | emit(buf); 58 | } 59 | 60 | void emitf(const char *fmt, ...) 61 | { 62 | const char *start = fmt, *end = fmt; 63 | 64 | va_list args; 65 | va_start(args, fmt); 66 | 67 | while (*fmt) 68 | { 69 | switch (*fmt) 70 | { 71 | case '%': 72 | emit_extent(start, end); 73 | 74 | switch (fmt[1]) 75 | { 76 | case '%': 77 | emit("%"); 78 | break; 79 | 80 | case 'u': 81 | emit_uint32(va_arg(args, uint32_t)); 82 | break; 83 | 84 | case 's': 85 | emit(va_arg(args, const char *)); 86 | break; 87 | } 88 | start = end = fmt + 2; 89 | break; 90 | 91 | default: 92 | end = fmt; 93 | break; 94 | } 95 | 96 | fmt++; 97 | } 98 | 99 | va_end(args); 100 | emit_extent(start, end); 101 | } 102 | 103 | static const char *hex_chars = "0123456789abcdef"; 104 | 105 | void emit_hex(const void *ptr, size_t len) 106 | { 107 | const uint8_t *bb = ptr; 108 | char byte[3]; 109 | 110 | byte[2] = 0; 111 | 112 | for (size_t i = 0; i < len; i++) 113 | { 114 | byte[0] = hex_chars[(bb[i] >> 4) & 0xf]; 115 | byte[1] = hex_chars[bb[i] & 0xf]; 116 | emit(byte); 117 | } 118 | } 119 | 120 | void emit_uint32(uint32_t x) 121 | { 122 | char buf[sizeof "0x11223344"]; 123 | buf[0] = '0'; 124 | buf[1] = 'x'; 125 | buf[2] = hex_chars[(x >> 28) & 0xf]; 126 | buf[3] = hex_chars[(x >> 24) & 0xf]; 127 | buf[4] = hex_chars[(x >> 20) & 0xf]; 128 | buf[5] = hex_chars[(x >> 16) & 0xf]; 129 | buf[6] = hex_chars[(x >> 12) & 0xf]; 130 | buf[7] = hex_chars[(x >> 8) & 0xf]; 131 | buf[8] = hex_chars[(x >> 4) & 0xf]; 132 | buf[9] = hex_chars[x & 0xf]; 133 | buf[10] = 0; 134 | 135 | emit(buf); 136 | } 137 | 138 | typedef struct 139 | { 140 | volatile uint32_t ctrl; 141 | volatile uint32_t reload; 142 | volatile uint32_t current; 143 | } systick; 144 | 145 | #define SysTick ((systick *)0xe000e010) 146 | 147 | #define STCTRL_SYSCLOCK 0x04 148 | #define STCTRL_TICKINT 0x02 149 | #define STCTRL_ENABLE 0x01 150 | 151 | #define STCTRL_MAX 0xffffff 152 | #define STCTRL_SHIFT 24 153 | 154 | extern uint32_t get_ticks(void); 155 | extern void reset_ticks(void); 156 | 157 | uint32_t reset_cycles(void) 158 | { 159 | SysTick->reload = STCTRL_MAX; 160 | SysTick->ctrl = STCTRL_SYSCLOCK | STCTRL_TICKINT | STCTRL_ENABLE; 161 | SysTick->current = 0; 162 | reset_ticks(); 163 | return get_ticks(); 164 | } 165 | 166 | uint32_t get_cycles(void) 167 | { 168 | return (get_ticks() << STCTRL_SHIFT) + (STCTRL_MAX - SysTick->current); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /src/arm/unacl/cortex_m0_reduce25519.s: -------------------------------------------------------------------------------- 1 | // Implementation of a partial reduction modulo 2^255 - 38. 2 | // 3 | // B. Haase, Endress + Hauser Conducta GmbH & Ko. KG 4 | // public domain. 5 | // 6 | // gnu assembler format. 7 | // 8 | // Generated and tested with C++ functions in the test subdirectory and on the target. 9 | // 10 | 11 | .cpu cortex-m0 12 | .fpu softvfp 13 | .eabi_attribute 20, 1 14 | .eabi_attribute 21, 1 15 | .eabi_attribute 23, 3 16 | .eabi_attribute 24, 1 17 | .eabi_attribute 25, 1 18 | .eabi_attribute 26, 1 19 | .eabi_attribute 30, 2 20 | .eabi_attribute 34, 0 21 | .eabi_attribute 18, 4 22 | .code 16 23 | 24 | .file "cortex_m0_reduce25519.s" 25 | 26 | .text 27 | .align 2 28 | 29 | .global fe25519_reduceTo256Bits_asm 30 | .code 16 31 | .thumb_func 32 | .type fe25519_reduceTo256Bits_asm, %function 33 | 34 | fe25519_reduceTo256Bits_asm: 35 | push {r4,r5,r6,r7,r14} 36 | ldr r2,[r1,#60] 37 | lsr r3,r2,#16 38 | uxth r2,r2 39 | mov r7,#38 40 | mul r2,r7 41 | mul r3,r7 42 | ldr r4,[r1,#28] 43 | lsr r5,r3,#16 44 | lsl r3,r3,#16 45 | mov r6,#0 46 | add r4,r2 47 | adc r5,r6 48 | add r4,r3 49 | adc r5,r6 50 | lsl r2,r4,#1 51 | lsr r2,r2,#1 52 | str r2,[r0,#28] 53 | lsr r4,r4,#31 54 | lsl r5,r5,#1 55 | orr r4,r5 56 | mov r2,#19 57 | mul r2,r4 58 | ldr r4,[r1,#0] 59 | add r2,r4 60 | mov r3,#0 61 | adc r3,r6 62 | ldr r4,[r1,#32] 63 | lsr r5,r4,#16 64 | uxth r4,r4 65 | mul r5,r7 66 | mul r4,r7 67 | add r2,r4 68 | adc r3,r6 69 | lsl r4,r5,#16 70 | lsr r5,r5,#16 71 | add r2,r4 72 | adc r3,r5 73 | str r2,[r0,#0] 74 | ldr r4,[r1,#4] 75 | add r3,r4 76 | mov r2,#0 77 | adc r2,r6 78 | ldr r4,[r1,#36] 79 | lsr r5,r4,#16 80 | uxth r4,r4 81 | mul r5,r7 82 | mul r4,r7 83 | add r3,r4 84 | adc r2,r6 85 | lsl r4,r5,#16 86 | lsr r5,r5,#16 87 | add r3,r4 88 | adc r2,r5 89 | str r3,[r0,#4] 90 | ldr r4,[r1,#8] 91 | add r2,r4 92 | mov r3,#0 93 | adc r3,r6 94 | ldr r4,[r1,#40] 95 | lsr r5,r4,#16 96 | uxth r4,r4 97 | mul r5,r7 98 | mul r4,r7 99 | add r2,r4 100 | adc r3,r6 101 | lsl r4,r5,#16 102 | lsr r5,r5,#16 103 | add r2,r4 104 | adc r3,r5 105 | str r2,[r0,#8] 106 | ldr r4,[r1,#12] 107 | add r3,r4 108 | mov r2,#0 109 | adc r2,r6 110 | ldr r4,[r1,#44] 111 | lsr r5,r4,#16 112 | uxth r4,r4 113 | mul r5,r7 114 | mul r4,r7 115 | add r3,r4 116 | adc r2,r6 117 | lsl r4,r5,#16 118 | lsr r5,r5,#16 119 | add r3,r4 120 | adc r2,r5 121 | str r3,[r0,#12] 122 | ldr r4,[r1,#16] 123 | add r2,r4 124 | mov r3,#0 125 | adc r3,r6 126 | ldr r4,[r1,#48] 127 | lsr r5,r4,#16 128 | uxth r4,r4 129 | mul r5,r7 130 | mul r4,r7 131 | add r2,r4 132 | adc r3,r6 133 | lsl r4,r5,#16 134 | lsr r5,r5,#16 135 | add r2,r4 136 | adc r3,r5 137 | str r2,[r0,#16] 138 | ldr r4,[r1,#20] 139 | add r3,r4 140 | mov r2,#0 141 | adc r2,r6 142 | ldr r4,[r1,#52] 143 | lsr r5,r4,#16 144 | uxth r4,r4 145 | mul r5,r7 146 | mul r4,r7 147 | add r3,r4 148 | adc r2,r6 149 | lsl r4,r5,#16 150 | lsr r5,r5,#16 151 | add r3,r4 152 | adc r2,r5 153 | str r3,[r0,#20] 154 | ldr r4,[r1,#24] 155 | add r2,r4 156 | mov r3,#0 157 | adc r3,r6 158 | ldr r4,[r1,#56] 159 | lsr r5,r4,#16 160 | uxth r4,r4 161 | mul r5,r7 162 | mul r4,r7 163 | add r2,r4 164 | adc r3,r6 165 | lsl r4,r5,#16 166 | lsr r5,r5,#16 167 | add r2,r4 168 | adc r3,r5 169 | str r2,[r0,#24] 170 | ldr r4,[r0,#28] 171 | add r4,r3 172 | str r4,[r0,#28] 173 | pop {r4,r5,r6,r7,r15} 174 | 175 | .size fe25519_reduceTo256Bits_asm, .-fe25519_reduceTo256Bits_asm 176 | 177 | -------------------------------------------------------------------------------- /src/testshake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2020 by Silex Insight. 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef TESTSHAKE_H 16 | #define TESTSHAKE_H 17 | 18 | #include 19 | 20 | static void vector_shake(const cf_cshake *hash, 21 | const void *vmsg, size_t nmsg, 22 | const char *expect, size_t nexpect) 23 | { 24 | uint8_t *digest; 25 | const uint8_t *msg = vmsg; 26 | size_t orig_nmsg = nmsg; 27 | cf_chash_ctx ctx; 28 | 29 | digest = malloc(nexpect); 30 | if (digest == NULL) { 31 | printf("Error malloc() \n"); 32 | return; 33 | } 34 | 35 | hash->init(&ctx); 36 | 37 | /* Input in carefully chosen chunk sizes to exercise blockwise code. */ 38 | if (nmsg) 39 | { 40 | hash->update(&ctx, msg, 1); 41 | nmsg--; 42 | msg++; 43 | } 44 | 45 | hash->update(&ctx, msg, nmsg); 46 | hash->digest(&ctx, digest, nexpect); 47 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 48 | 49 | /* Now try with other arrangements. */ 50 | msg = vmsg; 51 | nmsg = orig_nmsg; 52 | 53 | hash->init(&ctx); 54 | if (nmsg >= hash->blocksz) 55 | { 56 | hash->update(&ctx, msg, hash->blocksz - 1); 57 | nmsg -= hash->blocksz - 1; 58 | msg += hash->blocksz - 1; 59 | } 60 | 61 | hash->update(&ctx, msg, nmsg); 62 | hash->digest(&ctx, digest, nexpect); 63 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 64 | 65 | /* One more arrangement */ 66 | msg = vmsg; 67 | nmsg = orig_nmsg; 68 | 69 | hash->init(&ctx); 70 | if (nmsg >= hash->blocksz) 71 | { 72 | hash->update(&ctx, msg, hash->blocksz - 1); 73 | nmsg -= hash->blocksz - 1; 74 | msg += hash->blocksz - 1; 75 | 76 | hash->update(&ctx, msg, 1); 77 | nmsg--; 78 | msg++; 79 | } 80 | 81 | if (nmsg >= hash->blocksz) 82 | { 83 | hash->update(&ctx, msg, hash->blocksz); 84 | nmsg -= hash->blocksz; 85 | msg += hash->blocksz; 86 | } 87 | 88 | hash->update(&ctx, msg, nmsg); 89 | hash->digest(&ctx, digest, nexpect); 90 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 91 | free(digest); 92 | } 93 | 94 | typedef void (*final_fn)(void *ctx, uint8_t *out, size_t noutbytes); 95 | 96 | /* Check incremental interface works, and final function likewise. */ 97 | static void vector_shake_abc_final(const cf_cshake *hash, const void *vfinal_fn, 98 | const void *expect, size_t nexpect) 99 | { 100 | uint8_t *digest; 101 | final_fn final = vfinal_fn; 102 | cf_chash_ctx ctx; 103 | 104 | digest = malloc(nexpect); 105 | if (digest == NULL) { 106 | printf("Error malloc() \n"); 107 | return; 108 | } 109 | 110 | hash->init(&ctx); 111 | hash->update(&ctx, "a", 1); 112 | hash->digest(&ctx, digest, nexpect); 113 | hash->update(&ctx, "b", 1); 114 | hash->digest(&ctx, digest, nexpect); 115 | hash->update(&ctx, "c", 1); 116 | final(&ctx, digest, nexpect); 117 | 118 | TEST_CHECK(memcmp(expect, digest, nexpect) == 0); 119 | free(digest); 120 | } 121 | 122 | static void test_one_shot_shake(const cf_cshake *hash, const void *vmsg, 123 | size_t nmsg, const char *expect, size_t nexpect) 124 | { 125 | uint8_t *digest; 126 | 127 | digest = malloc(nexpect); 128 | if (digest == NULL) { 129 | printf("Error malloc() \n"); 130 | return; 131 | } 132 | 133 | cf_shake(hash, vmsg, nmsg, digest, nexpect); 134 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/sha3_shake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2020 by Silex Insight. 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef SHA3_SHAKE_H 16 | #define SHA3_SHAKE_H 17 | 18 | #include "chash.h" 19 | #include "sha3.h" 20 | 21 | /** 22 | * SHA3 SHAKE functions 23 | * =========== 24 | * The functions SHAKE-128 and SHAKE-256. from FIPS 202. 25 | * 26 | */ 27 | 28 | /* SHAKE hashing initialisation function type */ 29 | typedef void (*cf_cshake_init)(void *ctx); 30 | 31 | /* SHAKE hashing data processing function type */ 32 | typedef void (*cf_cshake_update)(void *ctx, const void *data, size_t nbytes); 33 | 34 | /* SHAKE hashing completion function type */ 35 | typedef void (*cf_cshake_digest)(const void *ctx, uint8_t *hash, size_t noutbytes); 36 | 37 | /* .. c:type:: cf_cshake 38 | * This type describes an incremental SHAKE function in an abstract way. 39 | * 40 | * .. c:member:: cf_cshake.blocksz 41 | * The SHAKE function's internal block size, in bytes. 42 | * 43 | * .. c:member:: cf_cshake.init 44 | * Context initialisation function. 45 | * 46 | * .. c:member:: cf_cshake:update 47 | * Data processing function. 48 | * 49 | * .. c:member:: cf_cshake:digest 50 | * Completion function. 51 | * 52 | */ 53 | typedef struct 54 | { 55 | size_t blocksz; 56 | cf_cshake_init init; 57 | cf_cshake_update update; 58 | cf_cshake_digest digest; 59 | } cf_cshake; 60 | 61 | /* .. c:function:: $DECL */ 62 | extern void cf_shake_128_init(cf_sha3_context *ctx); 63 | /* .. c:function:: $DECL 64 | * Sets up `ctx` ready to hash a new message. 65 | */ 66 | extern void cf_shake_256_init(cf_sha3_context *ctx); 67 | 68 | /* -- update functions -- */ 69 | 70 | /* .. c:function:: $DECL */ 71 | extern void cf_shake_128_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 72 | /* .. c:function:: $DECL 73 | * Hashes `nbytes` at `data`. Copies the data for processing later if there 74 | * isn't enough to make a full block. 75 | */ 76 | extern void cf_shake_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 77 | 78 | /* -- _digest functions -- */ 79 | 80 | /* .. c:function:: $DECL */ 81 | extern void cf_shake_128_digest(const cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes); 82 | /* .. c:function:: $DECL 83 | * Finishes the hashing operation, writing result to `hash`. 84 | * 85 | * This leaves `ctx` unchanged. 86 | */ 87 | extern void cf_shake_256_digest(const cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes); 88 | 89 | /* -- _digest_final functions -- */ 90 | 91 | /* .. c:function:: $DECL */ 92 | extern void cf_shake_128_digest_final(cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes); 93 | 94 | /* .. c:function:: $DECL 95 | * Finishes the hashing operation, writing result to `hash`. 96 | * 97 | * This destroys the contents of `ctx`. 98 | */ 99 | extern void cf_shake_256_digest_final(cf_sha3_context *ctx, uint8_t *hash, size_t noutbytes); 100 | 101 | /* .. c:function:: $DECL 102 | * One-shot, general SHAKE computation. 103 | * 104 | * :param h: describe which SHAKE algorithm to use. 105 | * :param m: input message to be hashed. 106 | * :param nm: length of message. May be zero. 107 | * :param out: pointer to output buffer. 108 | * :param nout: size of output buffer. 109 | */ 110 | extern void cf_shake(const cf_cshake *h, const void *m, size_t nm, uint8_t *out, size_t nout); 111 | 112 | /* .. c:var:: cf_shake_128 113 | * .. c:var:: cf_shake_256 114 | * Abstract interface to SHAKE functions. See :c:type:`cf_cshake` for more information. 115 | */ 116 | extern const cf_cshake cf_shake_128; 117 | extern const cf_cshake cf_shake_256; 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /src/testpoly1305.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | 16 | #include "poly1305.h" 17 | 18 | #include "testutil.h" 19 | #include "handy.h" 20 | #include "cutest.h" 21 | 22 | static void check(const char *rstr, const char *sstr, 23 | const char *msgstr, const char *tagstr) 24 | { 25 | uint8_t r[16], s[16], tag[16]; 26 | uint8_t msg[132], out[16]; 27 | 28 | unhex(r, sizeof r, rstr); 29 | unhex(s, sizeof s, sstr); 30 | size_t nmsg = unhex(msg, sizeof msg, msgstr); 31 | unhex(tag, sizeof tag, tagstr); 32 | 33 | cf_poly1305 ctx; 34 | cf_poly1305_init(&ctx, r, s); 35 | cf_poly1305_update(&ctx, msg, nmsg); 36 | cf_poly1305_finish(&ctx, out); 37 | 38 | TEST_CHECK(memcmp(out, tag, 16) == 0); 39 | } 40 | 41 | static void test_poly1305(void) 42 | { 43 | check("eea6a7251c1e72916d11c2cb214d3c25", 44 | "2539121d8e234e652d651fa4c8cff880", 45 | "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5", 46 | "f3ffc7703f9400e52a7dfb4b3d3305d9"); 47 | 48 | check("851fc40c3467ac0be05cc20404f3f700", 49 | "580b3b0f9447bb1e69d095b5928b6dbc", 50 | "f3f6", 51 | "f4c633c3044fc145f84f335cb81953de"); 52 | 53 | check("a0f3080000f46400d0c7e9076c834403", 54 | "dd3fab2251f11ac759f0887129cc2ee7", 55 | "", 56 | "dd3fab2251f11ac759f0887129cc2ee7"); 57 | 58 | check("48443d0bb0d21109c89a100b5ce2c208", 59 | "83149c69b561dd88298a1798b10716ef", 60 | "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136", 61 | "0ee1c16bb73f0f4fd19881753c01cdbe"); 62 | 63 | check("12976a08c4426d0ce8a82407c4f48207", 64 | "80f8c20aa71202d1e29179cbcb555a57", 65 | "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9", 66 | "5154ad0d2cb26e01274fc51148491f1b"); 67 | 68 | /* extras from RFC7539 */ 69 | check("02000000000000000000000000000000", 70 | "00000000000000000000000000000000", 71 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 72 | "03000000000000000000000000000000"); 73 | check("02000000000000000000000000000000", 74 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 75 | "02000000000000000000000000000000", 76 | "03000000000000000000000000000000"); 77 | check("01000000000000000000000000000000", 78 | "00000000000000000000000000000000", 79 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000", 80 | "05000000000000000000000000000000"); 81 | check("01000000000000000000000000000000", 82 | "00000000000000000000000000000000", 83 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101", 84 | "00000000000000000000000000000000"); 85 | check("02000000000000000000000000000000", 86 | "00000000000000000000000000000000", 87 | "FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 88 | "FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); 89 | check("01000000000000000400000000000000", 90 | "00000000000000000000000000000000", 91 | "E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000", 92 | "14000000000000005500000000000000"); 93 | check("01000000000000000400000000000000", 94 | "00000000000000000000000000000000", 95 | "E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000", 96 | "13000000000000000000000000000000"); 97 | } 98 | 99 | TEST_LIST = { 100 | { "poly1305", test_poly1305 }, 101 | { 0 } 102 | }; 103 | -------------------------------------------------------------------------------- /src/arm/unacl/cortex_m0_mpy121666.s: -------------------------------------------------------------------------------- 1 | // Implementation of multiplication of an fe25519 bit value with the curve constant 121666. 2 | // 3 | // B. Haase, Endress + Hauser Conducta GmbH & Ko. KG 4 | // public domain. 5 | // 6 | // gnu assembler format. 7 | // 8 | // Generated and tested with C++ functions in the test subdirectory. 9 | // 10 | // ATTENTION: 11 | // Not yet tested on target hardware. 12 | 13 | 14 | .cpu cortex-m0 15 | .fpu softvfp 16 | .eabi_attribute 20, 1 17 | .eabi_attribute 21, 1 18 | .eabi_attribute 23, 3 19 | .eabi_attribute 24, 1 20 | .eabi_attribute 25, 1 21 | .eabi_attribute 26, 1 22 | .eabi_attribute 30, 2 23 | .eabi_attribute 34, 0 24 | .eabi_attribute 18, 4 25 | .code 16 26 | 27 | .file "cortex_m0_reduce25519.s" 28 | 29 | .text 30 | .align 2 31 | 32 | .global fe25519_mpyWith121666_asm 33 | .code 16 34 | .thumb_func 35 | .type fe25519_mpyWith121666_asm, %function 36 | 37 | fe25519_mpyWith121666_asm: 38 | push {r4,r5,r6,r7,r14} 39 | ldr r7,__label_for_immediate_56130 40 | ldr r2,[r1,#28] 41 | lsl r5,r2,#16 42 | lsr r6,r2,#16 43 | lsr r3,r2,#16 44 | uxth r2,r2 45 | mul r2,r7 46 | mul r3,r7 47 | add r5,r2 48 | mov r2,#0 49 | adc r6,r2 50 | lsl r2,r3,#16 51 | lsr r3,r3,#16 52 | add r5,r2 53 | adc r6,r3 54 | lsl r2,r5,#1 55 | lsr r2,r2,#1 56 | str r2,[r0,#28] 57 | lsr r5,r5,#31 58 | lsl r6,r6,#1 59 | orr r5,r6 60 | mov r6,#19 61 | mul r5,r6 62 | mov r6,#0 63 | ldr r2,[r1,#0] 64 | lsl r3,r2,#16 65 | lsr r4,r2,#16 66 | add r5,r3 67 | adc r6,r4 68 | lsr r3,r2,#16 69 | uxth r2,r2 70 | mul r2,r7 71 | mul r3,r7 72 | add r5,r2 73 | mov r2,#0 74 | adc r6,r2 75 | lsl r2,r3,#16 76 | lsr r3,r3,#16 77 | add r5,r2 78 | adc r6,r3 79 | str r5,[r0,#0] 80 | mov r5,#0 81 | ldr r2,[r1,#4] 82 | lsl r3,r2,#16 83 | lsr r4,r2,#16 84 | add r6,r3 85 | adc r5,r4 86 | lsr r3,r2,#16 87 | uxth r2,r2 88 | mul r2,r7 89 | mul r3,r7 90 | add r6,r2 91 | mov r2,#0 92 | adc r5,r2 93 | lsl r2,r3,#16 94 | lsr r3,r3,#16 95 | add r6,r2 96 | adc r5,r3 97 | str r6,[r0,#4] 98 | mov r6,#0 99 | ldr r2,[r1,#8] 100 | lsl r3,r2,#16 101 | lsr r4,r2,#16 102 | add r5,r3 103 | adc r6,r4 104 | lsr r3,r2,#16 105 | uxth r2,r2 106 | mul r2,r7 107 | mul r3,r7 108 | add r5,r2 109 | mov r2,#0 110 | adc r6,r2 111 | lsl r2,r3,#16 112 | lsr r3,r3,#16 113 | add r5,r2 114 | adc r6,r3 115 | str r5,[r0,#8] 116 | mov r5,#0 117 | ldr r2,[r1,#12] 118 | lsl r3,r2,#16 119 | lsr r4,r2,#16 120 | add r6,r3 121 | adc r5,r4 122 | lsr r3,r2,#16 123 | uxth r2,r2 124 | mul r2,r7 125 | mul r3,r7 126 | add r6,r2 127 | mov r2,#0 128 | adc r5,r2 129 | lsl r2,r3,#16 130 | lsr r3,r3,#16 131 | add r6,r2 132 | adc r5,r3 133 | str r6,[r0,#12] 134 | mov r6,#0 135 | ldr r2,[r1,#16] 136 | lsl r3,r2,#16 137 | lsr r4,r2,#16 138 | add r5,r3 139 | adc r6,r4 140 | lsr r3,r2,#16 141 | uxth r2,r2 142 | mul r2,r7 143 | mul r3,r7 144 | add r5,r2 145 | mov r2,#0 146 | adc r6,r2 147 | lsl r2,r3,#16 148 | lsr r3,r3,#16 149 | add r5,r2 150 | adc r6,r3 151 | str r5,[r0,#16] 152 | mov r5,#0 153 | ldr r2,[r1,#20] 154 | lsl r3,r2,#16 155 | lsr r4,r2,#16 156 | add r6,r3 157 | adc r5,r4 158 | lsr r3,r2,#16 159 | uxth r2,r2 160 | mul r2,r7 161 | mul r3,r7 162 | add r6,r2 163 | mov r2,#0 164 | adc r5,r2 165 | lsl r2,r3,#16 166 | lsr r3,r3,#16 167 | add r6,r2 168 | adc r5,r3 169 | str r6,[r0,#20] 170 | mov r6,#0 171 | ldr r2,[r1,#24] 172 | lsl r3,r2,#16 173 | lsr r4,r2,#16 174 | add r5,r3 175 | adc r6,r4 176 | lsr r3,r2,#16 177 | uxth r2,r2 178 | mul r2,r7 179 | mul r3,r7 180 | add r5,r2 181 | mov r2,#0 182 | adc r6,r2 183 | lsl r2,r3,#16 184 | lsr r3,r3,#16 185 | add r5,r2 186 | adc r6,r3 187 | str r5,[r0,#24] 188 | mov r5,#0 189 | ldr r2,[r0,#28] 190 | add r6,r2 191 | str r6,[r0,#28] 192 | pop {r4,r5,r6,r7,r15} 193 | 194 | .align 2 195 | __label_for_immediate_56130: 196 | .word 56130 197 | 198 | .size fe25519_mpyWith121666_asm, .-fe25519_mpyWith121666_asm 199 | 200 | -------------------------------------------------------------------------------- /src/sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include 16 | 17 | #include "sha1.h" 18 | #include "blockwise.h" 19 | #include "bitops.h" 20 | #include "handy.h" 21 | #include "tassert.h" 22 | 23 | void cf_sha1_init(cf_sha1_context *ctx) 24 | { 25 | memset(ctx, 0, sizeof *ctx); 26 | ctx->H[0] = 0x67452301; 27 | ctx->H[1] = 0xefcdab89; 28 | ctx->H[2] = 0x98badcfe; 29 | ctx->H[3] = 0x10325476; 30 | ctx->H[4] = 0xc3d2e1f0; 31 | } 32 | 33 | static void sha1_update_block(void *vctx, const uint8_t *inp) 34 | { 35 | cf_sha1_context *ctx = vctx; 36 | 37 | /* This is a 16-word window into the whole W array. */ 38 | uint32_t W[16]; 39 | 40 | uint32_t a = ctx->H[0], 41 | b = ctx->H[1], 42 | c = ctx->H[2], 43 | d = ctx->H[3], 44 | e = ctx->H[4], 45 | Wt; 46 | 47 | for (size_t t = 0; t < 80; t++) 48 | { 49 | /* For W[0..16] we process the input into W. 50 | * For W[16..79] we compute the next W value: 51 | * 52 | * W[t] = (W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]) <<< 1 53 | * 54 | * But all W indices are reduced mod 16 into our window. 55 | */ 56 | if (t < 16) 57 | { 58 | W[t] = Wt = read32_be(inp); 59 | inp += 4; 60 | } else { 61 | Wt = W[(t - 3) % 16] ^ W[(t - 8) % 16] ^ W[(t - 14) % 16] ^ W[(t - 16) % 16]; 62 | Wt = rotl32(Wt, 1); 63 | W[t % 16] = Wt; 64 | } 65 | 66 | uint32_t f, k; 67 | 68 | if (t <= 19) 69 | { 70 | f = (b & c) | (~b & d); 71 | k = 0x5a827999; 72 | } else if (t <= 39) { 73 | f = b ^ c ^ d; 74 | k = 0x6ed9eba1; 75 | } else if (t <= 59) { 76 | f = (b & c) | (b & d) | (c & d); 77 | k = 0x8f1bbcdc; 78 | } else { 79 | f = b ^ c ^ d; 80 | k = 0xca62c1d6; 81 | } 82 | 83 | uint32_t temp = rotl32(a, 5) + f + e + k + Wt; 84 | e = d; 85 | d = c; 86 | c = rotl32(b, 30); 87 | b = a; 88 | a = temp; 89 | } 90 | 91 | ctx->H[0] += a; 92 | ctx->H[1] += b; 93 | ctx->H[2] += c; 94 | ctx->H[3] += d; 95 | ctx->H[4] += e; 96 | 97 | ctx->blocks++; 98 | } 99 | 100 | void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes) 101 | { 102 | cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial, 103 | data, nbytes, 104 | sha1_update_block, ctx); 105 | } 106 | 107 | void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]) 108 | { 109 | cf_sha1_context ours = *ctx; 110 | cf_sha1_digest_final(&ours, hash); 111 | } 112 | 113 | void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]) 114 | { 115 | uint64_t digested_bytes = ctx->blocks; 116 | digested_bytes = digested_bytes * CF_SHA1_BLOCKSZ + ctx->npartial; 117 | uint64_t digested_bits = digested_bytes * 8; 118 | 119 | size_t padbytes = CF_SHA1_BLOCKSZ - ((digested_bytes + 8) % CF_SHA1_BLOCKSZ); 120 | 121 | /* Hash 0x80 00 ... block first. */ 122 | cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial, 123 | 0x80, 0x00, 0x00, padbytes, 124 | sha1_update_block, ctx); 125 | 126 | /* Now hash length. */ 127 | uint8_t buf[8]; 128 | write64_be(digested_bits, buf); 129 | cf_sha1_update(ctx, buf, 8); 130 | 131 | /* We ought to have got our padding calculation right! */ 132 | assert(ctx->npartial == 0); 133 | 134 | write32_be(ctx->H[0], hash + 0); 135 | write32_be(ctx->H[1], hash + 4); 136 | write32_be(ctx->H[2], hash + 8); 137 | write32_be(ctx->H[3], hash + 12); 138 | write32_be(ctx->H[4], hash + 16); 139 | 140 | memset(ctx, 0, sizeof *ctx); 141 | } 142 | 143 | const cf_chash cf_sha1 = { 144 | .hashsz = CF_SHA1_HASHSZ, 145 | .blocksz = CF_SHA1_BLOCKSZ, 146 | .init = (cf_chash_init) cf_sha1_init, 147 | .update = (cf_chash_update) cf_sha1_update, 148 | .digest = (cf_chash_digest) cf_sha1_digest 149 | }; 150 | 151 | -------------------------------------------------------------------------------- /src/chash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef CHASH_H 16 | #define CHASH_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * General hash function description 23 | * ================================= 24 | * This allows us to make use of hash functions without depending 25 | * on a specific one. This is useful in implementing, for example, 26 | * :doc:`HMAC `. 27 | */ 28 | 29 | /* .. c:type:: cf_chash_init 30 | * Hashing initialisation function type. 31 | * 32 | * Functions of this type should initialise the context in preparation 33 | * for hashing a message with `cf_chash_update` functions. 34 | * 35 | * :rtype: void 36 | * :param ctx: hash function-specific context structure. 37 | */ 38 | typedef void (*cf_chash_init)(void *ctx); 39 | 40 | /* .. c:type:: cf_chash_update 41 | * Hashing data processing function type. 42 | * 43 | * Functions of this type hash `count` bytes of data at `data`, 44 | * updating the contents of `ctx`. 45 | * 46 | * :rtype: void 47 | * :param ctx: hash function-specific context structure. 48 | * :param data: input data to hash. 49 | * :param count: number of bytes to hash. 50 | */ 51 | typedef void (*cf_chash_update)(void *ctx, const void *data, size_t count); 52 | 53 | /* .. c:type:: cf_chash_digest 54 | * Hashing completion function type. 55 | * 56 | * Functions of this type complete a hashing operation, 57 | * writing :c:member:`cf_chash.hashsz` bytes to `hash`. 58 | * 59 | * This function does not change `ctx` -- any padding which needs doing 60 | * must be done seperately (in a copy of `ctx`, say). 61 | * 62 | * This means you can interlave `_update` and `_digest` calls to 63 | * learn `H(A)` and `H(A || B)` without hashing `A` twice. 64 | * 65 | * :rtype: void 66 | * :param ctx: hash function-specific context structure. 67 | * :param hash: location to write hash result. 68 | */ 69 | typedef void (*cf_chash_digest)(const void *ctx, uint8_t *hash); 70 | 71 | /* .. c:type:: cf_chash 72 | * This type describes an incremental hash function in an abstract way. 73 | * 74 | * .. c:member:: cf_chash.hashsz 75 | * The hash function's output, in bytes. 76 | * 77 | * .. c:member:: cf_chash.blocksz 78 | * The hash function's internal block size, in bytes. 79 | * 80 | * .. c:member:: cf_chash.init 81 | * Context initialisation function. 82 | * 83 | * .. c:member:: cf_chash:update 84 | * Data processing function. 85 | * 86 | * .. c:member:: cf_chash:digest 87 | * Completion function. 88 | * 89 | */ 90 | typedef struct 91 | { 92 | size_t hashsz; 93 | size_t blocksz; 94 | 95 | cf_chash_init init; 96 | cf_chash_update update; 97 | cf_chash_digest digest; 98 | } cf_chash; 99 | 100 | /* .. c:macro:: CF_CHASH_MAXCTX 101 | * The maximum size of a :c:type:`cf_chash_ctx`. This allows 102 | * use to put a structure in automatic storage that can 103 | * store working data for any supported hash function. */ 104 | #define CF_CHASH_MAXCTX 390 105 | 106 | /* .. c:macro:: CF_CHASH_MAXBLK 107 | * Maximum hash function block size (in bytes). */ 108 | #define CF_CHASH_MAXBLK 128 109 | 110 | /* .. c:macro:: CF_MAXHASH 111 | * Maximum hash function output (in bytes). */ 112 | #define CF_MAXHASH 64 113 | 114 | /* .. c:type:: cf_chash_ctx 115 | * A type usable with any `cf_chash` as a context. */ 116 | typedef union 117 | { 118 | uint8_t ctx[CF_CHASH_MAXCTX]; 119 | uint16_t u16; 120 | uint32_t u32; 121 | uint64_t u64; 122 | } cf_chash_ctx; 123 | 124 | /* .. c:function:: $DECL 125 | * One shot hashing: `out = h(m)`. 126 | * 127 | * Using the hash function `h`, `nm` bytes at `m` are hashed and `h->hashsz` bytes 128 | * of result is written to the buffer `out`. 129 | * 130 | * :param h: hash function description. 131 | * :param m: message buffer. 132 | * :param nm: message length. 133 | * :param out: hash result buffer (written). 134 | */ 135 | void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out); 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/cmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "handy.h" 16 | #include "prp.h" 17 | #include "modes.h" 18 | #include "bitops.h" 19 | #include "blockwise.h" 20 | #include "gf128.h" 21 | #include "tassert.h" 22 | 23 | #include 24 | 25 | void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx) 26 | { 27 | uint8_t L[CF_MAXBLOCK]; 28 | assert(prp->blocksz == 16); 29 | 30 | mem_clean(ctx, sizeof *ctx); 31 | 32 | /* L = E_K(0^n) */ 33 | mem_clean(L, prp->blocksz); 34 | prp->encrypt(prpctx, L, L); 35 | 36 | /* B = 2L */ 37 | cf_gf128 gf; 38 | cf_gf128_frombytes_be(L, gf); 39 | cf_gf128_double(gf, gf); 40 | cf_gf128_tobytes_be(gf, ctx->B); 41 | 42 | /* P = 4L */ 43 | cf_gf128_double(gf, gf); 44 | cf_gf128_tobytes_be(gf, ctx->P); 45 | 46 | ctx->prp = prp; 47 | ctx->prpctx = prpctx; 48 | } 49 | 50 | void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK]) 51 | { 52 | cf_cmac_stream stream; 53 | stream.cmac = *ctx; 54 | cf_cmac_stream_reset(&stream); 55 | cf_cmac_stream_update(&stream, data, len, 1); 56 | cf_cmac_stream_final(&stream, out); 57 | } 58 | 59 | void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx) 60 | { 61 | cf_cmac_init(&ctx->cmac, prp, prpctx); 62 | cf_cmac_stream_reset(ctx); 63 | } 64 | 65 | void cf_cmac_stream_reset(cf_cmac_stream *ctx) 66 | { 67 | uint8_t iv_zero[CF_MAXBLOCK] = { 0 }; 68 | cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero); 69 | mem_clean(ctx->buffer, sizeof ctx->buffer); 70 | ctx->used = 0; 71 | ctx->processed = 0; 72 | ctx->finalised = 0; 73 | } 74 | 75 | static void cmac_process(void *vctx, const uint8_t *block) 76 | { 77 | cf_cmac_stream *ctx = vctx; 78 | uint8_t output[CF_MAXBLOCK]; 79 | cf_cbc_encrypt(&ctx->cbc, block, output, 1); 80 | ctx->processed += ctx->cmac.prp->blocksz; 81 | } 82 | 83 | static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block, 84 | const uint8_t *xor) 85 | { 86 | uint8_t input[CF_MAXBLOCK]; 87 | uint8_t output[CF_MAXBLOCK]; 88 | xor_bb(input, block, xor, ctx->cmac.prp->blocksz); 89 | cf_cbc_encrypt(&ctx->cbc, input, output, 1); 90 | ctx->processed += ctx->cmac.prp->blocksz; 91 | /* signature is in ctx->cbc.block. */ 92 | } 93 | 94 | static void cmac_process_final_nopad(void *vctx, const uint8_t *block) 95 | { 96 | cf_cmac_stream *ctx = vctx; 97 | cmac_process_final(ctx, block, ctx->cmac.B); 98 | ctx->finalised = 1; 99 | } 100 | 101 | static void cmac_process_final_pad(void *vctx, const uint8_t *block) 102 | { 103 | cf_cmac_stream *ctx = vctx; 104 | cmac_process_final(ctx, block, ctx->cmac.P); 105 | ctx->finalised = 1; 106 | } 107 | 108 | void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal) 109 | { 110 | size_t blocksz = ctx->cmac.prp->blocksz; 111 | cf_blockwise_in_fn final_fn = cmac_process; 112 | int needpad = 0; 113 | 114 | if (isfinal) 115 | { 116 | int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0; 117 | int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0; 118 | 119 | assert(!ctx->finalised); /* finalised before? */ 120 | assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */ 121 | 122 | /* If we have a whole number of blocks, and at least 1 block, we XOR in B. 123 | * Otherwise, we need to pad and XOR in P. */ 124 | if (whole_number_of_blocks && !empty_message) 125 | final_fn = cmac_process_final_nopad; 126 | else 127 | needpad = 1; 128 | } 129 | 130 | /* Input data */ 131 | cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz, 132 | data, len, 133 | cmac_process, 134 | final_fn, ctx); 135 | 136 | /* Input padding */ 137 | if (needpad) 138 | { 139 | cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz, 140 | 0x80, 0x00, 0x00, blocksz - ctx->used, 141 | cmac_process_final_pad, ctx); 142 | } 143 | } 144 | 145 | void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) 146 | { 147 | assert(ctx->finalised); 148 | memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz); 149 | } 150 | 151 | -------------------------------------------------------------------------------- /src/arm/linkscript.std.ld: -------------------------------------------------------------------------------- 1 | 2 | /* Linker script to place sections and symbol values. Should be used together 3 | * with other linker script that defines memory regions FLASH and RAM. 4 | * It references following symbols, which must be defined in code: 5 | * Reset_Handler : Entry of reset handler 6 | * 7 | * It defines following symbols, which code can use without definition: 8 | * __exidx_start 9 | * __exidx_end 10 | * __copy_table_start__ 11 | * __copy_table_end__ 12 | * __zero_table_start__ 13 | * __zero_table_end__ 14 | * __etext 15 | * __data_start__ 16 | * __preinit_array_start 17 | * __preinit_array_end 18 | * __init_array_start 19 | * __init_array_end 20 | * __fini_array_start 21 | * __fini_array_end 22 | * __data_end__ 23 | * __bss_start__ 24 | * __bss_end__ 25 | * __end__ 26 | * end 27 | * __HeapLimit 28 | * __StackLimit 29 | * __StackTop 30 | * __stack 31 | */ 32 | ENTRY(Reset_Handler) 33 | 34 | SECTIONS 35 | { 36 | .text : 37 | { 38 | KEEP(*(.isr_vector)) 39 | *(.text*) 40 | 41 | KEEP(*(.init)) 42 | KEEP(*(.fini)) 43 | 44 | /* .ctors */ 45 | *crtbegin.o(.ctors) 46 | *crtbegin?.o(.ctors) 47 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 48 | *(SORT(.ctors.*)) 49 | *(.ctors) 50 | 51 | /* .dtors */ 52 | *crtbegin.o(.dtors) 53 | *crtbegin?.o(.dtors) 54 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 55 | *(SORT(.dtors.*)) 56 | *(.dtors) 57 | 58 | *(.rodata*) 59 | 60 | KEEP(*(.eh_frame*)) 61 | } > FLASH 62 | 63 | .ARM.extab : 64 | { 65 | *(.ARM.extab* .gnu.linkonce.armextab.*) 66 | } > FLASH 67 | 68 | __exidx_start = .; 69 | .ARM.exidx : 70 | { 71 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 72 | } > FLASH 73 | __exidx_end = .; 74 | 75 | /* To copy multiple ROM to RAM sections, 76 | * uncomment .copy.table section and, 77 | * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ 78 | 79 | .copy.table : 80 | { 81 | . = ALIGN(4); 82 | __copy_table_start__ = .; 83 | LONG (__etext) 84 | LONG (__data_start__) 85 | LONG (__data_end__ - __data_start__) 86 | __copy_table_end__ = .; 87 | } > FLASH 88 | 89 | 90 | /* To clear multiple BSS sections, 91 | * uncomment .zero.table section and, 92 | * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ 93 | .zero.table : 94 | { 95 | . = ALIGN(4); 96 | __zero_table_start__ = .; 97 | LONG (__bss_start__) 98 | LONG (__bss_end__ - __bss_start__) 99 | __zero_table_end__ = .; 100 | } > FLASH 101 | 102 | __etext = .; 103 | 104 | .data : AT (__etext) 105 | { 106 | __data_start__ = .; 107 | *(vtable) 108 | *(.data*) 109 | 110 | . = ALIGN(4); 111 | /* preinit data */ 112 | PROVIDE_HIDDEN (__preinit_array_start = .); 113 | KEEP(*(.preinit_array)) 114 | PROVIDE_HIDDEN (__preinit_array_end = .); 115 | 116 | . = ALIGN(4); 117 | /* init data */ 118 | PROVIDE_HIDDEN (__init_array_start = .); 119 | KEEP(*(SORT(.init_array.*))) 120 | KEEP(*(.init_array)) 121 | PROVIDE_HIDDEN (__init_array_end = .); 122 | 123 | 124 | . = ALIGN(4); 125 | /* finit data */ 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP(*(SORT(.fini_array.*))) 128 | KEEP(*(.fini_array)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | 131 | KEEP(*(.jcr*)) 132 | . = ALIGN(4); 133 | /* All data end */ 134 | __data_end__ = .; 135 | 136 | } > RAM 137 | 138 | .bss : 139 | { 140 | . = ALIGN(4); 141 | __bss_start__ = .; 142 | *(.bss*) 143 | *(COMMON) 144 | . = ALIGN(4); 145 | __bss_end__ = .; 146 | } > RAM 147 | 148 | .heap (COPY): 149 | { 150 | __end__ = .; 151 | PROVIDE(end = .); 152 | *(.heap*) 153 | __HeapLimit = .; 154 | } > RAM 155 | 156 | /* .stack_dummy section doesn't contains any symbols. It is only 157 | * used for linker to calculate size of stack sections, and assign 158 | * values to stack symbols later */ 159 | .stack_dummy (COPY): 160 | { 161 | *(.stack*) 162 | } > RAM 163 | 164 | /* Set stack top to end of RAM, and stack limit move down by 165 | * size of stack_dummy section */ 166 | __StackTop = ORIGIN(RAM) + LENGTH(RAM); 167 | __StackLimit = __StackTop - SIZEOF(.stack_dummy); 168 | PROVIDE(__stack = __StackTop); 169 | 170 | /* Check if data + heap + stack exceeds RAM limit */ 171 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") 172 | } 173 | -------------------------------------------------------------------------------- /src/salsa20.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "salsa20.h" 16 | #include "bitops.h" 17 | #include "blockwise.h" 18 | 19 | #include 20 | #include 21 | 22 | void cf_salsa20_core(const uint8_t key0[16], 23 | const uint8_t key1[16], 24 | const uint8_t nonce[16], 25 | const uint8_t constant[16], 26 | uint8_t out[64]) 27 | { 28 | /* unpack sequence is: 29 | * 30 | * c0 31 | * key0 32 | * c1 33 | * nonce 34 | * c2 35 | * key1 36 | * c3 37 | * 38 | * where c0, c1, c2, c3 = constant 39 | */ 40 | 41 | uint32_t z0, z1, z2, z3, z4, z5, z6, z7, 42 | z8, z9, za, zb, zc, zd, ze, zf; 43 | 44 | uint32_t x0 = z0 = read32_le(constant + 0), 45 | x1 = z1 = read32_le(key0 + 0), 46 | x2 = z2 = read32_le(key0 + 4), 47 | x3 = z3 = read32_le(key0 + 8), 48 | x4 = z4 = read32_le(key0 + 12), 49 | x5 = z5 = read32_le(constant + 4), 50 | x6 = z6 = read32_le(nonce + 0), 51 | x7 = z7 = read32_le(nonce + 4), 52 | x8 = z8 = read32_le(nonce + 8), 53 | x9 = z9 = read32_le(nonce + 12), 54 | xa = za = read32_le(constant + 8), 55 | xb = zb = read32_le(key1 + 0), 56 | xc = zc = read32_le(key1 + 4), 57 | xd = zd = read32_le(key1 + 8), 58 | xe = ze = read32_le(key1 + 12), 59 | xf = zf = read32_le(constant + 12); 60 | 61 | #define QUARTER(v0, v1, v2, v3) \ 62 | v1 ^= rotl32(v0 + v3, 7); \ 63 | v2 ^= rotl32(v1 + v0, 9); \ 64 | v3 ^= rotl32(v2 + v1, 13);\ 65 | v0 ^= rotl32(v3 + v2, 18) 66 | 67 | #define ROW \ 68 | QUARTER(z0, z1, z2, z3); \ 69 | QUARTER(z5, z6, z7, z4); \ 70 | QUARTER(za, zb, z8, z9); \ 71 | QUARTER(zf, zc, zd, ze) 72 | 73 | #define COLUMN\ 74 | QUARTER(z0, z4, z8, zc); \ 75 | QUARTER(z5, z9, zd, z1); \ 76 | QUARTER(za, ze, z2, z6); \ 77 | QUARTER(zf, z3, z7, zb) 78 | 79 | for (int i = 0; i < 10; i++) 80 | { 81 | COLUMN; 82 | ROW; 83 | } 84 | 85 | x0 += z0; 86 | x1 += z1; 87 | x2 += z2; 88 | x3 += z3; 89 | x4 += z4; 90 | x5 += z5; 91 | x6 += z6; 92 | x7 += z7; 93 | x8 += z8; 94 | x9 += z9; 95 | xa += za; 96 | xb += zb; 97 | xc += zc; 98 | xd += zd; 99 | xe += ze; 100 | xf += zf; 101 | 102 | write32_le(x0, out + 0); 103 | write32_le(x1, out + 4); 104 | write32_le(x2, out + 8); 105 | write32_le(x3, out + 12); 106 | write32_le(x4, out + 16); 107 | write32_le(x5, out + 20); 108 | write32_le(x6, out + 24); 109 | write32_le(x7, out + 28); 110 | write32_le(x8, out + 32); 111 | write32_le(x9, out + 36); 112 | write32_le(xa, out + 40); 113 | write32_le(xb, out + 44); 114 | write32_le(xc, out + 48); 115 | write32_le(xd, out + 52); 116 | write32_le(xe, out + 56); 117 | write32_le(xf, out + 60); 118 | } 119 | 120 | static const uint8_t *salsa20_tau = (const uint8_t *) "expand 16-byte k"; 121 | static const uint8_t *salsa20_sigma = (const uint8_t *) "expand 32-byte k"; 122 | 123 | void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]) 124 | { 125 | switch (nkey) 126 | { 127 | case 16: 128 | memcpy(ctx->key0, key, 16); 129 | memcpy(ctx->key1, key, 16); 130 | ctx->constant = salsa20_tau; 131 | break; 132 | case 32: 133 | memcpy(ctx->key0, key, 16); 134 | memcpy(ctx->key1, key + 16, 16); 135 | ctx->constant = salsa20_sigma; 136 | break; 137 | default: 138 | abort(); 139 | } 140 | 141 | memset(ctx->nonce, 0, sizeof ctx->nonce); 142 | memcpy(ctx->nonce, nonce, 8); 143 | ctx->nblock = 0; 144 | ctx->ncounter = 8; 145 | } 146 | 147 | static void cf_salsa20_next_block(void *vctx, uint8_t *out) 148 | { 149 | cf_salsa20_ctx *ctx = vctx; 150 | cf_salsa20_core(ctx->key0, 151 | ctx->key1, 152 | ctx->nonce, 153 | ctx->constant, 154 | out); 155 | incr_le(ctx->nonce + 8, ctx->ncounter); 156 | } 157 | 158 | void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes) 159 | { 160 | cf_blockwise_xor(ctx->block, &ctx->nblock, 64, 161 | input, output, bytes, 162 | cf_salsa20_next_block, 163 | ctx); 164 | } 165 | -------------------------------------------------------------------------------- /src/salsa20.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef SALSA20_H 16 | #define SALSA20_H 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * The Salsa20/Chacha20 stream ciphers 23 | * =================================== 24 | * 25 | * These are similar stream ciphers by djb. 26 | * 27 | * A reduced round variant of Salsa20 (Salsa20/12) 28 | * was selected as a finalist of the eSTREAM stream 29 | * cipher competition. This implementation does 30 | * the full 20 rounds. 31 | * 32 | * ChaCha20 is fundamentally like Salsa20, but 33 | * has a tweaked round function to improve security 34 | * margin without damaging performance. 35 | */ 36 | 37 | /* Salsa20 core transform. */ 38 | void cf_salsa20_core(const uint8_t key0[16], 39 | const uint8_t key1[16], 40 | const uint8_t nonce[16], 41 | const uint8_t constant[16], 42 | uint8_t out[64]); 43 | 44 | /* Chacha20 core transform. */ 45 | void cf_chacha20_core(const uint8_t key0[16], 46 | const uint8_t key1[16], 47 | const uint8_t nonce[16], 48 | const uint8_t constant[16], 49 | uint8_t out[64]); 50 | 51 | /* .. c:type:: cf_salsa20_ctx 52 | * Incremental interface to Salsa20. 53 | * 54 | * .. c:member:: cf_salsa20_ctx.key0 55 | * Half of key material. 56 | * 57 | * .. c:member:: cf_salsa20_ctx.key1 58 | * Half of key material. 59 | * 60 | * .. c:member:: cf_salsa20_ctx.nonce 61 | * Nonce and counter block. 62 | * 63 | * .. c:member:: cf_salsa20_ctx.constant 64 | * Per-key-length constants. 65 | * 66 | * .. c:member:: cf_salsa20_ctx.block 67 | * Buffer for unused key stream material. 68 | * 69 | * .. c:member:: cf_salsa20_ctx.nblock 70 | * Number of bytes at end of `block` that can be used as key stream. 71 | * 72 | */ 73 | typedef struct 74 | { 75 | uint8_t key0[16], key1[16]; 76 | uint8_t nonce[16]; 77 | const uint8_t *constant; 78 | uint8_t block[64]; 79 | size_t nblock; 80 | size_t ncounter; 81 | } cf_salsa20_ctx, cf_chacha20_ctx; 82 | 83 | /* .. c:type:: cf_chacha20_ctx 84 | * Incremental interface to Chacha20. This structure 85 | * is identical to :c:type:`cf_salsa20_ctx`. 86 | */ 87 | 88 | /* .. c:function:: $DECL 89 | * Salsa20 initialisation function. 90 | * 91 | * :param ctx: salsa20 context. 92 | * :param key: key material. 93 | * :param nkey: length of key in bytes, either 16 or 32. 94 | * :param nonce: per-message nonce. 95 | */ 96 | void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]); 97 | 98 | /* .. c:function:: $DECL 99 | * Chacha20 initialisation function. 100 | * 101 | * :param ctx: chacha20 context (written). 102 | * :param key: key material. 103 | * :param nkey: length of key in bytes, either 16 or 32. 104 | * :param nonce: per-message nonce. 105 | */ 106 | void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]); 107 | 108 | /* .. c:function:: $DECL 109 | * Chacha20 initialisation function. This version gives full control over the whole 110 | * initial nonce value, and the size of the counter. The counter is always at the front 111 | * of the nonce. 112 | * 113 | * :param ctx: chacha20 context (written). 114 | * :param key: key material. 115 | * :param nkey: length of key in bytes, either 16 or 32. 116 | * :param nonce: per-message nonce. `ncounter` bytes at the start are the block counter. 117 | * :param ncounter: length, in bytes, of the counter portion of the nonce. 118 | */ 119 | void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, 120 | const uint8_t nonce[16], size_t ncounter); 121 | 122 | /* .. c:function:: $DECL 123 | * Salsa20 encryption/decryption function. 124 | * 125 | * :param ctx: salsa20 context. 126 | * :param input: input data buffer (read), `count` bytes long. 127 | * :param output: output data buffer (written), `count` bytes long. 128 | */ 129 | void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count); 130 | 131 | /* .. c:function:: $DECL 132 | * Chacha20 encryption/decryption function. 133 | * 134 | * :param ctx: chacha20 context. 135 | * :param input: input data buffer (read), `count` bytes long. 136 | * :param output: output data buffer (written), `count` bytes long. 137 | */ 138 | void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count); 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /src/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | /** 16 | * The AES block cipher 17 | * ==================== 18 | * 19 | * This is a small, simple implementation of AES. Key expansion is done 20 | * first, filling in a :c:type:`cf_aes_context`. Then encryption and 21 | * decryption can be performed as desired. 22 | * 23 | * Usually you don't want to use AES directly; you should use it via 24 | * a :doc:`block cipher mode `. 25 | */ 26 | 27 | #ifndef AES_H 28 | #define AES_H 29 | 30 | #include 31 | #include 32 | 33 | #include "prp.h" 34 | 35 | /* .. c:macro:: AES_BLOCKSZ 36 | * AES has a 128-bit block size. This quantity is in bytes. 37 | */ 38 | #define AES_BLOCKSZ 16 39 | 40 | /* --- Size configuration --- */ 41 | 42 | /* .. c:macro:: AES128_ROUNDS 43 | * .. c:macro:: AES192_ROUNDS 44 | * .. c:macro:: AES256_ROUNDS 45 | * 46 | * Round counts for different key sizes. 47 | */ 48 | #define AES128_ROUNDS 10 49 | #define AES192_ROUNDS 12 50 | #define AES256_ROUNDS 14 51 | 52 | /* .. c:macro:: CF_AES_MAXROUNDS 53 | * 54 | * You can reduce the maximum number of rounds this implementation 55 | * supports. This reduces the storage needed by :c:type:`cf_aes_context`. 56 | * 57 | * The default is :c:macro:`AES256_ROUNDS` and is good for all key 58 | * sizes. 59 | */ 60 | #ifndef CF_AES_MAXROUNDS 61 | # define CF_AES_MAXROUNDS AES256_ROUNDS 62 | #endif 63 | 64 | /* .. c:macro:: CF_AES_ENCRYPT_ONLY 65 | * 66 | * Define this to 1 if you don't need to decrypt anything. 67 | * This saves space. :c:func:`cf_aes_decrypt` calls `abort(3)`. 68 | */ 69 | #ifndef CF_AES_ENCRYPT_ONLY 70 | # define CF_AES_ENCRYPT_ONLY 0 71 | #endif 72 | 73 | /* .. c:type:: cf_aes_context 74 | * This type represents an expanded AES key. Create one 75 | * using :c:func:`cf_aes_init`, make use of one using 76 | * :c:func:`cf_aes_encrypt` or :c:func:`cf_aes_decrypt`. 77 | * 78 | * The contents of this structure are equivalent to the 79 | * original key material. You should clean the 80 | * contents of this structure with :c:func:`cf_aes_finish` 81 | * when you're done. 82 | * 83 | * .. c:member:: cf_aes_context.rounds 84 | * 85 | * Number of rounds to use, set by :c:func:`cf_aes_init`. 86 | * 87 | * This depends on the original key size, and will be 88 | * :c:macro:`AES128_ROUNDS`, :c:macro:`AES192_ROUNDS` or 89 | * :c:macro:`AES256_ROUNDS`. 90 | * 91 | * .. c:member:: cf_aes_context.ks 92 | * 93 | * Expanded key material. Filled in by :c:func:`cf_aes_init`. 94 | */ 95 | typedef struct 96 | { 97 | uint32_t rounds; 98 | uint32_t ks[AES_BLOCKSZ / 4 * (CF_AES_MAXROUNDS + 1)]; 99 | } cf_aes_context; 100 | 101 | /* .. c:function:: $DECL 102 | * This function does AES key expansion. It destroys 103 | * existing contents of :c:data:`ctx`. 104 | * 105 | * :param ctx: expanded key context, filled in by this function. 106 | * :param key: pointer to key material, of :c:data:`nkey` bytes. 107 | * :param nkey: length of key material. Must be `16`, `24` or `32`. 108 | */ 109 | extern void cf_aes_init(cf_aes_context *ctx, 110 | const uint8_t *key, 111 | size_t nkey); 112 | 113 | /* .. c:function:: $DECL 114 | * Encrypts the given block, from :c:data:`in` to :c:data:`out`. 115 | * These may alias. 116 | * 117 | * Fails at runtime if :c:data:`ctx` is invalid. 118 | * 119 | * :param ctx: expanded key context 120 | * :param in: input block (read) 121 | * :param out: output block (written) 122 | */ 123 | extern void cf_aes_encrypt(const cf_aes_context *ctx, 124 | const uint8_t in[AES_BLOCKSZ], 125 | uint8_t out[AES_BLOCKSZ]); 126 | 127 | /* .. c:function:: $DECL 128 | * Decrypts the given block, from :c:data:`in` to :c:data:`out`. 129 | * These may alias. 130 | * 131 | * Fails at runtime if :c:data:`ctx` is invalid. 132 | * 133 | * :param ctx: expanded key context 134 | * :param in: input block (read) 135 | * :param out: output block (written) 136 | */ 137 | extern void cf_aes_decrypt(const cf_aes_context *ctx, 138 | const uint8_t in[AES_BLOCKSZ], 139 | uint8_t out[AES_BLOCKSZ]); 140 | 141 | /* .. c:function:: $DECL 142 | * Erase scheduled key material. 143 | * 144 | * Call this when you're done to erase the round keys. */ 145 | extern void cf_aes_finish(cf_aes_context *ctx); 146 | 147 | /* .. c:var:: const cf_prp cf_aes 148 | * Abstract interface to AES. See :c:type:`cf_prp` for 149 | * more information. */ 150 | extern const cf_prp cf_aes; 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /src/chacha20.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "bitops.h" 16 | #include "salsa20.h" 17 | #include "blockwise.h" 18 | #include "tassert.h" 19 | 20 | #include 21 | #include 22 | 23 | void cf_chacha20_core(const uint8_t key0[16], 24 | const uint8_t key1[16], 25 | const uint8_t nonce[16], 26 | const uint8_t constant[16], 27 | uint8_t out[64]) 28 | { 29 | uint32_t z0, z1, z2, z3, z4, z5, z6, z7, 30 | z8, z9, za, zb, zc, zd, ze, zf; 31 | 32 | uint32_t x0 = z0 = read32_le(constant + 0), 33 | x1 = z1 = read32_le(constant + 4), 34 | x2 = z2 = read32_le(constant + 8), 35 | x3 = z3 = read32_le(constant + 12), 36 | x4 = z4 = read32_le(key0 + 0), 37 | x5 = z5 = read32_le(key0 + 4), 38 | x6 = z6 = read32_le(key0 + 8), 39 | x7 = z7 = read32_le(key0 + 12), 40 | x8 = z8 = read32_le(key1 + 0), 41 | x9 = z9 = read32_le(key1 + 4), 42 | xa = za = read32_le(key1 + 8), 43 | xb = zb = read32_le(key1 + 12), 44 | xc = zc = read32_le(nonce + 0), 45 | xd = zd = read32_le(nonce + 4), 46 | xe = ze = read32_le(nonce + 8), 47 | xf = zf = read32_le(nonce + 12); 48 | 49 | #define QUARTER(a, b, c, d) \ 50 | a += b; d = rotl32(d ^ a, 16); \ 51 | c += d; b = rotl32(b ^ c, 12); \ 52 | a += b; d = rotl32(d ^ a, 8); \ 53 | c += d; b = rotl32(b ^ c, 7); 54 | 55 | for (int i = 0; i < 10; i++) 56 | { 57 | QUARTER(z0, z4, z8, zc); 58 | QUARTER(z1, z5, z9, zd); 59 | QUARTER(z2, z6, za, ze); 60 | QUARTER(z3, z7, zb, zf); 61 | QUARTER(z0, z5, za, zf); 62 | QUARTER(z1, z6, zb, zc); 63 | QUARTER(z2, z7, z8, zd); 64 | QUARTER(z3, z4, z9, ze); 65 | } 66 | 67 | x0 += z0; 68 | x1 += z1; 69 | x2 += z2; 70 | x3 += z3; 71 | x4 += z4; 72 | x5 += z5; 73 | x6 += z6; 74 | x7 += z7; 75 | x8 += z8; 76 | x9 += z9; 77 | xa += za; 78 | xb += zb; 79 | xc += zc; 80 | xd += zd; 81 | xe += ze; 82 | xf += zf; 83 | 84 | write32_le(x0, out + 0); 85 | write32_le(x1, out + 4); 86 | write32_le(x2, out + 8); 87 | write32_le(x3, out + 12); 88 | write32_le(x4, out + 16); 89 | write32_le(x5, out + 20); 90 | write32_le(x6, out + 24); 91 | write32_le(x7, out + 28); 92 | write32_le(x8, out + 32); 93 | write32_le(x9, out + 36); 94 | write32_le(xa, out + 40); 95 | write32_le(xb, out + 44); 96 | write32_le(xc, out + 48); 97 | write32_le(xd, out + 52); 98 | write32_le(xe, out + 56); 99 | write32_le(xf, out + 60); 100 | } 101 | 102 | static const uint8_t *chacha20_tau = (const uint8_t *) "expand 16-byte k"; 103 | static const uint8_t *chacha20_sigma = (const uint8_t *) "expand 32-byte k"; 104 | 105 | static void set_key(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey) 106 | { 107 | switch (nkey) 108 | { 109 | case 16: 110 | memcpy(ctx->key0, key, 16); 111 | memcpy(ctx->key1, key, 16); 112 | ctx->constant = chacha20_tau; 113 | break; 114 | case 32: 115 | memcpy(ctx->key0, key, 16); 116 | memcpy(ctx->key1, key + 16, 16); 117 | ctx->constant = chacha20_sigma; 118 | break; 119 | default: 120 | abort(); 121 | } 122 | } 123 | 124 | void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]) 125 | { 126 | set_key(ctx, key, nkey); 127 | memset(ctx->nonce, 0, sizeof ctx->nonce); 128 | memcpy(ctx->nonce + 8, nonce, 8); 129 | ctx->nblock = 0; 130 | ctx->ncounter = 8; 131 | } 132 | 133 | void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, 134 | const uint8_t nonce[16], size_t ncounter) 135 | { 136 | assert(ncounter > 0); 137 | set_key(ctx, key, nkey); 138 | memcpy(ctx->nonce, nonce, sizeof ctx->nonce); 139 | ctx->nblock = 0; 140 | ctx->ncounter = ncounter; 141 | } 142 | 143 | static void cf_chacha20_next_block(void *vctx, uint8_t *out) 144 | { 145 | cf_chacha20_ctx *ctx = vctx; 146 | cf_chacha20_core(ctx->key0, 147 | ctx->key1, 148 | ctx->nonce, 149 | ctx->constant, 150 | out); 151 | incr_le(ctx->nonce, ctx->ncounter); 152 | } 153 | 154 | void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes) 155 | { 156 | cf_blockwise_xor(ctx->block, &ctx->nblock, 64, 157 | input, output, bytes, 158 | cf_chacha20_next_block, 159 | ctx); 160 | } 161 | -------------------------------------------------------------------------------- /src/chacha20poly1305.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "chacha20poly1305.h" 16 | #include "salsa20.h" 17 | #include "poly1305.h" 18 | #include "bitops.h" 19 | #include "handy.h" 20 | 21 | #define ENCRYPT 1 22 | #define DECRYPT 0 23 | 24 | #define SUCCESS 0 25 | #define FAILURE 1 26 | 27 | static int process(const uint8_t key[static 32], 28 | const uint8_t nonce[static 12], 29 | const uint8_t *header, size_t nheader, 30 | const uint8_t *input, size_t nbytes, 31 | uint8_t *output, 32 | int mode, 33 | uint8_t tag[static 16]) 34 | { 35 | /* First, generate the Poly1305 key by running ChaCha20 with the 36 | * given key and a zero counter. The first half of the 37 | * 64-byte output is the key. */ 38 | uint8_t fullnonce[16] = { 0 }; 39 | memcpy(fullnonce + 4, nonce, 12); 40 | 41 | uint8_t polykey[32] = { 0 }; 42 | cf_chacha20_ctx chacha; 43 | cf_chacha20_init_custom(&chacha, key, 32, fullnonce, 4); 44 | cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); 45 | 46 | /* Now initialise Poly1305. */ 47 | cf_poly1305 poly; 48 | cf_poly1305_init(&poly, polykey, polykey + 16); 49 | mem_clean(polykey, sizeof polykey); 50 | 51 | /* Discard next 32 bytes of chacha20 key stream. */ 52 | cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); 53 | mem_clean(polykey, sizeof polykey); 54 | 55 | /* The input to Poly1305 is: 56 | * AAD || pad(AAD) || cipher || pad(cipher) || len_64(aad) || len_64(cipher) */ 57 | uint8_t padbuf[16] = { 0 }; 58 | 59 | #define PADLEN(x) ((16 - ((x) & 0xf)) & 0xf) 60 | 61 | /* AAD || pad(AAD) */ 62 | cf_poly1305_update(&poly, header, nheader); 63 | cf_poly1305_update(&poly, padbuf, PADLEN(nheader)); 64 | 65 | /* || cipher */ 66 | if (mode == ENCRYPT) 67 | { 68 | /* If we're encrypting, we compute the ciphertext 69 | * before inputting it into the MAC. */ 70 | cf_chacha20_cipher(&chacha, input, output, nbytes); 71 | cf_poly1305_update(&poly, output, nbytes); 72 | } else { 73 | /* Otherwise: decryption -- input the ciphertext. 74 | * Delay actual decryption until we checked the MAC. */ 75 | cf_poly1305_update(&poly, input, nbytes); 76 | } 77 | 78 | /* || pad(cipher) */ 79 | cf_poly1305_update(&poly, padbuf, PADLEN(nbytes)); 80 | 81 | /* || len_64(aad) || len_64(cipher) */ 82 | write64_le(nheader, padbuf); 83 | write64_le(nbytes, padbuf + 8); 84 | cf_poly1305_update(&poly, padbuf, sizeof padbuf); 85 | 86 | /* MAC computation is now complete. */ 87 | 88 | if (mode == ENCRYPT) 89 | { 90 | cf_poly1305_finish(&poly, tag); 91 | mem_clean(&chacha, sizeof chacha); 92 | return SUCCESS; 93 | } 94 | 95 | /* Decrypt mode: calculate tag, and check it. 96 | * If it's correct, proceed with decryption. */ 97 | uint8_t checktag[16]; 98 | cf_poly1305_finish(&poly, checktag); 99 | 100 | if (mem_eq(checktag, tag, sizeof checktag)) 101 | { 102 | cf_chacha20_cipher(&chacha, input, output, nbytes); 103 | mem_clean(&chacha, sizeof chacha); 104 | mem_clean(checktag, sizeof checktag); 105 | return SUCCESS; 106 | } else { 107 | mem_clean(output, nbytes); 108 | mem_clean(&chacha, sizeof chacha); 109 | mem_clean(checktag, sizeof checktag); 110 | return FAILURE; 111 | } 112 | } 113 | 114 | void cf_chacha20poly1305_encrypt(const uint8_t key[static 32], 115 | const uint8_t nonce[static 12], 116 | const uint8_t *header, size_t nheader, 117 | const uint8_t *plaintext, size_t nbytes, 118 | uint8_t *ciphertext, 119 | uint8_t tag[static 16]) 120 | { 121 | process(key, 122 | nonce, 123 | header, nheader, 124 | plaintext, nbytes, 125 | ciphertext, 126 | ENCRYPT, 127 | tag); 128 | } 129 | 130 | int cf_chacha20poly1305_decrypt(const uint8_t key[static 32], 131 | const uint8_t nonce[static 12], 132 | const uint8_t *header, size_t nheader, 133 | const uint8_t *ciphertext, size_t nbytes, 134 | const uint8_t tag[static 16], 135 | uint8_t *plaintext) 136 | { 137 | uint8_t ourtag[16]; 138 | memcpy(ourtag, tag, sizeof ourtag); 139 | 140 | return process(key, 141 | nonce, 142 | header, nheader, 143 | ciphertext, nbytes, 144 | plaintext, 145 | DECRYPT, 146 | ourtag); 147 | } 148 | 149 | -------------------------------------------------------------------------------- /src/curve25519.tweetnacl.c: -------------------------------------------------------------------------------- 1 | /* This is based on tweetnacl. Some typedefs have been 2 | * replaced with their stdint equivalents. 3 | * 4 | * Original code was public domain. */ 5 | 6 | #include 7 | #include 8 | 9 | #include "handy.h" 10 | 11 | typedef int64_t gf[16]; 12 | 13 | static const uint8_t _0[16], 14 | _9[32] = {9}; 15 | static const gf gf0, 16 | gf1 = {1}, 17 | _121665 = {0xDB41, 1}, 18 | D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 19 | 0xd8ab, 0x4141, 0x0a4d, 0x0070, 20 | 0xe898, 0x7779, 0x4079, 0x8cc7, 21 | 0xfe73, 0x2b6f, 0x6cee, 0x5203}, 22 | D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 23 | 0xb156, 0x8283, 0x149a, 0x00e0, 24 | 0xd130, 0xeef3, 0x80f2, 0x198e, 25 | 0xfce7, 0x56df, 0xd9dc, 0x2406}, 26 | X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 27 | 0xa7b2, 0x9525, 0xc760, 0x692c, 28 | 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 29 | 0x53fe, 0xcd6e, 0x36d3, 0x2169}, 30 | Y = {0x6658, 0x6666, 0x6666, 0x6666, 31 | 0x6666, 0x6666, 0x6666, 0x6666, 32 | 0x6666, 0x6666, 0x6666, 0x6666, 33 | 0x6666, 0x6666, 0x6666, 0x6666}, 34 | I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 35 | 0xe478, 0xad2f, 0x1806, 0x2f43, 36 | 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 37 | 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; 38 | 39 | static void set25519(gf r, const gf a) 40 | { 41 | for (size_t i = 0; i < 16; i++) 42 | r[i] = a[i]; 43 | } 44 | 45 | static void car25519(gf o) 46 | { 47 | int64_t c; 48 | 49 | for (size_t i = 0; i < 16; i++) 50 | { 51 | o[i] += (1LL << 16); 52 | c = o[i] >> 16; 53 | o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15); 54 | o[i] -= c << 16; 55 | } 56 | } 57 | 58 | static void sel25519(gf p, gf q, int b) 59 | { 60 | int64_t tmp, mask = ~(b-1); 61 | for (size_t i = 0; i < 16; i++) 62 | { 63 | tmp = mask & (p[i] ^ q[i]); 64 | p[i] ^= tmp; 65 | q[i] ^= tmp; 66 | } 67 | } 68 | 69 | static void pack25519(uint8_t out[32], const gf n) 70 | { 71 | int b; 72 | gf m, t; 73 | set25519(t, n); 74 | car25519(t); 75 | car25519(t); 76 | car25519(t); 77 | 78 | for(size_t j = 0; j < 2; j++) 79 | { 80 | m[0] = t[0] - 0xffed; 81 | for (size_t i = 1; i < 15; i++) 82 | { 83 | m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); 84 | m[i - 1] &= 0xffff; 85 | } 86 | m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); 87 | b = (m[15] >> 16) & 1; 88 | m[14] &= 0xffff; 89 | sel25519(t, m, 1 - b); 90 | } 91 | 92 | for (size_t i = 0; i < 16; i++) 93 | { 94 | out[2 * i] = t[i] & 0xff; 95 | out[2 * i + 1] = t[i] >> 8; 96 | } 97 | } 98 | 99 | 100 | 101 | static void unpack25519(gf o, const uint8_t *n) 102 | { 103 | for (size_t i = 0; i < 16; i++) 104 | o[i] = n[2 * i] + ((int64_t) n[2 * i + 1] << 8); 105 | o[15] &= 0x7fff; 106 | } 107 | 108 | static void add(gf o, const gf a, const gf b) 109 | { 110 | for (size_t i = 0; i < 16; i++) 111 | o[i] = a[i] + b[i]; 112 | } 113 | 114 | static void sub(gf o, const gf a, const gf b) 115 | { 116 | for (size_t i = 0; i < 16; i++) 117 | o[i] = a[i] - b[i]; 118 | } 119 | 120 | static void mul(gf o, const gf a, const gf b) 121 | { 122 | int64_t t[31]; 123 | 124 | for (size_t i = 0; i < 31; i++) 125 | t[i] = 0; 126 | 127 | for (size_t i = 0; i < 16; i++) 128 | for (size_t j = 0; j < 16; j++) 129 | t[i + j] += a[i] * b[j]; 130 | 131 | for (size_t i = 0; i < 15; i++) 132 | t[i] += 38 * t[i + 16]; 133 | 134 | for (size_t i = 0; i < 16; i++) 135 | o[i] = t[i]; 136 | 137 | car25519(o); 138 | car25519(o); 139 | } 140 | 141 | static void sqr(gf o, const gf a) 142 | { 143 | mul(o, a, a); 144 | } 145 | 146 | static void inv25519(gf o, const gf i) 147 | { 148 | gf c; 149 | for (int a = 0; a < 16; a++) 150 | c[a] = i[a]; 151 | 152 | for (int a = 253; a >= 0; a--) 153 | { 154 | sqr(c, c); 155 | if(a != 2 && a != 4) 156 | mul(c, c, i); 157 | } 158 | 159 | for (int a = 0; a < 16; a++) 160 | o[a] = c[a]; 161 | } 162 | 163 | 164 | void cf_curve25519_mul(uint8_t *q, const uint8_t *n, const uint8_t *p) 165 | { 166 | uint8_t z[32]; 167 | gf x; 168 | gf a, b, c, d, e, f; 169 | 170 | for (size_t i = 0; i < 31; i++) 171 | z[i] = n[i]; 172 | z[31] = (n[31] & 127) | 64; 173 | z[0] &= 248; 174 | 175 | unpack25519(x, p); 176 | 177 | for(size_t i = 0; i < 16; i++) 178 | { 179 | b[i] = x[i]; 180 | d[i] = a[i] = c[i] = 0; 181 | } 182 | 183 | a[0] = d[0] = 1; 184 | 185 | for (int i = 254; i >= 0; i--) 186 | { 187 | int64_t r = (z[i >> 3] >> (i & 7)) & 1; 188 | sel25519(a, b, r); 189 | sel25519(c, d, r); 190 | add(e, a, c); 191 | sub(a, a, c); 192 | add(c, b, d); 193 | sub(b, b, d); 194 | sqr(d, e); 195 | sqr(f, a); 196 | mul(a, c, a); 197 | mul(c, b, e); 198 | add(e, a, c); 199 | sub(a, a, c); 200 | sqr(b, a); 201 | sub(c, d, f); 202 | mul(a, c, _121665); 203 | add(a, a, d); 204 | mul(c, c, a); 205 | mul(a, d, f); 206 | mul(d, b, x); 207 | sqr(b, e); 208 | sel25519(a, b, r); 209 | sel25519(c, d, r); 210 | } 211 | 212 | inv25519(c, c); 213 | mul(a, a, c); 214 | pack25519(q, a); 215 | } 216 | 217 | void cf_curve25519_mul_base(uint8_t *q, const uint8_t *n) 218 | { 219 | cf_curve25519_mul(q, n, _9); 220 | } 221 | 222 | -------------------------------------------------------------------------------- /src/poly1305.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "poly1305.h" 16 | #include "bitops.h" 17 | #include "handy.h" 18 | #include "blockwise.h" 19 | 20 | #include 21 | #include 22 | 23 | void cf_poly1305_init(cf_poly1305 *ctx, 24 | const uint8_t r[static 16], 25 | const uint8_t s[static 16]) 26 | { 27 | memset(ctx, 0, sizeof *ctx); 28 | 29 | ctx->r[0] = r[0]; 30 | ctx->r[1] = r[1]; 31 | ctx->r[2] = r[2]; 32 | ctx->r[3] = r[3] & 0x0f; 33 | ctx->r[4] = r[4] & 0xfc; 34 | ctx->r[5] = r[5]; 35 | ctx->r[6] = r[6]; 36 | ctx->r[7] = r[7] & 0x0f; 37 | ctx->r[8] = r[8] & 0xfc; 38 | ctx->r[9] = r[9]; 39 | ctx->r[10] = r[10]; 40 | ctx->r[11] = r[11] & 0x0f; 41 | ctx->r[12] = r[12] & 0xfc; 42 | ctx->r[13] = r[13]; 43 | ctx->r[14] = r[14]; 44 | ctx->r[15] = r[15] & 0x0f; 45 | ctx->r[16] = 0; 46 | 47 | memcpy(ctx->s, s, 16); 48 | } 49 | 50 | static void poly1305_add(uint32_t h[static 17], 51 | const uint32_t x[static 17]) 52 | { 53 | uint32_t carry = 0; 54 | 55 | for (int i = 0; i < 17; i++) 56 | { 57 | carry += h[i] + x[i]; 58 | h[i] = carry & 0xff; 59 | carry >>= 8; 60 | } 61 | } 62 | 63 | /* Minimal reduction/carry chain. */ 64 | static void poly1305_min_reduce(uint32_t x[static 17]) 65 | { 66 | uint32_t carry = 0; 67 | for (int i = 0; i < 16; i++) 68 | { 69 | carry += x[i]; 70 | x[i] = carry & 0xff; 71 | carry >>= 8; 72 | } 73 | 74 | /* 2 ** 130 - 5 = 0x3fffffffffffffffffffffffffffffffb 75 | * ^ 76 | * So 2 bits of carry are put into top word. 77 | * Remaining bits get multiplied by 5 and carried back 78 | * into bottom */ 79 | carry += x[16]; 80 | x[16] = carry & 0x03; 81 | carry = 5 * (carry >> 2); 82 | 83 | for (int i = 0; i < 16; i++) 84 | { 85 | carry += x[i]; 86 | x[i] = carry & 0xff; 87 | carry >>= 8; 88 | } 89 | 90 | x[16] += carry; 91 | } 92 | 93 | /* This is - 2 ** 130 - 5 in twos complement. */ 94 | static const uint32_t negative_1305[17] = { 95 | 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96 | 0, 0, 0, 0, 0, 0, 0xfc 97 | }; 98 | 99 | static void poly1305_full_reduce(uint32_t x[static 17]) 100 | { 101 | uint32_t xsub[17]; 102 | 103 | for (size_t i = 0; i < 17; i++) 104 | xsub[i] = x[i]; 105 | 106 | poly1305_add(xsub, negative_1305); 107 | 108 | /* If x - (2 ** 130 - 5) is negative, then 109 | * x didn't need reduction: we discard the results. 110 | * Do this in a side-channel silent way. */ 111 | uint32_t negative_mask = mask_u32(xsub[16] & 0x80, 0x80); 112 | uint32_t positive_mask = negative_mask ^ 0xffffffff; 113 | 114 | for (size_t i = 0; i < 17; i++) 115 | x[i] = (x[i] & negative_mask) | (xsub[i] & positive_mask); 116 | } 117 | 118 | static void poly1305_mul(uint32_t x[static 17], 119 | const uint32_t y[static 17]) 120 | { 121 | uint32_t r[17]; 122 | 123 | for (int i = 0; i < 17; i++) 124 | { 125 | uint32_t accum = 0; 126 | 127 | for (int j = 0; j <= i; j++) 128 | accum += x[j] * y[i - j]; 129 | 130 | /* Add in carries. These get shifted 130 bits 131 | * to the right, with a combination of byte indexing 132 | * and shifting (136 bits right, then 6 bits left). 133 | * 134 | * nb. 5 << 6 is made up of two parts: 135 | * 5: reduction of 2 ** 130 leaves a multiple 5 136 | * shift 6 places left 137 | * 17 * 8: byte indexing shift (136 bits) 138 | * 130: desired shift 139 | */ 140 | for (int j = i + 1; j < 17; j++) 141 | accum += (5 << 6) * x[j] * y[i + 17 - j]; 142 | 143 | r[i] = accum; 144 | } 145 | 146 | poly1305_min_reduce(r); 147 | 148 | for (size_t i = 0; i < 17; i++) 149 | x[i] = r[i]; 150 | } 151 | 152 | static void poly1305_block(cf_poly1305 *ctx, 153 | const uint32_t c[static 17]) 154 | { 155 | poly1305_add(ctx->h, c); 156 | poly1305_mul(ctx->h, ctx->r); 157 | } 158 | 159 | static void poly1305_whole_block(void *vctx, 160 | const uint8_t *buf) 161 | { 162 | cf_poly1305 *ctx = vctx; 163 | uint32_t c[17]; 164 | 165 | for (int i = 0; i < 16; i++) 166 | c[i] = buf[i]; 167 | 168 | c[16] = 1; 169 | poly1305_block(ctx, c); 170 | } 171 | 172 | static void poly1305_last_block(cf_poly1305 *ctx) 173 | { 174 | uint32_t c[17] = { 0 }; 175 | 176 | for (size_t i = 0; i < ctx->npartial; i++) 177 | c[i] = ctx->partial[i]; 178 | 179 | c[ctx->npartial] = 1; 180 | poly1305_block(ctx, c); 181 | } 182 | 183 | void cf_poly1305_update(cf_poly1305 *ctx, 184 | const uint8_t *buf, 185 | size_t nbytes) 186 | { 187 | cf_blockwise_accumulate(ctx->partial, &ctx->npartial, 188 | sizeof ctx->partial, 189 | buf, nbytes, 190 | poly1305_whole_block, 191 | ctx); 192 | } 193 | 194 | void cf_poly1305_finish(cf_poly1305 *ctx, 195 | uint8_t out[static 16]) 196 | { 197 | if (ctx->npartial) 198 | poly1305_last_block(ctx); 199 | 200 | uint32_t s[17]; 201 | for (size_t i = 0; i < 16; i++) 202 | s[i] = ctx->s[i]; 203 | s[16] = 0; 204 | 205 | poly1305_full_reduce(ctx->h); 206 | poly1305_add(ctx->h, s); 207 | 208 | for (size_t i = 0; i < 16; i++) 209 | out[i] = ctx->h[i]; 210 | 211 | mem_clean(ctx, sizeof *ctx); 212 | } 213 | 214 | -------------------------------------------------------------------------------- /src/ccm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "handy.h" 16 | #include "prp.h" 17 | #include "modes.h" 18 | #include "tassert.h" 19 | 20 | #include 21 | 22 | #define CCM_ADATA_PRESENT 0x40 23 | 24 | static void write_be(uint8_t *out, size_t value, size_t bytes) 25 | { 26 | while (bytes) 27 | { 28 | out[bytes - 1] = value & 0xff; 29 | value >>= 8; 30 | bytes--; 31 | } 32 | 33 | assert(value == 0); /* or we couldn't encode the value. */ 34 | } 35 | 36 | static void zero_pad(cf_cbcmac_stream *cm) 37 | { 38 | cf_cbcmac_stream_finish_block_zero(cm); 39 | } 40 | 41 | /* nb. block is general workspace. */ 42 | static void add_aad(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK], 43 | const uint8_t *header, size_t nheader) 44 | { 45 | assert(nheader <= 0xffffffff); /* we don't support 64 bit lengths. */ 46 | 47 | /* Add length using stupidly complicated rules. */ 48 | if (nheader < 0xff00) 49 | { 50 | write_be(block, nheader, 2); 51 | cf_cbcmac_stream_update(cm, block, 2); 52 | } else { 53 | write_be(block, 0xfffe, 2); 54 | write_be(block + 2, nheader, 4); 55 | cf_cbcmac_stream_update(cm, block, 6); 56 | } 57 | 58 | cf_cbcmac_stream_update(cm, header, nheader); 59 | zero_pad(cm); 60 | } 61 | 62 | static void add_block0(cf_cbcmac_stream *cm, 63 | uint8_t block[CF_MAXBLOCK], size_t nblock, 64 | const uint8_t *nonce, size_t nnonce, 65 | size_t L, size_t nplain, 66 | size_t nheader, size_t ntag) 67 | { 68 | /* Construct first block B_0. */ 69 | block[0] = ((nheader == 0) ? 0x00 : CCM_ADATA_PRESENT) | 70 | ((ntag - 2) / 2) << 3 | 71 | (L - 1); 72 | memcpy(block + 1, nonce, nnonce); 73 | write_be(block + 1 + nnonce, nplain, L); 74 | 75 | cf_cbcmac_stream_update(cm, block, nblock); 76 | } 77 | 78 | static void build_ctr_nonce(uint8_t ctr_nonce[CF_MAXBLOCK], 79 | size_t L, 80 | const uint8_t *nonce, size_t nnonce) 81 | { 82 | ctr_nonce[0] = (L - 1); 83 | memcpy(ctr_nonce + 1, nonce, nnonce); 84 | memset(ctr_nonce + 1 + nnonce, 0, L); 85 | } 86 | 87 | void cf_ccm_encrypt(const cf_prp *prp, void *prpctx, 88 | const uint8_t *plain, size_t nplain, size_t L, 89 | const uint8_t *header, size_t nheader, 90 | const uint8_t *nonce, size_t nnonce, 91 | uint8_t *cipher, 92 | uint8_t *tag, size_t ntag) 93 | { 94 | uint8_t block[CF_MAXBLOCK]; 95 | 96 | assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); 97 | assert(L >= 2 && L <= 8); 98 | assert(nnonce == prp->blocksz - L - 1); 99 | 100 | cf_cbcmac_stream cm; 101 | cf_cbcmac_stream_init(&cm, prp, prpctx); 102 | 103 | /* Add first block. */ 104 | add_block0(&cm, block, prp->blocksz, 105 | nonce, nnonce, 106 | L, nplain, nheader, ntag); 107 | 108 | /* Add AAD with length prefix, if present. */ 109 | if (nheader) 110 | add_aad(&cm, block, header, nheader); 111 | 112 | /* Add message. */ 113 | cf_cbcmac_stream_update(&cm, plain, nplain); 114 | zero_pad(&cm); 115 | 116 | /* Finish tag. */ 117 | cf_cbcmac_stream_nopad_final(&cm, block); 118 | 119 | /* Start encryption. */ 120 | /* Construct A_0 */ 121 | uint8_t ctr_nonce[CF_MAXBLOCK]; 122 | build_ctr_nonce(ctr_nonce, L, nonce, nnonce); 123 | 124 | cf_ctr ctr; 125 | cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); 126 | cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); 127 | 128 | /* Encrypt tag first. */ 129 | cf_ctr_cipher(&ctr, block, block, prp->blocksz); 130 | memcpy(tag, block, ntag); 131 | 132 | /* Then encrypt message. */ 133 | cf_ctr_cipher(&ctr, plain, cipher, nplain); 134 | } 135 | 136 | int cf_ccm_decrypt(const cf_prp *prp, void *prpctx, 137 | const uint8_t *cipher, size_t ncipher, size_t L, 138 | const uint8_t *header, size_t nheader, 139 | const uint8_t *nonce, size_t nnonce, 140 | const uint8_t *tag, size_t ntag, 141 | uint8_t *plain) 142 | { 143 | uint8_t block[CF_MAXBLOCK]; 144 | 145 | assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); 146 | assert(L >= 2 && L <= 8); 147 | assert(nnonce == prp->blocksz - L - 1); 148 | 149 | uint8_t ctr_nonce[CF_MAXBLOCK]; 150 | build_ctr_nonce(ctr_nonce, L, nonce, nnonce); 151 | 152 | cf_ctr ctr; 153 | cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); 154 | cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); 155 | 156 | /* Decrypt tag. */ 157 | uint8_t plain_tag[CF_MAXBLOCK]; 158 | cf_ctr_cipher(&ctr, tag, plain_tag, ntag); 159 | cf_ctr_discard_block(&ctr); 160 | 161 | /* Decrypt message. */ 162 | cf_ctr_cipher(&ctr, cipher, plain, ncipher); 163 | 164 | cf_cbcmac_stream cm; 165 | cf_cbcmac_stream_init(&cm, prp, prpctx); 166 | 167 | /* Add first block. */ 168 | add_block0(&cm, block, prp->blocksz, 169 | nonce, nnonce, 170 | L, ncipher, nheader, ntag); 171 | 172 | if (nheader) 173 | add_aad(&cm, block, header, nheader); 174 | 175 | cf_cbcmac_stream_update(&cm, plain, ncipher); 176 | zero_pad(&cm); 177 | 178 | /* Finish tag. */ 179 | cf_cbcmac_stream_nopad_final(&cm, block); 180 | 181 | int err = 0; 182 | 183 | if (!mem_eq(block, plain_tag, ntag)) 184 | { 185 | err = 1; 186 | mem_clean(plain, ncipher); 187 | } 188 | 189 | mem_clean(block, sizeof block); 190 | mem_clean(plain_tag, sizeof plain_tag); 191 | return err; 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/blockwise.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "blockwise.h" 16 | #include "bitops.h" 17 | #include "handy.h" 18 | #include "tassert.h" 19 | 20 | #include 21 | 22 | void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, size_t nblock, 23 | const void *inp, size_t nbytes, 24 | cf_blockwise_in_fn process, 25 | void *ctx) 26 | { 27 | cf_blockwise_accumulate_final(partial, npartial, nblock, 28 | inp, nbytes, 29 | process, process, ctx); 30 | } 31 | 32 | void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, size_t nblock, 33 | const void *inp, size_t nbytes, 34 | cf_blockwise_in_fn process, 35 | cf_blockwise_in_fn process_final, 36 | void *ctx) 37 | { 38 | const uint8_t *bufin = inp; 39 | assert(partial && *npartial < nblock); 40 | assert(inp || !nbytes); 41 | assert(process && ctx); 42 | 43 | /* If we have partial data, copy in to buffer. */ 44 | if (*npartial && nbytes) 45 | { 46 | size_t space = nblock - *npartial; 47 | size_t taken = MIN(space, nbytes); 48 | 49 | memcpy(partial + *npartial, bufin, taken); 50 | 51 | bufin += taken; 52 | nbytes -= taken; 53 | *npartial += taken; 54 | 55 | /* If that gives us a full block, process it. */ 56 | if (*npartial == nblock) 57 | { 58 | if (nbytes == 0) 59 | process_final(ctx, partial); 60 | else 61 | process(ctx, partial); 62 | *npartial = 0; 63 | } 64 | } 65 | 66 | /* now nbytes < nblock or *npartial == 0. */ 67 | 68 | /* If we have a full block of data, process it directly. */ 69 | while (nbytes >= nblock) 70 | { 71 | /* Partial buffer must be empty, or we're ignoring extant data */ 72 | assert(*npartial == 0); 73 | 74 | if (nbytes == nblock) 75 | process_final(ctx, bufin); 76 | else 77 | process(ctx, bufin); 78 | bufin += nblock; 79 | nbytes -= nblock; 80 | } 81 | 82 | /* Finally, if we have remaining data, buffer it. */ 83 | while (nbytes) 84 | { 85 | size_t space = nblock - *npartial; 86 | size_t taken = MIN(space, nbytes); 87 | 88 | memcpy(partial + *npartial, bufin, taken); 89 | 90 | bufin += taken; 91 | nbytes -= taken; 92 | *npartial += taken; 93 | 94 | /* If we started with *npartial, we must have copied it 95 | * in first. */ 96 | assert(*npartial < nblock); 97 | } 98 | } 99 | 100 | void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock, 101 | const void *inp, void *outp, size_t nbytes, 102 | cf_blockwise_out_fn process, void *ctx) 103 | { 104 | const uint8_t *inb = inp; 105 | uint8_t *outb = outp; 106 | 107 | assert(partial && *npartial < nblock); 108 | assert(inp || !nbytes); 109 | assert(process && ctx); 110 | 111 | while (nbytes) 112 | { 113 | /* If we're out of material, and need more, produce a block. */ 114 | if (*npartial == 0) 115 | { 116 | process(ctx, partial); 117 | *npartial = nblock; 118 | } 119 | 120 | size_t offset = nblock - *npartial; 121 | size_t taken = MIN(*npartial, nbytes); 122 | xor_bb(outb, inb, partial + offset, taken); 123 | *npartial -= taken; 124 | nbytes -= taken; 125 | outb += taken; 126 | inb += taken; 127 | } 128 | } 129 | 130 | void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial, 131 | size_t nblock, 132 | uint8_t byte, size_t nbytes, 133 | cf_blockwise_in_fn process, 134 | void *ctx) 135 | { 136 | /* only memset the whole of the block once */ 137 | int filled = 0; 138 | 139 | while (nbytes) 140 | { 141 | size_t start = *npartial; 142 | size_t count = MIN(nbytes, nblock - start); 143 | 144 | if (!filled) 145 | memset(partial + start, byte, count); 146 | 147 | if (start == 0 && count == nblock) 148 | filled = 1; 149 | 150 | if (start + count == nblock) 151 | { 152 | process(ctx, partial); 153 | *npartial = 0; 154 | } else { 155 | *npartial += count; 156 | } 157 | 158 | nbytes -= count; 159 | } 160 | } 161 | 162 | void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial, 163 | size_t nblock, 164 | uint8_t fbyte, uint8_t mbyte, uint8_t lbyte, 165 | size_t nbytes, 166 | cf_blockwise_in_fn process, 167 | void *ctx) 168 | { 169 | 170 | switch (nbytes) 171 | { 172 | case 0: break; 173 | case 1: fbyte ^= lbyte; 174 | cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); 175 | break; 176 | case 2: 177 | cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); 178 | cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx); 179 | break; 180 | default: 181 | cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); 182 | 183 | /* If the middle and last bytes differ, then process the last byte separately. 184 | * Otherwise, just extend the middle block size. */ 185 | if (lbyte != mbyte) 186 | { 187 | cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 2, process, ctx); 188 | cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx); 189 | } else { 190 | cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 1, process, ctx); 191 | } 192 | 193 | break; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/sha3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef SHA3_H 16 | #define SHA3_H 17 | 18 | #include 19 | #include 20 | 21 | #include "chash.h" 22 | 23 | /** 24 | * SHA3/Keccak 25 | * =========== 26 | * This implementation is compatible with FIPS 202, 27 | * rather than the original Keccak submission. 28 | * 29 | */ 30 | 31 | /* .. c:macro:: CF_SHA3_224_HASHSZ 32 | * The output size of SHA3-224: 28 bytes. */ 33 | #define CF_SHA3_224_HASHSZ 28 34 | 35 | /* .. c:macro:: CF_SHA3_256_HASHSZ 36 | * The output size of SHA3-256: 32 bytes. */ 37 | #define CF_SHA3_256_HASHSZ 32 38 | 39 | /* .. c:macro:: CF_SHA3_384_HASHSZ 40 | * The output size of SHA3-384: 48 bytes. */ 41 | #define CF_SHA3_384_HASHSZ 48 42 | 43 | /* .. c:macro:: CF_SHA3_512_HASHSZ 44 | * The output size of SHA3-512: 64 bytes. */ 45 | #define CF_SHA3_512_HASHSZ 64 46 | 47 | /* .. c:macro:: CF_SHA3_224_BLOCKSZ 48 | * The block size of SHA3-224. */ 49 | #define CF_SHA3_224_BLOCKSZ 144 50 | 51 | /* .. c:macro:: CF_SHA3_256_BLOCKSZ 52 | * The block size of SHA3-256. */ 53 | #define CF_SHA3_256_BLOCKSZ 136 54 | 55 | /* .. c:macro:: CF_SHA3_384_BLOCKSZ 56 | * The block size of SHA3-384. */ 57 | #define CF_SHA3_384_BLOCKSZ 104 58 | 59 | /* .. c:macro:: CF_SHA3_512_BLOCKSZ 60 | * The block size of SHA3-512. */ 61 | #define CF_SHA3_512_BLOCKSZ 72 62 | 63 | /* The block size of SHAKE128 */ 64 | #define CF_SHAKE_128_BLOCKSZ 168 65 | 66 | /* The block size of SHAKE256 */ 67 | #define CF_SHAKE_256_BLOCKSZ 136 68 | 69 | /* Padding and domain separation constants. 70 | * 71 | * FIPS 202 specifies that 0b01 is appended to hash function 72 | * input, and 0b1111 is appended to SHAKE input. 73 | * 74 | * This is done in internal (little endian) bit ordering, and 75 | * we convolve it with the leftmost (first) padding bit, so: 76 | * 77 | * Hash: 0b110 78 | * SHAKE: 0b11111 79 | */ 80 | #define DOMAIN_HASH_PAD 0x06 81 | #define DOMAIN_SHAKE_PAD 0x1f 82 | 83 | /* We use bit-interleaved internal representation. This 84 | * stores a 64 bit quantity in two 32 bit words: one word 85 | * contains odd bits, the other even. This means 64-bit rotations 86 | * are cheaper to compute. */ 87 | typedef struct 88 | { 89 | uint32_t odd, evn; 90 | } cf_sha3_bi; 91 | 92 | /* .. c:type:: cf_sha3_context 93 | * Incremental SHA3 hashing context. 94 | * 95 | * .. c:member:: cf_sha3_context.A 96 | * Intermediate state. 97 | * 98 | * .. c:member:: cf_sha3_context.partial 99 | * Unprocessed input. 100 | * 101 | * .. c:member:: cf_sha3_context.npartial 102 | * Number of bytes of unprocessed input. 103 | * 104 | * .. c:member:: cf_sha3_context.rate 105 | * Sponge absorption rate. 106 | * 107 | * .. c:member:: cf_sha3_context.rate 108 | * Sponge capacity. 109 | */ 110 | typedef struct 111 | { 112 | /* State is a 5x5 block of 64-bit values, for Keccak-f[1600]. */ 113 | cf_sha3_bi A[5][5]; 114 | uint8_t partial[CF_SHAKE_128_BLOCKSZ]; 115 | size_t npartial; 116 | uint16_t rate, capacity; /* rate and capacity, in bytes. */ 117 | uint8_t domain_pad; 118 | } cf_sha3_context; 119 | 120 | 121 | /* -- _init functions -- */ 122 | 123 | /* .. c:function:: $DECL */ 124 | extern void cf_sha3_224_init(cf_sha3_context *ctx); 125 | 126 | /* .. c:function:: $DECL */ 127 | extern void cf_sha3_256_init(cf_sha3_context *ctx); 128 | 129 | /* .. c:function:: $DECL */ 130 | extern void cf_sha3_384_init(cf_sha3_context *ctx); 131 | 132 | /* .. c:function:: $DECL 133 | * Sets up `ctx` ready to hash a new message. 134 | */ 135 | extern void cf_sha3_512_init(cf_sha3_context *ctx); 136 | 137 | /* -- _update functions -- */ 138 | 139 | /* .. c:function:: $DECL */ 140 | extern void cf_sha3_224_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 141 | 142 | /* .. c:function:: $DECL */ 143 | extern void cf_sha3_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 144 | 145 | /* .. c:function:: $DECL */ 146 | extern void cf_sha3_384_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 147 | 148 | /* .. c:function:: $DECL 149 | * Hashes `nbytes` at `data`. Copies the data for processing later if there 150 | * isn't enough to make a full block. 151 | */ 152 | extern void cf_sha3_512_update(cf_sha3_context *ctx, const void *data, size_t nbytes); 153 | 154 | /* -- _digest functions -- */ 155 | 156 | /* .. c:function:: $DECL */ 157 | extern void cf_sha3_224_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]); 158 | 159 | /* .. c:function:: $DECL */ 160 | extern void cf_sha3_256_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]); 161 | 162 | /* .. c:function:: $DECL */ 163 | extern void cf_sha3_384_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]); 164 | 165 | /* .. c:function:: $DECL 166 | * Finishes the hashing operation, writing result to `hash`. 167 | * 168 | * This leaves `ctx` unchanged. 169 | */ 170 | extern void cf_sha3_512_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]); 171 | 172 | /* -- _digest_final functions -- */ 173 | 174 | /* .. c:function:: $DECL */ 175 | extern void cf_sha3_224_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]); 176 | 177 | /* .. c:function:: $DECL */ 178 | extern void cf_sha3_256_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]); 179 | 180 | /* .. c:function:: $DECL */ 181 | extern void cf_sha3_384_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]); 182 | 183 | /* .. c:function:: $DECL 184 | * Finishes the hashing operation, writing result to `hash`. 185 | * 186 | * This destroys the contents of `ctx`. 187 | */ 188 | extern void cf_sha3_512_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]); 189 | 190 | /* .. c:var:: cf_sha3_224 191 | * .. c:var:: cf_sha3_256 192 | * .. c:var:: cf_sha3_384 193 | * .. c:var:: cf_sha3_512 194 | * Abstract interface to SHA3 functions. See :c:type:`cf_chash` for more information. 195 | */ 196 | extern const cf_chash cf_sha3_224; 197 | extern const cf_chash cf_sha3_256; 198 | extern const cf_chash cf_sha3_384; 199 | extern const cf_chash cf_sha3_512; 200 | 201 | #endif 202 | -------------------------------------------------------------------------------- /src/blockwise.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef BLOCKWISE_H 16 | #define BLOCKWISE_H 17 | 18 | #include 19 | #include 20 | 21 | /* Processing function for cf_blockwise_accumulate. */ 22 | typedef void (*cf_blockwise_in_fn)(void *ctx, const uint8_t *data); 23 | 24 | /* Processing function for cf_blockwise_xor. */ 25 | typedef void (*cf_blockwise_out_fn)(void *ctx, uint8_t *data); 26 | 27 | /* This function manages the common abstraction of accumulating input in 28 | * a buffer, and processing it when a full block is available. 29 | * 30 | * partial is the buffer (maintained by the caller) 31 | * on entry, npartial is the currently valid count of used bytes on 32 | * the front of partial. 33 | * on exit, npartial is updated to reflect the status of partial. 34 | * nblock is the blocksize to accumulate -- partial must be at least 35 | * this long! 36 | * input is the new data to process, of length nbytes. 37 | * process is the processing function, passed ctx and a pointer 38 | * to the data to process (always exactly nblock bytes long!) 39 | * which may not neccessarily be the same as partial. 40 | */ 41 | void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, 42 | size_t nblock, 43 | const void *input, size_t nbytes, 44 | cf_blockwise_in_fn process, 45 | void *ctx); 46 | 47 | /* This function manages the common abstraction of accumulating input in 48 | * a buffer, and processing it when a full block is available. 49 | * This version supports calling a different processing function for 50 | * the last block. 51 | * 52 | * partial is the buffer (maintained by the caller) 53 | * on entry, npartial is the currently valid count of used bytes on 54 | * the front of partial. 55 | * on exit, npartial is updated to reflect the status of partial. 56 | * nblock is the blocksize to accumulate -- partial must be at least 57 | * this long! 58 | * input is the new data to process, of length nbytes. 59 | * process is the processing function, passed ctx and a pointer 60 | * to the data to process (always exactly nblock bytes long!) 61 | * which may not neccessarily be the same as partial. 62 | * process_final is called last (but may not be called at all if 63 | * all input is buffered). 64 | */ 65 | void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, 66 | size_t nblock, 67 | const void *input, size_t nbytes, 68 | cf_blockwise_in_fn process, 69 | cf_blockwise_in_fn process_final, 70 | void *ctx); 71 | 72 | /* This function manages XORing an input stream with a keystream 73 | * to produce an output stream. The keystream is produced in blocks 74 | * (ala a block cipher in counter mode). 75 | * 76 | * partial is the keystream buffer (maintained by the caller) 77 | * on entry, *npartial is the currently valid count of bytes in partial: 78 | * unused bytes are at the *end*. So *npartial = 4 means the last four 79 | * bytes of partial are usable as keystream. 80 | * on exit, npartial is updated to reflect the new state of partial. 81 | * nblock is the blocksize to accumulate -- partial must be at least 82 | * this long! 83 | * input is the new data to process, of length nbytes. 84 | * output is where to write input xored with the keystream -- also length 85 | * nbytes. 86 | * process is the processing function, passed ctx and partial which it 87 | * should fill with fresh key stream. 88 | */ 89 | void cf_blockwise_xor(uint8_t *partial, size_t *npartial, 90 | size_t nblock, 91 | const void *input, void *output, size_t nbytes, 92 | cf_blockwise_out_fn newblock, 93 | void *ctx); 94 | 95 | /* This function processes a single byte a number of times. It's useful 96 | * for padding, and more efficient than calling cf_blockwise_accumulate 97 | * a bunch of times. 98 | * 99 | * partial is the buffer (maintained by the caller) 100 | * on entry, npartial is the currently valid count of used bytes on 101 | * the front of partial. 102 | * on exit, npartial is updated to reflect the status of partial. 103 | * nblock is the blocksize to accumulate -- partial must be at least 104 | * this long! 105 | * process is the processing function, passed ctx and a pointer 106 | * to the data to process (always exactly nblock bytes long!) 107 | * which may not neccessarily be the same as partial. 108 | * byte is the byte to process, nbytes times. 109 | */ 110 | void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial, 111 | size_t nblock, 112 | uint8_t byte, size_t nbytes, 113 | cf_blockwise_in_fn process, 114 | void *ctx); 115 | 116 | /* This function attempts to process patterns of bytes common in 117 | * block cipher padding. 118 | * 119 | * This takes three bytes: 120 | * - a first byte, fbyte, 121 | * - a middle byte, mbyte, 122 | * - a last byte, lbyte. 123 | * 124 | * If nbytes is zero, nothing happens. 125 | * If nbytes is one, the byte fbyte ^ lbyte is processed. 126 | * If nbytes is two, the fbyte then lbyte are processed. 127 | * If nbytes is three or more, fbyte, then one or more mbytes, then fbyte 128 | * is processed. 129 | * 130 | * partial is the buffer (maintained by the caller) 131 | * on entry, npartial is the currently valid count of used bytes on 132 | * the front of partial. 133 | * on exit, npartial is updated to reflect the status of partial. 134 | * nblock is the blocksize to accumulate -- partial must be at least 135 | * this long! 136 | * process is the processing function, passed ctx and a pointer 137 | * to the data to process (always exactly nblock bytes long!) 138 | * which may not neccessarily be the same as partial. 139 | */ 140 | void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial, 141 | size_t nblock, 142 | uint8_t fbyte, uint8_t mbyte, uint8_t lbyte, 143 | size_t nbytes, 144 | cf_blockwise_in_fn process, 145 | void *ctx); 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /src/gcm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #include "handy.h" 16 | #include "prp.h" 17 | #include "modes.h" 18 | #include "blockwise.h" 19 | #include "bitops.h" 20 | #include "gf128.h" 21 | #include "tassert.h" 22 | 23 | #include 24 | 25 | /* Incremental GHASH computation. */ 26 | typedef struct 27 | { 28 | cf_gf128 H; 29 | cf_gf128 Y; 30 | uint8_t buffer[16]; 31 | size_t buffer_used; 32 | uint64_t len_aad; 33 | uint64_t len_cipher; 34 | unsigned state; 35 | #define STATE_INVALID 0 36 | #define STATE_AAD 1 37 | #define STATE_CIPHER 2 38 | } ghash_ctx; 39 | 40 | static void ghash_init(ghash_ctx *ctx, uint8_t H[16]) 41 | { 42 | memset(ctx, 0, sizeof *ctx); 43 | cf_gf128_frombytes_be(H, ctx->H); 44 | ctx->state = STATE_AAD; 45 | } 46 | 47 | static void ghash_block(void *vctx, const uint8_t *data) 48 | { 49 | ghash_ctx *ctx = vctx; 50 | cf_gf128 gfdata; 51 | cf_gf128_frombytes_be(data, gfdata); 52 | cf_gf128_add(gfdata, ctx->Y, ctx->Y); 53 | cf_gf128_mul(ctx->Y, ctx->H, ctx->Y); 54 | } 55 | 56 | static void ghash_add(ghash_ctx *ctx, const uint8_t *buf, size_t n) 57 | { 58 | cf_blockwise_accumulate(ctx->buffer, &ctx->buffer_used, 59 | sizeof ctx->buffer, 60 | buf, n, 61 | ghash_block, 62 | ctx); 63 | } 64 | 65 | static void ghash_add_pad(ghash_ctx *ctx) 66 | { 67 | if (ctx->buffer_used == 0) 68 | return; 69 | 70 | memset(ctx->buffer + ctx->buffer_used, 0, sizeof(ctx->buffer) - ctx->buffer_used); 71 | ghash_block(ctx, ctx->buffer); 72 | ctx->buffer_used = 0; 73 | } 74 | 75 | static void ghash_add_aad(ghash_ctx *ctx, const uint8_t *buf, size_t n) 76 | { 77 | assert(ctx->state == STATE_AAD); 78 | ctx->len_aad += n; 79 | ghash_add(ctx, buf, n); 80 | } 81 | 82 | static void ghash_add_cipher(ghash_ctx *ctx, const uint8_t *buf, size_t n) 83 | { 84 | if (ctx->state == STATE_AAD) 85 | { 86 | ghash_add_pad(ctx); 87 | ctx->state = STATE_CIPHER; 88 | } 89 | 90 | assert(ctx->state == STATE_CIPHER); 91 | ctx->len_cipher += n; 92 | ghash_add(ctx, buf, n); 93 | } 94 | 95 | static void ghash_final(ghash_ctx *ctx, uint8_t out[16]) 96 | { 97 | uint8_t lenbuf[8]; 98 | 99 | if (ctx->state == STATE_AAD || ctx->state == STATE_CIPHER) 100 | { 101 | ghash_add_pad(ctx); 102 | ctx->state = STATE_INVALID; 103 | } 104 | 105 | /* Add len(A) || len(C) */ 106 | write64_be(ctx->len_aad * 8, lenbuf); 107 | ghash_add(ctx, lenbuf, sizeof lenbuf); 108 | 109 | write64_be(ctx->len_cipher * 8, lenbuf); 110 | ghash_add(ctx, lenbuf, sizeof lenbuf); 111 | 112 | assert(ctx->buffer_used == 0); 113 | cf_gf128_tobytes_be(ctx->Y, out); 114 | } 115 | 116 | void cf_gcm_encrypt(const cf_prp *prp, void *prpctx, 117 | const uint8_t *plain, size_t nplain, 118 | const uint8_t *header, size_t nheader, 119 | const uint8_t *nonce, size_t nnonce, 120 | uint8_t *cipher, /* the same size as nplain */ 121 | uint8_t *tag, size_t ntag) 122 | { 123 | uint8_t H[16] = { 0 }; 124 | uint8_t Y0[16]; 125 | 126 | /* H = E_K(0^128) */ 127 | prp->encrypt(prpctx, H, H); 128 | 129 | /* Produce CTR nonce, Y_0: 130 | * 131 | * if len(IV) == 96 132 | * Y_0 = IV || 0^31 || 1 133 | * otherwise 134 | * Y_0 = GHASH(H, {}, IV) 135 | */ 136 | 137 | if (nnonce == 12) 138 | { 139 | memcpy(Y0, nonce, nnonce); 140 | Y0[12] = Y0[13] = Y0[14] = 0x00; 141 | Y0[15] = 0x01; 142 | } else { 143 | ghash_ctx gh; 144 | ghash_init(&gh, H); 145 | ghash_add_cipher(&gh, nonce, nnonce); 146 | ghash_final(&gh, Y0); 147 | } 148 | 149 | /* Hash AAD */ 150 | ghash_ctx gh; 151 | ghash_init(&gh, H); 152 | ghash_add_aad(&gh, header, nheader); 153 | 154 | /* Produce ciphertext */ 155 | uint8_t e_Y0[16] = { 0 }; 156 | cf_ctr ctr; 157 | cf_ctr_init(&ctr, prp, prpctx, Y0); 158 | cf_ctr_custom_counter(&ctr, 12, 4); /* counter is 2^32 */ 159 | cf_ctr_cipher(&ctr, e_Y0, e_Y0, sizeof e_Y0); /* first block is tag offset */ 160 | cf_ctr_cipher(&ctr, plain, cipher, nplain); 161 | 162 | /* Hash ciphertext */ 163 | ghash_add_cipher(&gh, cipher, nplain); 164 | 165 | /* Post-process ghash output */ 166 | uint8_t full_tag[16] = { 0 }; 167 | ghash_final(&gh, full_tag); 168 | 169 | assert(ntag > 1 && ntag <= 16); 170 | xor_bb(tag, full_tag, e_Y0, ntag); 171 | 172 | mem_clean(H, sizeof H); 173 | mem_clean(Y0, sizeof Y0); 174 | mem_clean(e_Y0, sizeof e_Y0); 175 | mem_clean(full_tag, sizeof full_tag); 176 | mem_clean(&gh, sizeof gh); 177 | mem_clean(&ctr, sizeof ctr); 178 | } 179 | 180 | int cf_gcm_decrypt(const cf_prp *prp, void *prpctx, 181 | const uint8_t *cipher, size_t ncipher, 182 | const uint8_t *header, size_t nheader, 183 | const uint8_t *nonce, size_t nnonce, 184 | const uint8_t *tag, size_t ntag, 185 | uint8_t *plain) 186 | { 187 | uint8_t H[16] = { 0 }; 188 | uint8_t Y0[16]; 189 | 190 | /* H = E_K(0^128) */ 191 | prp->encrypt(prpctx, H, H); 192 | 193 | /* Produce CTR nonce, Y_0: 194 | * 195 | * if len(IV) == 96 196 | * Y_0 = IV || 0^31 || 1 197 | * otherwise 198 | * Y_0 = GHASH(H, {}, IV) 199 | */ 200 | 201 | if (nnonce == 12) 202 | { 203 | memcpy(Y0, nonce, nnonce); 204 | Y0[12] = Y0[13] = Y0[14] = 0x00; 205 | Y0[15] = 0x01; 206 | } else { 207 | ghash_ctx gh; 208 | ghash_init(&gh, H); 209 | ghash_add_cipher(&gh, nonce, nnonce); 210 | ghash_final(&gh, Y0); 211 | } 212 | 213 | /* Hash AAD. */ 214 | ghash_ctx gh; 215 | ghash_init(&gh, H); 216 | ghash_add_aad(&gh, header, nheader); 217 | 218 | /* Start counter mode, to obtain offset on tag. */ 219 | uint8_t e_Y0[16] = { 0 }; 220 | cf_ctr ctr; 221 | cf_ctr_init(&ctr, prp, prpctx, Y0); 222 | cf_ctr_custom_counter(&ctr, 12, 4); 223 | cf_ctr_cipher(&ctr, e_Y0, e_Y0, sizeof e_Y0); 224 | 225 | /* Hash ciphertext. */ 226 | ghash_add_cipher(&gh, cipher, ncipher); 227 | 228 | /* Produce tag. */ 229 | uint8_t full_tag[16]; 230 | ghash_final(&gh, full_tag); 231 | assert(ntag > 1 && ntag <= 16); 232 | xor_bb(full_tag, full_tag, e_Y0, ntag); 233 | 234 | int err = 1; 235 | if (!mem_eq(full_tag, tag, ntag)) 236 | goto x_err; 237 | 238 | /* Complete decryption. */ 239 | cf_ctr_cipher(&ctr, cipher, plain, ncipher); 240 | err = 0; 241 | 242 | x_err: 243 | mem_clean(H, sizeof H); 244 | mem_clean(Y0, sizeof Y0); 245 | mem_clean(e_Y0, sizeof e_Y0); 246 | mem_clean(full_tag, sizeof full_tag); 247 | mem_clean(&gh, sizeof gh); 248 | mem_clean(&ctr, sizeof ctr); 249 | return err; 250 | } 251 | -------------------------------------------------------------------------------- /src/testsha.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2014 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef TESTSHA_H 16 | #define TESTSHA_H 17 | 18 | #include "hmac.h" 19 | 20 | /* Common functions for testing hash functions. 21 | * You shouldn't use this file. */ 22 | 23 | static void vector(const cf_chash *hash, 24 | const void *vmsg, size_t nmsg, 25 | const char *expect, size_t nexpect) 26 | { 27 | uint8_t digest[CF_MAXHASH]; 28 | const uint8_t *msg = vmsg; 29 | size_t orig_nmsg = nmsg; 30 | 31 | cf_chash_ctx ctx; 32 | hash->init(&ctx); 33 | 34 | /* Input in carefully chosen chunk sizes to exercise blockwise code. */ 35 | if (nmsg) 36 | { 37 | hash->update(&ctx, msg, 1); 38 | nmsg--; 39 | msg++; 40 | } 41 | 42 | hash->update(&ctx, msg, nmsg); 43 | hash->digest(&ctx, digest); 44 | TEST_CHECK(nexpect == hash->hashsz); 45 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 46 | 47 | /* Now try with other arrangements. */ 48 | msg = vmsg; 49 | nmsg = orig_nmsg; 50 | 51 | hash->init(&ctx); 52 | if (nmsg >= hash->blocksz) 53 | { 54 | hash->update(&ctx, msg, hash->blocksz - 1); 55 | nmsg -= hash->blocksz - 1; 56 | msg += hash->blocksz - 1; 57 | } 58 | 59 | hash->update(&ctx, msg, nmsg); 60 | hash->digest(&ctx, digest); 61 | TEST_CHECK(memcmp(digest, expect, nexpect) == 0); 62 | } 63 | 64 | /* These are shared between RFC2202 and RFC4231. */ 65 | static inline void hmac_test(const cf_chash *hash, 66 | const void *hi_there, 67 | const void *jefe, 68 | const void *aa_dd, 69 | const void *counter_key) 70 | { 71 | uint8_t sig[CF_MAXHASH]; 72 | uint8_t key[25], message[50]; 73 | 74 | /* Key: 0x0b * 20 75 | * Message: "Hi There" 76 | */ 77 | memset(key, 0x0b, 20); 78 | memcpy(message, "Hi There", 8); 79 | cf_hmac(key, 20, message, 8, sig, hash); 80 | 81 | TEST_CHECK(memcmp(sig, hi_there, hash->hashsz) == 0); 82 | 83 | /* Key: "Jefe" 84 | * Message: "what do ya want for nothing?" 85 | */ 86 | memcpy(key, "Jefe", 4); 87 | memcpy(message, "what do ya want for nothing?", 28); 88 | cf_hmac(key, 4, message, 28, sig, hash); 89 | TEST_CHECK(memcmp(sig, jefe, hash->hashsz) == 0); 90 | 91 | /* Key: 0xaa * 20 92 | * Message: 0xdd * 50 93 | */ 94 | memset(key, 0xaa, 20); 95 | memset(message, 0xdd, 50); 96 | cf_hmac(key, 20, message, 50, sig, hash); 97 | TEST_CHECK(memcmp(sig, aa_dd, hash->hashsz) == 0); 98 | 99 | /* Key: 0x01..0x19 100 | * Message: 0xcd * 50 101 | */ 102 | for (uint8_t i = 1; i < 26; i++) 103 | key[i - 1] = i; 104 | memset(message, 0xcd, 50); 105 | cf_hmac(key, 25, message, 50, sig, hash); 106 | TEST_CHECK(memcmp(sig, counter_key, hash->hashsz) == 0); 107 | } 108 | 109 | /* These are specific to RFC4231. */ 110 | static inline void hmac_test_sha2(const cf_chash *hash, 111 | const char *long_key, 112 | const char *long_message) 113 | { 114 | uint8_t sig[CF_MAXHASH]; 115 | uint8_t key[131], message[152]; 116 | 117 | /* Key: 0xaa * 131 118 | * Message: "Test Using Larger Than Block-Size Key - Hash Key First" 119 | */ 120 | memset(key, 0xaa, 131); 121 | memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54); 122 | cf_hmac(key, 131, message, 54, sig, hash); 123 | TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0); 124 | 125 | /* Key: 0xaa * 131 126 | * Message: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." 127 | */ 128 | memset(key, 0xaa, 131); 129 | memcpy(message, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", 152); 130 | cf_hmac(key, 131, message, 152, sig, hash); 131 | TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0); 132 | } 133 | 134 | /* This is as hmac_test_sha2, except the sizes are specific to 135 | * a 512-bit block. This is from RFC2202. */ 136 | static inline void hmac_test_sha1(const cf_chash *hash, 137 | const char *long_key, 138 | const char *long_message) 139 | { 140 | uint8_t sig[CF_MAXHASH]; 141 | uint8_t key[80], message[73]; 142 | 143 | /* Key: 0xaa * 80 144 | * Message: "Test Using Larger Than Block-Size Key - Hash Key First" 145 | */ 146 | memset(key, 0xaa, 80); 147 | memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54); 148 | cf_hmac(key, 80, message, 54, sig, hash); 149 | TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0); 150 | 151 | /* Key: 0xaa * 80 152 | * Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" 153 | */ 154 | memset(key, 0xaa, 80); 155 | memcpy(message, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73); 156 | cf_hmac(key, 80, message, 73, sig, hash); 157 | TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0); 158 | } 159 | 160 | typedef void (*final_fn)(void *ctx, uint8_t *out); 161 | 162 | /* Check incremental interface works, and final function likewise. */ 163 | static void vector_abc_final(const cf_chash *hash, const void *vfinal_fn, 164 | const void *expect, size_t nexpect) 165 | { 166 | uint8_t digest[CF_MAXHASH]; 167 | 168 | final_fn final = vfinal_fn; 169 | cf_chash_ctx ctx; 170 | hash->init(&ctx); 171 | hash->update(&ctx, "a", 1); 172 | hash->digest(&ctx, digest); 173 | hash->update(&ctx, "b", 1); 174 | hash->digest(&ctx, digest); 175 | hash->update(&ctx, "c", 1); 176 | final(&ctx, digest); 177 | 178 | TEST_CHECK(hash->hashsz == nexpect); 179 | TEST_CHECK(memcmp(expect, digest, nexpect) == 0); 180 | } 181 | 182 | /* Check length-checking vectors work (generated by programs in ../extra_vecs) */ 183 | static inline void vector_length(const cf_chash *h, 184 | size_t max, 185 | const void *expect, size_t nexpect) 186 | { 187 | cf_chash_ctx outer, inner; 188 | uint8_t digest[CF_MAXHASH]; 189 | 190 | h->init(&outer); 191 | 192 | for (size_t n = 0; n < max; n++) 193 | { 194 | h->init(&inner); 195 | 196 | for (size_t i = 0; i < n; i++) 197 | { 198 | uint8_t byte = (uint8_t) n & 0xff; 199 | h->update(&inner, &byte, 1); 200 | } 201 | 202 | h->digest(&inner, digest); 203 | 204 | h->update(&outer, digest, h->hashsz); 205 | } 206 | 207 | h->digest(&outer, digest); 208 | 209 | TEST_CHECK(h->hashsz == nexpect); 210 | TEST_CHECK(memcmp(expect, digest, nexpect) == 0); 211 | } 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /src/drbg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cifra - embedded cryptography library 3 | * Written in 2016 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef DRBG_H 16 | #define DRBG_H 17 | 18 | #include 19 | #include 20 | 21 | #include "chash.h" 22 | #include "hmac.h" 23 | 24 | /** 25 | * Hash_DRBG 26 | * ========= 27 | * This is Hash_DRBG from SP800-90A rev 1, with SHA256 as 28 | * the underlying hash function. 29 | * 30 | * This generator enforces a `reseed_interval` of 2^32-1: 31 | * use :c:func:`cf_hash_drbg_sha256_needs_reseed` to check 32 | * whether you need to reseed before use, and reseed using 33 | * :c:func:`cf_hash_drbg_sha256_reseed`. If you try to use 34 | * the generator when it thinks it needs reseeding, it will 35 | * call `abort`. 36 | * 37 | * Internally it enforces a `max_number_of_bits_per_request` 38 | * of 2^19 bits. It sorts out chunking up multiple requests 39 | * for you though, so feel free to ask for more than 2^16 bytes 40 | * at a time. If you provide additional input when doing that, 41 | * it is added only once, on the first subrequest. 42 | * 43 | * It does not enforce any `max_length` or 44 | * `max_personalization_string_length`. 45 | */ 46 | 47 | /* .. c:type:: cf_hash_drbg_sha256 48 | * Hash_DRBG with SHA256 context. 49 | * 50 | * .. c:member:: cf_hash_drbg_sha256.V 51 | * Current internal state. 52 | * 53 | * .. c:member:: cf_hash_drbg_sha256.C 54 | * Current update offset. 55 | * 56 | * .. c:member:: cf_hash_drbg_sha256.reseed_counter 57 | * Current number of times entropy has been extracted from 58 | * generator. 59 | */ 60 | typedef struct 61 | { 62 | uint8_t V[440/8]; 63 | uint8_t C[440/8]; 64 | uint32_t reseed_counter; 65 | } cf_hash_drbg_sha256; 66 | 67 | /* .. c:function:: $DECL 68 | * Initialises the generator state `ctx`, using the provided `entropy`, 69 | * `nonce` and personalisation string `persn`. 70 | */ 71 | extern void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx, 72 | const void *entropy, size_t nentropy, 73 | const void *nonce, size_t nnonce, 74 | const void *persn, size_t npersn); 75 | 76 | /* .. c:function:: $DECL 77 | * Returns non-zero if the generator needs reseeding. If 78 | * this function returns non-zero, the next :c:func:`cf_hash_drbg_sha256_gen` 79 | * or :c:func:`cf_hash_drbg_sha256_gen_additional` call will call `abort`. 80 | */ 81 | extern uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx); 82 | 83 | /* .. c:function:: $DECL 84 | * Reseeds the generator with the given `entropy` and additional data `addnl`. 85 | */ 86 | extern void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx, 87 | const void *entropy, size_t nentropy, 88 | const void *addnl, size_t naddnl); 89 | 90 | /* .. c:function:: $DECL 91 | * Generates pseudo-random output, writing `nout` bytes at `out`. 92 | * This function aborts if the generator needs seeding. 93 | */ 94 | extern void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx, 95 | void *out, size_t nout); 96 | 97 | /* .. c:function:: $DECL 98 | * Generates pseudo-random output, writing `nout` bytes at `out`. 99 | * At the same time, `addnl` is input to the generator as further 100 | * entropy. 101 | * This function aborts if the generator needs seeding. 102 | */ 103 | extern void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx, 104 | const void *addnl, size_t naddnl, 105 | void *out, size_t nout); 106 | 107 | /** 108 | * HMAC_DRBG 109 | * ========= 110 | * This is HMAC_DRBG from SP800-90a r1 with any hash function. 111 | * 112 | * This generator enforces a `reseed_interval` of 2^32-1: 113 | * use :c:func:`cf_hmac_drbg_needs_reseed` to check whether 114 | * you need to reseed before use, and reseed using 115 | * :c:func:`cf_hmac_drbg_reseed`. If you try to use the 116 | * generator when it thinks it needs reseeding, it will 117 | * call `abort`. 118 | * 119 | * Internally it enforces a `max_number_of_bits_per_request` 120 | * of 2^19 bits. It sorts out chunking up multiple requests 121 | * for you though, so feel free to ask for more than 2^16 bytes 122 | * at a time. If you provide additional input when doing that, 123 | * it is added only once, on the first subrequest. 124 | * 125 | * It does not enforce any `max_length` or 126 | * `max_personalization_string_length`. 127 | */ 128 | 129 | /* .. c:type:: cf_hmac_drbg 130 | * HMAC_DRBG context. 131 | * 132 | * .. c:member:: cf_hmac_drbg.V 133 | * Current internal state. 134 | * 135 | * .. c:member:: cf_hmac_drbg.hmac 136 | * Current HMAC context, with key scheduled in it. 137 | * 138 | * .. c:member:: cf_hmac_drbg.reseed_counter 139 | * Current number of times entropy has been extracted from 140 | * generator. 141 | */ 142 | typedef struct 143 | { 144 | uint8_t V[CF_MAXHASH]; 145 | cf_hmac_ctx hmac; /* pristine context with key scheduled */ 146 | uint32_t reseed_counter; 147 | } cf_hmac_drbg; 148 | 149 | /* .. c:function:: $DECL 150 | * Initialises the generator state `ctx`, using the provided `entropy`, 151 | * `nonce` and personalisation string `persn`. 152 | */ 153 | extern void cf_hmac_drbg_init(cf_hmac_drbg *ctx, 154 | const cf_chash *hash, 155 | const void *entropy, size_t nentropy, 156 | const void *nonce, size_t nnonce, 157 | const void *persn, size_t npersn); 158 | 159 | /* .. c:function:: $DECL 160 | * Returns non-zero if the generator needs reseeding. If 161 | * this function returns non-zero, the next :c:func:`cf_hmac_drbg_gen` 162 | * or :c:func:`cf_hmac_drbg_gen_additional` call will call `abort`. 163 | */ 164 | extern uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx); 165 | 166 | /* .. c:function:: $DECL 167 | * Reseeds the generator with the given `entropy` and additional data 168 | * `addnl`. 169 | */ 170 | extern void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx, 171 | const void *entropy, size_t nentropy, 172 | const void *addnl, size_t naddnl); 173 | 174 | /* .. c:function:: $DECL 175 | * Generates pseudo-random output, writing `nout` bytes at `out`. 176 | * This function aborts if the generator needs seeding. 177 | */ 178 | extern void cf_hmac_drbg_gen(cf_hmac_drbg *ctx, 179 | void *out, size_t nout); 180 | 181 | /* .. c:function:: $DECL 182 | * Generates pseudo-random output, writing `nout` bytes at `out`. 183 | * At the same time, `addnl` is input to the generator as further 184 | * entropy. 185 | * This function aborts if the generator needs seeding. 186 | */ 187 | extern void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx, 188 | const void *addnl, size_t naddnl, 189 | void *out, size_t nout); 190 | 191 | #endif 192 | --------------------------------------------------------------------------------