1/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. 2 * 3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT 4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE 5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE 6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, 7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL 8 * EXPOSE YOU TO LIABILITY. 9 *************************************************************************** 10 * 11 * SHA1.c - generic, portable SHA-1 hash object 12 * 13 * Revision History 14 * ---------------- 15 * 10/06/98 ap 16 * Changed to compile with C++. 17 * 07 Jan 1998 Doug Mitchell at Apple 18 * Created. 19 */ 20 21#include "SHA1.h" 22#include "SHA1_priv.h" 23#include <strings.h> 24 25/* for now map falloc to malloc, FIXME */ 26#include <stdlib.h> 27#define fmalloc(s) malloc(s) 28#define ffree(p) free(p) 29 30/* 31 * Private data for this object. A sha1Obj handle is cast to a pointer 32 * to one of these. 33 */ 34typedef struct { 35 SHS_INFO context; 36 int isDone; 37 38 /* 39 * For storing partial blocks 40 */ 41 BYTE dataBuf[SHS_BLOCKSIZE]; 42 unsigned bufBytes; // valid bytes in dataBuf[p] 43} sha1Inst; 44 45/* 46 * Alloc and init an empty sha1 object. 47 */ 48sha1Obj sha1Alloc(void) 49{ 50 sha1Inst *sinst; 51 52 sinst = (sha1Inst *)fmalloc(sizeof(sha1Inst)); 53 if(sinst == NULL) { 54 return NULL; 55 } 56 shsInit(&sinst->context); 57 sha1Reinit((sha1Obj)sinst); 58 return (sha1Obj)sinst; 59} 60 61/* 62 * Reusable init function. 63 */ 64void sha1Reinit(sha1Obj sha1) 65{ 66 sha1Inst *sinst = (sha1Inst *) sha1; 67 68 shsInit(&sinst->context); 69 sinst->isDone = 0; 70 sinst->bufBytes = 0; 71} 72 73/* 74 * Free an sha1 object. 75 */ 76void sha1Free(sha1Obj sha1) 77{ 78 sha1Inst *sinst = (sha1Inst *) sha1; 79 80 memset(sha1, 0, sizeof(sha1Inst)); 81 ffree(sinst); 82} 83 84/* 85 * Add some data to the sha1 object. 86 */ 87void sha1AddData(sha1Obj sha1, 88 const unsigned char *data, 89 unsigned dataLen) 90{ 91 sha1Inst *sinst = (sha1Inst *) sha1; 92 unsigned toMove; 93 unsigned blocks; 94 95 if(sinst->isDone) { 96 /* 97 * Log some kind of error here... 98 */ 99 return; 100 } 101 102 /* 103 * First deal with partial buffered block 104 */ 105 if(sinst->bufBytes != 0) { 106 toMove = SHS_BLOCKSIZE - sinst->bufBytes; 107 if(toMove > dataLen) { 108 toMove = dataLen; 109 } 110 memmove(sinst->dataBuf+sinst->bufBytes, data, toMove); 111 data += toMove; 112 dataLen -= toMove; 113 sinst->bufBytes += toMove; 114 if(sinst->bufBytes == SHS_BLOCKSIZE) { 115 shsUpdate(&sinst->context, sinst->dataBuf, SHS_BLOCKSIZE); 116 sinst->bufBytes = 0; 117 } 118 } 119 120 /* 121 * Now the bulk of the data, in a multiple of full blocks 122 */ 123 blocks = dataLen / SHS_BLOCKSIZE; 124 toMove = blocks * SHS_BLOCKSIZE; 125 if(toMove != 0) { 126 shsUpdate(&sinst->context, data, toMove); 127 data += toMove; 128 dataLen -= toMove; 129 } 130 131 /* 132 * Store any remainder in dataBuf 133 */ 134 if(dataLen != 0) { 135 memmove(sinst->dataBuf, data, dataLen); 136 sinst->bufBytes = dataLen; 137 } 138} 139 140/* 141 * Obtain a pointer to completed message digest, and the length of the digest. 142 */ 143unsigned char *sha1Digest(sha1Obj sha1) 144{ 145 sha1Inst *sinst = (sha1Inst *) sha1; 146 147 if(!sinst->isDone) { 148 /* 149 * Deal with partial resid block 150 */ 151 if(sinst->bufBytes != 0) { 152 shsUpdate(&sinst->context, sinst->dataBuf, 153 sinst->bufBytes); 154 sinst->bufBytes = 0; 155 } 156 shsFinal(&sinst->context); 157 sinst->isDone = 1; 158 } 159 /* 160 * FIXME - should do explicit conversion to char array....? 161 */ 162 return (unsigned char *)sinst->context.digest; 163} 164 165/* As above, with copy. */ 166void sha1GetDigest(sha1Obj sha1, 167 unsigned char *digest) 168{ 169 unsigned char *dig = sha1Digest(sha1); 170 memmove(digest, dig, SHS_DIGESTSIZE); 171} 172 173unsigned sha1DigestLen(void) 174{ 175 return SHS_DIGESTSIZE; 176} 177