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