diff --git a/Makefile.am b/Makefile.am index 9cee974..22995db 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,7 +43,12 @@ lib_LTLIBRARIES = src/libdt-utils.la bin_PROGRAMS = barebox-state fdtdump -barebox_state_SOURCES = src/barebox-state.c +barebox_state_SOURCES = \ + src/crypto/digest.c \ + src/crypto/hmac.c \ + src/crypto/sha1.c \ + src/crypto/sha2.c \ + src/barebox-state.c barebox_state_CFLAGS = $(LIBDT_CFLAGS) barebox_state_LDADD = src/libdt-utils.la diff --git a/src/asm/unaligned.h b/src/asm/unaligned.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/src/asm/unaligned.h @@ -0,0 +1 @@ +/* empty */ diff --git a/src/barebox-state.c b/src/barebox-state.c index 01b396e..840c700 100644 --- a/src/barebox-state.c +++ b/src/barebox-state.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -50,20 +51,6 @@ #define asprintf(fmt, arg...) barebox_asprintf(fmt, ##arg) -char *barebox_asprintf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); -char *barebox_asprintf(const char *fmt, ...) -{ - va_list ap; - char *p; - int ret; - - va_start(ap, fmt); - ret = vasprintf(&p, fmt, ap); - va_end(ap); - - return ret == -1 ? NULL : p; -} - /* ------------------------------------------------------------ */ #define RAW_BACKEND_COPIES 2 diff --git a/src/crypto/digest.c b/src/crypto/digest.c new file mode 100644 index 0000000..7a8c3c0 --- /dev/null +++ b/src/crypto/digest.c @@ -0,0 +1,323 @@ +/* + * (C) Copyright 2008-2010 Jean-Christophe PLAGNIOL-VILLARD + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; version 2 of + * the License. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(digests); + +static struct digest_algo *digest_algo_get_by_name(const char *name); + +static int dummy_init(struct digest *d) +{ + return 0; +} + +static void dummy_free(struct digest *d) {} + +int digest_generic_verify(struct digest *d, const unsigned char *md) +{ + int ret; + int len = digest_length(d); + unsigned char *tmp; + + tmp = xmalloc(len); + + ret = digest_final(d, tmp); + if (ret) + goto end; + + ret = memcmp(md, tmp, len); + ret = ret ? -EINVAL : 0; +end: + free(tmp); + return ret; +} + +int digest_generic_digest(struct digest *d, const void *data, + unsigned int len, u8 *md) + +{ + int ret; + + if (!data || len == 0 || !md) + return -EINVAL; + + ret = digest_init(d); + if (ret) + return ret; + ret = digest_update(d, data, len); + if (ret) + return ret; + return digest_final(d, md); +} + +int digest_algo_register(struct digest_algo *d) +{ + if (!d || !d->base.name || !d->update || !d->final || !d->verify) + return -EINVAL; + + if (!d->init) + d->init = dummy_init; + + if (!d->alloc) + d->alloc = dummy_init; + + if (!d->free) + d->free = dummy_free; + + list_add_tail(&d->list, &digests); + + return 0; +} +EXPORT_SYMBOL(digest_algo_register); + +void digest_algo_unregister(struct digest_algo *d) +{ + if (!d) + return; + + list_del(&d->list); +} +EXPORT_SYMBOL(digest_algo_unregister); + +static struct digest_algo *digest_algo_get_by_name(const char *name) +{ + struct digest_algo *d = NULL; + struct digest_algo *tmp; + int priority = -1; + + if (!name) + return NULL; + + list_for_each_entry(tmp, &digests, list) { + if (strcmp(tmp->base.name, name) != 0) + continue; + + if (tmp->base.priority <= priority) + continue; + + d = tmp; + priority = tmp->base.priority; + } + + return d; +} + +static struct digest_algo *digest_algo_get_by_algo(enum hash_algo algo) +{ + struct digest_algo *d = NULL; + struct digest_algo *tmp; + int priority = -1; + + list_for_each_entry(tmp, &digests, list) { + if (tmp->base.algo != algo) + continue; + + if (tmp->base.priority <= priority) + continue; + + d = tmp; + priority = tmp->base.priority; + } + + return d; +} + +void digest_algo_prints(const char *prefix) +{ + struct digest_algo* d; + + printf("%s%-15s\t%-20s\t%-15s\n", prefix, "name", "driver", "priority"); + printf("%s--------------------------------------------------\n", prefix); + list_for_each_entry(d, &digests, list) { + printf("%s%-15s\t%-20s\t%d\n", prefix, d->base.name, + d->base.driver_name, d->base.priority); + } +} + +struct digest *digest_alloc(const char *name) +{ + struct digest *d; + struct digest_algo *algo; + + algo = digest_algo_get_by_name(name); + if (!algo) + return NULL; + + d = xzalloc(sizeof(*d)); + d->algo = algo; + d->ctx = xzalloc(algo->ctx_length); + if (d->algo->alloc(d)) { + digest_free(d); + return NULL; + } + + return d; +} +EXPORT_SYMBOL_GPL(digest_alloc); + +struct digest *digest_alloc_by_algo(enum hash_algo hash_algo) +{ + struct digest *d; + struct digest_algo *algo; + + algo = digest_algo_get_by_algo(hash_algo); + if (!algo) + return NULL; + + d = xzalloc(sizeof(*d)); + d->algo = algo; + d->ctx = xzalloc(algo->ctx_length); + if (d->algo->alloc(d)) { + digest_free(d); + return NULL; + } + + return d; +} +EXPORT_SYMBOL_GPL(digest_alloc_by_algo); + +void digest_free(struct digest *d) +{ + if (!d) + return; + d->algo->free(d); + free(d->ctx); + free(d); +} +EXPORT_SYMBOL_GPL(digest_free); + +int digest_file_window(struct digest *d, const char *filename, + unsigned char *hash, + const unsigned char *sig, + ulong start, ulong size) +{ + ulong len = 0; + int fd, now, ret = 0; + unsigned char *buf; + int flags = 0; + + ret = digest_init(d); + if (ret) + return ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + return fd; + } + + buf = memmap(fd, PROT_READ); + if (buf == (void *)-1) { + buf = xmalloc(4096); + flags = 1; + } + + if (start > 0) { + if (flags) { + ret = lseek(fd, start, SEEK_SET); + if (ret == -1) { + perror("lseek"); + goto out; + } + } else { + buf += start; + } + } + + while (size) { + now = min((ulong)4096, size); + if (flags) { + now = read(fd, buf, now); + if (now < 0) { + ret = now; + perror("read"); + goto out_free; + } + if (!now) + break; + } + + if (ctrlc()) { + ret = -EINTR; + goto out_free; + } + + ret = digest_update(d, buf, now); + if (ret) + goto out_free; + size -= now; + len += now; + } + + if (sig) + ret = digest_verify(d, sig); + else + ret = digest_final(d, hash); + +out_free: + if (flags) + free(buf); +out: + close(fd); + + return ret; +} +EXPORT_SYMBOL_GPL(digest_file_window); + +int digest_file(struct digest *d, const char *filename, + unsigned char *hash, + const unsigned char *sig) +{ + struct stat st; + int ret; + + ret = stat(filename, &st); + + if (ret < 0) + return ret; + + return digest_file_window(d, filename, hash, sig, 0, st.st_size); +} +EXPORT_SYMBOL_GPL(digest_file); + +int digest_file_by_name(const char *algo, const char *filename, + unsigned char *hash, + const unsigned char *sig) +{ + struct digest *d; + int ret; + + d = digest_alloc(algo); + if (!d) + return -EIO; + + ret = digest_file(d, filename, hash, sig); + digest_free(d); + return ret; +} +EXPORT_SYMBOL_GPL(digest_file_by_name); diff --git a/src/crypto/hmac.c b/src/crypto/hmac.c new file mode 100644 index 0000000..ab1b24d --- /dev/null +++ b/src/crypto/hmac.c @@ -0,0 +1,201 @@ +/* + * (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD + * + * GPL v2 only + */ + +#include +#include +#include +#include +#include + +#define asprintf(fmt, arg...) barebox_asprintf(fmt, ##arg) + +struct digest_hmac { + char *name; + unsigned int pad_length; + struct digest_algo algo; +}; + +struct digest_hmac_ctx { + struct digest *d; + + unsigned char *ipad; + unsigned char *opad; + + unsigned char *key; + unsigned int keylen; +}; + +static inline struct digest_hmac *to_digest_hmac(struct digest_algo *algo) +{ + return container_of(algo, struct digest_hmac, algo); +} + +static int digest_hmac_alloc(struct digest *d) +{ + struct digest_hmac_ctx *dh = d->ctx; + struct digest_hmac *hmac = to_digest_hmac(d->algo); + + dh->d = digest_alloc(hmac->name); + if (!dh->d) + return -EINVAL; + + d->length = dh->d->algo->length; + + dh->ipad = xmalloc(hmac->pad_length); + dh->opad = xmalloc(hmac->pad_length); + + return 0; +} + +static void digest_hmac_free(struct digest *d) +{ + struct digest_hmac_ctx *dh = d->ctx; + + free(dh->ipad); + free(dh->opad); + free(dh->key); + + digest_free(dh->d); +} + +static int digest_hmac_set_key(struct digest *d, const unsigned char *key, + unsigned int len) +{ + struct digest_hmac_ctx *dh = d->ctx; + struct digest_hmac *hmac = to_digest_hmac(d->algo); + unsigned char *sum = NULL; + int ret; + + free(dh->key); + if (len > hmac->pad_length) { + sum = xmalloc(digest_length(dh->d)); + ret = digest_digest(dh->d, dh->key, dh->keylen, sum); + if (ret) + goto err; + dh->keylen = digest_length(dh->d); + dh->key = sum; + } else { + dh->key = xmalloc(len); + memcpy(dh->key, key, len); + dh->keylen = len; + } + + ret = 0; +err: + free(sum); + return ret; +} + +static int digest_hmac_init(struct digest *d) +{ + struct digest_hmac_ctx *dh = d->ctx; + struct digest_hmac *hmac = to_digest_hmac(d->algo); + int i, ret; + unsigned char *key = dh->key; + unsigned int keylen = dh->keylen; + + memset(dh->ipad, 0x36, hmac->pad_length); + memset(dh->opad, 0x5C, hmac->pad_length); + + for (i = 0; i < keylen; i++) { + dh->ipad[i] = (unsigned char)(dh->ipad[i] ^ key[i]); + dh->opad[i] = (unsigned char)(dh->opad[i] ^ key[i]); + } + + ret = digest_init(dh->d); + if (ret) + return ret; + return digest_update(dh->d, dh->ipad, hmac->pad_length); +} + +static int digest_hmac_update(struct digest *d, const void *data, + unsigned long len) +{ + struct digest_hmac_ctx *dh = d->ctx; + + return digest_update(dh->d, data, len); +} + +static int digest_hmac_final(struct digest *d, unsigned char *md) +{ + struct digest_hmac_ctx *dh = d->ctx; + struct digest_hmac *hmac = to_digest_hmac(d->algo); + unsigned char *tmp = NULL; + int ret; + + tmp = xmalloc(digest_length(d)); + + ret = digest_final(dh->d, tmp); + if (ret) + goto err; + ret = digest_init(dh->d); + if (ret) + goto err; + ret = digest_update(dh->d, dh->opad, hmac->pad_length); + if (ret) + goto err; + ret = digest_update(dh->d, tmp, digest_length(d)); + if (ret) + goto err; + ret = digest_final(dh->d, md); + +err: + free(tmp); + + return ret; +} + +struct digest_algo hmac_algo = { + .base = { + .priority = 0, + .flags = DIGEST_ALGO_NEED_KEY, + }, + .alloc = digest_hmac_alloc, + .init = digest_hmac_init, + .update = digest_hmac_update, + .final = digest_hmac_final, + .digest = digest_generic_digest, + .verify = digest_generic_verify, + .set_key = digest_hmac_set_key, + .free = digest_hmac_free, + .ctx_length = sizeof(struct digest_hmac), +}; + +static int digest_hmac_register(char *name, unsigned int pad_length) +{ + struct digest_hmac *dh; + + if (!name || !pad_length) + return -EINVAL; + + dh = xzalloc(sizeof(*dh)); + dh->name = xstrdup(name); + dh->pad_length = pad_length; + dh->algo = hmac_algo; + dh->algo.base.name = asprintf("hmac(%s)", name); + dh->algo.base.driver_name = asprintf("hmac(%s)-generic", name); + + return digest_algo_register(&dh->algo); +} + +static int digest_hmac_initcall(void) +{ + if (IS_ENABLED(CONFIG_MD5)) + digest_hmac_register("md5", 64); + if (IS_ENABLED(CONFIG_SHA1)) + digest_hmac_register("sha1", 64); + if (IS_ENABLED(CONFIG_SHA224)) + digest_hmac_register("sha224", 64); + if (IS_ENABLED(CONFIG_SHA256)) + digest_hmac_register("sha256", 64); + if (IS_ENABLED(CONFIG_SHA384)) + digest_hmac_register("sha384", 128); + if (IS_ENABLED(CONFIG_SHA512)) + digest_hmac_register("sha512", 128); + + return 0; +} +crypto_initcall(digest_hmac_initcall); diff --git a/src/crypto/internal.h b/src/crypto/internal.h new file mode 100644 index 0000000..06254ea --- /dev/null +++ b/src/crypto/internal.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD + * + * GPL v2 only + */ + +int digest_generic_verify(struct digest *d, const unsigned char *md); +int digest_generic_digest(struct digest *d, const void *data, + unsigned int len, u8 *out); + +#define CONFIG_SHA1 1 +#define CONFIG_SHA224 1 +#define CONFIG_SHA256 1 diff --git a/src/crypto/sha.h b/src/crypto/sha.h new file mode 100644 index 0000000..190f8a0 --- /dev/null +++ b/src/crypto/sha.h @@ -0,0 +1,95 @@ +/* + * Common values for SHA algorithms + */ + +#ifndef _CRYPTO_SHA_H +#define _CRYPTO_SHA_H + +#include + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_BLOCK_SIZE 64 + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 + +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 + +#define SHA1_H0 0x67452301UL +#define SHA1_H1 0xefcdab89UL +#define SHA1_H2 0x98badcfeUL +#define SHA1_H3 0x10325476UL +#define SHA1_H4 0xc3d2e1f0UL + +#define SHA224_H0 0xc1059ed8UL +#define SHA224_H1 0x367cd507UL +#define SHA224_H2 0x3070dd17UL +#define SHA224_H3 0xf70e5939UL +#define SHA224_H4 0xffc00b31UL +#define SHA224_H5 0x68581511UL +#define SHA224_H6 0x64f98fa7UL +#define SHA224_H7 0xbefa4fa4UL + +#define SHA256_H0 0x6a09e667UL +#define SHA256_H1 0xbb67ae85UL +#define SHA256_H2 0x3c6ef372UL +#define SHA256_H3 0xa54ff53aUL +#define SHA256_H4 0x510e527fUL +#define SHA256_H5 0x9b05688cUL +#define SHA256_H6 0x1f83d9abUL +#define SHA256_H7 0x5be0cd19UL + +#define SHA384_H0 0xcbbb9d5dc1059ed8ULL +#define SHA384_H1 0x629a292a367cd507ULL +#define SHA384_H2 0x9159015a3070dd17ULL +#define SHA384_H3 0x152fecd8f70e5939ULL +#define SHA384_H4 0x67332667ffc00b31ULL +#define SHA384_H5 0x8eb44a8768581511ULL +#define SHA384_H6 0xdb0c2e0d64f98fa7ULL +#define SHA384_H7 0x47b5481dbefa4fa4ULL + +#define SHA512_H0 0x6a09e667f3bcc908ULL +#define SHA512_H1 0xbb67ae8584caa73bULL +#define SHA512_H2 0x3c6ef372fe94f82bULL +#define SHA512_H3 0xa54ff53a5f1d36f1ULL +#define SHA512_H4 0x510e527fade682d1ULL +#define SHA512_H5 0x9b05688c2b3e6c1fULL +#define SHA512_H6 0x1f83d9abfb41bd6bULL +#define SHA512_H7 0x5be0cd19137e2179ULL + +struct sha1_state { + u64 count; + u32 state[SHA1_DIGEST_SIZE / 4]; + u8 buffer[SHA1_BLOCK_SIZE]; +}; + +struct sha256_state { + u64 count; + u32 state[SHA256_DIGEST_SIZE / 4]; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +struct sha512_state { + u64 count[2]; + u64 state[SHA512_DIGEST_SIZE / 8]; + u8 buf[SHA512_BLOCK_SIZE]; +}; + +struct shash_desc; + +extern int crypto_sha1_update(struct shash_desc *desc, const u8 *data, + unsigned int len); + +extern int crypto_sha256_update(struct shash_desc *desc, const u8 *data, + unsigned int len); + +extern int crypto_sha512_update(struct shash_desc *desc, const u8 *data, + unsigned int len); +#endif diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c new file mode 100644 index 0000000..cbde4d2 --- /dev/null +++ b/src/crypto/sha1.c @@ -0,0 +1,306 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * + * 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 (at your option) + * any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SHA_WORKSPACE_WORDS 16 + +static int sha1_init(struct digest *desc) +{ + struct sha1_state *ctx = digest_ctx(desc); + + ctx->count = 0; + + ctx->state[0] = SHA1_H0; + ctx->state[1] = SHA1_H1; + ctx->state[2] = SHA1_H2; + ctx->state[3] = SHA1_H3; + ctx->state[4] = SHA1_H4; + + return 0; +} + +/* + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * + * Ben Herrenschmidt reports that on PPC, the C version comes close + * to the optimized asm with this (ie on PPC you don't want that + * 'volatile', since there are lots of registers). + * + * On ARM we get the best code generation by forcing a full memory barrier + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and + * the stack frame size simply explode and performance goes down the drain. + */ + +#ifdef CONFIG_X86 + #define setW(x, val) (*(volatile __u32 *)&W(x) = (val)) +#elif defined(CONFIG_ARM) + #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) +#else + #define setW(x, val) (W(x) = (val)) +#endif + +/* This "rolls" over the 512-bit array */ +#define W(x) (array[(x)&15]) + +/* + * Where do we get the source from? The first 16 iterations get it from + * the input data, the next mix it from the 512-bit array. + */ +#define SHA_SRC(t) get_unaligned_be32((__u32 *)data + t) +#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1) + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + __u32 TEMP = input(t); setW(t, TEMP); \ + E += TEMP + rol32(A,5) + (fn) + (constant); \ + B = ror32(B, 2); } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +/** + * sha_transform - single block SHA1 transform + * + * @digest: 160 bit digest to update + * @data: 512 bits of data to hash + * @array: 16 words of workspace (see note) + * + * This function generates a SHA1 digest for a single 512-bit block. + * Be warned, it does not handle padding and message digest, do not + * confuse it with the full FIPS 180-1 digest algorithm for variable + * length messages. + * + * Note: If the hash is security sensitive, the caller should be sure + * to clear the workspace. This is left to the caller to avoid + * unnecessary clears between chained hashing operations. + */ +static void sha_transform(__u32 *digest, const char *data, __u32 *array) +{ + __u32 A, B, C, D, E; + + A = digest[0]; + B = digest[1]; + C = digest[2]; + D = digest[3]; + E = digest[4]; + + /* Round 1 - iterations 0-16 take their input from 'data' */ + T_0_15( 0, A, B, C, D, E); + T_0_15( 1, E, A, B, C, D); + T_0_15( 2, D, E, A, B, C); + T_0_15( 3, C, D, E, A, B); + T_0_15( 4, B, C, D, E, A); + T_0_15( 5, A, B, C, D, E); + T_0_15( 6, E, A, B, C, D); + T_0_15( 7, D, E, A, B, C); + T_0_15( 8, C, D, E, A, B); + T_0_15( 9, B, C, D, E, A); + T_0_15(10, A, B, C, D, E); + T_0_15(11, E, A, B, C, D); + T_0_15(12, D, E, A, B, C); + T_0_15(13, C, D, E, A, B); + T_0_15(14, B, C, D, E, A); + T_0_15(15, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + T_16_19(16, E, A, B, C, D); + T_16_19(17, D, E, A, B, C); + T_16_19(18, C, D, E, A, B); + T_16_19(19, B, C, D, E, A); + + /* Round 2 */ + T_20_39(20, A, B, C, D, E); + T_20_39(21, E, A, B, C, D); + T_20_39(22, D, E, A, B, C); + T_20_39(23, C, D, E, A, B); + T_20_39(24, B, C, D, E, A); + T_20_39(25, A, B, C, D, E); + T_20_39(26, E, A, B, C, D); + T_20_39(27, D, E, A, B, C); + T_20_39(28, C, D, E, A, B); + T_20_39(29, B, C, D, E, A); + T_20_39(30, A, B, C, D, E); + T_20_39(31, E, A, B, C, D); + T_20_39(32, D, E, A, B, C); + T_20_39(33, C, D, E, A, B); + T_20_39(34, B, C, D, E, A); + T_20_39(35, A, B, C, D, E); + T_20_39(36, E, A, B, C, D); + T_20_39(37, D, E, A, B, C); + T_20_39(38, C, D, E, A, B); + T_20_39(39, B, C, D, E, A); + + /* Round 3 */ + T_40_59(40, A, B, C, D, E); + T_40_59(41, E, A, B, C, D); + T_40_59(42, D, E, A, B, C); + T_40_59(43, C, D, E, A, B); + T_40_59(44, B, C, D, E, A); + T_40_59(45, A, B, C, D, E); + T_40_59(46, E, A, B, C, D); + T_40_59(47, D, E, A, B, C); + T_40_59(48, C, D, E, A, B); + T_40_59(49, B, C, D, E, A); + T_40_59(50, A, B, C, D, E); + T_40_59(51, E, A, B, C, D); + T_40_59(52, D, E, A, B, C); + T_40_59(53, C, D, E, A, B); + T_40_59(54, B, C, D, E, A); + T_40_59(55, A, B, C, D, E); + T_40_59(56, E, A, B, C, D); + T_40_59(57, D, E, A, B, C); + T_40_59(58, C, D, E, A, B); + T_40_59(59, B, C, D, E, A); + + /* Round 4 */ + T_60_79(60, A, B, C, D, E); + T_60_79(61, E, A, B, C, D); + T_60_79(62, D, E, A, B, C); + T_60_79(63, C, D, E, A, B); + T_60_79(64, B, C, D, E, A); + T_60_79(65, A, B, C, D, E); + T_60_79(66, E, A, B, C, D); + T_60_79(67, D, E, A, B, C); + T_60_79(68, C, D, E, A, B); + T_60_79(69, B, C, D, E, A); + T_60_79(70, A, B, C, D, E); + T_60_79(71, E, A, B, C, D); + T_60_79(72, D, E, A, B, C); + T_60_79(73, C, D, E, A, B); + T_60_79(74, B, C, D, E, A); + T_60_79(75, A, B, C, D, E); + T_60_79(76, E, A, B, C, D); + T_60_79(77, D, E, A, B, C); + T_60_79(78, C, D, E, A, B); + T_60_79(79, B, C, D, E, A); + + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; +} + +static int sha1_update(struct digest *desc, const void *data, + unsigned long len) +{ + struct sha1_state *sctx = digest_ctx(desc); + unsigned int partial, done; + const u8 *src; + + partial = sctx->count % SHA1_BLOCK_SIZE; + sctx->count += len; + done = 0; + src = data; + + if ((partial + len) >= SHA1_BLOCK_SIZE) { + u32 temp[SHA_WORKSPACE_WORDS]; + + if (partial) { + done = -partial; + memcpy(sctx->buffer + partial, data, + done + SHA1_BLOCK_SIZE); + src = sctx->buffer; + } + + do { + sha_transform(sctx->state, src, temp); + done += SHA1_BLOCK_SIZE; + src = data + done; + } while (done + SHA1_BLOCK_SIZE <= len); + + memset(temp, 0, sizeof(temp)); + partial = 0; + } + memcpy(sctx->buffer + partial, src, len - done); + + return 0; +} + +static int sha1_final(struct digest *desc, unsigned char *md) +{ + struct sha1_state *sctx = digest_ctx(desc); + __be32 *dst = (__be32 *)md; + u32 i, index, padlen; + __be64 bits; + static const u8 padding[64] = { 0x80, }; + + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64 */ + index = sctx->count & 0x3f; + padlen = (index < 56) ? (56 - index) : ((64+56) - index); + sha1_update(desc, padding, padlen); + + /* Append length */ + sha1_update(desc, (const u8 *)&bits, sizeof(bits)); + + /* Store state in digest */ + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(sctx->state[i]); + + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); + + return 0; +} + +static struct digest_algo m = { + .base = { + .name = "sha1", + .driver_name = "sha1-generic", + .priority = 0, + .algo = HASH_ALGO_SHA1, + }, + + .init = sha1_init, + .update = sha1_update, + .final = sha1_final, + .digest = digest_generic_digest, + .verify = digest_generic_verify, + .length = SHA1_DIGEST_SIZE, + .ctx_length = sizeof(struct sha1_state), +}; + +static int sha1_digest_register(void) +{ + return digest_algo_register(&m); +} +device_initcall(sha1_digest_register); diff --git a/src/crypto/sha2.c b/src/crypto/sha2.c new file mode 100644 index 0000000..cb0f11c --- /dev/null +++ b/src/crypto/sha2.c @@ -0,0 +1,375 @@ +/* + * Cryptographic API. + * + * SHA-256, as specified in + * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf + * + * SHA-256 code by Jean-Luc Cooke . + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2002 James Morris + * SHA224 Support Copyright 2007 Intel Corporation + * + * 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 (at your option) + * any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return z ^ (x & (y ^ z)); +} + +static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return (x & y) | (z & (x | y)); +} + +#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22)) +#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25)) +#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3)) +#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10)) + +static inline void LOAD_OP(int I, u32 *W, const u8 *input) +{ + W[I] = get_unaligned_be32((__u32 *)input + I); +} + +static inline void BLEND_OP(int I, u32 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void sha256_transform(u32 *state, const u8 *input) +{ + u32 a, b, c, d, e, f, g, h, t1, t2; + u32 W[64]; + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + /* now blend */ + for (i = 16; i < 64; i++) + BLEND_OP(i, W); + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* clear any sensitive info... */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 64 * sizeof(u32)); +} + +static int sha224_init(struct digest *desc) +{ + struct sha256_state *sctx = digest_ctx(desc); + sctx->state[0] = SHA224_H0; + sctx->state[1] = SHA224_H1; + sctx->state[2] = SHA224_H2; + sctx->state[3] = SHA224_H3; + sctx->state[4] = SHA224_H4; + sctx->state[5] = SHA224_H5; + sctx->state[6] = SHA224_H6; + sctx->state[7] = SHA224_H7; + sctx->count = 0; + + return 0; +} + +static int sha256_init(struct digest *desc) +{ + struct sha256_state *sctx = digest_ctx(desc); + sctx->state[0] = SHA256_H0; + sctx->state[1] = SHA256_H1; + sctx->state[2] = SHA256_H2; + sctx->state[3] = SHA256_H3; + sctx->state[4] = SHA256_H4; + sctx->state[5] = SHA256_H5; + sctx->state[6] = SHA256_H6; + sctx->state[7] = SHA256_H7; + sctx->count = 0; + + return 0; +} + +static int sha256_update(struct digest *desc, const void *data, + unsigned long len) +{ + struct sha256_state *sctx = digest_ctx(desc); + unsigned int partial, done; + const u8 *src; + + partial = sctx->count & 0x3f; + sctx->count += len; + done = 0; + src = data; + + if ((partial + len) > 63) { + if (partial) { + done = -partial; + memcpy(sctx->buf + partial, data, done + 64); + src = sctx->buf; + } + + do { + sha256_transform(sctx->state, src); + done += 64; + src = data + done; + } while (done + 63 < len); + + partial = 0; + } + memcpy(sctx->buf + partial, src, len - done); + + return 0; +} + +static int sha256_final(struct digest *desc, u8 *out) +{ + struct sha256_state *sctx = digest_ctx(desc); + __be32 *dst = (__be32 *)out; + __be64 bits; + unsigned int index, pad_len; + int i; + static const u8 padding[64] = { 0x80, }; + + /* Save number of bits */ + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64. */ + index = sctx->count & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64+56) - index); + sha256_update(desc, padding, pad_len); + + /* Append length (before padding) */ + sha256_update(desc, (const u8 *)&bits, sizeof(bits)); + + /* Store state in digest */ + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be32(sctx->state[i]); + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(*sctx)); + + return 0; +} + +static int sha224_final(struct digest *desc, u8 *hash) +{ + u8 D[SHA256_DIGEST_SIZE]; + + sha256_final(desc, D); + + memcpy(hash, D, SHA224_DIGEST_SIZE); + memset(D, 0, SHA256_DIGEST_SIZE); + + return 0; +} + +static struct digest_algo m224 = { + .base = { + .name = "sha224", + .driver_name = "sha224-generic", + .priority = 0, + .algo = HASH_ALGO_SHA224, + }, + + .init = sha224_init, + .update = sha256_update, + .final = sha224_final, + .digest = digest_generic_digest, + .verify = digest_generic_verify, + .length = SHA224_DIGEST_SIZE, + .ctx_length = sizeof(struct sha256_state), +}; + +static int sha224_digest_register(void) +{ + if (!IS_ENABLED(CONFIG_SHA224)) + return 0; + + return digest_algo_register(&m224); +} +device_initcall(sha224_digest_register); + +static struct digest_algo m256 = { + .base = { + .name = "sha256", + .driver_name = "sha256-generic", + .priority = 0, + .algo = HASH_ALGO_SHA256, + }, + + .init = sha256_init, + .update = sha256_update, + .final = sha256_final, + .digest = digest_generic_digest, + .verify = digest_generic_verify, + .length = SHA256_DIGEST_SIZE, + .ctx_length = sizeof(struct sha256_state), +}; + +static int sha256_digest_register(void) +{ + if (!IS_ENABLED(CONFIG_SHA256)) + return 0; + + return digest_algo_register(&m256); +} +device_initcall(sha256_digest_register); diff --git a/src/digest.h b/src/digest.h new file mode 100644 index 0000000..efe330d --- /dev/null +++ b/src/digest.h @@ -0,0 +1,158 @@ +/* + * (C) Copyright 2008-2010 Jean-Christophe PLAGNIOL-VILLARD + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; version 2 of + * the License. + * + * 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. + * + */ + +#ifndef __DIGEST_H__ +#define __DIGEST_H__ + +#include + +struct digest; + +enum hash_algo { + HASH_ALGO_MD4, + HASH_ALGO_MD5, + HASH_ALGO_SHA1, + HASH_ALGO_RIPE_MD_160, + HASH_ALGO_SHA224, + HASH_ALGO_SHA256, + HASH_ALGO_SHA384, + HASH_ALGO_SHA512, + HASH_ALGO_RIPE_MD_128, + HASH_ALGO_RIPE_MD_256, + HASH_ALGO_RIPE_MD_320, + HASH_ALGO_WP_256, + HASH_ALGO_WP_384, + HASH_ALGO_WP_512, + HASH_ALGO_TGR_128, + HASH_ALGO_TGR_160, + HASH_ALGO_TGR_192, + HASH_ALGO__LAST +}; + +struct crypto_alg { + char *name; + char *driver_name; + int priority; +#define DIGEST_ALGO_NEED_KEY (1 << 0) + unsigned int flags; + enum hash_algo algo; +}; + +struct digest_algo { + struct crypto_alg base; + + int (*alloc)(struct digest *d); + void (*free)(struct digest *d); + int (*init)(struct digest *d); + int (*update)(struct digest *d, const void *data, unsigned long len); + int (*final)(struct digest *d, unsigned char *md); + int (*digest)(struct digest *d, const void *data, + unsigned int len, u8 *out); + int (*set_key)(struct digest *d, const unsigned char *key, unsigned int len); + int (*verify)(struct digest *d, const unsigned char *md); + + unsigned int length; + unsigned int ctx_length; + + struct list_head list; +}; + +struct digest { + struct digest_algo *algo; + void *ctx; + unsigned int length; +}; + +/* + * digest functions + */ +int digest_algo_register(struct digest_algo *d); +void digest_algo_unregister(struct digest_algo *d); +void digest_algo_prints(const char *prefix); + +struct digest *digest_alloc(const char *name); +struct digest *digest_alloc_by_algo(enum hash_algo); +void digest_free(struct digest *d); + +int digest_file_window(struct digest *d, const char *filename, + unsigned char *hash, + const unsigned char *sig, + ulong start, ulong size); +int digest_file(struct digest *d, const char *filename, + unsigned char *hash, + const unsigned char *sig); +int digest_file_by_name(const char *algo, const char *filename, + unsigned char *hash, + const unsigned char *sig); + +static inline int digest_init(struct digest *d) +{ + return d->algo->init(d); +} + +static inline int digest_update(struct digest *d, const void *data, + unsigned long len) +{ + return d->algo->update(d, data, len); +} + +static inline int digest_final(struct digest *d, unsigned char *md) +{ + return d->algo->final(d, md); +} + +static inline int digest_digest(struct digest *d, const void *data, + unsigned int len, u8 *md) +{ + return d->algo->digest(d, data, len, md); +} + +static inline int digest_verify(struct digest *d, const unsigned char *md) +{ + return d->algo->verify(d, md); +} + +static inline int digest_length(struct digest *d) +{ + return d->length ? d->length : d->algo->length; +} + +static inline int digest_set_key(struct digest *d, const unsigned char *key, + unsigned int len) +{ + if (!d->algo->set_key) + return -ENOTSUPP; + return d->algo->set_key(d, key, len); +} + +static inline int digest_is_flags(struct digest *d, unsigned int flags) +{ + return d->algo->base.flags & flags; +} + +static inline const char *digest_name(struct digest *d) +{ + return d->algo->base.name; +} + +static inline void* digest_ctx(struct digest *d) +{ + return d->ctx; +} + +#endif /* __SH_ST_DEVICES_H__ */ diff --git a/src/dt/common.h b/src/dt/common.h index 5645bad..d049ee7 100644 --- a/src/dt/common.h +++ b/src/dt/common.h @@ -3,8 +3,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -40,11 +42,23 @@ #define dev_info(dev, fmt, arg...) pr_err(fmt, ##arg) #define dev_dbg(dev, fmt, arg...) pr_debug(fmt, ##arg) +#ifndef ENOTSUPP +#define ENOTSUPP 524 +#endif + static inline void *xzalloc(size_t size) { return calloc(1, size); } +static inline void *xmalloc(size_t size) +{ + return xzalloc(size); +} + +#define EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_GPL(sym) + /* * Kernel pointers have redundant information, so we can use a * scheme where we can return either an error code or a dentry @@ -92,6 +106,20 @@ return (void *) ptr; } +static inline char *barebox_asprintf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); +static inline char *barebox_asprintf(const char *fmt, ...) +{ + va_list ap; + char *p; + int ret; + + va_start(ap, fmt); + ret = vasprintf(&p, fmt, ap); + va_end(ap); + + return ret == -1 ? NULL : p; +} + /** * strlcpy - Copy a %NUL terminated string into a sized buffer * @dest: Where to copy the string to @@ -226,6 +254,15 @@ return insize; } +static inline void *memmap(int fd, int flags) +{ + return (void *)-1; +} + +static inline int ctrlc (void) +{ + return 0; +} #define MAX_DRIVER_NAME 32 #define DEVICE_ID_SINGLE -1 @@ -295,9 +332,37 @@ return 0; } +#define __define_initcall(level,fn,id) \ +static void __attribute__ ((constructor)) __initcall_##id##_##fn() { \ + fn(); \ +} + +#define core_initcall(fn) __define_initcall("1",fn,1) +#define postcore_initcall(fn) __define_initcall("2",fn,2) +#define console_initcall(fn) __define_initcall("3",fn,3) +#define postconsole_initcall(fn) __define_initcall("4",fn,4) +#define mem_initcall(fn) __define_initcall("5",fn,5) +#define mmu_initcall(fn) __define_initcall("6",fn,6) +#define postmmu_initcall(fn) __define_initcall("7",fn,7) +#define coredevice_initcall(fn) __define_initcall("8",fn,8) +#define fs_initcall(fn) __define_initcall("9",fn,9) +#define device_initcall(fn) __define_initcall("10",fn,10) +#define crypto_initcall(fn) __define_initcall("11",fn,11) +#define late_initcall(fn) __define_initcall("12",fn,12) +#define environment_initcall(fn) __define_initcall("13",fn,13) +#define postenvironment_initcall(fn) __define_initcall("14",fn,14) + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + #define cpu_to_be32 __cpu_to_be32 #define be32_to_cpu __be32_to_cpu +#define cpu_to_be64 __cpu_to_be64 +#define be64_to_cpu __be64_to_cpu + #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) @@ -305,6 +370,136 @@ #define __maybe_unused __attribute__((unused)) +static inline u16 __get_unaligned_be16(const u8 *p) +{ + return p[0] << 8 | p[1]; +} + +static inline u32 __get_unaligned_be32(const u8 *p) +{ + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +static inline u64 __get_unaligned_be64(const u8 *p) +{ + return (u64)__get_unaligned_be32(p) << 32 | + __get_unaligned_be32(p + 4); +} + +static inline void __put_unaligned_be16(u16 val, u8 *p) +{ + *p++ = val >> 8; + *p++ = val; +} + +static inline void __put_unaligned_be32(u32 val, u8 *p) +{ + __put_unaligned_be16(val >> 16, p); + __put_unaligned_be16(val, p + 2); +} + +static inline void __put_unaligned_be64(u64 val, u8 *p) +{ + __put_unaligned_be32(val >> 32, p); + __put_unaligned_be32(val, p + 4); +} + +static inline u16 get_unaligned_be16(const void *p) +{ + return __get_unaligned_be16((const u8 *)p); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return __get_unaligned_be32((const u8 *)p); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return __get_unaligned_be64((const u8 *)p); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + __put_unaligned_be16(val, p); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + __put_unaligned_be32(val, p); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + __put_unaligned_be64(val, p); +} + +/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u32 rol32(__u32 word, unsigned int shift) +{ + return (word << shift) | (word >> (32 - shift)); +} + +/** + * ror32 - rotate a 32-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u32 ror32(__u32 word, unsigned int shift) +{ + return (word >> shift) | (word << (32 - shift)); +} + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +/* + * Helper macros to use CONFIG_ options in C expressions. Note that + * these only work with boolean and tristate options. + */ + +/* + * Getting something that works in C and CPP for an arg that may or may + * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" + * we match on the placeholder define, insert the "0," for arg1 and generate + * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). + * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when + * the last step cherry picks the 2nd arg, we get a zero. + */ +#define __ARG_PLACEHOLDER_1 0, +#define config_enabled(cfg) _config_enabled(cfg) +#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value) +#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0) +#define ___config_enabled(__ignored, val, ...) val + +/* + * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', + * 0 otherwise. + * + */ +#define IS_ENABLED(option) \ + (config_enabled(option) || config_enabled(option##_MODULE)) + +/* + * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 + * otherwise. For boolean options, this is equivalent to + * IS_ENABLED(CONFIG_FOO). + */ +#define IS_BUILTIN(option) config_enabled(option) + +/* + * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0 + * otherwise. + */ +#define IS_MODULE(option) config_enabled(option##_MODULE) + #endif uint32_t crc32(uint32_t crc, const void *_buf, unsigned int len); diff --git a/src/fs.h b/src/fs.h new file mode 100644 index 0000000..8b05b1a --- /dev/null +++ b/src/fs.h @@ -0,0 +1 @@ +#include diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/src/init.h @@ -0,0 +1 @@ +/* empty */ diff --git a/src/linux/err.h b/src/linux/err.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/src/linux/err.h @@ -0,0 +1 @@ +/* empty */ diff --git a/src/linux/list.h b/src/linux/list.h new file mode 100644 index 0000000..83c6d75 --- /dev/null +++ b/src/linux/list.h @@ -0,0 +1 @@ +#include
diff --git a/src/module.h b/src/module.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/src/module.h @@ -0,0 +1 @@ +/* empty */