Here is an implementation I've written myself, so no license issues.

  OG.


On Fri, Dec 12, 2014 at 10:48 AM, Jose Fonseca <jfons...@vmware.com> wrote:
> On 11/12/14 22:02, Brian Paul wrote:
>>
>> On 12/11/2014 02:51 PM, Carl Worth wrote:
>>>
>>> From: Kristian Høgsberg <k...@bitplanet.net>
>>>
>>> The upcoming shader cache uses the SHA-1 algorithm for cryptographic
>>> naming. These new mesa_sha1 functions are implemented with the nettle
>>> library.
>>> ---
>>>
>>> This patch is another in support of my upcoming shader-cache work.
>>> Thanks to
>>> Kritian for coding this piece.
>>>
>>> As currently written, this patch introduces a new dependency of Mesa
>>> on the
>>> Nettle library to implement SHA-1. I'm open to recommendations if
>>> people would prefer some other option.
>>>
>>> For example, the xserver can be configured to get a SHA-1
>>> implementation from
>>> libmd, libc, CommonCrypto, CryptoAPI, libnettle, libgcrypt, libsha1, or
>>> openssl.
>>>
>>> I don't know if it's important to offer as many options as that, which
>>> is why
>>> I'm asking for opinions here.
>>
>>
>>
>> We'll need a solution for Windows too.  I don't have time right now to
>> do any research into that.
>
>
> Yes, ideally we'd have something small that we could bundle into mesa source
> tree, for sake of non Linux OSes.
>
> If Windows was the only concern, we could use its Crypto API,
> http://msdn.microsoft.com/en-us/library/windows/desktop/aa382379.aspx and
> avoid depending on anything else, but some of the above mention libraries
> are not trivial to install.
>
> The other alternative is to disable shader cache when no suitable dependency
> is found. That is, make this an optional dependency.
>
> Jose
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
/*
 * Copyright © 2014 Olivier Galibert & Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdlib.h>
#include <string.h>

#include "sha1.h"

static inline unsigned int mesa_sha1_shift(unsigned int val, int count)
{
    return (val << count) | (val >> (32-count));
}

static void mesa_sha1_init(struct mesa_sha1 *ctx)
{
    ctx->digest[0] = 0x67452301;
    ctx->digest[1] = 0xefcdab89;
    ctx->digest[2] = 0x98badcfe;
    ctx->digest[3] = 0x10325476;
    ctx->digest[4] = 0xc3d2e1f0;
    ctx->msize = 0;
}

static void mesa_sha1_handle_block(struct mesa_sha1 *ctx, const unsigned char *b)
{
    unsigned int W[80];
    for(int i=0; i != 16; i++)
        W[i] = (b[4*i] << 24) | (b[4*i+1] << 16) | (b[4*i+2] << 8) | b[4*i+3];
    for(int i=16; i != 80; i++)
        W[i] = mesa_sha1_shift(W[i-3]^W[i-8]^W[i-14]^W[i-16], 1);

    unsigned int A = ctx->digest[0];
    unsigned int B = ctx->digest[1];
    unsigned int C = ctx->digest[2];
    unsigned int D = ctx->digest[3];
    unsigned int E = ctx->digest[4];

    for(int i= 0; i != 20; i++) {
        unsigned int T = mesa_sha1_shift(A, 5) + ((B & C) | ((~B) & D))        + E + W[i] + 0x5A827999;
        E = D;
        D = C;
        C = mesa_sha1_shift(B, 30);
        B = A;
        A = T;
    }

    for(int i=20; i != 40; i++) {
        unsigned int T = mesa_sha1_shift(A, 5) + (B^C^D)                       + E + W[i] + 0x6ed9eba1;
        E = D;
        D = C;
        C = mesa_sha1_shift(B, 30);
        B = A;
        A = T;
    }

    for(int i=40; i != 60; i++) {
        unsigned int T = mesa_sha1_shift(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8f1bbcdc;
        E = D;
        D = C;
        C = mesa_sha1_shift(B, 30);
        B = A;
        A = T;
    }

    for(int i=60; i != 80; i++) {
        unsigned int T = mesa_sha1_shift(A, 5) + (B^C^D)                       + E + W[i] + 0xca62c1d6;
        E = D;
        D = C;
        C = mesa_sha1_shift(B, 30);
        B = A;
        A = T;
    }

    ctx->digest[0] += A;
    ctx->digest[1] += B;
    ctx->digest[2] += C;
    ctx->digest[3] += D;
    ctx->digest[4] += E;
}

void
mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
{
    unsigned int offset = ctx->msize & 63;
    ctx->block[offset] = 0x80;
    memset(ctx->block+offset+1, 0, 64-offset-1);
    if(offset > 55) {
        mesa_sha1_handle_block(ctx, ctx->block);
        memset(ctx->block, 0, 64);
    }

    ctx->block[59] = ctx->msize >> 29;
    ctx->block[60] = ctx->msize >> 21;
    ctx->block[61] = ctx->msize >> 13;
    ctx->block[62] = ctx->msize >> 5;
    ctx->block[63] = ctx->msize << 3;
    mesa_sha1_handle_block(ctx, ctx->block);

    for(int i=0; i<20; i++)
        result[i] = ctx->digest[i >> 2] >> (28 - 8*(i & 3));
}

struct mesa_sha1 *
_mesa_sha1_init(void)
{
    struct mesa_sha1 *ctx = (struct mesa_sha1 *)malloc(sizeof(*ctx));

    if (!ctx)
        return NULL;

    mesa_sha1_init(ctx);

    return ctx;
}

int
_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
{
    const unsigned char *pdata = (const unsigned char *)data;
    unsigned int offset = ctx->msize & 63;
    ctx->msize += size;
    if(offset) {
        if(offset+size >= 64) {
            memcpy(ctx->block+offset, pdata, 64-offset);
            mesa_sha1_handle_block(ctx, ctx->block);
            pdata += offset;
            size -= offset;
        }
    }
    while(size >= 64) {
        mesa_sha1_handle_block(ctx, pdata);
        pdata += 64;
        size -= 64;
    }
    if(size)
        memcpy(ctx->block, pdata, size);

   return 1;
}

int
_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
{
    mesa_sha1_final(ctx, result);

    free(ctx);

    return 1;
}

void
_mesa_sha1_compute(const void *data, size_t size, unsigned char result[20])
{
   struct mesa_sha1 ctx;

   mesa_sha1_init(&ctx);
   _mesa_sha1_update(&ctx, data, size);
   mesa_sha1_final(&ctx, result);
}

char *
_mesa_sha1_format(char *buf, const unsigned char *sha1)
{
   static const char hex_digits[] = "0123456789abcdef";
   int i;

   for (i = 0; i < 40; i += 2) {
      buf[i] = hex_digits[sha1[i >> 1] >> 4];
      buf[i + 1] = hex_digits[sha1[i >> 1] & 0x0f];
   }
   buf[i] = '\0';

   return buf;
}
#ifndef SHA1_H
#define SHA1_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>

struct mesa_sha1 {
    unsigned char block[64];
    unsigned int digest[5];
    unsigned int msize;
};

struct mesa_sha1 *_mesa_sha1_init(void);
int _mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size);
int _mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20]);
char *_mesa_sha1_format(char *buf, const unsigned char *sha1);
void _mesa_sha1_compute(const void *data, size_t size, unsigned char result[20]);

#ifdef __cplusplus
} /* extern C */
#endif

#endif
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to