210 lines
6.6 KiB
C
210 lines
6.6 KiB
C
//
|
|
// --------------------------------------------------------------------------
|
|
// Gurux Ltd
|
|
//
|
|
//
|
|
//
|
|
// Filename: $HeadURL$
|
|
//
|
|
// Version: $Revision$,
|
|
// $Date$
|
|
// $Author$
|
|
//
|
|
// Copyright (c) Gurux Ltd
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This file is a part of Gurux Device Framework.
|
|
//
|
|
// Gurux Device Framework is Open Source 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.
|
|
// Gurux Device Framework 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.
|
|
//
|
|
// This code is licensed under the GNU General Public License v2.
|
|
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "gxignore.h"
|
|
#ifndef DLMS_IGNORE_HIGH_SHA1
|
|
#include <string.h>
|
|
#include "gxsha1.h"
|
|
|
|
#define SHA1_ROL(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits))))
|
|
#define SHA1_BLK(i) (block[i&15] = SHA1_ROL(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15],1))
|
|
|
|
#define SHA1_R0(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
|
|
#define SHA1_R1(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + SHA1_BLK(i) + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
|
|
#define SHA1_R2(v,w,x,y,z,i) z += (w ^ x ^ y) + SHA1_BLK(i) + 0x6ed9eba1 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
|
|
#define SHA1_R3(v,w,x,y,z,i) z += (((w | x) & y) | ( w & x)) + SHA1_BLK(i) + 0x8f1bbcdc + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
|
|
#define SHA1_R4(v,w,x,y,z,i) z += (w ^ x ^ y) + SHA1_BLK(i) + 0xca62c1d6 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
|
|
|
|
/*
|
|
* Hash block is a single 512-bit block.
|
|
*/
|
|
void gxsha1_transform(uint32_t* block, uint32_t* digest, uint32_t* transforms)
|
|
{
|
|
uint32_t a = digest[0];
|
|
uint32_t b = digest[1];
|
|
uint32_t c = digest[2];
|
|
uint32_t d = digest[3];
|
|
uint32_t e = digest[4];
|
|
|
|
SHA1_R0(a, b, c, d, e, 0);
|
|
SHA1_R0(e, a, b, c, d, 1);
|
|
SHA1_R0(d, e, a, b, c, 2);
|
|
SHA1_R0(c, d, e, a, b, 3);
|
|
SHA1_R0(b, c, d, e, a, 4);
|
|
SHA1_R0(a, b, c, d, e, 5);
|
|
SHA1_R0(e, a, b, c, d, 6);
|
|
SHA1_R0(d, e, a, b, c, 7);
|
|
SHA1_R0(c, d, e, a, b, 8);
|
|
SHA1_R0(b, c, d, e, a, 9);
|
|
SHA1_R0(a, b, c, d, e, 10);
|
|
SHA1_R0(e, a, b, c, d, 11);
|
|
SHA1_R0(d, e, a, b, c, 12);
|
|
SHA1_R0(c, d, e, a, b, 13);
|
|
SHA1_R0(b, c, d, e, a, 14);
|
|
SHA1_R0(a, b, c, d, e, 15);
|
|
SHA1_R1(e, a, b, c, d, 16);
|
|
SHA1_R1(d, e, a, b, c, 17);
|
|
SHA1_R1(c, d, e, a, b, 18);
|
|
SHA1_R1(b, c, d, e, a, 19);
|
|
SHA1_R2(a, b, c, d, e, 20);
|
|
SHA1_R2(e, a, b, c, d, 21);
|
|
SHA1_R2(d, e, a, b, c, 22);
|
|
SHA1_R2(c, d, e, a, b, 23);
|
|
SHA1_R2(b, c, d, e, a, 24);
|
|
SHA1_R2(a, b, c, d, e, 25);
|
|
SHA1_R2(e, a, b, c, d, 26);
|
|
SHA1_R2(d, e, a, b, c, 27);
|
|
SHA1_R2(c, d, e, a, b, 28);
|
|
SHA1_R2(b, c, d, e, a, 29);
|
|
SHA1_R2(a, b, c, d, e, 30);
|
|
SHA1_R2(e, a, b, c, d, 31);
|
|
SHA1_R2(d, e, a, b, c, 32);
|
|
SHA1_R2(c, d, e, a, b, 33);
|
|
SHA1_R2(b, c, d, e, a, 34);
|
|
SHA1_R2(a, b, c, d, e, 35);
|
|
SHA1_R2(e, a, b, c, d, 36);
|
|
SHA1_R2(d, e, a, b, c, 37);
|
|
SHA1_R2(c, d, e, a, b, 38);
|
|
SHA1_R2(b, c, d, e, a, 39);
|
|
SHA1_R3(a, b, c, d, e, 40);
|
|
SHA1_R3(e, a, b, c, d, 41);
|
|
SHA1_R3(d, e, a, b, c, 42);
|
|
SHA1_R3(c, d, e, a, b, 43);
|
|
SHA1_R3(b, c, d, e, a, 44);
|
|
SHA1_R3(a, b, c, d, e, 45);
|
|
SHA1_R3(e, a, b, c, d, 46);
|
|
SHA1_R3(d, e, a, b, c, 47);
|
|
SHA1_R3(c, d, e, a, b, 48);
|
|
SHA1_R3(b, c, d, e, a, 49);
|
|
SHA1_R3(a, b, c, d, e, 50);
|
|
SHA1_R3(e, a, b, c, d, 51);
|
|
SHA1_R3(d, e, a, b, c, 52);
|
|
SHA1_R3(c, d, e, a, b, 53);
|
|
SHA1_R3(b, c, d, e, a, 54);
|
|
SHA1_R3(a, b, c, d, e, 55);
|
|
SHA1_R3(e, a, b, c, d, 56);
|
|
SHA1_R3(d, e, a, b, c, 57);
|
|
SHA1_R3(c, d, e, a, b, 58);
|
|
SHA1_R3(b, c, d, e, a, 59);
|
|
SHA1_R4(a, b, c, d, e, 60);
|
|
SHA1_R4(e, a, b, c, d, 61);
|
|
SHA1_R4(d, e, a, b, c, 62);
|
|
SHA1_R4(c, d, e, a, b, 63);
|
|
SHA1_R4(b, c, d, e, a, 64);
|
|
SHA1_R4(a, b, c, d, e, 65);
|
|
SHA1_R4(e, a, b, c, d, 66);
|
|
SHA1_R4(d, e, a, b, c, 67);
|
|
SHA1_R4(c, d, e, a, b, 68);
|
|
SHA1_R4(b, c, d, e, a, 69);
|
|
SHA1_R4(a, b, c, d, e, 70);
|
|
SHA1_R4(e, a, b, c, d, 71);
|
|
SHA1_R4(d, e, a, b, c, 72);
|
|
SHA1_R4(c, d, e, a, b, 73);
|
|
SHA1_R4(b, c, d, e, a, 74);
|
|
SHA1_R4(a, b, c, d, e, 75);
|
|
SHA1_R4(e, a, b, c, d, 76);
|
|
SHA1_R4(d, e, a, b, c, 77);
|
|
SHA1_R4(c, d, e, a, b, 78);
|
|
SHA1_R4(b, c, d, e, a, 79);
|
|
|
|
digest[0] += a;
|
|
digest[1] += b;
|
|
digest[2] += c;
|
|
digest[3] += d;
|
|
digest[4] += e;
|
|
|
|
++* transforms;
|
|
}
|
|
|
|
void gxsha1_update(gxByteBuffer* data, uint32_t* digest, uint32_t* transforms)
|
|
{
|
|
unsigned int pos;
|
|
uint32_t block[16];
|
|
while (data->size - data->position > 64)
|
|
{
|
|
for (pos = 0; pos != 16; ++pos)
|
|
{
|
|
bb_getUInt32(data, &block[pos]);
|
|
}
|
|
gxsha1_transform(block, digest, transforms);
|
|
}
|
|
}
|
|
|
|
int gxsha1_final(gxByteBuffer* data, uint32_t* digest, uint32_t* transforms, gxByteBuffer* reply)
|
|
{
|
|
int pos;
|
|
bb_capacity(reply, (uint16_t) *transforms * 64);
|
|
bb_set(reply, data->data, data->size);
|
|
/* Total number of hashed bits */
|
|
uint64_t total_bits = (*transforms * 64 + data->size) * 8;
|
|
|
|
/* Padding */
|
|
bb_setUInt8(reply, 0x80);
|
|
uint32_t orig_size = reply->size;
|
|
bb_zero(reply, reply->size, 64 - reply->size);
|
|
uint32_t block[16];
|
|
for (pos = 0; pos != 16; ++pos)
|
|
{
|
|
bb_getUInt32(reply, &block[pos]);
|
|
}
|
|
if (orig_size > 64 - 8)
|
|
{
|
|
gxsha1_transform(block, digest, transforms);
|
|
for (pos = 0; pos < 16 - 2; ++pos)
|
|
{
|
|
block[pos] = 0;
|
|
}
|
|
}
|
|
|
|
/* Append total_bits, split this uint64 into two uint32 */
|
|
block[16 - 1] = (uint32_t)total_bits;
|
|
block[16 - 2] = (uint32_t)(total_bits >> 32);
|
|
gxsha1_transform(block, digest, transforms);
|
|
bb_capacity(reply, 20);
|
|
reply->position = reply->size = 0;
|
|
for (pos = 0; pos < 5; ++pos)
|
|
{
|
|
bb_setUInt32(reply, digest[pos]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int gxsha1_encrypt(gxByteBuffer* data, gxByteBuffer* result)
|
|
{
|
|
uint32_t digest[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
|
|
uint32_t transforms = 0;
|
|
gxsha1_update(data, digest, &transforms);
|
|
return gxsha1_final(data, digest, &transforms, result);
|
|
}
|
|
|
|
#endif //DLMS_IGNORE_HIGH_SHA1
|