Skip to content

Commit 14d7ca6

Browse files
committed
add sha256 generation func to opal util toolbox
Looks like there may be at least one place in ompi where being able to compute a sha of a user supplied string plus internally generated data could be useful, so add function to do this to the opal util toolbox. Related to #10895 This code is derived from a sha256 implementation at https://github.com/B-Con/crypto-algorithms.git Signed-off-by: Howard Pritchard <[email protected]>
1 parent 710ff57 commit 14d7ca6

File tree

6 files changed

+305
-2
lines changed

6 files changed

+305
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ test/util/opal_path_nfs
516516
test/util/opal_path_nfs.out
517517
test/util/opal_bit_ops
518518
test/util/bipartite_graph
519+
test/util/opal_sha256
519520

520521
opal/test/reachable/reachable_netlink
521522
opal/test/reachable/reachable_weighted

opal/util/Makefile.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ headers = \
8080
uri.h \
8181
info_subscriber.h \
8282
info.h \
83-
minmax.h
83+
minmax.h \
84+
sha256.h
8485

8586
libopalutil_la_SOURCES = \
8687
$(headers) \
@@ -115,6 +116,7 @@ libopalutil_core_la_SOURCES = \
115116
printf.c \
116117
proc.c \
117118
qsort.c \
119+
sha256.c \
118120
show_help.c \
119121
show_help_lex.l \
120122
stacktrace.c \

opal/util/sha256.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2+
/*
3+
* Copyright (c) 2022 Triad National Security, LLC. All rights
4+
* reserved.
5+
*
6+
* Additional copyrights may follow
7+
*
8+
* $HEADER$
9+
*/
10+
11+
12+
/*********************************************************************
13+
* Filename: sha256.c
14+
* Author: Brad Conte (brad AT bradconte.com)
15+
* Copyright:
16+
* Disclaimer: This code is presented "as is" without any guarantees.
17+
* Details: Implementation of the SHA-256 hashing algorithm.
18+
SHA-256 is one of the three algorithms in the SHA2
19+
specification. The others, SHA-384 and SHA-512, are not
20+
offered in this implementation.
21+
Algorithm specification can be found here:
22+
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
23+
This implementation uses little endian byte order.
24+
See https://github.com/B-Con/crypto-algorithms
25+
*********************************************************************/
26+
27+
/*************************** HEADER FILES ***************************/
28+
#include <stdlib.h>
29+
#include <memory.h>
30+
#include "sha256.h"
31+
32+
/****************************** MACROS ******************************/
33+
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
34+
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
35+
36+
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
37+
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
38+
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
39+
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
40+
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
41+
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
42+
43+
/**************************** VARIABLES *****************************/
44+
static const WORD k[64] = {
45+
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
46+
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
47+
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
48+
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
49+
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
50+
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
51+
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
52+
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
53+
};
54+
55+
/*********************** FUNCTION DEFINITIONS ***********************/
56+
static void sha256_transform(opal_sha256_ctx *ctx, const BYTE data[])
57+
{
58+
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
59+
60+
for (i = 0, j = 0; i < 16; ++i, j += 4)
61+
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
62+
for ( ; i < 64; ++i)
63+
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
64+
65+
a = ctx->state[0];
66+
b = ctx->state[1];
67+
c = ctx->state[2];
68+
d = ctx->state[3];
69+
e = ctx->state[4];
70+
f = ctx->state[5];
71+
g = ctx->state[6];
72+
h = ctx->state[7];
73+
74+
for (i = 0; i < 64; ++i) {
75+
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
76+
t2 = EP0(a) + MAJ(a,b,c);
77+
h = g;
78+
g = f;
79+
f = e;
80+
e = d + t1;
81+
d = c;
82+
c = b;
83+
b = a;
84+
a = t1 + t2;
85+
}
86+
87+
ctx->state[0] += a;
88+
ctx->state[1] += b;
89+
ctx->state[2] += c;
90+
ctx->state[3] += d;
91+
ctx->state[4] += e;
92+
ctx->state[5] += f;
93+
ctx->state[6] += g;
94+
ctx->state[7] += h;
95+
}
96+
97+
void opal_sha256_init(opal_sha256_ctx *ctx)
98+
{
99+
ctx->datalen = 0;
100+
ctx->bitlen = 0;
101+
ctx->state[0] = 0x6a09e667;
102+
ctx->state[1] = 0xbb67ae85;
103+
ctx->state[2] = 0x3c6ef372;
104+
ctx->state[3] = 0xa54ff53a;
105+
ctx->state[4] = 0x510e527f;
106+
ctx->state[5] = 0x9b05688c;
107+
ctx->state[6] = 0x1f83d9ab;
108+
ctx->state[7] = 0x5be0cd19;
109+
}
110+
111+
void opal_sha256_update(opal_sha256_ctx *ctx, const BYTE data[], size_t len)
112+
{
113+
WORD i;
114+
115+
for (i = 0; i < len; ++i) {
116+
ctx->data[ctx->datalen] = data[i];
117+
ctx->datalen++;
118+
if (ctx->datalen == 64) {
119+
sha256_transform(ctx, ctx->data);
120+
ctx->bitlen += 512;
121+
ctx->datalen = 0;
122+
}
123+
}
124+
}
125+
126+
void opal_sha256_final(opal_sha256_ctx *ctx, BYTE hash[])
127+
{
128+
WORD i;
129+
130+
i = ctx->datalen;
131+
132+
// Pad whatever data is left in the buffer.
133+
if (ctx->datalen < 56) {
134+
ctx->data[i++] = 0x80;
135+
while (i < 56)
136+
ctx->data[i++] = 0x00;
137+
}
138+
else {
139+
ctx->data[i++] = 0x80;
140+
while (i < 64)
141+
ctx->data[i++] = 0x00;
142+
sha256_transform(ctx, ctx->data);
143+
memset(ctx->data, 0, 56);
144+
}
145+
146+
// Append to the padding the total message's length in bits and transform.
147+
ctx->bitlen += ctx->datalen * 8;
148+
ctx->data[63] = ctx->bitlen;
149+
ctx->data[62] = ctx->bitlen >> 8;
150+
ctx->data[61] = ctx->bitlen >> 16;
151+
ctx->data[60] = ctx->bitlen >> 24;
152+
ctx->data[59] = ctx->bitlen >> 32;
153+
ctx->data[58] = ctx->bitlen >> 40;
154+
ctx->data[57] = ctx->bitlen >> 48;
155+
ctx->data[56] = ctx->bitlen >> 56;
156+
sha256_transform(ctx, ctx->data);
157+
158+
// Since this implementation uses little endian byte ordering and SHA uses big endian,
159+
// reverse all the bytes when copying the final state to the output hash.
160+
for (i = 0; i < 4; ++i) {
161+
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
162+
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
163+
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
164+
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
165+
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
166+
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
167+
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
168+
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
169+
}
170+
}

opal/util/sha256.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2+
/*
3+
* Copyright (c) 2022 Triad National Security, LLC. All rights
4+
* reserved.
5+
*
6+
* Additional copyrights may follow
7+
*
8+
* $HEADER$
9+
*/
10+
11+
/*********************************************************************
12+
* Filename: sha256.h
13+
* Author: Brad Conte (brad AT bradconte.com)
14+
* Copyright:
15+
* Disclaimer: This code is presented "as is" without any guarantees.
16+
* Details: Defines the API for the corresponding SHA1 implementation.
17+
* Notes: see https://github.com/B-Con/crypto-algorithms
18+
*********************************************************************/
19+
20+
#ifndef OPAL_SHA256_H
21+
#define OPAL_SHA256_H
22+
23+
/*************************** HEADER FILES ***************************/
24+
#include <stddef.h>
25+
26+
/****************************** MACROS ******************************/
27+
#define OPAL_SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
28+
29+
/**************************** DATA TYPES ****************************/
30+
typedef unsigned char BYTE; // 8-bit byte
31+
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
32+
33+
typedef struct {
34+
BYTE data[64];
35+
WORD datalen;
36+
unsigned long long bitlen;
37+
WORD state[8];
38+
} opal_sha256_ctx;
39+
40+
/*********************** FUNCTION DECLARATIONS **********************/
41+
void opal_sha256_init(opal_sha256_ctx *ctx);
42+
void opal_sha256_update(opal_sha256_ctx *ctx, const BYTE data[], size_t len);
43+
void opal_sha256_final(opal_sha256_ctx *ctx, BYTE hash[]);
44+
45+
#endif // OPAL_SHA256_H

test/util/Makefile.am

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/test/support
3939
check_PROGRAMS = \
4040
opal_bit_ops \
4141
opal_path_nfs \
42-
bipartite_graph
42+
bipartite_graph \
43+
opal_sha256
4344

4445
TESTS = \
4546
$(check_PROGRAMS)
@@ -128,6 +129,12 @@ bipartite_graph_LDADD = \
128129
$(top_builddir)/test/support/libsupport.a
129130
bipartite_graph_DEPENDENCIES = $(bipartite_graph_LDADD)
130131

132+
opal_sha256_SOURCES = opal_sha256.c
133+
opal_sha256_LDADD = \
134+
$(top_builddir)/opal/lib@[email protected] \
135+
$(top_builddir)/test/support/libsupport.a
136+
opal_sha256_DEPENDENCIES = $(opal_sha256_LDADD)
137+
131138
clean-local:
132139
rm -f test_session_dir_out test-file opal_path_nfs.out
133140

test/util/opal_sha256.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2+
/*
3+
* Copyright (c) 2022 Triad National Security, LLC. All rights
4+
* reserved.
5+
*
6+
* Additional copyrights may follow
7+
*
8+
* $HEADER$
9+
*/
10+
11+
/*********************************************************************
12+
* Filename: sha256.c
13+
* Author: Brad Conte (brad AT bradconte.com)
14+
* Copyright:
15+
* Disclaimer: This code is presented "as is" without any guarantees.
16+
* Details: Performs known-answer tests on the corresponding SHA1
17+
implementation. These tests do not encompass the full
18+
range of available test vectors, however, if the tests
19+
pass it is very, very likely that the code is correct
20+
and was compiled properly. This code also serves as
21+
example usage of the functions.
22+
*********************************************************************/
23+
24+
/*************************** HEADER FILES ***************************/
25+
#include <stdio.h>
26+
#include <memory.h>
27+
#include <string.h>
28+
#include "support.h"
29+
#include "opal/util/sha256.h"
30+
31+
/*********************** FUNCTION DEFINITIONS ***********************/
32+
static int sha256_test(void)
33+
{
34+
BYTE text1[] = {"abc"};
35+
BYTE text2[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
36+
BYTE text3[] = {"aaaaaaaaaa"};
37+
BYTE hash1[OPAL_SHA256_BLOCK_SIZE] = {0xba,0x78,0x16,0xbf,0x8f,0x01,0xcf,0xea,0x41,0x41,0x40,0xde,0x5d,0xae,0x22,0x23,
38+
0xb0,0x03,0x61,0xa3,0x96,0x17,0x7a,0x9c,0xb4,0x10,0xff,0x61,0xf2,0x00,0x15,0xad};
39+
BYTE hash2[OPAL_SHA256_BLOCK_SIZE] = {0x24,0x8d,0x6a,0x61,0xd2,0x06,0x38,0xb8,0xe5,0xc0,0x26,0x93,0x0c,0x3e,0x60,0x39,
40+
0xa3,0x3c,0xe4,0x59,0x64,0xff,0x21,0x67,0xf6,0xec,0xed,0xd4,0x19,0xdb,0x06,0xc1};
41+
BYTE hash3[OPAL_SHA256_BLOCK_SIZE] = {0xcd,0xc7,0x6e,0x5c,0x99,0x14,0xfb,0x92,0x81,0xa1,0xc7,0xe2,0x84,0xd7,0x3e,0x67,
42+
0xf1,0x80,0x9a,0x48,0xa4,0x97,0x20,0x0e,0x04,0x6d,0x39,0xcc,0xc7,0x11,0x2c,0xd0};
43+
BYTE buf[OPAL_SHA256_BLOCK_SIZE];
44+
opal_sha256_ctx ctx;
45+
int idx;
46+
int pass = 1;
47+
48+
opal_sha256_init(&ctx);
49+
opal_sha256_update(&ctx, text1, strlen((const char *)text1));
50+
opal_sha256_final(&ctx, buf);
51+
pass = pass && !memcmp(hash1, buf, OPAL_SHA256_BLOCK_SIZE);
52+
53+
opal_sha256_init(&ctx);
54+
opal_sha256_update(&ctx, text2, strlen((const char *)text2));
55+
opal_sha256_final(&ctx, buf);
56+
pass = pass && !memcmp(hash2, buf, OPAL_SHA256_BLOCK_SIZE);
57+
58+
opal_sha256_init(&ctx);
59+
for (idx = 0; idx < 100000; ++idx)
60+
opal_sha256_update(&ctx, text3, strlen((const char *)text3));
61+
opal_sha256_final(&ctx, buf);
62+
pass = pass && !memcmp(hash3, buf, OPAL_SHA256_BLOCK_SIZE);
63+
64+
return pass;
65+
}
66+
67+
int main(void)
68+
{
69+
test_init("sha256 test");
70+
71+
if (sha256_test()) {
72+
test_success();
73+
} else {
74+
test_failure("sh256 test failed");
75+
}
76+
77+
return test_finalize();
78+
}

0 commit comments

Comments
 (0)