From 192fc5f1ef433d1153bc47afa6401eb14cfbf32c Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Sat, 5 Nov 2016 15:26:28 +0100 Subject: [PATCH] trezor.crypto: add sha1, regenerate mocks --- extmod/modtrezorcrypto/modtrezorcrypto-sha1.h | 90 +++++++++++++++++++ extmod/modtrezorcrypto/modtrezorcrypto.c | 2 + mocks/trezor/crypto/hashlib.py | 23 +++-- mocks/trezor/crypto/hashlib/Blake2s.py | 12 +++ mocks/trezor/crypto/hashlib/Sha1.py | 12 +++ src/tests/test_crypto_sha1.py | 56 ++++++++++++ src/trezor/crypto/hashlib.py | 1 + vendor/trezor-crypto | 2 +- 8 files changed, 191 insertions(+), 7 deletions(-) create mode 100644 extmod/modtrezorcrypto/modtrezorcrypto-sha1.h create mode 100644 mocks/trezor/crypto/hashlib/Blake2s.py create mode 100644 mocks/trezor/crypto/hashlib/Sha1.py create mode 100644 src/tests/test_crypto_sha1.py diff --git a/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h b/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h new file mode 100644 index 000000000..a462d5921 --- /dev/null +++ b/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) Pavol Rusnak, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + +#include "py/objstr.h" + +#include "trezor-crypto/sha2.h" + +#define HASH_SHA1_BLOCK_SIZE SHA1_BLOCK_LENGTH +#define HASH_SHA1_DIGEST_SIZE SHA1_DIGEST_LENGTH + +typedef struct _mp_obj_Sha1_t { + mp_obj_base_t base; + SHA1_CTX ctx; +} mp_obj_Sha1_t; + +STATIC mp_obj_t mod_TrezorCrypto_Sha1_update(mp_obj_t self, mp_obj_t data); + +/// def trezor.crypto.hashlib.sha1(data: bytes=None) -> Sha1: +/// ''' +/// Creates a hash context object. +/// ''' +STATIC mp_obj_t mod_TrezorCrypto_Sha1_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, 0, 1, false); + mp_obj_Sha1_t *o = m_new_obj(mp_obj_Sha1_t); + o->base.type = type; + sha1_Init(&(o->ctx)); + // constructor called with bytes/str as first parameter + if (n_args == 1) { + mod_TrezorCrypto_Sha1_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); +} + +/// def trezor.crypto.hashlib.Sha1.update(self, data: bytes) -> None: +/// ''' +/// Update the hash context with hashed data. +/// ''' +STATIC mp_obj_t mod_TrezorCrypto_Sha1_update(mp_obj_t self, mp_obj_t data) { + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha1_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Sha1_update_obj, mod_TrezorCrypto_Sha1_update); + +/// def trezor.crypto.hashlib.Sha1.digest(self) -> bytes: +/// ''' +/// Returns the digest of hashed data. +/// ''' +STATIC mp_obj_t mod_TrezorCrypto_Sha1_digest(mp_obj_t self) { + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + vstr_t vstr; + vstr_init_len(&vstr, HASH_SHA1_DIGEST_SIZE); + SHA1_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA1_CTX)); + sha1_Final(&ctx, (uint8_t *)vstr.buf); + memset(&ctx, 0, sizeof(SHA1_CTX)); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha1_digest_obj, mod_TrezorCrypto_Sha1_digest); + +STATIC mp_obj_t mod_TrezorCrypto_Sha1___del__(mp_obj_t self) { + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + memset(&(o->ctx), 0, sizeof(SHA1_CTX)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha1___del___obj, mod_TrezorCrypto_Sha1___del__); + +STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Sha1_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_TrezorCrypto_Sha1_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_TrezorCrypto_Sha1_digest_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_TrezorCrypto_Sha1___del___obj) }, + { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA1_BLOCK_SIZE) }, + { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA1_DIGEST_SIZE) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_TrezorCrypto_Sha1_locals_dict, mod_TrezorCrypto_Sha1_locals_dict_table); + +STATIC const mp_obj_type_t mod_TrezorCrypto_Sha1_type = { + { &mp_type_type }, + .name = MP_QSTR_Sha1, + .make_new = mod_TrezorCrypto_Sha1_make_new, + .locals_dict = (void*)&mod_TrezorCrypto_Sha1_locals_dict, +}; diff --git a/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/modtrezorcrypto/modtrezorcrypto.c index 5187cbebe..e8a26978a 100644 --- a/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -26,6 +26,7 @@ #include "modtrezorcrypto-ripemd160.h" #include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-secp256k1.h" +#include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha256.h" #include "modtrezorcrypto-sha512.h" #include "modtrezorcrypto-sha3-256.h" @@ -45,6 +46,7 @@ STATIC const mp_rom_map_elem_t mp_module_TrezorCrypto_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Random), MP_ROM_PTR(&mod_TrezorCrypto_Random_type) }, { MP_ROM_QSTR(MP_QSTR_Ripemd160), MP_ROM_PTR(&mod_TrezorCrypto_Ripemd160_type) }, { MP_ROM_QSTR(MP_QSTR_Secp256k1), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_type) }, + { MP_ROM_QSTR(MP_QSTR_Sha1), MP_ROM_PTR(&mod_TrezorCrypto_Sha1_type) }, { MP_ROM_QSTR(MP_QSTR_Sha256), MP_ROM_PTR(&mod_TrezorCrypto_Sha256_type) }, { MP_ROM_QSTR(MP_QSTR_Sha512), MP_ROM_PTR(&mod_TrezorCrypto_Sha512_type) }, { MP_ROM_QSTR(MP_QSTR_Sha3_256), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256_type) }, diff --git a/mocks/trezor/crypto/hashlib.py b/mocks/trezor/crypto/hashlib.py index 97fe9c0ce..11a6bc979 100644 --- a/mocks/trezor/crypto/hashlib.py +++ b/mocks/trezor/crypto/hashlib.py @@ -1,3 +1,14 @@ +# ../extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h +def blake2s(data: bytes=None, key: bytes=None) -> Blake2s: + ''' + Creates a hash context object. + ''' + +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha1.h +def sha1(data: bytes=None) -> Sha1: + ''' + Creates a hash context object. + ''' # ../extmod/modtrezorcrypto/modtrezorcrypto-ripemd160.h def ripemd160(data: bytes=None) -> Ripemd160: @@ -11,20 +22,20 @@ def sha256(data: bytes=None) -> Sha256: Creates a hash context object. ''' -# ../extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h -def sha3_256(data: bytes=None) -> Sha3_256: +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha512.h +def sha512(data: bytes=None) -> Sha512: ''' Creates a hash context object. ''' -# ../extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h -def sha3_512(data: bytes=None) -> Sha3_512: +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h +def sha3_256(data: bytes=None) -> Sha3_256: ''' Creates a hash context object. ''' -# ../extmod/modtrezorcrypto/modtrezorcrypto-sha512.h -def sha512(data: bytes=None) -> Sha512: +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h +def sha3_512(data: bytes=None) -> Sha3_512: ''' Creates a hash context object. ''' diff --git a/mocks/trezor/crypto/hashlib/Blake2s.py b/mocks/trezor/crypto/hashlib/Blake2s.py new file mode 100644 index 000000000..61ad7bdb2 --- /dev/null +++ b/mocks/trezor/crypto/hashlib/Blake2s.py @@ -0,0 +1,12 @@ + +# ../extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h +def update(self, data: bytes) -> None: + ''' + Update the hash context with hashed data. + ''' + +# ../extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h +def digest(self) -> bytes: + ''' + Returns the digest of hashed data. + ''' diff --git a/mocks/trezor/crypto/hashlib/Sha1.py b/mocks/trezor/crypto/hashlib/Sha1.py new file mode 100644 index 000000000..a20e9043b --- /dev/null +++ b/mocks/trezor/crypto/hashlib/Sha1.py @@ -0,0 +1,12 @@ + +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha1.h +def update(self, data: bytes) -> None: + ''' + Update the hash context with hashed data. + ''' + +# ../extmod/modtrezorcrypto/modtrezorcrypto-sha1.h +def digest(self) -> bytes: + ''' + Returns the digest of hashed data. + ''' diff --git a/src/tests/test_crypto_sha1.py b/src/tests/test_crypto_sha1.py new file mode 100644 index 000000000..38a2bafe3 --- /dev/null +++ b/src/tests/test_crypto_sha1.py @@ -0,0 +1,56 @@ +import sys +sys.path.append('..') +sys.path.append('../lib') +import unittest +from ubinascii import unhexlify + +from trezor.crypto import hashlib + +class TestCryptoSha1(unittest.TestCase): + + # vectors from http://www.di-mgt.com.au/sha_testvectors.html + + def test_digest(self): + self.assertEqual(hashlib.sha1(b'').digest(), unhexlify('da39a3ee5e6b4b0d3255bfef95601890afd80709')) + self.assertEqual(hashlib.sha1(b'abc').digest(), unhexlify('a9993e364706816aba3e25717850c26c9cd0d89d')) + self.assertEqual(hashlib.sha1(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq').digest(), unhexlify('84983e441c3bd26ebaae4aa1f95129e5e54670f1')) + self.assertEqual(hashlib.sha1(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu').digest(), unhexlify('a49b2446a02c645bf419f995b67091253a04a259')) + + def test_update(self): + x = hashlib.sha1() + self.assertEqual(x.digest(), unhexlify('da39a3ee5e6b4b0d3255bfef95601890afd80709')) + + x = hashlib.sha1() + x.update(b'abc') + self.assertEqual(x.digest(), unhexlify('a9993e364706816aba3e25717850c26c9cd0d89d')) + + x = hashlib.sha1() + x.update(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq') + self.assertEqual(x.digest(), unhexlify('84983e441c3bd26ebaae4aa1f95129e5e54670f1')) + + x = hashlib.sha1() + x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu') + self.assertEqual(x.digest(), unhexlify('a49b2446a02c645bf419f995b67091253a04a259')) + + x = hashlib.sha1() + for i in range(1000000): + x.update(b'a') + self.assertEqual(x.digest(), unhexlify('34aa973cd4c4daa4f61eeb2bdbad27316534016f')) + + ''' + x = hashlib.sha1() + for i in range(16777216): + x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno') + self.assertEqual(x.digest(), unhexlify('7789f0c9ef7bfc40d93311143dfbe69e2017f592')) + ''' + + def test_digest_multi(self): + x = hashlib.sha1() + d0 = x.digest() + d1 = x.digest() + d2 = x.digest() + self.assertEqual(d0, d1) + self.assertEqual(d0, d2) + +if __name__ == '__main__': + unittest.main() diff --git a/src/trezor/crypto/hashlib.py b/src/trezor/crypto/hashlib.py index 41ef5ddd0..3438c5a4b 100644 --- a/src/trezor/crypto/hashlib.py +++ b/src/trezor/crypto/hashlib.py @@ -1,5 +1,6 @@ from TrezorCrypto import Blake2s as blake2s from TrezorCrypto import Ripemd160 as ripemd160 +from TrezorCrypto import Sha1 as sha1 from TrezorCrypto import Sha256 as sha256 from TrezorCrypto import Sha512 as sha512 from TrezorCrypto import Sha3_256 as sha3_256 diff --git a/vendor/trezor-crypto b/vendor/trezor-crypto index a91e00563..19efbeef8 160000 --- a/vendor/trezor-crypto +++ b/vendor/trezor-crypto @@ -1 +1 @@ -Subproject commit a91e005633fa6950a95beae58f49561a29cc0053 +Subproject commit 19efbeef8dbb1595a1a88850f7da3bc8c7fb335f