diff options
author | Michael Brown | 2015-04-12 15:50:18 +0200 |
---|---|---|
committer | Michael Brown | 2015-04-12 18:01:10 +0200 |
commit | 4dbc44348ca9011465c3bce38757173c059309ec (patch) | |
tree | c5f0790a71bc74fe3083a18e164416b0ecf3ed4b | |
parent | [test] Simplify digest algorithm self-tests (diff) | |
download | ipxe-4dbc44348ca9011465c3bce38757173c059309ec.tar.gz ipxe-4dbc44348ca9011465c3bce38757173c059309ec.tar.xz ipxe-4dbc44348ca9011465c3bce38757173c059309ec.zip |
[crypto] Add SHA-224 algorithm
SHA-224 is almost identical to SHA-256, with differing initial hash
values and a truncated output length.
This implementation has been verified using the NIST SHA-224 test
vectors.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/crypto/sha224.c | 82 | ||||
-rw-r--r-- | src/crypto/sha256.c | 49 | ||||
-rw-r--r-- | src/include/ipxe/asn1.h | 7 | ||||
-rw-r--r-- | src/include/ipxe/sha256.h | 12 | ||||
-rw-r--r-- | src/tests/sha256_test.c | 33 |
5 files changed, 167 insertions, 16 deletions
diff --git a/src/crypto/sha224.c b/src/crypto/sha224.c new file mode 100644 index 00000000..be25f24e --- /dev/null +++ b/src/crypto/sha224.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * SHA-224 algorithm + * + */ + +#include <stdint.h> +#include <byteswap.h> +#include <ipxe/crypto.h> +#include <ipxe/asn1.h> +#include <ipxe/sha256.h> + +/** SHA-224 initial digest values */ +static const struct sha256_digest sha224_init_digest = { + .h = { + cpu_to_be32 ( 0xc1059ed8 ), + cpu_to_be32 ( 0x367cd507 ), + cpu_to_be32 ( 0x3070dd17 ), + cpu_to_be32 ( 0xf70e5939 ), + cpu_to_be32 ( 0xffc00b31 ), + cpu_to_be32 ( 0x68581511 ), + cpu_to_be32 ( 0x64f98fa7 ), + cpu_to_be32 ( 0xbefa4fa4 ), + }, +}; + +/** + * Initialise SHA-224 algorithm + * + * @v ctx SHA-224 context + */ +static void sha224_init ( void *ctx ) { + struct sha256_context *context = ctx; + + sha256_family_init ( context, &sha224_init_digest, SHA224_DIGEST_SIZE ); +} + +/** SHA-224 algorithm */ +struct digest_algorithm sha224_algorithm = { + .name = "sha224", + .ctxsize = sizeof ( struct sha256_context ), + .blocksize = sizeof ( union sha256_block ), + .digestsize = SHA224_DIGEST_SIZE, + .init = sha224_init, + .update = sha256_update, + .final = sha256_final, +}; + +/** "sha224" object identifier */ +static uint8_t oid_sha224[] = { ASN1_OID_SHA224 }; + +/** "sha224" OID-identified algorithm */ +struct asn1_algorithm oid_sha224_algorithm __asn1_algorithm = { + .name = "sha224", + .digest = &sha224_algorithm, + .oid = ASN1_OID_CURSOR ( oid_sha224 ), +}; diff --git a/src/crypto/sha256.c b/src/crypto/sha256.c index 3a560560..695ae70c 100644 --- a/src/crypto/sha256.c +++ b/src/crypto/sha256.c @@ -69,6 +69,37 @@ static const uint32_t k[64] = { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; +/** SHA-256 initial digest values */ +static const struct sha256_digest sha256_init_digest = { + .h = { + cpu_to_be32 ( 0x6a09e667 ), + cpu_to_be32 ( 0xbb67ae85 ), + cpu_to_be32 ( 0x3c6ef372 ), + cpu_to_be32 ( 0xa54ff53a ), + cpu_to_be32 ( 0x510e527f ), + cpu_to_be32 ( 0x9b05688c ), + cpu_to_be32 ( 0x1f83d9ab ), + cpu_to_be32 ( 0x5be0cd19 ), + }, +}; + +/** + * Initialise SHA-256 family algorithm + * + * @v context SHA-256 context + * @v init Initial digest values + * @v digestsize Digest size + */ +void sha256_family_init ( struct sha256_context *context, + const struct sha256_digest *init, + size_t digestsize ) { + + context->len = 0; + context->digestsize = digestsize; + memcpy ( &context->ddd.dd.digest, init, + sizeof ( context->ddd.dd.digest ) ); +} + /** * Initialise SHA-256 algorithm * @@ -77,15 +108,8 @@ static const uint32_t k[64] = { static void sha256_init ( void *ctx ) { struct sha256_context *context = ctx; - context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x6a09e667 ); - context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xbb67ae85 ); - context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x3c6ef372 ); - context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0xa54ff53a ); - context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0x510e527f ); - context->ddd.dd.digest.h[5] = cpu_to_be32 ( 0x9b05688c ); - context->ddd.dd.digest.h[6] = cpu_to_be32 ( 0x1f83d9ab ); - context->ddd.dd.digest.h[7] = cpu_to_be32 ( 0x5be0cd19 ); - context->len = 0; + sha256_family_init ( context, &sha256_init_digest, + sizeof ( struct sha256_digest ) ); } /** @@ -190,7 +214,7 @@ static void sha256_digest ( struct sha256_context *context ) { * @v data Data * @v len Length of data */ -static void sha256_update ( void *ctx, const void *data, size_t len ) { +void sha256_update ( void *ctx, const void *data, size_t len ) { struct sha256_context *context = ctx; const uint8_t *byte = data; size_t offset; @@ -213,7 +237,7 @@ static void sha256_update ( void *ctx, const void *data, size_t len ) { * @v ctx SHA-256 context * @v out Output buffer */ -static void sha256_final ( void *ctx, void *out ) { +void sha256_final ( void *ctx, void *out ) { struct sha256_context *context = ctx; uint64_t len_bits; uint8_t pad; @@ -234,8 +258,7 @@ static void sha256_final ( void *ctx, void *out ) { assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); /* Copy out final digest */ - memcpy ( out, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); + memcpy ( out, &context->ddd.dd.digest, context->digestsize ); } /** SHA-256 algorithm */ diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 3302c805..4e8605fe 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -160,6 +160,13 @@ struct asn1_builder_header { ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \ ASN1_OID_SINGLE ( 2 ), ASN1_OID_SINGLE ( 1 ) +/** ASN.1 OID for id-sha224 (2.16.840.1.101.3.4.2.4) */ +#define ASN1_OID_SHA224 \ + ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \ + ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \ + ASN1_OID_SINGLE ( 2 ), ASN1_OID_SINGLE ( 4 ) + /** ASN.1 OID for commonName (2.5.4.3) */ #define ASN1_OID_COMMON_NAME \ ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 4 ), \ diff --git a/src/include/ipxe/sha256.h b/src/include/ipxe/sha256.h index 1e4dcece..811279a6 100644 --- a/src/include/ipxe/sha256.h +++ b/src/include/ipxe/sha256.h @@ -58,6 +58,8 @@ union sha256_digest_data_dwords { struct sha256_context { /** Amount of accumulated data */ size_t len; + /** Digest size */ + size_t digestsize; /** Digest and accumulated data */ union sha256_digest_data_dwords ddd; } __attribute__ (( packed )); @@ -68,6 +70,16 @@ struct sha256_context { /** SHA-256 digest size */ #define SHA256_DIGEST_SIZE sizeof ( struct sha256_digest ) +/** SHA-224 digest size */ +#define SHA224_DIGEST_SIZE ( SHA256_DIGEST_SIZE * 224 / 256 ) + +extern void sha256_family_init ( struct sha256_context *context, + const struct sha256_digest *init, + size_t digestsize ); +extern void sha256_update ( void *ctx, const void *data, size_t len ); +extern void sha256_final ( void *ctx, void *out ); + extern struct digest_algorithm sha256_algorithm; +extern struct digest_algorithm sha224_algorithm; #endif /* _IPXE_SHA256_H */ diff --git a/src/tests/sha256_test.c b/src/tests/sha256_test.c index 80756466..3b4c423f 100644 --- a/src/tests/sha256_test.c +++ b/src/tests/sha256_test.c @@ -25,11 +25,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * - * SHA-256 tests + * SHA-256 family tests * * NIST test vectors are taken from * * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf * */ @@ -61,8 +62,29 @@ DIGEST_TEST ( sha256_nist_abc_opq, &sha256_algorithm, DIGEST_NIST_ABC_OPQ, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 ) ); +/* Empty test vector (digest obtained from "sha224sum /dev/null") */ +DIGEST_TEST ( sha224_empty, &sha224_algorithm, DIGEST_EMPTY, + DIGEST ( 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, + 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2, + 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, + 0x2f ) ); + +/* NIST test vector "abc" */ +DIGEST_TEST ( sha224_nist_abc, &sha224_algorithm, DIGEST_NIST_ABC, + DIGEST ( 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, 0x86, + 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, 0x2a, 0xad, + 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, + 0xa7 ) ); + +/* NIST test vector "abc...opq" */ +DIGEST_TEST ( sha224_nist_abc_opq, &sha224_algorithm, DIGEST_NIST_ABC_OPQ, + DIGEST ( 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, 0x5d, + 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, 0xb0, 0xc6, + 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, + 0x25 ) ); + /** - * Perform SHA-256 self-test + * Perform SHA-256 family self-test * */ static void sha256_test_exec ( void ) { @@ -71,13 +93,18 @@ static void sha256_test_exec ( void ) { digest_ok ( &sha256_empty ); digest_ok ( &sha256_nist_abc ); digest_ok ( &sha256_nist_abc_opq ); + digest_ok ( &sha224_empty ); + digest_ok ( &sha224_nist_abc ); + digest_ok ( &sha224_nist_abc_opq ); /* Speed tests */ DBG ( "SHA256 required %ld cycles per byte\n", digest_cost ( &sha256_algorithm ) ); + DBG ( "SHA224 required %ld cycles per byte\n", + digest_cost ( &sha224_algorithm ) ); } -/** SHA-256 self-test */ +/** SHA-256 family self-test */ struct self_test sha256_test __self_test = { .name = "sha256", .exec = sha256_test_exec, |