Beispiel #1
0
void sha512_final_file(HASH_ctx* ctx, const unsigned char* buf, size_t bufsize)
{
    while (ctx->SHA512_unprocessed_ >= SHA512_BLOCK_SIZE)
    {
        sha512_process_block(ctx->SHA512_hash_, reinterpret_cast<const uint64_t*>(buf));
        buf += SHA512_BLOCK_SIZE;
        ctx->SHA512_unprocessed_ -= SHA512_BLOCK_SIZE;
    }
    uint64_t message[SHA512_BLOCK_SIZE / 8];

    if (ctx->SHA512_unprocessed_)
    {
        memcpy(message, buf, static_cast<size_t>(ctx->SHA512_unprocessed_));
    }

    // The final SHA3 block size will be 0~127, then devide by 8 (sizeof uint64)
    // to get index
    uint32_t index = ((uint64_t)ctx->length_ & 127) >> 3;
    // shift of uint64 will be ranged from 0 to 7, times 8 to convert the unit to
    // bit
    uint32_t shift = ((uint64_t)ctx->length_ & 7) * 8;

    message[index] &= ~(0xFFFFFFFFFFFFFFFFULL << shift);
    message[index++] ^= 0x80ULL << shift;

    if (index > 14)
    {
        while (index < 16)
        {
            message[index++] = 0;
        }

        sha512_process_block(ctx->SHA512_hash_, message);
        index = 0;
    }

    while (index < 14)
    {
        message[index++] = 0;
    }

    // length in bit = length in char * 8
    uint64_t data_len = (ctx->length_) << 3;
    data_len = SWAP_UINT64(data_len);

    // store the size, only consider data_len < 2^64, so message[14] is always 0
    message[14] = 0x0ULL;
    message[15] = data_len;

    sha512_process_block(ctx->SHA512_hash_, message);

    swap_uint64_memcpy(&ctx->SHA512_result, &ctx->SHA512_hash_, SHA512_HASH_SIZE);
}
Beispiel #2
0
int
hmac_sha512 (const void *key, size_t keylen,
             const void *in, size_t inlen, void *resbuf)
{
  struct sha512_ctx inner;
  struct sha512_ctx outer;
  char optkeybuf[64];
  char block[128];
  char innerhash[64];

  /* Reduce the key's size, so that it becomes <= 128 bytes large.  */

  if (keylen > 128)
    {
      struct sha512_ctx keyhash;

      sha512_init_ctx (&keyhash);
      sha512_process_bytes (key, keylen, &keyhash);
      sha512_finish_ctx (&keyhash, optkeybuf);

      key = optkeybuf;
      keylen = 128;
    }

  /* Compute INNERHASH from KEY and IN.  */

  sha512_init_ctx (&inner);

  memset (block, IPAD, sizeof (block));
  memxor (block, key, keylen);

  sha512_process_block (block, 128, &inner);
  sha512_process_bytes (in, inlen, &inner);

  sha512_finish_ctx (&inner, innerhash);

  /* Compute result from KEY and INNERHASH.  */

  sha512_init_ctx (&outer);

  memset (block, OPAD, sizeof (block));
  memxor (block, key, keylen);

  sha512_process_block (block, 128, &outer);
  sha512_process_bytes (innerhash, 64, &outer);

  sha512_finish_ctx (&outer, resbuf);

  return 0;
}
Beispiel #3
0
/* Process the remaining bytes in the internal buffer and the usual
   prolog according to the standard and write the result to RESBUF.  */
static void
sha512_conclude_ctx (struct sha512_ctx *ctx)
{
    /* Take yet unprocessed bytes into account.  */
    size_t bytes = ctx->buflen;
    size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8;

    /* Now count remaining bytes.  */
    ctx->total[0] = u64plus (ctx->total[0], u64lo (bytes));
    if (u64lt (ctx->total[0], u64lo (bytes)))
        ctx->total[1] = u64plus (ctx->total[1], u64lo (1));

    /* Put the 128-bit file length in *bits* at the end of the buffer.
       Use set_uint64 rather than a simple assignment, to avoid risk of
       unaligned access.  */
    set_uint64 ((char *) &ctx->buffer[size - 2],
                SWAP (u64or (u64shl (ctx->total[1], 3),
                             u64shr (ctx->total[0], 61))));
    set_uint64 ((char *) &ctx->buffer[size - 1],
                SWAP (u64shl (ctx->total[0], 3)));

    memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 8 - bytes);

    /* Process last bytes.  */
    sha512_process_block (ctx->buffer, size * 8, ctx);
}
Beispiel #4
0
void sha512_final(HASH_ctx* ctx, const unsigned char* msg, size_t size)
{
    uint64_t message[SHA512_BLOCK_SIZE / 8];

    if (ctx->unprocessed_)
    {
        memcpy(message, msg + size - ctx->unprocessed_, static_cast<size_t>(ctx->unprocessed_));
    }

    uint32_t index = ((uint64_t)ctx->length_ & 127) >> 3;
    uint32_t shift = ((uint64_t)ctx->length_ & 7) * 8;

    message[index] &= ~(0xFFFFFFFFFFFFFFFFULL << shift);
    message[index++] ^= 0x80ULL << shift;

    if (index > 14)
    {
        while (index < 16)
        {
            message[index++] = 0;
        }

        sha512_process_block(ctx->SHA384_hash_, message);
        index = 0;
    }

    while (index < 14)
    {
        message[index++] = 0;
    }

    // length in bit = length in char * 8
    uint64_t data_len = (ctx->length_) << 3;
    data_len = SWAP_UINT64(data_len);

    // store the size, only consider data_len < 2^64, so message[14] is always 0
    message[14] = 0x0ULL;
    message[15] = data_len;

    sha512_process_block(ctx->SHA512_hash_, message);

    swap_uint64_memcpy(&ctx->SHA512_result, &ctx->SHA512_hash_, SHA512_HASH_SIZE);
}
Beispiel #5
0
void sha512_update_file(HASH_ctx* ctx, const unsigned char* buf, size_t bufsize)
{
    size_t i;
    for (i = 0; i < bufsize; i += SHA512_BLOCK_SIZE)
    {
        sha512_process_block(ctx->SHA512_hash_, reinterpret_cast<const uint64_t*>(buf));
        buf += SHA512_BLOCK_SIZE;
        ctx->SHA512_unprocessed_ -= SHA512_BLOCK_SIZE;
    }
    return;
}
Beispiel #6
0
void sha512_update(HASH_ctx* ctx, const unsigned char* buf, uint32_t size)
{
    ctx->length_ += size;

    while (size >= SHA512_BLOCK_SIZE)
    {
        sha512_process_block(ctx->SHA512_hash_, reinterpret_cast<const uint64_t*>(buf));
        buf += SHA512_BLOCK_SIZE;
        size -= SHA512_BLOCK_SIZE;
    }

    ctx->unprocessed_ = size;
}
Beispiel #7
0
void
sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
{
    /* When we already have some bits in our internal buffer concatenate
       both inputs first.  */
    if (ctx->buflen != 0)
    {
        size_t left_over = ctx->buflen;
        size_t add = 256 - left_over > len ? len : 256 - left_over;

        memcpy (&((char *) ctx->buffer)[left_over], buffer, add);
        ctx->buflen += add;

        if (ctx->buflen > 128)
        {
            sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);

            ctx->buflen &= 127;
            /* The regions in the following copy operation cannot overlap.  */
            memcpy (ctx->buffer,
                    &((char *) ctx->buffer)[(left_over + add) & ~127],
                    ctx->buflen);
        }

        buffer = (const char *) buffer + add;
        len -= add;
    }

    /* Process available complete blocks.  */
    if (len >= 128)
    {
#if !_STRING_ARCH_unaligned
# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (u64) != 0)
        if (UNALIGNED_P (buffer))
            while (len > 128)
            {
                sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx);
                buffer = (const char *) buffer + 128;
                len -= 128;
            }
        else
#endif
        {
            sha512_process_block (buffer, len & ~127, ctx);
            buffer = (const char *) buffer + (len & ~127);
            len &= 127;
        }
    }

    /* Move remaining bytes in internal buffer.  */
    if (len > 0)
    {
        size_t left_over = ctx->buflen;

        memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
        left_over += len;
        if (left_over >= 128)
        {
            sha512_process_block (ctx->buffer, 128, ctx);
            left_over -= 128;
            memcpy (ctx->buffer, &ctx->buffer[16], left_over);
        }
        ctx->buflen = left_over;
    }
}
Beispiel #8
0
/* FIXME: Avoid code duplication */
int
sha384_stream (FILE *stream, void *resblock)
{
    struct sha512_ctx ctx;
    size_t sum;

    char *buffer = (char *)malloc (BLOCKSIZE + 72);
    if (!buffer)
        return 1;

    /* Initialize the computation context.  */
    sha384_init_ctx (&ctx);

    /* Iterate over full file contents.  */
    while (1)
    {
        /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
           computation function processes the whole buffer so that with the
           next round of the loop another block can be read.  */
        size_t n;
        sum = 0;

        /* Read block.  Take care for partial reads.  */
        while (1)
        {
            n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);

            sum += n;

            if (sum == BLOCKSIZE)
                break;

            if (n == 0)
            {
                /* Check for the error flag IFF N == 0, so that we don't
                   exit the loop after a partial read due to e.g., EAGAIN
                   or EWOULDBLOCK.  */
                if (ferror (stream))
                {
                    free (buffer);
                    return 1;
                }
                goto process_partial_block;
            }

            /* We've read at least one byte, so ignore errors.  But always
               check for EOF, since feof may be true even though N > 0.
               Otherwise, we could end up calling fread after EOF.  */
            if (feof (stream))
                goto process_partial_block;
        }

        /* Process buffer with BLOCKSIZE bytes.  Note that
                          BLOCKSIZE % 128 == 0
         */
        sha512_process_block (buffer, BLOCKSIZE, &ctx);
    }

process_partial_block:
    ;

    /* Process any remaining bytes.  */
    if (sum > 0)
        sha512_process_bytes (buffer, sum, &ctx);

    /* Construct result in desired memory.  */
    sha384_finish_ctx (&ctx, resblock);
    free (buffer);
    return 0;
}