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 *
null_hash_new_context(void)11 null_hash_new_context(void)
12 {
13 return NULL;
14 }
15
16 static void *
null_hash_clone_context(void * v)17 null_hash_clone_context(void *v)
18 {
19 PORT_Assert(v == NULL);
20 return NULL;
21 }
22
23 static void
null_hash_begin(void * v)24 null_hash_begin(void *v)
25 {
26 }
27
28 static void
null_hash_update(void * v,const unsigned char * input,unsigned int length)29 null_hash_update(void *v, const unsigned char *input, unsigned int length)
30 {
31 }
32
33 static void
null_hash_end(void * v,unsigned char * output,unsigned int * outLen,unsigned int maxOut)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
null_hash_destroy_context(void * v,PRBool b)41 null_hash_destroy_context(void *v, PRBool b)
42 {
43 PORT_Assert(v == NULL);
44 }
45
46 static void *
md2_NewContext(void)47 md2_NewContext(void)
48 {
49 return (void *)PK11_CreateDigestContext(SEC_OID_MD2);
50 }
51
52 static void *
md5_NewContext(void)53 md5_NewContext(void)
54 {
55 return (void *)PK11_CreateDigestContext(SEC_OID_MD5);
56 }
57
58 static void *
sha1_NewContext(void)59 sha1_NewContext(void)
60 {
61 return (void *)PK11_CreateDigestContext(SEC_OID_SHA1);
62 }
63
64 static void *
sha224_NewContext(void)65 sha224_NewContext(void)
66 {
67 return (void *)PK11_CreateDigestContext(SEC_OID_SHA224);
68 }
69
70 static void *
sha256_NewContext(void)71 sha256_NewContext(void)
72 {
73 return (void *)PK11_CreateDigestContext(SEC_OID_SHA256);
74 }
75
76 static void *
sha384_NewContext(void)77 sha384_NewContext(void)
78 {
79 return (void *)PK11_CreateDigestContext(SEC_OID_SHA384);
80 }
81
82 static void *
sha512_NewContext(void)83 sha512_NewContext(void)
84 {
85 return (void *)PK11_CreateDigestContext(SEC_OID_SHA512);
86 }
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 *
HASH_GetHashObject(HASH_HashType type)172 HASH_GetHashObject(HASH_HashType type)
173 {
174 return &SECHashObjects[type];
175 }
176
177 HASH_HashType
HASH_GetHashTypeByOidTag(SECOidTag hashOid)178 HASH_GetHashTypeByOidTag(SECOidTag hashOid)
179 {
180 HASH_HashType ht = HASH_AlgNULL;
181
182 switch (hashOid) {
183 case SEC_OID_MD2:
184 ht = HASH_AlgMD2;
185 break;
186 case SEC_OID_MD5:
187 ht = HASH_AlgMD5;
188 break;
189 case SEC_OID_SHA1:
190 ht = HASH_AlgSHA1;
191 break;
192 case SEC_OID_SHA224:
193 ht = HASH_AlgSHA224;
194 break;
195 case SEC_OID_SHA256:
196 ht = HASH_AlgSHA256;
197 break;
198 case SEC_OID_SHA384:
199 ht = HASH_AlgSHA384;
200 break;
201 case SEC_OID_SHA512:
202 ht = HASH_AlgSHA512;
203 break;
204 default:
205 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
206 break;
207 }
208 return ht;
209 }
210
211 SECOidTag
HASH_GetHashOidTagByHashType(HASH_HashType type)212 HASH_GetHashOidTagByHashType(HASH_HashType type)
213 {
214 SECOidTag oid = SEC_OID_UNKNOWN;
215
216 switch (type) {
217 case HASH_AlgMD2:
218 oid = SEC_OID_MD2;
219 break;
220 case HASH_AlgMD5:
221 oid = SEC_OID_MD5;
222 break;
223 case HASH_AlgSHA1:
224 oid = SEC_OID_SHA1;
225 break;
226 case HASH_AlgSHA224:
227 oid = SEC_OID_SHA224;
228 break;
229 case HASH_AlgSHA256:
230 oid = SEC_OID_SHA256;
231 break;
232 case HASH_AlgSHA384:
233 oid = SEC_OID_SHA384;
234 break;
235 case HASH_AlgSHA512:
236 oid = SEC_OID_SHA512;
237 break;
238 default:
239 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
240 break;
241 }
242 return oid;
243 }
244
245 SECOidTag
HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)246 HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)
247 {
248 SECOidTag hashOid = SEC_OID_UNKNOWN;
249
250 switch (hmacOid) {
251 /* no oid exists for HMAC_MD2 */
252 /* NSS does not define a oid for HMAC_MD4 */
253 case SEC_OID_HMAC_SHA1:
254 hashOid = SEC_OID_SHA1;
255 break;
256 case SEC_OID_HMAC_SHA224:
257 hashOid = SEC_OID_SHA224;
258 break;
259 case SEC_OID_HMAC_SHA256:
260 hashOid = SEC_OID_SHA256;
261 break;
262 case SEC_OID_HMAC_SHA384:
263 hashOid = SEC_OID_SHA384;
264 break;
265 case SEC_OID_HMAC_SHA512:
266 hashOid = SEC_OID_SHA512;
267 break;
268 default:
269 hashOid = SEC_OID_UNKNOWN;
270 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
271 break;
272 }
273 return hashOid;
274 }
275
276 SECOidTag
HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)277 HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)
278 {
279 SECOidTag hmacOid = SEC_OID_UNKNOWN;
280
281 switch (hashOid) {
282 /* no oid exists for HMAC_MD2 */
283 /* NSS does not define a oid for HMAC_MD4 */
284 case SEC_OID_SHA1:
285 hmacOid = SEC_OID_HMAC_SHA1;
286 break;
287 case SEC_OID_SHA224:
288 hmacOid = SEC_OID_HMAC_SHA224;
289 break;
290 case SEC_OID_SHA256:
291 hmacOid = SEC_OID_HMAC_SHA256;
292 break;
293 case SEC_OID_SHA384:
294 hmacOid = SEC_OID_HMAC_SHA384;
295 break;
296 case SEC_OID_SHA512:
297 hmacOid = SEC_OID_HMAC_SHA512;
298 break;
299 default:
300 hmacOid = SEC_OID_UNKNOWN;
301 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
302 break;
303 }
304 return hmacOid;
305 }
306
307 const SECHashObject *
HASH_GetHashObjectByOidTag(SECOidTag hashOid)308 HASH_GetHashObjectByOidTag(SECOidTag hashOid)
309 {
310 HASH_HashType ht = HASH_GetHashTypeByOidTag(hashOid);
311
312 return (ht == HASH_AlgNULL) ? NULL : &SECHashObjects[ht];
313 }
314
315 /* returns zero for unknown hash OID */
316 unsigned int
HASH_ResultLenByOidTag(SECOidTag hashOid)317 HASH_ResultLenByOidTag(SECOidTag hashOid)
318 {
319 const SECHashObject *hashObject = HASH_GetHashObjectByOidTag(hashOid);
320 unsigned int resultLen = 0;
321
322 if (hashObject)
323 resultLen = hashObject->length;
324 return resultLen;
325 }
326
327 /* returns zero if hash type invalid. */
328 unsigned int
HASH_ResultLen(HASH_HashType type)329 HASH_ResultLen(HASH_HashType type)
330 {
331 if ((type < HASH_AlgNULL) || (type >= HASH_AlgTOTAL)) {
332 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
333 return (0);
334 }
335
336 return (SECHashObjects[type].length);
337 }
338
339 unsigned int
HASH_ResultLenContext(HASHContext * context)340 HASH_ResultLenContext(HASHContext *context)
341 {
342 return (context->hashobj->length);
343 }
344
345 SECStatus
HASH_HashBuf(HASH_HashType type,unsigned char * dest,const unsigned char * src,PRUint32 src_len)346 HASH_HashBuf(HASH_HashType type,
347 unsigned char *dest,
348 const unsigned char *src,
349 PRUint32 src_len)
350 {
351 HASHContext *cx;
352 unsigned int part;
353
354 if ((type < HASH_AlgNULL) || (type >= HASH_AlgTOTAL)) {
355 return (SECFailure);
356 }
357
358 cx = HASH_Create(type);
359 if (cx == NULL) {
360 return (SECFailure);
361 }
362 HASH_Begin(cx);
363 HASH_Update(cx, src, src_len);
364 HASH_End(cx, dest, &part, HASH_ResultLenContext(cx));
365 HASH_Destroy(cx);
366
367 return (SECSuccess);
368 }
369
370 HASHContext *
HASH_Create(HASH_HashType type)371 HASH_Create(HASH_HashType type)
372 {
373 void *hash_context = NULL;
374 HASHContext *ret = NULL;
375
376 if ((type < HASH_AlgNULL) || (type >= HASH_AlgTOTAL)) {
377 return (NULL);
378 }
379
380 hash_context = (*SECHashObjects[type].create)();
381 if (hash_context == NULL) {
382 goto loser;
383 }
384
385 ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext));
386 if (ret == NULL) {
387 goto loser;
388 }
389
390 ret->hash_context = hash_context;
391 ret->hashobj = &SECHashObjects[type];
392
393 return (ret);
394
395 loser:
396 if (hash_context != NULL) {
397 (*SECHashObjects[type].destroy)(hash_context, PR_TRUE);
398 }
399
400 return (NULL);
401 }
402
403 HASHContext *
HASH_Clone(HASHContext * context)404 HASH_Clone(HASHContext *context)
405 {
406 void *hash_context = NULL;
407 HASHContext *ret = NULL;
408
409 hash_context = (*context->hashobj->clone)(context->hash_context);
410 if (hash_context == NULL) {
411 goto loser;
412 }
413
414 ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext));
415 if (ret == NULL) {
416 goto loser;
417 }
418
419 ret->hash_context = hash_context;
420 ret->hashobj = context->hashobj;
421
422 return (ret);
423
424 loser:
425 if (hash_context != NULL) {
426 (*context->hashobj->destroy)(hash_context, PR_TRUE);
427 }
428
429 return (NULL);
430 }
431
432 void
HASH_Destroy(HASHContext * context)433 HASH_Destroy(HASHContext *context)
434 {
435 (*context->hashobj->destroy)(context->hash_context, PR_TRUE);
436 PORT_Free(context);
437 return;
438 }
439
440 void
HASH_Begin(HASHContext * context)441 HASH_Begin(HASHContext *context)
442 {
443 (*context->hashobj->begin)(context->hash_context);
444 return;
445 }
446
447 void
HASH_Update(HASHContext * context,const unsigned char * src,unsigned int len)448 HASH_Update(HASHContext *context,
449 const unsigned char *src,
450 unsigned int len)
451 {
452 (*context->hashobj->update)(context->hash_context, src, len);
453 return;
454 }
455
456 void
HASH_End(HASHContext * context,unsigned char * result,unsigned int * result_len,unsigned int max_result_len)457 HASH_End(HASHContext *context,
458 unsigned char *result,
459 unsigned int *result_len,
460 unsigned int max_result_len)
461 {
462 (*context->hashobj->end)(context->hash_context, result, result_len,
463 max_result_len);
464 return;
465 }
466
467 HASH_HashType
HASH_GetType(HASHContext * context)468 HASH_GetType(HASHContext *context)
469 {
470 return (context->hashobj->type);
471 }
472