SHA-256

There is currently a software implementation of SHA-256 for zeptoforth. This implementation runs on all platforms zeptoforth supports, and can be used by multiple tasks simultaneously as long as separate SHA-256 structures are used by each of them.

There is also support for the RP2350’s hardware SHA-256 accelerator. The latter will provide performance benefits in many use cases, but has the disadvantage of that only a single task can have access to the SHA-256 accelerator at a time, so if multiple tasks wish to use it one task will have to wait until the other task completes an SHA-256 hash calculation, which may have performance impacts if the SHA-256 calculation is limited in performance by an external factor such as filesystem or network performance.

Note that a basic limitation of SHA-256 is that the total data size must be smaller than 2^64 bits, i.e. 2^56 bytes. For most practical applications this should not be a problem.

The source code for the software implementation of SHA-256 is in extra/common/sha256.fs. This code is based closely off of https://github.com/amosnier/sha-2 which in turn is closely based off https://en.wikipedia.org/wiki/SHA-2 .

The source code for the support for the RP2350’s hardware SHA-256 accelerator is in extra/rp2350/sha256_accel.fs. This borrows aspects of the same original codebase as the software SHA-256 implementation.

There is a set of SHA-256 tests in test/common/sha256.fs and a set of SHA-256 accelerator tests in test/rp2350/sha256_accel.fs.

sha-256

The sha-256 module comprises the software SHA-256 implementation and contains the following words:

size-of-sha-256-hash

( – bytes )

Size of an SHA-256 hash in bytes

sha-256-size

( – bytes )

Size of SHA-256 structure in bytes

init-sha-256

( hash sha-256 – )

Initialize an SHA-256 streaming calculation.

  • hash: address of hash array, where the result is delivered

  • sha-256: address of an SHA-256 structure

If all the data you are calculating the hash value on is not available in a contiguous buffer in memory, this is where you should start. Instantiate an SHA-256 structure, and invoke this word. Once a SHA-256 hash has been calculated the SHA-256 structure can be initialized again for the next calculation.

write-sha-256

( data len sha-256 – )

Stream more input for an on-going SHA-256 calculation.

  • data: address of data to be added to the calculation

  • len: length of the data to add, in bytes

  • sha-256: address of a previously initialized SHA-256 structure

This word may be invoked an arbitrary number of times between initialization and closing, but the data length is limited by the SHA-256 algorithm: the total number of bits (i.e. the total number of bytes times eight) must be representable by a 64-bit unsigned integer. While that is not a practical limitation, the result is unpredictable if that limit is exceeded.

This word may be invoked on empty data (zero length), although that obviously will not add any data.

close-sha-256

( sha-256 – hash )

Conclude an SHA-256 streaming calculation, making the hash value available.

  • sha-256: address of a previously initialized SHA-256 structure

After this word has been invoked, the result is available in the hash buffer that initially was provided. The address of the hash value is returned for convenience, but you should feel free to drop it; it is simply the address of the first byte of your initially provided hash array.

Invoking this word for a calculation with no data (the writing function has never been invoked, or it only has been invoked with empty data) is legal. It will calculate the SHA-256 value of the empty string.

calc-sha-256

( input len hash – )

The simple SHA-256 calculation word

  • input: address of the data the hash will be calculated on

  • len: length of the input data, in bytes

  • hash: address of hash array, where the result is delivered

If all the data you are calculating the hash value on is available in a contiguous buffer in memory, this is the word you should use.

The length must be correspond to an unsigned 64-bit number of bits (i.e. the length times eight must be less than 2^64).

sha-256-accel

The sha-256-accel module comprises the support for the RP2350’s hardware SHA-256 accelerator and contains the following words:

size-of-sha-256-hash

( – bytes )

Size of an SHA-256 hash in bytes

sha-256-accel-size

( – bytes )

Size of SHA-256 accelerator structure in bytes

init-sha-256-accel

( hash sha-256 – )

Initialize an SHA-256 accelerator streaming calculation.

  • hash: address of hash array, where the result is delivered

  • sha-256: address of an SHA-256 accelerator structure

If all the data you are calculating the hash value on is not available in a contiguous buffer in memory, this is where you should start. Instantiate an SHA-256 accelerator structure, and invoke this word. Once a SHA-256 hash has been calculated the SHA-256 accelerator structure can be initialized again for the next calculation.

This locks the SHA-256 accelerator, and all operations on the SHA-256 accelerator structure up to the generation of a hash must be from the same task as this was called in.

write-sha-256-accel

( data len sha-256 – )

Stream more input for an on-going SHA-256 accelerator calculation.

  • data: address of data to be added to the calculation

  • len: length of the data to add, in bytes

  • sha-256: address of a previously initialized SHA-256 accelerator structure

This word may be invoked an arbitrary number of times between initialization and closing, but the data length is limited by the SHA-256 algorithm: the total number of bits (i.e. the total number of bytes times eight) must be representable by a 64-bit unsigned integer. While that is not a practical limitation, the result is unpredictable if that limit is exceeded.

This word may be invoked on empty data (zero length), although that obviously will not add any data.

This must be called from the same task in which the corresponding call to init-sha-256-accel was carried out.

close-sha-256-accel

( sha-256 – hash )

Conclude an SHA-256 accelerator streaming calculation, making the hash value available.

  • sha-256: address of a previously initialized SHA-256 accelerator structure

After this word has been invoked, the result is available in the hash buffer that initially was provided. The address of the hash value is returned for convenience, but you should feel free to drop it; it is simply the address of the first byte of your initially provided hash array.

Invoking this word for a calculation with no data (the writing function has never been invoked, or it only has been invoked with empty data) is legal. It will calculate the SHA-256 value of the empty string.

This must be called from the same task in which the corresponding call to init-sha-256-accel was carried out.

calc-sha-256-accel

( input len hash – )

The simple SHA-256 accelerator calculation word

  • input: address of the data the hash will be calculated on

  • len: length of the input data, in bytes

  • hash: address of hash array, where the result is delivered

If all the data you are calculating the hash value on is available in a contiguous buffer in memory, this is the word you should use.

The length must be correspond to an unsigned 64-bit number of bits (i.e. the length times eight must be less than 2^64).

This will lock the SHA-256 accelerator for the duration of the calculation.