Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: CPL - Common Portability Library
4 : * Purpose: Implement SHA1
5 : * Author: Even Rouault, even.rouault at spatialys.com
6 : *
7 : * SHA1 computation coming from Public Domain code at:
8 : * https://github.com/B-Con/crypto-algorithms/blob/master/sha1.c
9 : * by Brad Conte (brad AT bradconte.com)
10 : *
11 : ******************************************************************************
12 : * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
13 : *
14 : * SPDX-License-Identifier: MIT
15 : ****************************************************************************/
16 :
17 : #include <string.h>
18 : #include "cpl_sha1.h"
19 :
20 : typedef struct
21 : {
22 : GByte data[64];
23 : GUInt32 datalen;
24 : GUIntBig bitlen;
25 : GUInt32 state[5];
26 : } CPL_SHA1Context;
27 :
28 : #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
29 :
30 : /************************************************************************/
31 : /* sha1_transform() */
32 : /************************************************************************/
33 :
34 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
35 435 : static void sha1_transform(CPL_SHA1Context *ctx, const GByte data[])
36 : {
37 : GUInt32 a, b, c, d, e, i, j, t, m[80];
38 :
39 7395 : for (i = 0, j = 0; i < 16; ++i, j += 4)
40 6960 : m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) +
41 6960 : (data[j + 3]);
42 28275 : for (; i < 80; ++i)
43 : {
44 27840 : m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
45 27840 : m[i] = (m[i] << 1) | (m[i] >> 31);
46 : }
47 :
48 435 : a = ctx->state[0];
49 435 : b = ctx->state[1];
50 435 : c = ctx->state[2];
51 435 : d = ctx->state[3];
52 435 : e = ctx->state[4];
53 :
54 9135 : for (i = 0; i < 20; ++i)
55 : {
56 8700 : t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + 0x5a827999U + m[i];
57 8700 : e = d;
58 8700 : d = c;
59 8700 : c = ROTLEFT(b, 30);
60 8700 : b = a;
61 8700 : a = t;
62 : }
63 9135 : for (; i < 40; ++i)
64 : {
65 8700 : t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0x6ed9eba1U + m[i];
66 8700 : e = d;
67 8700 : d = c;
68 8700 : c = ROTLEFT(b, 30);
69 8700 : b = a;
70 8700 : a = t;
71 : }
72 9135 : for (; i < 60; ++i)
73 : {
74 8700 : t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + 0x8f1bbcdcU +
75 8700 : m[i];
76 8700 : e = d;
77 8700 : d = c;
78 8700 : c = ROTLEFT(b, 30);
79 8700 : b = a;
80 8700 : a = t;
81 : }
82 9135 : for (; i < 80; ++i)
83 : {
84 8700 : t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0xca62c1d6U + m[i];
85 8700 : e = d;
86 8700 : d = c;
87 8700 : c = ROTLEFT(b, 30);
88 8700 : b = a;
89 8700 : a = t;
90 : }
91 :
92 435 : ctx->state[0] += a;
93 435 : ctx->state[1] += b;
94 435 : ctx->state[2] += c;
95 435 : ctx->state[3] += d;
96 435 : ctx->state[4] += e;
97 435 : }
98 :
99 : /************************************************************************/
100 : /* CPL_SHA1Init() */
101 : /************************************************************************/
102 :
103 208 : static void CPL_SHA1Init(CPL_SHA1Context *ctx)
104 : {
105 208 : ctx->datalen = 0;
106 208 : ctx->bitlen = 0;
107 208 : ctx->state[0] = 0x67452301U;
108 208 : ctx->state[1] = 0xEFCDAB89U;
109 208 : ctx->state[2] = 0x98BADCFEU;
110 208 : ctx->state[3] = 0x10325476U;
111 208 : ctx->state[4] = 0xc3d2e1f0U;
112 208 : }
113 :
114 : /************************************************************************/
115 : /* CPL_SHA1Update() */
116 : /************************************************************************/
117 :
118 416 : static void CPL_SHA1Update(CPL_SHA1Context *ctx, const GByte data[], size_t len)
119 : {
120 : size_t i;
121 :
122 21106 : for (i = 0; i < len; ++i)
123 : {
124 20690 : ctx->data[ctx->datalen] = data[i];
125 20690 : ctx->datalen++;
126 20690 : if (ctx->datalen == 64)
127 : {
128 222 : sha1_transform(ctx, ctx->data);
129 222 : ctx->bitlen += 512;
130 222 : ctx->datalen = 0;
131 : }
132 : }
133 416 : }
134 :
135 : /************************************************************************/
136 : /* CPL_SHA1Final() */
137 : /************************************************************************/
138 :
139 208 : static void CPL_SHA1Final(CPL_SHA1Context *ctx, GByte hash[CPL_SHA1_HASH_SIZE])
140 : {
141 : GUInt32 i;
142 :
143 208 : i = ctx->datalen;
144 :
145 : // Pad whatever data is left in the buffer.
146 208 : if (ctx->datalen < 56)
147 : {
148 203 : ctx->data[i++] = 0x80;
149 5183 : while (i < 56)
150 4980 : ctx->data[i++] = 0x00;
151 : }
152 : else
153 : {
154 5 : ctx->data[i++] = 0x80;
155 23 : while (i < 64)
156 18 : ctx->data[i++] = 0x00;
157 5 : sha1_transform(ctx, ctx->data);
158 5 : memset(ctx->data, 0, 56);
159 : }
160 :
161 : // Append to the padding the total message's length in bits and transform.
162 208 : ctx->bitlen += ctx->datalen * 8;
163 208 : ctx->data[63] = static_cast<GByte>((ctx->bitlen) & 0xFFU);
164 208 : ctx->data[62] = static_cast<GByte>((ctx->bitlen >> 8) & 0xFFU);
165 208 : ctx->data[61] = static_cast<GByte>((ctx->bitlen >> 16) & 0xFFU);
166 208 : ctx->data[60] = static_cast<GByte>((ctx->bitlen >> 24) & 0xFFU);
167 208 : ctx->data[59] = static_cast<GByte>((ctx->bitlen >> 32) & 0xFFU);
168 208 : ctx->data[58] = static_cast<GByte>((ctx->bitlen >> 40) & 0xFFU);
169 208 : ctx->data[57] = static_cast<GByte>((ctx->bitlen >> 48) & 0xFFU);
170 208 : ctx->data[56] = static_cast<GByte>((ctx->bitlen >> 56) & 0xFFU);
171 208 : sha1_transform(ctx, ctx->data);
172 :
173 : // Since this implementation uses little endian byte ordering and MD uses
174 : // big endian, reverse all the bytes when copying the final state to the
175 : // output hash.
176 1040 : for (i = 0; i < 4; ++i)
177 : {
178 832 : hash[i] =
179 832 : static_cast<GByte>((ctx->state[0] >> (24 - i * 8)) & 0x000000ffU);
180 832 : hash[i + 4] =
181 832 : static_cast<GByte>((ctx->state[1] >> (24 - i * 8)) & 0x000000ffU);
182 832 : hash[i + 8] =
183 832 : static_cast<GByte>((ctx->state[2] >> (24 - i * 8)) & 0x000000ffU);
184 832 : hash[i + 12] =
185 832 : static_cast<GByte>((ctx->state[3] >> (24 - i * 8)) & 0x000000ffU);
186 832 : hash[i + 16] =
187 832 : static_cast<GByte>((ctx->state[4] >> (24 - i * 8)) & 0x000000ffU);
188 : }
189 208 : }
190 :
191 : /************************************************************************/
192 : /* CPL_SHA1() */
193 : /************************************************************************/
194 :
195 0 : static void CPL_SHA1(const void *data, size_t len,
196 : GByte hash[CPL_SHA1_HASH_SIZE])
197 : {
198 : CPL_SHA1Context sSHA1Ctxt;
199 0 : CPL_SHA1Init(&sSHA1Ctxt);
200 0 : CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(data), len);
201 0 : CPL_SHA1Final(&sSHA1Ctxt, hash);
202 0 : memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
203 0 : }
204 :
205 : /************************************************************************/
206 : /* CPL_HMAC_SHA1() */
207 : /************************************************************************/
208 :
209 : #define CPL_HMAC_SHA1_BLOCKSIZE 64U
210 :
211 : // See
212 : // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
213 104 : void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen, const void *pabyMessage,
214 : size_t nMessageLen, GByte abyDigest[CPL_SHA1_HASH_SIZE])
215 : {
216 104 : GByte abyPad[CPL_HMAC_SHA1_BLOCKSIZE] = {};
217 104 : if (nKeyLen > CPL_HMAC_SHA1_BLOCKSIZE)
218 : {
219 0 : CPL_SHA1(pKey, nKeyLen, abyPad);
220 : }
221 : else
222 : {
223 104 : memcpy(abyPad, pKey, nKeyLen);
224 : }
225 :
226 : // Compute ipad.
227 6760 : for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
228 6656 : abyPad[i] = 0x36 ^ abyPad[i];
229 :
230 : CPL_SHA1Context sSHA1Ctxt;
231 104 : CPL_SHA1Init(&sSHA1Ctxt);
232 104 : CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
233 104 : CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(pabyMessage),
234 : nMessageLen);
235 104 : CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
236 :
237 : // Compute opad.
238 6760 : for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
239 6656 : abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
240 :
241 104 : CPL_SHA1Init(&sSHA1Ctxt);
242 104 : CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
243 104 : CPL_SHA1Update(&sSHA1Ctxt, abyDigest, CPL_SHA1_HASH_SIZE);
244 104 : CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
245 :
246 104 : memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
247 104 : memset(abyPad, 0, CPL_HMAC_SHA1_BLOCKSIZE);
248 104 : }
|