trezor.crypto: implement chacha20poly1305 aka rfc7539

pull/25/head
Pavol Rusnak 6 years ago
parent 5a304d8e25
commit fa95f0a037
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

@ -45,6 +45,10 @@ SOURCE_MOD += [
'vendor/trezor-crypto/blake2s.c',
'vendor/trezor-crypto/curves.c',
'vendor/trezor-crypto/ecdsa.c',
'vendor/trezor-crypto/chacha20poly1305/chacha20poly1305.c',
'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c',
'vendor/trezor-crypto/chacha20poly1305/poly1305-donna.c',
'vendor/trezor-crypto/chacha20poly1305/rfc7539.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c',

@ -46,6 +46,10 @@ SOURCE_MOD += [
'vendor/trezor-crypto/blake2s.c',
'vendor/trezor-crypto/curves.c',
'vendor/trezor-crypto/ecdsa.c',
'vendor/trezor-crypto/chacha20poly1305/chacha20poly1305.c',
'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c',
'vendor/trezor-crypto/chacha20poly1305/poly1305-donna.c',
'vendor/trezor-crypto/chacha20poly1305/rfc7539.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c',
@ -107,10 +111,7 @@ SOURCE_MICROPYTHON = [
'vendor/micropython/extmod/modubinascii.c',
'vendor/micropython/extmod/moductypes.c',
'vendor/micropython/extmod/moduheapq.c',
'vendor/micropython/extmod/modujson.c',
'vendor/micropython/extmod/modure.c',
'vendor/micropython/extmod/modutimeq.c',
'vendor/micropython/extmod/moduzlib.c',
'vendor/micropython/extmod/utime_mphal.c',
'vendor/micropython/lib/mp-readline/readline.c',
'vendor/micropython/lib/timeutils/timeutils.c',
@ -224,9 +225,7 @@ SOURCE_UNIX = [
'vendor/micropython/ports/unix/mpthreadport.c',
'vendor/micropython/ports/unix/input.c',
'vendor/micropython/ports/unix/file.c',
'vendor/micropython/ports/unix/modos.c',
'vendor/micropython/ports/unix/modtime.c',
'vendor/micropython/ports/unix/moduselect.c',
'vendor/micropython/ports/unix/alloc.c',
'embed/unix/common.c',
'embed/unix/flash.c',

@ -0,0 +1,130 @@
/*
* Copyright (c) Pavol Rusnak, SatoshiLabs
*
* Licensed under TREZOR License
* see LICENSE file for details
*/
#include "py/objstr.h"
#include "chacha20poly1305/rfc7539.h"
/// class ChaCha20Poly1305:
/// '''
/// ChaCha20Poly1305 context.
/// '''
typedef struct _mp_obj_ChaCha20Poly1305_t {
mp_obj_base_t base;
chacha20poly1305_ctx ctx;
int64_t alen, plen;
} mp_obj_ChaCha20Poly1305_t;
/// def __init__(self, key: bytes, nonce: bytes) -> None:
/// '''
/// Initialize the ChaCha20 + Poly1305 context for encryption or decryption
/// using a 32 byte key and 12 byte nonce as in the RFC 7539 style.
/// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, 2, false);
mp_obj_ChaCha20Poly1305_t *o = m_new_obj(mp_obj_ChaCha20Poly1305_t);
o->base.type = type;
mp_buffer_info_t key, nonce;
mp_get_buffer_raise(args[0], &key, MP_BUFFER_READ);
mp_get_buffer_raise(args[1], &nonce, MP_BUFFER_READ);
if (key.len != 32) {
mp_raise_ValueError("Invalid length of key");
}
if (nonce.len != 12) {
mp_raise_ValueError("Invalid length of nonce");
}
rfc7539_init(&(o->ctx), key.buf, nonce.buf);
o->alen = 0;
o->plen = 0;
return MP_OBJ_FROM_PTR(o);
}
/// def encrypt(self, data: bytes) -> bytes:
/// '''
/// Encrypt data (length of data must be divisible by 64 except for the final value).
/// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_encrypt(mp_obj_t self, mp_obj_t data) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
vstr_t vstr;
vstr_init_len(&vstr, in.len);
chacha20poly1305_encrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len);
o->plen += in.len;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj, mod_trezorcrypto_ChaCha20Poly1305_encrypt);
/// def decrypt(self, data: bytes) -> bytes:
/// '''
/// Decrypt data (length of data must be divisible by 64 except for the final value).
/// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_decrypt(mp_obj_t self, mp_obj_t data) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
vstr_t vstr;
vstr_init_len(&vstr, in.len);
chacha20poly1305_decrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len);
o->plen += in.len;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj, mod_trezorcrypto_ChaCha20Poly1305_decrypt);
/// def auth(self, data: bytes) -> None:
/// '''
/// Include authenticated data in the Poly1305 MAC using the RFC 7539
/// style with 16 byte padding. This must only be called once and prior
/// to encryption or decryption.
/// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_auth(mp_obj_t self, mp_obj_t data) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
rfc7539_auth(&(o->ctx), in.buf, in.len);
o->alen += in.len;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_auth_obj, mod_trezorcrypto_ChaCha20Poly1305_auth);
/// def finish(self) -> bytes:
/// '''
/// Compute RFC 7539-style Poly1305 MAC.
/// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_finish(mp_obj_t self) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
vstr_t vstr;
vstr_init_len(&vstr, 16);
rfc7539_finish(&(o->ctx), o->alen, o->plen, (uint8_t *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305_finish_obj, mod_trezorcrypto_ChaCha20Poly1305_finish);
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305___del__(mp_obj_t self) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
memset(&(o->ctx), 0, sizeof(chacha20poly1305_ctx));
o->alen = 0;
o->plen = 0;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305___del___obj, mod_trezorcrypto_ChaCha20Poly1305___del__);
STATIC const mp_rom_map_elem_t mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj) },
{ MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj) },
{ MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_auth_obj) },
{ MP_ROM_QSTR(MP_QSTR_finish), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_finish_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305___del___obj) },
};
STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_ChaCha20Poly1305_locals_dict, mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table);
STATIC const mp_obj_type_t mod_trezorcrypto_ChaCha20Poly1305_type = {
{ &mp_type_type },
.name = MP_QSTR_ChaCha20Poly1305,
.make_new = mod_trezorcrypto_ChaCha20Poly1305_make_new,
.locals_dict = (void*)&mod_trezorcrypto_ChaCha20Poly1305_locals_dict,
};

@ -19,6 +19,7 @@
#include "modtrezorcrypto-blake256.h"
#include "modtrezorcrypto-blake2b.h"
#include "modtrezorcrypto-blake2s.h"
#include "modtrezorcrypto-chacha20poly1305.h"
#include "modtrezorcrypto-crc.h"
#include "modtrezorcrypto-curve25519.h"
#include "modtrezorcrypto-ed25519.h"
@ -42,6 +43,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_blake256), MP_ROM_PTR(&mod_trezorcrypto_Blake256_type) },
{ MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type) },
{ MP_ROM_QSTR(MP_QSTR_blake2s), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_type) },
{ MP_ROM_QSTR(MP_QSTR_chacha20poly1305), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_type) },
{ MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module) },
{ MP_ROM_QSTR(MP_QSTR_curve25519), MP_ROM_PTR(&mod_trezorcrypto_curve25519_module) },
{ MP_ROM_QSTR(MP_QSTR_ed25519), MP_ROM_PTR(&mod_trezorcrypto_ed25519_module) },

@ -1,7 +1,7 @@
from trezorcrypto import bip32
from trezorcrypto import bip39
from trezorcrypto import chacha20poly1305
from trezorcrypto import crc
from trezorcrypto import pbkdf2
from trezorcrypto import random
from trezorcrypto import rfc6979
from trezorcrypto import ssss

@ -0,0 +1,61 @@
from common import *
from trezor.crypto import chacha20poly1305
class TestCryptoChaCha20Poly1305(unittest.TestCase):
vectors = [
# from https://github.com/wg/c20p1305/blob/master/rfc7539_test.c
(
'4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e',
'50515253c0c1c2c3c4c5c6c7',
'808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
'070000004041424344454647',
'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116',
'1ae10b594f09e26a7e902ecbd0600691',
),
# from https://tools.ietf.org/html/rfc7539#appendix-A.5
(
'496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d',
'f33388860000000000004e91',
'1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0',
'000000000102030405060708',
'64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b',
'eead9d67890cbb22392336fea1851f38',
),
]
def test_chacha20_encrypt(self):
for plaintext, _, key, nonce, ciphertext, _ in self.vectors:
ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
out = ctx.encrypt(unhexlify(plaintext))
self.assertEqual(out, unhexlify(ciphertext))
def test_chacha20_decrypt(self):
for plaintext, _, key, nonce, ciphertext, _ in self.vectors:
ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
out = ctx.encrypt(unhexlify(ciphertext))
self.assertEqual(out, unhexlify(plaintext))
def test_chacha20poly1305_encrypt_mac(self):
for plaintext, aad, key, nonce, ciphertext, tag in self.vectors:
ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
ctx.auth(unhexlify(aad))
out = ctx.encrypt(unhexlify(plaintext))
self.assertEqual(out, unhexlify(ciphertext))
out = ctx.finish()
self.assertEqual(out, unhexlify(tag))
def test_chacha20poly1305_decrypt_mac(self):
for plaintext, aad, key, nonce, ciphertext, tag in self.vectors:
ctx = chacha20poly1305(unhexlify(key), unhexlify(nonce))
ctx.auth(unhexlify(aad))
out = ctx.decrypt(unhexlify(ciphertext))
self.assertEqual(out, unhexlify(plaintext))
out = ctx.finish()
self.assertEqual(out, unhexlify(tag))
if __name__ == '__main__':
unittest.main()
Loading…
Cancel
Save