0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <asm/unaligned.h>
0013 #include <crypto/sm3.h>
0014
0015 static const u32 ____cacheline_aligned K[64] = {
0016 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb,
0017 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc,
0018 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce,
0019 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6,
0020 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
0021 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
0022 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
0023 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5,
0024 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53,
0025 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d,
0026 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4,
0027 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43,
0028 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
0029 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
0030 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
0031 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
0032 };
0033
0034
0035
0036
0037
0038 #define R(i, a, b, c, d, e, f, g, h, t, w1, w2) \
0039 do { \
0040 ss1 = rol32((rol32((a), 12) + (e) + (t)), 7); \
0041 ss2 = ss1 ^ rol32((a), 12); \
0042 d += FF ## i(a, b, c) + ss2 + ((w1) ^ (w2)); \
0043 h += GG ## i(e, f, g) + ss1 + (w1); \
0044 b = rol32((b), 9); \
0045 f = rol32((f), 19); \
0046 h = P0((h)); \
0047 } while (0)
0048
0049 #define R1(a, b, c, d, e, f, g, h, t, w1, w2) \
0050 R(1, a, b, c, d, e, f, g, h, t, w1, w2)
0051 #define R2(a, b, c, d, e, f, g, h, t, w1, w2) \
0052 R(2, a, b, c, d, e, f, g, h, t, w1, w2)
0053
0054 #define FF1(x, y, z) (x ^ y ^ z)
0055 #define FF2(x, y, z) ((x & y) | (x & z) | (y & z))
0056
0057 #define GG1(x, y, z) FF1(x, y, z)
0058 #define GG2(x, y, z) ((x & y) | (~x & z))
0059
0060
0061 #define P0(x) ((x) ^ rol32((x), 9) ^ rol32((x), 17))
0062 #define P1(x) ((x) ^ rol32((x), 15) ^ rol32((x), 23))
0063 #define I(i) (W[i] = get_unaligned_be32(data + i * 4))
0064 #define W1(i) (W[i & 0x0f])
0065 #define W2(i) (W[i & 0x0f] = \
0066 P1(W[i & 0x0f] \
0067 ^ W[(i-9) & 0x0f] \
0068 ^ rol32(W[(i-3) & 0x0f], 15)) \
0069 ^ rol32(W[(i-13) & 0x0f], 7) \
0070 ^ W[(i-6) & 0x0f])
0071
0072 static void sm3_transform(struct sm3_state *sctx, u8 const *data, u32 W[16])
0073 {
0074 u32 a, b, c, d, e, f, g, h, ss1, ss2;
0075
0076 a = sctx->state[0];
0077 b = sctx->state[1];
0078 c = sctx->state[2];
0079 d = sctx->state[3];
0080 e = sctx->state[4];
0081 f = sctx->state[5];
0082 g = sctx->state[6];
0083 h = sctx->state[7];
0084
0085 R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4));
0086 R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5));
0087 R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6));
0088 R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7));
0089 R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8));
0090 R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9));
0091 R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10));
0092 R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11));
0093 R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12));
0094 R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13));
0095 R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14));
0096 R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15));
0097 R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16));
0098 R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17));
0099 R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18));
0100 R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19));
0101
0102 R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20));
0103 R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21));
0104 R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22));
0105 R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23));
0106 R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24));
0107 R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25));
0108 R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26));
0109 R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27));
0110 R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28));
0111 R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29));
0112 R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30));
0113 R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31));
0114 R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32));
0115 R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33));
0116 R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34));
0117 R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35));
0118
0119 R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36));
0120 R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37));
0121 R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38));
0122 R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39));
0123 R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40));
0124 R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41));
0125 R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42));
0126 R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43));
0127 R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44));
0128 R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45));
0129 R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46));
0130 R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47));
0131 R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48));
0132 R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49));
0133 R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50));
0134 R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51));
0135
0136 R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52));
0137 R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53));
0138 R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54));
0139 R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55));
0140 R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56));
0141 R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57));
0142 R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58));
0143 R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59));
0144 R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60));
0145 R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61));
0146 R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62));
0147 R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63));
0148 R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64));
0149 R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65));
0150 R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66));
0151 R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67));
0152
0153 sctx->state[0] ^= a;
0154 sctx->state[1] ^= b;
0155 sctx->state[2] ^= c;
0156 sctx->state[3] ^= d;
0157 sctx->state[4] ^= e;
0158 sctx->state[5] ^= f;
0159 sctx->state[6] ^= g;
0160 sctx->state[7] ^= h;
0161 }
0162 #undef R
0163 #undef R1
0164 #undef R2
0165 #undef I
0166 #undef W1
0167 #undef W2
0168
0169 static inline void sm3_block(struct sm3_state *sctx,
0170 u8 const *data, int blocks, u32 W[16])
0171 {
0172 while (blocks--) {
0173 sm3_transform(sctx, data, W);
0174 data += SM3_BLOCK_SIZE;
0175 }
0176 }
0177
0178 void sm3_update(struct sm3_state *sctx, const u8 *data, unsigned int len)
0179 {
0180 unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
0181 u32 W[16];
0182
0183 sctx->count += len;
0184
0185 if ((partial + len) >= SM3_BLOCK_SIZE) {
0186 int blocks;
0187
0188 if (partial) {
0189 int p = SM3_BLOCK_SIZE - partial;
0190
0191 memcpy(sctx->buffer + partial, data, p);
0192 data += p;
0193 len -= p;
0194
0195 sm3_block(sctx, sctx->buffer, 1, W);
0196 }
0197
0198 blocks = len / SM3_BLOCK_SIZE;
0199 len %= SM3_BLOCK_SIZE;
0200
0201 if (blocks) {
0202 sm3_block(sctx, data, blocks, W);
0203 data += blocks * SM3_BLOCK_SIZE;
0204 }
0205
0206 memzero_explicit(W, sizeof(W));
0207
0208 partial = 0;
0209 }
0210 if (len)
0211 memcpy(sctx->buffer + partial, data, len);
0212 }
0213 EXPORT_SYMBOL_GPL(sm3_update);
0214
0215 void sm3_final(struct sm3_state *sctx, u8 *out)
0216 {
0217 const int bit_offset = SM3_BLOCK_SIZE - sizeof(u64);
0218 __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
0219 __be32 *digest = (__be32 *)out;
0220 unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
0221 u32 W[16];
0222 int i;
0223
0224 sctx->buffer[partial++] = 0x80;
0225 if (partial > bit_offset) {
0226 memset(sctx->buffer + partial, 0, SM3_BLOCK_SIZE - partial);
0227 partial = 0;
0228
0229 sm3_block(sctx, sctx->buffer, 1, W);
0230 }
0231
0232 memset(sctx->buffer + partial, 0, bit_offset - partial);
0233 *bits = cpu_to_be64(sctx->count << 3);
0234 sm3_block(sctx, sctx->buffer, 1, W);
0235
0236 for (i = 0; i < 8; i++)
0237 put_unaligned_be32(sctx->state[i], digest++);
0238
0239
0240 memzero_explicit(W, sizeof(W));
0241 memzero_explicit(sctx, sizeof(*sctx));
0242 }
0243 EXPORT_SYMBOL_GPL(sm3_final);
0244
0245 MODULE_DESCRIPTION("Generic SM3 library");
0246 MODULE_LICENSE("GPL v2");