static void ccn_mod_521(cczp_const_t zp, cc_unit *r, const cc_unit *a, CC_UNUSED cc_ws_t ws) { cc_assert(cczp_n(zp) == CCN521_N); cc_unit t[CCN521_N]; cc_unit t2[CCN521_N]; cc_unit *select[2] __attribute__((aligned(16))) ={t,t2}; cc_unit borrow; #if CCN_UNIT_SIZE == 1 ccn_shift_right(CCN521_N - 1, t2, &a[CCN521_N - 1], 1); // r = a521,...,a1041 t2[CCN521_N - 1] += a[CCN521_N - 1] & CC_UNIT_C(1); t2[CCN521_N - 1] += ccn_add(CCN521_N - 1,t2,t2,a); #else ccn_shift_right(CCN521_N, t2, &a[CCN512_N], 9); // r = a521,...,a1041 t2[CCN512_N] += a[CCN512_N] & CC_UNIT_C(0x1ff); // r += (a512,...,a520)*2^512 t2[CCN512_N] += ccn_add(CCN512_N,t2,t2,a); // r += a0,...,a511 #endif borrow=ccn_sub(CCN521_N, t, t2, cczp_prime(zp)); ccn_set(CCN521_N,r,select[borrow]); }
void cczp_div2(cczp_const_short_t zp, cc_unit *r, const cc_unit *x) { if (x[0] & 1) { /* x is odd r = (x + p) >> 1 */ cc_unit carry = ccn_add(cczp_n(zp), r, x, cczp_prime(zp)); ccn_shift_right(cczp_n(zp), r, r, 1); r[cczp_n(zp) - 1] |= carry << (CCN_UNIT_BITS - 1); } else { /* x is even r = x >> 1 */ ccn_shift_right(cczp_n(zp), r, x, 1); } }
static void ccn_mod_384(cczp_const_t zp, cc_unit *r, const cc_unit *a, CC_UNUSED cc_ws_t ws) { cc_assert(cczp_n(zp) == CCN384_N); cc_unit s1[CCN384_N] = { ccn384_32( Anil, Anil, Anil, Anil, Anil, A(23), A(22), A(21), Anil, Anil, Anil, Anil) }; //cc_unit s2[CCN384_N] = { ccn384_32( A(23), A(22), A(21), A(20), A(19), A(18), A(17), A(16), A(15), A(14), A(13), A(12)) }; cc_unit s3[CCN384_N] = { ccn384_32( A(20), A(19), A(18), A(17), A(16), A(15), A(14), A(13), A(12), A(23), A(22), A(21)) }; cc_unit s4[CCN384_N] = { ccn384_32( A(19), A(18), A(17), A(16), A(15), A(14), A(13), A(12), A(20), Anil, A(23), Anil) }; cc_unit s5[CCN384_N] = { ccn384_32( Anil, Anil, Anil, Anil, A(23), A(22), A(21), A(20), Anil, Anil, Anil, Anil) }; cc_unit s6[CCN384_N] = { ccn384_32( Anil, Anil, Anil, Anil, Anil, Anil, A(23), A(22), A(21), Anil, Anil, A(20)) }; cc_unit d1[CCN384_N] = { ccn384_32( A(22), A(21), A(20), A(19), A(18), A(17), A(16), A(15), A(14), A(13), A(12), A(23)) }; cc_unit d2[CCN384_N] = { ccn384_32( Anil, Anil, Anil, Anil, Anil, Anil, Anil, A(23), A(22), A(21), A(20), Anil) }; cc_unit d3[CCN384_N] = { ccn384_32( Anil, Anil, Anil, Anil, Anil, Anil, Anil, A(23), A(23), Anil, Anil, Anil) }; cc_unit *select[2] __attribute__((aligned(16))) ={s1,s3}; cc_unit carry,carry_mask; ccn_add(ccn_nof(160)+1, d2, d2, d3); // smaller size and no carry possible ccn_add(ccn_nof(224)+1, s1, s1, s1); // smaller size and no carry possible, alternatively cc_shiftl(s1, 1) but add is currently faster. ccn_add(ccn_nof(256)+1, s5, s5, s1); // smaller size and no carry possible ccn_add(ccn_nof(256)+1, s5, s5, s6); // smaller size and no carry possible carry = ccn_add(CCN384_N, r, a, &a[CCN384_N]); carry += ccn_add(CCN384_N, r, r, s3); carry += ccn_add(CCN384_N, r, r, s4); carry += ccn_add(CCN384_N, r, r, s5); carry -= ccn_sub(CCN384_N, d1, cczp_prime(zp), d1); carry += ccn_add(CCN384_N, r, r, d1); carry -= ccn_sub(CCN384_N, s3, r, d2); /* Reduce r mod p384 by subtraction of up to four multiples of p384. */ carry_mask=CC_CARRY_3BITS(carry); carry -= (carry_mask & ccn_sub(CCN384_N,select[carry_mask],s3,cczp_prime(zp))); carry_mask=CC_CARRY_2BITS(carry); carry -= (carry_mask & ccn_sub(CCN384_N,select[carry_mask],s3,cczp_prime(zp))); carry_mask=CC_CARRY_2BITS(carry); carry -= (carry_mask & ccn_sub(CCN384_N,select[carry_mask],s3,cczp_prime(zp))); carry ^= ccn_sub(CCN384_N,s1,s3,cczp_prime(zp)); ccn_set(CCN384_N,r,select[carry]); /* Sanity for debug */ cc_assert(ccn_cmp(CCN384_N, r, cczp_prime(zp)) < 0); }
int p12_pbe_gen(CFStringRef passphrase, uint8_t *salt_ptr, size_t salt_length, unsigned iter_count, P12_PBE_ID pbe_id, uint8_t *data, size_t length) { unsigned int hash_blocksize = CC_SHA1_BLOCK_BYTES; unsigned int hash_outputsize = CC_SHA1_DIGEST_LENGTH; if (!passphrase) return -1; /* generate diversifier block */ unsigned char diversifier[hash_blocksize]; memset(diversifier, pbe_id, sizeof(diversifier)); /* convert passphrase to BE UTF16 and append double null */ CFDataRef passphrase_be_unicode = CFStringCreateExternalRepresentation(kCFAllocatorDefault, passphrase, kCFStringEncodingUTF16BE, '\0'); if (!passphrase_be_unicode) return -1; uint8_t null_termination[2] = { 0, 0 }; CFMutableDataRef passphrase_be_unicode_null_term = CFDataCreateMutableCopy(NULL, 0, passphrase_be_unicode); CFRelease(passphrase_be_unicode); if (!passphrase_be_unicode_null_term) return -1; CFDataAppendBytes(passphrase_be_unicode_null_term, null_termination, sizeof(null_termination)); /* generate passphrase block */ uint8_t *passphrase_data = NULL; size_t passphrase_data_len = 0; size_t passphrase_length = CFDataGetLength(passphrase_be_unicode_null_term); const unsigned char *passphrase_ptr = CFDataGetBytePtr(passphrase_be_unicode_null_term); passphrase_data = concatenate_to_blocksize(passphrase_ptr, passphrase_length, hash_blocksize, &passphrase_data_len); CFRelease(passphrase_be_unicode_null_term); if (!passphrase_data) return -1; /* generate salt block */ uint8_t *salt_data = NULL; size_t salt_data_len = 0; if (salt_length) salt_data = concatenate_to_blocksize(salt_ptr, salt_length, hash_blocksize, &salt_data_len); if (!salt_data) return -1; /* generate S||P block */ size_t I_length = salt_data_len + passphrase_data_len; uint8_t *I_data = malloc(I_length); if (!I_data) return -1; memcpy(I_data + 0, salt_data, salt_data_len); memcpy(I_data + salt_data_len, passphrase_data, passphrase_data_len); free(salt_data); free(passphrase_data); /* round up output buffer to multiple of hash block size and allocate */ size_t hash_output_blocks = (length + hash_outputsize - 1) / hash_outputsize; size_t temp_buf_size = hash_output_blocks * hash_outputsize; uint8_t *temp_buf = malloc(temp_buf_size); uint8_t *cursor = temp_buf; if (!temp_buf) return -1; /* 64 bits cast(s): worst case here is we dont hash all the data and incorectly derive the wrong key, when the passphrase + salt are over 2^32 bytes long */ /* loop over output in hash_output_size increments */ while (cursor < temp_buf + temp_buf_size) { CC_SHA1_CTX ctx; CC_SHA1_Init(&ctx); CC_SHA1_Update(&ctx, diversifier, (CC_LONG)sizeof(diversifier)); assert(I_length<=UINT32_MAX); /* debug check. Correct as long as CC_LONG is uint32_t */ CC_SHA1_Update(&ctx, I_data, (CC_LONG)I_length); CC_SHA1_Final(cursor, &ctx); /* run block through SHA-1 for iteration count */ unsigned int i; for (i = 1; /*first round done above*/ i < iter_count; i++) CC_SHA1(cursor, hash_outputsize, cursor); /* * b) Concatenate copies of A[i] to create a string B of * length v bits (the final copy of A[i]i may be truncated * to create B). */ size_t A_i_len = 0; uint8_t *A_i = concatenate_to_blocksize(cursor, hash_outputsize, hash_blocksize, &A_i_len); if (!A_i) return -1; /* * c) Treating I as a concatenation I[0], I[1], ..., * I[k-1] of v-bit blocks, where k = ceil(s/v) + ceil(p/v), * modify I by setting I[j]=(I[j]+B+1) mod (2 ** v) * for each j. */ /* tmp1 = B+1 */ 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); cc_unit tmp1[tmp_n]; ccn_read_uint(tmp_n, tmp1, A_i_len, A_i); ccn_add1(tmp_n, tmp1, tmp1, 1); free(A_i); cc_unit tmp2[tmp_n]; unsigned int j; for (j = 0; j < I_length; j+=hash_blocksize) { /* tempg = I[j]; */ ccn_read_uint(tmp_n, tmp2, hash_blocksize, I_data + j); /* tempg += tmp1 */ ccn_add(tmp_n, tmp2, tmp2, tmp1); /* I[j] = tempg mod 2**v Just clear all the high bits above 2**v In practice at most it rolled over by 1 bit, since all we did was add so we should only clear one bit at most. */ size_t bitSize; const size_t hash_blocksize_bits = hash_blocksize * 8; while ((bitSize = ccn_bitlen(tmp_n, tmp2)) > hash_blocksize_bits) { ccn_set_bit(tmp2, bitSize - 1, 0); } ccn_write_uint_padded(tmp_n, tmp2, hash_blocksize, I_data + j); } cursor += hash_outputsize; } /* * 7. Concatenate A[1], A[2], ..., A[c] together to form a * pseudo-random bit string, A. * * 8. Use the first n bits of A as the output of this entire * process. */ memmove(data, temp_buf, length); free(temp_buf); free(I_data); return 0; }