├── 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 | --------------------------------------------------------------------------------