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