1/* 2 * Copyright (c) 2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// #define COMMON_DIGEST_FUNCTIONS 25#define COMMON_DIGEST_FOR_RFC_1321 26 27#include "CommonDigest.h" 28#include "CommonDigestPriv.h" 29#include "CommonDigestSPI.h" 30#include "ccErrors.h" 31#include "ccGlobals.h" 32#include "ccMemory.h" 33#include "ccdebug.h" 34#include <stdio.h> 35#include <dispatch/dispatch.h> 36#include <dispatch/queue.h> 37#include <corecrypto/ccmd2.h> 38#include <corecrypto/ccmd4.h> 39#include <corecrypto/ccmd5.h> 40#include <corecrypto/ccripemd.h> 41#include <corecrypto/ccsha1.h> 42#include <corecrypto/ccsha2.h> 43 44// #define NDEBUG 45#ifndef NDEBUG 46#define ASSERT(s) 47#else 48#define ASSERT(s) assert(s) 49#endif 50 51static const size_t diMax = kCCDigestSkein512+1; 52 53// This returns a pointer to the corecrypto "di" structure for a digest. 54// It's used for all functions that need a di (HMac, Key Derivation, etc). 55 56const struct ccdigest_info * 57CCDigestGetDigestInfo(CCDigestAlgorithm algorithm) { 58 cc_globals_t globals = _cc_globals(); 59 dispatch_once(&globals->digest_info_init, ^{ 60 globals->digest_info = (const struct ccdigest_info **)calloc(diMax, sizeof(struct ccdigest_info *)); 61 globals->digest_info[kCCDigestNone] = NULL; 62 globals->digest_info[kCCDigestMD2] = &ccmd2_di; 63 globals->digest_info[kCCDigestMD4] = &ccmd4_di; 64 globals->digest_info[kCCDigestMD5] = ccmd5_di(); 65 globals->digest_info[kCCDigestRMD128] = &ccrmd128_di; 66 globals->digest_info[kCCDigestRMD160] = &ccrmd160_di; 67 globals->digest_info[kCCDigestRMD256] = &ccrmd256_di; 68 globals->digest_info[kCCDigestRMD320] = &ccrmd320_di; 69 globals->digest_info[kCCDigestSHA1] = ccsha1_di(); 70 globals->digest_info[kCCDigestSHA224] = ccsha224_di(); 71 globals->digest_info[kCCDigestSHA256] = ccsha256_di(); 72 globals->digest_info[kCCDigestSHA384] = ccsha384_di(); 73 globals->digest_info[kCCDigestSHA512] = ccsha512_di(); 74 globals->digest_info[kCCDigestSkein128] = NULL; 75 globals->digest_info[kCCDigestSkein160] = NULL; 76 globals->digest_info[15] = NULL; // gap 77 globals->digest_info[kCCDigestSkein224] = NULL; 78 globals->digest_info[kCCDigestSkein256] = NULL; 79 globals->digest_info[kCCDigestSkein384] = NULL; 80 globals->digest_info[kCCDigestSkein512] = NULL; 81 }); 82 return globals->digest_info[algorithm]; 83} 84 85 86int 87CCDigestInit(CCDigestAlgorithm alg, CCDigestRef c) 88{ 89 if(alg == 0 || alg >= diMax) return kCCParamError; 90 if(!c) return kCCParamError; 91 92 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", alg); 93 CCDigestCtxPtr p = (CCDigestCtxPtr) c; 94 95 if((p->di = CCDigestGetDigestInfo(alg)) != NULL) { 96 ccdigest_init(p->di, (struct ccdigest_ctx *) p->md); 97 return 0; 98 } else { 99 return kCCUnimplemented; 100 } 101} 102 103int 104CCDigestUpdate(CCDigestRef c, const void *data, size_t len) 105{ 106 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 107 if(c == NULL) return kCCParamError; 108 if(len == 0) return kCCSuccess; 109 if(data == NULL) return kCCParamError; /* this is only a problem if len > 0 */ 110 CCDigestCtxPtr p = (CCDigestCtxPtr) c; 111 if(p->di) { 112 ccdigest_update(p->di, (struct ccdigest_ctx *) p->md, len, data); 113 return kCCSuccess; 114 } 115 return kCCUnimplemented; 116} 117 118int 119CCDigestFinal(CCDigestRef c, uint8_t *out) 120{ 121 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 122 if(c == NULL || out == NULL) return kCCParamError; 123 CCDigestCtxPtr p = (CCDigestCtxPtr) c; 124 if(p->di) { 125 ccdigest_final(p->di, (struct ccdigest_ctx *) p->md, out); 126 return 0; 127 } 128 return kCCUnimplemented; 129} 130 131int 132CCDigest(CCDigestAlgorithm alg, const uint8_t *data, size_t len, uint8_t *out) 133{ 134 const struct ccdigest_info *di; 135 136 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", alg); 137 if((di = CCDigestGetDigestInfo(alg)) != NULL) { 138 ccdigest(di, len, data, out); 139 return 0; 140 } 141 return kCCUnimplemented; 142} 143 144size_t 145CCDigestGetBlockSize(CCDigestAlgorithm algorithm) 146{ 147 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", algorithm); 148 const struct ccdigest_info *di = CCDigestGetDigestInfo(algorithm); 149 if(di) return di->block_size; 150 return kCCUnimplemented; 151} 152 153size_t 154CCDigestGetOutputSize(CCDigestAlgorithm algorithm) 155{ 156 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", algorithm); 157 const struct ccdigest_info *di = CCDigestGetDigestInfo(algorithm); 158 if(di) return di->output_size; 159 return kCCUnimplemented; 160} 161 162size_t 163CCDigestGetBlockSizeFromRef(CCDigestRef ctx) 164{ 165 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 166 CCDigestCtxPtr p = (CCDigestCtxPtr) ctx; 167 if(p->di) return p->di->block_size; 168 return kCCUnimplemented; 169} 170 171size_t 172CCDigestBlockSize(CCDigestRef ctx) 173{ 174 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 175 return CCDigestGetBlockSizeFromRef(ctx); 176} 177 178size_t 179CCDigestOutputSize(CCDigestRef ctx) 180{ 181 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 182 return CCDigestGetOutputSizeFromRef(ctx); 183} 184 185size_t 186CCDigestGetOutputSizeFromRef(CCDigestRef ctx) 187{ 188 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 189 CCDigestCtxPtr p = (CCDigestCtxPtr) ctx; 190 if(p->di) return p->di->output_size; 191 return kCCUnimplemented; 192} 193 194 195 196 197 198CCDigestRef 199CCDigestCreate(CCDigestAlgorithm alg) 200{ 201 CCDigestRef retval = CC_XMALLOC(sizeof(CCDigestCtx)); 202 203 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 204 if(!retval) return NULL; 205 if(CCDigestInit(alg, retval)) { 206 CC_XFREE(retval, sizeof(CCDigestCtx_t)); 207 return NULL; 208 } 209 return retval; 210} 211 212 213uint8_t * 214CCDigestOID(CCDigestRef ctx) 215{ 216 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 217 CCDigestCtxPtr p = (CCDigestCtxPtr) ctx; 218 return p->di->oid; 219} 220 221size_t 222CCDigestOIDLen(CCDigestRef ctx) 223{ 224 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 225 CCDigestCtxPtr p = (CCDigestCtxPtr) ctx; 226 return p->di->oid_size; 227} 228 229CCDigestRef 230CCDigestCreateByOID(uint8_t *OID, size_t OIDlen) 231{ 232 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 233 for(unsigned int i=kCCDigestMD2; i<diMax; i++) { 234 const struct ccdigest_info *di = CCDigestGetDigestInfo(i); 235 if(di && (OIDlen == di->oid_size) && (CC_XMEMCMP(OID, di->oid, OIDlen) == 0)) 236 return CCDigestCreate(i); 237 } 238 return NULL; 239} 240 241void 242CCDigestReset(CCDigestRef ctx) 243{ 244 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 245 CCDigestCtxPtr p = (CCDigestCtxPtr) ctx; 246 if(p->di) ccdigest_init(p->di, (struct ccdigest_ctx *) p->md); 247} 248 249 250void 251CCDigestDestroy(CCDigestRef ctx) 252{ 253 // CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 254 if(ctx) { 255 CC_XZEROMEM(ctx, sizeof(CCDigestCtx_t)); 256 CC_XFREE(ctx, sizeof(CCDigestCtx_t)); 257 } 258} 259/* 260 * Legacy CommonDigest API shims. 261 */ 262 263#define CC_COMPAT_DIGEST_RETURN 1 264 265// corecrypto to CommonCrypto 266#define CC_ccToCC_DIGEST_CTX(di,cc_c,CC_c) \ 267 CC_XMEMCPY((uint8_t*)CC_c, ccdigest_state_u8(di, cc_c), di->state_size); \ 268 CC_XMEMCPY(&CC_c->data[0], ccdigest_data(di, cc_c), di->block_size); \ 269 CC_XMEMCPY(&CC_c->Nl, &ccdigest_nbits(di, cc_c), 2*sizeof(CC_c->Nl)); \ 270 CC_c->num=ccdigest_num(di, cc_c); 271 272// CommonCrypto to corecrypto 273#define CC_CCTocc_DIGEST_CTX(di,CC_c,cc_c) \ 274 CC_XMEMCPY(ccdigest_state_u8(di, cc_c), (uint8_t*)CC_c, di->state_size); \ 275 CC_XMEMCPY(ccdigest_data(di, cc_c), &CC_c->data[0], di->block_size); \ 276 CC_XMEMCPY(&ccdigest_nbits(di, cc_c), &CC_c->Nl, 2*sizeof(CC_c->Nl)); \ 277 ccdigest_num(di, cc_c)=CC_c->num; 278 279 280#define DIGEST_SHIMS(_name_,_constant_) \ 281\ 282int CC_##_name_##_Init(CC_##_name_##_CTX *CC_ctx) { \ 283 ASSERT(sizeof(CC_##_name_##_CTX) <= ccdigest_di_size(CCDigestGetDigestInfo(_constant_))); \ 284 const struct ccdigest_info *di=CCDigestGetDigestInfo(_constant_); \ 285 ccdigest_di_decl(di, cc_ctx); \ 286 ccdigest_init(di, cc_ctx); \ 287 CC_ccToCC_DIGEST_CTX(di,cc_ctx,CC_ctx); \ 288 return 1; \ 289} \ 290 \ 291int \ 292CC_##_name_##_Update(CC_##_name_##_CTX *CC_ctx, const void *data, CC_LONG len) \ 293{ \ 294 const struct ccdigest_info *di=CCDigestGetDigestInfo(_constant_); \ 295 ccdigest_di_decl(di, cc_ctx); \ 296 CC_CCTocc_DIGEST_CTX(di,CC_ctx,cc_ctx); \ 297 ccdigest_update(di, cc_ctx, len, data); \ 298 CC_ccToCC_DIGEST_CTX(di,cc_ctx,CC_ctx); \ 299 return 1; \ 300} \ 301 \ 302int \ 303CC_##_name_##_Final(unsigned char *md, CC_##_name_##_CTX *CC_ctx) \ 304{ \ 305 const struct ccdigest_info *di=CCDigestGetDigestInfo(_constant_); \ 306 ccdigest_di_decl(di, cc_ctx); \ 307 CC_CCTocc_DIGEST_CTX(di,CC_ctx,cc_ctx); \ 308 ccdigest_final(di, cc_ctx, md); \ 309 CC_ccToCC_DIGEST_CTX(di,cc_ctx,CC_ctx); \ 310 return 1; \ 311} \ 312 \ 313unsigned char * \ 314CC_##_name_ (const void *data, CC_LONG len, unsigned char *md) \ 315{ \ 316 (void) CCDigest(_constant_, data, len, md); \ 317 return md; \ 318} 319 320 321#define DIGEST_FINAL_SHIMS(_name_,_constant_) \ 322unsigned char * \ 323CC_##_name_ (const void *data, CC_LONG len, unsigned char *md) \ 324{ \ 325(void) CCDigest(_constant_, data, len, md); \ 326return md; \ 327} 328 329 330 331DIGEST_FINAL_SHIMS(MD2, kCCDigestMD2) 332DIGEST_SHIMS(MD4, kCCDigestMD4) 333DIGEST_SHIMS(MD5, kCCDigestMD5) 334DIGEST_SHIMS(SHA1, kCCDigestSHA1) 335DIGEST_FINAL_SHIMS(SHA224, kCCDigestSHA224) 336DIGEST_FINAL_SHIMS(SHA256, kCCDigestSHA256) 337DIGEST_FINAL_SHIMS(SHA384, kCCDigestSHA384) 338DIGEST_FINAL_SHIMS(SHA512, kCCDigestSHA512) 339 340 341#define MD5_CTX CC_MD5_CTX 342void MD5Final(unsigned char md[16], MD5_CTX *c) 343{ 344 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 345 (void) CC_MD5_Final(md, c); 346} 347 348static void 349ccdigest_process(const struct ccdigest_info *di, uint8_t *bufptr, ccdigest_state_t state, 350 uint64_t curlen, size_t len, const uint8_t *data) 351{ 352 while(len) { 353 if (curlen == 0 && len >= di->block_size) { 354 uint64_t fullblocks = len / di->block_size; 355 di->compress(state, (unsigned long) fullblocks, data); 356 uint64_t nbytes = fullblocks * di->block_size; 357 len -= nbytes; data += nbytes; 358 } else { 359 uint64_t n = CC_XMIN(len, (di->block_size - curlen)); 360 CC_XMEMCPY(bufptr + curlen, data, n); 361 curlen += n; len -= n; data += n; 362 if (curlen == di->block_size) { 363 di->compress(state, 1, bufptr); 364 curlen = 0; 365 } 366 } 367 } 368} 369 370static void 371ccdigest_finalize(const struct ccdigest_info *di, uint8_t *bufptr, ccdigest_state_t state, 372 uint64_t curlen, uint64_t totalLen) 373{ 374 bufptr[curlen++] = (unsigned char)0x80; 375 int reserve = 8; 376 if(di->block_size == 128) reserve = 16; // SHA384/512 reserves 16 bytes below. 377 378 /* if the length is currently above block_size - reserve bytes we append zeros 379 * then compress. Then we can fall back to padding zeros and length 380 * encoding like normal. 381 */ 382 383 if (curlen > (di->block_size - reserve)) { 384 while (curlen < di->block_size) bufptr[curlen++] = (unsigned char)0; 385 di->compress(state, 1, bufptr); 386 curlen = 0; 387 } 388 389 /* pad out with zeros, but store length in last 8 bytes (sizeof uint64_t) */ 390 while (curlen < (di->block_size - 8)) bufptr[curlen++] = (unsigned char)0; 391 totalLen *= 8; // size in bits 392 CC_XSTORE64H(totalLen, bufptr+(di->block_size - 8)); 393 di->compress(state, 1, bufptr); 394} 395 396/* 397 #define CC_MD2_DIGEST_LENGTH 16 398 #define CC_MD2_BLOCK_BYTES 64 399 #define CC_MD2_BLOCK_LONG (CC_MD2_BLOCK_BYTES / sizeof(CC_LONG)) 400 401 402 typedef struct CC_MD2state_st 403 { 404 int num; 405 unsigned char data[CC_MD2_DIGEST_LENGTH]; 406 CC_LONG cksm[CC_MD2_BLOCK_LONG]; 407 CC_LONG state[CC_MD2_BLOCK_LONG]; 408 } CC_MD2_CTX; 409 */ 410 411static inline void md2in(const struct ccdigest_info *di, ccdigest_ctx_t ctx, CC_MD2_CTX *c) 412{ 413 CC_XMEMCPY(ccdigest_state_u8(di, ctx)+48, c->cksm, CC_MD2_BLOCK_LONG); 414 CC_XMEMCPY(ccdigest_state_u8(di, ctx), c->state, CC_MD2_BLOCK_LONG); 415 CC_XMEMCPY(ccdigest_data(di, ctx), c->data, CC_MD2_DIGEST_LENGTH); 416 ccdigest_num(di, ctx) = c->num; 417} 418 419static inline void md2out(const struct ccdigest_info *di, CC_MD2_CTX *c, ccdigest_ctx_t ctx) 420{ 421 CC_XMEMCPY(c->cksm, ccdigest_state_u8(di, ctx)+48, CC_MD2_BLOCK_LONG); 422 CC_XMEMCPY(c->state, ccdigest_state_u8(di, ctx), CC_MD2_BLOCK_LONG); 423 CC_XMEMCPY(c->data, ccdigest_data(di, ctx), CC_MD2_DIGEST_LENGTH); 424 c->num = (int) ccdigest_num(di, ctx); 425} 426 427int CC_MD2_Init(CC_MD2_CTX *c) 428{ 429 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestMD2); 430 ccdigest_di_decl(di, ctx); 431 ccdigest_init(di, ctx); 432 md2out(di, c, ctx); 433 return CC_COMPAT_DIGEST_RETURN; 434} 435 436int CC_MD2_Update(CC_MD2_CTX *c, const void *data, CC_LONG len) 437{ 438 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestMD2); 439 ccdigest_di_decl(di, ctx); 440 md2in(di, ctx, c); 441 ccdigest_update(di, ctx, len, data); 442 md2out(di, c, ctx); 443 return CC_COMPAT_DIGEST_RETURN; 444} 445 446int CC_MD2_Final(unsigned char *md, CC_MD2_CTX *c) 447{ 448 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestMD2); 449 ccdigest_di_decl(di, ctx); 450 md2in(di, ctx, c); 451 ccdigest_final(di, ctx, md); 452 md2out(di, c, ctx); 453 return CC_COMPAT_DIGEST_RETURN; 454} 455 456 457 458 459 460/* 461 typedef struct CC_SHA256state_st 462 { 463 CC_LONG count[2]; 464 CC_LONG hash[8]; 465 CC_LONG wbuf[16]; 466 } CC_SHA256_CTX; 467 468 */ 469 470typedef struct CC_SHA256state_x 471{ 472 uint64_t count; 473 uint32_t hash[8]; 474 uint32_t wbuf[16]; 475} CC_SHA256_CTX_X; 476 477 478 479int 480CC_SHA256_Init(CC_SHA256_CTX *x) 481{ 482 CC_SHA256_CTX_X *c = (CC_SHA256_CTX_X *) x; 483 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 484 ASSERT(sizeof(CC_SHA256_CTX) == sizeof(CC_SHA256_CTX_X)); 485 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA256); 486 ASSERT(di->state_size == CC_SHA256_DIGEST_LENGTH); 487 CC_XZEROMEM(c->hash, CC_SHA256_DIGEST_LENGTH); 488 ASSERT(di->block_size == CC_SHA256_BLOCK_BYTES); 489 CC_XZEROMEM(c->wbuf, CC_SHA256_BLOCK_BYTES); 490 c->count = 0; 491 CC_XMEMCPY(c->hash, di->initial_state, di->state_size); 492 return CC_COMPAT_DIGEST_RETURN; 493} 494 495int 496CC_SHA256_Update(CC_SHA256_CTX *x, const void *data, CC_LONG len) 497{ 498 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA256); 499 CC_SHA256_CTX_X *c = (CC_SHA256_CTX_X *) x; 500 uint64_t totalLen = c->count; 501 uint64_t curlen = totalLen % di->block_size; 502 uint8_t *bufptr = (uint8_t *) c->wbuf; 503 struct ccdigest_state *state = (struct ccdigest_state *) c->hash; 504 505 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 506 if(!len || !data) return CC_COMPAT_DIGEST_RETURN; 507 c->count += len; 508 509 ccdigest_process(di, bufptr, state, curlen, len, data); 510 511 return CC_COMPAT_DIGEST_RETURN; 512} 513 514int 515CC_SHA256_Final(unsigned char *md, CC_SHA256_CTX *x) 516{ 517 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA256); 518 CC_SHA256_CTX_X *c = (CC_SHA256_CTX_X *) x; 519 uint64_t totalLen = c->count; 520 uint64_t curlen = totalLen % di->block_size; 521 uint8_t *bufptr = (uint8_t *) c->wbuf; 522 struct ccdigest_state *state = (struct ccdigest_state *) c->hash; 523 524 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 525 if(!md) return CC_COMPAT_DIGEST_RETURN; 526 527 ccdigest_finalize(di, bufptr, state, curlen, totalLen); 528 529 /* copy output */ 530 for (int i = 0; i < 8; i++) CC_XSTORE32H(c->hash[i], md+(4*i)); 531 532 return CC_COMPAT_DIGEST_RETURN; 533} 534 535 536/* 537typedef struct CC_SHA512state_st 538{ CC_LONG64 count[2]; 539 CC_LONG64 hash[8]; 540 CC_LONG64 wbuf[16]; 541} CC_SHA512_CTX; 542*/ 543 544typedef struct CC_SHA512state_x 545{ 546 uint64_t count; 547 uint64_t countx; 548 uint64_t hash[8]; 549 uint64_t wbuf[16]; 550} CC_SHA512_CTX_X; 551 552 553int 554CC_SHA512_Init(CC_SHA512_CTX *x) 555{ 556 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 557 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA512); 558 CC_SHA512_CTX_X *c = (CC_SHA512_CTX_X *) x; 559 ASSERT(di->state_size == CC_SHA512_DIGEST_LENGTH); 560 CC_XZEROMEM(c->hash, CC_SHA512_DIGEST_LENGTH); 561 ASSERT(di->block_size == CC_SHA512_BLOCK_BYTES); 562 CC_XZEROMEM(c->wbuf, CC_SHA512_BLOCK_BYTES); 563 c->count = 0; 564 CC_XMEMCPY(c->hash, di->initial_state, di->state_size); 565 return CC_COMPAT_DIGEST_RETURN; 566} 567 568int 569CC_SHA512_Update(CC_SHA512_CTX *x, const void *data, CC_LONG len) 570{ 571 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA512); 572 CC_SHA512_CTX_X *c = (CC_SHA512_CTX_X *) x; 573 uint64_t totalLen = c->count; 574 uint64_t curlen = totalLen % di->block_size; 575 uint8_t *bufptr = (uint8_t *) c->wbuf; 576 struct ccdigest_state *state = (struct ccdigest_state *) c->hash; 577 578 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 579 580 if(!len || !data) return CC_COMPAT_DIGEST_RETURN; 581 582 c->count += len; 583 ccdigest_process(di, bufptr, state, curlen, len, data); 584 return CC_COMPAT_DIGEST_RETURN; 585} 586 587int 588CC_SHA512_Final(unsigned char *md, CC_SHA512_CTX *x) 589{ 590 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA512); 591 CC_SHA512_CTX_X *c = (CC_SHA512_CTX_X *) x; 592 uint64_t totalLen = c->count; 593 uint64_t curlen = totalLen % di->block_size; 594 uint8_t *bufptr = (uint8_t *) c->wbuf; 595 struct ccdigest_state *state = (struct ccdigest_state *) c->hash; 596 597 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 598 if(!md) return CC_COMPAT_DIGEST_RETURN; 599 600 ccdigest_finalize(di, bufptr, state, curlen, totalLen); 601 602 /* copy output */ 603 for (unsigned long i = 0; i < di->output_size/8; i++) CC_XSTORE64H(c->hash[i], md+(8*i)); 604 605 return CC_COMPAT_DIGEST_RETURN; 606} 607 608/* 609 * Dependent sets of routines (SHA224 and SHA384) 610 */ 611 612int 613CC_SHA224_Init(CC_SHA256_CTX *c) 614{ 615 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 616 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA224); 617 ASSERT(di->state_size == CC_SHA256_DIGEST_LENGTH); 618 CC_XZEROMEM(c->hash, CC_SHA256_DIGEST_LENGTH); 619 ASSERT(di->block_size == CC_SHA256_BLOCK_BYTES); 620 CC_XZEROMEM(c->wbuf, CC_SHA256_BLOCK_BYTES); 621 c->count[0] = c->count[1] = 0; 622 CC_XMEMCPY(c->hash, di->initial_state, di->state_size); 623 return CC_COMPAT_DIGEST_RETURN; 624} 625 626int 627CC_SHA224_Update(CC_SHA256_CTX *c, const void *data, CC_LONG len) 628{ 629 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 630 return CC_SHA256_Update(c, data, len); 631} 632 633int 634CC_SHA224_Final(unsigned char *md, CC_SHA256_CTX *c) 635{ 636 uint32_t buf[CC_SHA256_DIGEST_LENGTH/4]; 637 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 638 639 CC_SHA256_Final((unsigned char *) buf, c); 640 CC_XMEMCPY(md, buf, CC_SHA224_DIGEST_LENGTH); 641 return CC_COMPAT_DIGEST_RETURN; 642} 643 644 645int 646CC_SHA384_Init(CC_SHA512_CTX *c) 647{ 648 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 649 const struct ccdigest_info *di = CCDigestGetDigestInfo(kCCDigestSHA384); 650 ASSERT(di->state_size == CC_SHA512_DIGEST_LENGTH); 651 CC_XZEROMEM(c->hash, CC_SHA512_DIGEST_LENGTH); 652 ASSERT(di->block_size == CC_SHA512_BLOCK_BYTES); 653 CC_XZEROMEM(c->wbuf, CC_SHA512_BLOCK_BYTES); 654 c->count[0] = c->count[1] = 0; 655 CC_XMEMCPY(c->hash, di->initial_state, di->state_size); 656 return CC_COMPAT_DIGEST_RETURN; 657} 658 659 660int 661CC_SHA384_Update(CC_SHA512_CTX *c, const void *data, CC_LONG len) 662{ 663 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 664 return CC_SHA512_Update(c, data, len); 665} 666 667int 668CC_SHA384_Final(unsigned char *md, CC_SHA512_CTX *c) 669{ 670 uint64_t buf[CC_SHA512_DIGEST_LENGTH/8]; 671 672 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 673 CC_SHA512_Final((unsigned char *) buf, c); 674 CC_XMEMCPY(md, buf, CC_SHA384_DIGEST_LENGTH); 675 return CC_COMPAT_DIGEST_RETURN; 676} 677 678