+-Discord Shoutbox

Alternatively, join us on Discord directly.
You can help CodeWalrus stay online by donating here.

HASHLIB - Cryptography Library for the CE

Started by ACagliano, July 15, 2021, 02:47:58 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.


July 15, 2021, 02:47:58 PM Last Edit: July 17, 2021, 02:56:38 AM by ACagliano
For the past few months, I've been working with beckadamtheinventor and others on HASHLIB, a library that provides d*mn-near industry standard encryption for the TI-84+ CE. It is a Libload Library, meaning it works the same way as the other libraries distributed with the toolchain (GRAPHX, FILEIOC, etc). Simply send HASHLIB.8xv to your calculator, move the .lib and .h file to your $CEDEV/lib/libload and $CEDEV/include directories respectively, then `#include <hashlib.h>` in your C project source. At this point you can use any of the functions in hashlib in your code.

HASHLIB provides the following crypto standards:

(1) SHA-256 Hash
A rather fast implementation of the SHA-256 crypto hash. First written in C, myself and beck endeavored to rewrite it in EZ80 Assembly because the C version was quite slow. I started things off with a code of the Init, Update, and Final functions and a skeleton of the transform function. Beck "corrected" any mistakes I made due to my Asm knowledge being (1) rusty, and (2) from Z80 Asm, as well as optimized all of the functions, and wrote much of the transform math routines. The current SHA-256 implementation sports a speed increase of 9x over the C version, and can fully hash GRAPHX, the largest of the toolchain libraries, in ~1.5 seconds.

(2) An Entropy-Based Secure Random Number Generator
This PRNG, unlike the toolchain's default is not deterministic in nature. It works by polling every bit in the CE's unmapped memory, searching for a floating bit with the least bias, upon which it sets its state internally to read from the address containing that bit. An add entropy function can be called by the user, but is also called automatically every time a random number is generated. This function reads from the entropy source to a reserved pool 192 bytes large. Because the maximum bias accepted by the entropy source selection function is 75/25, this gives us an entropy of .811 bit per byte, which multiplies out to ~150 bits of entropy for the entire pool. Bear in mind that is the worst case entropy possible--the entropy source selected will likely be higher. This entropy goes into generating a 32-bit random number; the pool is hashed using SHA-256 and then xored cyclically into the random number. The PRNG passes all Dieharder tests when run on 16KB of data as well as 1MB of data.

(3) Advanced Encryption Standard, CBC Mode
As the above implies, HASHLIB provides routines for encrypting and decrypting data using the CBC mode AES block cipher. This implementation has support for 128, 192, and 256 bit keys. Additionally, the CBC-MAC protocol is also provided, which you can pass data to and generate a message authentication code one block size in length. The library provides a macro that takes a plaintext, padding scheme, an output buffer, and two AES key schedules (one for encryption, one for MAC), as well as an IV. It encrypts the plaintext using the IV and encryption key schedule (padding appropriately), then runs the CBC-MAC algorithm on the encryption output and the IV, using the MAC key schedule (the MAC variant of the CBC cipher does not take an IV, but rather initializes it to a constant value causing it to act more like a counter than a nonce), appending the output of that MAC function to the ciphertext, providing an authenticated encryption scheme derived from IPsec.

(4) RSA, Encryption Only
A WIP; This library will also provide support for public key encryption over RSA keys of a modulus length up to 2048 bits. It will depend on a BIGINT lib by beckadamtheinventor currently a WIP as well (which is why RSA is still not added). Because generating two random coprime prime numbers of the required size on a CE would likely take a very long time, I decided to implement the encryption part only. Use this implementation in a server-centric setup where a server generates an RSA keypair, sends the public key to your calculator, and then the calculator encrypts a shared secret for AES, sends that to the server, and then the two communicate using AES.

(5) Padding Schemes (and Strip Padding)
HASHLIB provides functions to implement the ISO, PKCS7, and ANSIX928 padding schemes for AES as well as OAEP for RSA. For those who don't know, the ISO scheme pads with the byte 0x80 and then the bytes 0x00 until the end of the block. The PKCS7 scheme pads with the size of the padding. The ANSIX scheme pads with randomness. For OAEP, the scheme is implemented as indicated by the standard (a Feistel network where the message is padded with zeros to the modulus length minus 16, a 16-byte salt is generated, hashed, and xored with the message. The encoded message is then hashed and xored with the salt, and the encoded message and encoded salt are the OAEP-encoded plaintext). However, rather than an expandable hashing oracle, SHA-256 is applied cyclically to the message. This was done predominantly to save space in the library by using an existing hash rather than adding a new one specifically for this purpose.

The "Strip Padding" functions all properly strip the padding, returning the unpadded plaintext into a provided buffer as well as the size of the unpadded data into a return value. The only padding scheme it cannot decipher is ANSIX; if you are using this padding mode, you will have to know the expected plaintext size.

Other Functions Provided:
(a) hashlib_CompareDigest(): buffer comparison function that is resistant to timing attacks (written by jacobly in ez80 Assembly)
(b) Base64 Encode/Decode: Added these planning to implement bcrypt, but when Blowfish was replaced with AES, decided to just leave them in.
(c) Macros to return the padded size of an AES/RSA plaintext, useful for allocating a buffer large enough.
(d) Context erase function. When you are done with an SHA, AES, or RSA context, you can pass it to this function to write zeroes to it, erasing all traces of cryptographic state.

Special thanks to:
(1) beckadamtheinventor: Converted many of my C routines into EZ80 Assembly for speed
(2) Zeroko: Provided useful information on extracting entropy from the CE
(3) jacobly: Rewriting hashlib_CompareDigest() in EZ80 Assembly
(4) B-Con crypto algorithms, which was my source for the base of the AES and SHA implementations.

Project Page: http://cagstech.com/tistuff/hashlib/
Github: https://github.com/acagliano/hashlib
  • Calculators owned: TI-84+ CE


The Time Has Come!! for another progress update.

HASHLIB v6 is out on Github: https://github.com/acagliano/hashlib/releases/latest

Here's What's New:
(1) MGF1 hashing function is added. It uses SHA-256 and hashes a given length of data as well as a 4-byte counter.
(2) OAEP now uses MGF1 (as is standard) instead of cyclic SHA-256.
(3) SPRNG now minimizes entropy loss due to correlation (thanks, Zeroko!) and runs ~1.5x faster for generating large pools of random data. The entropy pool is reduced from 192 bytes to 119 bytes, but each time we update a byte in the pool from the entropy source, it is a composite of 7 distinct reads xor'd together.
(4) SPRNGRandom() rewritten in assembly. Thanks to jacobly for optimization and some small code corrections.
(5) SPRNG now uses FastMem for its SHA memory and entropy pool to accelerate even faster.
(6) AES ECB-mode single block encrypt/decrypt functions exposed to let skilled users construct their own cipher modes
Still waiting on vint powmod to be fixed in the bigintce library, and then RSA will be added for v7.
  • Calculators owned: TI-84+ CE

Powered by EzPortal