|
1
|
/* |
|
2
|
** Copyright (c) 2017 D. Richard Hipp |
|
3
|
** |
|
4
|
** This program is free software; you can redistribute it and/or |
|
5
|
** modify it under the terms of the Simplified BSD License (also |
|
6
|
** known as the "2-Clause License" or "FreeBSD License".) |
|
7
|
** |
|
8
|
** This program is distributed in the hope that it will be useful, |
|
9
|
** but without any warranty; without even the implied warranty of |
|
10
|
** merchantability or fitness for a particular purpose. |
|
11
|
** |
|
12
|
** Author contact information: |
|
13
|
** [email protected] |
|
14
|
** http://www.hwaci.com/drh/ |
|
15
|
** |
|
16
|
******************************************************************************* |
|
17
|
** |
|
18
|
** This file contains generic code for dealing with hashes used for |
|
19
|
** naming artifacts. Specific hash algorithms are implemented separately |
|
20
|
** (for example in sha1.c and sha3.c). This file contains the generic |
|
21
|
** interface logic. |
|
22
|
** |
|
23
|
** "hname" is intended to be an abbreviation of "hash name". |
|
24
|
*/ |
|
25
|
#include "config.h" |
|
26
|
#include "hname.h" |
|
27
|
|
|
28
|
|
|
29
|
#if INTERFACE |
|
30
|
/* |
|
31
|
** Code numbers for the allowed hash algorithms. |
|
32
|
*/ |
|
33
|
#define HNAME_ERROR 0 /* Not a valid hash */ |
|
34
|
#define HNAME_SHA1 1 /* SHA1 */ |
|
35
|
#define HNAME_K256 2 /* SHA3-256 */ |
|
36
|
|
|
37
|
/* |
|
38
|
** Minimum and maximum lengths for a hash value when hex encoded. |
|
39
|
*/ |
|
40
|
#define HNAME_MIN 40 /* Length for SHA1 */ |
|
41
|
#define HNAME_MAX 64 /* Length for SHA3-256 */ |
|
42
|
|
|
43
|
/* |
|
44
|
** Hash lengths for the various algorithms |
|
45
|
*/ |
|
46
|
#define HNAME_LEN_SHA1 40 |
|
47
|
#define HNAME_LEN_K256 64 |
|
48
|
|
|
49
|
/* |
|
50
|
** The number of distinct hash algorithms: |
|
51
|
*/ |
|
52
|
#define HNAME_COUNT 2 /* Just SHA1 and SHA3-256. Let's keep it that way! */ |
|
53
|
|
|
54
|
/* |
|
55
|
** Hash naming policies |
|
56
|
*/ |
|
57
|
#define HPOLICY_SHA1 0 /* Use SHA1 hashes */ |
|
58
|
#define HPOLICY_AUTO 1 /* SHA1 but auto-promote to SHA3 */ |
|
59
|
#define HPOLICY_SHA3 2 /* Use SHA3 hashes */ |
|
60
|
#define HPOLICY_SHA3_ONLY 3 /* Use SHA3 hashes exclusively */ |
|
61
|
#define HPOLICY_SHUN_SHA1 4 /* Shun all SHA1 objects */ |
|
62
|
|
|
63
|
#endif /* INTERFACE */ |
|
64
|
|
|
65
|
/* |
|
66
|
** Return a human-readable name for the hash algorithm given a hash with |
|
67
|
** a length of nHash hexadecimal digits. |
|
68
|
*/ |
|
69
|
const char *hname_alg(int nHash){ |
|
70
|
if( nHash==HNAME_LEN_SHA1 ) return "SHA1"; |
|
71
|
if( nHash==HNAME_LEN_K256 ) return "SHA3-256"; |
|
72
|
return "?"; |
|
73
|
} |
|
74
|
|
|
75
|
/* |
|
76
|
** Return the integer hash algorithm code number (ex: HNAME_K256) for |
|
77
|
** the hash string provided. Or return HNAME_ERROR (0) if the input string |
|
78
|
** is not a valid artifact hash string. |
|
79
|
*/ |
|
80
|
int hname_validate(const char *zHash, int nHash){ |
|
81
|
int id; |
|
82
|
switch( nHash ){ |
|
83
|
case HNAME_LEN_SHA1: id = HNAME_SHA1; break; |
|
84
|
case HNAME_LEN_K256: id = HNAME_K256; break; |
|
85
|
default: return HNAME_ERROR; |
|
86
|
} |
|
87
|
if( !validate16(zHash, nHash) ) return HNAME_ERROR; |
|
88
|
return id; |
|
89
|
} |
|
90
|
|
|
91
|
/* |
|
92
|
** Verify that zHash is a valid hash for the content in pContent. |
|
93
|
** Return true if the hash is correct. Return false if the content |
|
94
|
** does not match the hash. |
|
95
|
** |
|
96
|
** Actually, the returned value is one of the hash algorithm constants |
|
97
|
** corresponding to the hash that matched if the hash is correct. |
|
98
|
** (Examples: HNAME_SHA1 or HNAME_K256). And the return is HNAME_ERROR |
|
99
|
** if the hash does not match. |
|
100
|
*/ |
|
101
|
int hname_verify_hash(Blob *pContent, const char *zHash, int nHash){ |
|
102
|
int id = HNAME_ERROR; |
|
103
|
switch( nHash ){ |
|
104
|
case HNAME_LEN_SHA1: { |
|
105
|
Blob hash; |
|
106
|
sha1sum_blob(pContent, &hash); |
|
107
|
if( memcmp(blob_buffer(&hash),zHash,HNAME_LEN_SHA1)==0 ) id = HNAME_SHA1; |
|
108
|
blob_reset(&hash); |
|
109
|
break; |
|
110
|
} |
|
111
|
case HNAME_LEN_K256: { |
|
112
|
sha3sum_init(256); |
|
113
|
sha3sum_step_blob(pContent); |
|
114
|
if( memcmp(sha3sum_finish(0),zHash,64)==0 ) id = HNAME_K256; |
|
115
|
break; |
|
116
|
} |
|
117
|
} |
|
118
|
return id; |
|
119
|
} |
|
120
|
|
|
121
|
/* |
|
122
|
** Verify that zHash is a valid hash for the content of a file on |
|
123
|
** disk named zFile. |
|
124
|
** |
|
125
|
** Return true if the hash is correct. Return false if the content |
|
126
|
** does not match the hash. |
|
127
|
** |
|
128
|
** Actually, the returned value is one of the hash algorithm constants |
|
129
|
** corresponding to the hash that matched if the hash is correct. |
|
130
|
** (Examples: HNAME_SHA1 or HNAME_K256). And the return is HNAME_ERROR |
|
131
|
** if the hash does not match. |
|
132
|
*/ |
|
133
|
int hname_verify_file_hash(const char *zFile, const char *zHash, int nHash){ |
|
134
|
int id = HNAME_ERROR; |
|
135
|
switch( nHash ){ |
|
136
|
case HNAME_LEN_SHA1: { |
|
137
|
Blob hash; |
|
138
|
if( sha1sum_file(zFile, RepoFILE, &hash) ) break; |
|
139
|
if( memcmp(blob_buffer(&hash),zHash,HNAME_LEN_SHA1)==0 ) id = HNAME_SHA1; |
|
140
|
blob_reset(&hash); |
|
141
|
break; |
|
142
|
} |
|
143
|
case HNAME_LEN_K256: { |
|
144
|
Blob hash; |
|
145
|
if( sha3sum_file(zFile, RepoFILE, 256, &hash) ) break; |
|
146
|
if( memcmp(blob_buffer(&hash),zHash,64)==0 ) id = HNAME_LEN_K256; |
|
147
|
blob_reset(&hash); |
|
148
|
break; |
|
149
|
} |
|
150
|
} |
|
151
|
return id; |
|
152
|
} |
|
153
|
|
|
154
|
/* |
|
155
|
** Compute a hash on blob pContent. Write the hash into blob pHashOut. |
|
156
|
** This routine assumes that pHashOut is uninitialized. |
|
157
|
** |
|
158
|
** The preferred hash is used for iHType==0 and the alternative hash is |
|
159
|
** used if iHType==1. (The interface is designed to accommodate more than |
|
160
|
** just two hashes, but HNAME_COUNT is currently fixed at 2.) |
|
161
|
** |
|
162
|
** Depending on the hash policy, the alternative hash may be disallowed. |
|
163
|
** If the alterative hash is disallowed, the routine returns 0. This |
|
164
|
** routine returns 1 if iHType>0 and the alternative hash is allowed, |
|
165
|
** and it always returns 1 when iHType==0. |
|
166
|
** |
|
167
|
** Alternative hash is disallowed for all hash policies except auto, |
|
168
|
** sha1 and sha3. |
|
169
|
*/ |
|
170
|
int hname_hash(const Blob *pContent, unsigned int iHType, Blob *pHashOut){ |
|
171
|
assert( iHType==0 || iHType==1 ); |
|
172
|
if( iHType==1 ){ |
|
173
|
switch( g.eHashPolicy ){ |
|
174
|
case HPOLICY_AUTO: |
|
175
|
case HPOLICY_SHA1: |
|
176
|
sha3sum_blob(pContent, 256, pHashOut); |
|
177
|
return 1; |
|
178
|
case HPOLICY_SHA3: |
|
179
|
sha1sum_blob(pContent, pHashOut); |
|
180
|
return 1; |
|
181
|
} |
|
182
|
} |
|
183
|
if( iHType==0 ){ |
|
184
|
switch( g.eHashPolicy ){ |
|
185
|
case HPOLICY_SHA1: |
|
186
|
case HPOLICY_AUTO: |
|
187
|
sha1sum_blob(pContent, pHashOut); |
|
188
|
return 1; |
|
189
|
case HPOLICY_SHA3: |
|
190
|
case HPOLICY_SHA3_ONLY: |
|
191
|
case HPOLICY_SHUN_SHA1: |
|
192
|
sha3sum_blob(pContent, 256, pHashOut); |
|
193
|
return 1; |
|
194
|
} |
|
195
|
} |
|
196
|
blob_init(pHashOut, 0, 0); |
|
197
|
return 0; |
|
198
|
} |
|
199
|
|
|
200
|
/* |
|
201
|
** Return the default hash policy for repositories that do not currently |
|
202
|
** have an assigned hash policy. |
|
203
|
** |
|
204
|
** Make the default HPOLICY_AUTO if there are SHA1 artifacts but no SHA3 |
|
205
|
** artifacts in the repository. Make the default HPOLICY_SHA3 if there |
|
206
|
** are one or more SHA3 artifacts or if the repository is initially empty. |
|
207
|
*/ |
|
208
|
int hname_default_policy(void){ |
|
209
|
if( db_exists("SELECT 1 FROM blob WHERE length(uuid)>40") |
|
210
|
|| !db_exists("SELECT 1 FROM blob WHERE length(uuid)==40") |
|
211
|
){ |
|
212
|
return HPOLICY_SHA3; |
|
213
|
}else{ |
|
214
|
return HPOLICY_AUTO; |
|
215
|
} |
|
216
|
} |
|
217
|
|
|
218
|
/* |
|
219
|
** Names of the hash policies. |
|
220
|
*/ |
|
221
|
static const char *const azPolicy[] = { |
|
222
|
"sha1", "auto", "sha3", "sha3-only", "shun-sha1" |
|
223
|
}; |
|
224
|
|
|
225
|
/* Return the name of the current hash policy. |
|
226
|
*/ |
|
227
|
const char *hpolicy_name(void){ |
|
228
|
return azPolicy[g.eHashPolicy]; |
|
229
|
} |
|
230
|
|
|
231
|
|
|
232
|
/* |
|
233
|
** COMMAND: hash-policy* |
|
234
|
** |
|
235
|
** Usage: fossil hash-policy ?NEW-POLICY? |
|
236
|
** |
|
237
|
** Query or set the hash policy for the current repository. Available hash |
|
238
|
** policies are as follows: |
|
239
|
** |
|
240
|
** sha1 New artifact names are created using SHA1 |
|
241
|
** |
|
242
|
** auto New artifact names are created using SHA1, but |
|
243
|
** automatically change the policy to "sha3" when |
|
244
|
** any SHA3 artifact enters the repository. |
|
245
|
** |
|
246
|
** sha3 New artifact names are created using SHA3, but |
|
247
|
** older artifacts with SHA1 names may be reused. |
|
248
|
** |
|
249
|
** sha3-only Use only SHA3 artifact names. Do not reuse legacy |
|
250
|
** SHA1 names. |
|
251
|
** |
|
252
|
** shun-sha1 Shun any SHA1 artifacts received by sync operations |
|
253
|
** other than clones. Older legacy SHA1 artifacts are |
|
254
|
** allowed during a clone. |
|
255
|
** |
|
256
|
** The default hash policy for existing repositories is "auto", which will |
|
257
|
** immediately promote to "sha3" if the repository contains one or more |
|
258
|
** artifacts with SHA3 names. The default hash policy for new repositories |
|
259
|
** is "shun-sha1". |
|
260
|
*/ |
|
261
|
void hash_policy_command(void){ |
|
262
|
int i; |
|
263
|
db_find_and_open_repository(0, 0); |
|
264
|
if( g.argc!=2 && g.argc!=3 ) usage("?NEW-POLICY?"); |
|
265
|
if( g.argc==2 ){ |
|
266
|
fossil_print("%s\n", azPolicy[g.eHashPolicy]); |
|
267
|
return; |
|
268
|
} |
|
269
|
for(i=HPOLICY_SHA1; i<=HPOLICY_SHUN_SHA1; i++){ |
|
270
|
if( fossil_strcmp(g.argv[2],azPolicy[i])==0 ){ |
|
271
|
if( i==HPOLICY_AUTO |
|
272
|
&& db_exists("SELECT 1 FROM blob WHERE length(uuid)>40") |
|
273
|
){ |
|
274
|
i = HPOLICY_SHA3; |
|
275
|
} |
|
276
|
g.eHashPolicy = i; |
|
277
|
db_set_int("hash-policy", i, 0); |
|
278
|
fossil_print("%s\n", azPolicy[i]); |
|
279
|
return; |
|
280
|
} |
|
281
|
} |
|
282
|
fossil_fatal("unknown hash policy \"%s\" - should be one of: sha1 auto" |
|
283
|
" sha3 sha3-only shun-sha1", g.argv[2]); |
|
284
|
} |
|
285
|
|