1/* 2 * Copyright (c) 2000-2009 Apple, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * This SHA1 code is based on the basic framework from the reference 31 * implementation for MD5. That implementation is Copyright (C) 32 * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. 33 * 34 * License to copy and use this software is granted provided that it 35 * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 36 * Algorithm" in all material mentioning or referencing this software 37 * or this function. 38 * 39 * License is also granted to make and use derivative works provided 40 * that such works are identified as "derived from the RSA Data 41 * Security, Inc. MD5 Message-Digest Algorithm" in all material 42 * mentioning or referencing the derived work. 43 * 44 * RSA Data Security, Inc. makes no representations concerning either 45 * the merchantability of this software or the suitability of this 46 * software for any particular purpose. It is provided "as is" 47 * without express or implied warranty of any kind. 48 * 49 * These notices must be retained in any copies of any part of this 50 * documentation and/or software. 51 * 52 * Based on the FIPS 180-1: Secure Hash Algorithm (SHA-1) available at 53 * http://www.itl.nist.gov/div897/pubs/fip180-1.htm 54 */ 55 56/* 57 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! 58 59 THIS FILE IS NEEDED TO PASS FIPS ACCEPTANCE FOR THE RANDOM NUMBER GENERATOR. 60 IF YOU ALTER IT IN ANY WAY, WE WILL NEED TO GO THOUGH FIPS ACCEPTANCE AGAIN, 61 AN OPERATION THAT IS VERY EXPENSIVE AND TIME CONSUMING. IN OTHER WORDS, 62 DON'T MESS WITH THIS FILE. 63 64 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! 65*/ 66 67#include <sys/types.h> 68#include <string.h> 69 70#include "fips_sha1.h" 71 72typedef int Boolean; 73 74/* Internal mappings to the legacy sha1_ctxt structure. */ 75#define state h.b32 76#define bcount c.b32 77#define buffer m.b8 78 79/* 80 * The digest algorithm interprets the input message as a sequence of 32-bit 81 * big-endian words. We must reverse bytes in each word on x86/64 platforms, 82 * but not on big-endian ones such as PPC. For performance, we take advantage 83 * of the bswap instruction on x86/64 to perform byte-reversal. On PPC, we 84 * could do 4-byte load if the address is 4-byte aligned which should further 85 * improve the performance. But for code simplicity, we punt and do 1-byte 86 * loads instead. 87 */ 88#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) 89#define FETCH_32(p) ({ \ 90 register u_int32_t l = (u_int32_t)*((const u_int32_t *)(p)); \ 91 __asm__ __volatile__("bswap %0" : "=r" (l) : "0" (l)); \ 92 l; \ 93}) 94#else 95#define FETCH_32(p) \ 96 (((u_int32_t)*((const u_int8_t *)(p) + 3)) | \ 97 (((u_int32_t)*((const u_int8_t *)(p) + 2)) << 8) | \ 98 (((u_int32_t)*((const u_int8_t *)(p) + 1)) << 16) | \ 99 (((u_int32_t)*((const u_int8_t *)(p))) << 24)) 100#endif /* __i386__ || __x86_64__ */ 101 102/* 103 * Encodes input (u_int32_t) into output (unsigned char). Assumes len is 104 * a multiple of 4. This is not compatible with memcpy(). 105 */ 106static void 107Encode(unsigned char *output, u_int32_t *input, unsigned int len) 108{ 109 unsigned int i, j; 110 111 for (i = 0, j = 0; j < len; i++, j += 4) { 112 output[j + 3] = input[i] & 0xff; 113 output[j + 2] = (input[i] >> 8) & 0xff; 114 output[j + 1] = (input[i] >> 16) & 0xff; 115 output[j] = (input[i] >> 24) & 0xff; 116 } 117} 118 119static unsigned char PADDING[64] = { 0x80, /* zeros */ }; 120 121/* Constants from FIPS 180-1 */ 122#define K_00_19 0x5a827999UL 123#define K_20_39 0x6ed9eba1UL 124#define K_40_59 0x8f1bbcdcUL 125#define K_60_79 0xca62c1d6UL 126 127/* F, G, H and I are basic SHA1 functions. */ 128#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d)) 129#define G(b, c, d) ((b) ^ (c) ^ (d)) 130#define H(b, c, d) (((b) & (c)) | (((b) | (c)) & (d))) 131 132/* ROTATE_LEFT rotates x left n bits. */ 133#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 134 135/* R, R1-R4 are macros used during each transformation round. */ 136#define R(f, k, v, w, x, y, z, i) { \ 137 (v) = ROTATE_LEFT(w, 5) + f(x, y, z) + (v) + (i) + (k); \ 138 (x) = ROTATE_LEFT(x, 30); \ 139} 140 141#define R1(v, w, x, y, z, i) R(F, K_00_19, v, w, x, y, z, i) 142#define R2(v, w, x, y, z, i) R(G, K_20_39, v, w, x, y, z, i) 143#define R3(v, w, x, y, z, i) R(H, K_40_59, v, w, x, y, z, i) 144#define R4(v, w, x, y, z, i) R(G, K_60_79, v, w, x, y, z, i) 145 146/* WUPDATE represents Wt variable that gets updated for steps 16-79 */ 147#define WUPDATE(p, q, r, s) { \ 148 (p) = ((q) ^ (r) ^ (s) ^ (p)); \ 149 (p) = ROTATE_LEFT(p, 1); \ 150} 151 152static void SHA1Transform(u_int32_t, u_int32_t, u_int32_t, u_int32_t, 153 u_int32_t, const u_int8_t *, SHA1_CTX *); 154 155/* 156 * SHA1 initialization. Begins a SHA1 operation, writing a new context. 157 */ 158void 159FIPS_SHA1Init(SHA1_CTX *context) 160{ 161 context->bcount[0] = context->bcount[1] = 0; 162 context->count = 0; 163 164 /* Load magic initialization constants. */ 165 context->state[0] = 0x67452301UL; 166 context->state[1] = 0xefcdab89UL; 167 context->state[2] = 0x98badcfeUL; 168 context->state[3] = 0x10325476UL; 169 context->state[4] = 0xc3d2e1f0UL; 170} 171 172/* 173 * SHA1 block update operation. Continues a SHA1 message-digest 174 * operation, processing another message block, and updating the 175 * context. 176 */ 177void FIPS_SHA1Update(SHA1_CTX *context, const void *inpp, size_t inputLen) 178{ 179 u_int32_t i, index, partLen; 180 const unsigned char *input = (const unsigned char *)inpp; 181 182 if (inputLen == 0) 183 return; 184 185 /* Compute number of bytes mod 64 */ 186 index = (context->bcount[1] >> 3) & 0x3F; 187 188 /* Update number of bits */ 189 if ((context->bcount[1] += (inputLen << 3)) < (inputLen << 3)) 190 context->bcount[0]++; 191 context->bcount[0] += (inputLen >> 29); 192 193 partLen = 64 - index; 194 195 /* Transform as many times as possible. */ 196 i = 0; 197 if (inputLen >= partLen) { 198 if (index != 0) { 199 memcpy(&context->buffer[index], input, partLen); 200 SHA1Transform(context->state[0], context->state[1], 201 context->state[2], context->state[3], 202 context->state[4], context->buffer, context); 203 i = partLen; 204 } 205 206 for (; i + 63 < inputLen; i += 64) 207 SHA1Transform(context->state[0], context->state[1], 208 context->state[2], context->state[3], 209 context->state[4], &input[i], context); 210 211 if (inputLen == i) 212 return; 213 214 index = 0; 215 } 216 217 /* Buffer remaining input */ 218 memcpy(&context->buffer[index], &input[i], inputLen - i); 219} 220 221 222 223 224/* 225 * This is function is only called in from the pagefault path or from page_copy(). 226 * So we assume that we can safely convert the virtual address to the physical address and use it. 227 * Assumptions: The passed in address(inpp) is a kernel virtual address 228 * and a physical page has been faulted in. 229 * The inputLen passed in should always be less than or equal to a page size (4096) 230 * and inpp should be on a page boundary. 231 * "performSHA1WithinKernelOnly" is initialized only when the hardware driver exists and is ready. 232 */ 233 234 235 236/* 237 * SHA1 finalization. Ends an SHA1 message-digest operation, writing the 238 * the message digest and zeroizing the context. 239 */ 240void 241FIPS_SHA1Final(void *digest, SHA1_CTX *context) 242{ 243 unsigned char bits[8]; 244 u_int32_t index = (context->bcount[1] >> 3) & 0x3f; 245 246 /* Save number of bits */ 247 Encode(bits, context->bcount, 8); 248 249 /* Pad out to 56 mod 64. */ 250 FIPS_SHA1Update(context, PADDING, ((index < 56) ? 56 : 120) - index); 251 252 /* Append length (before padding) */ 253 FIPS_SHA1Update(context, bits, 8); 254 255 /* Store state in digest */ 256 Encode(digest, context->state, 20); 257 258 /* Zeroize sensitive information. */ 259 memset(context, 0, sizeof (*context)); 260} 261 262/* 263 * SHA1 basic transformation. Transforms state based on block. 264 */ 265static void 266SHA1Transform(u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t d, 267 u_int32_t e, const u_int8_t block[64], SHA1_CTX *context) 268{ 269 /* Register (instead of array) is a win in most cases */ 270 register u_int32_t w0, w1, w2, w3, w4, w5, w6, w7; 271 register u_int32_t w8, w9, w10, w11, w12, w13, w14, w15; 272 273 w15 = FETCH_32(block + 60); 274 w14 = FETCH_32(block + 56); 275 w13 = FETCH_32(block + 52); 276 w12 = FETCH_32(block + 48); 277 w11 = FETCH_32(block + 44); 278 w10 = FETCH_32(block + 40); 279 w9 = FETCH_32(block + 36); 280 w8 = FETCH_32(block + 32); 281 w7 = FETCH_32(block + 28); 282 w6 = FETCH_32(block + 24); 283 w5 = FETCH_32(block + 20); 284 w4 = FETCH_32(block + 16); 285 w3 = FETCH_32(block + 12); 286 w2 = FETCH_32(block + 8); 287 w1 = FETCH_32(block + 4); 288 w0 = FETCH_32(block + 0); 289 290 /* Round 1 */ 291 R1(e, a, b, c, d, w0); /* 0 */ 292 R1(d, e, a, b, c, w1); /* 1 */ 293 R1(c, d, e, a, b, w2); /* 2 */ 294 R1(b, c, d, e, a, w3); /* 3 */ 295 R1(a, b, c, d, e, w4); /* 4 */ 296 R1(e, a, b, c, d, w5); /* 5 */ 297 R1(d, e, a, b, c, w6); /* 6 */ 298 R1(c, d, e, a, b, w7); /* 7 */ 299 R1(b, c, d, e, a, w8); /* 8 */ 300 R1(a, b, c, d, e, w9); /* 9 */ 301 R1(e, a, b, c, d, w10); /* 10 */ 302 R1(d, e, a, b, c, w11); /* 11 */ 303 R1(c, d, e, a, b, w12); /* 12 */ 304 R1(b, c, d, e, a, w13); /* 13 */ 305 R1(a, b, c, d, e, w14); /* 14 */ 306 R1(e, a, b, c, d, w15); /* 15 */ 307 WUPDATE( w0, w13, w8, w2); R1(d, e, a, b, c, w0); /* 16 */ 308 WUPDATE( w1, w14, w9, w3); R1(c, d, e, a, b, w1); /* 17 */ 309 WUPDATE( w2, w15, w10, w4); R1(b, c, d, e, a, w2); /* 18 */ 310 WUPDATE( w3, w0, w11, w5); R1(a, b, c, d, e, w3); /* 19 */ 311 312 /* Round 2 */ 313 WUPDATE( w4, w1, w12, w6); R2(e, a, b, c, d, w4); /* 20 */ 314 WUPDATE( w5, w2, w13, w7); R2(d, e, a, b, c, w5); /* 21 */ 315 WUPDATE( w6, w3, w14, w8); R2(c, d, e, a, b, w6); /* 22 */ 316 WUPDATE( w7, w4, w15, w9); R2(b, c, d, e, a, w7); /* 23 */ 317 WUPDATE( w8, w5, w0, w10); R2(a, b, c, d, e, w8); /* 24 */ 318 WUPDATE( w9, w6, w1, w11); R2(e, a, b, c, d, w9); /* 25 */ 319 WUPDATE(w10, w7, w2, w12); R2(d, e, a, b, c, w10); /* 26 */ 320 WUPDATE(w11, w8, w3, w13); R2(c, d, e, a, b, w11); /* 27 */ 321 WUPDATE(w12, w9, w4, w14); R2(b, c, d, e, a, w12); /* 28 */ 322 WUPDATE(w13, w10, w5, w15); R2(a, b, c, d, e, w13); /* 29 */ 323 WUPDATE(w14, w11, w6, w0); R2(e, a, b, c, d, w14); /* 30 */ 324 WUPDATE(w15, w12, w7, w1); R2(d, e, a, b, c, w15); /* 31 */ 325 WUPDATE( w0, w13, w8, w2); R2(c, d, e, a, b, w0); /* 32 */ 326 WUPDATE( w1, w14, w9, w3); R2(b, c, d, e, a, w1); /* 33 */ 327 WUPDATE( w2, w15, w10, w4); R2(a, b, c, d, e, w2); /* 34 */ 328 WUPDATE( w3, w0, w11, w5); R2(e, a, b, c, d, w3); /* 35 */ 329 WUPDATE( w4, w1, w12, w6); R2(d, e, a, b, c, w4); /* 36 */ 330 WUPDATE( w5, w2, w13, w7); R2(c, d, e, a, b, w5); /* 37 */ 331 WUPDATE( w6, w3, w14, w8); R2(b, c, d, e, a, w6); /* 38 */ 332 WUPDATE( w7, w4, w15, w9); R2(a, b, c, d, e, w7); /* 39 */ 333 334 /* Round 3 */ 335 WUPDATE( w8, w5, w0, w10); R3(e, a, b, c, d, w8); /* 40 */ 336 WUPDATE( w9, w6, w1, w11); R3(d, e, a, b, c, w9); /* 41 */ 337 WUPDATE(w10, w7, w2, w12); R3(c, d, e, a, b, w10); /* 42 */ 338 WUPDATE(w11, w8, w3, w13); R3(b, c, d, e, a, w11); /* 43 */ 339 WUPDATE(w12, w9, w4, w14); R3(a, b, c, d, e, w12); /* 44 */ 340 WUPDATE(w13, w10, w5, w15); R3(e, a, b, c, d, w13); /* 45 */ 341 WUPDATE(w14, w11, w6, w0); R3(d, e, a, b, c, w14); /* 46 */ 342 WUPDATE(w15, w12, w7, w1); R3(c, d, e, a, b, w15); /* 47 */ 343 WUPDATE( w0, w13, w8, w2); R3(b, c, d, e, a, w0); /* 48 */ 344 WUPDATE( w1, w14, w9, w3); R3(a, b, c, d, e, w1); /* 49 */ 345 WUPDATE( w2, w15, w10, w4); R3(e, a, b, c, d, w2); /* 50 */ 346 WUPDATE( w3, w0, w11, w5); R3(d, e, a, b, c, w3); /* 51 */ 347 WUPDATE( w4, w1, w12, w6); R3(c, d, e, a, b, w4); /* 52 */ 348 WUPDATE( w5, w2, w13, w7); R3(b, c, d, e, a, w5); /* 53 */ 349 WUPDATE( w6, w3, w14, w8); R3(a, b, c, d, e, w6); /* 54 */ 350 WUPDATE( w7, w4, w15, w9); R3(e, a, b, c, d, w7); /* 55 */ 351 WUPDATE( w8, w5, w0, w10); R3(d, e, a, b, c, w8); /* 56 */ 352 WUPDATE( w9, w6, w1, w11); R3(c, d, e, a, b, w9); /* 57 */ 353 WUPDATE(w10, w7, w2, w12); R3(b, c, d, e, a, w10); /* 58 */ 354 WUPDATE(w11, w8, w3, w13); R3(a, b, c, d, e, w11); /* 59 */ 355 356 WUPDATE(w12, w9, w4, w14); R4(e, a, b, c, d, w12); /* 60 */ 357 WUPDATE(w13, w10, w5, w15); R4(d, e, a, b, c, w13); /* 61 */ 358 WUPDATE(w14, w11, w6, w0); R4(c, d, e, a, b, w14); /* 62 */ 359 WUPDATE(w15, w12, w7, w1); R4(b, c, d, e, a, w15); /* 63 */ 360 WUPDATE( w0, w13, w8, w2); R4(a, b, c, d, e, w0); /* 64 */ 361 WUPDATE( w1, w14, w9, w3); R4(e, a, b, c, d, w1); /* 65 */ 362 WUPDATE( w2, w15, w10, w4); R4(d, e, a, b, c, w2); /* 66 */ 363 WUPDATE( w3, w0, w11, w5); R4(c, d, e, a, b, w3); /* 67 */ 364 WUPDATE( w4, w1, w12, w6); R4(b, c, d, e, a, w4); /* 68 */ 365 WUPDATE( w5, w2, w13, w7); R4(a, b, c, d, e, w5); /* 69 */ 366 WUPDATE( w6, w3, w14, w8); R4(e, a, b, c, d, w6); /* 70 */ 367 WUPDATE( w7, w4, w15, w9); R4(d, e, a, b, c, w7); /* 71 */ 368 WUPDATE( w8, w5, w0, w10); R4(c, d, e, a, b, w8); /* 72 */ 369 WUPDATE( w9, w6, w1, w11); R4(b, c, d, e, a, w9); /* 73 */ 370 WUPDATE(w10, w7, w2, w12); R4(a, b, c, d, e, w10); /* 74 */ 371 WUPDATE(w11, w8, w3, w13); R4(e, a, b, c, d, w11); /* 75 */ 372 WUPDATE(w12, w9, w4, w14); R4(d, e, a, b, c, w12); /* 76 */ 373 WUPDATE(w13, w10, w5, w15); R4(c, d, e, a, b, w13); /* 77 */ 374 WUPDATE(w14, w11, w6, w0); R4(b, c, d, e, a, w14); /* 78 */ 375 WUPDATE(w15, w12, w7, w1); R4(a, b, c, d, e, w15); /* 79 */ 376 377 context->state[0] += a; 378 context->state[1] += b; 379 context->state[2] += c; 380 context->state[3] += d; 381 context->state[4] += e; 382 383 /* Zeroize sensitive information. */ 384 w15 = w14 = w13 = w12 = w11 = w10 = w9 = w8 = 0; 385 w7 = w6 = w5 = w4 = w3 = w2 = w1 = w0 = 0; 386} 387