├── Makefile
├── README.md
├── sha256-armv8-aarch32.S
├── sha256-armv8-aarch64.S
└── sha256.c
/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | CFLAGS = -O3 -mcpu=generic+crypto
3 | sha256:sha256.c
4 | $(CC) $(CFLAGS) sha256.c sha256-armv8-aarch64.S -o sha256
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SHA-256
2 |
3 | This is a very basic implementation of a SHA-256 hash according to the [FIPS
4 | 180-4 standard](http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf)
5 | in C. I did it for educational purposes, the code is not optimized at all, but
6 | (almost) corresponds line by line to the standard.
7 |
8 | The algorithm to process a small block of data is quite simple and very well
9 | described in the standard. I found that correctly implementing the padding is
10 | much harder.
11 |
12 | It does not have any dependencies (except for the C standard library of course)
13 | and can be compiled with `make`. When `sha256sum` is installed, a short test can
14 | be run with `make test`.
15 |
16 | Usage:
17 |
18 | ```
19 | ./main
20 | ```
21 |
--------------------------------------------------------------------------------
/sha256-armv8-aarch32.S:
--------------------------------------------------------------------------------
1 |
2 | .text
3 | .code 32
4 |
5 | # SHA256 assembly implementation for ARMv8 AArch32
6 |
7 | .global sha256_block_data_order
8 | .type sha256_block_data_order,%function
9 | .align 2
10 | sha256_block_data_order:
11 |
12 | .Lsha256prolog:
13 |
14 | vpush {q4}
15 | vldmia r0, {s0, s1, s2, s3, s4, s5, s6, s7}
16 | add r2, r1, r2, lsl #6
17 |
18 | .Lsha256loop:
19 |
20 | vld1.32 {d16-d19}, [r1]!
21 | adr r3, .LKConstant256
22 | vmov q2, q0
23 | vmov q3, q1
24 | vld1.32 {d20-d23}, [r1]!
25 |
26 | vrev32.8 q8, q8
27 | vldmia r3!, {d24, d25}
28 | vrev32.8 q9, q9
29 | vrev32.8 q10, q10
30 | vldmia r3!, {d26, d27}
31 | vadd.i32 q12, q8, q12
32 | sha256su0.32 q8, q9
33 | vrev32.8 q11, q11
34 | vldmia r3!, {d28, d29}
35 | vadd.i32 q13, q9, q13
36 | vmov q4, q2
37 | sha256h.32 q2, q3, q12
38 | sha256h2.32 q3, q4, q12
39 | sha256su0.32 q9, q10
40 | sha256su1.32 q8, q10, q11
41 | vldmia r3!, {d30, d31}
42 | vadd.i32 q14, q10, q14
43 | vmov q4, q2
44 | sha256h.32 q2, q3, q13
45 | sha256h2.32 q3, q4, q13
46 | sha256su0.32 q10, q11
47 | sha256su1.32 q9, q11, q8
48 | vldmia r3!, {d24, d25}
49 | vadd.i32 q15, q11, q15
50 | vmov q4, q2
51 | sha256h.32 q2, q3, q14
52 | sha256h2.32 q3, q4, q14
53 | sha256su0.32 q11, q8
54 | sha256su1.32 q10, q8, q9
55 | vldmia r3!, {d26, d27}
56 | vadd.i32 q12, q8, q12
57 | vmov q4, q2
58 | sha256h.32 q2, q3, q15
59 | sha256h2.32 q3, q4, q15
60 | sha256su0.32 q8, q9
61 | sha256su1.32 q11, q9, q10
62 | vldmia r3!, {d28, d29}
63 | vadd.i32 q13, q9, q13
64 | vmov q4, q2
65 | sha256h.32 q2, q3, q12
66 | sha256h2.32 q3, q4, q12
67 | sha256su0.32 q9, q10
68 | sha256su1.32 q8, q10, q11
69 | vldmia r3!, {d30, d31}
70 | vadd.i32 q14, q10, q14
71 | vmov q4, q2
72 | sha256h.32 q2, q3, q13
73 | sha256h2.32 q3, q4, q13
74 | sha256su0.32 q10, q11
75 | sha256su1.32 q9, q11, q8
76 | vldmia r3!, {d24, d25}
77 | vadd.i32 q15, q11, q15
78 | vmov q4, q2
79 | sha256h.32 q2, q3, q14
80 | sha256h2.32 q3, q4, q14
81 | sha256su0.32 q11, q8
82 | sha256su1.32 q10, q8, q9
83 | vldmia r3!, {d26, d27}
84 | vadd.i32 q12, q8, q12
85 | vmov q4, q2
86 | sha256h.32 q2, q3, q15
87 | sha256h2.32 q3, q4, q15
88 | sha256su0.32 q8, q9
89 | sha256su1.32 q11, q9, q10
90 | vldmia r3!, {d28, d29}
91 | vadd.i32 q13, q9, q13
92 | vmov q4, q2
93 | sha256h.32 q2, q3, q12
94 | sha256h2.32 q3, q4, q12
95 | sha256su0.32 q9, q10
96 | sha256su1.32 q8, q10, q11
97 | vldmia r3!, {d30, d31}
98 | vadd.i32 q14, q10, q14
99 | vmov q4, q2
100 | sha256h.32 q2, q3, q13
101 | sha256h2.32 q3, q4, q13
102 | sha256su0.32 q10, q11
103 | sha256su1.32 q9, q11, q8
104 | vldmia r3!, {d24, d25}
105 | vadd.i32 q15, q11, q15
106 | vmov q4, q2
107 | sha256h.32 q2, q3, q14
108 | sha256h2.32 q3, q4, q14
109 | sha256su0.32 q11, q8
110 | sha256su1.32 q10, q8, q9
111 | vldmia r3!, {d26, d27}
112 | vadd.i32 q12, q8, q12
113 | vmov q4, q2
114 | sha256h.32 q2, q3, q15
115 | sha256h2.32 q3, q4, q15
116 | sha256su1.32 q11, q9, q10
117 | vldmia r3!, {d28, d29}
118 | vadd.i32 q13, q9, q13
119 | vmov q4, q2
120 | sha256h.32 q2, q3, q12
121 | sha256h2.32 q3, q4, q12
122 | vldmia r3!, {d30, d31}
123 | vadd.i32 q14, q10, q14
124 | vmov q4, q2
125 | sha256h.32 q2, q3, q13
126 | sha256h2.32 q3, q4, q13
127 | vadd.i32 q15, q11, q15
128 | vmov q4, q2
129 | sha256h.32 q2, q3, q14
130 | sha256h2.32 q3, q4, q14
131 | vmov q4, q2
132 | sha256h.32 q2, q3, q15
133 | sha256h2.32 q3, q4, q15
134 | teq r1, r2
135 | vadd.i32 q0, q0, q2
136 | vadd.i32 q1, q1, q3
137 | bne .Lsha256loop
138 |
139 | .Lsha256epilog:
140 |
141 | vstmia r0, {s0, s1, s2, s3, s4, s5, s6, s7}
142 | vpop {q4}
143 | bx lr
144 |
145 | .align 5
146 | .LKConstant256:
147 | .word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
148 | .word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
149 | .word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
150 | .word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
151 | .word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
152 | .word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
153 | .word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
154 | .word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
155 | .word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
156 | .word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
157 | .word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
158 | .word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
159 | .word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
160 | .word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
161 | .word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
162 | .word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
163 |
164 | .size sha256_block_data_order,.-sha256_block_data_order
165 | .align 2
166 |
167 |
--------------------------------------------------------------------------------
/sha256-armv8-aarch64.S:
--------------------------------------------------------------------------------
1 |
2 | .text
3 | .arch armv8-a+crypto
4 |
5 | # SHA256 assembly implementation for ARMv8 AArch64
6 |
7 | .global sha256_block_data_order
8 | .type sha256_block_data_order,%function
9 | .align 2
10 | sha256_block_data_order:
11 |
12 | .Lsha256prolog:
13 |
14 | stp x29, x30, [sp,#-64]!
15 | mov x29, sp
16 | adr x3, .LKConstant256
17 | str q8, [sp, #16]
18 | ld1 {v16.4s-v19.4s}, [x3], #64
19 | ld1 {v0.4s}, [x0], #16
20 | ld1 {v20.4s-v23.4s}, [x3], #64
21 | add x2, x1, x2, lsl #6
22 | ld1 {v1.4s}, [x0]
23 | ld1 {v24.4s-v27.4s}, [x3], #64
24 | sub x0, x0, #16
25 | str q9, [sp, #32]
26 | str q10, [sp, #48]
27 | ld1 {v28.4s-v31.4s}, [x3], #64
28 |
29 | .Lsha256loop:
30 |
31 | ld1 {v5.16b-v8.16b}, [x1], #64
32 | mov v2.16b, v0.16b
33 | mov v3.16b, v1.16b
34 |
35 | rev32 v5.16b, v5.16b
36 | rev32 v6.16b, v6.16b
37 | add v9.4s, v5.4s, v16.4s
38 | rev32 v7.16b, v7.16b
39 | add v10.4s, v6.4s, v17.4s
40 | mov v4.16b, v2.16b
41 | sha256h q2, q3, v9.4s
42 | sha256h2 q3, q4, v9.4s
43 | sha256su0 v5.4s, v6.4s
44 | rev32 v8.16b, v8.16b
45 | add v9.4s, v7.4s, v18.4s
46 | mov v4.16b, v2.16b
47 | sha256h q2, q3, v10.4s
48 | sha256h2 q3, q4, v10.4s
49 | sha256su0 v6.4s, v7.4s
50 | sha256su1 v5.4s, v7.4s, v8.4s
51 | add v10.4s, v8.4s, v19.4s
52 | mov v4.16b, v2.16b
53 | sha256h q2, q3, v9.4s
54 | sha256h2 q3, q4, v9.4s
55 | sha256su0 v7.4s, v8.4s
56 | sha256su1 v6.4s, v8.4s, v5.4s
57 | add v9.4s, v5.4s, v20.4s
58 | mov v4.16b, v2.16b
59 | sha256h q2, q3, v10.4s
60 | sha256h2 q3, q4, v10.4s
61 | sha256su0 v8.4s, v5.4s
62 | sha256su1 v7.4s, v5.4s, v6.4s
63 | add v10.4s, v6.4s, v21.4s
64 | mov v4.16b, v2.16b
65 | sha256h q2, q3, v9.4s
66 | sha256h2 q3, q4, v9.4s
67 | sha256su0 v5.4s, v6.4s
68 | sha256su1 v8.4s, v6.4s, v7.4s
69 | add v9.4s, v7.4s, v22.4s
70 | mov v4.16b, v2.16b
71 | sha256h q2, q3, v10.4s
72 | sha256h2 q3, q4, v10.4s
73 | sha256su0 v6.4s, v7.4s
74 | sha256su1 v5.4s, v7.4s, v8.4s
75 | add v10.4s, v8.4s, v23.4s
76 | mov v4.16b, v2.16b
77 | sha256h q2, q3, v9.4s
78 | sha256h2 q3, q4, v9.4s
79 | sha256su0 v7.4s, v8.4s
80 | sha256su1 v6.4s, v8.4s, v5.4s
81 | add v9.4s, v5.4s, v24.4s
82 | mov v4.16b, v2.16b
83 | sha256h q2, q3, v10.4s
84 | sha256h2 q3, q4, v10.4s
85 | sha256su0 v8.4s, v5.4s
86 | sha256su1 v7.4s, v5.4s, v6.4s
87 | add v10.4s, v6.4s, v25.4s
88 | mov v4.16b, v2.16b
89 | sha256h q2, q3, v9.4s
90 | sha256h2 q3, q4, v9.4s
91 | sha256su0 v5.4s, v6.4s
92 | sha256su1 v8.4s, v6.4s, v7.4s
93 | add v9.4s, v7.4s, v26.4s
94 | mov v4.16b, v2.16b
95 | sha256h q2, q3, v10.4s
96 | sha256h2 q3, q4, v10.4s
97 | sha256su0 v6.4s, v7.4s
98 | sha256su1 v5.4s, v7.4s, v8.4s
99 | add v10.4s, v8.4s, v27.4s
100 | mov v4.16b, v2.16b
101 | sha256h q2, q3, v9.4s
102 | sha256h2 q3, q4, v9.4s
103 | sha256su0 v7.4s, v8.4s
104 | sha256su1 v6.4s, v8.4s, v5.4s
105 | add v9.4s, v5.4s, v28.4s
106 | mov v4.16b, v2.16b
107 | sha256h q2, q3, v10.4s
108 | sha256h2 q3, q4, v10.4s
109 | sha256su0 v8.4s, v5.4s
110 | sha256su1 v7.4s, v5.4s, v6.4s
111 | add v10.4s, v6.4s, v29.4s
112 | mov v4.16b, v2.16b
113 | sha256h q2, q3, v9.4s
114 | sha256h2 q3, q4, v9.4s
115 | sha256su1 v8.4s, v6.4s, v7.4s
116 | add v9.4s, v7.4s, v30.4s
117 | mov v4.16b, v2.16b
118 | sha256h q2, q3, v10.4s
119 | sha256h2 q3, q4, v10.4s
120 | add v10.4s, v8.4s, v31.4s
121 | mov v4.16b, v2.16b
122 | sha256h q2, q3, v9.4s
123 | sha256h2 q3, q4, v9.4s
124 | mov v4.16b, v2.16b
125 | sha256h q2, q3, v10.4s
126 | sha256h2 q3, q4, v10.4s
127 | cmp x1, x2
128 | add v1.4s, v1.4s, v3.4s
129 | add v0.4s, v0.4s, v2.4s
130 | b.ne .Lsha256loop
131 |
132 | .Lsha256epilog:
133 |
134 | st1 {v0.4s,v1.4s}, [x0]
135 | ldr q10, [sp, #48]
136 | ldr q9, [sp, #32]
137 | ldr q8, [sp, #16]
138 | ldr x29, [sp], #64
139 | ret
140 |
141 | .align 5
142 | .LKConstant256:
143 | .word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
144 | .word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
145 | .word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
146 | .word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
147 | .word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
148 | .word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
149 | .word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
150 | .word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
151 | .word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
152 | .word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
153 | .word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
154 | .word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
155 | .word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
156 | .word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
157 | .word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
158 | .word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
159 |
160 | .size sha256_block_data_order,.-sha256_block_data_order
161 | .align 2
162 |
163 |
164 |
--------------------------------------------------------------------------------
/sha256.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | void sha256_block_data_order (uint32_t *ctx, const void *in, size_t num);
7 |
8 | // SHA-256 initial hash value
9 | const uint32_t H_0[8] = {
10 | 0x6a09e667,
11 | 0xbb67ae85,
12 | 0x3c6ef372,
13 | 0xa54ff53a,
14 | 0x510e527f,
15 | 0x9b05688c,
16 | 0x1f83d9ab,
17 | 0x5be0cd19,
18 | };
19 |
20 |
21 | void sha256_print_hash(uint32_t *H, const char *title) {
22 | printf("-----------------------------------------------------------------------------------------\n");
23 | printf("| %-85s |\n", title);
24 | printf("-----------------------------------------------------------------------------------------\n");
25 | printf("| H[0] | H[1] | H[2] | H[3] | H[4] | H[5] | H[6] | H[7] |\n");
26 | printf("| %08x | %08x | %08x | %08x | %08x | %08x | %08x | %08x |\n", H[0], H[1], H[2], H[3], H[4], H[5], H[6], H[7]);
27 | printf("-----------------------------------------------------------------------------------------\n");
28 | }
29 |
30 |
31 | // initialize hash value
32 | void sha256_init(uint32_t *H) {
33 | H[0] = 0x6a09e667;
34 | H[1] = 0xbb67ae85;
35 | H[2] = 0x3c6ef372;
36 | H[3] = 0xa54ff53a;
37 | H[4] = 0x510e527f;
38 | H[5] = 0x9b05688c;
39 | H[6] = 0x1f83d9ab;
40 | H[7] = 0x5be0cd19;
41 | }
42 |
43 |
44 | int main(int argc, char **argv) {
45 | unsigned int i;
46 |
47 | // check arguments
48 | if (argc != 2) {
49 | printf("Usage: %s \n", argv[0]);
50 | return -1;
51 | }
52 |
53 | // open input file
54 | FILE *fp = fopen(argv[1], "r");
55 | if (!fp) {
56 | printf("Error opening file '%s' for reading.\n", argv[1]);
57 | return -1;
58 | }
59 |
60 | // initialize hash value
61 | uint32_t H[8];
62 | memcpy(H, H_0, 8*4);
63 |
64 | // read file and calculate hash
65 | uint64_t bits = 0;
66 | unsigned char buffer[64];
67 | size_t len;
68 | while (len = fread(buffer, 1, sizeof(buffer), fp)) {
69 | bits += len * 8;
70 |
71 | // preserve value of len by breaking on end of file (or error)
72 | if (len < 64) {
73 | break;
74 | }
75 | sha256_block_data_order(H, buffer,1);
76 | }
77 |
78 | // add padding
79 | if (len < 56) {
80 | // padd current block to 56 byte
81 | buffer[len] = 0x80;
82 | i = len + 1;
83 | } else {
84 | // fill up current block and update hash
85 | buffer[len] = 0x80;
86 | for (i = len + 1; i < 64; i++) {
87 | buffer[i] = 0x00;
88 | }
89 |
90 | sha256_block_data_order(H, buffer,1);
91 |
92 | // add (almost) one block of zero bytes
93 | i = 0;
94 | }
95 | for (; i < 56; i++) {
96 | buffer[i] = 0x00;
97 | }
98 |
99 | // add message length in bits in big endian
100 | for (i = 0; i < 8; i++) {
101 | buffer[63 - i] = bits >> (i * 8);
102 | }
103 |
104 | sha256_block_data_order(H, buffer,1);
105 |
106 | // print hash
107 | sha256_print_hash(H, "Final Hash");
108 |
109 | // convert hash to char array (in correct order)
110 | for (i = 0; i < 8; i++) {
111 | buffer[i*4 + 0] = H[i] >> 24;
112 | buffer[i*4 + 1] = H[i] >> 16;
113 | buffer[i*4 + 2] = H[i] >> 8;
114 | buffer[i*4 + 3] = H[i];
115 | }
116 |
117 | // print hash
118 | printf("Hash:\t");
119 | for (i = 0; i < 32; i++) {
120 | printf("%02x", buffer[i]);
121 | }
122 | printf("\n");
123 |
124 | return 0;
125 | }
126 |
127 |
--------------------------------------------------------------------------------