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 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include <string.h>
34 : #include "cpl_sha1.h"
35 :
36 : typedef struct
37 : {
38 : GByte data[64];
39 : GUInt32 datalen;
40 : GUIntBig bitlen;
41 : GUInt32 state[5];
42 : } CPL_SHA1Context;
43 :
44 : #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
45 :
46 : /************************************************************************/
47 : /* sha1_transform() */
48 : /************************************************************************/
49 :
50 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
51 530 : static void sha1_transform(CPL_SHA1Context *ctx, const GByte data[])
52 : {
53 : GUInt32 a, b, c, d, e, i, j, t, m[80];
54 :
55 9010 : for (i = 0, j = 0; i < 16; ++i, j += 4)
56 8480 : m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) +
57 8480 : (data[j + 3]);
58 34450 : for (; i < 80; ++i)
59 : {
60 33920 : m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
61 33920 : m[i] = (m[i] << 1) | (m[i] >> 31);
62 : }
63 :
64 530 : a = ctx->state[0];
65 530 : b = ctx->state[1];
66 530 : c = ctx->state[2];
67 530 : d = ctx->state[3];
68 530 : e = ctx->state[4];
69 :
70 11130 : for (i = 0; i < 20; ++i)
71 : {
72 10600 : t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + 0x5a827999U + m[i];
73 10600 : e = d;
74 10600 : d = c;
75 10600 : c = ROTLEFT(b, 30);
76 10600 : b = a;
77 10600 : a = t;
78 : }
79 11130 : for (; i < 40; ++i)
80 : {
81 10600 : t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0x6ed9eba1U + m[i];
82 10600 : e = d;
83 10600 : d = c;
84 10600 : c = ROTLEFT(b, 30);
85 10600 : b = a;
86 10600 : a = t;
87 : }
88 11130 : for (; i < 60; ++i)
89 : {
90 10600 : t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + 0x8f1bbcdcU +
91 10600 : m[i];
92 10600 : e = d;
93 10600 : d = c;
94 10600 : c = ROTLEFT(b, 30);
95 10600 : b = a;
96 10600 : a = t;
97 : }
98 11130 : for (; i < 80; ++i)
99 : {
100 10600 : t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0xca62c1d6U + m[i];
101 10600 : e = d;
102 10600 : d = c;
103 10600 : c = ROTLEFT(b, 30);
104 10600 : b = a;
105 10600 : a = t;
106 : }
107 :
108 530 : ctx->state[0] += a;
109 530 : ctx->state[1] += b;
110 530 : ctx->state[2] += c;
111 530 : ctx->state[3] += d;
112 530 : ctx->state[4] += e;
113 530 : }
114 :
115 : /************************************************************************/
116 : /* CPL_SHA1Init() */
117 : /************************************************************************/
118 :
119 246 : static void CPL_SHA1Init(CPL_SHA1Context *ctx)
120 : {
121 246 : ctx->datalen = 0;
122 246 : ctx->bitlen = 0;
123 246 : ctx->state[0] = 0x67452301U;
124 246 : ctx->state[1] = 0xEFCDAB89U;
125 246 : ctx->state[2] = 0x98BADCFEU;
126 246 : ctx->state[3] = 0x10325476U;
127 246 : ctx->state[4] = 0xc3d2e1f0U;
128 246 : }
129 :
130 : /************************************************************************/
131 : /* CPL_SHA1Update() */
132 : /************************************************************************/
133 :
134 492 : static void CPL_SHA1Update(CPL_SHA1Context *ctx, const GByte data[], size_t len)
135 : {
136 : size_t i;
137 :
138 25672 : for (i = 0; i < len; ++i)
139 : {
140 25180 : ctx->data[ctx->datalen] = data[i];
141 25180 : ctx->datalen++;
142 25180 : if (ctx->datalen == 64)
143 : {
144 278 : sha1_transform(ctx, ctx->data);
145 278 : ctx->bitlen += 512;
146 278 : ctx->datalen = 0;
147 : }
148 : }
149 492 : }
150 :
151 : /************************************************************************/
152 : /* CPL_SHA1Final() */
153 : /************************************************************************/
154 :
155 246 : static void CPL_SHA1Final(CPL_SHA1Context *ctx, GByte hash[CPL_SHA1_HASH_SIZE])
156 : {
157 : GUInt32 i;
158 :
159 246 : i = ctx->datalen;
160 :
161 : // Pad whatever data is left in the buffer.
162 246 : if (ctx->datalen < 56)
163 : {
164 240 : ctx->data[i++] = 0x80;
165 6409 : while (i < 56)
166 6169 : ctx->data[i++] = 0x00;
167 : }
168 : else
169 : {
170 6 : ctx->data[i++] = 0x80;
171 27 : while (i < 64)
172 21 : ctx->data[i++] = 0x00;
173 6 : sha1_transform(ctx, ctx->data);
174 6 : memset(ctx->data, 0, 56);
175 : }
176 :
177 : // Append to the padding the total message's length in bits and transform.
178 246 : ctx->bitlen += ctx->datalen * 8;
179 246 : ctx->data[63] = static_cast<GByte>((ctx->bitlen) & 0xFFU);
180 246 : ctx->data[62] = static_cast<GByte>((ctx->bitlen >> 8) & 0xFFU);
181 246 : ctx->data[61] = static_cast<GByte>((ctx->bitlen >> 16) & 0xFFU);
182 246 : ctx->data[60] = static_cast<GByte>((ctx->bitlen >> 24) & 0xFFU);
183 246 : ctx->data[59] = static_cast<GByte>((ctx->bitlen >> 32) & 0xFFU);
184 246 : ctx->data[58] = static_cast<GByte>((ctx->bitlen >> 40) & 0xFFU);
185 246 : ctx->data[57] = static_cast<GByte>((ctx->bitlen >> 48) & 0xFFU);
186 246 : ctx->data[56] = static_cast<GByte>((ctx->bitlen >> 56) & 0xFFU);
187 246 : sha1_transform(ctx, ctx->data);
188 :
189 : // Since this implementation uses little endian byte ordering and MD uses
190 : // big endian, reverse all the bytes when copying the final state to the
191 : // output hash.
192 1230 : for (i = 0; i < 4; ++i)
193 : {
194 984 : hash[i] =
195 984 : static_cast<GByte>((ctx->state[0] >> (24 - i * 8)) & 0x000000ffU);
196 984 : hash[i + 4] =
197 984 : static_cast<GByte>((ctx->state[1] >> (24 - i * 8)) & 0x000000ffU);
198 984 : hash[i + 8] =
199 984 : static_cast<GByte>((ctx->state[2] >> (24 - i * 8)) & 0x000000ffU);
200 984 : hash[i + 12] =
201 984 : static_cast<GByte>((ctx->state[3] >> (24 - i * 8)) & 0x000000ffU);
202 984 : hash[i + 16] =
203 984 : static_cast<GByte>((ctx->state[4] >> (24 - i * 8)) & 0x000000ffU);
204 : }
205 246 : }
206 :
207 : /************************************************************************/
208 : /* CPL_SHA1() */
209 : /************************************************************************/
210 :
211 0 : static void CPL_SHA1(const void *data, size_t len,
212 : GByte hash[CPL_SHA1_HASH_SIZE])
213 : {
214 : CPL_SHA1Context sSHA1Ctxt;
215 0 : CPL_SHA1Init(&sSHA1Ctxt);
216 0 : CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(data), len);
217 0 : CPL_SHA1Final(&sSHA1Ctxt, hash);
218 0 : memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
219 0 : }
220 :
221 : /************************************************************************/
222 : /* CPL_HMAC_SHA1() */
223 : /************************************************************************/
224 :
225 : #define CPL_HMAC_SHA1_BLOCKSIZE 64U
226 :
227 : // See
228 : // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
229 123 : void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen, const void *pabyMessage,
230 : size_t nMessageLen, GByte abyDigest[CPL_SHA1_HASH_SIZE])
231 : {
232 123 : GByte abyPad[CPL_HMAC_SHA1_BLOCKSIZE] = {};
233 123 : if (nKeyLen > CPL_HMAC_SHA1_BLOCKSIZE)
234 : {
235 0 : CPL_SHA1(pKey, nKeyLen, abyPad);
236 : }
237 : else
238 : {
239 123 : memcpy(abyPad, pKey, nKeyLen);
240 : }
241 :
242 : // Compute ipad.
243 7995 : for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
244 7872 : abyPad[i] = 0x36 ^ abyPad[i];
245 :
246 : CPL_SHA1Context sSHA1Ctxt;
247 123 : CPL_SHA1Init(&sSHA1Ctxt);
248 123 : CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
249 123 : CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(pabyMessage),
250 : nMessageLen);
251 123 : CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
252 :
253 : // Compute opad.
254 7995 : for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
255 7872 : abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
256 :
257 123 : CPL_SHA1Init(&sSHA1Ctxt);
258 123 : CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
259 123 : CPL_SHA1Update(&sSHA1Ctxt, abyDigest, CPL_SHA1_HASH_SIZE);
260 123 : CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
261 :
262 123 : memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
263 123 : memset(abyPad, 0, CPL_HMAC_SHA1_BLOCKSIZE);
264 123 : }
|