|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 #include "sechash.h" |
|
5 #include "secoidt.h" |
|
6 #include "secerr.h" |
|
7 #include "blapi.h" |
|
8 #include "pk11func.h" /* for the PK11_ calls below. */ |
|
9 |
|
10 static void * |
|
11 null_hash_new_context(void) |
|
12 { |
|
13 return NULL; |
|
14 } |
|
15 |
|
16 static void * |
|
17 null_hash_clone_context(void *v) |
|
18 { |
|
19 PORT_Assert(v == NULL); |
|
20 return NULL; |
|
21 } |
|
22 |
|
23 static void |
|
24 null_hash_begin(void *v) |
|
25 { |
|
26 } |
|
27 |
|
28 static void |
|
29 null_hash_update(void *v, const unsigned char *input, unsigned int length) |
|
30 { |
|
31 } |
|
32 |
|
33 static void |
|
34 null_hash_end(void *v, unsigned char *output, unsigned int *outLen, |
|
35 unsigned int maxOut) |
|
36 { |
|
37 *outLen = 0; |
|
38 } |
|
39 |
|
40 static void |
|
41 null_hash_destroy_context(void *v, PRBool b) |
|
42 { |
|
43 PORT_Assert(v == NULL); |
|
44 } |
|
45 |
|
46 |
|
47 static void * |
|
48 md2_NewContext(void) { |
|
49 return (void *) PK11_CreateDigestContext(SEC_OID_MD2); |
|
50 } |
|
51 |
|
52 static void * |
|
53 md5_NewContext(void) { |
|
54 return (void *) PK11_CreateDigestContext(SEC_OID_MD5); |
|
55 } |
|
56 |
|
57 static void * |
|
58 sha1_NewContext(void) { |
|
59 return (void *) PK11_CreateDigestContext(SEC_OID_SHA1); |
|
60 } |
|
61 |
|
62 static void * |
|
63 sha224_NewContext(void) { |
|
64 return (void *) PK11_CreateDigestContext(SEC_OID_SHA224); |
|
65 } |
|
66 |
|
67 static void * |
|
68 sha256_NewContext(void) { |
|
69 return (void *) PK11_CreateDigestContext(SEC_OID_SHA256); |
|
70 } |
|
71 |
|
72 static void * |
|
73 sha384_NewContext(void) { |
|
74 return (void *) PK11_CreateDigestContext(SEC_OID_SHA384); |
|
75 } |
|
76 |
|
77 static void * |
|
78 sha512_NewContext(void) { |
|
79 return (void *) PK11_CreateDigestContext(SEC_OID_SHA512); |
|
80 } |
|
81 |
|
82 const SECHashObject SECHashObjects[] = { |
|
83 { 0, |
|
84 (void * (*)(void)) null_hash_new_context, |
|
85 (void * (*)(void *)) null_hash_clone_context, |
|
86 (void (*)(void *, PRBool)) null_hash_destroy_context, |
|
87 (void (*)(void *)) null_hash_begin, |
|
88 (void (*)(void *, const unsigned char *, unsigned int)) null_hash_update, |
|
89 (void (*)(void *, unsigned char *, unsigned int *, |
|
90 unsigned int)) null_hash_end, |
|
91 0, |
|
92 HASH_AlgNULL |
|
93 }, |
|
94 { MD2_LENGTH, |
|
95 (void * (*)(void)) md2_NewContext, |
|
96 (void * (*)(void *)) PK11_CloneContext, |
|
97 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
98 (void (*)(void *)) PK11_DigestBegin, |
|
99 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
100 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
101 PK11_DigestFinal, |
|
102 MD2_BLOCK_LENGTH, |
|
103 HASH_AlgMD2 |
|
104 }, |
|
105 { MD5_LENGTH, |
|
106 (void * (*)(void)) md5_NewContext, |
|
107 (void * (*)(void *)) PK11_CloneContext, |
|
108 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
109 (void (*)(void *)) PK11_DigestBegin, |
|
110 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
111 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
112 PK11_DigestFinal, |
|
113 MD5_BLOCK_LENGTH, |
|
114 HASH_AlgMD5 |
|
115 }, |
|
116 { SHA1_LENGTH, |
|
117 (void * (*)(void)) sha1_NewContext, |
|
118 (void * (*)(void *)) PK11_CloneContext, |
|
119 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
120 (void (*)(void *)) PK11_DigestBegin, |
|
121 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
122 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
123 PK11_DigestFinal, |
|
124 SHA1_BLOCK_LENGTH, |
|
125 HASH_AlgSHA1 |
|
126 }, |
|
127 { SHA256_LENGTH, |
|
128 (void * (*)(void)) sha256_NewContext, |
|
129 (void * (*)(void *)) PK11_CloneContext, |
|
130 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
131 (void (*)(void *)) PK11_DigestBegin, |
|
132 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
133 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
134 PK11_DigestFinal, |
|
135 SHA256_BLOCK_LENGTH, |
|
136 HASH_AlgSHA256 |
|
137 }, |
|
138 { SHA384_LENGTH, |
|
139 (void * (*)(void)) sha384_NewContext, |
|
140 (void * (*)(void *)) PK11_CloneContext, |
|
141 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
142 (void (*)(void *)) PK11_DigestBegin, |
|
143 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
144 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
145 PK11_DigestFinal, |
|
146 SHA384_BLOCK_LENGTH, |
|
147 HASH_AlgSHA384 |
|
148 }, |
|
149 { SHA512_LENGTH, |
|
150 (void * (*)(void)) sha512_NewContext, |
|
151 (void * (*)(void *)) PK11_CloneContext, |
|
152 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
153 (void (*)(void *)) PK11_DigestBegin, |
|
154 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
155 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
156 PK11_DigestFinal, |
|
157 SHA512_BLOCK_LENGTH, |
|
158 HASH_AlgSHA512 |
|
159 }, |
|
160 { SHA224_LENGTH, |
|
161 (void * (*)(void)) sha224_NewContext, |
|
162 (void * (*)(void *)) PK11_CloneContext, |
|
163 (void (*)(void *, PRBool)) PK11_DestroyContext, |
|
164 (void (*)(void *)) PK11_DigestBegin, |
|
165 (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, |
|
166 (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) |
|
167 PK11_DigestFinal, |
|
168 SHA224_BLOCK_LENGTH, |
|
169 HASH_AlgSHA224 |
|
170 }, |
|
171 }; |
|
172 |
|
173 const SECHashObject * |
|
174 HASH_GetHashObject(HASH_HashType type) |
|
175 { |
|
176 return &SECHashObjects[type]; |
|
177 } |
|
178 |
|
179 HASH_HashType |
|
180 HASH_GetHashTypeByOidTag(SECOidTag hashOid) |
|
181 { |
|
182 HASH_HashType ht = HASH_AlgNULL; |
|
183 |
|
184 switch(hashOid) { |
|
185 case SEC_OID_MD2: ht = HASH_AlgMD2; break; |
|
186 case SEC_OID_MD5: ht = HASH_AlgMD5; break; |
|
187 case SEC_OID_SHA1: ht = HASH_AlgSHA1; break; |
|
188 case SEC_OID_SHA224: ht = HASH_AlgSHA224; break; |
|
189 case SEC_OID_SHA256: ht = HASH_AlgSHA256; break; |
|
190 case SEC_OID_SHA384: ht = HASH_AlgSHA384; break; |
|
191 case SEC_OID_SHA512: ht = HASH_AlgSHA512; break; |
|
192 default: ht = HASH_AlgNULL; |
|
193 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
|
194 break; |
|
195 } |
|
196 return ht; |
|
197 } |
|
198 |
|
199 SECOidTag |
|
200 HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid) |
|
201 { |
|
202 SECOidTag hashOid = SEC_OID_UNKNOWN; |
|
203 |
|
204 switch(hmacOid) { |
|
205 /* no oid exists for HMAC_MD2 */ |
|
206 /* NSS does not define a oid for HMAC_MD4 */ |
|
207 case SEC_OID_HMAC_SHA1: hashOid = SEC_OID_SHA1; break; |
|
208 case SEC_OID_HMAC_SHA224: hashOid = SEC_OID_SHA224; break; |
|
209 case SEC_OID_HMAC_SHA256: hashOid = SEC_OID_SHA256; break; |
|
210 case SEC_OID_HMAC_SHA384: hashOid = SEC_OID_SHA384; break; |
|
211 case SEC_OID_HMAC_SHA512: hashOid = SEC_OID_SHA512; break; |
|
212 default: hashOid = SEC_OID_UNKNOWN; |
|
213 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
|
214 break; |
|
215 } |
|
216 return hashOid; |
|
217 } |
|
218 |
|
219 SECOidTag |
|
220 HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid) |
|
221 { |
|
222 SECOidTag hmacOid = SEC_OID_UNKNOWN; |
|
223 |
|
224 switch(hashOid) { |
|
225 /* no oid exists for HMAC_MD2 */ |
|
226 /* NSS does not define a oid for HMAC_MD4 */ |
|
227 case SEC_OID_SHA1: hmacOid = SEC_OID_HMAC_SHA1; break; |
|
228 case SEC_OID_SHA224: hmacOid = SEC_OID_HMAC_SHA224; break; |
|
229 case SEC_OID_SHA256: hmacOid = SEC_OID_HMAC_SHA256; break; |
|
230 case SEC_OID_SHA384: hmacOid = SEC_OID_HMAC_SHA384; break; |
|
231 case SEC_OID_SHA512: hmacOid = SEC_OID_HMAC_SHA512; break; |
|
232 default: hmacOid = SEC_OID_UNKNOWN; |
|
233 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
|
234 break; |
|
235 } |
|
236 return hmacOid; |
|
237 } |
|
238 |
|
239 const SECHashObject * |
|
240 HASH_GetHashObjectByOidTag(SECOidTag hashOid) |
|
241 { |
|
242 HASH_HashType ht = HASH_GetHashTypeByOidTag(hashOid); |
|
243 |
|
244 return (ht == HASH_AlgNULL) ? NULL : &SECHashObjects[ht]; |
|
245 } |
|
246 |
|
247 /* returns zero for unknown hash OID */ |
|
248 unsigned int |
|
249 HASH_ResultLenByOidTag(SECOidTag hashOid) |
|
250 { |
|
251 const SECHashObject * hashObject = HASH_GetHashObjectByOidTag(hashOid); |
|
252 unsigned int resultLen = 0; |
|
253 |
|
254 if (hashObject) |
|
255 resultLen = hashObject->length; |
|
256 return resultLen; |
|
257 } |
|
258 |
|
259 /* returns zero if hash type invalid. */ |
|
260 unsigned int |
|
261 HASH_ResultLen(HASH_HashType type) |
|
262 { |
|
263 if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) { |
|
264 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
|
265 return(0); |
|
266 } |
|
267 |
|
268 return(SECHashObjects[type].length); |
|
269 } |
|
270 |
|
271 unsigned int |
|
272 HASH_ResultLenContext(HASHContext *context) |
|
273 { |
|
274 return(context->hashobj->length); |
|
275 } |
|
276 |
|
277 |
|
278 |
|
279 SECStatus |
|
280 HASH_HashBuf(HASH_HashType type, |
|
281 unsigned char *dest, |
|
282 const unsigned char *src, |
|
283 PRUint32 src_len) |
|
284 { |
|
285 HASHContext *cx; |
|
286 unsigned int part; |
|
287 |
|
288 if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) { |
|
289 return(SECFailure); |
|
290 } |
|
291 |
|
292 cx = HASH_Create(type); |
|
293 if ( cx == NULL ) { |
|
294 return(SECFailure); |
|
295 } |
|
296 HASH_Begin(cx); |
|
297 HASH_Update(cx, src, src_len); |
|
298 HASH_End(cx, dest, &part, HASH_ResultLenContext(cx)); |
|
299 HASH_Destroy(cx); |
|
300 |
|
301 return(SECSuccess); |
|
302 } |
|
303 |
|
304 HASHContext * |
|
305 HASH_Create(HASH_HashType type) |
|
306 { |
|
307 void *hash_context = NULL; |
|
308 HASHContext *ret = NULL; |
|
309 |
|
310 if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) { |
|
311 return(NULL); |
|
312 } |
|
313 |
|
314 hash_context = (* SECHashObjects[type].create)(); |
|
315 if ( hash_context == NULL ) { |
|
316 goto loser; |
|
317 } |
|
318 |
|
319 ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext)); |
|
320 if ( ret == NULL ) { |
|
321 goto loser; |
|
322 } |
|
323 |
|
324 ret->hash_context = hash_context; |
|
325 ret->hashobj = &SECHashObjects[type]; |
|
326 |
|
327 return(ret); |
|
328 |
|
329 loser: |
|
330 if ( hash_context != NULL ) { |
|
331 (* SECHashObjects[type].destroy)(hash_context, PR_TRUE); |
|
332 } |
|
333 |
|
334 return(NULL); |
|
335 } |
|
336 |
|
337 |
|
338 HASHContext * |
|
339 HASH_Clone(HASHContext *context) |
|
340 { |
|
341 void *hash_context = NULL; |
|
342 HASHContext *ret = NULL; |
|
343 |
|
344 hash_context = (* context->hashobj->clone)(context->hash_context); |
|
345 if ( hash_context == NULL ) { |
|
346 goto loser; |
|
347 } |
|
348 |
|
349 ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext)); |
|
350 if ( ret == NULL ) { |
|
351 goto loser; |
|
352 } |
|
353 |
|
354 ret->hash_context = hash_context; |
|
355 ret->hashobj = context->hashobj; |
|
356 |
|
357 return(ret); |
|
358 |
|
359 loser: |
|
360 if ( hash_context != NULL ) { |
|
361 (* context->hashobj->destroy)(hash_context, PR_TRUE); |
|
362 } |
|
363 |
|
364 return(NULL); |
|
365 |
|
366 } |
|
367 |
|
368 void |
|
369 HASH_Destroy(HASHContext *context) |
|
370 { |
|
371 (* context->hashobj->destroy)(context->hash_context, PR_TRUE); |
|
372 PORT_Free(context); |
|
373 return; |
|
374 } |
|
375 |
|
376 |
|
377 void |
|
378 HASH_Begin(HASHContext *context) |
|
379 { |
|
380 (* context->hashobj->begin)(context->hash_context); |
|
381 return; |
|
382 } |
|
383 |
|
384 |
|
385 void |
|
386 HASH_Update(HASHContext *context, |
|
387 const unsigned char *src, |
|
388 unsigned int len) |
|
389 { |
|
390 (* context->hashobj->update)(context->hash_context, src, len); |
|
391 return; |
|
392 } |
|
393 |
|
394 void |
|
395 HASH_End(HASHContext *context, |
|
396 unsigned char *result, |
|
397 unsigned int *result_len, |
|
398 unsigned int max_result_len) |
|
399 { |
|
400 (* context->hashobj->end)(context->hash_context, result, result_len, |
|
401 max_result_len); |
|
402 return; |
|
403 } |
|
404 |
|
405 HASH_HashType |
|
406 HASH_GetType(HASHContext *context) |
|
407 { |
|
408 return(context->hashobj->type); |
|
409 } |