diff options
Diffstat (limited to 'libc/bionic')
-rw-r--r-- | libc/bionic/cpuacct.c | 24 | ||||
-rw-r--r-- | libc/bionic/dlmalloc.c | 89 | ||||
-rw-r--r-- | libc/bionic/libc_init_common.h | 2 | ||||
-rw-r--r-- | libc/bionic/libc_init_static.c | 2 | ||||
-rw-r--r-- | libc/bionic/pthread.c | 8 | ||||
-rw-r--r-- | libc/bionic/ptrace.c | 131 | ||||
-rw-r--r-- | libc/bionic/sha1.c | 186 |
7 files changed, 223 insertions, 219 deletions
diff --git a/libc/bionic/cpuacct.c b/libc/bionic/cpuacct.c index 73170739e..1321d0eec 100644 --- a/libc/bionic/cpuacct.c +++ b/libc/bionic/cpuacct.c @@ -30,16 +30,19 @@ #include <errno.h> #include <sys/stat.h> #include "cpuacct.h" +#include <fcntl.h> int cpuacct_add(uid_t uid) { int count; - FILE *fp; + int fd; char buf[80]; + ssize_t n; + int ret = 0; count = snprintf(buf, sizeof(buf), "/acct/uid/%d/tasks", uid); - fp = fopen(buf, "w+"); - if (!fp) { + fd = open(buf, O_RDWR | O_CREAT, 0666); + if (fd == -1) { /* Note: sizeof("tasks") returns 6, which includes the NULL char */ buf[count - sizeof("tasks")] = 0; if (mkdir(buf, 0775) < 0) @@ -47,14 +50,19 @@ int cpuacct_add(uid_t uid) /* Note: sizeof("tasks") returns 6, which includes the NULL char */ buf[count - sizeof("tasks")] = '/'; - fp = fopen(buf, "w+"); + fd = open(buf, O_RDWR | O_CREAT, 0666); } - if (!fp) + if (fd == -1) return -errno; - fprintf(fp, "0"); - if (fclose(fp)) + n = TEMP_FAILURE_RETRY(write(fd, "0", 1)); + if (n < 0) + ret = -errno; + else if (n == 0) + ret = -EIO; + + if (TEMP_FAILURE_RETRY(close(fd)) == -1) return -errno; - return 0; + return ret; } diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c index 19fbb7521..ff94e2972 100644 --- a/libc/bionic/dlmalloc.c +++ b/libc/bionic/dlmalloc.c @@ -465,6 +465,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K */ +#ifdef ANDROID +#define USE_BUILTIN_FFS 1 +#ifdef __arm__ +#include <machine/cpu-features.h> +#endif +#endif /* ANDROID */ + #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 @@ -2394,6 +2401,17 @@ static size_t traverse_and_check(mstate m); } #else /* GNUC */ +#if defined(__ARM_ARCH__) && __ARM_ARCH__ >= 7 +#define compute_bit2idx(X, I) \ +{ \ + unsigned int J; \ + __asm__ ("rbit %0, %1\n" \ + "clz %0, %0" \ + : "=r" (J) : "r" (X)); \ + I = (bindex_t) J; \ +} + +#else /* ARM_ARCH */ #if USE_BUILTIN_FFS #define compute_bit2idx(X, I) I = ffs(X)-1 @@ -2409,6 +2427,7 @@ static size_t traverse_and_check(mstate m); N += K = Y >> (1-0) & 1; Y >>= K;\ I = (bindex_t)(N + Y);\ } +#endif /* ARM_ARCH */ #endif /* USE_BUILTIN_FFS */ #endif /* GNUC */ @@ -4542,8 +4561,25 @@ void dlmalloc_stats() { size_t dlmalloc_usable_size(void* mem) { if (mem != 0) { mchunkptr p = mem2chunk(mem); - if (cinuse(p)) - return chunksize(p) - overhead_for(p); + +#if FOOTERS + mstate fm = get_mstate_for(p); + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } +#else /* FOOTERS */ +#define fm gm +#endif + + if (!PREACTION(fm)) { + if (cinuse(p)) { + size_t ret = chunksize(p) - overhead_for(p); + POSTACTION(fm); + return ret; + } + POSTACTION(fm); + } } return 0; } @@ -5147,32 +5183,35 @@ void dlmalloc_walk_heap(void(*handler)(const void *chunkptr, size_t chunklen, mstate m = (mstate)gm; #endif - s = &m->seg; - while (s != 0) { - mchunkptr p = align_as_chunk(s->base); - while (segment_holds(s, p) && - p != m->top && p->head != FENCEPOST_HEAD) { - void *chunkptr, *userptr; - size_t chunklen, userlen; - chunkptr = p; - chunklen = chunksize(p); - if (cinuse(p)) { - userptr = chunk2mem(p); - userlen = chunklen - overhead_for(p); + if (!PREACTION(m)) { + s = &m->seg; + while (s != 0) { + mchunkptr p = align_as_chunk(s->base); + while (segment_holds(s, p) && + p != m->top && p->head != FENCEPOST_HEAD) { + void *chunkptr, *userptr; + size_t chunklen, userlen; + chunkptr = p; + chunklen = chunksize(p); + if (cinuse(p)) { + userptr = chunk2mem(p); + userlen = chunklen - overhead_for(p); + } + else { + userptr = NULL; + userlen = 0; + } + handler(chunkptr, chunklen, userptr, userlen, harg); + p = next_chunk(p); } - else { - userptr = NULL; - userlen = 0; + if (p == m->top) { + /* The top chunk is just a big free chunk for our purposes. + */ + handler(m->top, m->topsize, NULL, 0, harg); } - handler(chunkptr, chunklen, userptr, userlen, harg); - p = next_chunk(p); - } - if (p == m->top) { - /* The top chunk is just a big free chunk for our purposes. - */ - handler(m->top, m->topsize, NULL, 0, harg); + s = s->next; } - s = s->next; + POSTACTION(m); } } diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h index 6016d4d2d..35050a1da 100644 --- a/libc/bionic/libc_init_common.h +++ b/libc/bionic/libc_init_common.h @@ -35,7 +35,9 @@ typedef struct void (**preinit_array)(void); void (**init_array)(void); void (**fini_array)(void); +#ifndef __i386__ void (**ctors_array)(void); +#endif } structors_array_t; extern void __libc_init_common(uintptr_t *elfdata); diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c index 3634c7ba8..a2c11a9d0 100644 --- a/libc/bionic/libc_init_static.c +++ b/libc/bionic/libc_init_static.c @@ -75,8 +75,10 @@ __noreturn void __libc_init(uintptr_t *elfdata, /* pre-init array. */ call_array(structors->preinit_array); +#ifndef __i386__ /* .ctors section initializers, for non-arm-eabi ABIs */ call_array(structors->ctors_array); +#endif // call static constructors call_array(structors->init_array); diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index fcccbed89..6b0183074 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -68,7 +68,13 @@ int __futex_wait_ex(volatile void *ftx, int pshared, int val, const struct time #define __likely(cond) __builtin_expect(!!(cond), 1) #define __unlikely(cond) __builtin_expect(!!(cond), 0) -void _thread_created_hook(pid_t thread_id) __attribute__((noinline)); +#ifdef __i386__ +#define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall)) +#else +#define ATTRIBUTES __attribute__((noinline)) +#endif + +void ATTRIBUTES _thread_created_hook(pid_t thread_id); #define PTHREAD_ATTR_FLAG_DETACHED 0x00000001 #define PTHREAD_ATTR_FLAG_USER_STACK 0x00000002 diff --git a/libc/bionic/ptrace.c b/libc/bionic/ptrace.c index b1ca00ccd..0bb1acd78 100644 --- a/libc/bionic/ptrace.c +++ b/libc/bionic/ptrace.c @@ -1,63 +1,68 @@ -/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <sys/types.h>
-#include <sys/ptrace.h>
-
-extern long __ptrace(int request, pid_t pid, void *addr, void *data);
-
-long ptrace(int request, pid_t pid, void * addr, void * data)
-{
- switch (request) {
- case PTRACE_PEEKUSR:
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKDATA:
- {
- long word;
- long ret;
-
- ret = __ptrace(request, pid, addr, &word);
- if (ret == 0) {
- return word;
- } else {
- // __ptrace will set errno for us
- return -1;
- }
- }
-
- default:
- return __ptrace(request, pid, addr, data);
- }
-}
-
-/*
- * Hook for gdb to get notified when a thread is created
- */
-void _thread_created_hook(pid_t thread_id) __attribute__((noinline));
-void _thread_created_hook(pid_t thread_id)
-{
-}
+/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <sys/types.h> +#include <sys/ptrace.h> + +extern long __ptrace(int request, pid_t pid, void *addr, void *data); + +long ptrace(int request, pid_t pid, void * addr, void * data) +{ + switch (request) { + case PTRACE_PEEKUSR: + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + { + long word; + long ret; + + ret = __ptrace(request, pid, addr, &word); + if (ret == 0) { + return word; + } else { + // __ptrace will set errno for us + return -1; + } + } + + default: + return __ptrace(request, pid, addr, data); + } +} + +/* + * Hook for gdb to get notified when a thread is created + */ +#ifdef __i386__ +#define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall)) +#else +#define ATTRIBUTES __attribute__((noinline)) +#endif + +void ATTRIBUTES _thread_created_hook(pid_t thread_id) +{ +} diff --git a/libc/bionic/sha1.c b/libc/bionic/sha1.c index efa95a55c..a4fbd673b 100644 --- a/libc/bionic/sha1.c +++ b/libc/bionic/sha1.c @@ -22,10 +22,7 @@ #include <assert.h> #include <sha1.h> #include <string.h> - -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif +#include <endian.h> #if !HAVE_SHA1_H @@ -36,8 +33,7 @@ * I got the idea of expanding during the round function from SSLeay */ #if BYTE_ORDER == LITTLE_ENDIAN -# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) +# define blk0(i) swap32(block->l[i]) #else # define blk0(i) block->l[i] #endif @@ -54,77 +50,17 @@ #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); typedef union { - u_char c[64]; - u_int l[16]; + uint8_t c[SHA1_BLOCK_SIZE]; + uint32_t l[SHA1_BLOCK_SIZE/4]; } CHAR64LONG16; -/* old sparc64 gcc could not compile this */ -#undef SPARC64_GCC_WORKAROUND -#if defined(__sparc64__) && defined(__GNUC__) && __GNUC__ < 3 -#define SPARC64_GCC_WORKAROUND -#endif - -#ifdef SPARC64_GCC_WORKAROUND -void do_R01(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); -void do_R2(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); -void do_R3(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); -void do_R4(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); - -#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) -#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) -#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) -#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) -#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) - -void -do_R01(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) -{ - nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3); - nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); - nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); - nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15); - nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); -} - -void -do_R2(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) -{ - nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23); - nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); - nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); - nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35); - nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); -} - -void -do_R3(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) -{ - nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43); - nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); - nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); - nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55); - nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); -} - -void -do_R4(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) -{ - nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63); - nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); - nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); - nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75); - nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); -} -#endif - /* * Hash a single 512-bit block. This is the core of the algorithm. */ -void SHA1Transform(state, buffer) - u_int32_t state[5]; - const u_char buffer[64]; +void SHA1Transform(uint32_t state[SHA1_DIGEST_LENGTH/4], + const uint8_t buffer[SHA1_BLOCK_SIZE]) { - u_int32_t a, b, c, d, e; + uint32_t a, b, c, d, e; CHAR64LONG16 *block; #ifdef SHA1HANDSOFF @@ -136,7 +72,7 @@ void SHA1Transform(state, buffer) #ifdef SHA1HANDSOFF block = &workspace; - (void)memcpy(block, buffer, 64); + (void)memcpy(block, buffer, SHA1_BLOCK_SIZE); #else block = (CHAR64LONG16 *)(void *)buffer; #endif @@ -148,12 +84,6 @@ void SHA1Transform(state, buffer) d = state[3]; e = state[4]; -#ifdef SPARC64_GCC_WORKAROUND - do_R01(&a, &b, &c, &d, &e, block); - do_R2(&a, &b, &c, &d, &e, block); - do_R3(&a, &b, &c, &d, &e, block); - do_R4(&a, &b, &c, &d, &e, block); -#else /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); @@ -175,7 +105,6 @@ void SHA1Transform(state, buffer) R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -#endif /* Add the working vars back into context.state[] */ state[0] += a; @@ -192,78 +121,91 @@ void SHA1Transform(state, buffer) /* * SHA1Init - Initialize new context */ -void SHA1Init(context) - SHA1_CTX *context; +void SHA1Init(SHA1_CTX *context) { - assert(context != 0); /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; + *context = (SHA1_CTX) { + .state = { + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0, + }, + .count = 0, + }; } /* * Run your data through this. */ -void SHA1Update(context, data, len) - SHA1_CTX *context; - const u_char *data; - u_int len; +void SHA1Update(SHA1_CTX *context, const uint8_t *data, unsigned int len) { - u_int i, j; + unsigned int i, j; + unsigned int partial, done; + const uint8_t *src; assert(context != 0); assert(data != 0); - j = context->count[0]; - if ((context->count[0] += len << 3) < j) - context->count[1] += (len>>29)+1; - j = (j >> 3) & 63; - if ((j + len) > 63) { - (void)memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) - SHA1Transform(context->state, &data[i]); - j = 0; - } else { - i = 0; + partial = context->count % SHA1_BLOCK_SIZE; + context->count += len; + done = 0; + src = data; + + if ((partial + len) >= SHA1_BLOCK_SIZE) { + if (partial) { + done = -partial; + memcpy(context->buffer + partial, data, done + SHA1_BLOCK_SIZE); + src = context->buffer; + } + do { + SHA1Transform(context->state, src); + done += SHA1_BLOCK_SIZE; + src = data + done; + } while (done + SHA1_BLOCK_SIZE <= len); + partial = 0; } - (void)memcpy(&context->buffer[j], &data[i], len - i); + memcpy(context->buffer + partial, src, len - done); } /* * Add padding and return the message digest. */ -void SHA1Final(digest, context) - u_char digest[20]; - SHA1_CTX* context; +void SHA1Final(uint8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) { - u_int i; - u_char finalcount[8]; + uint32_t i, index, pad_len; + uint64_t bits; + static const uint8_t padding[SHA1_BLOCK_SIZE] = { 0x80, }; assert(digest != 0); assert(context != 0); - for (i = 0; i < 8; i++) { - finalcount[i] = (u_char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (const u_char *)"\200", 1); - while ((context->count[0] & 504) != 448) - SHA1Update(context, (const u_char *)"\0", 1); - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ +#if BYTE_ORDER == LITTLE_ENDIAN + bits = swap64(context->count << 3); +#else + bits = context->count << 3; +#endif + + /* Pad out to 56 mod 64 */ + index = context->count & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64 + 56) - index); + SHA1Update(context, padding, pad_len); + + /* Append length */ + SHA1Update(context, (const uint8_t *)&bits, sizeof(bits)); if (digest) { - for (i = 0; i < 20; i++) - digest[i] = (u_char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + for (i = 0; i < SHA1_DIGEST_LENGTH/4; i++) +#if BYTE_ORDER == LITTLE_ENDIAN + ((uint32_t *)digest)[i] = swap32(context->state[i]); +#else + ((uint32_t *)digest)[i] = context->state[i]; +#endif } } |