1/* 2 * Copyright (c) 2007-2008,2010,2012-2013 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <stdlib.h> 25#include <string.h> // memcpy 26 27#include <CommonCrypto/CommonDigest.h> 28#include <CommonCrypto/CommonDigestSPI.h> 29 30#include <corecrypto/ccn.h> 31 32#include "p12pbegen.h" 33 34static uint8_t *concatenate_to_blocksize(const uint8_t *data, size_t data_length, 35 size_t blocksize, size_t *blocklength) 36{ 37 size_t block_length = blocksize * ((data_length + blocksize - 1) / blocksize); 38 uint8_t *block_ptr, *block; 39 block_ptr = block = malloc(block_length); 40 if (!block_ptr) 41 return NULL; 42 while (block_ptr < block + block_length) { 43 size_t bytes_to_move = block + block_length - block_ptr; 44 memcpy(block_ptr, data, bytes_to_move > data_length ? data_length : bytes_to_move); 45 block_ptr += data_length; 46 } 47 *blocklength = block_length; 48 return block; 49} 50 51int p12_pbe_gen(CFStringRef passphrase, uint8_t *salt_ptr, size_t salt_length, 52 unsigned iter_count, P12_PBE_ID pbe_id, uint8_t *data, size_t length) 53{ 54 unsigned int hash_blocksize = CC_SHA1_BLOCK_BYTES; 55 unsigned int hash_outputsize = CC_SHA1_DIGEST_LENGTH; 56 57 if (!passphrase) 58 return -1; 59 60 /* generate diversifier block */ 61 unsigned char diversifier[hash_blocksize]; 62 memset(diversifier, pbe_id, sizeof(diversifier)); 63 64 /* convert passphrase to BE UTF16 and append double null */ 65 CFDataRef passphrase_be_unicode = CFStringCreateExternalRepresentation(kCFAllocatorDefault, passphrase, kCFStringEncodingUTF16BE, '\0'); 66 if (!passphrase_be_unicode) 67 return -1; 68 uint8_t null_termination[2] = { 0, 0 }; 69 CFMutableDataRef passphrase_be_unicode_null_term = CFDataCreateMutableCopy(NULL, 0, passphrase_be_unicode); 70 CFRelease(passphrase_be_unicode); 71 if (!passphrase_be_unicode_null_term) 72 return -1; 73 CFDataAppendBytes(passphrase_be_unicode_null_term, null_termination, sizeof(null_termination)); 74 75 /* generate passphrase block */ 76 uint8_t *passphrase_data = NULL; 77 size_t passphrase_data_len = 0; 78 size_t passphrase_length = CFDataGetLength(passphrase_be_unicode_null_term); 79 const unsigned char *passphrase_ptr = CFDataGetBytePtr(passphrase_be_unicode_null_term); 80 passphrase_data = concatenate_to_blocksize(passphrase_ptr, passphrase_length, hash_blocksize, &passphrase_data_len); 81 CFRelease(passphrase_be_unicode_null_term); 82 if (!passphrase_data) 83 return -1; 84 85 /* generate salt block */ 86 uint8_t *salt_data = NULL; 87 size_t salt_data_len = 0; 88 if (salt_length) 89 salt_data = concatenate_to_blocksize(salt_ptr, salt_length, hash_blocksize, &salt_data_len); 90 if (!salt_data){ 91 free(passphrase_data); 92 return -1; 93 } 94 /* generate S||P block */ 95 size_t I_length = salt_data_len + passphrase_data_len; 96 uint8_t *I_data = malloc(I_length); 97 if (!I_data){ 98 free(salt_data); 99 free(passphrase_data); 100 return -1; 101 } 102 memcpy(I_data + 0, salt_data, salt_data_len); 103 memcpy(I_data + salt_data_len, passphrase_data, passphrase_data_len); 104 free(salt_data); 105 free(passphrase_data); 106 107 /* round up output buffer to multiple of hash block size and allocate */ 108 size_t hash_output_blocks = (length + hash_outputsize - 1) / hash_outputsize; 109 size_t temp_buf_size = hash_output_blocks * hash_outputsize; 110 uint8_t *temp_buf = malloc(temp_buf_size); 111 uint8_t *cursor = temp_buf; 112 if (!temp_buf){ 113 free(I_data); 114 return -1; 115 } 116 /* 64 bits cast(s): worst case here is we dont hash all the data and incorectly derive the wrong key, 117 when the passphrase + salt are over 2^32 bytes long */ 118 /* loop over output in hash_output_size increments */ 119 while (cursor < temp_buf + temp_buf_size) { 120 CC_SHA1_CTX ctx; 121 CC_SHA1_Init(&ctx); 122 CC_SHA1_Update(&ctx, diversifier, (CC_LONG)sizeof(diversifier)); 123 assert(I_length<=UINT32_MAX); /* debug check. Correct as long as CC_LONG is uint32_t */ 124 CC_SHA1_Update(&ctx, I_data, (CC_LONG)I_length); 125 CC_SHA1_Final(cursor, &ctx); 126 127 /* run block through SHA-1 for iteration count */ 128 unsigned int i; 129 for (i = 1; /*first round done above*/ i < iter_count; i++) 130 CCDigest(kCCDigestSHA1, cursor, hash_outputsize, cursor); 131 132 /* 133 * b) Concatenate copies of A[i] to create a string B of 134 * length v bits (the final copy of A[i]i may be truncated 135 * to create B). 136 */ 137 size_t A_i_len = 0; 138 uint8_t *A_i = concatenate_to_blocksize(cursor, 139 hash_outputsize, hash_blocksize, &A_i_len); 140 if (!A_i){ 141 free(I_data); 142 free(temp_buf); 143 return -1; 144 } 145 /* 146 * c) Treating I as a concatenation I[0], I[1], ..., 147 * I[k-1] of v-bit blocks, where k = ceil(s/v) + ceil(p/v), 148 * modify I by setting I[j]=(I[j]+B+1) mod (2 ** v) 149 * for each j. 150 */ 151 152 /* tmp1 = B+1 */ 153 154 const cc_size tmp_n = ccn_nof_size(A_i_len + 1) > ccn_nof_size(hash_blocksize) ? ccn_nof_size(A_i_len + 1) : ccn_nof_size(hash_blocksize); 155 cc_unit tmp1[tmp_n]; 156 ccn_read_uint(tmp_n, tmp1, A_i_len, A_i); 157 ccn_add1(tmp_n, tmp1, tmp1, 1); 158 159 free(A_i); 160 161 cc_unit tmp2[tmp_n]; 162 unsigned int j; 163 for (j = 0; j < I_length; j+=hash_blocksize) { 164 /* tempg = I[j]; */ 165 ccn_read_uint(tmp_n, tmp2, hash_blocksize, I_data + j); 166 /* tempg += tmp1 */ 167 ccn_add(tmp_n, tmp2, tmp2, tmp1); 168 169 /* I[j] = tempg mod 2**v 170 Just clear all the high bits above 2**v 171 In practice at most it rolled over by 1 bit, since all we did was add so 172 we should only clear one bit at most. 173 */ 174 size_t bitSize; 175 const size_t hash_blocksize_bits = hash_blocksize * 8; 176 while ((bitSize = ccn_bitlen(tmp_n, tmp2)) > hash_blocksize_bits) 177 { 178 ccn_set_bit(tmp2, bitSize - 1, 0); 179 } 180 181 ccn_write_uint_padded(tmp_n, tmp2, hash_blocksize, I_data + j); 182 } 183 184 cursor += hash_outputsize; 185 } 186 187 /* 188 * 7. Concatenate A[1], A[2], ..., A[c] together to form a 189 * pseudo-random bit string, A. 190 * 191 * 8. Use the first n bits of A as the output of this entire 192 * process. 193 */ 194 memmove(data, temp_buf, length); 195 free(temp_buf); 196 free(I_data); 197 return 0; 198} 199 200#if 0 201bool test() 202{ 203 //smeg => 0073006D006500670000 204 CFStringRef password = CFSTR("smeg"); 205 //Salt (length 8): 206 unsigned char salt_bytes[] = { 0x0A, 0x58, 0xCF, 0x64, 0x53, 0x0D, 0x82, 0x3F }; 207 CFDataRef salt = CFDataCreate(NULL, salt_bytes, sizeof(salt_bytes)); 208 // ID 1, ITER 1 209 // Output KEY (length 24) 210 unsigned char correct_result[] = { 0x8A, 0xAA, 0xE6, 0x29, 0x7B, 0x6C, 0xB0, 0x46, 0x42, 0xAB, 0x5B, 0x07, 0x78, 0x51, 0x28, 0x4E, 0xB7, 0x12, 0x8F, 0x1A, 0x2A, 0x7F, 0xBC, 0xA3 }; 211 unsigned char result[24]; 212 p12PbeGen(password, salt, 1, PBE_ID_Key, result, sizeof(result)); 213 if (memcmp(correct_result, result, sizeof(correct_result))) { 214 printf("test failure\n"); 215 return false; 216 } 217 return true; 218} 219 220bool test2() 221{ 222 CFStringRef password = CFSTR("queeg"); 223 unsigned char salt_bytes[] = { 0x05,0xDE,0xC9,0x59,0xAC,0xFF,0x72,0xF7 }; 224 CFDataRef salt = CFDataCreate(NULL, salt_bytes, sizeof(salt_bytes)); 225 unsigned char correct_result[] = { 0xED,0x20,0x34,0xE3,0x63,0x28,0x83,0x0F,0xF0,0x9D,0xF1,0xE1,0xA0,0x7D,0xD3,0x57,0x18,0x5D,0xAC,0x0D,0x4F,0x9E,0xB3,0xD4 }; 226 unsigned char result[24]; 227 p12PbeGen(password, salt, 1000, PBE_ID_Key, result, sizeof(result)); 228 if (memcmp(correct_result, result, sizeof(correct_result))) { 229 printf("test failure\n"); 230 return false; 231 } 232 return true; 233} 234 235int main(int argc, char *argv[]) 236{ 237 test(); 238 test2(); 239} 240 241#endif 242 243/* http://www.drh-consultancy.demon.co.uk/test.txt 244 245 Test Vectors set 1. 246 247 Password: smeg 248 249KEYGEN DEBUG 250ID 1, ITER 1 251Password (length 10): 2520073006D006500670000 253Salt (length 8): 2540A58CF64530D823F 255ID 1, ITER 1 256Output KEY (length 24) 2578AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3 258 259KEYGEN DEBUG 260ID 2, ITER 1 261Password (length 10): 2620073006D006500670000 263Salt (length 8): 2640A58CF64530D823F 265ID 2, ITER 1 266Output KEY (length 8) 26779993DFE048D3B76 268 269KEYGEN DEBUG 270ID 1, ITER 1 271Password (length 10): 2720073006D006500670000 273Salt (length 8): 274642B99AB44FB4B1F 275ID 1, ITER 1 276Output KEY (length 24) 277F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966 278 279KEYGEN DEBUG 280ID 2, ITER 1 281Password (length 10): 2820073006D006500670000 283Salt (length 8): 284642B99AB44FB4B1F 285ID 2, ITER 1 286Output KEY (length 8) 287C0A38D64A79BEA1D 288 289KEYGEN DEBUG 290ID 3, ITER 1 291Password (length 10): 2920073006D006500670000 293Salt (length 8): 2943D83C0E4546AC140 295ID 3, ITER 1 296Output KEY (length 20) 2978D967D88F6CAA9D714800AB3D48051D63F73A312 298 299Test Vectors set 2. 300Password: queeg 301 302KEYGEN DEBUG 303ID 1, ITER 1000 304Password (length 12): 305007100750065006500670000 306Salt (length 8): 30705DEC959ACFF72F7 308ID 1, ITER 1000 309Output KEY (length 24) 310ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4 311 312KEYGEN DEBUG 313ID 2, ITER 1000 314Password (length 12): 315007100750065006500670000 316Salt (length 8): 31705DEC959ACFF72F7 318ID 2, ITER 1000 319Output KEY (length 8) 32011DEDAD7758D4860 321 322KEYGEN DEBUG 323ID 1, ITER 1000 324Password (length 12): 325007100750065006500670000 326Salt (length 8): 3271682C0FC5B3F7EC5 328ID 1, ITER 1000 329Output KEY (length 24) 330483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F 331 332KEYGEN DEBUG 333ID 2, ITER 1000 334Password (length 12): 335007100750065006500670000 336Salt (length 8): 3371682C0FC5B3F7EC5 338ID 2, ITER 1000 339Output KEY (length 8) 3409D461D1B00355C50 341 342KEYGEN DEBUG 343ID 3, ITER 1000 344Password (length 12): 345007100750065006500670000 346Salt (length 8): 347263216FCC2FAB31C 348ID 3, ITER 1000 349Output KEY (length 20) 3505EC4C7A80DF652294C3925B6489A7AB857C83476 351*/ 352 353