1/* 2 * Copyright (c) 2000-2001,2012,2014 Apple 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,2012,2014 Apple Inc. All Rights Reserved. 23*/ 24#include "pbkdf2.h" 25#include <string.h> 26/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. 27 See: http://www.rsa.com/rsalabs/node.asp?id=2127 for details. 28 tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ 29static void 30F (PRF prf, size_t hLen, 31 const void *passwordPtr, size_t passwordLen, 32 const void *saltPtr, size_t saltLen, 33 size_t iterationCount, 34 uint32_t blockNumber, 35 void *dataPtr, 36 void *tempBuffer) 37{ 38 uint8_t *inBlock, *outBlock, *resultBlockPtr; 39 size_t iteration; 40 outBlock = (uint8_t*)tempBuffer; 41 inBlock = outBlock + hLen; 42 /* Set up inBlock to contain Salt || INT (blockNumber). */ 43 memcpy (inBlock, saltPtr, saltLen); 44 45 inBlock[saltLen + 0] = (uint8_t)(blockNumber >> 24); 46 inBlock[saltLen + 1] = (uint8_t)(blockNumber >> 16); 47 inBlock[saltLen + 2] = (uint8_t)(blockNumber >> 8); 48 inBlock[saltLen + 3] = (uint8_t)(blockNumber); 49 50 /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ 51 resultBlockPtr = (uint8_t*)dataPtr; 52 prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); 53 memcpy (resultBlockPtr, outBlock, hLen); 54 /* Calculate U2 though UiterationCount. */ 55 for (iteration = 2; iteration <= iterationCount; iteration++) 56 { 57 uint8_t *tempBlock; 58 uint32_t byte; 59 /* Swap inBlock and outBlock pointers. */ 60 tempBlock = inBlock; 61 inBlock = outBlock; 62 outBlock = tempBlock; 63 /* Now inBlock conatins Uiteration-1. Calculate Uiteration into outBlock. */ 64 prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); 65 /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with 66 outBlock (Uiteration). */ 67 for (byte = 0; byte < hLen; byte++) 68 resultBlockPtr[byte] ^= outBlock[byte]; 69 } 70} 71void pbkdf2 (PRF prf, size_t hLen, 72 const void *passwordPtr, size_t passwordLen, 73 const void *saltPtr, size_t saltLen, 74 size_t iterationCount, 75 void *dkPtr, size_t dkLen, 76 void *tempBuffer) 77{ 78 size_t completeBlocks = dkLen / hLen; 79 size_t partialBlockSize = dkLen % hLen; 80 uint32_t blockNumber; 81 uint8_t *dataPtr = (uint8_t*)dkPtr; 82 uint8_t *blkBuffer = (uint8_t*)tempBuffer; 83 84 /* This check make sure that the following loops ends, in case where dk_len is 64 bits, and very large. 85 This will cause the derived key to be the maximum size supported by pbkdf2 (4GB * size of the hash) 86 rather than the actual requested size.*/ 87 completeBlocks=completeBlocks & UINT32_MAX; 88 89 /* First calculate all the complete hLen sized blocks required. */ 90 for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) 91 { 92 F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, 93 iterationCount, blockNumber, dataPtr, blkBuffer + hLen); 94 dataPtr += hLen; 95 } 96 /* Finally if the requested output size was not an even multiple of hLen, calculate 97 the final block and copy the first partialBlockSize bytes of it to the output. */ 98 if (partialBlockSize > 0) 99 { 100 F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, 101 iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); 102 memcpy (dataPtr, blkBuffer, partialBlockSize); 103 } 104} 105