1/* 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19/* 20 File: pbkdf2.c 21 Contains: Apple Data Security Services PKCS #5 PBKDF2 function definition. 22 Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved 23 Written by: Michael Brouwer <mb@apple.com> 24*/ 25#include "pbkdf2.h" 26#include <ConditionalMacros.h> 27#include <string.h> 28/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. 29 See: http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html for details. 30 tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ 31static void 32F (PRF prf, uint32 hLen, 33 const void *passwordPtr, uint32 passwordLen, 34 const void *saltPtr, uint32 saltLen, 35 uint32 iterationCount, 36 uint32 blockNumber, 37 void *dataPtr, 38 void *tempBuffer) 39{ 40 uint8 *inBlock, *outBlock, *resultBlockPtr; 41 uint32 iteration; 42 outBlock = (uint8*)tempBuffer; 43 inBlock = outBlock + hLen; 44 /* Set up inBlock to contain Salt || INT (blockNumber). */ 45 memcpy (inBlock, saltPtr, saltLen); 46 47 inBlock[saltLen + 0] = (uint8)(blockNumber >> 24); 48 inBlock[saltLen + 1] = (uint8)(blockNumber >> 16); 49 inBlock[saltLen + 2] = (uint8)(blockNumber >> 8); 50 inBlock[saltLen + 3] = (uint8)(blockNumber); 51 52 /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ 53 resultBlockPtr = (uint8*)dataPtr; 54 prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); 55 memcpy (resultBlockPtr, outBlock, hLen); 56 /* Calculate U2 though UiterationCount. */ 57 for (iteration = 2; iteration <= iterationCount; iteration++) 58 { 59 uint8 *tempBlock; 60 uint32 byte; 61 /* Swap inBlock and outBlock pointers. */ 62 tempBlock = inBlock; 63 inBlock = outBlock; 64 outBlock = tempBlock; 65 /* Now inBlock conatins Uiteration-1. Calclulate Uiteration into outBlock. */ 66 prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); 67 /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with 68 outBlock (Uiteration). */ 69 for (byte = 0; byte < hLen; byte++) 70 resultBlockPtr[byte] ^= outBlock[byte]; 71 } 72} 73void pbkdf2 (PRF prf, uint32 hLen, 74 const void *passwordPtr, uint32 passwordLen, 75 const void *saltPtr, uint32 saltLen, 76 uint32 iterationCount, 77 void *dkPtr, uint32 dkLen, 78 void *tempBuffer) 79{ 80 uint32 completeBlocks = dkLen / hLen; 81 uint32 partialBlockSize = dkLen % hLen; 82 uint32 blockNumber; 83 uint8 *dataPtr = (uint8*)dkPtr; 84 uint8 *blkBuffer = (uint8*)tempBuffer; 85 /* First calculate all the complete hLen sized blocks required. */ 86 for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) 87 { 88 F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, 89 iterationCount, blockNumber, dataPtr, blkBuffer + hLen); 90 dataPtr += hLen; 91 } 92 /* Finally if the requested output size was not an even multiple of hLen, calculate 93 the final block and copy the first partialBlockSize bytes of it to the output. */ 94 if (partialBlockSize > 0) 95 { 96 F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, 97 iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); 98 memcpy (dataPtr, blkBuffer, partialBlockSize); 99 } 100} 101