]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/pbkdf2.c
Security-58286.70.7.tar.gz
[apple/security.git] / OSX / sec / Security / pbkdf2.c
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. */
29 static void
30 F (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 }
71 void 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 }