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