Fossil SCM

fossil-scm / src / hname.c
Blame History Raw 285 lines
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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button